mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 01:34:01 +00:00
Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com> Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
1137 lines
36 KiB
Plaintext
1137 lines
36 KiB
Plaintext
#define RANDOM_GRAFFITI "Random Graffiti"
|
|
#define RANDOM_LETTER "Random Letter"
|
|
#define RANDOM_PUNCTUATION "Random Punctuation"
|
|
#define RANDOM_NUMBER "Random Number"
|
|
#define RANDOM_SYMBOL "Random Symbol"
|
|
#define RANDOM_DRAWING "Random Drawing"
|
|
#define RANDOM_ORIENTED "Random Oriented"
|
|
#define RANDOM_RUNE "Random Rune"
|
|
#define RANDOM_ANY "Random Anything"
|
|
|
|
#define PAINT_NORMAL 1
|
|
#define PAINT_LARGE_HORIZONTAL 2
|
|
#define PAINT_LARGE_HORIZONTAL_ICON 'icons/effects/96x32.dmi'
|
|
|
|
#define AVAILABLE_SPRAYCAN_SPACE 8 // enough to fill one radial menu page
|
|
|
|
#define DRAW_TIME 5 SECONDS
|
|
#define INFINITE_CHARGES -1
|
|
|
|
/*
|
|
* Crayons
|
|
*/
|
|
|
|
/obj/item/toy/crayon
|
|
name = "crayon"
|
|
desc = "A colourful crayon. Looks tasty. Mmmm..."
|
|
icon = 'icons/obj/art/crayons.dmi'
|
|
icon_state = "crayonred"
|
|
worn_icon_state = "crayon"
|
|
w_class = WEIGHT_CLASS_TINY
|
|
attack_verb_continuous = list("attacks", "colours")
|
|
attack_verb_simple = list("attack", "colour")
|
|
grind_results = list()
|
|
interaction_flags_atom = parent_type::interaction_flags_atom | INTERACT_ATOM_IGNORE_MOBILITY
|
|
|
|
/// Icon state to use when capped
|
|
var/icon_capped
|
|
/// Icon state to use when uncapped
|
|
var/icon_uncapped
|
|
/// If true, a coloured overlay is applied to display the currently selected colour
|
|
var/overlay_paint_colour = FALSE
|
|
|
|
/// Crayon overlay to use if placed into a crayon box
|
|
var/crayon_color = "red"
|
|
/// Current paint colour
|
|
var/paint_color = COLOR_RED
|
|
|
|
/// Contains chosen symbol to draw
|
|
var/drawtype
|
|
/// Stores buffer of text to draw, one character at a time
|
|
var/text_buffer = ""
|
|
|
|
/// Dictates how large of an area we cover with our paint
|
|
var/paint_mode = PAINT_NORMAL
|
|
|
|
/// Number of times this item can be used, INFINITE_CHARGES for unlimited
|
|
var/charges = 30
|
|
/// Number of remaining charges
|
|
var/charges_left
|
|
/// Multiplies effect of reagent when applied to mobs or surfaces
|
|
var/volume_multiplier = 1
|
|
/// If true, sprayed turfs should also have the internal chemical applied to them
|
|
var/expose_turfs = FALSE
|
|
/// If set to false, this just applies a chemical and cannot paint symbols
|
|
var/actually_paints = TRUE
|
|
|
|
/// If false a do_after is required to draw something, otherwise it applies immediately
|
|
var/instant = FALSE
|
|
/// If true, this deletes itself when empty
|
|
var/self_contained = TRUE
|
|
|
|
/// Whether or not you can eat this. Doesn't mean it is a good idea to eat it.
|
|
var/edible = TRUE
|
|
|
|
/// Reagents which are applied to things you use this on, or yourself if you eat it
|
|
var/list/reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5)
|
|
/// If the user can toggle the colour, a la vanilla spraycan
|
|
var/can_change_colour = FALSE
|
|
|
|
/// Whether this item has a cap that can be toggled on and off
|
|
var/has_cap = FALSE
|
|
/// Whether the cap is currently on or off
|
|
var/is_capped = FALSE
|
|
|
|
/// Whether to play a sound before using
|
|
var/pre_noise = FALSE
|
|
/// Whether to play a sound after using
|
|
var/post_noise = FALSE
|
|
|
|
/**
|
|
* List of selectable graffiti options
|
|
* If an associated value is present, the graffiti has its own cost
|
|
* otherwise it'll be the default value.
|
|
* Ditto with the other other lists below.
|
|
*/
|
|
var/static/list/graffiti = list(
|
|
"amyjon",
|
|
"antilizard",
|
|
"body",
|
|
"cyka",
|
|
"dwarf",
|
|
"end",
|
|
"engie",
|
|
"face",
|
|
"guy",
|
|
"matt",
|
|
"prolizard",
|
|
"revolution",
|
|
"star",
|
|
"uboa",
|
|
)
|
|
/// List of selectable symbol options
|
|
var/static/list/symbols = list(
|
|
"biohazard",
|
|
"credit",
|
|
"danger",
|
|
"electricdanger",
|
|
"firedanger", // These symbols left intentionally un-alphabetised as they should be next to each other in the menu
|
|
"evac",
|
|
"food",
|
|
"heart",
|
|
"like",
|
|
"med",
|
|
"nay",
|
|
"peace",
|
|
"radiation",
|
|
"safe",
|
|
"shop",
|
|
"skull",
|
|
"space",
|
|
"trade",
|
|
)
|
|
/// List of selectable drawing options
|
|
var/static/list/drawings = list(
|
|
"beepsky",
|
|
"blueprint",
|
|
"bottle",
|
|
"brush",
|
|
"carp",
|
|
"cat",
|
|
"clown",
|
|
"corgi",
|
|
"disk",
|
|
"fireaxe",
|
|
"ghost",
|
|
"largebrush",
|
|
"scroll",
|
|
"shotgun",
|
|
"smallbrush" = CRAYON_COST_SMALL,
|
|
"snake",
|
|
"splatter",
|
|
"stickman",
|
|
"taser",
|
|
"toilet",
|
|
"toolbox",
|
|
)
|
|
/// List of selectable orientable options
|
|
var/static/list/oriented = list(
|
|
"arrow" = CRAYON_COST_SMALL,
|
|
"body",
|
|
"chevron" = CRAYON_COST_SMALL,
|
|
"clawprint" = CRAYON_COST_SMALL,
|
|
"footprint" = CRAYON_COST_SMALL,
|
|
"line",
|
|
"pawprint" = CRAYON_COST_SMALL,
|
|
"shortline" = CRAYON_COST_SMALL,
|
|
"thinline",
|
|
)
|
|
/// List of selectable rune options
|
|
var/static/list/runes = list(
|
|
"rune1",
|
|
"rune2",
|
|
"rune3",
|
|
"rune4",
|
|
"rune5",
|
|
"rune6",
|
|
)
|
|
/// List of selectable random options
|
|
var/static/list/randoms = list(
|
|
RANDOM_ANY,
|
|
RANDOM_DRAWING,
|
|
RANDOM_GRAFFITI,
|
|
RANDOM_ORIENTED,
|
|
RANDOM_LETTER,
|
|
RANDOM_NUMBER,
|
|
RANDOM_PUNCTUATION,
|
|
RANDOM_RUNE,
|
|
RANDOM_SYMBOL,
|
|
)
|
|
/// List of selectable large options
|
|
var/static/list/graffiti_large_h = list(
|
|
"furrypride" = CRAYON_COST_LARGE,
|
|
"paint" = CRAYON_COST_LARGE,
|
|
"secborg" = CRAYON_COST_LARGE,
|
|
"yiffhell" = CRAYON_COST_LARGE,
|
|
)
|
|
/// Combined lists
|
|
var/static/list/all_drawables = graffiti + symbols + drawings + oriented + runes + graffiti_large_h
|
|
|
|
/obj/item/toy/crayon/proc/isValidSurface(surface)
|
|
return isfloorturf(surface)
|
|
|
|
/obj/item/toy/crayon/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] is jamming [src] up [user.p_their()] nose and into [user.p_their()] brain. It looks like [user.p_theyre()] trying to commit suicide!"))
|
|
user.add_atom_colour(color_transition_filter(paint_color, SATURATION_OVERRIDE), ADMIN_COLOUR_PRIORITY)
|
|
return (BRUTELOSS|OXYLOSS)
|
|
|
|
/obj/item/toy/crayon/Initialize(mapload)
|
|
. = ..()
|
|
|
|
dye_color = crayon_color
|
|
|
|
drawtype = pick(all_drawables)
|
|
|
|
AddElement(/datum/element/venue_price, FOOD_PRICE_EXOTIC)
|
|
if(can_change_colour)
|
|
AddComponent(/datum/component/palette, AVAILABLE_SPRAYCAN_SPACE, paint_color)
|
|
|
|
refill()
|
|
if(edible)
|
|
AddComponentFrom(
|
|
SOURCE_EDIBLE_INNATE, \
|
|
/datum/component/edible, \
|
|
bite_consumption = reagents.total_volume / (charges_left / 5), \
|
|
after_eat = CALLBACK(src, PROC_REF(after_eat)), \
|
|
)
|
|
|
|
/// Used for edible component to reduce charges_left on bite.
|
|
/obj/item/toy/crayon/proc/after_eat(mob/user)
|
|
use_charges(user, amount = 5, requires_full = FALSE, override_infinity = TRUE)
|
|
if(check_empty(user, override_infinity = TRUE)) //Prevents division by zero
|
|
return
|
|
|
|
/// Sets painting color and updates appearance.
|
|
/obj/item/toy/crayon/set_painting_tool_color(chosen_color)
|
|
. = ..()
|
|
paint_color = chosen_color
|
|
update_appearance()
|
|
|
|
/**
|
|
* Refills charges_left in infinite crayons on use.
|
|
* Sets charges_left in infinite crayons to 100 for spawning reagents.
|
|
* Spawns reagents in crayons based on the amount of charges_left if not spawned yet.
|
|
*/
|
|
/obj/item/toy/crayon/proc/refill()
|
|
if(charges == INFINITE_CHARGES)
|
|
charges_left = 100
|
|
else
|
|
charges_left = charges
|
|
|
|
if(!reagents)
|
|
create_reagents(charges_left * volume_multiplier)
|
|
reagents.clear_reagents()
|
|
|
|
var/total_weight = 0
|
|
for(var/key in reagent_contents)
|
|
total_weight += reagent_contents[key]
|
|
|
|
var/units_per_weight = reagents.maximum_volume / total_weight
|
|
for(var/reagent in reagent_contents)
|
|
var/weight = reagent_contents[reagent]
|
|
var/amount = weight * units_per_weight
|
|
reagents.add_reagent(reagent, amount)
|
|
|
|
/**
|
|
* Returns number of charges actually used.
|
|
*
|
|
* Arguments:
|
|
* * user - the user.
|
|
* * amount - how much charges do we reduce.
|
|
* * requires_full - Seems to transfer its data to the same argument on check_empty(). I'm not sure tho.
|
|
* * override_infinity - if TRUE stops infinite crayons from refilling.
|
|
*/
|
|
/obj/item/toy/crayon/proc/use_charges(mob/user, amount = 1, requires_full = TRUE, override_infinity = FALSE)
|
|
if(charges == INFINITE_CHARGES && !override_infinity)
|
|
refill()
|
|
return TRUE
|
|
if(check_empty(user, amount, requires_full))
|
|
return FALSE
|
|
charges_left -= min(charges_left, amount)
|
|
return TRUE
|
|
|
|
/**
|
|
* When eating a crayon, check_empty() can be called twice producing two messages unless we check for being deleted first.
|
|
*
|
|
* Arguments:
|
|
* * user - the user.
|
|
* * amount - used for use_on() and when requires_full is TRUE
|
|
* * requires_full - if TRUE and charges_left < amount it will balloon_alert you. Used just for borgs spraycan it seems.
|
|
* * override_infinity - if TRUE it will override checks for infinite crayons.
|
|
*/
|
|
/obj/item/toy/crayon/proc/check_empty(mob/user, amount = 1, requires_full = TRUE, override_infinity = FALSE)
|
|
if(QDELETED(src))
|
|
return TRUE
|
|
|
|
// INFINITE_CHARGES is unlimited charges
|
|
if(charges == INFINITE_CHARGES && !override_infinity)
|
|
return FALSE
|
|
if(!charges_left)
|
|
if(self_contained)
|
|
qdel(src)
|
|
else
|
|
balloon_alert(user, "empty!")
|
|
return TRUE
|
|
if(charges_left < amount && requires_full)
|
|
balloon_alert(user, "not enough left!")
|
|
return TRUE
|
|
|
|
return FALSE
|
|
|
|
/obj/item/toy/crayon/ui_state(mob/user)
|
|
return GLOB.hands_state
|
|
|
|
/obj/item/toy/crayon/ui_interact(mob/user, datum/tgui/ui)
|
|
if (!actually_paints)
|
|
return
|
|
// tgui is a plague upon this codebase
|
|
// no u
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "Crayon", name)
|
|
ui.open()
|
|
|
|
/obj/item/toy/crayon/proc/staticDrawables(is_literate_user)
|
|
. = list()
|
|
|
|
var/list/g_items = list()
|
|
. += list(list("name" = "Graffiti", "items" = g_items))
|
|
for(var/g in graffiti)
|
|
g_items += list(list("item" = g))
|
|
|
|
var/list/glh_items = list()
|
|
. += list(list("name" = "Graffiti Large Horizontal", "items" = glh_items))
|
|
for(var/glh in graffiti_large_h)
|
|
glh_items += list(list("item" = glh))
|
|
|
|
var/list/S_items = list()
|
|
. += list(list("name" = "Symbols", "items" = S_items))
|
|
for(var/S in symbols)
|
|
S_items += list(list("item" = S))
|
|
|
|
var/list/D_items = list()
|
|
. += list(list("name" = "Drawings", "items" = D_items))
|
|
for(var/D in drawings)
|
|
D_items += list(list("item" = D))
|
|
|
|
var/list/O_items = list()
|
|
. += list(list(name = "Oriented", "items" = O_items))
|
|
for(var/O in oriented)
|
|
O_items += list(list("item" = O))
|
|
|
|
var/list/R_items = list()
|
|
. += list(list(name = "Runes", "items" = R_items))
|
|
for(var/R in runes)
|
|
R_items += list(list("item" = R))
|
|
|
|
var/list/rand_items = list()
|
|
. += list(list(name = "Random", "items" = rand_items))
|
|
for(var/i in randoms)
|
|
if(!is_literate_user) // no spelling allowed
|
|
if(i == RANDOM_LETTER || i == RANDOM_NUMBER || i == RANDOM_PUNCTUATION)
|
|
continue
|
|
rand_items += list(list("item" = i))
|
|
|
|
/obj/item/toy/crayon/ui_data(mob/user)
|
|
var/list/crayon_drawables
|
|
var/is_literate_user = user.is_literate()
|
|
|
|
if(!crayon_drawables)
|
|
crayon_drawables = staticDrawables(is_literate_user)
|
|
|
|
. = list()
|
|
.["drawables"] = crayon_drawables
|
|
.["selected_stencil"] = drawtype
|
|
.["text_buffer"] = text_buffer
|
|
.["is_literate_user"] = is_literate_user
|
|
.["has_cap"] = has_cap
|
|
.["is_capped"] = is_capped
|
|
.["can_change_colour"] = can_change_colour
|
|
.["selected_color"] = GLOB.pipe_color_name[paint_color] || paint_color
|
|
.["paint_colors"] = GLOB.pipe_paint_colors
|
|
|
|
/obj/item/toy/crayon/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
switch(action)
|
|
if("toggle_cap")
|
|
if(has_cap)
|
|
is_capped = !is_capped
|
|
. = TRUE
|
|
if("select_stencil")
|
|
var/stencil = params["item"]
|
|
if(stencil in (all_drawables + randoms))
|
|
drawtype = stencil
|
|
. = TRUE
|
|
text_buffer = ""
|
|
if(stencil in graffiti_large_h)
|
|
paint_mode = PAINT_LARGE_HORIZONTAL
|
|
text_buffer = ""
|
|
else
|
|
paint_mode = PAINT_NORMAL
|
|
if("custom_color")
|
|
. = can_change_colour && pick_painting_tool_color(usr, paint_color)
|
|
if("color")
|
|
if(!can_change_colour)
|
|
return
|
|
paint_color = GLOB.pipe_paint_colors[params["paint_color"]]
|
|
set_painting_tool_color(paint_color)
|
|
. = TRUE
|
|
if("enter_text")
|
|
var/txt = tgui_input_text(usr, "Choose what to write", "Scribbles", text_buffer, max_length = MAX_MESSAGE_LEN)
|
|
if(isnull(txt))
|
|
return
|
|
txt = crayon_text_strip(txt)
|
|
if(text_buffer == txt)
|
|
return // No valid changes.
|
|
text_buffer = txt
|
|
|
|
. = TRUE
|
|
paint_mode = PAINT_NORMAL
|
|
drawtype = "a"
|
|
update_appearance()
|
|
|
|
/obj/item/toy/crayon/proc/crayon_text_strip(text)
|
|
text = copytext(text, 1, MAX_MESSAGE_LEN)
|
|
var/static/regex/crayon_regex = new /regex(@"[^\w!?,.=&%#+/\-]", "ig")
|
|
return LOWER_TEXT(crayon_regex.Replace(text, ""))
|
|
|
|
/// Is this a valid object for use_on to run on?
|
|
/obj/item/toy/crayon/proc/can_use_on(atom/target, mob/user, list/modifiers)
|
|
if(!isturf(target) && !istype(target, /obj/effect/decal/cleanable))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/// Attempts to color the target.
|
|
/obj/item/toy/crayon/proc/use_on(atom/target, mob/user, list/modifiers)
|
|
var/static/list/punctuation = list("!","?",".",",","/","+","-","=","%","#","&")
|
|
|
|
if(istype(target, /obj/effect/decal/cleanable))
|
|
target = target.loc
|
|
|
|
if(!isValidSurface(target))
|
|
target.balloon_alert(user, "can't use there!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
var/drawing = drawtype
|
|
switch(drawtype)
|
|
if(RANDOM_LETTER)
|
|
drawing = ascii2text(rand(97, 122)) // a-z
|
|
if(RANDOM_PUNCTUATION)
|
|
drawing = pick(punctuation)
|
|
if(RANDOM_SYMBOL)
|
|
drawing = pick(symbols)
|
|
if(RANDOM_DRAWING)
|
|
drawing = pick(drawings)
|
|
if(RANDOM_GRAFFITI)
|
|
drawing = pick(graffiti)
|
|
if(RANDOM_RUNE)
|
|
drawing = pick(runes)
|
|
if(RANDOM_ORIENTED)
|
|
drawing = pick(oriented)
|
|
if(RANDOM_NUMBER)
|
|
drawing = ascii2text(rand(48, 57)) // 0-9
|
|
if(RANDOM_ANY)
|
|
drawing = pick(all_drawables)
|
|
|
|
if(drawing in graffiti_large_h)
|
|
paint_mode = PAINT_LARGE_HORIZONTAL
|
|
text_buffer = ""
|
|
else
|
|
paint_mode = PAINT_NORMAL
|
|
|
|
var/istagger = HAS_TRAIT(user, TRAIT_TAGGER)
|
|
var/cost = all_drawables[drawing] || CRAYON_COST_DEFAULT
|
|
if(istype(target, /obj/item/canvas))
|
|
cost = 0
|
|
if (istagger)
|
|
cost *= 0.5
|
|
if(check_empty(user, cost))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
var/temp = "rune"
|
|
var/ascii = (length(drawing) == 1)
|
|
if(ascii && is_lowercase_character(drawing))
|
|
temp = "letter"
|
|
else if(ascii && is_digit(drawing))
|
|
temp = "number"
|
|
else if(drawing in punctuation)
|
|
temp = "punctuation mark"
|
|
else if(drawing in symbols)
|
|
temp = "symbol"
|
|
else if(drawing in drawings)
|
|
temp = "drawing"
|
|
else if(drawing in (graffiti|oriented))
|
|
temp = "graffiti"
|
|
|
|
var/graf_rot
|
|
if(drawing in oriented)
|
|
switch(user.dir)
|
|
if(EAST)
|
|
graf_rot = 90
|
|
if(SOUTH)
|
|
graf_rot = 180
|
|
if(WEST)
|
|
graf_rot = 270
|
|
else
|
|
graf_rot = 0
|
|
|
|
var/clickx
|
|
var/clicky
|
|
|
|
if(LAZYACCESS(modifiers, ICON_X) && LAZYACCESS(modifiers, ICON_Y))
|
|
clickx = clamp(text2num(LAZYACCESS(modifiers, ICON_X)) - 16, -(ICON_SIZE_X/2), ICON_SIZE_X/2)
|
|
clicky = clamp(text2num(LAZYACCESS(modifiers, ICON_Y)) - 16, -(ICON_SIZE_Y/2), ICON_SIZE_Y/2)
|
|
|
|
if(!instant)
|
|
to_chat(user, span_notice("You start drawing a [temp] on \the [target]..."))
|
|
|
|
if(pre_noise)
|
|
audible_message(span_notice("You hear spraying."))
|
|
playsound(user.loc, 'sound/effects/spray.ogg', 5, TRUE, 5)
|
|
|
|
var/wait_time = DRAW_TIME
|
|
if(paint_mode == PAINT_LARGE_HORIZONTAL)
|
|
wait_time *= 3
|
|
if(istagger)
|
|
wait_time *= 0.5
|
|
|
|
if(!instant && !do_after(user, wait_time, target = target, max_interact_count = 4))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
if(!use_charges(user, cost))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
if(length(text_buffer))
|
|
drawing = text_buffer[1]
|
|
|
|
|
|
var/list/turf/affected_turfs = list(target)
|
|
|
|
if(actually_paints)
|
|
var/obj/effect/decal/cleanable/crayon/created_art
|
|
switch(paint_mode)
|
|
if(PAINT_NORMAL)
|
|
created_art = new(target, paint_color, drawing, temp, graf_rot)
|
|
created_art.pixel_x = clickx
|
|
created_art.pixel_y = clicky
|
|
if(PAINT_LARGE_HORIZONTAL)
|
|
var/turf/left = locate(target.x-1,target.y,target.z)
|
|
var/turf/right = locate(target.x+1,target.y,target.z)
|
|
if(isValidSurface(left) && isValidSurface(right))
|
|
created_art = new(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON)
|
|
affected_turfs += left
|
|
affected_turfs += right
|
|
else
|
|
balloon_alert(user, "no room!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
created_art.add_hiddenprint(user)
|
|
if(istagger)
|
|
created_art.AddElement(/datum/element/art, GOOD_ART)
|
|
else
|
|
created_art.AddElement(/datum/element/art, BAD_ART)
|
|
|
|
if(!instant)
|
|
to_chat(user, span_notice("You finish drawing \the [temp]."))
|
|
else
|
|
to_chat(user, span_notice("You spray a [temp] on \the [target.name]"))
|
|
|
|
if(length(text_buffer) > 1)
|
|
text_buffer = copytext(text_buffer, length(text_buffer[1]) + 1)
|
|
SStgui.update_uis(src)
|
|
|
|
if(post_noise)
|
|
audible_message(span_hear("You hear spraying."))
|
|
playsound(user.loc, 'sound/effects/spray.ogg', 5, TRUE, 5)
|
|
|
|
var/fraction = min(1, . / reagents.maximum_volume)
|
|
if(affected_turfs.len)
|
|
fraction /= affected_turfs.len
|
|
if (expose_turfs)
|
|
for(var/turf/draw_turf as anything in affected_turfs)
|
|
reagents.expose(draw_turf, methods = TOUCH, volume_modifier = volume_multiplier)
|
|
check_empty(user)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/item/toy/crayon/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
|
if (!check_allowed_items(interacting_with))
|
|
return NONE
|
|
|
|
if(can_use_on(interacting_with, user, modifiers))
|
|
return use_on(interacting_with, user, modifiers)
|
|
return NONE
|
|
|
|
/obj/item/toy/crayon/get_writing_implement_details()
|
|
return list(
|
|
interaction_mode = MODE_WRITING,
|
|
font = CRAYON_FONT,
|
|
color = paint_color,
|
|
use_bold = TRUE,
|
|
)
|
|
|
|
/obj/item/toy/crayon/red
|
|
name = "red crayon"
|
|
icon_state = "crayonred"
|
|
paint_color = COLOR_CRAYON_RED
|
|
crayon_color = "red"
|
|
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5, /datum/reagent/colorful_reagent/powder/red/crayon = 1.5)
|
|
dye_color = DYE_RED
|
|
|
|
/obj/item/toy/crayon/orange
|
|
name = "orange crayon"
|
|
icon_state = "crayonorange"
|
|
paint_color = COLOR_CRAYON_ORANGE
|
|
crayon_color = "orange"
|
|
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5, /datum/reagent/colorful_reagent/powder/orange/crayon = 1.5)
|
|
dye_color = DYE_ORANGE
|
|
|
|
/obj/item/toy/crayon/yellow
|
|
name = "yellow crayon"
|
|
icon_state = "crayonyellow"
|
|
paint_color = COLOR_CRAYON_YELLOW
|
|
crayon_color = "yellow"
|
|
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5, /datum/reagent/colorful_reagent/powder/yellow/crayon = 1.5)
|
|
dye_color = DYE_YELLOW
|
|
|
|
/obj/item/toy/crayon/green
|
|
name = "green crayon"
|
|
icon_state = "crayongreen"
|
|
paint_color = COLOR_CRAYON_GREEN
|
|
crayon_color = "green"
|
|
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5, /datum/reagent/colorful_reagent/powder/green/crayon = 1.5)
|
|
dye_color = DYE_GREEN
|
|
|
|
/obj/item/toy/crayon/blue
|
|
name = "blue crayon"
|
|
icon_state = "crayonblue"
|
|
paint_color = COLOR_CRAYON_BLUE
|
|
crayon_color = "blue"
|
|
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5, /datum/reagent/colorful_reagent/powder/blue/crayon = 1.5)
|
|
dye_color = DYE_BLUE
|
|
|
|
/obj/item/toy/crayon/purple
|
|
name = "purple crayon"
|
|
icon_state = "crayonpurple"
|
|
paint_color = COLOR_CRAYON_PURPLE
|
|
crayon_color = "purple"
|
|
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5, /datum/reagent/colorful_reagent/powder/purple/crayon = 1.5)
|
|
dye_color = DYE_PURPLE
|
|
|
|
/obj/item/toy/crayon/black
|
|
name = "black crayon"
|
|
icon_state = "crayonblack"
|
|
paint_color = COLOR_CRAYON_BLACK
|
|
crayon_color = "black"
|
|
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5, /datum/reagent/colorful_reagent/powder/black/crayon = 1.5)
|
|
dye_color = DYE_BLACK
|
|
|
|
/obj/item/toy/crayon/white
|
|
name = "stick of chalk"
|
|
desc = "A stark-white stick of chalk."
|
|
icon_state = "crayonwhite"
|
|
paint_color = COLOR_WHITE
|
|
crayon_color = "white"
|
|
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5, /datum/reagent/colorful_reagent/powder/white/crayon = 1.5)
|
|
dye_color = DYE_WHITE
|
|
|
|
/obj/item/toy/crayon/white/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
|
/// Wherein, we draw a chalk body outline vaguely around the dead or "dead" mob
|
|
if(!ishuman(interacting_with) || user.combat_mode)
|
|
return ..()
|
|
|
|
var/mob/living/carbon/human/pwned_human = interacting_with
|
|
|
|
if(!(pwned_human.stat == DEAD || HAS_TRAIT(pwned_human, TRAIT_FAKEDEATH)))
|
|
balloon_alert_to_viewers("FEEDING TIME")
|
|
return ..()
|
|
|
|
balloon_alert_to_viewers("drawing outline...")
|
|
if(!do_after(user, DRAW_TIME, target = pwned_human, max_interact_count = 4))
|
|
return NONE
|
|
if(!use_charges(user, 1))
|
|
return NONE
|
|
|
|
var/decal_rotation = GET_LYING_ANGLE(pwned_human) - 90
|
|
var/obj/effect/decal/cleanable/crayon/chalk_line = new(get_turf(pwned_human), paint_color, "body", "chalk outline", decal_rotation, null, "A vaguely [pwned_human] shaped outline of a body.")
|
|
to_chat(user, span_notice("You draw a chalk outline around [pwned_human]."))
|
|
chalk_line.pixel_y = (pwned_human.pixel_y + pwned_human.pixel_z) + rand(-2, 2)
|
|
chalk_line.pixel_x = (pwned_human.pixel_x + pwned_human.pixel_w) + rand(-1, 1)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/item/toy/crayon/mime
|
|
name = "mime crayon"
|
|
icon_state = "crayonmime"
|
|
desc = "A very sad-looking crayon."
|
|
paint_color = COLOR_WHITE
|
|
crayon_color = "mime"
|
|
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5, /datum/reagent/colorful_reagent/powder/invisible = 1.5)
|
|
charges = INFINITE_CHARGES
|
|
dye_color = DYE_MIME
|
|
|
|
/obj/item/toy/crayon/rainbow
|
|
name = "rainbow crayon"
|
|
icon_state = "crayonrainbow"
|
|
paint_color = COLOR_CRAYON_RAINBOW
|
|
crayon_color = "rainbow"
|
|
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.5, /datum/reagent/colorful_reagent = 1.5)
|
|
drawtype = RANDOM_ANY // just the default starter.
|
|
charges = INFINITE_CHARGES
|
|
dye_color = DYE_RAINBOW
|
|
|
|
/obj/item/toy/crayon/rainbow/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
|
set_painting_tool_color(rgb(rand(0,255), rand(0,255), rand(0,255)))
|
|
return ..()
|
|
|
|
/*
|
|
* Crayon Box
|
|
*/
|
|
|
|
/obj/item/storage/crayons
|
|
name = "box of crayons"
|
|
desc = "A box of crayons for all your rune drawing needs."
|
|
icon = 'icons/obj/art/crayons.dmi'
|
|
icon_state = "crayonbox"
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
custom_materials = list(/datum/material/cardboard = SHEET_MATERIAL_AMOUNT)
|
|
storage_type = /datum/storage/crayons
|
|
|
|
/obj/item/storage/crayons/PopulateContents()
|
|
new /obj/item/toy/crayon/red(src)
|
|
new /obj/item/toy/crayon/orange(src)
|
|
new /obj/item/toy/crayon/yellow(src)
|
|
new /obj/item/toy/crayon/green(src)
|
|
new /obj/item/toy/crayon/blue(src)
|
|
new /obj/item/toy/crayon/purple(src)
|
|
new /obj/item/toy/crayon/black(src)
|
|
update_appearance()
|
|
|
|
/obj/item/storage/crayons/update_overlays()
|
|
. = ..()
|
|
for(var/obj/item/toy/crayon/crayon in contents)
|
|
. += mutable_appearance('icons/obj/art/crayons.dmi', crayon.crayon_color)
|
|
|
|
/obj/item/storage/crayons/attack_self(mob/user)
|
|
. = ..()
|
|
if(contents.len > 0)
|
|
balloon_alert(user, "too full to fold!")
|
|
return
|
|
if(flags_1 & HOLOGRAM_1)
|
|
return
|
|
|
|
var/obj/item/stack/sheet/cardboard/cardboard = new /obj/item/stack/sheet/cardboard(user.drop_location())
|
|
to_chat(user, span_notice("You fold the [src] into cardboard."))
|
|
user.put_in_active_hand(cardboard)
|
|
qdel(src)
|
|
|
|
//Spraycan stuff
|
|
|
|
/obj/item/toy/crayon/spraycan
|
|
name = "spray can"
|
|
icon_state = "spraycan"
|
|
worn_icon_state = "spraycan"
|
|
|
|
icon_capped = "spraycan_cap"
|
|
icon_uncapped = "spraycan"
|
|
overlay_paint_colour = TRUE
|
|
paint_color = null
|
|
|
|
inhand_icon_state = "spraycan"
|
|
lefthand_file = 'icons/mob/inhands/equipment/hydroponics_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi'
|
|
desc = "A metallic container containing tasty paint."
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
custom_price = PAYCHECK_CREW * 2.5
|
|
|
|
instant = TRUE
|
|
edible = FALSE
|
|
has_cap = TRUE
|
|
is_capped = TRUE
|
|
self_contained = FALSE // Don't disappear when they're empty
|
|
can_change_colour = TRUE
|
|
|
|
reagent_contents = list(/datum/reagent/fuel = 1, /datum/reagent/consumable/ethanol = 1)
|
|
|
|
pre_noise = TRUE
|
|
post_noise = FALSE
|
|
interaction_flags_click = NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING
|
|
|
|
/// Types which use their color var for additional logic, so we need to avoid using transition filters on them.
|
|
var/static/list/direct_color_types = typecacheof(list(
|
|
/obj/item/paper, // Uses color for TGUI backgrounds, doesn't look very good either
|
|
/obj/item/fish, // Used for aquarium sprites
|
|
/obj/structure/window, // Does not play nice with window tint
|
|
))
|
|
|
|
/obj/item/toy/crayon/spraycan/Initialize(mapload)
|
|
. = ..()
|
|
var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/improvised_coolant)
|
|
|
|
AddElement(
|
|
/datum/element/slapcrafting,\
|
|
slapcraft_recipes = slapcraft_recipe_list,\
|
|
)
|
|
register_context()
|
|
register_item_context()
|
|
|
|
/obj/item/toy/crayon/spraycan/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
|
|
. = ..()
|
|
|
|
if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS|SILENT_ADJACENCY))
|
|
return .
|
|
|
|
if(has_cap)
|
|
context[SCREENTIP_CONTEXT_ALT_LMB] = "Toggle cap"
|
|
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/obj/item/toy/crayon/spraycan/add_item_context(datum/source, list/context, atom/target, mob/living/user)
|
|
. = ..()
|
|
|
|
if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS|SILENT_ADJACENCY))
|
|
return .
|
|
|
|
context[SCREENTIP_CONTEXT_LMB] = "Paint"
|
|
context[SCREENTIP_CONTEXT_RMB] = "Coat with paint"
|
|
|
|
if(isbodypart(target))
|
|
var/obj/item/bodypart/limb = target
|
|
if(IS_ROBOTIC_LIMB(limb))
|
|
context[SCREENTIP_CONTEXT_LMB] = "Restyle robotic limb"
|
|
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/obj/item/toy/crayon/spraycan/isValidSurface(surface)
|
|
return (isfloorturf(surface) || iswallturf(surface))
|
|
|
|
/obj/item/toy/crayon/spraycan/suicide_act(mob/living/user)
|
|
var/used = min(charges_left, 10)
|
|
if(is_capped || !actually_paints || !use_charges(user, 10, FALSE))
|
|
user.visible_message(span_suicide("[user] shakes up [src] with a rattle and lifts it to [user.p_their()] mouth, but nothing happens!"))
|
|
user.say("MEDIOCRE!!", forced = "spraycan suicide")
|
|
return SHAME
|
|
|
|
user.visible_message(span_suicide("[user] shakes up [src] with a rattle and lifts it to [user.p_their()] mouth, spraying paint across [user.p_their()] teeth!"))
|
|
user.say("WITNESS ME!!", forced = "spraycan suicide")
|
|
if(pre_noise || post_noise)
|
|
playsound(src, 'sound/effects/spray.ogg', 5, TRUE, 5)
|
|
if(can_change_colour)
|
|
set_painting_tool_color(COLOR_SILVER)
|
|
update_appearance()
|
|
if(actually_paints)
|
|
user.AddComponent(/datum/component/face_decal, "spray", EXTERNAL_ADJACENT, paint_color)
|
|
reagents.trans_to(user, used, volume_multiplier, transferred_by = user, methods = VAPOR)
|
|
return OXYLOSS
|
|
|
|
/obj/item/toy/crayon/spraycan/Initialize(mapload)
|
|
. = ..()
|
|
// If default crayon red colour, pick a more fun spraycan colour
|
|
if(!paint_color)
|
|
set_painting_tool_color(pick(COLOR_CRAYON_RED, COLOR_CRAYON_ORANGE, COLOR_CRAYON_YELLOW, COLOR_CRAYON_GREEN, COLOR_CRAYON_BLUE, COLOR_CRAYON_PURPLE))
|
|
refill()
|
|
|
|
/obj/item/toy/crayon/spraycan/examine(mob/user)
|
|
. = ..()
|
|
if(charges != INFINITE_CHARGES)
|
|
if(charges_left)
|
|
. += "It's roughly [PERCENT(charges_left/charges)]% full."
|
|
else
|
|
. += "It is empty."
|
|
. += span_notice("Alt-click [src] to [ is_capped ? "take the cap off" : "put the cap on"].")
|
|
|
|
|
|
/obj/item/toy/crayon/spraycan/can_use_on(atom/target, mob/user, list/modifiers)
|
|
if(iscarbon(target))
|
|
return TRUE
|
|
if(is_capped && HAS_TRAIT(target, TRAIT_COMBAT_MODE_SKIP_INTERACTION))
|
|
// specifically don't try to use a capped spraycan on stuff like bags and tables, just place it
|
|
return FALSE
|
|
if(ismob(target) && HAS_TRAIT(target, TRAIT_SPRAY_PAINTABLE))
|
|
return TRUE
|
|
if(isobj(target) && !(target.flags_1 & UNPAINTABLE_1))
|
|
return TRUE
|
|
return ..()
|
|
|
|
/obj/item/toy/crayon/spraycan/use_on(atom/target, mob/user, list/modifiers)
|
|
if(is_capped)
|
|
balloon_alert(user, "take the cap off first!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
if(check_empty(user))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
if (isbodypart(target))
|
|
if (color_limb(target, user))
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
if(iscarbon(target))
|
|
if(pre_noise || post_noise)
|
|
playsound(user.loc, 'sound/effects/spray.ogg', 25, TRUE, 5)
|
|
|
|
if(SEND_SIGNAL(target, COMSIG_CARBON_SPRAYPAINTED, user, src))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
var/mob/living/carbon/carbon_target = target
|
|
user.visible_message(span_danger("[user] sprays [src] into the face of [target]!"))
|
|
to_chat(target, span_userdanger("[user] sprays [src] into your face!"))
|
|
|
|
if(carbon_target.client)
|
|
carbon_target.set_eye_blur_if_lower(6 SECONDS)
|
|
carbon_target.adjust_temp_blindness(2 SECONDS)
|
|
if(carbon_target.get_eye_protection() <= 0 || carbon_target.is_eyes_covered()) // no eye protection? ARGH IT BURNS. Warning: don't add a stun here. It's a roundstart item with some quirks. added redundancy because gas masks don't give you eye protection
|
|
carbon_target.adjust_jitter(1 SECONDS)
|
|
carbon_target.adjust_eye_blur(0.5 SECONDS)
|
|
flash_color(carbon_target, flash_color=paint_color, flash_time=40)
|
|
if(ishuman(carbon_target) && actually_paints)
|
|
var/mob/living/carbon/human/human_target = carbon_target
|
|
human_target.AddComponent(/datum/component/face_decal, "spray", EXTERNAL_ADJACENT, paint_color)
|
|
use_charges(user, 10, FALSE)
|
|
var/fraction = min(1, . / reagents.maximum_volume)
|
|
reagents.expose(carbon_target, VAPOR, fraction * volume_multiplier)
|
|
|
|
else if(actually_paints && target.is_atom_colour(paint_color, min_priority_index = WASHABLE_COLOUR_PRIORITY))
|
|
balloon_alert(user, "[target.p_theyre()] already that color!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
var/saturation_mode = SATURATION_MULTIPLY
|
|
if (LAZYACCESS(modifiers, RIGHT_CLICK))
|
|
saturation_mode = SATURATION_OVERRIDE
|
|
|
|
if(ismob(target) && (HAS_TRAIT(target, TRAIT_SPRAY_PAINTABLE)))
|
|
if(actually_paints)
|
|
target.add_atom_colour(color_transition_filter(paint_color, saturation_mode), WASHABLE_COLOUR_PRIORITY)
|
|
SEND_SIGNAL(target, COMSIG_LIVING_MOB_PAINTED)
|
|
use_charges(user, 2, requires_full = FALSE)
|
|
reagents.trans_to(target, ., volume_multiplier, transferred_by = user, methods = VAPOR)
|
|
|
|
if(pre_noise || post_noise)
|
|
playsound(user.loc, 'sound/effects/spray.ogg', 5, TRUE, 5)
|
|
user.visible_message(span_notice("[user] coats [target] with spray paint!"), span_notice("You coat [target] with spray paint."))
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
if(!isobj(target) || (target.flags_1 & UNPAINTABLE_1))
|
|
return ..()
|
|
|
|
var/color_is_dark = is_color_dark(paint_color)
|
|
if(!actually_paints)
|
|
if(!(SEND_SIGNAL(target, COMSIG_OBJ_PAINTED, user, src, color_is_dark) & DONT_USE_SPRAYCAN_CHARGES))
|
|
use_charges(user, 2, requires_full = FALSE)
|
|
reagents.trans_to(target, ., volume_multiplier, transferred_by = user, methods = VAPOR)
|
|
|
|
if(pre_noise || post_noise)
|
|
playsound(user.loc, 'sound/effects/spray.ogg', 5, TRUE, 5)
|
|
user.visible_message(span_notice("[user] coats [target] with spray paint!"), span_notice("You coat [target] with spray paint."))
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
if (color_is_dark && saturation_mode == SATURATION_OVERRIDE && !(target.flags_1 & ALLOW_DARK_PAINTS_1))
|
|
to_chat(user, span_warning("A color that dark on an object like this? Surely not..."))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
if(istype(target, /obj/item/pipe))
|
|
if(!GLOB.pipe_color_name.Find(paint_color))
|
|
balloon_alert(user, "invalid pipe color!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
var/obj/item/pipe/target_pipe = target
|
|
target_pipe.pipe_color = paint_color
|
|
target.add_atom_colour(paint_color, FIXED_COLOUR_PRIORITY)
|
|
balloon_alert(user, "painted in [GLOB.pipe_color_name[paint_color]] color")
|
|
else if(istype(target, /obj/machinery/atmospherics))
|
|
if(!GLOB.pipe_color_name.Find(paint_color))
|
|
balloon_alert(user, "invalid pipe color!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
var/obj/machinery/atmospherics/target_pipe = target
|
|
target_pipe.paint(paint_color)
|
|
balloon_alert(user, "painted in [GLOB.pipe_color_name[paint_color]] color")
|
|
else if (is_type_in_typecache(target, direct_color_types))
|
|
target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY)
|
|
else
|
|
target.add_atom_colour(color_transition_filter(paint_color, saturation_mode), WASHABLE_COLOUR_PRIORITY)
|
|
|
|
if(isitem(target) && isliving(target.loc))
|
|
var/obj/item/target_item = target
|
|
var/mob/living/holder = target.loc
|
|
if(holder.is_holding(target_item))
|
|
holder.update_held_items()
|
|
else
|
|
holder.update_clothing(target_item.slot_flags)
|
|
|
|
if(!(SEND_SIGNAL(target, COMSIG_OBJ_PAINTED, user, src, color_is_dark) & DONT_USE_SPRAYCAN_CHARGES))
|
|
use_charges(user, 2, requires_full = FALSE)
|
|
reagents.trans_to(target, ., volume_multiplier, transferred_by = user, methods = VAPOR)
|
|
|
|
if(pre_noise || post_noise)
|
|
playsound(user.loc, 'sound/effects/spray.ogg', 5, TRUE, 5)
|
|
user.visible_message(span_notice("[user] coats [target] with spray paint!"), span_notice("You coat [target] with spray paint."))
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/item/toy/crayon/spraycan/proc/color_limb(obj/item/bodypart/limb, mob/living/user)
|
|
if(!IS_ROBOTIC_LIMB(limb))
|
|
return FALSE
|
|
|
|
var/list/skins = list()
|
|
var/static/list/style_list_icons = list(
|
|
"standard" = 'icons/mob/augmentation/augments.dmi',
|
|
"engineer" = 'icons/mob/augmentation/augments_engineer.dmi',
|
|
"security" = 'icons/mob/augmentation/augments_security.dmi',
|
|
"mining" = 'icons/mob/augmentation/augments_mining.dmi',
|
|
)
|
|
|
|
for(var/skin_option in style_list_icons)
|
|
var/image/part_image = image(icon = style_list_icons[skin_option], icon_state = "[limb.limb_id]_[limb.body_zone]")
|
|
if(limb.aux_zone) //Hands
|
|
part_image.overlays += image(icon = style_list_icons[skin_option], icon_state = "[limb.limb_id]_[limb.aux_zone]")
|
|
skins += list("[skin_option]" = part_image)
|
|
var/choice = show_radial_menu(user, src, skins, require_near = TRUE)
|
|
if(choice && (use_charges(user, 5, requires_full = FALSE)))
|
|
playsound(user.loc, 'sound/effects/spray.ogg', 5, TRUE, 5)
|
|
limb.change_appearance(style_list_icons[choice], greyscale = FALSE)
|
|
return TRUE
|
|
|
|
/obj/item/toy/crayon/spraycan/click_alt(mob/user)
|
|
if(!has_cap)
|
|
return CLICK_ACTION_BLOCKING
|
|
is_capped = !is_capped
|
|
balloon_alert(user, is_capped ? "capped" : "cap removed")
|
|
update_appearance()
|
|
return CLICK_ACTION_SUCCESS
|
|
|
|
/obj/item/toy/crayon/spraycan/update_icon_state()
|
|
icon_state = is_capped ? icon_capped : icon_uncapped
|
|
return ..()
|
|
|
|
/obj/item/toy/crayon/spraycan/update_overlays()
|
|
. = ..()
|
|
if(overlay_paint_colour)
|
|
var/mutable_appearance/spray_overlay = mutable_appearance('icons/obj/art/crayons.dmi', "[is_capped ? "spraycan_cap_colors" : "spraycan_colors"]")
|
|
spray_overlay.color = paint_color
|
|
. += spray_overlay
|
|
|
|
/obj/item/toy/crayon/spraycan/borg
|
|
name = "cyborg spraycan"
|
|
desc = "A metallic container containing shiny synthesised paint."
|
|
charges = INFINITE_CHARGES
|
|
|
|
/obj/item/toy/crayon/spraycan/borg/use_charges(mob/user, amount = 1, requires_full = TRUE, override_infinity = FALSE)
|
|
if(!iscyborg(user))
|
|
to_chat(user, span_notice("How did you get this?"))
|
|
qdel(src)
|
|
return FALSE
|
|
|
|
var/mob/living/silicon/robot/borgy = user
|
|
// 25 is our cost per unit of paint, making it cost 25 energy per
|
|
// normal tag, 50 per window, and 250 per attack
|
|
if(!borgy.cell?.use(amount * 25))
|
|
return FALSE
|
|
return ..()
|
|
|
|
|
|
/obj/item/toy/crayon/spraycan/hellcan
|
|
name = "hellcan"
|
|
desc = "This spraycan doesn't seem to be filled with paint..."
|
|
icon_state = "deathcan2_cap"
|
|
icon_capped = "deathcan2_cap"
|
|
icon_uncapped = "deathcan2"
|
|
overlay_paint_colour = FALSE
|
|
|
|
volume_multiplier = 25
|
|
actually_paints = FALSE
|
|
expose_turfs = TRUE
|
|
charges = 100
|
|
reagent_contents = list(/datum/reagent/clf3 = 1)
|
|
paint_color = COLOR_BLACK
|
|
|
|
/obj/item/toy/crayon/spraycan/hellcan/isValidSurface(surface)
|
|
return isfloorturf(surface)
|
|
|
|
/obj/item/toy/crayon/spraycan/lubecan
|
|
name = "slippery spraycan"
|
|
desc = "You can barely keep hold of this thing."
|
|
icon_state = "clowncan2_cap"
|
|
icon_capped = "clowncan2_cap"
|
|
icon_uncapped = "clowncan2"
|
|
overlay_paint_colour = FALSE
|
|
|
|
reagent_contents = list(/datum/reagent/lube = 1, /datum/reagent/consumable/banana = 1)
|
|
volume_multiplier = 5
|
|
expose_turfs = TRUE
|
|
|
|
/obj/item/toy/crayon/spraycan/lubecan/isValidSurface(surface)
|
|
return isfloorturf(surface)
|
|
|
|
/obj/item/toy/crayon/spraycan/mimecan
|
|
name = "silent spraycan"
|
|
desc = "Art is best seen, not heard."
|
|
icon_state = "mimecan_cap"
|
|
icon_capped = "mimecan_cap"
|
|
icon_uncapped = "mimecan"
|
|
overlay_paint_colour = FALSE
|
|
|
|
can_change_colour = FALSE
|
|
paint_color = COLOR_WHITE //RGB
|
|
|
|
pre_noise = FALSE
|
|
post_noise = FALSE
|
|
reagent_contents = list(/datum/reagent/consumable/nothing = 1, /datum/reagent/toxin/mutetoxin = 1)
|
|
|
|
/obj/item/toy/crayon/spraycan/infinite
|
|
name = "infinite spraycan"
|
|
charges = INFINITE_CHARGES
|
|
desc = "Now with 30% more bluespace technology."
|
|
|
|
/obj/item/toy/crayon/spraycan/roboticist
|
|
name = "roboticist spraycan"
|
|
desc = "Paint for restyling unattached robotic limbs. Sadly doesn't shine like chrome."
|
|
icon_state = "robocan"
|
|
icon_capped = "robocan_cap"
|
|
icon_uncapped = "robocan"
|
|
|
|
#undef RANDOM_GRAFFITI
|
|
#undef RANDOM_LETTER
|
|
#undef RANDOM_PUNCTUATION
|
|
#undef RANDOM_SYMBOL
|
|
#undef RANDOM_DRAWING
|
|
#undef RANDOM_NUMBER
|
|
#undef RANDOM_ORIENTED
|
|
#undef RANDOM_RUNE
|
|
#undef RANDOM_ANY
|
|
|
|
#undef AVAILABLE_SPRAYCAN_SPACE
|
|
|
|
#undef PAINT_NORMAL
|
|
#undef PAINT_LARGE_HORIZONTAL
|
|
#undef PAINT_LARGE_HORIZONTAL_ICON
|
|
|
|
#undef INFINITE_CHARGES
|
|
#undef DRAW_TIME
|