Component Traits. (#17665)

* Drippy component

* Converts disabilities to components.

* Makes weaver a component

* living

* Update vorestation.dme

* Update weaver.dm

* yeah tis

* no spawn

* yes

* signals hell yeah

* Teaching

* yeaaah

* makes gargoyle follow the law

* whoops

* return properly

* wah

* Update station.dm
This commit is contained in:
Cameron Lennox
2025-05-15 00:59:47 -07:00
committed by GitHub
parent adbc9063fb
commit 5d95b50db9
27 changed files with 646 additions and 342 deletions
@@ -0,0 +1,28 @@
/datum/component/coughing_disability
var/mob/living/owner
var/cough_chance = 5
/datum/component/coughing_disability/Initialize()
if (!isliving(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component))
/datum/component/coughing_disability/proc/process_component()
if (QDELETED(parent))
return
if(isbelly(owner.loc))
return
if(owner.stat != CONSCIOUS)
return
if(owner.transforming)
return
if((prob(cough_chance) && owner.paralysis <= 1))
owner.drop_item()
owner.emote("cough")
/datum/component/coughing_disability/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES)
owner = null
. = ..()
@@ -0,0 +1,32 @@
/datum/component/epilepsy_disability
var/mob/living/owner
/datum/component/epilepsy_disability/Initialize()
if (!isliving(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component))
/datum/component/epilepsy_disability/proc/process_component()
if (QDELETED(parent))
return
if(isbelly(owner.loc))
return
if(owner.stat != CONSCIOUS)
return
if(owner.transforming)
return
if((prob(1) && prob(1) && owner.paralysis < 1))
to_chat(owner, span_red("You have a seizure!"))
for(var/mob/O in viewers(owner, null))
if(O == owner)
continue
O.show_message(span_danger("[owner] starts having a seizure!"), 1)
owner.Paralyse(10)
owner.make_jittery(1000)
/datum/component/epilepsy_disability/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES)
owner = null
. = ..()
@@ -0,0 +1,40 @@
/datum/component/gibbing_disability
var/mob/living/owner
var/gutdeathpressure = 0
var/death_time = FALSE
dupe_mode = COMPONENT_DUPE_UNIQUE
/datum/component/gibbing_disability/Initialize()
if (!isliving(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component))
/datum/component/gibbing_disability/proc/process_component()
if(QDELETED(parent))
return
if(isbelly(owner.loc))
return
if(owner.transforming)
return
if(death_time)
if(death_time < 4)
owner.emote(pick("whimper","belch","shiver"))
death_time++
return
else
owner.emote(pick("belch"))
owner.gib()
return
gutdeathpressure += 0.01
if(gutdeathpressure > 0 && prob(gutdeathpressure))
owner.emote(pick("whimper","belch","belch","belch","choke","shiver"))
owner.Weaken(gutdeathpressure / 3)
if((gutdeathpressure/3) >= 1 && prob(gutdeathpressure/3))
death_time = TRUE
/datum/component/gibbing_disability/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES)
owner = null
. = ..()
@@ -0,0 +1,29 @@
/datum/component/nervousness_disability
var/mob/owner
var/gutdeathpressure = 0
/datum/component/nervousness_disability/Initialize()
if (!ishuman(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component))
/datum/component/nervousness_disability/proc/process_component()
if(QDELETED(parent))
return
if(isbelly(owner.loc))
return
if(owner.stat != CONSCIOUS)
return
if(owner.transforming)
return
if(prob(5) && prob(7))
owner.stuttering = max(15, owner.stuttering)
if(owner.jitteriness < 50)
owner.make_jittery(65)
/datum/component/nervousness_disability/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES)
owner = null
. = ..()
@@ -0,0 +1,41 @@
/datum/component/rotting_disability
var/mob/living/carbon/human/owner
/datum/component/rotting_disability/Initialize()
if (!ishuman(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component))
/datum/component/rotting_disability/proc/process_component()
if (QDELETED(parent))
return
if(isbelly(owner.loc))
return
if(owner.transforming)
return
if(prob(2) && prob(3)) // stacked percents for rarity
// random strange symptoms from organ/limb
owner.automatic_custom_emote(VISIBLE_MESSAGE, "flinches slightly.", check_stat = TRUE)
switch(rand(1,4))
if(1)
owner.adjustToxLoss(rand(2,8))
if(2)
owner.adjustCloneLoss(rand(1,2))
if(3)
owner.add_chemical_effect(CE_PAINKILLER, rand(8,28))
else
owner.adjustOxyLoss(rand(13,26))
// external organs need to fall off if damaged enough
var/obj/item/organ/O = pick(owner.organs)
if(O && !(O.organ_tag == BP_GROIN || O.organ_tag == BP_TORSO) && istype(O,/obj/item/organ/external))
var/obj/item/organ/external/E = O
if(O.damage >= O.min_broken_damage && O.robotic <= ORGAN_ASSISTED && prob(70))
owner.add_chemical_effect(CE_PAINKILLER, 120) // what limb? Extreme nerve damage. Can't feel a thing + shock
E.droplimb(TRUE, DROPLIMB_ACID)
/datum/component/rotting_disability/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES)
owner = null
. = ..()
@@ -0,0 +1,34 @@
/datum/component/tourettes_disability
var/mob/living/owner
var/gutdeathpressure = 0
/datum/component/tourettes_disability/Initialize()
if (!ishuman(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component))
/datum/component/tourettes_disability/proc/process_component()
if(QDELETED(parent))
return
if(isbelly(owner.loc))
return
if(owner.stat != CONSCIOUS)
return
if(owner.transforming)
return
if((prob(1) && prob(2) && owner.paralysis <= 1))
owner.Stun(10)
owner.make_jittery(100)
switch(rand(1, 3))
if(1)
owner.emote("twitch")
if(2 to 3)
owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]")
/datum/component/tourettes_disability/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES)
owner = null
. = ..()
@@ -0,0 +1,67 @@
//Some notes:
//How you APPLY a component: Call LoadComponent(/datum/component/template) on the thing you want to apply it to.
//How you CHECK a component: var/datum/component/template/comp = GetComponent(/datum/component/template)
//You can CHECK VARIABLES on a component and adjust them by doing the above and then doing something like: if(comp.energy < 50) comp.energy += 1
//How you GET RID of a component: Just qdel() it. It'll remove itself from the owner and then delete nicely.
//BIG NOTE: As the README.md notes: Using GetComponent is a crutch and should be avoided.
//Traits shouldn't NEED for external code to check for their components. It should be self-contained.
//However, for something more complex like xenochimera or shadekin, signals should be used...But we aren't at that point yet, so we're using GetComponent
/datum/component/template
//Insert variables here if you require them. Using energy and cooldown as examples.
var/energy = 100
var/cooldown
//Reference to our owner (the person that possesses us)
//This can be anything that is our owner that we want to reference. Swap out with mob/living/carbon/human/owner as needed.
var/mob/living/owner //easy reference
//dupe_mode = COMPONENT_DUPE_HIGHLANDER //Default mode. See flags.dm
/datum/component/template/Initialize()
if (!isliving(parent)) //When we get created, parent is 'whatever we are being applied to' This can be ANYTHING. For this trait, we're doing living only.
return COMPONENT_INCOMPATIBLE //If it's not a living mob, we tell the component 'We can't be applied to this' and don't get applied.
//We then get a reference to the thing we're applied to. In this case, a living mob.
owner = parent
add_verb(owner,/mob/living/proc/example_proc) //We can add verbs to our owner.
RegisterSignal(owner, COMSIG_EXAMPLE_SIGNAL, PROC_REF(example_proc)) //To put this easily: Owner is the person we're attached to, COMSIG_EXAMPLE_SIGNAL is the signal we expect them to send out when they want us to use our 'example_proc'
//Register this to a signal that is sent out whenever you want this to be called. For example: We want this trait to happen every life() tick, so we register it to the COMSIG_LIVING_LIFE signal that is sent every time life() is called on a /mob.
RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(process))
/datum/component/template/process()
if (QDELETED(parent))
return
energy = min(100, energy+1) //Add one energy per tick, up to 100
/datum/component/template/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_LIVING_LIFE) //IF we registered a signal, we need to unregister it.
UnregisterSignal(owner, COMSIG_EXAMPLE_SIGNAL) //MAKE SURE TO UNREGISTER YOUR SIGNALS. SERIOUSLY. OR THE SERVER WILL DIE.
owner = null //MAKE SURE TO CLEAR YOUR REFS!
. = ..()
/mob/living/proc/example_proc()
set name = "Example proc"
set category = "Abilities"
set desc = "See example."
SEND_SIGNAL(src, COMSIG_EXAMPLE_SIGNAL)
//This sends a signal to the world saying 'We did this thing!' This is then interpreed by the component and the component calls whatever proc it needs to.
/datum/component/template/proc/example_proc()
if (stat == DEAD)
return
if (energy <= 0) //Check a variable on the component.
to_chat(owner, span_danger("You currently have no energy!"))
else if (cooldown > world.time) //Check the cooldown variable on the component and compare it.
var/time_to_wait = (cooldown - world.time) / (1 SECONDS) //Simple cooldown
to_chat(owner, span_warning("You're currently on cooldown! Wait for another [round(time_to_wait,0.1)] seconds!"))
return
else
cooldown = world.time + 5 SECONDS //Set the component on a 5 second cooldown.
to_chat(owner, span_warning("You successfully used the example proc!"))
+67
View File
@@ -0,0 +1,67 @@
/datum/component/drippy
var/drip_chance = 5
var/blood_color = "#A10808"
var/mob/living/owner
/datum/component/drippy/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
if(ishuman(parent))
var/mob/living/carbon/human/temp_owner = parent
blood_color = rgb(temp_owner.r_skin,temp_owner.g_skin,temp_owner.b_skin)
RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(process_component))
/datum/component/drippy/proc/process_component()
if(QDELETED(parent))
return
if(!prob(drip_chance))
return
if(owner.stat == DEAD)
return
var/turf/T = get_turf(owner.loc)
if(!isturf(T))
return
var/obj/effect/decal/cleanable/blood/B
var/decal_type = /obj/effect/decal/cleanable/blood/splatter
// Are we dripping or splattering?
var/list/drips = list()
// Only a certain number of drips (or one large splatter) can be on a given turf.
for(var/obj/effect/decal/cleanable/blood/drip/drop in T)
drips |= drop.drips
qdel(drop)
if(drips.len < 4)
decal_type = /obj/effect/decal/cleanable/blood/drip
// Find a blood decal or create a new one.
B = locate(decal_type) in T
if(!B)
B = new decal_type(T)
var/obj/effect/decal/cleanable/blood/drip/drop = B
if(istype(drop) && drips && drips.len)
drop.add_overlay(drips)
drop.drips |= drips
B.basecolor = blood_color
B.update_icon()
if(istype(B, drop)) //We're a drop.
B.name = "drips of something"
else //We're a puddle.
B.name = "puddle of something"
B.desc = "It's thick and gooey. Perhaps it's the chef's cooking?"
B.dryname = "dried something"
B.drydesc = "It's dry and crusty. The janitor isn't doing their job."
B.fluorescent = 0
B.invisibility = INVISIBILITY_NONE
/datum/component/drippy/Destroy(force = FALSE)
owner = null
. = ..()
@@ -21,10 +21,13 @@
add_verb(gargoyle,/mob/living/carbon/human/proc/gargoyle_transformation)
add_verb(gargoyle,/mob/living/carbon/human/proc/gargoyle_pause)
add_verb(gargoyle,/mob/living/carbon/human/proc/gargoyle_checkenergy)
RegisterSignal(gargoyle, COMSIG_GARGOYLE_TRANSFORMATION, PROC_REF(gargoyle_transformation))
RegisterSignal(gargoyle, COMSIG_GARGOYLE_PAUSE, PROC_REF(gargoyle_pause))
RegisterSignal(gargoyle, COMSIG_GARGOYLE_CHECK_ENERGY, PROC_REF(gargoyle_checkenergy))
START_PROCESSING(SSprocessing, src)
RegisterSignal(gargoyle, COMSIG_LIVING_LIFE, PROC_REF(process_component))
/datum/component/gargoyle/process()
/datum/component/gargoyle/proc/process_component()
if (QDELETED(gargoyle))
return
if (paused && gargoyle.loc != paused_loc)
@@ -40,6 +43,15 @@
statue.damage(-0.5)
energy = min(energy+0.3, 100)
/datum/component/gargoyle/Destroy(force = FALSE)
UnregisterSignal(gargoyle, COMSIG_GARGOYLE_TRANSFORMATION)
UnregisterSignal(gargoyle, COMSIG_GARGOYLE_PAUSE)
UnregisterSignal(gargoyle, COMSIG_GARGOYLE_CHECK_ENERGY)
UnregisterSignal(gargoyle, COMSIG_LIVING_LIFE)
gargoyle = null
statue = null
. = ..()
/datum/component/gargoyle/proc/unpause()
if (!paused || transformed)
paused = FALSE
@@ -59,43 +71,44 @@
set name = "Gargoyle - Petrification"
set category = "Abilities.Gargoyle"
set desc = "Turn yourself into (or back from) being a gargoyle."
SEND_SIGNAL(src, COMSIG_GARGOYLE_TRANSFORMATION)
if (stat == DEAD)
/datum/component/gargoyle/proc/gargoyle_transformation()
if (gargoyle.stat == DEAD)
return
var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle)
if (comp)
if (comp.energy <= 0 && isturf(loc))
to_chat(src, span_danger("You suddenly turn into a [comp.identifier] as you run out of energy!"))
else if (comp.cooldown > world.time)
var/time_to_wait = (comp.cooldown - world.time) / (1 SECONDS)
to_chat(src, span_warning("You can't transform just yet again! Wait for another [round(time_to_wait,0.1)] seconds!"))
return
if (istype(loc, /obj/structure/gargoyle))
qdel(loc)
else if (isturf(loc))
new /obj/structure/gargoyle(loc, src)
if (energy <= 0 && isturf(gargoyle.loc))
to_chat(gargoyle, span_danger("You suddenly turn into a [identifier] as you run out of energy!"))
else if (cooldown > world.time)
var/time_to_wait = (cooldown - world.time) / (1 SECONDS)
to_chat(gargoyle, span_warning("You can't transform just yet again! Wait for another [round(time_to_wait,0.1)] seconds!"))
return
if (istype(gargoyle.loc, /obj/structure/gargoyle))
qdel(gargoyle.loc)
else if (isturf(gargoyle.loc))
new /obj/structure/gargoyle(gargoyle.loc, gargoyle)
/mob/living/carbon/human/proc/gargoyle_pause()
set name = "Gargoyle - Pause"
set category = "Abilities.Gargoyle"
set desc = "Pause your energy while standing still, so you don't use up any more, though you will lose a small amount upon moving again."
SEND_SIGNAL(src, COMSIG_GARGOYLE_PAUSE)
if (stat)
/datum/component/gargoyle/proc/gargoyle_pause()
if (gargoyle.stat)
return
var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle)
if (comp && !comp.transformed && !comp.paused)
comp.paused = TRUE
comp.paused_loc = loc
comp.RegisterSignal(src, COMSIG_ATOM_ENTERING, /datum/component/gargoyle/proc/unpause)
to_chat(src, span_notice("You start conserving your energy."))
if (!transformed && !paused)
paused = TRUE
paused_loc = gargoyle.loc
RegisterSignal(gargoyle, COMSIG_ATOM_ENTERING, /datum/component/gargoyle/proc/unpause)
to_chat(gargoyle, span_notice("You start conserving your energy."))
/mob/living/carbon/human/proc/gargoyle_checkenergy()
set name = "Gargoyle - Check Energy"
set category = "Abilities.Gargoyle"
set desc = "Check how much energy you have remaining as a gargoyle."
SEND_SIGNAL(src, COMSIG_GARGOYLE_CHECK_ENERGY)
var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle)
if (comp)
to_chat(src, span_notice("You have [round(comp.energy,0.01)] energy remaining. It is currently [comp.paused ? "stable" : (comp.transformed ? "increasing" : "decreasing")]."))
/datum/component/gargoyle/proc/gargoyle_checkenergy()
to_chat(gargoyle, span_notice("You have [round(energy,0.01)] energy remaining. It is currently [paused ? "stable" : (transformed ? "increasing" : "decreasing")]."))
+193
View File
@@ -0,0 +1,193 @@
/datum/component/weaver
var/silk_reserve = 100
var/silk_max_reserve = 500
var/silk_color = "#FFFFFF"
var/silk_production = FALSE
var/silk_generation_amount = 2
var/nutrtion_per_silk = 0.2
var/mob/living/owner
dupe_mode = COMPONENT_DUPE_UNIQUE
/datum/component/weaver/Initialize()
if (!isliving(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
add_verb(owner, /mob/living/proc/check_silk_amount)
add_verb(owner, /mob/living/proc/toggle_silk_production)
add_verb(owner, /mob/living/proc/weave_structure)
add_verb(owner, /mob/living/proc/weave_item)
add_verb(owner, /mob/living/proc/set_silk_color)
//Processing
RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(process_component))
//When procs are used
RegisterSignal(owner, COMSIG_CHECK_SILK_AMOUNT, PROC_REF(check_silk_amount))
RegisterSignal(owner, COMSIG_WEAVE_STRUCTURE, PROC_REF(weave_structure))
RegisterSignal(owner, COMSIG_TOGGLE_SILK_PRODUCTION, PROC_REF(weave_item))
RegisterSignal(owner, COMSIG_WEAVE_ITEM, PROC_REF(weave_item))
RegisterSignal(owner, COMSIG_SET_SILK_COLOR, PROC_REF(set_silk_color))
/datum/component/weaver/proc/process_component()
if (QDELETED(parent))
return
process_weaver_silk()
/datum/component/weaver/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_LIVING_LIFE) //IF we registered a signal, we need to unregister it.
UnregisterSignal(owner, COMSIG_CHECK_SILK_AMOUNT)
UnregisterSignal(owner, COMSIG_WEAVE_STRUCTURE)
UnregisterSignal(owner, COMSIG_TOGGLE_SILK_PRODUCTION)
UnregisterSignal(owner, COMSIG_WEAVE_ITEM)
UnregisterSignal(owner, COMSIG_SET_SILK_COLOR)
remove_verb(owner, /mob/living/proc/check_silk_amount)
remove_verb(owner, /mob/living/proc/toggle_silk_production)
remove_verb(owner, /mob/living/proc/weave_structure)
remove_verb(owner, /mob/living/proc/weave_item)
remove_verb(owner, /mob/living/proc/set_silk_color)
owner = null
. = ..()
/datum/component/weaver/proc/process_weaver_silk()
if(silk_reserve < silk_max_reserve && silk_production == TRUE && owner.nutrition > 100)
silk_reserve = min(silk_reserve + silk_generation_amount, silk_max_reserve)
owner.adjust_nutrition(-(nutrtion_per_silk*silk_generation_amount))
/mob/living/proc/check_silk_amount()
set name = "Check Silk Amount"
set category = "Abilities.Weaver"
SEND_SIGNAL(src, COMSIG_CHECK_SILK_AMOUNT)
/datum/component/weaver/proc/check_silk_amount()
to_chat(owner, "Your silk reserves are at [silk_reserve]/[silk_max_reserve].")
/mob/living/proc/toggle_silk_production()
set name = "Toggle Silk Production"
set category = "Abilities.Weaver"
SEND_SIGNAL(src, COMSIG_TOGGLE_SILK_PRODUCTION)
/datum/component/weaver/proc/toggle_silk_production()
silk_production = !(silk_production)
to_chat(owner, "You are [silk_production ? "now" : "no longer"] producing silk.")
/mob/living/proc/weave_structure()
set name = "Weave Structure"
set category = "Abilities.Weaver"
SEND_SIGNAL(src, COMSIG_WEAVE_STRUCTURE)
/datum/component/weaver/proc/weave_structure()
var/choice
var/datum/weaver_recipe/structure/desired_result
var/finalized = "No"
while(finalized == "No" && owner.client)
choice = tgui_input_list(owner,"What would you like to weave?", "Weave Choice", GLOB.weavable_structures)
desired_result = GLOB.weavable_structures[choice]
if(!desired_result || !istype(desired_result))
return
if(choice)
finalized = tgui_alert(owner, "Are you sure you want to weave [desired_result.title]? It will cost you [desired_result.cost] silk.","Confirmation",list("Yes","No"))
if(!desired_result || !istype(desired_result))
return
if(desired_result.cost > silk_reserve)
to_chat(owner, span_warning("You don't have enough silk to weave that!"))
return
if(owner.stat)
to_chat(owner, span_warning("You can't do that in your current state!"))
return
if(locate(desired_result.result_type) in owner.loc)
to_chat(owner, span_warning("You can't create another weaversilk [desired_result.title] here!"))
return
if(!isturf(owner.loc))
to_chat(owner, span_warning("You can't weave here!"))
return
if(do_after(owner, desired_result.time, exclusive = TASK_USER_EXCLUSIVE))
if(desired_result.cost > silk_reserve)
to_chat(owner, span_warning("You don't have enough silk to weave that!"))
return
if(locate(desired_result.result_type) in owner.loc)
to_chat(owner, span_warning("You can't create another weaversilk [desired_result.title] here!"))
return
if(!isturf(owner.loc))
to_chat(owner, span_warning("You can't weave here!"))
return
silk_reserve = max(silk_reserve - desired_result.cost, 0)
var/atom/O = new desired_result.result_type(owner.loc)
O.color = silk_color
/mob/living/proc/weave_item()
set name = "Weave Item"
set category = "Abilities.Weaver"
SEND_SIGNAL(src, COMSIG_WEAVE_ITEM)
/datum/component/weaver/proc/weave_item()
var/choice
var/datum/weaver_recipe/item/desired_result
var/finalized = "No"
while(finalized == "No" && owner.client)
choice = tgui_input_list(owner,"What would you like to weave?", "Weave Choice", GLOB.weavable_items)
desired_result = GLOB.weavable_items[choice]
if(!desired_result || !istype(desired_result))
return
if(choice)
finalized = tgui_alert(owner, "Are you sure you want to weave [desired_result.title]? It will cost you [desired_result.cost] silk.","Confirmation",list("Yes","No"))
if(!desired_result || !istype(desired_result))
return
if(desired_result.cost > silk_reserve)
to_chat(owner, span_warning("You don't have enough silk to weave that!"))
return
if(owner.stat)
to_chat(owner, span_warning("You can't do that in your current state!"))
return
if(!isturf(owner.loc))
to_chat(owner, span_warning("You can't weave here!"))
return
if(do_after(owner, desired_result.time, exclusive = TASK_USER_EXCLUSIVE))
if(desired_result.cost > silk_reserve)
to_chat(owner, span_warning("You don't have enough silk to weave that!"))
return
if(!isturf(owner.loc))
to_chat(owner, span_warning("You can't weave here!"))
return
silk_reserve = max(silk_reserve - desired_result.cost, 0)
var/atom/O = new desired_result.result_type(owner.loc)
O.color = silk_color
/mob/living/proc/set_silk_color()
set name = "Set Silk Color"
set category = "Abilities.Weaver"
SEND_SIGNAL(src, COMSIG_SET_SILK_COLOR)
/datum/component/weaver/proc/set_silk_color()
var/new_silk_color = tgui_color_picker(owner, "Pick a color for your woven products:","Silk Color", silk_color)
if(new_silk_color)
silk_color = new_silk_color