From 237909eea3c0600c86ec15e9d101f225799d1071 Mon Sep 17 00:00:00 2001 From: InsaneRed Date: Thu, 16 Jan 2025 07:14:20 +0300 Subject: [PATCH 1/2] changes --- .../mob/living/carbon/xenomorph/Abilities.dm | 385 ------------------ .../abilities/burrower/burrower_abilities.dm | 20 +- .../abilities/burrower/burrower_powers.dm | 88 ++++ .../xenomorph/abilities/general_abilities.dm | 6 + .../abilities/queen/queen_abilities.dm | 46 +++ .../xenomorph/abilities/queen/queen_powers.dm | 307 +++++++++----- .../living/carbon/xenomorph/castes/Queen.dm | 10 +- colonialmarines.dme | 1 - 8 files changed, 365 insertions(+), 498 deletions(-) delete mode 100644 code/modules/mob/living/carbon/xenomorph/Abilities.dm diff --git a/code/modules/mob/living/carbon/xenomorph/Abilities.dm b/code/modules/mob/living/carbon/xenomorph/Abilities.dm deleted file mode 100644 index cc28c8779b19..000000000000 --- a/code/modules/mob/living/carbon/xenomorph/Abilities.dm +++ /dev/null @@ -1,385 +0,0 @@ -/datum/action/xeno_action/onclick/build_tunnel - name = "Dig Tunnel (200)" - action_icon_state = "build_tunnel" - plasma_cost = 200 - macro_path = /datum/action/xeno_action/verb/verb_dig_tunnel - action_type = XENO_ACTION_ACTIVATE //doesn't really need a macro - -/datum/action/xeno_action/onclick/build_tunnel/can_use_action() - if(!owner) - return FALSE - var/mob/living/carbon/xenomorph/X = owner - if(!istype(X)) - return FALSE - if(X.tunnel_delay) - return FALSE - return ..() - -/datum/action/xeno_action/onclick/build_tunnel/use_ability(atom/A) - var/mob/living/carbon/xenomorph/X = owner - if(!X.check_state()) - return - - if(X.action_busy) - to_chat(X, SPAN_XENOWARNING("We should finish up what we're doing before digging.")) - return - - var/turf/T = X.loc - if(!istype(T)) //logic - to_chat(X, SPAN_XENOWARNING("We can't do that from there.")) - return - - if(!T.can_dig_xeno_tunnel() || !is_ground_level(T.z)) - to_chat(X, SPAN_XENOWARNING("We scrape around, but we can't seem to dig through that kind of floor.")) - return - - if(locate(/obj/structure/tunnel) in X.loc) - to_chat(X, SPAN_XENOWARNING("There already is a tunnel here.")) - return - - if(locate(/obj/structure/machinery/sentry_holder/landing_zone) in X.loc) - to_chat(X, SPAN_XENOWARNING("We can't dig a tunnel with this object in the way.")) - return - - if(X.tunnel_delay) - to_chat(X, SPAN_XENOWARNING("We are not ready to dig a tunnel again.")) - return - - if(X.get_active_hand()) - to_chat(X, SPAN_XENOWARNING("We need an empty claw for this!")) - return - - if(!X.check_plasma(plasma_cost)) - return - - var/area/AR = get_area(T) - - if(isnull(AR) || !(AR.is_resin_allowed)) - if(!AR || AR.flags_area & AREA_UNWEEDABLE) - to_chat(X, SPAN_XENOWARNING("This area is unsuited to host the hive!")) - return - to_chat(X, SPAN_XENOWARNING("It's too early to spread the hive this far.")) - return - - X.visible_message(SPAN_XENONOTICE("[X] begins digging out a tunnel entrance."), \ - SPAN_XENONOTICE("We begin digging out a tunnel entrance."), null, 5) - if(!do_after(X, 100, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) - to_chat(X, SPAN_WARNING("Our tunnel caves in as we stop digging it.")) - return - if(!X.check_plasma(plasma_cost)) - return - X.visible_message(SPAN_XENONOTICE("\The [X] digs out a tunnel entrance."), \ - SPAN_XENONOTICE("We dig out an entrance to the tunnel network."), null, 5) - - var/obj/structure/tunnel/tunnelobj = new(T, X.hivenumber) - X.tunnel_delay = 1 - addtimer(CALLBACK(src, PROC_REF(cooldown_end)), 4 MINUTES) - var/msg = strip_html(input("Add a description to the tunnel:", "Tunnel Description") as text|null) - msg = replace_non_alphanumeric_plus(msg) - var/description - if(msg) - description = msg - msg = "[msg] ([get_area_name(tunnelobj)])" - log_admin("[key_name(X)] has named a new tunnel \"[msg]\".") - msg_admin_niche("[X]/([key_name(X)]) has named a new tunnel \"[msg]\".") - tunnelobj.tunnel_desc = "[msg]" - - if(X.hive.living_xeno_queen || X.hive.allow_no_queen_actions) - for(var/mob/living/carbon/xenomorph/target_for_message as anything in X.hive.totalXenos) - var/overwatch_target = XENO_OVERWATCH_TARGET_HREF - var/overwatch_src = XENO_OVERWATCH_SRC_HREF - to_chat(target_for_message, SPAN_XENOANNOUNCE("Hive: A new tunnel[description ? " ([description])" : ""] has been created by [X] (watch) at [get_area_name(tunnelobj)].")) - - X.use_plasma(plasma_cost) - to_chat(X, SPAN_NOTICE("We will be ready to dig a new tunnel in 4 minutes.")) - playsound(X.loc, 'sound/weapons/pierce.ogg', 25, 1) - - return ..() - -/datum/action/xeno_action/onclick/build_tunnel/proc/cooldown_end() - var/mob/living/carbon/xenomorph/X = owner - to_chat(X, SPAN_NOTICE("We are ready to dig a tunnel again.")) - X.tunnel_delay = 0 - -//Queen Abilities -/datum/action/xeno_action/onclick/screech - name = "Screech (250)" - action_icon_state = "screech" - macro_path = /datum/action/xeno_action/verb/verb_screech - action_type = XENO_ACTION_CLICK - xeno_cooldown = 50 SECONDS - plasma_cost = 250 - cooldown_message = "You feel your throat muscles vibrate. You are ready to screech again." - no_cooldown_msg = FALSE // Needed for onclick actions - ability_primacy = XENO_SCREECH - -/datum/action/xeno_action/onclick/screech/use_ability(atom/target) - var/mob/living/carbon/xenomorph/queen/xeno = owner - - if (!istype(xeno)) - return - - if (!action_cooldown_check()) - return - - if (!xeno.check_state()) - return - - if (!check_and_use_plasma_owner()) - return - - //screech is so powerful it kills huggers in our hands - if(istype(xeno.r_hand, /obj/item/clothing/mask/facehugger)) - var/obj/item/clothing/mask/facehugger/hugger = xeno.r_hand - if(hugger.stat != DEAD) - hugger.die() - - if(istype(xeno.l_hand, /obj/item/clothing/mask/facehugger)) - var/obj/item/clothing/mask/facehugger/hugger = xeno.l_hand - if(hugger.stat != DEAD) - hugger.die() - - playsound(xeno.loc, pick(xeno.screech_sound_effect_list), 75, 0, status = 0) - xeno.visible_message(SPAN_XENOHIGHDANGER("[xeno] emits an ear-splitting guttural roar!")) - xeno.create_shriekwave(14) //Adds the visual effect. Wom wom wom, 14 shriekwaves - - FOR_DVIEW(var/mob/mob, world.view, owner, HIDE_INVISIBLE_OBSERVER) - if(mob && mob.client) - if(isxeno(mob)) - shake_camera(mob, 10, 1) - else - shake_camera(mob, 30, 1) //50 deciseconds, SORRY 5 seconds was way too long. 3 seconds now - FOR_DVIEW_END - - var/list/mobs_in_view = list() - FOR_DOVIEW(var/mob/living/carbon/M, 7, xeno, HIDE_INVISIBLE_OBSERVER) - mobs_in_view += M - FOR_DOVIEW_END - for(var/mob/living/carbon/M in orange(10, xeno)) - if(SEND_SIGNAL(M, COMSIG_MOB_SCREECH_ACT, xeno) & COMPONENT_SCREECH_ACT_CANCEL) - continue - M.handle_queen_screech(xeno, mobs_in_view) - - apply_cooldown() - - return ..() - -/datum/action/xeno_action/activable/gut - name = "Gut (200)" - action_icon_state = "gut" - macro_path = /datum/action/xeno_action/verb/verb_gut - action_type = XENO_ACTION_CLICK - xeno_cooldown = 15 MINUTES - plasma_cost = 200 - cooldown_message = "You feel your anger return. You are ready to gut again." - -/datum/action/xeno_action/activable/gut/use_ability(atom/target) - var/mob/living/carbon/xenomorph/queen/xeno = owner - if(!action_cooldown_check()) - return - if(xeno.queen_gut(target)) - apply_cooldown() - return ..() - -/datum/action/xeno_action/onclick/psychic_whisper - name = "Psychic Whisper" - action_icon_state = "psychic_whisper" - plasma_cost = 0 - -/datum/action/xeno_action/onclick/psychic_whisper/use_ability(atom/A) - var/mob/living/carbon/xenomorph/xeno_player = owner - if(xeno_player.client.prefs.muted & MUTE_IC) - to_chat(xeno_player, SPAN_DANGER("You cannot whisper (muted).")) - return - if(!xeno_player.check_state(TRUE)) - return - var/list/target_list = list() - for(var/mob/living/carbon/possible_target in view(7, xeno_player)) - if(possible_target == xeno_player || !possible_target.client) continue - target_list += possible_target - - var/mob/living/carbon/target_mob = tgui_input_list(usr, "Target", "Send a Psychic Whisper to whom?", target_list, theme="hive_status") - if(!target_mob) return - - if(!xeno_player.check_state(TRUE)) - return - - var/whisper = tgui_input_text(xeno_player, "What do you wish to say?", "Psychic Whisper") - if(whisper) - log_say("PsychicWhisper: [key_name(xeno_player)]->[target_mob.key] : [whisper] (AREA: [get_area_name(target_mob)])") - if(!istype(target_mob, /mob/living/carbon/xenomorph)) - to_chat(target_mob, SPAN_XENOQUEEN("You hear a strange, alien voice in your head. \"[SPAN_PSYTALK(whisper)]\"")) - else - to_chat(target_mob, SPAN_XENOQUEEN("You hear the voice of [xeno_player] resonate in your head. \"[SPAN_PSYTALK(whisper)]\"")) - to_chat(xeno_player, SPAN_XENONOTICE("You said: \"[whisper]\" to [target_mob]")) - - for(var/mob/dead/observer/ghost as anything in GLOB.observer_list) - if(!ghost.client || isnewplayer(ghost)) - continue - if(ghost.client.prefs.toggles_chat & CHAT_GHOSTHIVEMIND) - var/rendered_message - var/xeno_track = "(F)" - var/target_track = "(F)" - rendered_message = SPAN_XENOLEADER("PsychicWhisper: [xeno_player.real_name][xeno_track] to [target_mob.real_name][target_track], '[SPAN_PSYTALK(whisper)]'") - ghost.show_message(rendered_message, SHOW_MESSAGE_AUDIBLE) - - return ..() - -/datum/action/xeno_action/onclick/psychic_whisper/can_use_action() - var/mob/living/carbon/xenomorph/xeno = owner - if(xeno && !xeno.is_mob_incapacitated()) - return TRUE - return FALSE - -/datum/action/xeno_action/onclick/psychic_radiance - name = "Psychic Radiance" - action_icon_state = "psychic_radiance" - plasma_cost = 100 - -/datum/action/xeno_action/onclick/psychic_radiance/use_ability(atom/A) - var/mob/living/carbon/xenomorph/xeno_player = owner - if(xeno_player.client.prefs.muted & MUTE_IC) - to_chat(xeno_player, SPAN_DANGER("You cannot whisper (muted).")) - return - if(!xeno_player.check_state(TRUE)) - return - var/list/target_list = list() - var/whisper = tgui_input_text(xeno_player, "What do you wish to say?", "Psychic Radiance") - if(!whisper || !xeno_player.check_state(TRUE)) - return - FOR_DVIEW(var/mob/living/possible_target, 12, xeno_player, HIDE_INVISIBLE_OBSERVER) - if(possible_target == xeno_player || !possible_target.client) - continue - target_list += possible_target - if(!istype(possible_target, /mob/living/carbon/xenomorph)) - to_chat(possible_target, SPAN_XENOQUEEN("You hear a strange, alien voice in your head. \"[SPAN_PSYTALK(whisper)]\"")) - else - to_chat(possible_target, SPAN_XENOQUEEN("You hear the voice of [xeno_player] resonate in your head. \"[SPAN_PSYTALK(whisper)]\"")) - FOR_DVIEW_END - if(!length(target_list)) - return - var/targetstring = english_list(target_list) - to_chat(xeno_player, SPAN_XENONOTICE("You said: \"[whisper]\" to [targetstring]")) - log_say("PsychicRadiance: [key_name(xeno_player)]->[targetstring] : [whisper] (AREA: [get_area_name(xeno_player)])") - for (var/mob/dead/observer/ghost as anything in GLOB.observer_list) - if(!ghost.client || isnewplayer(ghost)) - continue - if(ghost.client.prefs.toggles_chat & CHAT_GHOSTHIVEMIND) - var/rendered_message - var/xeno_track = "(F)" - rendered_message = SPAN_XENOLEADER("PsychicRadiance: [xeno_player.real_name][xeno_track] to [targetstring], '[SPAN_PSYTALK(whisper)]'") - ghost.show_message(rendered_message, SHOW_MESSAGE_AUDIBLE) - return ..() - -/datum/action/xeno_action/onclick/psychic_radiance/can_use_action() - var/mob/living/carbon/xenomorph/xeno = owner - if(xeno && !xeno.is_mob_incapacitated()) - return TRUE - return FALSE - -/datum/action/xeno_action/activable/queen_give_plasma - name = "Give Plasma (400)" - action_icon_state = "queen_give_plasma" - plasma_cost = 400 - macro_path = /datum/action/xeno_action/verb/verb_plasma_xeno - action_type = XENO_ACTION_CLICK - ability_primacy = XENO_PRIMARY_ACTION_2 - xeno_cooldown = 12 SECONDS - -/datum/action/xeno_action/activable/queen_give_plasma/use_ability(atom/A) - var/mob/living/carbon/xenomorph/queen/X = owner - if(!X.check_state()) - return - - if(!action_cooldown_check()) - return - - var/mob/living/carbon/xenomorph/target = A - if(!istype(target) || target.stat == DEAD) - to_chat(X, SPAN_WARNING("You must target the xeno you want to give plasma to.")) - return - - if(target == X) - to_chat(X, SPAN_XENOWARNING("You cannot give plasma to yourself!")) - return - - if(!X.can_not_harm(target)) - to_chat(X, SPAN_WARNING("You can only target xenos part of your hive!")) - return - - if(!target.caste.can_be_queen_healed) - to_chat(X, SPAN_XENOWARNING("This caste cannot be given plasma!")) - return - - if(SEND_SIGNAL(target, COMSIG_XENO_PRE_HEAL) & COMPONENT_CANCEL_XENO_HEAL) - to_chat(X, SPAN_XENOWARNING("This xeno cannot be given plasma!")) - return - - if(!check_and_use_plasma_owner()) - return - - target.gain_plasma(target.plasma_max * 0.75) - target.flick_heal_overlay(3 SECONDS, COLOR_CYAN) - apply_cooldown() - to_chat(X, SPAN_XENONOTICE("You transfer some plasma to [target].")) - return ..() - -/datum/action/xeno_action/onclick/queen_order - name = "Give Order (100)" - action_icon_state = "queen_order" - plasma_cost = 100 - -/datum/action/xeno_action/onclick/queen_order/use_ability(atom/A) - var/mob/living/carbon/xenomorph/queen/X = owner - if(!X.check_state()) - return - if(X.observed_xeno) - var/mob/living/carbon/xenomorph/target = X.observed_xeno - if(target.stat != DEAD && target.client) - if(X.check_plasma(plasma_cost)) - var/input = stripped_input(X, "This message will be sent to the overwatched xeno.", "Queen Order", "") - if(!input) - return - var/queen_order = SPAN_XENOANNOUNCE("[X] reaches you:\"[input]\"") - if(!X.check_state() || !X.check_plasma(plasma_cost) || X.observed_xeno != target || target.stat == DEAD) - return - if(target.client) - X.use_plasma(plasma_cost) - to_chat(target, "[queen_order]") - log_admin("[queen_order]") - message_admins("[key_name_admin(X)] has given the following Queen order to [target]: \"[input]\"", 1) - - else - to_chat(X, SPAN_WARNING("You must overwatch the Xenomorph you want to give orders to.")) - return - return ..() - -/datum/action/xeno_action/onclick/queen_word - name = "Word of the Queen (50)" - action_icon_state = "queen_word" - plasma_cost = 50 - xeno_cooldown = 10 SECONDS - -/datum/action/xeno_action/onclick/queen_word/use_ability(atom/target) - var/mob/living/carbon/xenomorph/queen/xeno = owner - // We don't test or apply the cooldown here because the proc does it since verbs can activate it too - xeno.hive_message() - return ..() - -/datum/action/xeno_action/onclick/queen_tacmap - name = "View Xeno Tacmap" - action_icon_state = "toggle_queen_zoom" - plasma_cost = 0 - -/datum/action/xeno_action/onclick/queen_tacmap/use_ability(atom/target) - var/mob/living/carbon/xenomorph/queen/xeno = owner - xeno.xeno_tacmap() - return ..() - -///////////////////////////////////////////////////////////////////////////////////////////// - -/mob/living/carbon/xenomorph/proc/add_abilities() - if(!base_actions) - return - for(var/action_path in base_actions) - give_action(src, action_path) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm index d8ee01d2d067..b5e834f92051 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm @@ -9,16 +9,16 @@ ability_primacy = XENO_PRIMARY_ACTION_3 /datum/action/xeno_action/activable/burrow/use_ability(atom/A) - var/mob/living/carbon/xenomorph/X = owner + var/mob/living/carbon/xenomorph/xenomorph = owner if(SSticker?.mode?.hardcore) - to_chat(X, SPAN_XENOWARNING("A certain presence is preventing us from burrowing here.")) + to_chat(xenomorph, SPAN_XENOWARNING("A certain presence is preventing us from burrowing here.")) return - if(HAS_TRAIT(X, TRAIT_ABILITY_BURROWED)) - X.tunnel(get_turf(A)) + if(HAS_TRAIT(xenomorph, TRAIT_ABILITY_BURROWED)) + xenomorph.tunnel(get_turf(A)) else - X.burrow() + xenomorph.burrow() return ..() /datum/action/xeno_action/onclick/tremor @@ -29,3 +29,13 @@ ability_primacy = XENO_PRIMARY_ACTION_4 xeno_cooldown = 45 SECONDS plasma_cost = 100 + +/datum/action/xeno_action/onclick/build_tunnel + name = "Dig Tunnel (200)" + action_icon_state = "build_tunnel" + plasma_cost = 200 + macro_path = /datum/action/xeno_action/verb/verb_dig_tunnel + action_type = XENO_ACTION_ACTIVATE //doesn't really need a macro + xeno_cooldown = 4 MINUTES + cooldown_message = "We can dig a tunnel again." + diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_powers.dm index 62d8b60d1200..aef98fe7a60e 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_powers.dm @@ -224,3 +224,91 @@ apply_cooldown() return ..() + +/datum/action/xeno_action/onclick/build_tunnel/use_ability(atom/A) + var/mob/living/carbon/xenomorph/xenomorph = owner + if(!xenomorph.check_state()) + return + + if(xenomorph.action_busy) + to_chat(xenomorph, SPAN_XENOWARNING("We should finish up what we're doing before digging.")) + return + + var/turf/turf = xenomorph.loc + if(!istype(turf)) //logic + to_chat(xenomorph, SPAN_XENOWARNING("We can't do that from there.")) + return + + if(!turf.can_dig_xeno_tunnel() || !is_ground_level(turf.z)) + to_chat(xenomorph, SPAN_XENOWARNING("We scrape around, but we can't seem to dig through that kind of floor.")) + return + + if(locate(/obj/structure/tunnel) in xenomorph.loc) + to_chat(xenomorph, SPAN_XENOWARNING("There already is a tunnel here.")) + return + + if(locate(/obj/structure/machinery/sentry_holder/landing_zone) in xenomorph.loc) + to_chat(xenomorph, SPAN_XENOWARNING("We can't dig a tunnel with this object in the way.")) + return + + if(xenomorph.tunnel_delay) + to_chat(xenomorph, SPAN_XENOWARNING("We are not ready to dig a tunnel again.")) + return + + if(xenomorph.get_active_hand()) + to_chat(xenomorph, SPAN_XENOWARNING("We need an empty claw for this!")) + return + + if(!xenomorph.check_plasma(plasma_cost)) + return + + var/area/AR = get_area(turf) + + if(isnull(AR) || !(AR.is_resin_allowed)) + if(!AR || AR.flags_area & AREA_UNWEEDABLE) + to_chat(xenomorph, SPAN_XENOWARNING("This area is unsuited to host the hive!")) + return + to_chat(xenomorph, SPAN_XENOWARNING("It's too early to spread the hive this far.")) + return + + xenomorph.visible_message(SPAN_XENONOTICE("[xenomorph] begins digging out a tunnel entrance."), \ + SPAN_XENONOTICE("We begin digging out a tunnel entrance."), null, 5) + if(!do_after(xenomorph, 10 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) + to_chat(xenomorph, SPAN_WARNING("Our tunnel caves in as we stop digging it.")) + return + if(!xenomorph.check_plasma(plasma_cost)) + return + xenomorph.visible_message(SPAN_XENONOTICE("\The [xenomorph] digs out a tunnel entrance."), \ + SPAN_XENONOTICE("We dig out an entrance to the tunnel network."), null, 5) + + var/obj/structure/tunnel/tunnelobj = new(turf, xenomorph.hivenumber) + xenomorph.tunnel_delay = 1 + addtimer(CALLBACK(src, PROC_REF(cooldown_end)), 4 MINUTES) + var/msg = strip_html(input("Add a description to the tunnel:", "Tunnel Description") as text|null) + msg = replace_non_alphanumeric_plus(msg) + var/description + if(msg) + description = msg + msg = "[msg] ([get_area_name(tunnelobj)])" + log_admin("[key_name(xenomorph)] has named a new tunnel \"[msg]\".") + msg_admin_niche("[xenomorph]/([key_name(xenomorph)]) has named a new tunnel \"[msg]\".") + tunnelobj.tunnel_desc = "[msg]" + + if(xenomorph.hive.living_xeno_queen || xenomorph.hive.allow_no_queen_actions) + for(var/mob/living/carbon/xenomorph/target_for_message as anything in xenomorph.hive.totalXenos) + var/overwatch_target = XENO_OVERWATCH_TARGET_HREF + var/overwatch_src = XENO_OVERWATCH_SRC_HREF + to_chat(target_for_message, SPAN_XENOANNOUNCE("Hive: A new tunnel[description ? " ([description])" : ""] has been created by [xenomorph] (watch) at [get_area_name(tunnelobj)].")) + + xenomorph.use_plasma(plasma_cost) + to_chat(xenomorph, SPAN_NOTICE("We will be ready to dig a new tunnel in 4 minutes.")) + playsound(xenomorph.loc, 'sound/weapons/pierce.ogg', 25, 1) + apply_cooldown() + + return ..() + + +/datum/action/xeno_action/onclick/build_tunnel/proc/cooldown_end() + var/mob/living/carbon/xenomorph/xenomorph = owner + to_chat(xenomorph, SPAN_NOTICE("We are ready to dig a tunnel again.")) + xenomorph.tunnel_delay = 0 diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm index b4fba61d51db..7485cfe0015a 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm @@ -583,3 +583,9 @@ /datum/action/xeno_action/active_toggle/toggle_meson_vision/disable_toggle() . = ..() owner.sight &= ~SEE_TURFS + +/mob/living/carbon/xenomorph/proc/add_abilities() + if(!base_actions) + return + for(var/action_path in base_actions) + give_action(src, action_path) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_abilities.dm index 4544f7c9e8d9..caaad90c4053 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_abilities.dm @@ -26,6 +26,47 @@ action_type = XENO_ACTION_CLICK xeno_cooldown = 8 SECONDS +/datum/action/xeno_action/onclick/screech + name = "Screech (250)" + action_icon_state = "screech" + macro_path = /datum/action/xeno_action/verb/verb_screech + action_type = XENO_ACTION_CLICK + xeno_cooldown = 50 SECONDS + plasma_cost = 250 + cooldown_message = "You feel your throat muscles vibrate. You are ready to screech again." + no_cooldown_msg = FALSE // Needed for onclick actions + ability_primacy = XENO_SCREECH + +/datum/action/xeno_action/onclick/queen_tacmap + name = "View Xeno Tacmap" + action_icon_state = "toggle_queen_zoom" + plasma_cost = 0 + + +/datum/action/xeno_action/activable/queen_give_plasma + name = "Give Plasma (400)" + action_icon_state = "queen_give_plasma" + plasma_cost = 400 + macro_path = /datum/action/xeno_action/verb/verb_plasma_xeno + action_type = XENO_ACTION_CLICK + ability_primacy = XENO_PRIMARY_ACTION_2 + xeno_cooldown = 12 SECONDS + +/datum/action/xeno_action/onclick/queen_word + name = "Word of the Queen (50)" + action_icon_state = "queen_word" + plasma_cost = 50 + xeno_cooldown = 10 SECONDS + +/datum/action/xeno_action/activable/gut + name = "Gut (200)" + action_icon_state = "gut" + macro_path = /datum/action/xeno_action/verb/verb_gut + action_type = XENO_ACTION_CLICK + xeno_cooldown = 15 MINUTES + plasma_cost = 200 + cooldown_message = "You feel your anger return. You are ready to gut again." + /datum/action/xeno_action/activable/expand_weeds name = "Expand Weeds (50)" action_icon_state = "plant_weeds" @@ -43,6 +84,11 @@ action_icon_state = "xeno_readmit" plasma_cost = 0 +/datum/action/xeno_action/onclick/send_thoughts // and prayers + name = "Psychic Communication" + action_icon_state = "psychic_whisper" + plasma_cost = 0 + /datum/action/xeno_action/activable/secrete_resin/remote/queen name = "Projected Resin (100)" action_icon_state = "secrete_resin" diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm index 431893bb014c..0ae08f9306da 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm @@ -316,6 +316,22 @@ if(give_jelly_award(xeno.hive)) xeno.use_plasma(plasma_cost_jelly) return + +/datum/action/xeno_action/onclick/send_thoughts/use_ability(atom/Atom) + var/mob/living/carbon/xenomorph/queen/thought_sender = owner + plasma_cost = 0 + var/list/options = list("Psychic Radiance(100)", "Psychic Whisper(0)", "Give Order(100)",) + + var/choice = tgui_input_list(thought_sender, "Communicate", "Send Thoughts", options, theme="hive_status") + switch(choice) + if("Psychic Radiance(100)") + psychic_radiance() + if("Psychic Whisper(0)") + psychic_whisper() + if("Give Order(100)") + queen_order() + return ..() + /datum/action/xeno_action/onclick/manage_hive/use_ability(atom/Atom) var/mob/living/carbon/xenomorph/queen/queen_manager = owner plasma_cost = 0 @@ -736,135 +752,226 @@ /datum/action/xeno_action/activable/expand_weeds/proc/reset_turf_cooldown(turf/T) recently_built_turfs -= T -/datum/action/xeno_action/activable/place_queen_beacon/use_ability(atom/A) - var/mob/living/carbon/xenomorph/queen/Q = owner - if(!Q.check_state()) - return FALSE +/mob/living/carbon/xenomorph/proc/xeno_tacmap() + set name = "View Xeno Tacmap" + set desc = "This opens a tactical map, where you can see where every xenomorph is." + set category = "Alien" + hive.tacmap.tgui_interact(src) - if(Q.action_busy) - return FALSE +/datum/action/xeno_action/onclick/screech/use_ability(atom/target) + var/mob/living/carbon/xenomorph/queen/xeno = owner - var/turf/T = get_turf(A) - if(!check_turf(Q, T)) - return FALSE - if(!do_after(Q, 1 SECONDS, INTERRUPT_NO_NEEDHAND, BUSY_ICON_FRIENDLY)) - return FALSE - if(!check_turf(Q, T)) - return FALSE + if (!istype(xeno)) + return + + if (!action_cooldown_check()) + return - for(var/i in transported_xenos) - UnregisterSignal(i, COMSIG_MOVABLE_PRE_MOVE) + if (!xeno.check_state()) + return - to_chat(Q, SPAN_XENONOTICE("You rally the hive to the queen beacon!")) - LAZYCLEARLIST(transported_xenos) - RegisterSignal(SSdcs, COMSIG_GLOB_XENO_SPAWN, PROC_REF(tunnel_xeno)) - for(var/xeno in hive.totalXenos) - if(xeno == Q) + if (!check_and_use_plasma_owner()) + return + + //screech is so powerful it kills huggers in our hands + if(istype(xeno.r_hand, /obj/item/clothing/mask/facehugger)) + var/obj/item/clothing/mask/facehugger/hugger = xeno.r_hand + if(hugger.stat != DEAD) + hugger.die() + + if(istype(xeno.l_hand, /obj/item/clothing/mask/facehugger)) + var/obj/item/clothing/mask/facehugger/hugger = xeno.l_hand + if(hugger.stat != DEAD) + hugger.die() + + playsound(xeno.loc, pick(xeno.screech_sound_effect_list), 75, 0, status = 0) + xeno.visible_message(SPAN_XENOHIGHDANGER("[xeno] emits an ear-splitting guttural roar!")) + xeno.create_shriekwave(14) //Adds the visual effect. Wom wom wom, 14 shriekwaves + + FOR_DVIEW(var/mob/mob, world.view, owner, HIDE_INVISIBLE_OBSERVER) + if(mob && mob.client) + if(isxeno(mob)) + shake_camera(mob, 10, 1) + else + shake_camera(mob, 30, 1) //50 deciseconds, SORRY 5 seconds was way too long. 3 seconds now + FOR_DVIEW_END + + var/list/mobs_in_view = list() + FOR_DOVIEW(var/mob/living/carbon/M, 7, xeno, HIDE_INVISIBLE_OBSERVER) + mobs_in_view += M + FOR_DOVIEW_END + for(var/mob/living/carbon/M in orange(10, xeno)) + if(SEND_SIGNAL(M, COMSIG_MOB_SCREECH_ACT, xeno) & COMPONENT_SCREECH_ACT_CANCEL) continue - tunnel_xeno(src, xeno) + M.handle_queen_screech(xeno, mobs_in_view) - addtimer(CALLBACK(src, PROC_REF(transport_xenos), T), 3 SECONDS) - return ..() + apply_cooldown() -/datum/action/xeno_action/activable/place_queen_beacon/proc/tunnel_xeno(datum/source, mob/living/carbon/xenomorph/X) - SIGNAL_HANDLER - if(X.z == owner.z) - to_chat(X, SPAN_XENONOTICE("You begin tunneling towards the queen beacon!")) - RegisterSignal(X, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(cancel_movement)) - LAZYADD(transported_xenos, X) - -/datum/action/xeno_action/activable/place_queen_beacon/proc/transport_xenos(turf/target) - UnregisterSignal(SSdcs, COMSIG_GLOB_XENO_SPAWN) - for(var/xeno in transported_xenos) - var/mob/living/carbon/xenomorph/X = xeno - to_chat(X, SPAN_XENONOTICE("You tunnel to the queen beacon!")) - UnregisterSignal(X, COMSIG_MOVABLE_PRE_MOVE) - if(target) - X.forceMove(target) - -/datum/action/xeno_action/activable/place_queen_beacon/proc/cancel_movement() - SIGNAL_HANDLER - return COMPONENT_CANCEL_MOVE - -/datum/action/xeno_action/activable/place_queen_beacon/proc/check_turf(mob/living/carbon/xenomorph/queen/Q, turf/T) - if(!T || T.density) - to_chat(Q, SPAN_XENOWARNING("You can't place a queen beacon here.")) - return FALSE + return ..() - if(T.z != Q.z) - to_chat(Q, SPAN_XENOWARNING("That's too far away!")) - return FALSE +/datum/action/xeno_action/activable/gut/use_ability(atom/target) + var/mob/living/carbon/xenomorph/queen/xeno = owner + if(!action_cooldown_check()) + return + if(xeno.queen_gut(target)) + apply_cooldown() + return ..() - var/obj/effect/alien/weeds/located_weeds = locate() in T - if(!located_weeds) - to_chat(Q, SPAN_XENOWARNING("You need to place the queen beacon on weeds.")) - return FALSE +/datum/action/xeno_action/onclick/send_thoughts/proc/psychic_whisper() + var/mob/living/carbon/xenomorph/xeno_player = owner + if(xeno_player.client.prefs.muted & MUTE_IC) + to_chat(xeno_player, SPAN_DANGER("You cannot whisper (muted).")) + return + if(!xeno_player.check_state(TRUE)) + return + var/list/target_list = list() + for(var/mob/living/carbon/possible_target in view(7, xeno_player)) + if(possible_target == xeno_player || !possible_target.client) continue + target_list += possible_target - return TRUE + var/mob/living/carbon/target_mob = tgui_input_list(usr, "Target", "Send a Psychic Whisper to whom?", target_list, theme="hive_status") + if(!target_mob) return + if(!xeno_player.check_state(TRUE)) + return -/datum/action/xeno_action/activable/blockade/use_ability(atom/A) - var/mob/living/carbon/xenomorph/queen/Q = owner - if(!Q.check_state()) - return FALSE + var/whisper = tgui_input_text(xeno_player, "What do you wish to say?", "Psychic Whisper") + if(whisper) + log_say("PsychicWhisper: [key_name(xeno_player)]->[target_mob.key] : [whisper] (AREA: [get_area_name(target_mob)])") + if(!istype(target_mob, /mob/living/carbon/xenomorph)) + to_chat(target_mob, SPAN_XENOQUEEN("You hear a strange, alien voice in your head. \"[SPAN_PSYTALK(whisper)]\"")) + else + to_chat(target_mob, SPAN_XENOQUEEN("You hear the voice of [xeno_player] resonate in your head. \"[SPAN_PSYTALK(whisper)]\"")) + to_chat(xeno_player, SPAN_XENONOTICE("You said: \"[whisper]\" to [target_mob]")) + + for(var/mob/dead/observer/ghost as anything in GLOB.observer_list) + if(!ghost.client || isnewplayer(ghost)) + continue + if(ghost.client.prefs.toggles_chat & CHAT_GHOSTHIVEMIND) + var/rendered_message + var/xeno_track = "(F)" + var/target_track = "(F)" + rendered_message = SPAN_XENOLEADER("PsychicWhisper: [xeno_player.real_name][xeno_track] to [target_mob.real_name][target_track], '[SPAN_PSYTALK(whisper)]'") + ghost.show_message(rendered_message, SHOW_MESSAGE_AUDIBLE) - if(!action_cooldown_check()) - return FALSE + return - if(Q.action_busy) - return FALSE +/datum/action/xeno_action/onclick/send_thoughts/proc/psychic_radiance() + var/radiance_plasma_cost = 100 + var/mob/living/carbon/xenomorph/xeno_player = owner - var/width = initial(pillar_type.width) - var/height = initial(pillar_type.height) + if(!xeno_player.check_plasma(radiance_plasma_cost)) + return + if(xeno_player.client.prefs.muted & MUTE_IC) + to_chat(xeno_player, SPAN_DANGER("You cannot whisper (muted).")) + return + if(!xeno_player.check_state(TRUE)) + return + var/list/target_list = list() + var/whisper = tgui_input_text(xeno_player, "What do you wish to say?", "Psychic Radiance") + if(!whisper || !xeno_player.check_state(TRUE)) + return + FOR_DVIEW(var/mob/living/possible_target, 12, xeno_player, HIDE_INVISIBLE_OBSERVER) + if(possible_target == xeno_player || !possible_target.client) + continue + target_list += possible_target + if(!istype(possible_target, /mob/living/carbon/xenomorph)) + to_chat(possible_target, SPAN_XENOQUEEN("You hear a strange, alien voice in your head. \"[SPAN_PSYTALK(whisper)]\"")) + else + to_chat(possible_target, SPAN_XENOQUEEN("You hear the voice of [xeno_player] resonate in your head. \"[SPAN_PSYTALK(whisper)]\"")) + FOR_DVIEW_END + if(!length(target_list)) + return + var/targetstring = english_list(target_list) + to_chat(xeno_player, SPAN_XENONOTICE("You said: \"[whisper]\" to [targetstring]")) + xeno_player.use_plasma(radiance_plasma_cost) + log_say("PsychicRadiance: [key_name(xeno_player)]->[targetstring] : [whisper] (AREA: [get_area_name(xeno_player)])") + for (var/mob/dead/observer/ghost as anything in GLOB.observer_list) + if(!ghost.client || isnewplayer(ghost)) + continue + if(ghost.client.prefs.toggles_chat & CHAT_GHOSTHIVEMIND) + var/rendered_message + var/xeno_track = "(F)" + rendered_message = SPAN_XENOLEADER("PsychicRadiance: [xeno_player.real_name][xeno_track] to [targetstring], '[SPAN_PSYTALK(whisper)]'") + ghost.show_message(rendered_message, SHOW_MESSAGE_AUDIBLE) + return - var/turf/T = get_turf(A) - if(T.density) - to_chat(Q, SPAN_XENOWARNING("You can only construct this blockade in open areas!")) - return FALSE +/datum/action/xeno_action/activable/queen_give_plasma/use_ability(atom/A) + var/mob/living/carbon/xenomorph/queen/X = owner + if(!X.check_state()) + return - if(T.z != owner.z) - to_chat(Q, SPAN_XENOWARNING("That's too far away!")) - return FALSE + if(!action_cooldown_check()) + return - if(!T.weeds) - to_chat(Q, SPAN_XENOWARNING("You can only construct this blockade on weeds!")) - return FALSE + var/mob/living/carbon/xenomorph/target = A + if(!istype(target) || target.stat == DEAD) + to_chat(X, SPAN_WARNING("You must target the xeno you want to give plasma to.")) + return - if(!Q.check_plasma(plasma_cost)) + if(target == X) + to_chat(X, SPAN_XENOWARNING("We cannot give plasma to yourself!")) return - var/list/alerts = list() - for(var/i as anything in RANGE_TURFS(floor(width/2), T)) - alerts += new /obj/effect/warning/alien(i) + if(!X.can_not_harm(target)) + to_chat(X, SPAN_WARNING("You can only target xenos part of your hive!")) + return - if(!do_after(Q, time_taken, INTERRUPT_NO_NEEDHAND, BUSY_ICON_FRIENDLY)) - QDEL_NULL_LIST(alerts) - return FALSE - QDEL_NULL_LIST(alerts) + if(!target.caste.can_be_queen_healed) + to_chat(X, SPAN_XENOWARNING("This caste cannot be given plasma!")) + return - if(!check_turf(Q, T)) - return FALSE + if(SEND_SIGNAL(target, COMSIG_XENO_PRE_HEAL) & COMPONENT_CANCEL_XENO_HEAL) + to_chat(X, SPAN_XENOWARNING("This xeno cannot be given plasma!")) + return if(!check_and_use_plasma_owner()) return - var/turf/new_turf = locate(max(T.x - floor(width/2), 1), max(T.y - floor(height/2), 1), T.z) - to_chat(Q, SPAN_XENONOTICE("You raise a blockade!")) - var/obj/effect/alien/resin/resin_pillar/RP = new pillar_type(new_turf) - RP.start_decay(brittle_time, decay_time) - + target.gain_plasma(target.plasma_max * 0.75) + target.flick_heal_overlay(3 SECONDS, COLOR_CYAN) + apply_cooldown() + to_chat(X, SPAN_XENONOTICE("You transfer some plasma to [target].")) return ..() -/datum/action/xeno_action/activable/blockade/proc/check_turf(mob/living/carbon/xenomorph/queen/Q, turf/T) - if(T.density) - to_chat(Q, SPAN_XENOWARNING("You can't place a blockade here.")) - return FALSE +/datum/action/xeno_action/onclick/send_thoughts/proc/queen_order() + var/mob/living/carbon/xenomorph/queen/xenomorph = owner + var/give_order_plasma_cost = 100 + + if(!xenomorph.check_plasma(give_order_plasma_cost)) + return + if(!xenomorph.check_state()) + return + if(xenomorph.observed_xeno) + var/mob/living/carbon/xenomorph/target = xenomorph.observed_xeno + if(target.stat != DEAD && target.client) + if(xenomorph.check_plasma(plasma_cost)) + var/input = stripped_input(xenomorph, "This message will be sent to the overwatched xeno.", "Queen Order", "") + if(!input) + return + var/queen_order = SPAN_XENOANNOUNCE("[xenomorph] reaches you:\"[input]\"") + if(!xenomorph.check_state() || !xenomorph.check_plasma(plasma_cost) || xenomorph.observed_xeno != target || target.stat == DEAD) + return + if(target.client) + xenomorph.use_plasma(plasma_cost) + to_chat(target, "[queen_order]") + log_admin("[queen_order]") + message_admins("[key_name_admin(xenomorph)] has given the following Queen order to [target]: \"[input]\"", 1) + xenomorph.use_plasma(give_order_plasma_cost) - return TRUE + else + to_chat(xenomorph, SPAN_WARNING("You must overwatch the Xenomorph you want to give orders to.")) + return + return -/mob/living/carbon/xenomorph/proc/xeno_tacmap() - set name = "View Xeno Tacmap" - set desc = "This opens a tactical map, where you can see where every xenomorph is." - set category = "Alien" - hive.tacmap.tgui_interact(src) +/datum/action/xeno_action/onclick/queen_word/use_ability(atom/target) + var/mob/living/carbon/xenomorph/queen/xeno = owner + // We don't test or apply the cooldown here because the proc does it since verbs can activate it too + xeno.hive_message() + return ..() + +/datum/action/xeno_action/onclick/queen_tacmap/use_ability(atom/target) + var/mob/living/carbon/xenomorph/queen/xeno = owner + xeno.xeno_tacmap() + return ..() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm b/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm index 0cc6dabd55d2..83e433b48b90 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm @@ -303,8 +303,6 @@ /datum/action/xeno_action/activable/corrosive_acid, /datum/action/xeno_action/onclick/emit_pheromones, /datum/action/xeno_action/onclick/queen_word, - /datum/action/xeno_action/onclick/psychic_whisper, - /datum/action/xeno_action/onclick/psychic_radiance, /datum/action/xeno_action/activable/gut, /datum/action/xeno_action/onclick/plant_weeds, //first macro, and fits near the resin structure buttons /datum/action/xeno_action/onclick/choose_resin/queen_macro, //fourth macro @@ -312,6 +310,7 @@ /datum/action/xeno_action/onclick/grow_ovipositor, /datum/action/xeno_action/activable/info_marker/queen, /datum/action/xeno_action/onclick/manage_hive, + /datum/action/xeno_action/onclick/send_thoughts, ) inherent_verbs = list( @@ -334,14 +333,13 @@ /datum/action/xeno_action/activable/corrosive_acid, /datum/action/xeno_action/onclick/emit_pheromones, /datum/action/xeno_action/onclick/queen_word, - /datum/action/xeno_action/onclick/psychic_whisper, - /datum/action/xeno_action/onclick/psychic_radiance, /datum/action/xeno_action/activable/gut, /datum/action/xeno_action/onclick/plant_weeds, //first macro, and fits near the resin structure buttons /datum/action/xeno_action/onclick/choose_resin/queen_macro, //fourth macro /datum/action/xeno_action/activable/secrete_resin/queen_macro, //fifth macro /datum/action/xeno_action/onclick/grow_ovipositor, /datum/action/xeno_action/onclick/manage_hive, + /datum/action/xeno_action/onclick/send_thoughts, /datum/action/xeno_action/activable/info_marker/queen, /datum/action/xeno_action/onclick/screech, //custom macro, Screech /datum/action/xeno_action/activable/xeno_spit/queen_macro, //third macro @@ -863,10 +861,9 @@ /datum/action/xeno_action/activable/place_construction/not_primary, /datum/action/xeno_action/onclick/emit_pheromones, /datum/action/xeno_action/onclick/queen_word, - /datum/action/xeno_action/onclick/psychic_whisper, - /datum/action/xeno_action/onclick/psychic_radiance, /datum/action/xeno_action/onclick/choose_resin/queen_macro, //fourth macro /datum/action/xeno_action/onclick/manage_hive, + /datum/action/xeno_action/onclick/send_thoughts, /datum/action/xeno_action/activable/info_marker/queen, // Screech is typically new for this list, but its possible they never ovi and it then is forced here: /datum/action/xeno_action/onclick/screech, //custom macro, Screech @@ -875,7 +872,6 @@ /datum/action/xeno_action/onclick/set_xeno_lead, /datum/action/xeno_action/activable/queen_heal, //first macro /datum/action/xeno_action/activable/queen_give_plasma, //second macro - /datum/action/xeno_action/onclick/queen_order, /datum/action/xeno_action/activable/expand_weeds, //third macro /datum/action/xeno_action/activable/secrete_resin/remote/queen, //fifth macro /datum/action/xeno_action/onclick/queen_tacmap, diff --git a/colonialmarines.dme b/colonialmarines.dme index 10c2be494574..038a077eb53b 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -2048,7 +2048,6 @@ #include "code\modules\mob\living\carbon\human\species\yautja\fake_sounds.dm" #include "code\modules\mob\living\carbon\human\species\yautja\fake_voice.dm" #include "code\modules\mob\living\carbon\human\species\yautja\yautja_sound.dm" -#include "code\modules\mob\living\carbon\xenomorph\Abilities.dm" #include "code\modules\mob\living\carbon\xenomorph\attack_alien.dm" #include "code\modules\mob\living\carbon\xenomorph\damage_procs.dm" #include "code\modules\mob\living\carbon\xenomorph\death.dm" From debed302575f1de51040b5e7e72293fa92c9b693 Mon Sep 17 00:00:00 2001 From: harryob <55142896+harryob@users.noreply.github.com> Date: Sat, 18 Jan 2025 09:05:51 +0000 Subject: [PATCH 2/2] radialled --- .../xenomorph/abilities/queen/queen_powers.dm | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm index 0ae08f9306da..5bfe1d7f9575 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm @@ -319,16 +319,28 @@ /datum/action/xeno_action/onclick/send_thoughts/use_ability(atom/Atom) var/mob/living/carbon/xenomorph/queen/thought_sender = owner - plasma_cost = 0 - var/list/options = list("Psychic Radiance(100)", "Psychic Whisper(0)", "Give Order(100)",) + var/static/list/options = list( + "Psychic Radiance (100)" = icon(/datum/action/xeno_action::icon_file, "psychic_radiance"), + "Psychic Whisper (0)" = icon(/datum/action/xeno_action::icon_file, "psychic_whisper"), + "Give Order (100)" = icon(/datum/action/xeno_action::icon_file, "queen_order") + ) + + var/choice + if(thought_sender.client?.prefs.no_radials_preference) + choice = tgui_input_list(thought_sender, "Communicate", "Send Thoughts", options, theme="hive_status") + else + choice = show_radial_menu(thought_sender, thought_sender?.client.eye, options) + + if(!choice) + return - var/choice = tgui_input_list(thought_sender, "Communicate", "Send Thoughts", options, theme="hive_status") + plasma_cost = 0 switch(choice) - if("Psychic Radiance(100)") + if("Psychic Radiance (100)") psychic_radiance() - if("Psychic Whisper(0)") + if("Psychic Whisper (0)") psychic_whisper() - if("Give Order(100)") + if("Give Order (100)") queen_order() return ..()