From 4e05c27cdbabaf4eaf3ac185f9810c78fba8bdbb Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Wed, 27 Nov 2019 01:54:10 +0100
Subject: [PATCH 1/2] Updating supply pods code.
---
code/__DEFINES/admin.dm | 1 +
code/__DEFINES/cargo.dm | 4 +-
code/__DEFINES/flags.dm | 1 +
code/datums/explosion.dm | 2 +-
code/game/atoms.dm | 3 -
code/modules/admin/admin.dm | 30 ++-
code/modules/admin/admin_verbs.dm | 2 +-
code/modules/admin/topic.dm | 15 +-
code/modules/admin/verbs/randomverbs.dm | 29 ++-
code/modules/cargo/centcom_podlauncher.dm | 118 ++++++++--
code/modules/cargo/expressconsole.dm | 4 +-
code/modules/cargo/gondolapod.dm | 11 +-
code/modules/cargo/supplypod.dm | 136 +++++++----
code/modules/events/immovable_rod.dm | 4 +-
code/modules/mob/living/silicon/silicon.dm | 4 +-
.../hostile/megafauna/megafauna.dm | 4 +-
code/modules/power/supermatter/supermatter.dm | 4 +-
html/create_object.html | 3 +-
sound/weapons/mortar_long_whistle.ogg | Bin 0 -> 14156 bytes
sound/weapons/mortar_whistle.ogg | Bin 0 -> 6885 bytes
tgui/assets/tgui.css | 2 +-
tgui/assets/tgui.js | 40 ++--
tgui/src/interfaces/centcom_podlauncher.ract | 220 ++++++++++--------
tgui/src/util/tooltip.styl | 2 +
24 files changed, 425 insertions(+), 214 deletions(-)
create mode 100644 sound/weapons/mortar_long_whistle.ogg
create mode 100644 sound/weapons/mortar_whistle.ogg
diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index b875998f0a..bded562a3c 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -69,6 +69,7 @@
#define ADMIN_PUNISHMENT_BSA "Bluespace Artillery Device"
#define ADMIN_PUNISHMENT_FIREBALL "Fireball"
#define ADMIN_PUNISHMENT_ROD "Immovable Rod"
+#define ADMIN_PUNISHMENT_SUPPLYPOD_QUICK "Supply Pod (Quick)"
#define ADMIN_PUNISHMENT_SUPPLYPOD "Supply Pod"
#define ADMIN_PUNISHMENT_MAZING "Puzzle"
#define ADMIN_PUNISHMENT_PIE "Cream Pie"
diff --git a/code/__DEFINES/cargo.dm b/code/__DEFINES/cargo.dm
index 0d07ef353a..52a2d56697 100644
--- a/code/__DEFINES/cargo.dm
+++ b/code/__DEFINES/cargo.dm
@@ -11,6 +11,7 @@
#define STYLE_FRUIT 11
#define STYLE_INVISIBLE 12
#define STYLE_GONDOLA 13
+#define STYLE_SEETHROUGH 14
#define POD_ICON_STATE 1
#define POD_NAME 2
@@ -29,5 +30,6 @@
list("honkpod", "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\
list("fruitpod", "\improper Orange", "An angry orange."),\
list("", "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
- list("gondolapod", "gondola", "The silent walker. This one seems to be part of a delivery agency.")\
+ list("gondolapod", "gondola", "The silent walker. This one seems to be part of a delivery agency."),\
+ list("", "", "")\
)
\ No newline at end of file
diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index 9e8a4f71c2..55962bf78c 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define TESLA_IGNORE_1 (1<<13) // TESLA_IGNORE grants immunity from being targeted by tesla-style electricity
#define INITIALIZED_1 (1<<14) //Whether /atom/Initialize() has already run for the object
#define ADMIN_SPAWNED_1 (1<<15) //was this spawned by an admin? used for stat tracking stuff.
+#define PREVENT_CONTENTS_EXPLOSION_1 (1<<16) /// should not get harmed if this gets caught by an explosion?
//turf-only flags
#define NOJAUNT_1 (1<<0)
diff --git a/code/datums/explosion.dm b/code/datums/explosion.dm
index b3c57e4838..7be4489e86 100644
--- a/code/datums/explosion.dm
+++ b/code/datums/explosion.dm
@@ -198,7 +198,7 @@ GLOBAL_LIST_EMPTY(explosions)
var/list/items = list()
for(var/I in T)
var/atom/A = I
- if (!A.prevent_content_explosion()) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't.
+ if (!(A.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't.
items += A.GetAllContents()
for(var/O in items)
var/atom/A = O
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 6f633f7c6d..2fe5380490 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -316,9 +316,6 @@
to_chat(user, "You can't move while buckled to [src]!")
return
-/atom/proc/prevent_content_explosion()
- return FALSE
-
/atom/proc/contents_explosion(severity, target)
return //For handling the effects of explosions on contents that would not normally be effected
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 87db105072..895f8c9f88 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -720,20 +720,44 @@
if(!check_rights(R_SPAWN))
return
+ var/turf/T = get_turf(usr)
var/chosen = pick_closest_path(object)
if(!chosen)
return
if(ispath(chosen, /turf))
- var/turf/T = get_turf(usr.loc)
T.ChangeTurf(chosen)
else
- var/atom/A = new chosen(usr.loc)
+ var/atom/A = new chosen(T)
A.flags_1 |= ADMIN_SPAWNED_1
log_admin("[key_name(usr)] spawned [chosen] at [AREACOORD(usr)]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Spawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+/datum/admins/proc/podspawn_atom(object as text)
+ set category = "Debug"
+ set desc = "(atom path) Spawn an atom via supply drop"
+ set name = "Podspawn"
+
+ if(!check_rights(R_SPAWN))
+ return
+
+ var/chosen = pick_closest_path(object)
+ if(!chosen)
+ return
+ var/turf/T = get_turf(usr)
+
+ if(ispath(chosen, /turf))
+ T.ChangeTurf(chosen)
+ else
+ var/obj/structure/closet/supplypod/centcompod/pod = new()
+ var/atom/A = new chosen(pod)
+ A.flags_1 |= ADMIN_SPAWNED_1
+ new /obj/effect/abstract/DPtarget(T, pod)
+
+ log_admin("[key_name(usr)] pod-spawned [chosen] at [AREACOORD(usr)]")
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Podspawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
/datum/admins/proc/spawn_cargo(object as text)
set category = "Debug"
set desc = "(atom path) Spawn a cargo crate"
@@ -875,7 +899,7 @@
/datum/admins/proc/dynamic_mode_options(mob/user)
var/dat = {"
Dynamic Mode Options
-
+
Common options
All these options can be changed midround.
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 5900847ef5..c3ffd10174 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -108,7 +108,7 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list(
/client/proc/roll_dices //CIT CHANGE - Adds dice verb
))
GLOBAL_PROTECT(admin_verbs_fun)
-GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom, /datum/admins/proc/spawn_cargo, /datum/admins/proc/spawn_objasmob, /client/proc/respawn_character))
+GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom, /datum/admins/proc/podspawn_atom, /datum/admins/proc/spawn_cargo, /datum/admins/proc/spawn_objasmob, /client/proc/respawn_character))
GLOBAL_PROTECT(admin_verbs_spawn)
GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
/world/proc/AVerbsServer()
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 4de2d9b5ca..5b751ffe30 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -2355,7 +2355,7 @@
var/atom/target //Where the object will be spawned
var/where = href_list["object_where"]
- if (!( where in list("onfloor","inhand","inmarked") ))
+ if (!( where in list("onfloor","frompod","inhand","inmarked") ))
where = "onfloor"
@@ -2366,7 +2366,7 @@
where = "onfloor"
target = usr
- if("onfloor")
+ if("onfloor", "frompod")
switch(href_list["offset_type"])
if ("absolute")
target = locate(0 + X,0 + Y,0 + Z)
@@ -2382,7 +2382,10 @@
else
target = marked_datum
+ var/obj/structure/closet/supplypod/centcompod/pod
if(target)
+ if(where == "frompod")
+ pod = new()
for (var/path in paths)
for (var/i = 0; i < number; i++)
if(path in typesof(/turf))
@@ -2391,7 +2394,11 @@
if(N && obj_name)
N.name = obj_name
else
- var/atom/O = new path(target)
+ var/atom/O
+ if(where == "frompod")
+ O = new path(pod)
+ else
+ O = new path(target)
if(!QDELETED(O))
O.flags_1 |= ADMIN_SPAWNED_1
if(obj_dir)
@@ -2411,6 +2418,8 @@
R.module.add_module(I, TRUE, TRUE)
R.activate_module(I)
+ if(pod)
+ new /obj/effect/abstract/DPtarget(target, pod)
if (number == 1)
log_admin("[key_name(usr)] created a [english_list(paths)]")
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 7a222d1ebc..f97822a043 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -1249,7 +1249,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
if(!check_rights(R_ADMIN) || !check_rights(R_FUN))
return
- var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING, ADMIN_PUNISHMENT_ROD)
+ var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_SUPPLYPOD_QUICK, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING, ADMIN_PUNISHMENT_ROD)
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
@@ -1277,6 +1277,22 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
var/turf/startT = spaceDebrisStartLoc(startside, T.z)
var/turf/endT = spaceDebrisFinishLoc(startside, T.z)
new /obj/effect/immovablerod(startT, endT,target)
+ if(ADMIN_PUNISHMENT_SUPPLYPOD_QUICK)
+ var/target_path = input(usr,"Enter typepath of an atom you'd like to send with the pod (type \"empty\" to send an empty pod):" ,"Typepath","/obj/item/reagent_containers/food/snacks/grown/harebell") as null|text
+ var/obj/structure/closet/supplypod/centcompod/pod = new()
+ pod.damage = 40
+ pod.explosionSize = list(0,0,0,2)
+ pod.effectStun = TRUE
+ if (isnull(target_path)) //The user pressed "Cancel"
+ return
+ if (target_path != "empty")//if you didn't type empty, we want to load the pod with a delivery
+ var/delivery = text2path(target_path)
+ if(!ispath(delivery))
+ delivery = pick_closest_path(target_path)
+ if(!delivery)
+ alert("ERROR: Incorrect / improper path given.")
+ new delivery(pod)
+ new /obj/effect/abstract/DPtarget(get_turf(target), pod)
if(ADMIN_PUNISHMENT_SUPPLYPOD)
var/datum/centcom_podlauncher/plaunch = new(usr)
if(!holder)
@@ -1289,6 +1305,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
plaunch.temp_pod.explosionSize = list(0,0,0,2)
plaunch.temp_pod.effectStun = TRUE
plaunch.ui_interact(usr)
+ return //We return here because punish_log() is handled by the centcom_podlauncher datum
if(ADMIN_PUNISHMENT_MAZING)
if(!puzzle_imprison(target))
@@ -1298,11 +1315,13 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target))
creamy.splat(target)
- var/msg = "[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment]."
- message_admins(msg)
- admin_ticket_log(target, msg)
- log_admin("[key_name(usr)] punished [key_name(target)] with [punishment].")
+ punish_log(target, punishment)
+/client/proc/punish_log(var/whom, var/punishment)
+ var/msg = "[key_name_admin(usr)] punished [key_name_admin(whom)] with [punishment]."
+ message_admins(msg)
+ admin_ticket_log(whom, msg)
+ log_admin("[key_name(usr)] punished [key_name(whom)] with [punishment].")
/client/proc/trigger_centcom_recall()
if(!check_rights(R_ADMIN))
diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm
index f57374db7c..c45461317d 100644
--- a/code/modules/cargo/centcom_podlauncher.dm
+++ b/code/modules/cargo/centcom_podlauncher.dm
@@ -19,7 +19,7 @@
//Variables declared to change how items in the launch bay are picked and launched. (Almost) all of these are changed in the ui_act proc
//Some effect groups are choices, while other are booleans. This is because some effects can stack, while others dont (ex: you can stack explosion and quiet, but you cant stack ordered launch and random launch)
/datum/centcom_podlauncher
- var/static/list/ignored_atoms = typecacheof(list(null, /mob/dead, /obj/effect/landmark, /obj/docking_port, /atom/movable/lighting_object, /obj/effect/particle_effect/sparks, /obj/effect/DPtarget, /obj/effect/supplypod_selector ))
+ var/static/list/ignored_atoms = typecacheof(list(null, /mob/dead, /obj/effect/landmark, /obj/docking_port, /atom/movable/lighting_object, /obj/effect/particle_effect/sparks, /obj/effect/abstract/DPtarget, /obj/effect/supplypod_selector ))
var/turf/oldTurf //Keeps track of where the user was at if they use the "teleport to centcom" button, so they can go back
var/client/holder //client of whoever is using this datum
var/area/bay //What bay we're using to launch shit from.
@@ -29,9 +29,10 @@
var/damageChoice = 0 //Determines if we do no damage (0), custom amnt of damage (1), or gib + 5000dmg (2)
var/launcherActivated = FALSE //check if we've entered "launch mode" (when we click a pod is launched). Used for updating mouse cursor
var/effectBurst = FALSE //Effect that launches 5 at once in a 3x3 area centered on the target
+ var/effectAnnounce = TRUE
var/numTurfs = 0 //Counts the number of turfs with things we can launch in the chosen bay (in the centcom map)
var/launchCounter = 1 //Used with the "Ordered" launch mode (launchChoice = 1) to see what item is launched
- var/specificTarget //Do we want to target a specific mob instead of where we click? Also used for smiting
+ var/atom/specificTarget //Do we want to target a specific mob instead of where we click? Also used for smiting
var/list/orderedArea = list() //Contains an ordered list of turfs in an area (filled in the createOrderedArea() proc), read top-left to bottom-right. Used for the "ordered" launch mode (launchChoice = 1)
var/list/turf/acceptableTurfs = list() //Contians a list of turfs (in the "bay" area on centcom) that have items that can be launched. Taken from orderedArea
var/list/launchList = list() //Contains whatever is going to be put in the supplypod and fired. Taken from acceptableTurfs
@@ -66,12 +67,14 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
data["launchChoice"] = launchChoice //Launch turfs all at once (0), ordered (1), or randomly(1)
data["explosionChoice"] = explosionChoice //An explosion that occurs when landing. Can be no explosion (0), custom explosion (1), or maxcap (2)
data["damageChoice"] = damageChoice //Damage that occurs to any mob under the pod when it lands. Can be no damage (0), custom damage (1), or gib+5000dmg (2)
+ data["fallDuration"] = temp_pod.fallDuration //How long the pod's falling animation lasts
data["landingDelay"] = temp_pod.landingDelay //How long the pod takes to land after launching
data["openingDelay"] = temp_pod.openingDelay //How long the pod takes to open after landing
data["departureDelay"] = temp_pod.departureDelay //How long the pod takes to leave after opening (if bluespace=true, it deletes. if reversing=true, it flies back to centcom)
data["styleChoice"] = temp_pod.style //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the POD_STYLES list in cargo.dm defines to get the proper icon/name/desc for the pod.
data["effectStun"] = temp_pod.effectStun //If true, stuns anyone under the pod when it launches until it lands, forcing them to get hit by the pod. Devilish!
data["effectLimb"] = temp_pod.effectLimb //If true, pops off a limb (if applicable) from anyone caught under the pod when it lands
+ data["effectOrgans"] = temp_pod.effectOrgans //If true, yeets the organs out of any bodies caught under the pod when it lands
data["effectBluespace"] = temp_pod.bluespace //If true, the pod deletes (in a shower of sparks) after landing
data["effectStealth"] = temp_pod.effectStealth //If true, a target icon isnt displayed on the turf where the pod will land
data["effectQuiet"] = temp_pod.effectQuiet //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc)
@@ -81,12 +84,14 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
data["effectReverse"] = temp_pod.reversing //If true, the pod will not send any items. Instead, after opening, it will close again (picking up items/mobs) and fly back to centcom
data["effectTarget"] = specificTarget //Launches the pod at the turf of a specific mob target, rather than wherever the user clicked. Useful for smites
data["effectName"] = temp_pod.adminNamed //Determines whether or not the pod has been named by an admin. If true, the pod's name will not get overridden when the style of the pod changes (changing the style of the pod normally also changes the name+desc)
+ data["effectAnnounce"] = effectAnnounce
data["giveLauncher"] = launcherActivated //If true, the user is in launch mode, and whenever they click a pod will be launched (either at their mouse position or at a specific target)
data["numObjects"] = numTurfs //Counts the number of turfs that contain a launchable object in the centcom supplypod bay
+ data["fallingSound"] = temp_pod.fallingSound != initial(temp_pod.fallingSound)//Admin sound to play as the pod falls
data["landingSound"] = temp_pod.landingSound //Admin sound to play when the pod lands
data["openingSound"] = temp_pod.openingSound //Admin sound to play when the pod opens
data["leavingSound"] = temp_pod.leavingSound //Admin sound to play when the pod leaves
- data["soundVolume"] = temp_pod.soundVolume != 50 //Admin sound to play when the pod leaves
+ data["soundVolume"] = temp_pod.soundVolume != initial(temp_pod.soundVolume) //Admin sound to play when the pod leaves
return data
/datum/centcom_podlauncher/ui_act(action, params)
@@ -227,6 +232,9 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if("effectLimb") //Toggle: Anyone carbon mob under the pod loses a limb when it lands
temp_pod.effectLimb = !temp_pod.effectLimb
. = TRUE
+ if("effectOrgans") //Toggle: Any carbon mob under the pod loses every limb and organ
+ temp_pod.effectOrgans = !temp_pod.effectOrgans
+ . = TRUE
if("effectBluespace") //Toggle: Deletes the pod after landing
temp_pod.bluespace = !temp_pod.bluespace
. = TRUE
@@ -245,6 +253,9 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if("effectBurst") //Toggle: Launch 5 pods (with a very slight delay between) in a 3x3 area centered around the target
effectBurst = !effectBurst
. = TRUE
+ if("effectAnnounce") //Toggle: Sends a ghost announcement.
+ effectAnnounce = !effectAnnounce
+ . = TRUE
if("effectReverse") //Toggle: Don't send any items. Instead, after landing, close (taking any objects inside) and go back to the centcom bay it came from
temp_pod.reversing = !temp_pod.reversing
. = TRUE
@@ -261,11 +272,23 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
. = TRUE
////////////////////////////TIMER DELAYS//////////////////
+ if("fallDuration") //Change the falling animation duration
+ if (temp_pod.fallDuration != initial(temp_pod.fallDuration)) //If the fall duration has already been changed when we push the "change value" button, then set it to default
+ temp_pod.fallDuration = initial(temp_pod.fallDuration)
+ return
+ var/timeInput = input("Enter the duration of the pod's falling animation, in seconds", "Delay Time", initial(temp_pod.fallDuration) * 0.1) as null|num
+ if (isnull(timeInput))
+ return
+ if (!isnum(timeInput)) //Sanitize input, if it doesnt check out, error and set to default
+ alert(usr, "That wasnt a number! Value set to default ([initial(temp_pod.fallDuration)*0.1]) instead.")
+ timeInput = initial(temp_pod.fallDuration)
+ temp_pod.fallDuration = 10 * timeInput
+ . = TRUE
if("landingDelay") //Change the time it takes the pod to land, after firing
if (temp_pod.landingDelay != initial(temp_pod.landingDelay)) //If the landing delay has already been changed when we push the "change value" button, then set it to default
temp_pod.landingDelay = initial(temp_pod.landingDelay)
return
- var/timeInput = input("Delay Time", "Enter the time it takes for the pod to land, in seconds", 0.5) as null|num
+ var/timeInput = input("Enter the time it takes for the pod to land, in seconds", "Delay Time", initial(temp_pod.landingDelay) * 0.1) as null|num
if (isnull(timeInput))
return
if (!isnum(timeInput)) //Sanitize input, if it doesnt check out, error and set to default
@@ -277,7 +300,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if (temp_pod.openingDelay != initial(temp_pod.openingDelay)) //If the opening delay has already been changed when we push the "change value" button, then set it to default
temp_pod.openingDelay = initial(temp_pod.openingDelay)
return
- var/timeInput = input("Delay Time", "Enter the time it takes for the pod to open after landing, in seconds", 3) as null|num
+ var/timeInput = input("Enter the time it takes for the pod to open after landing, in seconds", "Delay Time", initial(temp_pod.openingDelay) * 0.1) as null|num
if (isnull(timeInput))
return
if (!isnum(timeInput)) //Sanitize input
@@ -289,7 +312,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if (temp_pod.departureDelay != initial(temp_pod.departureDelay)) //If the departure delay has already been changed when we push the "change value" button, then set it to default
temp_pod.departureDelay = initial(temp_pod.departureDelay)
return
- var/timeInput = input("Delay Time", "Enter the time it takes for the pod to leave after opening, in seconds", 3) as null|num
+ var/timeInput = input("Enter the time it takes for the pod to leave after opening, in seconds", "Delay Time", initial(temp_pod.departureDelay) * 0.1) as null|num
if (isnull(timeInput))
return
if (!isnum(timeInput))
@@ -299,31 +322,57 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
. = TRUE
////////////////////////////ADMIN SOUNDS//////////////////
+ if("fallingSound") //Admin sound from a local file that plays when the pod falls
+ if ((temp_pod.fallingSound) != initial(temp_pod.fallingSound))
+ temp_pod.fallingSound = initial(temp_pod.fallingSound)
+ temp_pod.fallingSoundLength = initial(temp_pod.fallingSoundLength)
+ return
+ var/soundInput = input(holder, "Please pick a sound file to play when the pod lands! NOTICE: Take a note of exactly how long the sound is.", "Pick a Sound File") as null|sound
+ if (isnull(soundInput))
+ return
+ var/timeInput = input(holder, "What is the exact length of the sound file, in seconds. This number will be used to line the sound up so that it finishes right as the pod lands!", "Pick a Sound File", 0.3) as null|num
+ if (isnull(timeInput))
+ return
+ if (!isnum(timeInput))
+ alert(usr, "That wasnt a number! Value set to default ([initial(temp_pod.fallingSoundLength)*0.1]) instead.")
+ temp_pod.fallingSound = soundInput
+ temp_pod.fallingSoundLength = 10 * timeInput
+ . = TRUE
if("landingSound") //Admin sound from a local file that plays when the pod lands
if (!isnull(temp_pod.landingSound))
temp_pod.landingSound = null
return
- temp_pod.landingSound = input(holder, "Please pick a sound file to play when the pod lands! I reccomend a nice \"oh shit, i'm sorry\", incase you hit someone with the pod.", "Pick a Sound File") as null|sound
+ var/soundInput = input(holder, "Please pick a sound file to play when the pod lands! I reccomend a nice \"oh shit, i'm sorry\", incase you hit someone with the pod.", "Pick a Sound File") as null|sound
+ if (isnull(soundInput))
+ return
+ temp_pod.landingSound = soundInput
. = TRUE
if("openingSound") //Admin sound from a local file that plays when the pod opens
if (!isnull(temp_pod.openingSound))
temp_pod.openingSound = null
return
- temp_pod.openingSound = input(holder, "Please pick a sound file to play when the pod opens! I reccomend a stock sound effect of kids cheering at a party, incase your pod is full of fun exciting stuff!", "Pick a Sound File") as null|sound
+ var/soundInput = input(holder, "Please pick a sound file to play when the pod opens! I reccomend a stock sound effect of kids cheering at a party, incase your pod is full of fun exciting stuff!", "Pick a Sound File") as null|sound
+ if (isnull(soundInput))
+ return
+ temp_pod.openingSound = soundInput
. = TRUE
if("leavingSound") //Admin sound from a local file that plays when the pod leaves
if (!isnull(temp_pod.leavingSound))
temp_pod.leavingSound = null
return
- temp_pod.leavingSound = input(holder, "Please pick a sound file to play when the pod leaves! I reccomend a nice slide whistle sound, especially if you're using the reverse pod effect.", "Pick a Sound File") as null|sound
+ var/soundInput = input(holder, "Please pick a sound file to play when the pod leaves! I reccomend a nice slide whistle sound, especially if you're using the reverse pod effect.", "Pick a Sound File") as null|sound
+ if (isnull(soundInput))
+ return
+ temp_pod.leavingSound = soundInput
. = TRUE
if("soundVolume") //Admin sound from a local file that plays when the pod leaves
- if (temp_pod.soundVolume != 50)
- temp_pod.soundVolume = 50
+ if (temp_pod.soundVolume != initial(temp_pod.soundVolume))
+ temp_pod.soundVolume = initial(temp_pod.soundVolume)
return
- temp_pod.soundVolume = input(holder, "Please pick a volume. Default is between 1 and 100 with 50 being average, but pick whatever. I'm a notification, not a cop. If you still cant hear your sound, consider turning on the Quiet effect. It will silence all pod sounds except for the custom admin ones set by the previous three buttons.", "Pick Admin Sound Volume") as null|num
- if (isnull(temp_pod.soundVolume))
- temp_pod.soundVolume = 50
+ var/soundInput = input(holder, "Please pick a volume. Default is between 1 and 100 with 80 being average, but pick whatever. I'm a notification, not a cop. If you still cant hear your sound, consider turning on the Quiet effect. It will silence all pod sounds except for the custom admin ones set by the previous three buttons.", "Pick Admin Sound Volume") as null|num
+ if (isnull(soundInput))
+ return
+ temp_pod.soundVolume = soundInput
. = TRUE
////////////////////////////STYLE CHANGES//////////////////
//Style is a value that is used to keep track of what the pod is supposed to look like. It can be used with the POD_STYLES list (in cargo.dm defines)
@@ -364,6 +413,9 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if("styleGondola")
temp_pod.setStyle(STYLE_GONDOLA)
. = TRUE
+ if("styleSeeThrough")
+ temp_pod.setStyle(STYLE_SEETHROUGH)
+ . = TRUE
if("refresh") //Refresh the Pod bay. User should press this if they spawn something new in the centcom bay. Automatically called whenever the user launches a pod
refreshBay()
. = TRUE
@@ -403,12 +455,17 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if(left_click) //When we left click:
preLaunch() //Fill the acceptableTurfs list from the orderedArea list. Then, fill up the launchList list with items from the acceptableTurfs list based on the manner of launch (ordered, random, etc)
if (!isnull(specificTarget))
- target = get_turf(specificTarget) //if we have a specific mob target, then always launch the pod at the turf of the mob
+ target = get_turf(specificTarget) //if we have a specific target, then always launch the pod at the turf of the target
else if (target)
target = get_turf(target) //Make sure we're aiming at a turf rather than an item or effect or something
else
return //if target is null and we don't have a specific target, cancel
-
+ if (effectAnnounce)
+ deadchat_broadcast("A special package is being launched at the station!", turf_target = target)
+ var/list/bouttaDie = list()
+ for (var/mob/living/M in target)
+ bouttaDie.Add(M)
+ supplypod_punish_log(bouttaDie)
if (!effectBurst) //If we're not using burst mode, just launch normally.
launch(target)
else
@@ -422,7 +479,6 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
else
launch(target) //If we couldn't locate an adjacent turf, just launch at the normal target
sleep(rand()*2) //looks cooler than them all appearing at once. Gives the impression of burst fire.
- log_admin("Centcom Supplypod Launch: [key_name(user)] launched a supplypod in [AREACOORD(target)]")
/datum/centcom_podlauncher/proc/refreshBay() //Called whenever the bay is switched, as well as wheneber a pod is launched
orderedArea = createOrderedArea(bay) //Create an ordered list full of turfs form the bay
@@ -486,11 +542,11 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if (launchClone) //We arent launching the actual items from the bay, rather we are creating clones and launching those
for (var/atom/movable/O in launchList)
DuplicateObject(O).forceMove(toLaunch) //Duplicate each atom/movable in launchList and forceMove them into the supplypod
- new /obj/effect/DPtarget(A, toLaunch) //Create the DPTarget, which will eventually forceMove the temp_pod to it's location
+ new /obj/effect/abstract/DPtarget(A, toLaunch) //Create the DPTarget, which will eventually forceMove the temp_pod to it's location
else
for (var/atom/movable/O in launchList) //If we aren't cloning the objects, just go through the launchList
O.forceMove(toLaunch) //and forceMove any atom/moveable into the supplypod
- new /obj/effect/DPtarget(A, toLaunch) //Then, create the DPTarget effect, which will eventually forceMove the temp_pod to it's location
+ new /obj/effect/abstract/DPtarget(A, toLaunch) //Then, create the DPTarget effect, which will eventually forceMove the temp_pod to it's location
if (launchClone)
launchCounter++ //We only need to increment launchCounter if we are cloning objects.
//If we aren't cloning objects, taking and removing the first item each time from the acceptableTurfs list will inherently iterate through the list in order
@@ -508,4 +564,26 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
updateCursor(FALSE) //Make sure our moues cursor resets to default. False means we are not in launch mode
qdel(temp_pod) //Delete the temp_pod
qdel(selector) //Delete the selector effect
- . = ..()
\ No newline at end of file
+ . = ..()
+
+/datum/centcom_podlauncher/proc/supplypod_punish_log(var/list/whoDyin)
+ var/podString = effectBurst ? "5 pods" : "a pod"
+ var/whomString = ""
+ if (LAZYLEN(whoDyin))
+ for (var/mob/living/M in whoDyin)
+ whomString += "[key_name(M)], "
+
+ var/delayString = temp_pod.landingDelay == initial(temp_pod.landingDelay) ? "" : " Delay=[temp_pod.landingDelay*0.1]s"
+ var/damageString = temp_pod.damage == 0 ? "" : " Dmg=[temp_pod.damage]"
+ var/explosionString = ""
+ var/explosion_sum = temp_pod.explosionSize[1] + temp_pod.explosionSize[2] + temp_pod.explosionSize[3] + temp_pod.explosionSize[4]
+ if (explosion_sum != 0)
+ explosionString = " Boom=|"
+ for (var/X in temp_pod.explosionSize)
+ explosionString += "[X]|"
+
+ var/msg = "launched [podString][whomString].[delayString][damageString][explosionString]]"
+ message_admins("[key_name_admin(usr)] [msg] in [AREACOORD(specificTarget)].")
+ if (!isemptylist(whoDyin))
+ for (var/mob/living/M in whoDyin)
+ admin_ticket_log(M, "[key_name_admin(usr)] [msg]")
diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm
index 6170c80f8e..e38e5b55b9 100644
--- a/code/modules/cargo/expressconsole.dm
+++ b/code/modules/cargo/expressconsole.dm
@@ -183,7 +183,7 @@
LZ = pick(empty_turfs)
if (SO.pack.cost <= SSshuttle.points && LZ)//we need to call the cost check again because of the CHECK_TICK call
SSshuttle.points -= SO.pack.cost
- new /obj/effect/DPtarget(LZ, podType, SO)
+ new /obj/effect/abstract/DPtarget(LZ, podType, SO)
. = TRUE
update_icon()
else
@@ -200,7 +200,7 @@
for(var/i in 1 to MAX_EMAG_ROCKETS)
var/LZ = pick(empty_turfs)
LAZYREMOVE(empty_turfs, LZ)
- new /obj/effect/DPtarget(LZ, podType, SO)
+ new /obj/effect/abstract/DPtarget(LZ, podType, SO)
. = TRUE
update_icon()
CHECK_TICK
diff --git a/code/modules/cargo/gondolapod.dm b/code/modules/cargo/gondolapod.dm
index b507b617c3..7b78facf00 100644
--- a/code/modules/cargo/gondolapod.dm
+++ b/code/modules/cargo/gondolapod.dm
@@ -39,7 +39,14 @@
set name = "Release Contents"
set category = "Gondola"
set desc = "Release any contents stored within your vast belly."
- linked_pod.open(src)
+ linked_pod.open(src, forced = TRUE)
+
+/mob/living/simple_animal/pet/gondola/gondolapod/examine(mob/user)
+ ..()
+ if (contents.len)
+ to_chat(user, "It looks like it hasn't made its delivery yet.")
+ else
+ to_chat(user, "It looks like it has already made its delivery.")
/mob/living/simple_animal/pet/gondola/gondolapod/verb/check()
set name = "Count Contents"
@@ -47,7 +54,7 @@
set desc = "Take a deep look inside youself, and count up what's inside"
var/total = contents.len
if (total)
- to_chat(src, "You detect [total] object[total > 1 ? "s" : ""] within your incredibly vast belly.")
+ to_chat(src, "You detect [total] object\s within your incredibly vast belly.")
else
to_chat(src, "A closer look inside yourself reveals... nothing.")
diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm
index 89e221c339..2989ad0506 100644
--- a/code/modules/cargo/supplypod.dm
+++ b/code/modules/cargo/supplypod.dm
@@ -15,15 +15,17 @@
armor = list("melee" = 30, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 80)
anchored = TRUE //So it cant slide around after landing
anchorable = FALSE
+ flags_1 = PREVENT_CONTENTS_EXPLOSION_1
//*****NOTE*****: Many of these comments are similarly described in centcom_podlauncher.dm. If you change them here, please consider doing so in the centcom podlauncher code as well!
var/adminNamed = FALSE //Determines whether or not the pod has been named by an admin. If true, the pod's name will not get overridden when the style of the pod changes (changing the style of the pod normally also changes the name+desc)
var/bluespace = FALSE //If true, the pod deletes (in a shower of sparks) after landing
var/landingDelay = 30 //How long the pod takes to land after launching
var/openingDelay = 30 //How long the pod takes to open after landing
- var/departureDelay = 30 //How long the pod takes to leave after opening (if bluespace=true, it deletes. if reversing=true, it flies back to centcom)
+ var/departureDelay = 30 //How long the pod takes to leave after opening. If bluespace = TRUE, it deletes. If reversing = TRUE, it flies back to centcom.
var/damage = 0 //Damage that occurs to any mob under the pod when it lands.
var/effectStun = FALSE //If true, stuns anyone under the pod when it launches until it lands, forcing them to get hit by the pod. Devilish!
var/effectLimb = FALSE //If true, pops off a limb (if applicable) from anyone caught under the pod when it lands
+ var/effectOrgans = FALSE //If true, yeets out every limb and organ from anyone caught under the pod when it lands
var/effectGib = FALSE //If true, anyone under the pod will be gibbed when it lands
var/effectStealth = FALSE //If true, a target icon isnt displayed on the turf where the pod will land
var/effectQuiet = FALSE //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc)
@@ -31,10 +33,13 @@
var/effectCircle = FALSE //If true, allows the pod to come in at any angle. Bit of a weird feature but whatever its here
var/style = STYLE_STANDARD //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the POD_STYLES list in cargo.dm defines to get the proper icon/name/desc for the pod.
var/reversing = FALSE //If true, the pod will not send any items. Instead, after opening, it will close again (picking up items/mobs) and fly back to centcom
+ var/fallDuration = 4
+ var/fallingSoundLength = 11
+ var/fallingSound = 'sound/weapons/mortar_long_whistle.ogg'//Admin sound to play before the pod lands
var/landingSound //Admin sound to play when the pod lands
var/openingSound //Admin sound to play when the pod opens
var/leavingSound //Admin sound to play when the pod leaves
- var/soundVolume = 50 //Volume to play sounds at. Ignores the cap
+ var/soundVolume = 80 //Volume to play sounds at. Ignores the cap
var/bay //Used specifically for the centcom_podlauncher datum. Holds the current bay the user is launching objects from. Bays are specific rooms on the centcom map.
var/list/explosionSize = list(0,0,2,3)
@@ -48,16 +53,18 @@
style = STYLE_CENTCOM
bluespace = TRUE
explosionSize = list(0,0,0,0)
- landingDelay = 5 //Very speedy!
+ landingDelay = 20 //Very speedy!
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/obj/structure/closet/supplypod/Initialize()
- ..()
+ . = ..()
setStyle(style, TRUE) //Upon initialization, give the supplypod an iconstate, name, and description based on the "style" variable. This system is important for the centcom_podlauncher to function correctly
/obj/structure/closet/supplypod/update_icon()
cut_overlays()
- if (style != STYLE_INVISIBLE) //If we're invisible, we dont bother adding any overlays
+ if (style == STYLE_SEETHROUGH || style == STYLE_INVISIBLE) //If we're invisible, we dont bother adding any overlays
+ return
+ else
if (opened)
add_overlay("[icon_state]_open")
else
@@ -75,7 +82,7 @@
update_icon()
/obj/structure/closet/supplypod/tool_interact(obj/item/W, mob/user)
- if (bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways.
+ if(bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways.
return FALSE
else
..()
@@ -86,9 +93,6 @@
/obj/structure/closet/supplypod/contents_explosion() //Supplypods also protect their contents from the harmful effects of fucking exploding.
return
-/obj/structure/closet/supplypod/prevent_content_explosion() //Useful for preventing epicenter explosions from damaging contents
- return TRUE
-
/obj/structure/closet/supplypod/toggle(mob/living/user) //Supplypods shouldn't be able to be manually opened under any circumstances, as the open() proc generates supply order datums
return
@@ -101,17 +105,32 @@
if (effectLimb && iscarbon(M)) //If effectLimb is true (which means we pop limbs off when we hit people):
var/mob/living/carbon/CM = M
for (var/obj/item/bodypart/bodypart in CM.bodyparts) //Look at the bodyparts in our poor mob beneath our pod as it lands
- if(bodypart.body_part != HEAD && bodypart.body_zone != CHEST)//we dont want to kill him, just teach em a lesson!
+ if(bodypart.body_part != HEAD && bodypart.body_part != CHEST)//we dont want to kill him, just teach em a lesson!
if (bodypart.dismemberable)
bodypart.dismember() //Using the power of flextape i've sawed this man's limb in half!
break
+ if (effectOrgans && iscarbon(M)) //effectOrgans means remove every organ in our mob
+ var/mob/living/carbon/CM = M
+ for(var/X in CM.internal_organs)
+ var/destination = get_edge_target_turf(T, pick(GLOB.alldirs)) //Pick a random direction to toss them in
+ var/obj/item/organ/O = X
+ O.Remove(CM) //Note that this isn't the same proc as for lists
+ O.forceMove(T) //Move the organ outta the body
+ O.throw_at(destination, 2, 3) //Thow the organ at a random tile 3 spots away
+ sleep(1)
+ for (var/obj/item/bodypart/bodypart in CM.bodyparts) //Look at the bodyparts in our poor mob beneath our pod as it lands
+ var/destination = get_edge_target_turf(T, pick(GLOB.alldirs))
+ if (bodypart.dismemberable)
+ bodypart.dismember() //Using the power of flextape i've sawed this man's bodypart in half!
+ bodypart.throw_at(destination, 2, 3)
+ sleep(1)
+
if (effectGib) //effectGib is on, that means whatever's underneath us better be fucking oof'd on
M.adjustBruteLoss(5000) //THATS A LOT OF DAMAGE (called just in case gib() doesnt work on em)
M.gib() //After adjusting the fuck outta that brute loss we finish the job with some satisfying gibs
M.adjustBruteLoss(damage)
-
-
- if (B[1] || B[2] || B[3] || B[4]) //If the explosion list isn't all zeroes, call an explosion
+ var/explosion_sum = B[1] + B[2] + B[3] + B[4]
+ if (explosion_sum != 0) //If the explosion list isn't all zeroes, call an explosion
explosion(get_turf(src), B[1], B[2], B[3], flame_range = B[4], silent = effectQuiet, ignorecap = istype(src, /obj/structure/closet/supplypod/centcompod)) //less advanced equipment than bluespace pod, so larger explosion when landing
else if (!effectQuiet) //If our explosion list IS all zeroes, we still make a nice explosion sound (unless the effectQuiet var is true)
playsound(src, "explosion", landingSound ? 15 : 80, 1)
@@ -128,22 +147,31 @@
/obj/structure/closet/supplypod/open(atom/movable/holder, var/broken = FALSE, var/forced = FALSE) //The holder var represents an atom whose contents we will be working with
var/turf/T = get_turf(holder) //Get the turf of whoever's contents we're talking about
+ if (!holder)
+ return
+ if(opened)
+ return
+ opened = TRUE //This is to ensure we don't open something that has already been opened
var/mob/M
if (istype(holder, /mob)) //Allows mobs to assume the role of the holder, meaning we look at the mob's contents rather than the supplypod's contents. Typically by this point the supplypod's contents have already been moved over to the mob's contents
M = holder
if (M.key && !forced && !broken) //If we are player controlled, then we shouldnt open unless the opening is manual, or if it is due to being destroyed (represented by the "broken" parameter)
return
- opened = TRUE //This is to ensure we don't open something that has already been opened
if (openingSound)
- playsound(get_turf(holder), openingSound, soundVolume, 0, 0)
+ playsound(get_turf(holder), openingSound, soundVolume, 0, 0) //Special admin sound to play
INVOKE_ASYNC(holder, .proc/setOpened) //Use the INVOKE_ASYNC proc to call setOpened() on whatever the holder may be, without giving the atom/movable base class a setOpened() proc definition
+ if (style == STYLE_SEETHROUGH)
+ update_icon()
for (var/atom/movable/O in holder.contents) //Go through the contents of the holder
O.forceMove(T) //move everything from the contents of the holder to the turf of the holder
- if (!effectQuiet) //If we aren't being quiet, play an open sound
+ if (!effectQuiet && !openingSound && style != STYLE_SEETHROUGH) //If we aren't being quiet, play the default pod open sound
playsound(get_turf(holder), open_sound, 15, 1, -3)
if (broken) //If the pod is opening because it's been destroyed, we end here
return
- addtimer(CALLBACK(src, .proc/depart, holder), departureDelay) //Finish up the pod's duties after a certain amount of time
+ if (style == STYLE_SEETHROUGH)
+ depart(src)
+ else
+ addtimer(CALLBACK(src, .proc/depart, holder), departureDelay) //Finish up the pod's duties after a certain amount of time
/obj/structure/closet/supplypod/proc/depart(atom/movable/holder)
if (leavingSound)
@@ -151,7 +179,7 @@
if (reversing) //If we're reversing, we call the close proc. This sends the pod back up to centcom
close(holder)
else if (bluespace) //If we're a bluespace pod, then delete ourselves (along with our holder, if a seperate holder exists)
- if (style != STYLE_INVISIBLE)
+ if (!effectQuiet && style != STYLE_INVISIBLE && style != STYLE_SEETHROUGH)
do_sparks(5, TRUE, holder) //Create some sparks right before closing
qdel(src) //Delete ourselves and the holder
if (holder != src)
@@ -164,13 +192,14 @@
if (ismob(O) && !isliving(O)) //We dont want to take ghosts with us
continue
O.forceMove(holder) //Put objects inside before we close
- var/obj/effect/temp_visual/risingPod = new /obj/effect/temp_visual/DPfall(get_turf(holder), src) //Make a nice animation of flying back up
+ var/obj/effect/temp_visual/risingPod = new /obj/effect/abstract/DPfall(get_turf(holder), src) //Make a nice animation of flying back up
risingPod.pixel_z = 0 //The initial value of risingPod's pixel_z is 200 because it normally comes down from a high spot
holder.forceMove(bay) //Move the pod back to centcom, where it belongs
animate(risingPod, pixel_z = 200, time = 10, easing = LINEAR_EASING) //Animate our rising pod
+ QDEL_IN(risingPod, 10)
reversing = FALSE //Now that we're done reversing, we set this to false (otherwise we would get stuck in an infinite loop of calling the close proc at the bottom of open() )
+ bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever
open(holder, forced = TRUE)
- return
/obj/structure/closet/supplypod/proc/setOpened() //Proc exists here, as well as in any atom that can assume the role of a "holder" of a supplypod. Check the open() proc for more details
update_icon()
@@ -179,12 +208,11 @@
update_icon()
/obj/structure/closet/supplypod/Destroy()
- if (!opened) //If we havent opened yet, we're opening because we've been destroyed. Lets dump our contents by opening up
- open(src, broken = TRUE)
- return ..()
+ open(src, broken = TRUE) //Lets dump our contents by opening up
+ . = ..()
//------------------------------------FALLING SUPPLY POD-------------------------------------//
-/obj/effect/temp_visual/DPfall //Falling pod
+/obj/effect/abstract/DPfall //Falling pod
name = ""
icon = 'icons/obj/supplypods.dmi'
pixel_x = -16
@@ -192,17 +220,22 @@
pixel_z = 200
desc = "Get out of the way!"
layer = FLY_LAYER//that wasnt flying, that was falling with style!
- randomdir = FALSE
icon_state = ""
-/obj/effect/temp_visual/DPfall/Initialize(dropLocation, obj/structure/closet/supplypod/pod)
- if (pod.style != STYLE_INVISIBLE) //Check to ensure the pod isn't invisible
+/obj/effect/abstract/DPfall/Initialize(dropLocation, obj/structure/closet/supplypod/pod)
+ if (pod.style == STYLE_SEETHROUGH)
+ pixel_x = -16
+ pixel_y = 0
+ for (var/atom/movable/O in pod.contents)
+ var/icon/I = getFlatIcon(O) //im so sorry
+ add_overlay(I)
+ else if (pod.style != STYLE_INVISIBLE) //Check to ensure the pod isn't invisible
icon_state = "[pod.icon_state]_falling"
name = pod.name
. = ..()
//------------------------------------TEMPORARY_VISUAL-------------------------------------//
-/obj/effect/DPtarget //This is the object that forceMoves the supplypod to it's location
+/obj/effect/abstract/DPtarget //This is the object that forceMoves the supplypod to it's location
name = "Landing Zone Indicator"
desc = "A holographic projection designating the landing zone of something. It's probably best to stand back."
icon = 'icons/mob/actions/actions_items.dmi'
@@ -212,45 +245,60 @@
var/obj/effect/temp_visual/fallingPod //Temporary "falling pod" that we animate
var/obj/structure/closet/supplypod/pod //The supplyPod that will be landing ontop of this target
-/obj/effect/ex_act()
- return
-
-/obj/effect/DPtarget/Initialize(mapload, podParam, var/datum/supply_order/SO = null)
+/obj/effect/abstract/DPtarget/Initialize(mapload, podParam, single_order = null)
+ . = ..()
if (ispath(podParam)) //We can pass either a path for a pod (as expressconsoles do), or a reference to an instantiated pod (as the centcom_podlauncher does)
podParam = new podParam() //If its just a path, instantiate it
pod = podParam
- if (SO)
- SO.generate(pod)
- for (var/mob/living/M in podParam) //If there are any mobs in the supplypod, we want to forceMove them into the target. This is so that they can see where they are about to land, AND so that they don't get sent to the nullspace error room (as the pod is currently in nullspace)
+ if (single_order)
+ if (istype(single_order, /datum/supply_order))
+ var/datum/supply_order/SO = single_order
+ SO.generate(pod)
+ else if (istype(single_order, /atom/movable))
+ var/atom/movable/O = single_order
+ O.forceMove(pod)
+ for (var/mob/living/M in pod) //If there are any mobs in the supplypod, we want to forceMove them into the target. This is so that they can see where they are about to land, AND so that they don't get sent to the nullspace error room (as the pod is currently in nullspace)
M.forceMove(src)
if(pod.effectStun) //If effectStun is true, stun any mobs caught on this target until the pod gets a chance to hit them
for (var/mob/living/M in get_turf(src))
M.Stun(pod.landingDelay+10, ignore_canstun = TRUE)//you aint goin nowhere, kid.
if (pod.effectStealth) //If effectStealth is true we want to be invisible
- alpha = 255
+ icon_state = ""
+ if (pod.fallDuration == initial(pod.fallDuration) && pod.landingDelay + pod.fallDuration < pod.fallingSoundLength)
+ pod.fallingSoundLength = 3 //The default falling sound is a little long, so if the landing time is shorter than the default falling sound, use a special, shorter default falling sound
+ pod.fallingSound = 'sound/weapons/mortar_whistle.ogg'
+ var/soundStartTime = pod.landingDelay - pod.fallingSoundLength + pod.fallDuration
+ if (soundStartTime < 0)
+ soundStartTime = 1
+ if (!pod.effectQuiet)
+ addtimer(CALLBACK(src, .proc/playFallingSound), soundStartTime)
addtimer(CALLBACK(src, .proc/beginLaunch, pod.effectCircle), pod.landingDelay)
-/obj/effect/DPtarget/proc/beginLaunch(effectCircle) //Begin the animation for the pod falling. The effectCircle param determines whether the pod gets to come in from any descent angle
- fallingPod = new /obj/effect/temp_visual/DPfall(drop_location(), pod)
+/obj/effect/abstract/DPtarget/proc/playFallingSound()
+ playsound(src, pod.fallingSound, pod.soundVolume, 1, 6)
+
+/obj/effect/abstract/DPtarget/proc/beginLaunch(effectCircle) //Begin the animation for the pod falling. The effectCircle param determines whether the pod gets to come in from any descent angle
+ fallingPod = new /obj/effect/abstract/DPfall(drop_location(), pod)
var/matrix/M = matrix(fallingPod.transform) //Create a new matrix that we can rotate
var/angle = effectCircle ? rand(0,360) : rand(70,110) //The angle that we can come in from
- fallingPod.pixel_x = cos(angle)*200 //Use some ADVANCED MATHEMATICS to set the animated pod's position to somewhere on the edge of a circle with the center being the target
- fallingPod.pixel_z = sin(angle)*200
+ fallingPod.pixel_x = cos(angle)*400 //Use some ADVANCED MATHEMATICS to set the animated pod's position to somewhere on the edge of a circle with the center being the target
+ fallingPod.pixel_z = sin(angle)*400
var/rotation = Get_Pixel_Angle(fallingPod.pixel_z, fallingPod.pixel_x) //CUSTOM HOMEBREWED proc that is just arctan with extra steps
M.Turn(rotation) //Turn our matrix accordingly
fallingPod.transform = M //Transform the animated pod according to the matrix
M = matrix(pod.transform) //Make another matrix based on the pod
M.Turn(rotation) //Turn the matrix
pod.transform = M //Turn the actual pod (Won't be visible until endLaunch() proc tho)
- animate(fallingPod, pixel_z = 0, pixel_x = -16, time = 3, , easing = LINEAR_EASING) //Make the pod fall! At an angle!
- addtimer(CALLBACK(src, .proc/endLaunch), 3, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation
+ animate(fallingPod, pixel_z = 0, pixel_x = -16, time = pod.fallDuration, , easing = LINEAR_EASING) //Make the pod fall! At an angle!
+ addtimer(CALLBACK(src, .proc/endLaunch), pod.fallDuration, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation
-/obj/effect/DPtarget/proc/endLaunch()
+/obj/effect/abstract/DPtarget/proc/endLaunch()
+ pod.update_icon()
pod.forceMove(drop_location()) //The fallingPod animation is over, now's a good time to forceMove the actual pod into position
+ QDEL_NULL(fallingPod) //Delete the falling pod effect, because at this point its animation is over. We dont use temp_visual because we want to manually delete it as soon as the pod appears
for (var/mob/living/M in src) //Remember earlier (initialization) when we moved mobs into the DPTarget so they wouldnt get lost in nullspace? Time to get them out
M.forceMove(pod)
pod.preOpen() //Begin supplypod open procedures. Here effects like explosions, damage, and other dangerous (and potentially admin-caused, if the centcom_podlauncher datum was used) memes will take place
- QDEL_NULL(fallingPod) //The fallingPod's (the animated effect, not the actual pod) purpose is complete. It can rest easy now
qdel(src) //ditto
//------------------------------------UPGRADES-------------------------------------//
diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm
index e041d566e9..41b2bfee5a 100644
--- a/code/modules/events/immovable_rod.dm
+++ b/code/modules/events/immovable_rod.dm
@@ -45,6 +45,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
throwforce = 100
density = TRUE
anchored = TRUE
+ flags_1 = PREVENT_CONTENTS_EXPLOSION_1
var/mob/living/wizard
var/z_original = 0
var/destination
@@ -100,9 +101,6 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
/obj/effect/immovablerod/ex_act(severity, target)
return 0
-/obj/structure/closet/supplypod/prevent_content_explosion()
- return TRUE
-
/obj/effect/immovablerod/singularity_act()
return
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index cda4978f50..d92b300e28 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -13,6 +13,7 @@
mob_biotypes = list(MOB_ROBOTIC)
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
speech_span = SPAN_ROBOT
+ flags_1 = PREVENT_CONTENTS_EXPLOSION_1
no_vore = TRUE
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
@@ -71,9 +72,6 @@
/mob/living/silicon/contents_explosion(severity, target)
return
-/mob/living/silicon/prevent_content_explosion()
- return TRUE
-
/mob/living/silicon/proc/cancelAlarm()
return
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index d62f59cdd7..f59878ab0c 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -25,6 +25,7 @@
mob_size = MOB_SIZE_LARGE
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
+ flags_1 = PREVENT_CONTENTS_EXPLOSION_1
var/list/crusher_loot
var/medal_type
var/score_type = BOSS_SCORE
@@ -41,9 +42,6 @@
QDEL_NULL(internal)
. = ..()
-/mob/living/simple_animal/hostile/megafauna/prevent_content_explosion()
- return TRUE
-
/mob/living/simple_animal/hostile/megafauna/death(gibbed)
if(health > 0)
return
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index 9184c7e4eb..28e5774e93 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -75,6 +75,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
icon_state = "darkmatter"
density = TRUE
anchored = TRUE
+ flags_1 = PREVENT_CONTENTS_EXPLOSION_1
var/uid = 1
var/static/gl_uid = 1
light_range = 4
@@ -685,9 +686,6 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
/obj/machinery/power/supermatter_crystal/contents_explosion(severity, target)
return
-/obj/machinery/power/supermatter_crystal/prevent_content_explosion()
- return TRUE
-
/obj/machinery/power/supermatter_crystal/engine
is_main_engine = TRUE
diff --git a/html/create_object.html b/html/create_object.html
index 3609e46916..461dd37383 100644
--- a/html/create_object.html
+++ b/html/create_object.html
@@ -40,6 +40,7 @@
Where:
@@ -105,4 +106,4 @@