From e07913d751d4c7cd0261d3cd02fa5ec85395c2d2 Mon Sep 17 00:00:00 2001
From: cacogen <25089914+cacogen@users.noreply.github.com>
Date: Tue, 22 Feb 2022 22:40:32 +1300
Subject: [PATCH] Lets blobs mine (#64965)
Allows blobs to destroy mineral turfs when necessary, such as when spawning on Ice Box.
Without this they face a distinct disadvantage against crew that can destroy mineral turfs with plasma cutters like a hot knife through butter to get a better angle on their core.
The fact they can't already seems like an oversight left over from when they would never normally encounter them due to spawning on space stations.
The bubble alerts provide a lot of feedback that was previously missing and saves taking your eyes off the game to look at warning messages in the chat.
The screen tips save you having to read the help screed to at least know what two of the shortcuts are.
Making off-station blobs lighter makes it immediately obvious which blobs count towards victory.
---
code/__DEFINES/screentips.dm | 3 ++
.../contextual_screentip_bare_hands.dm | 11 +++++--
code/datums/screentips/atom_context.dm | 2 +-
code/game/atoms.dm | 24 +++++++++-----
code/game/machinery/doors/airlock.dm | 5 ++-
code/game/machinery/doors/door.dm | 5 ++-
code/game/machinery/doors/firedoor.dm | 9 +++--
code/game/turfs/closed/minerals.dm | 8 +++--
code/modules/antagonists/blob/powers.dm | 13 ++++++--
.../antagonists/blob/structures/_blob.dm | 33 +++++++++++++++++--
.../antagonists/blob/structures/core.dm | 2 +-
.../antagonists/blob/structures/node.dm | 5 ++-
.../antagonists/blob/structures/resource.dm | 1 +
.../mob/living/carbon/carbon_context.dm | 12 ++++---
14 files changed, 102 insertions(+), 31 deletions(-)
diff --git a/code/__DEFINES/screentips.dm b/code/__DEFINES/screentips.dm
index fecbc2a8264..9d07a72c618 100644
--- a/code/__DEFINES/screentips.dm
+++ b/code/__DEFINES/screentips.dm
@@ -7,6 +7,9 @@
/// Context applied to Ctrl-LMB actions
#define SCREENTIP_CONTEXT_CTRL_LMB "Ctrl-LMB"
+/// Context applied to Alt-LMB actions
+#define SCREENTIP_CONTEXT_ALT_LMB "Alt-LMB"
+
/// Screentips are always disabled
#define SCREENTIP_PREFERENCE_DISABLED "Disabled"
diff --git a/code/datums/elements/screentips/contextual_screentip_bare_hands.dm b/code/datums/elements/screentips/contextual_screentip_bare_hands.dm
index 898279b6e5f..f7afaf60dad 100644
--- a/code/datums/elements/screentips/contextual_screentip_bare_hands.dm
+++ b/code/datums/elements/screentips/contextual_screentip_bare_hands.dm
@@ -57,17 +57,22 @@
datum/source,
list/context,
obj/item/held_item,
- mob/living/user,
+ mob/user,
)
SIGNAL_HANDLER
+ if(!isliving(user))
+ return .
+
if (!isnull(held_item))
return NONE
+ var/mob/living/living_user = user
+
if (!isnull(lmb_text))
- context[SCREENTIP_CONTEXT_LMB] = user.combat_mode ? lmb_text_combat_mode : lmb_text
+ context[SCREENTIP_CONTEXT_LMB] = living_user.combat_mode ? lmb_text_combat_mode : lmb_text
if (!isnull(rmb_text))
- context[SCREENTIP_CONTEXT_RMB] = user.combat_mode ? rmb_text_combat_mode : rmb_text
+ context[SCREENTIP_CONTEXT_RMB] = living_user.combat_mode ? rmb_text_combat_mode : rmb_text
return CONTEXTUAL_SCREENTIP_SET
diff --git a/code/datums/screentips/atom_context.dm b/code/datums/screentips/atom_context.dm
index ae71d6f9297..7696a3d8e77 100644
--- a/code/datums/screentips/atom_context.dm
+++ b/code/datums/screentips/atom_context.dm
@@ -18,7 +18,7 @@
atom/source,
list/context,
obj/item/held_item,
- mob/living/user,
+ mob/user,
)
SIGNAL_HANDLER
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 3b067954573..ff8110150ff 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -2111,9 +2111,11 @@
if(screentips_enabled == SCREENTIP_PREFERENCE_DISABLED || (flags_1 & NO_SCREENTIPS_1))
active_hud.screentip_text.maptext = ""
else
+ var/lmb_rmb_line = ""
+ var/ctrl_lmb_alt_lmb_line = ""
var/extra_context = ""
- if (isliving(user))
+ if (isliving(user) || isovermind(user))
var/obj/item/held_item = user.get_active_held_item()
if ((flags_1 & HAS_CONTEXTUAL_SCREENTIPS_1) || (held_item?.item_flags & ITEM_HAS_CONTEXTUAL_SCREENTIPS))
@@ -2129,19 +2131,23 @@
var/rmb_text = (SCREENTIP_CONTEXT_RMB in context) ? "[SCREENTIP_CONTEXT_RMB]: [context[SCREENTIP_CONTEXT_RMB]]" : ""
if (lmb_text)
- extra_context = lmb_text
+ lmb_rmb_line = lmb_text
if (rmb_text)
- extra_context += " | [rmb_text]"
+ lmb_rmb_line += " | [rmb_text]"
else if (rmb_text)
- extra_context = rmb_text
+ lmb_rmb_line = rmb_text
- // Ctrl-LMB and (in the future) Alt-LMB on another
+ // Ctrl-LMB, Alt-LMB on one line...
+ if (lmb_rmb_line != "")
+ lmb_rmb_line += "
"
if (SCREENTIP_CONTEXT_CTRL_LMB in context)
- if (extra_context != "")
- extra_context += "
"
- extra_context += "[SCREENTIP_CONTEXT_CTRL_LMB]: [context[SCREENTIP_CONTEXT_CTRL_LMB]]"
+ ctrl_lmb_alt_lmb_line += "[SCREENTIP_CONTEXT_CTRL_LMB]: [context[SCREENTIP_CONTEXT_CTRL_LMB]]"
+ if (SCREENTIP_CONTEXT_ALT_LMB in context)
+ if (ctrl_lmb_alt_lmb_line != "")
+ ctrl_lmb_alt_lmb_line += " | "
+ ctrl_lmb_alt_lmb_line += "[SCREENTIP_CONTEXT_ALT_LMB]: [context[SCREENTIP_CONTEXT_ALT_LMB]]"
- extra_context = "
[extra_context]"
+ extra_context = "
[lmb_rmb_line][ctrl_lmb_alt_lmb_line]"
if (screentips_enabled == SCREENTIP_PREFERENCE_CONTEXT_ONLY && extra_context == "")
active_hud.screentip_text.maptext = ""
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 8ebbc8c63b6..97072ea65b0 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -627,9 +627,12 @@
. += span_notice("Alt-click [src] to [ secondsElectrified ? "un-electrify" : "permanently electrify"] it.")
. += span_notice("Ctrl-Shift-click [src] to [ emergency ? "disable" : "enable"] emergency access.")
-/obj/machinery/door/airlock/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
+/obj/machinery/door/airlock/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
+ if(!isliving(user))
+ return .
+
switch (held_item?.tool_behaviour)
if (TOOL_CROWBAR)
if (panel_open)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index bd069ca5657..ac0eb69b4fd 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -52,9 +52,12 @@
. += span_notice("In the event of a red alert, its access requirements will automatically lift.")
. += span_notice("Its maintenance panel is [panel_open ? "open" : "screwed in place"].")
-/obj/machinery/door/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
+/obj/machinery/door/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
+ if(!isliving(user))
+ return .
+
if (isnull(held_item))
context[SCREENTIP_CONTEXT_LMB] = "Open"
return CONTEXTUAL_SCREENTIP_SET
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index fe1ef2a2b39..8e5f7a1a80c 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -107,13 +107,18 @@
else
. += span_notice("The bolt locks have been unscrewed, but the bolts themselves are still wrenched to the floor.")
-/obj/machinery/door/firedoor/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
+/obj/machinery/door/firedoor/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
+ if(!isliving(user))
+ return .
+
+ var/mob/living/living_user = user
+
if (isnull(held_item))
if (density)
// This should be LMB/RMB one day
- if (user.combat_mode)
+ if (living_user.combat_mode)
context[SCREENTIP_CONTEXT_LMB] = "Knock"
else
context[SCREENTIP_CONTEXT_LMB] = "Bash"
diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm
index 6606de85f4e..6829f9e8b79 100644
--- a/code/game/turfs/closed/minerals.dm
+++ b/code/game/turfs/closed/minerals.dm
@@ -176,6 +176,10 @@
gets_drilled(null, FALSE)
return
+/turf/closed/mineral/blob_act(obj/structure/blob/B)
+ if(prob(50))
+ gets_drilled(give_exp = FALSE)
+
/turf/closed/mineral/random
var/list/mineralSpawnChanceList = list(/obj/item/stack/ore/uranium = 5, /obj/item/stack/ore/diamond = 1, /obj/item/stack/ore/gold = 10,
/obj/item/stack/ore/silver = 12, /obj/item/stack/ore/plasma = 20, /obj/item/stack/ore/iron = 40, /obj/item/stack/ore/titanium = 11,
@@ -592,7 +596,7 @@
det_time = 0
visible_message(span_notice("The chain reaction stopped! The gibtonite had [det_time] reactions left till the explosion!"))
-/turf/closed/mineral/gibtonite/gets_drilled(mob/user, triggered_by_explosion = FALSE)
+/turf/closed/mineral/gibtonite/gets_drilled(mob/user, give_exp = FALSE, triggered_by_explosion = FALSE)
if(stage == GIBTONITE_UNSTRUCK && mineralAmt >= 1) //Gibtonite deposit is activated
playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,TRUE)
explosive_reaction(user, triggered_by_explosion)
@@ -664,7 +668,7 @@
to_chat(usr, span_warning("The rock seems to be too strong to destroy. Maybe I can break it once I become a master miner."))
-/turf/closed/mineral/strong/gets_drilled(mob/user)
+/turf/closed/mineral/strong/gets_drilled(mob/user, give_exp = FALSE)
if(!ishuman(user))
return // see attackby
var/mob/living/carbon/human/H = user
diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm
index c0bef7be1ff..4ad0e359765 100644
--- a/code/modules/antagonists/blob/powers.dm
+++ b/code/modules/antagonists/blob/powers.dm
@@ -3,6 +3,7 @@
/mob/camera/blob/proc/can_buy(cost = 15)
if(blob_points < cost)
to_chat(src, span_warning("You cannot afford this, you need at least [cost] resources!"))
+ balloon_alert(src, "need [cost-blob_points] more resource\s!")
return FALSE
add_points(-cost)
return TRUE
@@ -85,22 +86,27 @@
var/obj/structure/blob/B = (locate(/obj/structure/blob) in T)
if(!B)
to_chat(src, span_warning("There is no blob here!"))
+ balloon_alert(src, "no blob here!")
return
if(!istype(B, /obj/structure/blob/normal))
to_chat(src, span_warning("Unable to use this blob, find a normal one."))
+ balloon_alert(src, "need normal blob!")
return
if(needsNode)
var/area/A = get_area(src)
if(!(A.area_flags & BLOBS_ALLOWED)) //factory and resource blobs must be legit
to_chat(src, span_warning("This type of blob must be placed on the station!"))
+ balloon_alert(src, "can't place off-station!")
return
if(nodes_required && !(locate(/obj/structure/blob/special/node) in orange(BLOB_NODE_PULSE_RANGE, T)) && !(locate(/obj/structure/blob/special/core) in orange(BLOB_CORE_PULSE_RANGE, T)))
to_chat(src, span_warning("You need to place this blob closer to a node or core!"))
+ balloon_alert(src, "too far from node or core!")
return //handholdotron 2000
if(minSeparation)
for(var/obj/structure/blob/L in orange(minSeparation, T))
if(L.type == blobstrain)
to_chat(src, span_warning("There is a similar blob nearby, move more than [minSeparation] tiles away from it!"))
+ L.balloon_alert(src, "too close!")
return
if(!can_buy(price))
return
@@ -124,9 +130,11 @@
to_chat(src, span_warning("This shield blob is too damaged to be modified properly!"))
return
to_chat(src, span_warning("You secrete a reflective ooze over the shield blob, allowing it to reflect projectiles at the cost of reduced integrity."))
- S.change_to(/obj/structure/blob/shield/reflective, src)
+ S = S.change_to(/obj/structure/blob/shield/reflective, src)
+ S.balloon_alert(src, "upgraded to [S.name]!")
else
- createSpecial(BLOB_UPGRADE_STRONG_COST, /obj/structure/blob/shield, 0, FALSE, T)
+ S = createSpecial(BLOB_UPGRADE_STRONG_COST, /obj/structure/blob/shield, 0, FALSE, T)
+ S?.balloon_alert(src, "upgraded to [S.name]!")
/mob/camera/blob/proc/create_blobbernaut()
var/turf/T = get_turf(src)
@@ -209,6 +217,7 @@
if(B.point_return)
add_points(B.point_return)
to_chat(src, span_notice("Gained [B.point_return] resources from removing \the [B]."))
+ B.balloon_alert(src, "+[B.point_return] resource\s")
qdel(B)
/mob/camera/blob/proc/expand_blob(turf/T)
diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm
index 38272c53c29..818d0261a40 100644
--- a/code/modules/antagonists/blob/structures/_blob.dm
+++ b/code/modules/antagonists/blob/structures/_blob.dm
@@ -34,12 +34,10 @@
/obj/structure/blob/Initialize(mapload, owner_overmind)
. = ..()
+ register_context()
if(owner_overmind)
overmind = owner_overmind
overmind.all_blobs += src
- var/area/Ablob = get_area(src)
- if(Ablob.area_flags & BLOBS_ALLOWED) //Is this area allowed for winning as blob?
- overmind.blobs_legit += src
GLOB.blobs += src //Keep track of the blob in the normal list either way
setDir(pick(GLOB.cardinals))
update_appearance()
@@ -49,6 +47,22 @@
if(!QDELETED(src)) //Consuming our tile can in rare cases cause us to del
AddElement(/datum/element/swabable, CELL_LINE_TABLE_BLOB, CELL_VIRUS_TABLE_GENERIC, 2, 2)
+/obj/structure/blob/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = ..()
+
+ if (!isovermind(user))
+ return .
+
+ if(istype(src, /obj/structure/blob/normal))
+ context[SCREENTIP_CONTEXT_CTRL_LMB] = "Create strong blob"
+ if(istype(src, /obj/structure/blob/shield) && !istype(src, /obj/structure/blob/shield/reflective))
+ context[SCREENTIP_CONTEXT_CTRL_LMB] = "Create reflective blob"
+
+ if(point_return >= 0)
+ context[SCREENTIP_CONTEXT_ALT_LMB] = "Remove blob"
+
+ return CONTEXTUAL_SCREENTIP_SET
+
/obj/structure/blob/proc/creation_action() //When it's created by the overmind, do this.
return
@@ -91,6 +105,9 @@
. = ..()
if(overmind)
add_atom_colour(overmind.blobstrain.color, FIXED_COLOUR_PRIORITY)
+ var/area/A = get_area(src)
+ if(!(A.area_flags & BLOBS_ALLOWED))
+ add_atom_colour(BlendRGB(overmind.blobstrain.color, COLOR_WHITE, 0.5), FIXED_COLOUR_PRIORITY) //lighten it to indicate an off-station blob
else
remove_atom_colour(FIXED_COLOUR_PRIORITY)
@@ -117,12 +134,17 @@
/obj/structure/blob/proc/blob_attack_animation(atom/A = null, controller) //visually attacks an atom
var/obj/effect/temp_visual/blob/O = new /obj/effect/temp_visual/blob(src.loc)
O.setDir(dir)
+ var/area/my_area = get_area(src)
if(controller)
var/mob/camera/blob/BO = controller
O.color = BO.blobstrain.color
+ if(!(my_area.area_flags & BLOBS_ALLOWED))
+ O.color = BlendRGB(O.color, COLOR_WHITE, 0.5) //lighten it to indicate an off-station blob
O.alpha = 200
else if(overmind)
O.color = overmind.blobstrain.color
+ if(!(my_area.area_flags & BLOBS_ALLOWED))
+ O.color = BlendRGB(O.color, COLOR_WHITE, 0.5) //lighten it to indicate an off-station blob
if(A)
O.do_attack_animation(A) //visually attack the whatever
return O //just in case you want to do something to the animation.
@@ -164,6 +186,11 @@
if(T.Enter(B)) //NOW we can attempt to move into the tile
B.set_density(initial(B.density))
B.forceMove(T)
+ var/area/Ablob = get_area(B)
+ if(Ablob.area_flags & BLOBS_ALLOWED) //Is this area allowed for winning as blob?
+ overmind.blobs_legit += B
+ else if(controller)
+ B.balloon_alert(overmind, "off-station, won't count!")
B.update_appearance()
if(B.overmind && expand_reaction)
B.overmind.blobstrain.expand_reaction(src, B, T, controller)
diff --git a/code/modules/antagonists/blob/structures/core.dm b/code/modules/antagonists/blob/structures/core.dm
index f8830b43279..776e8f1cd26 100644
--- a/code/modules/antagonists/blob/structures/core.dm
+++ b/code/modules/antagonists/blob/structures/core.dm
@@ -49,8 +49,8 @@
. += mutable_appearance('icons/mob/blob.dmi', "blob_core_overlay")
/obj/structure/blob/special/core/update_icon()
+ . = ..()
color = null
- return ..()
/obj/structure/blob/special/core/ex_act(severity, target)
var/damage = 10 * (severity + 1) //remember, the core takes half brute damage, so this is 20/15/10 damage based on severity
diff --git a/code/modules/antagonists/blob/structures/node.dm b/code/modules/antagonists/blob/structures/node.dm
index fd018cdaf6b..c9d9fc74335 100644
--- a/code/modules/antagonists/blob/structures/node.dm
+++ b/code/modules/antagonists/blob/structures/node.dm
@@ -24,14 +24,17 @@
return "Gradually expands and sustains nearby blob spores and blobbernauts."
/obj/structure/blob/special/node/update_icon()
+ . = ..()
color = null
- return ..()
/obj/structure/blob/special/node/update_overlays()
. = ..()
var/mutable_appearance/blob_overlay = mutable_appearance('icons/mob/blob.dmi', "blob")
if(overmind)
blob_overlay.color = overmind.blobstrain.color
+ var/area/A = get_area(src)
+ if(!(A.area_flags & BLOBS_ALLOWED))
+ blob_overlay.color = BlendRGB(overmind.blobstrain.color, COLOR_WHITE, 0.5) //lighten it to indicate an off-station blob
. += blob_overlay
. += mutable_appearance('icons/mob/blob.dmi', "blob_node_overlay")
diff --git a/code/modules/antagonists/blob/structures/resource.dm b/code/modules/antagonists/blob/structures/resource.dm
index e6b4ea61a97..32c3bafb5da 100644
--- a/code/modules/antagonists/blob/structures/resource.dm
+++ b/code/modules/antagonists/blob/structures/resource.dm
@@ -27,6 +27,7 @@
flick("blob_resource_glow", src)
if(overmind)
overmind.add_points(BLOB_RESOURCE_GATHER_AMOUNT)
+ balloon_alert(overmind, "+[BLOB_RESOURCE_GATHER_AMOUNT] resource\s")
resource_delay = world.time + BLOB_RESOURCE_GATHER_DELAY + overmind.resource_blobs.len * BLOB_RESOURCE_GATHER_ADDED_DELAY //4 seconds plus a quarter second for each resource blob the overmind has
else
resource_delay = world.time + BLOB_RESOURCE_GATHER_DELAY
diff --git a/code/modules/mob/living/carbon/carbon_context.dm b/code/modules/mob/living/carbon/carbon_context.dm
index 288cf2280d0..1c94e53823e 100644
--- a/code/modules/mob/living/carbon/carbon_context.dm
+++ b/code/modules/mob/living/carbon/carbon_context.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
+/mob/living/carbon/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
if (!isnull(held_item))
@@ -7,15 +7,17 @@
if (!ishuman(user))
return .
- if (user.combat_mode)
+ var/mob/living/carbon/human/human_user = user
+
+ if (human_user.combat_mode)
context[SCREENTIP_CONTEXT_LMB] = "Attack"
- else if (user == src)
+ else if (human_user == src)
context[SCREENTIP_CONTEXT_LMB] = "Check injuries"
- if (get_bodypart(user.zone_selected)?.get_bleed_rate())
+ if (get_bodypart(human_user.zone_selected)?.get_bleed_rate())
context[SCREENTIP_CONTEXT_CTRL_LMB] = "Grab limb"
- if (user != src)
+ if (human_user != src)
context[SCREENTIP_CONTEXT_RMB] = "Shove"
if (body_position == STANDING_UP)