diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
index 5a063b883a8..377a32af6ad 100644
--- a/code/__DEFINES/antagonists.dm
+++ b/code/__DEFINES/antagonists.dm
@@ -84,3 +84,6 @@ GLOBAL_LIST_INIT(heretic_start_knowledge,list(/datum/eldritch_knowledge/spell/ba
#define PATH_RUST "Rust"
#define PATH_FLESH "Flesh"
#define PATH_VOID "Void"
+
+/// How much does it cost to reroll strains?
+#define BLOB_REROLL_COST 40
diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm
index ebdadf4ac33..c22c060b6c0 100644
--- a/code/_onclick/hud/blob_overmind.dm
+++ b/code/_onclick/hud/blob_overmind.dm
@@ -93,17 +93,17 @@
/atom/movable/screen/blob/readapt_strain
icon_state = "ui_chemswap"
- name = "Readapt Strain (40)"
+ name = "Readapt Strain"
desc = "Allows you to choose a new strain from 4 random choices for 40 resources."
/atom/movable/screen/blob/readapt_strain/MouseEntered(location,control,params)
if(hud?.mymob && isovermind(hud.mymob))
var/mob/camera/blob/B = hud.mymob
if(B.free_strain_rerolls)
- name = "Readapt Strain (FREE)"
+ name = "[initial(name)] (FREE)"
desc = "Randomly rerolls your strain for free."
else
- name = initial(name)
+ name = "[initial(name)] ([BLOB_REROLL_COST])"
desc = initial(desc)
..()
diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm
index 4391b24591f..7176c4c373d 100644
--- a/code/_onclick/hud/radial.dm
+++ b/code/_onclick/hud/radial.dm
@@ -51,9 +51,18 @@ GLOBAL_LIST_EMPTY(radial_menus)
parent.finished = TRUE
/datum/radial_menu
- var/list/choices = list() //List of choice id's
- var/list/choices_icons = list() //choice_id -> icon
- var/list/choices_values = list() //choice_id -> choice
+ /// List of choice IDs
+ var/list/choices = list()
+
+ /// choice_id -> icon
+ var/list/choices_icons = list()
+
+ /// choice_id -> choice
+ var/list/choices_values = list()
+
+ /// choice_id -> /datum/radial_menu_choice
+ var/list/choice_datums = list()
+
var/list/page_data = list() //list of choices per page
@@ -188,6 +197,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
E.alpha = 255
E.mouse_opacity = MOUSE_OPACITY_ICON
E.cut_overlays()
+ E.vis_contents.Cut()
if(choice_id == NEXT_PAGE_ID)
E.name = "Next Page"
E.next_page = TRUE
@@ -206,6 +216,12 @@ GLOBAL_LIST_EMPTY(radial_menus)
E.next_page = FALSE
if(choices_icons[choice_id])
E.add_overlay(choices_icons[choice_id])
+ if (choice_datums[choice_id])
+ var/datum/radial_menu_choice/choice_datum = choice_datums[choice_id]
+ if (choice_datum.info)
+ var/obj/effect/abstract/info/info_button = new(E, choice_datum.info)
+ info_button.layer = ABOVE_HUD_LAYER
+ E.vis_contents += info_button
/datum/radial_menu/New()
close_button = new
@@ -234,11 +250,17 @@ GLOBAL_LIST_EMPTY(radial_menus)
var/I = extract_image(new_choices[E])
if(I)
choices_icons[id] = I
+
+ if (istype(new_choices[E], /datum/radial_menu_choice))
+ choice_datums[id] = new_choices[E]
setup_menu(use_tooltips)
+/datum/radial_menu/proc/extract_image(to_extract_from)
+ if (istype(to_extract_from, /datum/radial_menu_choice))
+ var/datum/radial_menu_choice/choice = to_extract_from
+ to_extract_from = choice.image
-/datum/radial_menu/proc/extract_image(E)
- var/mutable_appearance/MA = new /mutable_appearance(E)
+ var/mutable_appearance/MA = new /mutable_appearance(to_extract_from)
if(MA)
MA.layer = ABOVE_HUD_LAYER
MA.appearance_flags |= RESET_TRANSFORM
@@ -321,3 +343,15 @@ GLOBAL_LIST_EMPTY(radial_menus)
if(!custom_check.Invoke())
return
return answer
+
+/// Can be provided to choices in radial menus if you want to provide more information
+/datum/radial_menu_choice
+ /// Required -- what to display for this button
+ var/image
+
+ /// If provided, will display an info button that will put this text in your chat
+ var/info
+
+/datum/radial_menu_choice/Destroy(force, ...)
+ . = ..()
+ QDEL_NULL(image)
diff --git a/code/game/objects/effects/info.dm b/code/game/objects/effects/info.dm
new file mode 100644
index 00000000000..23f341c8a3c
--- /dev/null
+++ b/code/game/objects/effects/info.dm
@@ -0,0 +1,26 @@
+/// An info button that, when clicked, puts some text in the user's chat
+/obj/effect/abstract/info
+ name = "info"
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "info"
+
+ /// What should the info button display when clicked?
+ var/info_text
+
+/obj/effect/abstract/info/Initialize(mapload, info_text)
+ . = ..()
+
+ if (!isnull(info_text))
+ src.info_text = info_text
+
+/obj/effect/abstract/info/Click()
+ . = ..()
+ to_chat(usr, info_text)
+
+/obj/effect/abstract/info/MouseEntered()
+ . = ..()
+ icon_state = "info_hovered"
+
+/obj/effect/abstract/info/MouseExited()
+ . = ..()
+ icon_state = initial(icon_state)
diff --git a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm
index 5a2d9b5edef..4fa454a85e2 100644
--- a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm
+++ b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm
@@ -8,7 +8,7 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/
var/shortdesc = null //just damage and on_mob effects, doesn't include special, blob-tile only effects
var/effectdesc = null //any long, blob-tile specific effects
var/analyzerdescdamage = "Unknown. Report this bug to a coder, or just adminhelp."
- var/analyzerdesceffect = "N/A"
+ var/analyzerdesceffect
var/blobbernaut_message = "slams" //blobbernaut attack verb
var/message = "The blob strikes you" //message sent to any mob hit by the blob
var/message_living = null //extension to first mob sent to only living mobs i.e. silicons have no skin to be burnt
diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm
index cc71fbe536e..85abedf7e3a 100644
--- a/code/modules/antagonists/blob/overmind.dm
+++ b/code/modules/antagonists/blob/overmind.dm
@@ -43,6 +43,9 @@ GLOBAL_LIST_EMPTY(blob_nodes)
var/announcement_time
var/has_announced = FALSE
+ /// The list of strains the blob can reroll for.
+ var/list/strain_choices
+
/mob/camera/blob/Initialize(mapload, starting_points = 60)
validate_location()
blob_points = starting_points
@@ -182,6 +185,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
BM.overmind = null
BM.update_icons()
GLOB.overminds -= src
+ QDEL_LIST_ASSOC_VAL(strain_choices)
SSshuttle.clearHostileEnvironment(src)
STOP_PROCESSING(SSobj, src)
diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm
index e3cd629847c..e5388d1c8dc 100644
--- a/code/modules/antagonists/blob/powers.dm
+++ b/code/modules/antagonists/blob/powers.dm
@@ -1,3 +1,6 @@
+#define BLOB_REROLL_CHOICES 6
+#define BLOB_REROLL_RADIUS 60
+
/mob/camera/blob/proc/can_buy(cost = 15)
if(blob_points < cost)
to_chat(src, "You cannot afford this, you need at least [cost] resources!")
@@ -349,25 +352,54 @@
set category = "Blob"
set name = "Reactive Strain Adaptation (40)"
set desc = "Replaces your strain with a random, different one."
- if(!rerolling && (free_strain_rerolls || can_buy(40)))
- rerolling = TRUE
- reroll_strain()
- rerolling = FALSE
- if(free_strain_rerolls)
- free_strain_rerolls--
- last_reroll_time = world.time
-/mob/camera/blob/proc/reroll_strain()
- var/list/choices = list()
- while (length(choices) < 6)
- var/datum/blobstrain/bs = pick((GLOB.valid_blobstrains))
- choices[initial(bs.name)] = bs
+ if (!free_strain_rerolls && blob_points < BLOB_REROLL_COST)
+ to_chat(src, "You need at least [BLOB_REROLL_COST] resources to reroll your strain again!")
+ return
- var/choice = input(usr, "Please choose a new strain","Strain") as anything in sortList(choices, /proc/cmp_typepaths_asc)
- if (choice && choices[choice] && !QDELETED(src))
- var/datum/blobstrain/bs = choices[choice]
- set_strain(bs)
+ open_reroll_menu()
+/// Open the menu to reroll strains
+/mob/camera/blob/proc/open_reroll_menu()
+ if (!strain_choices)
+ strain_choices = list()
+
+ var/list/new_strains = GLOB.valid_blobstrains.Copy()
+ for (var/_ in 1 to BLOB_REROLL_CHOICES)
+ var/datum/blobstrain/strain = pick_n_take(new_strains)
+
+ var/image/strain_icon = image('icons/mob/blob.dmi', "blob_core")
+ strain_icon.color = initial(strain.color)
+
+ var/info_text = "[initial(strain.name)]"
+ info_text += "
[initial(strain.analyzerdescdamage)]"
+ if (!isnull(initial(strain.analyzerdesceffect)))
+ info_text += "
[initial(strain.analyzerdesceffect)]"
+
+ var/datum/radial_menu_choice/choice = new
+ choice.image = strain_icon
+ choice.info = info_text
+
+ strain_choices[initial(strain.name)] = choice
+
+ var/strain_result = show_radial_menu(src, src, strain_choices, radius = BLOB_REROLL_RADIUS, tooltips = TRUE)
+ if (isnull(strain_result))
+ return
+
+ if (!free_strain_rerolls && !can_buy(BLOB_REROLL_COST))
+ return
+
+ for (var/_other_strain in GLOB.valid_blobstrains)
+ var/datum/blobstrain/other_strain = _other_strain
+ if (initial(other_strain.name) == strain_result)
+ set_strain(other_strain)
+
+ if (free_strain_rerolls)
+ free_strain_rerolls -= 1
+
+ last_reroll_time = world.time
+
+ return
/mob/camera/blob/verb/blob_help()
set category = "Blob"
@@ -392,3 +424,6 @@
if(!placed && autoplace_max_time <= world.time)
to_chat(src, "You will automatically place your blob core in [DisplayTimeText(autoplace_max_time - world.time)].")
to_chat(src, "You [manualplace_min_time ? "will be able to":"can"] manually place your blob core by pressing the Place Blob Core button in the bottom right corner of the screen.")
+
+#undef BLOB_REROLL_CHOICES
+#undef BLOB_REROLL_RADIUS
diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm
index 1d868f38cbe..027cbeef870 100644
--- a/code/modules/antagonists/blob/structures/_blob.dm
+++ b/code/modules/antagonists/blob/structures/_blob.dm
@@ -235,7 +235,7 @@
if(overmind)
. += list("Material: [overmind.blobstrain.name].",
"Material Effects: [overmind.blobstrain.analyzerdescdamage]",
- "Material Properties: [overmind.blobstrain.analyzerdesceffect]")
+ "Material Properties: [overmind.blobstrain.analyzerdesceffect || "N/A"]")
else
. += "No Material Detected!"
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index 017556c5725..4df910d6ec5 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index a5a08dbcbb7..b03a47a0761 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -927,6 +927,7 @@
#include "code\game\objects\effects\effects.dm"
#include "code\game\objects\effects\forcefields.dm"
#include "code\game\objects\effects\glowshroom.dm"
+#include "code\game\objects\effects\info.dm"
#include "code\game\objects\effects\landmarks.dm"
#include "code\game\objects\effects\mines.dm"
#include "code\game\objects\effects\misc.dm"