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)