mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-09 16:05:07 +00:00
Melee attack chain now has a list passed along with it, `attack_modifiers`, which you can stick force modifiers to change the resulting attack This is basically a soft implementation of damage packets until a more definitive pr, but one that only applies to item attack chain, and not unarmed attacks. This change was done to facilitate a baton refactor - batons no longer hack together their own attack chain, and are now integrated straight into the real attack chain. This refactor itself was done because batons don't send any attack signals, which has been annoying in the past (for swing combat). 🆑 Melbert refactor: Batons have been refactored again. Baton stuns now properly count as an attack, when before it was a nothing. Report any oddities, particularly in regards to harmbatonning vs normal batonning. refactor: The method of adjusting item damage mid-attack has been refactored - some affected items include the Nullblade and knives. Report any strange happenings with damage numbers. refactor: A few objects have been moved to the new interaction chain - records consoles, mawed crucible, alien weeds and space vines, hedges, restaurant portals, and some mobs - to name a few. fix: Spears only deal bonus damage against secure lockers, not all closet types (including crates) /🆑
343 lines
13 KiB
Plaintext
343 lines
13 KiB
Plaintext
/obj/item/lipstick
|
|
gender = PLURAL
|
|
name = "red lipstick"
|
|
desc = "A generic brand of lipstick."
|
|
icon = 'modular_skyrat/modules/salon/icons/items.dmi' //SKYRAT EDIT CHANGE - ORIGINAL: icon = 'icons/obj/cosmetic.dmi'
|
|
icon_state = "lipstick"
|
|
base_icon_state = "lipstick"
|
|
inhand_icon_state = "lipstick"
|
|
w_class = WEIGHT_CLASS_TINY
|
|
interaction_flags_click = NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING
|
|
var/open = FALSE
|
|
/// Actual color of the lipstick, also gets applied to the human
|
|
var/lipstick_color = COLOR_RED
|
|
/// The style of lipstick. Upper, middle, or lower lip. Default is middle.
|
|
var/style = "lipstick"
|
|
/// A trait that's applied while someone has this lipstick applied, and is removed when the lipstick is removed
|
|
var/lipstick_trait
|
|
/// Can this lipstick spawn randomly
|
|
var/random_spawn = TRUE
|
|
|
|
/obj/item/lipstick/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/update_icon_updates_onmob)
|
|
update_appearance(UPDATE_ICON)
|
|
|
|
/obj/item/lipstick/vv_edit_var(vname, vval)
|
|
. = ..()
|
|
if(vname == NAMEOF(src, open))
|
|
update_appearance(UPDATE_ICON)
|
|
|
|
/obj/item/lipstick/examine(mob/user)
|
|
. = ..()
|
|
. += "Alt-click to change the style."
|
|
|
|
/obj/item/lipstick/update_icon_state()
|
|
icon_state = "[base_icon_state][open ? "_uncap" : null]"
|
|
inhand_icon_state = "[base_icon_state][open ? "open" : null]"
|
|
return ..()
|
|
|
|
/obj/item/lipstick/update_overlays()
|
|
. = ..()
|
|
if(!open)
|
|
return
|
|
var/mutable_appearance/colored_overlay = mutable_appearance(icon, "lipstick_uncap_color")
|
|
colored_overlay.color = lipstick_color
|
|
. += colored_overlay
|
|
|
|
/obj/item/lipstick/click_alt(mob/user)
|
|
display_radial_menu(user)
|
|
return CLICK_ACTION_SUCCESS
|
|
|
|
/obj/item/lipstick/proc/display_radial_menu(mob/living/carbon/human/user)
|
|
var/style_options = list(
|
|
UPPER_LIP = icon('icons/hud/radial.dmi', UPPER_LIP),
|
|
MIDDLE_LIP = icon('icons/hud/radial.dmi', MIDDLE_LIP),
|
|
LOWER_LIP = icon('icons/hud/radial.dmi', LOWER_LIP),
|
|
)
|
|
var/pick = show_radial_menu(user, src, style_options, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
|
|
if(!pick)
|
|
return TRUE
|
|
|
|
switch(pick)
|
|
if(MIDDLE_LIP)
|
|
style = "lipstick"
|
|
if(LOWER_LIP)
|
|
style = "lipstick_lower"
|
|
if(UPPER_LIP)
|
|
style = "lipstick_upper"
|
|
return TRUE
|
|
|
|
/obj/item/lipstick/proc/check_menu(mob/living/user)
|
|
if(!istype(user))
|
|
return FALSE
|
|
if(user.incapacitated || !user.is_holding(src))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/item/lipstick/purple
|
|
name = "purple lipstick"
|
|
lipstick_color = COLOR_PURPLE
|
|
|
|
/obj/item/lipstick/jade
|
|
name = "jade lipstick"
|
|
lipstick_color = COLOR_JADE
|
|
|
|
/obj/item/lipstick/blue
|
|
name = "blue lipstick"
|
|
lipstick_color = COLOR_BLUE
|
|
|
|
/obj/item/lipstick/green
|
|
name = "green lipstick"
|
|
lipstick_color = COLOR_GREEN
|
|
|
|
/obj/item/lipstick/white
|
|
name = "white lipstick"
|
|
lipstick_color = COLOR_WHITE
|
|
|
|
/obj/item/lipstick/black
|
|
name = "black lipstick"
|
|
lipstick_color = COLOR_BLACK
|
|
|
|
/obj/item/lipstick/black/death
|
|
name = "\improper Kiss of Death"
|
|
desc = "An incredibly potent tube of lipstick made from the venom of the dreaded Yellow Spotted Space Lizard, as deadly as it is chic. Try not to smear it!"
|
|
lipstick_trait = TRAIT_KISS_OF_DEATH
|
|
random_spawn = FALSE
|
|
|
|
/obj/item/lipstick/syndie
|
|
name = "syndie lipstick"
|
|
desc = "Syndicate branded lipstick with a killer dose of kisses. Observe safety regulations!"
|
|
icon_state = "slipstick"
|
|
base_icon_state = "slipstick"
|
|
lipstick_color = COLOR_SYNDIE_RED
|
|
lipstick_trait = TRAIT_SYNDIE_KISS
|
|
random_spawn = FALSE
|
|
|
|
/obj/item/lipstick/random
|
|
name = "lipstick"
|
|
icon_state = "random_lipstick"
|
|
|
|
/obj/item/lipstick/random/Initialize(mapload)
|
|
. = ..()
|
|
icon_state = "lipstick"
|
|
var/static/list/possible_colors
|
|
if(!possible_colors)
|
|
possible_colors = list()
|
|
for(var/obj/item/lipstick/lipstick_path as anything in (typesof(/obj/item/lipstick) - src.type))
|
|
if(!initial(lipstick_path.lipstick_color) || !initial(lipstick_path.random_spawn))
|
|
continue
|
|
possible_colors[initial(lipstick_path.lipstick_color)] = initial(lipstick_path.name)
|
|
lipstick_color = pick(possible_colors)
|
|
name = possible_colors[lipstick_color]
|
|
update_appearance()
|
|
|
|
/obj/item/lipstick/attack_self(mob/user)
|
|
to_chat(user, span_notice("You twist [src] [open ? "closed" : "open"]."))
|
|
open = !open
|
|
update_appearance(UPDATE_ICON)
|
|
|
|
/obj/item/lipstick/attack(mob/M, mob/user)
|
|
if(!open || !ismob(M))
|
|
return
|
|
|
|
if(!ishuman(M))
|
|
to_chat(user, span_warning("Where are the lips on that?"))
|
|
return
|
|
|
|
var/mob/living/carbon/human/target = M
|
|
if(target.is_mouth_covered())
|
|
to_chat(user, span_warning("Remove [ target == user ? "your" : "[target.p_their()]" ] mask!"))
|
|
return
|
|
if(target.lip_style) //if they already have lipstick on
|
|
to_chat(user, span_warning("You need to wipe off the old lipstick first!"))
|
|
return
|
|
|
|
if(target == user)
|
|
user.visible_message(span_notice("[user] does [user.p_their()] lips with \the [src]."), \
|
|
span_notice("You take a moment to apply \the [src]. Perfect!"))
|
|
target.update_lips(style, lipstick_color, lipstick_trait)
|
|
return
|
|
|
|
user.visible_message(span_warning("[user] begins to do [target]'s lips with \the [src]."), \
|
|
span_notice("You begin to apply \the [src] on [target]'s lips..."))
|
|
if(!do_after(user, 2 SECONDS, target = target))
|
|
return
|
|
user.visible_message(span_notice("[user] does [target]'s lips with \the [src]."), \
|
|
span_notice("You apply \the [src] on [target]'s lips."))
|
|
target.update_lips(style, lipstick_color, lipstick_trait)
|
|
|
|
//you can wipe off lipstick with paper!
|
|
/obj/item/paper/attack(mob/M, mob/user)
|
|
if(user.zone_selected != BODY_ZONE_PRECISE_MOUTH || !ishuman(M))
|
|
return ..()
|
|
|
|
var/mob/living/carbon/human/target = M
|
|
if(target == user)
|
|
to_chat(user, span_notice("You wipe off the lipstick with [src]."))
|
|
target.update_lips(null)
|
|
return
|
|
user.visible_message(span_warning("[user] begins to wipe [target]'s lipstick off with \the [src]."), \
|
|
span_notice("You begin to wipe off [target]'s lipstick..."))
|
|
if(!do_after(user, 1 SECONDS, target = target))
|
|
return
|
|
user.visible_message(span_notice("[user] wipes [target]'s lipstick off with \the [src]."), \
|
|
span_notice("You wipe off [target]'s lipstick."))
|
|
target.update_lips(null)
|
|
|
|
/* SKYRAT EDIT REMOVAL
|
|
/obj/item/razor
|
|
name = "electric razor"
|
|
desc = "The latest and greatest power razor born from the science of shaving."
|
|
icon = 'icons/obj/cosmetic.dmi'
|
|
icon_state = "razor"
|
|
inhand_icon_state = "razor"
|
|
obj_flags = CONDUCTS_ELECTRICITY
|
|
w_class = WEIGHT_CLASS_TINY
|
|
|
|
/obj/item/razor/suicide_act(mob/living/carbon/user)
|
|
user.visible_message(span_suicide("[user] begins shaving [user.p_them()]self without the razor guard! It looks like [user.p_theyre()] trying to commit suicide!"))
|
|
shave(user, BODY_ZONE_PRECISE_MOUTH)
|
|
shave(user, BODY_ZONE_HEAD)//doesn't need to be BODY_ZONE_HEAD specifically, but whatever
|
|
return BRUTELOSS
|
|
|
|
/obj/item/razor/proc/shave(mob/living/carbon/human/skinhead, location = BODY_ZONE_PRECISE_MOUTH)
|
|
if(location == BODY_ZONE_PRECISE_MOUTH)
|
|
skinhead.set_facial_hairstyle("Shaved", update = TRUE)
|
|
else
|
|
skinhead.set_hairstyle("Skinhead", update = TRUE)
|
|
playsound(loc, 'sound/items/tools/welder2.ogg', 20, TRUE)
|
|
|
|
/obj/item/razor/attack(mob/target_mob, mob/living/user, list/modifiers, list/attack_modifiers)
|
|
if(!ishuman(target_mob))
|
|
return ..()
|
|
var/mob/living/carbon/human/human_target = target_mob
|
|
var/obj/item/bodypart/head/noggin = human_target.get_bodypart(BODY_ZONE_HEAD)
|
|
var/location = user.zone_selected
|
|
var/static/list/head_zones = list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD)
|
|
if(!noggin && (location in head_zones))
|
|
to_chat(user, span_warning("[human_target] doesn't have a head!"))
|
|
return
|
|
if(location == BODY_ZONE_PRECISE_MOUTH)
|
|
if(!user.combat_mode)
|
|
if(human_target.gender == MALE)
|
|
if(human_target == user)
|
|
to_chat(user, span_warning("You need a mirror to properly style your own facial hair!"))
|
|
return
|
|
if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
|
|
return
|
|
var/new_style = tgui_input_list(user, "Select a facial hairstyle", "Grooming", SSaccessories.facial_hairstyles_list)
|
|
if(isnull(new_style))
|
|
return
|
|
if(!get_location_accessible(human_target, location))
|
|
to_chat(user, span_warning("The headgear is in the way!"))
|
|
return
|
|
if(!(noggin.head_flags & HEAD_FACIAL_HAIR))
|
|
to_chat(user, span_warning("There is no facial hair to style!"))
|
|
return
|
|
if(HAS_TRAIT(human_target, TRAIT_SHAVED))
|
|
to_chat(user, span_warning("[human_target] is just way too shaved. Like, really really shaved."))
|
|
return
|
|
user.visible_message(span_notice("[user] tries to change [human_target]'s facial hairstyle using [src]."), span_notice("You try to change [human_target]'s facial hairstyle using [src]."))
|
|
playsound(src, 'sound/items/hair-clippers.ogg', 50)
|
|
if(new_style && do_after(user, 6 SECONDS, target = human_target))
|
|
user.visible_message(span_notice("[user] successfully changes [human_target]'s facial hairstyle using [src]."), span_notice("You successfully change [human_target]'s facial hairstyle using [src]."))
|
|
human_target.set_facial_hairstyle(new_style, update = TRUE)
|
|
return
|
|
else
|
|
return
|
|
else
|
|
if(!get_location_accessible(human_target, location))
|
|
to_chat(user, span_warning("The mask is in the way!"))
|
|
return
|
|
if(!(noggin.head_flags & HEAD_FACIAL_HAIR))
|
|
to_chat(user, span_warning("There is no facial hair to shave!"))
|
|
return
|
|
if(human_target.facial_hairstyle == "Shaved")
|
|
to_chat(user, span_warning("Already clean-shaven!"))
|
|
return
|
|
|
|
if(human_target == user) //shaving yourself
|
|
user.visible_message(span_notice("[user] starts to shave [user.p_their()] facial hair with [src]."), \
|
|
span_notice("You take a moment to shave your facial hair with [src]..."))
|
|
playsound(src, 'sound/items/hair-clippers.ogg', 50)
|
|
if(do_after(user, 5 SECONDS, target = user))
|
|
user.visible_message(span_notice("[user] shaves [user.p_their()] facial hair clean with [src]."), \
|
|
span_notice("You finish shaving with [src]. Fast and clean!"))
|
|
shave(user, location)
|
|
return
|
|
else
|
|
user.visible_message(span_warning("[user] tries to shave [human_target]'s facial hair with [src]."), \
|
|
span_notice("You start shaving [human_target]'s facial hair..."))
|
|
playsound(src, 'sound/items/hair-clippers.ogg', 50)
|
|
if(do_after(user, 5 SECONDS, target = human_target))
|
|
user.visible_message(span_warning("[user] shaves off [human_target]'s facial hair with [src]."), \
|
|
span_notice("You shave [human_target]'s facial hair clean off."))
|
|
shave(human_target, location)
|
|
return
|
|
else if(location == BODY_ZONE_HEAD)
|
|
if(!user.combat_mode)
|
|
if(human_target == user)
|
|
to_chat(user, span_warning("You need a mirror to properly style your own hair!"))
|
|
return
|
|
if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
|
|
return
|
|
var/new_style = tgui_input_list(user, "Select a hairstyle", "Grooming", SSaccessories.hairstyles_list)
|
|
if(isnull(new_style))
|
|
return
|
|
if(!get_location_accessible(human_target, location))
|
|
to_chat(user, span_warning("The headgear is in the way!"))
|
|
return
|
|
if(!(noggin.head_flags & HEAD_HAIR))
|
|
to_chat(user, span_warning("There is no hair to style!"))
|
|
return
|
|
if(HAS_TRAIT(human_target, TRAIT_BALD))
|
|
to_chat(user, span_warning("[human_target] is just way too bald. Like, really really bald."))
|
|
return
|
|
user.visible_message(span_notice("[user] tries to change [human_target]'s hairstyle using [src]."), span_notice("You try to change [human_target]'s hairstyle using [src]."))
|
|
playsound(src, 'sound/items/hair-clippers.ogg', 50)
|
|
if(new_style && do_after(user, 6 SECONDS, target = human_target))
|
|
user.visible_message(span_notice("[user] successfully changes [human_target]'s hairstyle using [src]."), span_notice("You successfully change [human_target]'s hairstyle using [src]."))
|
|
human_target.set_hairstyle(new_style, update = TRUE)
|
|
return
|
|
else
|
|
if(!get_location_accessible(human_target, location))
|
|
to_chat(user, span_warning("The headgear is in the way!"))
|
|
return
|
|
if(!(noggin.head_flags & HEAD_HAIR))
|
|
to_chat(user, span_warning("There is no hair to shave!"))
|
|
return
|
|
if(human_target.hairstyle == "Bald" || human_target.hairstyle == "Balding Hair" || human_target.hairstyle == "Skinhead")
|
|
to_chat(user, span_warning("There is not enough hair left to shave!"))
|
|
return
|
|
|
|
if(human_target == user) //shaving yourself
|
|
user.visible_message(span_notice("[user] starts to shave [user.p_their()] head with [src]."), \
|
|
span_notice("You start to shave your head with [src]..."))
|
|
playsound(src, 'sound/items/hair-clippers.ogg', 50)
|
|
if(do_after(user, 5 SECONDS, target = user))
|
|
user.visible_message(span_notice("[user] shaves [user.p_their()] head with [src]."), \
|
|
span_notice("You finish shaving with [src]."))
|
|
shave(user, location)
|
|
return
|
|
else
|
|
user.visible_message(span_warning("[user] tries to shave [human_target]'s head with [src]!"), \
|
|
span_notice("You start shaving [human_target]'s head..."))
|
|
playsound(src, 'sound/items/hair-clippers.ogg', 50)
|
|
if(do_after(user, 5 SECONDS, target = human_target))
|
|
user.visible_message(span_warning("[user] shaves [human_target]'s head bald with [src]!"), \
|
|
span_notice("You shave [human_target]'s head bald."))
|
|
shave(human_target, location)
|
|
return
|
|
return ..()
|
|
*/
|
|
|
|
/obj/item/razor/surgery
|
|
name = "surgical razor"
|
|
desc = "A medical grade razor. Its precision blades provide a clean shave for surgical preparation."
|
|
icon = 'icons/obj/cosmetic.dmi'
|
|
icon_state = "medrazor"
|
|
|
|
/obj/item/razor/surgery/get_surgery_tool_overlay(tray_extended)
|
|
return "razor"
|