fixes merge conflict
@@ -242,6 +242,9 @@
|
||||
|
||||
#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return;
|
||||
|
||||
// Locations
|
||||
#define is_ventcrawling(A) (istype(A.loc, /obj/machinery/atmospherics))
|
||||
|
||||
// Hearing protection
|
||||
#define HEARING_PROTECTION_NONE 0
|
||||
#define HEARING_PROTECTION_MINOR 1
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
Note that AI have no need for the adjacency proc, and so this proc is a lot cleaner.
|
||||
*/
|
||||
/mob/living/silicon/ai/DblClickOn(var/atom/A, params)
|
||||
/mob/living/silicon/ai/DblClickOn(atom/A, params)
|
||||
if(client.click_intercept)
|
||||
// Not doing a click intercept here, because otherwise we double-tap with the `ClickOn` proc.
|
||||
// But we return here since we don't want to do regular dblclick handling
|
||||
@@ -23,7 +23,7 @@
|
||||
A.move_camera_by_click()
|
||||
|
||||
|
||||
/mob/living/silicon/ai/ClickOn(var/atom/A, params)
|
||||
/mob/living/silicon/ai/ClickOn(atom/A, params)
|
||||
if(client.click_intercept)
|
||||
client.click_intercept.InterceptClickOn(src, params, A)
|
||||
return
|
||||
@@ -123,7 +123,7 @@
|
||||
/mob/living/silicon/ai/RangedAttack(atom/A, params)
|
||||
A.attack_ai(src)
|
||||
|
||||
/atom/proc/attack_ai(mob/user as mob)
|
||||
/atom/proc/attack_ai(mob/user)
|
||||
return
|
||||
|
||||
/*
|
||||
@@ -132,17 +132,17 @@
|
||||
for AI shift, ctrl, and alt clicking.
|
||||
*/
|
||||
|
||||
/mob/living/silicon/ai/CtrlShiftClickOn(var/atom/A)
|
||||
/mob/living/silicon/ai/CtrlShiftClickOn(atom/A)
|
||||
A.AICtrlShiftClick(src)
|
||||
/mob/living/silicon/ai/AltShiftClickOn(var/atom/A)
|
||||
/mob/living/silicon/ai/AltShiftClickOn(atom/A)
|
||||
A.AIAltShiftClick(src)
|
||||
/mob/living/silicon/ai/ShiftClickOn(var/atom/A)
|
||||
/mob/living/silicon/ai/ShiftClickOn(atom/A)
|
||||
A.AIShiftClick(src)
|
||||
/mob/living/silicon/ai/CtrlClickOn(var/atom/A)
|
||||
/mob/living/silicon/ai/CtrlClickOn(atom/A)
|
||||
A.AICtrlClick(src)
|
||||
/mob/living/silicon/ai/AltClickOn(var/atom/A)
|
||||
/mob/living/silicon/ai/AltClickOn(atom/A)
|
||||
A.AIAltClick(src)
|
||||
/mob/living/silicon/ai/MiddleClickOn(var/atom/A)
|
||||
/mob/living/silicon/ai/MiddleClickOn(atom/A)
|
||||
A.AIMiddleClick(src)
|
||||
|
||||
|
||||
@@ -224,14 +224,6 @@
|
||||
return
|
||||
toggle_light(user)
|
||||
|
||||
// FIRE ALARMS
|
||||
|
||||
/obj/machinery/firealarm/AICtrlClick()
|
||||
if(enabled)
|
||||
reset()
|
||||
else
|
||||
alarm()
|
||||
|
||||
// AI-CONTROLLED SLIP GENERATOR IN AI CORE
|
||||
|
||||
/obj/machinery/ai_slipper/AICtrlClick(mob/living/silicon/ai/user) //Turns liquid dispenser on or off
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
adjacency code.
|
||||
*/
|
||||
|
||||
/mob/living/silicon/robot/ClickOn(var/atom/A, var/params)
|
||||
/mob/living/silicon/robot/ClickOn(atom/A, params)
|
||||
if(client.click_intercept)
|
||||
client.click_intercept.InterceptClickOn(src, params, A)
|
||||
return
|
||||
@@ -15,6 +15,8 @@
|
||||
return
|
||||
changeNext_click(1)
|
||||
|
||||
if(is_ventcrawling(src)) // To stop drones interacting with anything while ventcrawling
|
||||
return
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"] && modifiers["ctrl"])
|
||||
@@ -98,12 +100,12 @@
|
||||
return
|
||||
|
||||
//Ctrl+Middle click cycles through modules
|
||||
/mob/living/silicon/robot/proc/CtrlMiddleClickOn(var/atom/A)
|
||||
/mob/living/silicon/robot/proc/CtrlMiddleClickOn(atom/A)
|
||||
cycle_modules()
|
||||
return
|
||||
|
||||
//Middle click points
|
||||
/mob/living/silicon/robot/MiddleClickOn(var/atom/A)
|
||||
/mob/living/silicon/robot/MiddleClickOn(atom/A)
|
||||
if(istype(src, /mob/living/silicon/robot/drone))
|
||||
// Drones cannot point.
|
||||
return
|
||||
@@ -112,18 +114,31 @@
|
||||
|
||||
//Give cyborgs hotkey clicks without breaking existing uses of hotkey clicks
|
||||
// for non-doors/apcs
|
||||
/mob/living/silicon/robot/CtrlShiftClickOn(var/atom/A)
|
||||
A.BorgCtrlShiftClick(src)
|
||||
/mob/living/silicon/robot/AltShiftClickOn(var/atom/A)
|
||||
A.BorgAltShiftClick(src)
|
||||
/mob/living/silicon/robot/ShiftClickOn(var/atom/A)
|
||||
/mob/living/silicon/robot/ShiftClickOn(atom/A)
|
||||
A.BorgShiftClick(src)
|
||||
/mob/living/silicon/robot/CtrlClickOn(var/atom/A)
|
||||
/mob/living/silicon/robot/CtrlClickOn(atom/A)
|
||||
A.BorgCtrlClick(src)
|
||||
/mob/living/silicon/robot/AltClickOn(var/atom/A)
|
||||
/mob/living/silicon/robot/AltClickOn(atom/A)
|
||||
A.BorgAltClick(src)
|
||||
/mob/living/silicon/robot/CtrlShiftClickOn(atom/A)
|
||||
A.BorgCtrlShiftClick(src)
|
||||
/mob/living/silicon/robot/AltShiftClickOn(atom/A)
|
||||
A.BorgAltShiftClick(src)
|
||||
|
||||
/atom/proc/BorgCtrlShiftClick(var/mob/user) // Examines
|
||||
|
||||
/atom/proc/BorgShiftClick(mob/user)
|
||||
if(user.client && user.client.eye == user)
|
||||
user.examinate(src)
|
||||
return
|
||||
|
||||
/atom/proc/BorgCtrlClick(mob/living/silicon/robot/user) //forward to human click if not overriden
|
||||
CtrlClick(user)
|
||||
|
||||
/atom/proc/BorgAltClick(mob/living/silicon/robot/user)
|
||||
AltClick(user)
|
||||
return
|
||||
|
||||
/atom/proc/BorgCtrlShiftClick(mob/user) // Examines
|
||||
if(user.client && user.client.eye == user)
|
||||
user.examinate(src)
|
||||
return
|
||||
@@ -131,38 +146,29 @@
|
||||
/atom/proc/BorgAltShiftClick()
|
||||
return
|
||||
|
||||
/obj/machinery/door/airlock/BorgAltShiftClick(mob/living/silicon/robot/user) // Enables emergency override on doors! Forwards to AI code.
|
||||
AIAltShiftClick(user)
|
||||
|
||||
/atom/proc/BorgShiftClick(var/mob/user)
|
||||
if(user.client && user.client.eye == user)
|
||||
user.examinate(src)
|
||||
return
|
||||
// AIRLOCKS
|
||||
|
||||
/obj/machinery/door/airlock/BorgShiftClick(mob/living/silicon/robot/user) // Opens and closes doors! Forwards to AI code.
|
||||
AIShiftClick(user)
|
||||
|
||||
/atom/proc/BorgCtrlClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
|
||||
CtrlClick(user)
|
||||
|
||||
/obj/machinery/door/airlock/BorgCtrlClick(mob/living/silicon/robot/user) // Bolts doors. Forwards to AI code.
|
||||
AICtrlClick(user)
|
||||
|
||||
/obj/machinery/power/apc/BorgCtrlClick(mob/living/silicon/robot/user) // turns off/on APCs. Forwards to AI code.
|
||||
AICtrlClick(user)
|
||||
|
||||
/obj/machinery/turretid/BorgCtrlClick(mob/living/silicon/robot/user) //turret control on/off. Forwards to AI code.
|
||||
AICtrlClick(user)
|
||||
|
||||
/atom/proc/BorgAltClick(var/mob/living/silicon/robot/user)
|
||||
AltClick(user)
|
||||
return
|
||||
|
||||
/obj/machinery/door/airlock/BorgAltClick(mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code.
|
||||
AIAltClick(user)
|
||||
|
||||
/obj/machinery/turretid/BorgAltClick(mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
|
||||
AIAltClick(user)
|
||||
/obj/machinery/door/airlock/BorgAltShiftClick(mob/living/silicon/robot/user) // Enables emergency override on doors! Forwards to AI code.
|
||||
AIAltShiftClick(user)
|
||||
|
||||
|
||||
// APC
|
||||
|
||||
/obj/machinery/power/apc/BorgCtrlClick(mob/living/silicon/robot/user) // turns off/on APCs. Forwards to AI code.
|
||||
AICtrlClick(user)
|
||||
|
||||
|
||||
// AI SLIPPER
|
||||
|
||||
/obj/machinery/ai_slipper/BorgCtrlClick(mob/living/silicon/robot/user) //Turns liquid dispenser on or off
|
||||
ToggleOn()
|
||||
@@ -170,9 +176,15 @@
|
||||
/obj/machinery/ai_slipper/BorgAltClick(mob/living/silicon/robot/user) //Dispenses liquid if on
|
||||
Activate()
|
||||
|
||||
/obj/machinery/firealarm/BorgCtrlClick(mob/living/silicon/robot/user)
|
||||
|
||||
// TURRETCONTROL
|
||||
|
||||
/obj/machinery/turretid/BorgCtrlClick(mob/living/silicon/robot/user) //turret control on/off. Forwards to AI code.
|
||||
AICtrlClick(user)
|
||||
|
||||
/obj/machinery/turretid/BorgAltClick(mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
|
||||
AIAltClick(user)
|
||||
|
||||
/*
|
||||
As with AI, these are not used in click code,
|
||||
because the code for robots is specific, not generic.
|
||||
@@ -187,6 +199,6 @@
|
||||
/mob/living/silicon/robot/RangedAttack(atom/A, params)
|
||||
A.attack_robot(src)
|
||||
|
||||
/atom/proc/attack_robot(mob/user as mob)
|
||||
/atom/proc/attack_robot(mob/user)
|
||||
attack_ai(user)
|
||||
return
|
||||
|
||||
@@ -41,9 +41,16 @@
|
||||
var/tech_fluff_string = "BOOT SEQUENCE COMPLETE. ERROR MODULE LOADED. THIS SHOULDN'T HAPPEN. Submit a bug report!"
|
||||
var/bio_fluff_string = "Your scarabs fail to mutate. This shouldn't happen! Submit a bug report!"
|
||||
var/admin_fluff_string = "URK URF!"//the wheels on the bus...
|
||||
var/adminseal = FALSE
|
||||
var/name_color = "white"//only used with protector shields for the time being
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/Initialize(mapload, mob/living/host)
|
||||
. = ..()
|
||||
if(!host)
|
||||
return
|
||||
summoner = host
|
||||
host.grant_guardian_actions(src)
|
||||
RegisterSignal(host, COMSIG_MOB_DEATH, .proc/on_host_death)
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/med_hud_set_health()
|
||||
if(summoner)
|
||||
var/image/holder = hud_list[HEALTH_HUD]
|
||||
@@ -59,19 +66,26 @@
|
||||
else
|
||||
holder.icon_state = "hudhealthy"
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/Life(seconds, times_fired) //Dies if the summoner dies
|
||||
/**
|
||||
* Proc which is called when the guardian's host dies.
|
||||
*
|
||||
* This will only fire if the guardian was created through a holoparsite injector, or the equivalent.
|
||||
*/
|
||||
/mob/living/simple_animal/hostile/guardian/proc/on_host_death()
|
||||
if(summoner.stat == DEAD || (!summoner.check_death_method() && summoner.health <= HEALTH_THRESHOLD_DEAD))
|
||||
summoner.remove_guardian_actions() // Remove our summoner's action buttons.
|
||||
to_chat(src, "<span class='danger'>Your summoner has died!</span>")
|
||||
visible_message("<span class='danger'>[src] dies along with its user!</span>")
|
||||
ghostize()
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/Life(seconds, times_fired)
|
||||
..()
|
||||
if(summoner)
|
||||
if(summoner.stat == DEAD || (!summoner.check_death_method() && summoner.health <= HEALTH_THRESHOLD_DEAD))
|
||||
to_chat(src, "<span class='danger'>Your summoner has died!</span>")
|
||||
visible_message("<span class='danger'>[src] dies along with its user!</span>")
|
||||
ghostize()
|
||||
qdel(src)
|
||||
snapback()
|
||||
if(summoned && !summoner && !adminseal)
|
||||
if(summoned && !summoner && !admin_spawned)
|
||||
to_chat(src, "<span class='danger'>You somehow lack a summoner! As a result, you dispel!</span>")
|
||||
ghostize()
|
||||
qdel()
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/proc/snapback()
|
||||
// If the summoner dies instantly, the summoner's ghost may be drawn into null space as the protector is deleted. This check should prevent that.
|
||||
@@ -197,7 +211,7 @@
|
||||
|
||||
//override set to true if message should be passed through instead of going to host communication
|
||||
/mob/living/simple_animal/hostile/guardian/say(message, override = FALSE)
|
||||
if(adminseal || override)//if it's an admin-spawned guardian without a host it can still talk normally
|
||||
if(admin_spawned || override)//if it's an admin-spawned guardian without a host it can still talk normally
|
||||
return ..(message)
|
||||
Communicate(message)
|
||||
|
||||
@@ -206,61 +220,6 @@
|
||||
to_chat(src, "<span class='danger'>You dont have another mode!</span>")
|
||||
|
||||
|
||||
/mob/living/proc/guardian_comm()
|
||||
set name = "Communicate"
|
||||
set category = "Guardian"
|
||||
set desc = "Communicate telepathically with your guardian."
|
||||
var/input = stripped_input(src, "Please enter a message to tell your guardian.", "Message", "")
|
||||
if(!input)
|
||||
return
|
||||
|
||||
// Find the guardian in our host's contents.
|
||||
var/mob/living/simple_animal/hostile/guardian/G = locate() in contents
|
||||
if(!G)
|
||||
return
|
||||
|
||||
// Show the message to our guardian and to host.
|
||||
to_chat(G, "<span class='changeling'><i>[src]:</i> [input]</span>")
|
||||
to_chat(src, "<span class='changeling'><i>[src]:</i> [input]</span>")
|
||||
log_say("(GUARDIAN to [key_name(G)]) [input]", src)
|
||||
create_log(SAY_LOG, "HOST to GUARDIAN: [input]", G)
|
||||
|
||||
// Show the message to any ghosts/dead players.
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
if(M && M.client && M.stat == DEAD && !isnewplayer(M))
|
||||
to_chat(M, "<span class='changeling'><i>Guardian Communication from <b>[src]</b> ([ghost_follow_link(src, ghost=M)]): [input]</i>")
|
||||
|
||||
/mob/living/proc/guardian_recall()
|
||||
set name = "Recall Guardian"
|
||||
set category = "Guardian"
|
||||
set desc = "Forcibly recall your guardian."
|
||||
for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.mob_list)
|
||||
if(G.summoner == src)
|
||||
G.Recall()
|
||||
|
||||
/mob/living/proc/guardian_reset()
|
||||
set name = "Reset Guardian Player (One Use)"
|
||||
set category = "Guardian"
|
||||
set desc = "Re-rolls which ghost will control your Guardian. One use."
|
||||
|
||||
src.verbs -= /mob/living/proc/guardian_reset
|
||||
for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.mob_list)
|
||||
if(G.summoner == src)
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as [G.real_name]?", ROLE_GUARDIAN, FALSE, 10 SECONDS, source = G)
|
||||
var/mob/dead/observer/new_stand = null
|
||||
if(candidates.len)
|
||||
new_stand = pick(candidates)
|
||||
to_chat(G, "Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.")
|
||||
to_chat(src, "Your guardian has been successfully reset.")
|
||||
message_admins("[key_name_admin(new_stand)] has taken control of ([key_name_admin(G)])")
|
||||
G.ghostize()
|
||||
G.key = new_stand.key
|
||||
else
|
||||
to_chat(src, "There were no ghosts willing to take control. Looks like you're stuck with your Guardian for now.")
|
||||
spawn(3000)
|
||||
verbs += /mob/living/proc/guardian_reset
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/proc/ToggleLight()
|
||||
if(!light_on)
|
||||
set_light(luminosity_on)
|
||||
@@ -364,7 +323,6 @@
|
||||
pickedtype = /mob/living/simple_animal/hostile/guardian/protector
|
||||
|
||||
var/mob/living/simple_animal/hostile/guardian/G = new pickedtype(user, user)
|
||||
G.summoner = user
|
||||
G.summoned = TRUE
|
||||
G.key = key
|
||||
to_chat(G, "You are a [mob_name] bound to serve [user.real_name].")
|
||||
@@ -372,9 +330,6 @@
|
||||
to_chat(G, "While personally invincible, you will die if [user.real_name] does, and any damage dealt to you will have a portion passed on to them as you feed upon them to sustain yourself.")
|
||||
to_chat(G, "[G.playstyle_string]")
|
||||
G.faction = user.faction
|
||||
user.verbs += /mob/living/proc/guardian_comm
|
||||
user.verbs += /mob/living/proc/guardian_recall
|
||||
user.verbs += /mob/living/proc/guardian_reset
|
||||
|
||||
var/color = pick(color_list)
|
||||
G.name_color = color_list[color]
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* # Base guardian host action
|
||||
*
|
||||
* These are used by guardian hosts to interact with their guardians. These are not buttons that guardians themselves use.
|
||||
*/
|
||||
/datum/action/guardian
|
||||
name = "Generic guardian host action"
|
||||
icon_icon = 'icons/mob/guardian.dmi'
|
||||
button_icon_state = "base"
|
||||
var/mob/living/simple_animal/hostile/guardian/guardian
|
||||
|
||||
/datum/action/guardian/Grant(mob/M, mob/living/simple_animal/hostile/guardian/G)
|
||||
if(!G || !istype(G))
|
||||
stack_trace("/datum/action/guardian created with no guardian to link to.")
|
||||
qdel(src)
|
||||
guardian = G
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* # Communicate action
|
||||
*
|
||||
* Allows the guardian host to communicate with their guardian.
|
||||
*/
|
||||
/datum/action/guardian/communicate
|
||||
name = "Communicate"
|
||||
desc = "Communicate telepathically with your guardian."
|
||||
button_icon_state = "communicate"
|
||||
|
||||
/datum/action/guardian/communicate/Trigger()
|
||||
var/input = stripped_input(owner, "Enter a message to tell your guardian:", "Message", "")
|
||||
if(!input)
|
||||
return
|
||||
|
||||
// Show the message to our guardian and to host.
|
||||
to_chat(guardian, "<span class='changeling'><i>[owner]:</i> [input]</span>")
|
||||
to_chat(owner, "<span class='changeling'><i>[owner]:</i> [input]</span>")
|
||||
log_say("(GUARDIAN to [key_name(guardian)]) [input]", owner)
|
||||
owner.create_log(SAY_LOG, "HOST to GUARDIAN: [input]", guardian)
|
||||
|
||||
// Show the message to any ghosts/dead players.
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
if(M && M.client && M.stat == DEAD && !isnewplayer(M))
|
||||
to_chat(M, "<span class='changeling'><i>Guardian Communication from <b>[owner]</b> ([ghost_follow_link(owner, ghost=M)]): [input]</i>")
|
||||
|
||||
/**
|
||||
* # Recall guardian action
|
||||
*
|
||||
* Allows the guardian host to recall their guardian.
|
||||
*/
|
||||
/datum/action/guardian/recall
|
||||
name = "Recall Guardian"
|
||||
desc = "Forcibly recall your guardian."
|
||||
button_icon_state = "recall"
|
||||
|
||||
/datum/action/guardian/recall/Trigger()
|
||||
guardian.Recall()
|
||||
|
||||
/**
|
||||
* # Reset guardian action
|
||||
*
|
||||
* Allows the guardian host to exchange their guardian's player for another.
|
||||
*/
|
||||
/datum/action/guardian/reset_guardian
|
||||
name = "Replace Guardian Player"
|
||||
desc = "Replace your guardian's player with a ghost. This can only be done once."
|
||||
button_icon_state = "reset"
|
||||
var/cooldown_timer
|
||||
|
||||
/datum/action/guardian/reset_guardian/IsAvailable()
|
||||
if(cooldown_timer)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/guardian/reset_guardian/Trigger()
|
||||
if(cooldown_timer)
|
||||
to_chat(owner, "<span class='warning'>This ability is still recharging.</span>")
|
||||
return
|
||||
|
||||
var/confirm = alert("Are you sure you want replace your guardian's player?", "Confirm", "Yes", "No")
|
||||
if(confirm == "No")
|
||||
return
|
||||
|
||||
// Do this immediately, so the user can't spam a bunch of polls.
|
||||
cooldown_timer = addtimer(CALLBACK(src, .proc/reset_cooldown), 5 MINUTES)
|
||||
UpdateButtonIcon()
|
||||
|
||||
to_chat(owner, "<span class='danger'>Searching for a replacement ghost...</span>")
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as [guardian.real_name]?", ROLE_GUARDIAN, FALSE, 15 SECONDS, source = guardian)
|
||||
|
||||
if(!length(candidates))
|
||||
to_chat(owner, "<span class='danger'>There were no ghosts willing to take control of your guardian. You can try again in 5 minutes.</span>")
|
||||
return
|
||||
|
||||
var/mob/dead/observer/new_stand = pick(candidates)
|
||||
to_chat(guardian, "<span class='danger'>Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.</span>")
|
||||
to_chat(owner, "<span class='danger'>Your guardian has been successfully reset.</span>")
|
||||
message_admins("[key_name_admin(new_stand)] has taken control of ([key_name_admin(guardian)])")
|
||||
guardian.ghostize()
|
||||
guardian.key = new_stand.key
|
||||
qdel(src)
|
||||
|
||||
/**
|
||||
* Takes the action button off cooldown and makes it available again.
|
||||
*/
|
||||
/datum/action/guardian/reset_guardian/proc/reset_cooldown()
|
||||
cooldown_timer = null
|
||||
UpdateButtonIcon()
|
||||
|
||||
/**
|
||||
* Grants all existing `/datum/action/guardian` type actions to the src mob.
|
||||
*
|
||||
* Called whenever the host gains their gauardian.
|
||||
*/
|
||||
/mob/living/proc/grant_guardian_actions(mob/living/simple_animal/hostile/guardian/G)
|
||||
if(!G || !istype(G))
|
||||
return
|
||||
for(var/action in subtypesof(/datum/action/guardian))
|
||||
var/datum/action/guardian/A = new action
|
||||
A.Grant(src, G)
|
||||
|
||||
/**
|
||||
* Removes all `/datum/action/guardian` type actions from the src mob.
|
||||
*
|
||||
* Called whenever the host loses their guardian.
|
||||
*/
|
||||
/mob/living/proc/remove_guardian_actions()
|
||||
for(var/action in actions)
|
||||
var/datum/action/A = action
|
||||
if(istype(A, /datum/action/guardian))
|
||||
A.Remove(src)
|
||||
@@ -26,7 +26,7 @@
|
||||
melee_damage_lower = 0
|
||||
melee_damage_upper = 0
|
||||
melee_damage_type = STAMINA
|
||||
adminseal = TRUE
|
||||
admin_spawned = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/healer/New()
|
||||
..()
|
||||
@@ -68,7 +68,7 @@
|
||||
hud_used.action_intent.icon_state = a_intent
|
||||
speed = 0
|
||||
damage_transfer = 0.7
|
||||
if(adminseal)
|
||||
if(admin_spawned)
|
||||
damage_transfer = 0
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
@@ -79,7 +79,7 @@
|
||||
hud_used.action_intent.icon_state = a_intent
|
||||
speed = 1
|
||||
damage_transfer = 1
|
||||
if(adminseal)
|
||||
if(admin_spawned)
|
||||
damage_transfer = 0
|
||||
melee_damage_lower = 0
|
||||
melee_damage_upper = 0
|
||||
|
||||
@@ -18,13 +18,12 @@
|
||||
var/list/enemychains = list()
|
||||
var/successfulshocks = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/New(loc, mob/living/user)
|
||||
. = ..()
|
||||
if(!user)
|
||||
return
|
||||
summoner = user
|
||||
if(!(NO_SHOCK in summoner.mutations))
|
||||
summoner.mutations.Add(NO_SHOCK)
|
||||
/mob/living/simple_animal/hostile/guardian/beam/Initialize(mapload, mob/living/host)
|
||||
. = ..()
|
||||
if(!summoner)
|
||||
return
|
||||
if(!(NO_SHOCK in summoner.mutations))
|
||||
summoner.mutations.Add(NO_SHOCK)
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
|
||||
return FALSE //You are lightning, you should not be hurt by such things.
|
||||
|
||||
@@ -45,4 +45,4 @@
|
||||
playstyle_string = "As a standard type you have no special abilities, but have a high damage resistance and a powerful attack capable of smashing through walls."
|
||||
environment_smash = 2
|
||||
battlecry = "URK"
|
||||
adminseal = TRUE
|
||||
admin_spawned = TRUE
|
||||
|
||||
@@ -367,10 +367,8 @@ update_flag
|
||||
if("eject")
|
||||
if(holding)
|
||||
if(valve_open)
|
||||
if(air_contents && (air_contents.toxins > 0 || air_contents.sleeping_agent > 0))
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] removed [holding] from [src] with valve still open at [ADMIN_VERBOSEJMP(src)] releasing contents into the <span class='boldannounce'>air</span>.")
|
||||
release_log += "[key_name(usr)] removed the [holding], leaving the valve open and transferring into the air<br>"
|
||||
investigate_log("[key_name(usr)] removed the [holding], leaving the valve open and transferring into the <span class='boldannounce'>air</span>.", "atmos")
|
||||
valve_open = FALSE
|
||||
release_log += "Valve was <b>closed</b> by [key_name(usr)], stopping the transfer into the [holding]<br>"
|
||||
replace_tank(usr, FALSE)
|
||||
if("recolor")
|
||||
if(can_label)
|
||||
|
||||
@@ -32,7 +32,6 @@ FIRE ALARM
|
||||
|
||||
var/wiresexposed = 0
|
||||
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
|
||||
var/enabled = FALSE
|
||||
|
||||
var/report_fire_alarms = TRUE // Should triggered fire alarms also trigger an actual alarm?
|
||||
var/show_alert_level = TRUE // Should fire alarms display the current alert level?
|
||||
|
||||
@@ -183,6 +183,82 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/borg/upgrade/abductor_engi
|
||||
name = "engineering cyborg abductor upgrade"
|
||||
desc = "An experimental upgrade that replaces an engineering cyborgs tools with the abductor version."
|
||||
icon_state = "abductor_mod"
|
||||
origin_tech = "engineering=6;materials=6;abductor=3"
|
||||
require_module = TRUE
|
||||
module_type = /obj/item/robot_module/engineering
|
||||
|
||||
/obj/item/borg/upgrade/abductor_engi/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
|
||||
for(var/obj/item/weldingtool/largetank/cyborg/W in R.module.modules)
|
||||
qdel(W)
|
||||
for(var/obj/item/screwdriver/cyborg/S in R.module.modules)
|
||||
qdel(S)
|
||||
for(var/obj/item/wrench/cyborg/E in R.module.modules)
|
||||
qdel(E)
|
||||
for(var/obj/item/crowbar/cyborg/C in R.module.modules)
|
||||
qdel(C)
|
||||
for(var/obj/item/wirecutters/cyborg/I in R.module.modules)
|
||||
qdel(I)
|
||||
for(var/obj/item/multitool/cyborg/M in R.module.modules)
|
||||
qdel(M)
|
||||
|
||||
R.module.modules += new /obj/item/weldingtool/abductor(R.module)
|
||||
R.module.modules += new /obj/item/wrench/abductor(R.module)
|
||||
R.module.modules += new /obj/item/screwdriver/abductor(R.module)
|
||||
R.module.modules += new /obj/item/crowbar/abductor(R.module)
|
||||
R.module.modules += new /obj/item/wirecutters/abductor(R.module)
|
||||
R.module.modules += new /obj/item/multitool/abductor(R.module)
|
||||
R.module.rebuild()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/borg/upgrade/abductor_medi
|
||||
name = "medical cyborg abductor upgrade"
|
||||
desc = "An experimental upgrade that replaces a medical cyborgs tools with the abductor version."
|
||||
icon_state = "abductor_mod"
|
||||
origin_tech = "biotech=6;materials=6;abductor=3"
|
||||
require_module = TRUE
|
||||
module_type = /obj/item/robot_module/medical
|
||||
|
||||
/obj/item/borg/upgrade/abductor_medi/action(mob/living/silicon/robot/R)
|
||||
if(..())
|
||||
return
|
||||
|
||||
for(var/obj/item/scalpel/laser/laser1/L in R.module.modules)
|
||||
qdel(L)
|
||||
for(var/obj/item/hemostat/H in R.module.modules)
|
||||
qdel(H)
|
||||
for(var/obj/item/retractor/E in R.module.modules)
|
||||
qdel(E)
|
||||
for(var/obj/item/bonegel/B in R.module.modules)
|
||||
qdel(B)
|
||||
for(var/obj/item/FixOVein/F in R.module.modules)
|
||||
qdel(F)
|
||||
for(var/obj/item/bonesetter/S in R.module.modules)
|
||||
qdel(S)
|
||||
for(var/obj/item/circular_saw/C in R.module.modules)
|
||||
qdel(C)
|
||||
for(var/obj/item/surgicaldrill/D in R.module.modules)
|
||||
qdel(D)
|
||||
|
||||
R.module.modules += new /obj/item/scalpel/laser/laser3(R.module) //no abductor laser scalpel, so next best thing.
|
||||
R.module.modules += new /obj/item/hemostat/alien(R.module)
|
||||
R.module.modules += new /obj/item/retractor/alien(R.module)
|
||||
R.module.modules += new /obj/item/bonegel/alien(R.module)
|
||||
R.module.modules += new /obj/item/FixOVein/alien(R.module)
|
||||
R.module.modules += new /obj/item/bonesetter/alien(R.module)
|
||||
R.module.modules += new /obj/item/circular_saw/alien(R.module)
|
||||
R.module.modules += new /obj/item/surgicaldrill/alien(R.module)
|
||||
R.module.rebuild()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/borg/upgrade/syndicate
|
||||
name = "safety override module"
|
||||
desc = "Unlocks the hidden, deadlier functions of a cyborg."
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
desc = "It's the heavy-duty black polymer kind. Time to take out the trash!"
|
||||
icon = 'icons/obj/janitor.dmi'
|
||||
icon_state = "trashbag"
|
||||
item_state = "trashbag"
|
||||
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
max_w_class = WEIGHT_CLASS_SMALL
|
||||
@@ -48,14 +47,19 @@
|
||||
|
||||
/obj/item/storage/bag/trash/update_icon()
|
||||
switch(contents.len)
|
||||
if(20 to INFINITY)
|
||||
if(21 to INFINITY)
|
||||
icon_state = "[initial(icon_state)]3"
|
||||
if(11 to 20)
|
||||
icon_state = "[initial(icon_state)]2"
|
||||
if(1 to 11)
|
||||
if(1 to 10)
|
||||
icon_state = "[initial(icon_state)]1"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]"
|
||||
if(ishuman(loc))
|
||||
var/mob/living/carbon/human/H = loc
|
||||
H.update_inv_l_hand()
|
||||
H.update_inv_r_hand()
|
||||
..()
|
||||
|
||||
/obj/item/storage/bag/trash/cyborg
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/structure/closet/attack_ai(mob/user)
|
||||
if(isrobot(user) && Adjacent(user) && !istype(user.loc, /obj/machinery/atmospherics)) //Robots can open/close it, but not the AI
|
||||
if(isrobot(user) && Adjacent(user)) //Robots can open/close it, but not the AI
|
||||
attack_hand(user)
|
||||
|
||||
/obj/structure/closet/relaymove(mob/user)
|
||||
|
||||
@@ -312,6 +312,22 @@
|
||||
flags = BLOCKHAIR
|
||||
flags_inv = HIDEEARS
|
||||
|
||||
/obj/item/clothing/suit/hooded/salmon_costume
|
||||
name = "salmon suit"
|
||||
desc = "A costume made from authentic salmon scales, it reeks!"
|
||||
icon_state = "salmon"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
allowed = list(/obj/item/fish/salmon, /obj/item/fish_eggs/salmon)
|
||||
hoodtype = /obj/item/clothing/head/hooded/salmon_hood
|
||||
|
||||
/obj/item/clothing/head/hooded/salmon_hood
|
||||
name = "salmon hood"
|
||||
desc = "A hood attached to a salmon suit."
|
||||
icon_state = "salmon"
|
||||
body_parts_covered = HEAD
|
||||
flags = BLOCKHAIR
|
||||
flags_inv = HIDEEARS
|
||||
|
||||
/obj/item/clothing/suit/hooded/bee_costume // It's Hip!
|
||||
name = "bee costume"
|
||||
desc = "Bee the true Queen!"
|
||||
|
||||
@@ -152,3 +152,13 @@
|
||||
/obj/item/clothing/shoes/sandal = 1)
|
||||
tools = list(TOOL_WIRECUTTER)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/salmonsuit
|
||||
name = "Salmon Suit"
|
||||
result = /obj/item/clothing/suit/hooded/salmon_costume
|
||||
time = 60
|
||||
reqs = list(/obj/item/fish/salmon = 20,
|
||||
/obj/item/stack/tape_roll = 5)
|
||||
tools = list(TOOL_WIRECUTTER)
|
||||
pathtools = list(/obj/item/kitchen/knife)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
return FALSE
|
||||
|
||||
/mob/proc/death(gibbed)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
|
||||
return FALSE
|
||||
|
||||
/mob/proc/dust_animation()
|
||||
|
||||
@@ -514,10 +514,10 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
|
||||
|
||||
/mob/living/update_pipe_vision()
|
||||
if(pipes_shown.len)
|
||||
if(!istype(loc, /obj/machinery/atmospherics))
|
||||
if(!is_ventcrawling(src))
|
||||
remove_ventcrawl()
|
||||
else
|
||||
if(istype(loc, /obj/machinery/atmospherics))
|
||||
if(is_ventcrawling(src))
|
||||
add_ventcrawl(loc)
|
||||
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
// Whew! Good thing I'm indestructible! (or already dead)
|
||||
return FALSE
|
||||
|
||||
..()
|
||||
stat = DEAD
|
||||
SetDizzy(0)
|
||||
SetJitter(0)
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
var/list/temp_list = modules
|
||||
modules = list()
|
||||
for(var/obj/O in temp_list)
|
||||
if(O)
|
||||
if(!QDELETED(O)) //so items getting deleted don't stay in module list and haunt you
|
||||
modules += O
|
||||
|
||||
/obj/item/robot_module/proc/add_languages(mob/living/silicon/robot/R)
|
||||
|
||||
@@ -311,15 +311,6 @@
|
||||
/obj/machinery/power/supermatter_shard/attack_robot(mob/user as mob)
|
||||
if(Adjacent(user))
|
||||
return attack_hand(user)
|
||||
else
|
||||
ui_interact(user)
|
||||
return
|
||||
|
||||
/obj/machinery/power/supermatter_shard/attack_ai(mob/user as mob)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/power/supermatter_shard/attack_ghost(mob/user as mob)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/power/supermatter_shard/attack_hand(mob/user as mob)
|
||||
user.visible_message("<span class=\"warning\">\The [user] reaches out and touches \the [src], inducing a resonance... [user.p_their(TRUE)] body starts to glow and bursts into flames before flashing into ash.</span>",\
|
||||
@@ -336,35 +327,6 @@
|
||||
integrity = integrity < 0 ? 0 : integrity
|
||||
return integrity
|
||||
|
||||
// This is purely informational UI that may be accessed by AIs or robots
|
||||
/obj/machinery/power/supermatter_shard/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "supermatter_crystal.tmpl", "Supermatter Crystal", 500, 300)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/power/supermatter_shard/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
|
||||
data["integrity_percentage"] = round(get_integrity())
|
||||
var/datum/gas_mixture/env = null
|
||||
if(!istype(src.loc, /turf/space))
|
||||
env = src.loc.return_air()
|
||||
|
||||
if(!env)
|
||||
data["ambient_temp"] = 0
|
||||
data["ambient_pressure"] = 0
|
||||
else
|
||||
data["ambient_temp"] = round(env.temperature)
|
||||
data["ambient_pressure"] = round(env.return_pressure())
|
||||
if(damage > explosion_point)
|
||||
data["detonating"] = 1
|
||||
else
|
||||
data["detonating"] = 0
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/power/supermatter_shard/proc/transfer_energy()
|
||||
for(var/obj/machinery/power/rad_collector/R in GLOB.rad_collectors)
|
||||
if(get_dist(R, src) <= 15) // Better than using orange() every process
|
||||
|
||||
@@ -185,7 +185,8 @@
|
||||
/obj/structure/sign,
|
||||
/obj/machinery/gateway,
|
||||
/obj/structure/grille,
|
||||
/obj/machinery/the_singularitygen/tesla))
|
||||
/obj/machinery/the_singularitygen/tesla,
|
||||
/mob/living/simple_animal/slime))
|
||||
|
||||
|
||||
for(var/A in typecache_filter_multi_list_exclusion(oview(source, zap_range+2), things_to_shock, blacklisted_tesla_types))
|
||||
|
||||
@@ -917,6 +917,7 @@
|
||||
reagent_state = LIQUID
|
||||
color = "#191919"
|
||||
metabolization_rate = 0.1
|
||||
can_synth = FALSE
|
||||
penetrates_skin = TRUE
|
||||
taste_mult = 0
|
||||
|
||||
|
||||
@@ -1081,6 +1081,26 @@
|
||||
construction_time = 120
|
||||
category = list("Cyborg Upgrade Modules")
|
||||
|
||||
/datum/design/borg_upgrade_abductor_engi
|
||||
name = "Cyborg Upgrade (Abdcutor Engineering Equipment)"
|
||||
id = "borg_upgade_abductor_engi"
|
||||
build_type = MECHFAB
|
||||
build_path = /obj/item/borg/upgrade/abductor_engi
|
||||
req_tech = list("engineering" = 7, "materials" = 7, "abductor" = 4)
|
||||
materials = list(MAT_METAL = 25000, MAT_SILVER = 12500, MAT_PLASMA = 5000, MAT_TITANIUM = 10000, MAT_DIAMOND = 10000) //Base abductor engineering tools * 4
|
||||
construction_time = 120
|
||||
category = list("Cyborg Upgrade Modules")
|
||||
|
||||
/datum/design/borg_upgrade_abductor_medi
|
||||
name = "Cyborg Upgrade (Abdcutor Medical Equipment)"
|
||||
id = "borg_upgade_abductor_medi"
|
||||
build_type = MECHFAB
|
||||
build_path = /obj/item/borg/upgrade/abductor_medi
|
||||
req_tech = list("biotech" = 7, "materials" = 7, "abductor" = 4)
|
||||
materials = list(MAT_METAL = 18000, MAT_GLASS = 1500, MAT_SILVER = 13000, MAT_GOLD = 1000, MAT_PLASMA = 4000, MAT_TITANIUM = 12000, MAT_DIAMOND = 1000) //Base abductor engineering tools *8 + IMS cost
|
||||
construction_time = 120
|
||||
category = list("Cyborg Upgrade Modules")
|
||||
|
||||
/datum/design/borg_upgrade_lavaproof
|
||||
name = "Cyborg Upgrade (Lavaproof Chassis)"
|
||||
id = "borg_upgrade_lavaproof"
|
||||
|
||||
@@ -16,12 +16,14 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
/obj/item/gps/New()
|
||||
..()
|
||||
GLOB.GPS_list.Add(src)
|
||||
GLOB.poi_list.Add(src)
|
||||
if(name == "default gps") //use default naming scheme
|
||||
name = "global positioning system ([gpstag])"
|
||||
overlays += "working"
|
||||
|
||||
/obj/item/gps/Destroy()
|
||||
GLOB.GPS_list.Remove(src)
|
||||
GLOB.poi_list.Remove(src)
|
||||
return ..()
|
||||
|
||||
/obj/item/gps/emp_act(severity)
|
||||
|
||||
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 242 KiB |
|
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 162 KiB |
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 159 KiB |
|
Before Width: | Height: | Size: 505 KiB After Width: | Height: | Size: 507 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
@@ -1,25 +0,0 @@
|
||||
{{if data.detonating}}
|
||||
<div class="notice" style="color: #000000;">
|
||||
<h2 style="color: #000000;">CRYSTAL DELAMINATING</h2>
|
||||
<h3 style="color: #000000;">Evacuate area immediately</h3>
|
||||
<div class="clearBoth"></div>
|
||||
</div>
|
||||
{{else}}
|
||||
<h3>Crystal Integrity</h3>
|
||||
{{:helper.displayBar(data.integrity_percentage, 0, 100, (data.integrity_percentage >= 90) ? 'good' : (data.integrity_percentage >= 25) ? 'average' : 'bad')}}
|
||||
<b>{{:data.integrity_percentage}} %</b>
|
||||
<h3>Environment</h3>
|
||||
<span class="itemLabel">
|
||||
Temperature:
|
||||
</span>
|
||||
<span class="itemContent">
|
||||
{{:helper.displayBar(data.ambient_temp, 0, 10000, (data.ambient_temp >= 5000) ? 'bad' : (data.ambient_temp >= 4000) ? 'average' : 'good')}}
|
||||
{{:data.ambient_temp}} K
|
||||
</span>
|
||||
<span class="itemLabel">
|
||||
Pressure:
|
||||
</span>
|
||||
<span class="itemContent">
|
||||
{{:helper.smoothRound(data.ambient_pressure)}} kPa
|
||||
</span>
|
||||
{{/if}}
|
||||
@@ -575,6 +575,7 @@
|
||||
#include "code\game\gamemodes\miniantags\bot_swarm\swarmer.dm"
|
||||
#include "code\game\gamemodes\miniantags\bot_swarm\swarmer_event.dm"
|
||||
#include "code\game\gamemodes\miniantags\guardian\guardian.dm"
|
||||
#include "code\game\gamemodes\miniantags\guardian\host_actions.dm"
|
||||
#include "code\game\gamemodes\miniantags\guardian\types\assassin.dm"
|
||||
#include "code\game\gamemodes\miniantags\guardian\types\bomb.dm"
|
||||
#include "code\game\gamemodes\miniantags\guardian\types\charger.dm"
|
||||
|
||||
@@ -366,13 +366,13 @@ rules:
|
||||
## Enforce a maximum depth that blocks can be nested
|
||||
# max-depth: error
|
||||
## Enforce a maximum line length
|
||||
max-len: [error, {
|
||||
code: 80,
|
||||
#max-len: [error, {
|
||||
# code: 80,
|
||||
## Ignore imports
|
||||
ignorePattern: '^(import\s.+\sfrom\s|.*require\()',
|
||||
ignoreUrls: true,
|
||||
ignoreRegExpLiterals: true,
|
||||
}]
|
||||
#ignorePattern: '^(import\s.+\sfrom\s|.*require\()',
|
||||
#ignoreUrls: true,
|
||||
#ignoreRegExpLiterals: true,
|
||||
#}]
|
||||
## Enforce a maximum number of lines per file
|
||||
# max-lines: error
|
||||
## Enforce a maximum number of line of code in a function
|
||||
|
||||
@@ -221,7 +221,6 @@ export const Canister = (props, context) => {
|
||||
buttons={!!hasHoldingTank && (
|
||||
<Button
|
||||
icon="eject"
|
||||
color={valveOpen && 'danger'}
|
||||
content="Eject"
|
||||
onClick={() => act('eject')} />
|
||||
)}>
|
||||
|
||||