Merge remote-tracking branch 'citadel/master' into clickcd_experimental
This commit is contained in:
@@ -52,4 +52,4 @@
|
||||
#define ORGAN_VITAL (1<<4) //Currently only the brain
|
||||
#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances
|
||||
#define ORGAN_NO_DISMEMBERMENT (1<<6) //Immune to disembowelment.
|
||||
#define ORGAN_EDIBLE (1<<5) //is a snack? :D
|
||||
#define ORGAN_EDIBLE (1<<7) //is a snack? :D
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Defines for managed input/keybinding system.
|
||||
/// Max length of a keypress command before it's considered to be a forged packet/bogus command
|
||||
#define MAX_KEYPRESS_COMMANDLENGTH 16
|
||||
#define MAX_KEYPRESS_COMMANDLENGTH 32
|
||||
/// Maximum keys that can be bound to one button
|
||||
#define MAX_COMMANDS_PER_KEY 5
|
||||
/// Maximum keys per keybind
|
||||
|
||||
@@ -153,14 +153,17 @@
|
||||
var/list/po = A.priority_overlays;\
|
||||
if(LAZYLEN(rm)){\
|
||||
A.overlays -= rm;\
|
||||
rm.Cut();\
|
||||
A.remove_overlays = null;\
|
||||
}\
|
||||
if(LAZYLEN(ad)){\
|
||||
A.overlays |= ad;\
|
||||
ad.Cut();\
|
||||
A.add_overlays = null;\
|
||||
}\
|
||||
if(LAZYLEN(po)){\
|
||||
A.overlays |= po;\
|
||||
}\
|
||||
else{\
|
||||
A.priority_overlays = null;\
|
||||
}\
|
||||
A.flags_1 &= ~OVERLAY_QUEUED_1;\
|
||||
}
|
||||
|
||||
@@ -145,9 +145,9 @@
|
||||
continue
|
||||
if(!S.ckeys_allowed)
|
||||
snowflake_ipc_antenna_list[S.name] = mspath
|
||||
var/color1 = random_short_color()
|
||||
var/color2 = random_short_color()
|
||||
var/color3 = random_short_color()
|
||||
var/color1 = random_color()
|
||||
var/color2 = random_color()
|
||||
var/color3 = random_color()
|
||||
|
||||
var/body_model = MALE
|
||||
switch(intended_gender)
|
||||
|
||||
@@ -51,40 +51,111 @@
|
||||
return default
|
||||
return default
|
||||
|
||||
/proc/sanitize_hexcolor(color, desired_format=3, include_crunch=0, default)
|
||||
#define RGB_FORMAT_INVALID 0
|
||||
#define RGB_FORMAT_SHORT 1
|
||||
#define RGB_FORMAT_LONG 2
|
||||
|
||||
/**
|
||||
* Sanitizes a hexadecimal color. Always outputs lowercase.
|
||||
*
|
||||
* @params
|
||||
* * color - input color, 3 or 6 characters without the #.
|
||||
* * desired_format - 3 or 6 characters without the potential #. can only put in 3 or 6 here.
|
||||
* * include_crunch - do we put a # at the start
|
||||
* * default - default color. must be 3 or 6 characters with or without #.
|
||||
* * default_replacement - what we replace broken letters with.
|
||||
*/
|
||||
/proc/sanitize_hexcolor(color, desired_format = 3, include_crunch = 0, default = rgb(218, 72, 255), default_replacement = "f")
|
||||
if(!istext(default) || (length(default) < 3))
|
||||
CRASH("Default should be a text string of RGB format, with or without the crunch, 3 or 6 characters. Default was instead [default]")
|
||||
if(!istext(default_replacement) || (length(default_replacement) != 1))
|
||||
CRASH("Invalid default_replacement: [default_replacement]")
|
||||
default_replacement = lowertext(default_replacement)
|
||||
switch(text2ascii(default_replacement))
|
||||
if(48 to 57)
|
||||
if(97 to 102)
|
||||
if(65 to 70)
|
||||
else // yeah yeah i know 3 empty if's..
|
||||
CRASH("Invalid default_replacement: [default_replacement]")
|
||||
var/crunch = include_crunch ? "#" : ""
|
||||
if(!istext(color))
|
||||
color = ""
|
||||
color = default
|
||||
|
||||
var/start = 1 + (text2ascii(color, 1) == 35)
|
||||
var/len = length(color)
|
||||
var/char = ""
|
||||
// RRGGBB -> RGB but awful
|
||||
var/convert_to_shorthand = desired_format == 3 && length_char(color) > 3
|
||||
// get rid of crunch
|
||||
if(len && color[1] == "#")
|
||||
if(len >= 2)
|
||||
color = copytext(color, 2)
|
||||
else
|
||||
color = ""
|
||||
len = length(color)
|
||||
|
||||
. = ""
|
||||
var/i = start
|
||||
while(i <= len)
|
||||
switch(desired_format)
|
||||
if(3)
|
||||
desired_format = RGB_FORMAT_SHORT
|
||||
if(6)
|
||||
desired_format = RGB_FORMAT_LONG
|
||||
else
|
||||
CRASH("Invalid desired_format: [desired_format]. Must be 3 or 6.")
|
||||
var/current_format = RGB_FORMAT_INVALID
|
||||
switch(length(color))
|
||||
if(3)
|
||||
current_format = RGB_FORMAT_SHORT
|
||||
if(6)
|
||||
current_format = RGB_FORMAT_LONG
|
||||
else
|
||||
current_format = RGB_FORMAT_INVALID
|
||||
|
||||
if(current_format == RGB_FORMAT_INVALID) // nah
|
||||
color = default // process default
|
||||
if(color[1] == "#") // we checked default was at least 3 chars long earlier
|
||||
color = copytext(color, 2)
|
||||
len = length(color)
|
||||
switch(len)
|
||||
if(3)
|
||||
current_format = RGB_FORMAT_SHORT
|
||||
if(6)
|
||||
current_format = RGB_FORMAT_LONG
|
||||
else
|
||||
CRASH("Default was not 3 or 6 RGB hexadecimal characters: [default]")
|
||||
|
||||
var/sanitized = ""
|
||||
var/char = ""
|
||||
// first, sanitize hex
|
||||
for(var/i in 1 to len)
|
||||
char = color[i]
|
||||
switch(text2ascii(char))
|
||||
if(48 to 57) //numbers 0 to 9
|
||||
. += char
|
||||
if(97 to 102) //letters a to f
|
||||
. += char
|
||||
if(65 to 70) //letters A to F
|
||||
. += lowertext(char)
|
||||
if(48 to 57) // 0 to 9
|
||||
sanitized += char
|
||||
if(97 to 102) // a to f
|
||||
sanitized += char
|
||||
if(65 to 70) // A to F (capitalized!)
|
||||
sanitized += lowertext(char)
|
||||
else
|
||||
break
|
||||
i += length(char)
|
||||
if(convert_to_shorthand && i <= len) //skip next one
|
||||
i += length(color[i])
|
||||
sanitized += default_replacement
|
||||
// do we need to convert?
|
||||
if(desired_format == current_format)
|
||||
return crunch + sanitized // no
|
||||
// yes
|
||||
if((desired_format == RGB_FORMAT_SHORT) && (current_format == RGB_FORMAT_LONG)) // downconvert
|
||||
var/temp = ""
|
||||
// we could do some math but we're lazy and in practice floor()ing this.
|
||||
for(var/i in 1 to 6 step 2)
|
||||
temp += sanitized[i]
|
||||
sanitized = temp
|
||||
else if((desired_format == RGB_FORMAT_LONG) && (current_format == RGB_FORMAT_SHORT)) // upconvert
|
||||
var/temp = ""
|
||||
for(var/i in 1 to 3)
|
||||
temp += sanitized[i]
|
||||
temp += sanitized[i]
|
||||
sanitized = temp
|
||||
else
|
||||
CRASH("Invalid desired_format and current_format pair: [desired_format], [current_format]. Could not determine which way to convert.")
|
||||
return crunch + sanitized
|
||||
|
||||
if(length_char(.) != desired_format)
|
||||
if(default)
|
||||
return default
|
||||
return crunch + repeat_string(desired_format, "0")
|
||||
|
||||
return crunch + .
|
||||
#undef RGB_FORMAT_INVALID
|
||||
#undef RGB_FORMAT_SHORT
|
||||
#undef RGB_FORMAT_LONG
|
||||
|
||||
/proc/sanitize_ooccolor(color)
|
||||
if(length(color) != length_char(color))
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
deltimer(C.parallax_animate_timer)
|
||||
var/datum/callback/CB = CALLBACK(src, .proc/update_parallax_motionblur, C, animatedir, new_parallax_movedir, newtransform)
|
||||
if(skip_windups)
|
||||
CB.Invoke()
|
||||
CB.InvokeAsync()
|
||||
else
|
||||
C.parallax_animate_timer = addtimer(CB, min(shortesttimer, PARALLAX_LOOP_TIME), TIMER_CLIENT_TIME|TIMER_STOPPABLE)
|
||||
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
//similar to dog_fashion, but for beepsky, who has far more refined fashion tastes
|
||||
/datum/beepsky_fashion
|
||||
var/name //not setting the name and desc makes them go to the default
|
||||
var/desc
|
||||
|
||||
var/icon_file = 'icons/mob/secbot_accessories.dmi' //we sell secbots and secbot accessories
|
||||
var/obj_icon_state
|
||||
var/obj_alpha
|
||||
var/obj_color
|
||||
|
||||
var/list/stun_sounds //sound that replaces the stun attack when set
|
||||
var/ignore_sound = FALSE //whether to ignore sounds entirely or not
|
||||
|
||||
//emotes (don't set them if you want the default value)
|
||||
var/death_emote //what is said when beepsky dies
|
||||
var/capture_one //what is said when cuffing someone
|
||||
var/capture_two //what is said when cuffing someone, directly to the person being cuffed
|
||||
var/infraction //the level of threat detected
|
||||
var/taunt // beepsky pointing at a criminal
|
||||
var/attack_one //text when attacking criminal
|
||||
var/attack_two //text when attacking criminal, but directly to the criminal
|
||||
var/patrol_emote //engaging patrol text
|
||||
var/patrol_fail_emote //failing to engage patrol text
|
||||
var/list/arrest_texts //first is for not-cuffing, second is for cuffing
|
||||
var/arrest_emote //text stating that you're cuffing some criminal C with a threat of level X in location Y
|
||||
|
||||
//for reference, the following words are replaced when processed before speech:
|
||||
//LOCATION = the location passed, if any (this is only used by arrest_emote)
|
||||
//CRIMINAL = the name of the criminal (this is used by everything but patrol_emote and infraction)
|
||||
//BOT = the name of the bot (this can be used on any of the emotes)
|
||||
//THREAT_LEVEL = the level of the threat detected (can be used on arrest_emote and infraction)
|
||||
|
||||
/datum/beepsky_fashion/proc/get_overlay(var/dir)
|
||||
if(icon_file && obj_icon_state)
|
||||
var/image/beepsky_overlay = image(icon_file, obj_icon_state, dir = dir)
|
||||
beepsky_overlay.alpha = obj_alpha
|
||||
beepsky_overlay.color = obj_color
|
||||
return beepsky_overlay
|
||||
|
||||
/datum/beepsky_fashion/proc/stun_attack(mob/living/carbon/C) //fired when beepsky does a stun attack with the fashion worn, for sounds/overlays/etc
|
||||
return
|
||||
|
||||
//actual fashions from here on out
|
||||
/datum/beepsky_fashion/wizard
|
||||
obj_icon_state = "wizard"
|
||||
name = "Archmage Beepsky"
|
||||
desc = "A secbot stolen from the wizard federation."
|
||||
death_emote = "BOT casts EI NATH on themselves!"
|
||||
capture_one = "BOT is casting cable ties on CRIMINAL!"
|
||||
capture_two = "BOT is casting cable ties on you!"
|
||||
infraction = "Magical disturbance of magnitude THREAT_LEVEL detected!"
|
||||
taunt = "BOT points his staff towards CRIMINAL!"
|
||||
attack_one = "BOT casts magic missile on CRIMINAL!"
|
||||
attack_two = "BOT casts magic missile on you!"
|
||||
patrol_emote = "Beginning search for magical disturbances."
|
||||
patrol_fail_emote = "Failure to find magical disturbances. Recallibrating."
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL magical practitioner CRIMINAL in LOCATION."
|
||||
stun_sounds = list('sound/magic/lightningbolt.ogg',
|
||||
'sound/magic/fireball.ogg',
|
||||
'sound/weapons/zapbang.ogg',
|
||||
'sound/magic/knock.ogg',
|
||||
'sound/magic/fleshtostone.ogg',
|
||||
'sound/effects/magic.ogg',
|
||||
'sound/magic/disintegrate.ogg')
|
||||
|
||||
/datum/beepsky_fashion/cowboy
|
||||
obj_icon_state = "cowboy"
|
||||
name = "Sheriff Beepsky"
|
||||
desc = "The sheriff of this here station."
|
||||
capture_one = "BOT is tying CRIMINAL up!"
|
||||
capture_two = "BOT is tying you up!"
|
||||
infraction = "Outlaws with a bounty of THREAT_LEVEL000 space dollars detected!"
|
||||
taunt = "BOT aims his revolver towards CRIMINAL!"
|
||||
attack_one = "BOT unloads his revolver onto CRIMINAL!"
|
||||
attack_two = "BOT unloads his revolver onto you!"
|
||||
patrol_emote = "Engaging bounty hunting protocols."
|
||||
patrol_fail_emote = "Unable to find any bounties due to error. Rebooting."
|
||||
arrest_emote = "ARREST_TYPE outlaw CRIMINAL with a bounty of THREAT_LEVEL000 in LOCATION."
|
||||
stun_sounds = list('sound/weapons/Gunshot.ogg',
|
||||
'sound/weapons/Gunshot2.ogg',
|
||||
'sound/weapons/Gunshot3.ogg',
|
||||
'sound/weapons/Gunshot4.ogg')
|
||||
|
||||
/datum/beepsky_fashion/chef
|
||||
obj_icon_state = "chef"
|
||||
name = "Chef Beepsky"
|
||||
desc = "Cooking up the finest foods the station has ever seen."
|
||||
death_emote = "Mamma-mia!"
|
||||
infraction = "Grade THREAT_LEVEL prosciutto detected!"
|
||||
taunt = "BOT glares at CRIMINAL."
|
||||
attack_one = "BOT CQCs CRIMINAL!"
|
||||
attack_two = "BOT CQCs you!"
|
||||
patrol_emote = "Beginning search for the bad prosciutto."
|
||||
patrol_fail_emote = "All prosciutto is stale. Rebooting."
|
||||
arrest_texts = list("Frying", "Grilling") //any good secoff knows the difference
|
||||
arrest_emote = "ARREST_TYPE grade THREAT_LEVEL prosciutto CRIMINAL in LOCATION."
|
||||
stun_sounds = list('sound/weapons/cqchit1.ogg',
|
||||
'sound/weapons/cqchit2.ogg')
|
||||
|
||||
/datum/beepsky_fashion/cat
|
||||
obj_icon_state = "cat"
|
||||
name = "OwOfficer Bweepskwee"
|
||||
desc = "A beepsky unit with cat ears. Catgirl science has gone too far."
|
||||
death_emote = "Nya!"
|
||||
capture_one = "BOT is tying CRIMINAL up!!"
|
||||
capture_two = "BOT is tying you up!"
|
||||
infraction = "Wevel THREAT_LEVEL infwactwion awert!!!"
|
||||
taunt = "BOT points at CRIMINAL and nyas!"
|
||||
attack_one = "BOT shoves CRIMINAL onto a table!"
|
||||
attack_two = "BOT shoves you onto a table!"
|
||||
patrol_emote = "Enwgagwing patwol mwodies.."
|
||||
patrol_fail_emote = "Unawbwle two stwawt patwollies. Nya."
|
||||
arrest_texts = list("Dwetwaining", "Awwesting")
|
||||
arrest_emote = "ARREST_TYPE wevel THREAT_LEVEL scwumbwag CRIMINAL in LOCATION. Nya."
|
||||
ignore_sound = TRUE //we instead make the stunned person fire the nya emote
|
||||
|
||||
/datum/beepsky_fashion/cat/stun_attack(var/mob/living/carbon/C) //makes a fake table under you on hit, makes cat people nya when hit
|
||||
if(iscatperson(C))
|
||||
C.emote("nya")
|
||||
var/turf/target_turf = get_turf(C)
|
||||
if(target_turf) //slams you on a fake table
|
||||
playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, 1)
|
||||
var/obj/effect/overlay_holder = new(target_turf)
|
||||
overlay_holder.name = "Catboy Table"
|
||||
overlay_holder.desc = "Where bad catboys go."
|
||||
var/image/table_overlay = image('icons/obj/smooth_structures/table.dmi', "table")
|
||||
overlay_holder.add_overlay(table_overlay)
|
||||
QDEL_IN(overlay_holder, 10)
|
||||
|
||||
/datum/beepsky_fashion/cake //nothing else. it's just beepsky. with a cake on his head.
|
||||
obj_icon_state = "cake"
|
||||
name = "Cakesky"
|
||||
desc = "It's a secbot, wearing a cake on his head!"
|
||||
|
||||
/datum/beepsky_fashion/captain
|
||||
obj_icon_state = "captain"
|
||||
name = "Captainsky"
|
||||
desc = "The real captain of this station."
|
||||
capture_one = "BOT is lecturing CRIMINAL on why he is the captain!"
|
||||
capture_two = "BOT is lecturing you on why he is the captain!"
|
||||
infraction = "Level THREAT_LEVEL greytider detected."
|
||||
attack_one = "BOT beats CRIMINAL with the chain of command!"
|
||||
attack_two = "BOT beats you with the chain of command!"
|
||||
patrol_emote = "Uselessness protocols engaged."
|
||||
patrol_fail_emote = "Unit has been found as useless. Rebooting."
|
||||
arrest_texts = list("Demoting", "Firing")
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL lesser crewmember CRIMINAL in LOCATION."
|
||||
stun_sounds = list('sound/weapons/chainhit.ogg')
|
||||
|
||||
/datum/beepsky_fashion/king
|
||||
obj_icon_state = "king"
|
||||
name = "King Beepsky"
|
||||
desc = "He who has ascended to bare the right of king, sits atop the throne."
|
||||
capture_one = "BOT is calling the guards onto CRIMINAL!"
|
||||
capture_two = "BOT is calling the guards onto you!"
|
||||
infraction = "Treason of level THREAT_LEVEL detected!"
|
||||
attack_one = "BOT strikes CRIMINAL with his kingly authority!"
|
||||
attack_two = "BOT strikes you with his kingly authority!"
|
||||
patrol_emote = "Searching for peasants to beat up."
|
||||
patrol_fail_emote = "Peasants are using dark magic. Recallibrating."
|
||||
arrest_texts = list("Knighting", "Executing")
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL peasant CRIMINAL in LOCATION."
|
||||
stun_sounds = list('sound/weapons/punch1.ogg',
|
||||
'sound/weapons/punch2.ogg',
|
||||
'sound/weapons/punch3.ogg',
|
||||
'sound/weapons/punch4.ogg')
|
||||
|
||||
/datum/beepsky_fashion/pirate
|
||||
obj_icon_state = "pirate"
|
||||
name = "Beepsbeard the Pirate"
|
||||
desc = "Sailor of the seven seas, all sea-faring bots fear the one known as Beepsbeard."
|
||||
capture_one = "BOT is making CRIMINAL walk the plank!"
|
||||
capture_two = "BOT is making you walk the plank!"
|
||||
infraction = "Enemy vessel spotted with threat level THREAT_LEVEL!"
|
||||
attack_one = "BOT strikes CRIMINAL with his cutlass!"
|
||||
attack_two = "BOT strikes you with his cutlass!"
|
||||
patrol_emote = "Searching for enemy vessels to board."
|
||||
patrol_fail_emote = "No way to engage enemy vessels. Rebooting."
|
||||
arrest_texts = list("Boarding", "Sinking")
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL vessel CRIMINAL in LOCATION."
|
||||
stun_sounds = list('sound/weapons/bladeslice.ogg')
|
||||
|
||||
/datum/beepsky_fashion/engineer
|
||||
obj_icon_state = "engineer"
|
||||
name = "Chief Engineer Beepsky"
|
||||
desc = "He fixes criminals with a wrench to the face."
|
||||
capture_one = "BOT is tying CRIMINAL up!"
|
||||
capture_two = "BOT is tying you up!"
|
||||
infraction = "Structural integrity issue spotted with threat level THREAT_LEVEL"
|
||||
attack_one = "BOT strikes CRIMINAL with his wrench!"
|
||||
attack_two = "BOT strikes you with his wrench!"
|
||||
arrest_texts = list("Fixing", "Repairing")
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL structural issue in LOCATION"
|
||||
stun_sounds = list('sound/weapons/genhit.ogg')
|
||||
|
||||
/datum/beepsky_fashion/tophat
|
||||
obj_icon_state = "tophat"
|
||||
name = "Fancy Beepsky"
|
||||
desc = "It's a secbot, wearing a top hat! How fancy."
|
||||
|
||||
/datum/beepsky_fashion/fedora
|
||||
obj_icon_state = "fedora"
|
||||
name = "Fedorasky"
|
||||
desc = "It's a secbot, wearing a fedora!"
|
||||
|
||||
/datum/beepsky_fashion/sombrero
|
||||
obj_icon_state = "sombrero"
|
||||
name = "Sombrerosky"
|
||||
desc = "A secbot wearing a sombrero. Truly, a hombre to all."
|
||||
|
||||
/datum/beepsky_fashion/santa
|
||||
obj_icon_state = "santa"
|
||||
name = "Saint Beepsky"
|
||||
desc = "Have you been a level 7 infraction this holiday season?"
|
||||
capture_one = "BOT is tying CRIMINAL up with fairy lights!"
|
||||
capture_two = "BOT is tying you up with fairy lights!"
|
||||
infraction = "Level THREAT_LEVEL threat to holiday cheer spotted!"
|
||||
attack_one = "BOT crushes CRIMINAL with their holiday spirit!"
|
||||
attack_two = "BOT crushes you with their holiday spirit!"
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL threat to holiday cheer in LOCATION"
|
||||
|
||||
@@ -324,6 +324,13 @@
|
||||
result = /obj/item/toy/sword/cx
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/catgirlplushie
|
||||
name = "Catgirl Plushie"
|
||||
reqs = list(/obj/item/toy/plush/hairball = 3)
|
||||
result = /obj/item/toy/plush/catgirl
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
|
||||
////////////
|
||||
//Unsorted//
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
|
||||
/datum/datacore/proc/manifest()
|
||||
for(var/mob/dead/new_player/N in GLOB.player_list)
|
||||
if(!N?.client)
|
||||
continue
|
||||
if(N.new_character)
|
||||
log_manifest(N.ckey,N.new_character.mind,N.new_character)
|
||||
if(ishuman(N.new_character))
|
||||
|
||||
+6
-6
@@ -131,9 +131,9 @@
|
||||
L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color)
|
||||
L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)
|
||||
L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color)
|
||||
L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"])
|
||||
L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"])
|
||||
L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"])
|
||||
L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"], 6)
|
||||
L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"], 6)
|
||||
L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"], 6)
|
||||
if(!GLOB.mam_tails_list.len)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list)
|
||||
L[DNA_MUTANTTAIL_BLOCK] = construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
|
||||
@@ -239,11 +239,11 @@
|
||||
if(DNA_HAIR_STYLE_BLOCK)
|
||||
setblock(uni_identity, blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len))
|
||||
if(DNA_COLOR_ONE_BLOCK)
|
||||
sanitize_hexcolor(features["mcolor"])
|
||||
sanitize_hexcolor(features["mcolor"], 6)
|
||||
if(DNA_COLOR_TWO_BLOCK)
|
||||
sanitize_hexcolor(features["mcolor2"])
|
||||
sanitize_hexcolor(features["mcolor2"], 6)
|
||||
if(DNA_COLOR_THREE_BLOCK)
|
||||
sanitize_hexcolor(features["mcolor3"])
|
||||
sanitize_hexcolor(features["mcolor3"], 6)
|
||||
if(DNA_MUTANTTAIL_BLOCK)
|
||||
construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
|
||||
if(DNA_MUTANTEAR_BLOCK)
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
corgI.color = obj_color
|
||||
return corgI
|
||||
|
||||
|
||||
/datum/dog_fashion/head
|
||||
icon_file = 'icons/mob/corgi_head.dmi'
|
||||
|
||||
@@ -53,7 +52,6 @@
|
||||
name = "Sous chef REAL_NAME"
|
||||
desc = "Your food will be taste-tested. All of it."
|
||||
|
||||
|
||||
/datum/dog_fashion/head/captain
|
||||
name = "Captain REAL_NAME"
|
||||
desc = "Probably better than the last captain."
|
||||
|
||||
@@ -196,3 +196,7 @@
|
||||
description = "<span class='nicegreen'>That work of art was so great it made me believe in the goodness of humanity. Says a lot in a place like this.</span>\n"
|
||||
mood_change = 4
|
||||
timeout = 4 MINUTES
|
||||
|
||||
/datum/mood_event/cleared_stomach
|
||||
description = "<span class='nicegreen'>Feels nice to get that out of the way!</span>\n"
|
||||
mood_change = 3
|
||||
|
||||
@@ -152,6 +152,11 @@
|
||||
user.visible_message("<span class='notice'>[user] licks the wounds on [victim]'s [limb.name].</span>", "<span class='notice'>You lick some of the wounds on [victim]'s [limb.name]</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='green'>[user] licks the wounds on your [limb.name]!</span")
|
||||
blood_flow -= 0.5
|
||||
if(isinsect(victim) || iscatperson(victim) || ismammal(victim) || isdwarf(victim) || ismonkey(victim)) // Yep you can lick monkeys.
|
||||
user.reagents.add_reagent(/datum/reagent/hairball, 2)
|
||||
|
||||
else if(ishumanbasic(victim) || isflyperson(victim) || islizard(victim) || isdullahan(victim))
|
||||
user.reagents.add_reagent(/datum/reagent/hairball, 1)
|
||||
|
||||
if(blood_flow > minimum_flow)
|
||||
try_handling(user)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// To be removed on step_ conversion
|
||||
// All this work to prevent a second bump
|
||||
/atom/movable/Move(atom/newloc, direct=0)
|
||||
set waitfor = FALSE //n o
|
||||
. = FALSE
|
||||
if(!newloc || newloc == loc)
|
||||
return
|
||||
@@ -52,6 +53,7 @@
|
||||
////////////////////////////////////////
|
||||
|
||||
/atom/movable/Move(atom/newloc, direct)
|
||||
set waitfor = FALSE //n o
|
||||
var/atom/movable/pullee = pulling
|
||||
var/turf/T = loc
|
||||
if(!moving_from_pull)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
resistance_flags = FLAMMABLE
|
||||
var/list/squeak_override //Weighted list; If you want your plush to have different squeak sounds use this
|
||||
var/stuffed = TRUE //If the plushie has stuffing in it
|
||||
var/unstuffable = FALSE //for plushies that can't be stuffed
|
||||
var/obj/item/grenade/grenade //You can remove the stuffing from a plushie and add a grenade to it for *nefarious uses*
|
||||
//--love ~<3--
|
||||
gender = NEUTER
|
||||
@@ -174,6 +175,9 @@
|
||||
/obj/item/toy/plush/attackby(obj/item/I, mob/living/user, params)
|
||||
if(I.get_sharpness())
|
||||
if(!grenade)
|
||||
if(unstuffable)
|
||||
to_chat(user, "<span class='notice'>Nothing to do here.</span>")
|
||||
return
|
||||
if(!stuffed)
|
||||
to_chat(user, "<span class='warning'>You already murdered it!</span>")
|
||||
return
|
||||
@@ -187,6 +191,13 @@
|
||||
grenade = null
|
||||
return
|
||||
if(istype(I, /obj/item/grenade))
|
||||
if(unstuffable)
|
||||
to_chat(user, "<span class='warning'>No... you should destroy it now!</span>")
|
||||
sleep(10)
|
||||
if(QDELETED(user) || QDELETED(src))
|
||||
return
|
||||
SEND_SOUND(user, 'sound/weapons/armbomb.ogg')
|
||||
return
|
||||
if(stuffed)
|
||||
to_chat(user, "<span class='warning'>You need to remove some stuffing first!</span>")
|
||||
return
|
||||
@@ -743,3 +754,14 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
|
||||
attack_verb = list("headbutt", "scritched", "bit")
|
||||
squeak_override = list('modular_citadel/sound/voice/nya.ogg' = 1)
|
||||
can_random_spawn = FALSE
|
||||
|
||||
|
||||
/obj/item/toy/plush/hairball
|
||||
name = "Hairball"
|
||||
desc = "A bundle of undigested fibers and scales. Yuck."
|
||||
icon_state = "Hairball"
|
||||
unstuffable = TRUE
|
||||
young = TRUE // Your own mouth-baby.
|
||||
squeak_override = list('sound/misc/splort.ogg'=1)
|
||||
attack_verb = list("sploshed", "splorted", "slushed")
|
||||
can_random_spawn = FALSE
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
linked_minds |= user.mind
|
||||
|
||||
update_icon()
|
||||
float(linked_minds.len)
|
||||
INVOKE_ASYNC(src, /atom/movable.proc/float, linked_minds.len)
|
||||
if(linked_minds.len)
|
||||
START_PROCESSING(SSobj, src)
|
||||
set_light(lit_luminosity)
|
||||
|
||||
@@ -863,7 +863,7 @@
|
||||
if(jobban_isbanned(M, ROLE_TRAITOR) || isbanned_dept)
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=traitor;jobban4=[REF(M)]'><font color=red>Traitor</font></a></td>"
|
||||
else
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];jobban3=traitor;jobban4=[REF(M)]'>Traitor</a></td>"
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=traitor;jobban4=[REF(M)]'>Traitor</a></td>"
|
||||
|
||||
//Changeling
|
||||
if(jobban_isbanned(M, ROLE_CHANGELING) || isbanned_dept)
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
var/datum/changelingprofile/first_prof = null
|
||||
var/dna_max = 6 //How many extra DNA strands the changeling can store for transformation.
|
||||
var/absorbedcount = 0
|
||||
/// did we get succed by another changeling
|
||||
var/hostile_absorbed = FALSE
|
||||
var/trueabsorbs = 0//dna gained using absorb, not dna sting
|
||||
var/chem_charges = 20
|
||||
var/chem_storage = 75
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
|
||||
|
||||
var/datum/antagonist/changeling/target_ling = target.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(target_ling)//If the target was a changeling, suck out their extra juice and objective points!
|
||||
if(target_ling && !target_ling.hostile_absorbed)//If the target was a changeling, suck out their extra juice and objective points!
|
||||
to_chat(user, "<span class='boldnotice'>[target] was one of us. We have absorbed their power.</span>")
|
||||
target_ling.remove_changeling_powers()
|
||||
changeling.geneticpoints += round(target_ling.geneticpoints/2)
|
||||
@@ -102,6 +102,7 @@
|
||||
changeling.chem_storage += round(target_ling.chem_storage/2)
|
||||
changeling.chem_charges += min(target_ling.chem_charges, changeling.chem_storage)
|
||||
target_ling.chem_charges = 0
|
||||
target_ling.hostile_absorbed = TRUE
|
||||
target_ling.chem_storage = 0
|
||||
changeling.absorbedcount += (target_ling.absorbedcount)
|
||||
target_ling.stored_profiles.len = 1
|
||||
|
||||
@@ -36,9 +36,10 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(user, CHANGELING_DRAIN) || ((user.stat != DEAD) && !(HAS_TRAIT(user, TRAIT_DEATHCOMA))))
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(!changeling)
|
||||
return FALSE
|
||||
if(changeling.hostile_absorbed || ((user.stat != DEAD) && !(HAS_TRAIT(user, TRAIT_DEATHCOMA))))
|
||||
changeling.purchasedpowers -= src
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
if(stasis)
|
||||
return
|
||||
if(revealed && essence <= 0)
|
||||
death()
|
||||
INVOKE_ASYNC(src, .proc/death)
|
||||
if(unreveal_time && world.time >= unreveal_time)
|
||||
unreveal_time = 0
|
||||
revealed = FALSE
|
||||
|
||||
@@ -43,6 +43,12 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
var/list/dummy = get_gases()
|
||||
for(var/gas in dummy)
|
||||
dummy[gas] = get_moles(gas)
|
||||
dummy["TEMP"] = return_temperature()
|
||||
dummy["PRESSURE"] = return_pressure()
|
||||
dummy["HEAT CAPACITY"] = heat_capacity()
|
||||
dummy["TOTAL MOLES"] = total_moles()
|
||||
dummy["VOLUME"] = return_volume()
|
||||
dummy["THERMAL ENERGY"] = thermal_energy()
|
||||
return debug_variable("gases (READ ONLY)", dummy, 0, src)
|
||||
|
||||
/datum/gas_mixture/vv_get_dropdown()
|
||||
|
||||
@@ -83,24 +83,24 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/gender = MALE //gender of character (well duh)
|
||||
var/age = 30 //age of character
|
||||
var/underwear = "Nude" //underwear type
|
||||
var/undie_color = "FFF"
|
||||
var/undie_color = "FFFFFF"
|
||||
var/undershirt = "Nude" //undershirt type
|
||||
var/shirt_color = "FFF"
|
||||
var/shirt_color = "FFFFFF"
|
||||
var/socks = "Nude" //socks type
|
||||
var/socks_color = "FFF"
|
||||
var/socks_color = "FFFFFF"
|
||||
var/backbag = DBACKPACK //backpack type
|
||||
var/jumpsuit_style = PREF_SUIT //suit/skirt
|
||||
var/hair_style = "Bald" //Hair type
|
||||
var/hair_color = "000" //Hair color
|
||||
var/hair_color = "000000" //Hair color
|
||||
var/facial_hair_style = "Shaved" //Face hair type
|
||||
var/facial_hair_color = "000" //Facial hair color
|
||||
var/facial_hair_color = "000000" //Facial hair color
|
||||
var/skin_tone = "caucasian1" //Skin color
|
||||
var/use_custom_skin_tone = FALSE
|
||||
var/eye_color = "000" //Eye color
|
||||
var/eye_color = "000000" //Eye color
|
||||
var/datum/species/pref_species = new /datum/species/human() //Mutant race
|
||||
var/list/features = list("mcolor" = "FFF",
|
||||
"mcolor2" = "FFF",
|
||||
"mcolor3" = "FFF",
|
||||
var/list/features = list("mcolor" = "FFFFFF",
|
||||
"mcolor2" = "FFFFFF",
|
||||
"mcolor3" = "FFFFFF",
|
||||
"tail_lizard" = "Smooth",
|
||||
"tail_human" = "None",
|
||||
"snout" = "Round",
|
||||
@@ -131,23 +131,23 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
"cock_shape" = DEF_COCK_SHAPE,
|
||||
"cock_length" = COCK_SIZE_DEF,
|
||||
"cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF,
|
||||
"cock_color" = "fff",
|
||||
"cock_color" = "ffffff",
|
||||
"cock_taur" = FALSE,
|
||||
"has_balls" = FALSE,
|
||||
"balls_color" = "fff",
|
||||
"balls_color" = "ffffff",
|
||||
"balls_shape" = DEF_BALLS_SHAPE,
|
||||
"balls_size" = BALLS_SIZE_DEF,
|
||||
"balls_cum_rate" = CUM_RATE,
|
||||
"balls_cum_mult" = CUM_RATE_MULT,
|
||||
"balls_efficiency" = CUM_EFFICIENCY,
|
||||
"has_breasts" = FALSE,
|
||||
"breasts_color" = "fff",
|
||||
"breasts_color" = "ffffff",
|
||||
"breasts_size" = BREASTS_SIZE_DEF,
|
||||
"breasts_shape" = DEF_BREASTS_SHAPE,
|
||||
"breasts_producing" = FALSE,
|
||||
"has_vag" = FALSE,
|
||||
"vag_shape" = DEF_VAGINA_SHAPE,
|
||||
"vag_color" = "fff",
|
||||
"vag_color" = "ffffff",
|
||||
"has_womb" = FALSE,
|
||||
"balls_visibility" = GEN_VISIBLE_NO_UNDIES,
|
||||
"breasts_visibility"= GEN_VISIBLE_NO_UNDIES,
|
||||
@@ -1707,7 +1707,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("hair")
|
||||
var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference","#"+hair_color) as color|null
|
||||
if(new_hair)
|
||||
hair_color = sanitize_hexcolor(new_hair)
|
||||
hair_color = sanitize_hexcolor(new_hair, 6)
|
||||
|
||||
if("hair_style")
|
||||
var/new_hair_style
|
||||
@@ -1724,7 +1724,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("facial")
|
||||
var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference","#"+facial_hair_color) as color|null
|
||||
if(new_facial)
|
||||
facial_hair_color = sanitize_hexcolor(new_facial)
|
||||
facial_hair_color = sanitize_hexcolor(new_facial, 6)
|
||||
|
||||
if("facial_hair_style")
|
||||
var/new_facial_hair_style
|
||||
@@ -1749,7 +1749,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("undie_color")
|
||||
var/n_undie_color = input(user, "Choose your underwear's color.", "Character Preference", "#[undie_color]") as color|null
|
||||
if(n_undie_color)
|
||||
undie_color = sanitize_hexcolor(n_undie_color)
|
||||
undie_color = sanitize_hexcolor(n_undie_color, 6)
|
||||
|
||||
if("undershirt")
|
||||
var/new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in GLOB.undershirt_list
|
||||
@@ -1759,7 +1759,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("shirt_color")
|
||||
var/n_shirt_color = input(user, "Choose your undershirt's color.", "Character Preference", "#[shirt_color]") as color|null
|
||||
if(n_shirt_color)
|
||||
shirt_color = sanitize_hexcolor(n_shirt_color)
|
||||
shirt_color = sanitize_hexcolor(n_shirt_color, 6)
|
||||
|
||||
if("socks")
|
||||
var/new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in GLOB.socks_list
|
||||
@@ -1769,12 +1769,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("socks_color")
|
||||
var/n_socks_color = input(user, "Choose your socks' color.", "Character Preference", "#[socks_color]") as color|null
|
||||
if(n_socks_color)
|
||||
socks_color = sanitize_hexcolor(n_socks_color)
|
||||
socks_color = sanitize_hexcolor(n_socks_color, 6)
|
||||
|
||||
if("eyes")
|
||||
var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference","#"+eye_color) as color|null
|
||||
if(new_eyes)
|
||||
eye_color = sanitize_hexcolor(new_eyes)
|
||||
eye_color = sanitize_hexcolor(new_eyes, 6)
|
||||
|
||||
if("species")
|
||||
var/result = input(user, "Select a species", "Species Selection") as null|anything in GLOB.roundstart_race_names
|
||||
@@ -1798,11 +1798,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
//Now that we changed our species, we must verify that the mutant colour is still allowed.
|
||||
var/temp_hsv = RGBtoHSV(features["mcolor"])
|
||||
if(features["mcolor"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
|
||||
if(features["mcolor"] == "#000000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
|
||||
features["mcolor"] = pref_species.default_color
|
||||
if(features["mcolor2"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
|
||||
if(features["mcolor2"] == "#000000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
|
||||
features["mcolor2"] = pref_species.default_color
|
||||
if(features["mcolor3"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
|
||||
if(features["mcolor3"] == "#000000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
|
||||
features["mcolor3"] = pref_species.default_color
|
||||
|
||||
if("custom_species")
|
||||
@@ -1819,7 +1819,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_mutantcolor == "#000000")
|
||||
features["mcolor"] = pref_species.default_color
|
||||
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) // mutantcolors must be bright, but only if they affect the skin
|
||||
features["mcolor"] = sanitize_hexcolor(new_mutantcolor)
|
||||
features["mcolor"] = sanitize_hexcolor(new_mutantcolor, 6)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -1830,7 +1830,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_mutantcolor == "#000000")
|
||||
features["mcolor2"] = pref_species.default_color
|
||||
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) // mutantcolors must be bright, but only if they affect the skin
|
||||
features["mcolor2"] = sanitize_hexcolor(new_mutantcolor)
|
||||
features["mcolor2"] = sanitize_hexcolor(new_mutantcolor, 6)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -1841,7 +1841,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_mutantcolor == "#000000")
|
||||
features["mcolor3"] = pref_species.default_color
|
||||
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) // mutantcolors must be bright, but only if they affect the skin
|
||||
features["mcolor3"] = sanitize_hexcolor(new_mutantcolor)
|
||||
features["mcolor3"] = sanitize_hexcolor(new_mutantcolor, 6)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -1969,7 +1969,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if (new_horn_color == "#000000")
|
||||
features["horns_color"] = "85615A"
|
||||
else
|
||||
features["horns_color"] = sanitize_hexcolor(new_horn_color)
|
||||
features["horns_color"] = sanitize_hexcolor(new_horn_color, 6)
|
||||
|
||||
if("wings")
|
||||
var/new_wings
|
||||
@@ -1983,7 +1983,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if (new_wing_color == "#000000")
|
||||
features["wings_color"] = "#FFFFFF"
|
||||
else
|
||||
features["wings_color"] = sanitize_hexcolor(new_wing_color)
|
||||
features["wings_color"] = sanitize_hexcolor(new_wing_color, 6)
|
||||
|
||||
if("frills")
|
||||
var/new_frills
|
||||
@@ -2157,7 +2157,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_cockcolor == "#000000")
|
||||
features["cock_color"] = pref_species.default_color
|
||||
else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["cock_color"] = sanitize_hexcolor(new_cockcolor)
|
||||
features["cock_color"] = sanitize_hexcolor(new_cockcolor, 6)
|
||||
else
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -2197,7 +2197,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_ballscolor == "#000000")
|
||||
features["balls_color"] = pref_species.default_color
|
||||
else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["balls_color"] = sanitize_hexcolor(new_ballscolor)
|
||||
features["balls_color"] = sanitize_hexcolor(new_ballscolor, 6)
|
||||
else
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -2224,7 +2224,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_breasts_color == "#000000")
|
||||
features["breasts_color"] = pref_species.default_color
|
||||
else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["breasts_color"] = sanitize_hexcolor(new_breasts_color)
|
||||
features["breasts_color"] = sanitize_hexcolor(new_breasts_color, 6)
|
||||
else
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -2246,7 +2246,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_vagcolor == "#000000")
|
||||
features["vag_color"] = pref_species.default_color
|
||||
else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["vag_color"] = sanitize_hexcolor(new_vagcolor)
|
||||
features["vag_color"] = sanitize_hexcolor(new_vagcolor, 6)
|
||||
else
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
|
||||
@@ -224,6 +224,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
var/needs_update = savefile_needs_update(S)
|
||||
if(needs_update == -2) //fatal, can't load any data
|
||||
return 0
|
||||
|
||||
. = TRUE
|
||||
|
||||
//general preferences
|
||||
S["ooccolor"] >> ooccolor
|
||||
@@ -440,6 +442,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
if(needs_update == -2) //fatal, can't load any data
|
||||
return 0
|
||||
|
||||
. = TRUE
|
||||
|
||||
//Species
|
||||
var/species_id
|
||||
S["species"] >> species_id
|
||||
@@ -632,14 +636,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_list)
|
||||
underwear = sanitize_inlist(underwear, GLOB.underwear_list)
|
||||
undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list)
|
||||
undie_color = sanitize_hexcolor(undie_color, 3, FALSE, initial(undie_color))
|
||||
shirt_color = sanitize_hexcolor(shirt_color, 3, FALSE, initial(shirt_color))
|
||||
undie_color = sanitize_hexcolor(undie_color, 6, FALSE, initial(undie_color))
|
||||
shirt_color = sanitize_hexcolor(shirt_color, 6, FALSE, initial(shirt_color))
|
||||
socks = sanitize_inlist(socks, GLOB.socks_list)
|
||||
socks_color = sanitize_hexcolor(socks_color, 3, FALSE, initial(socks_color))
|
||||
socks_color = sanitize_hexcolor(socks_color, 6, FALSE, initial(socks_color))
|
||||
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
|
||||
hair_color = sanitize_hexcolor(hair_color, 3, 0)
|
||||
facial_hair_color = sanitize_hexcolor(facial_hair_color, 3, 0)
|
||||
eye_color = sanitize_hexcolor(eye_color, 3, 0)
|
||||
hair_color = sanitize_hexcolor(hair_color, 6, FALSE)
|
||||
facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE)
|
||||
eye_color = sanitize_hexcolor(eye_color, 6, FALSE)
|
||||
|
||||
var/static/allow_custom_skintones
|
||||
if(isnull(allow_custom_skintones))
|
||||
@@ -650,12 +654,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
else
|
||||
skin_tone = sanitize_inlist(skin_tone, GLOB.skin_tones - GLOB.nonstandard_skin_tones, initial(skin_tone))
|
||||
|
||||
features["horns_color"] = sanitize_hexcolor(features["horns_color"], 3, FALSE, "85615a")
|
||||
features["wings_color"] = sanitize_hexcolor(features["wings_color"], 3, FALSE, "FFFFFF")
|
||||
features["horns_color"] = sanitize_hexcolor(features["horns_color"], 6, FALSE, "85615a")
|
||||
features["wings_color"] = sanitize_hexcolor(features["wings_color"], 6, FALSE, "FFFFFF")
|
||||
backbag = sanitize_inlist(backbag, GLOB.backbaglist, initial(backbag))
|
||||
jumpsuit_style = sanitize_inlist(jumpsuit_style, GLOB.jumpsuitlist, initial(jumpsuit_style))
|
||||
uplink_spawn_loc = sanitize_inlist(uplink_spawn_loc, GLOB.uplink_spawn_loc_list, initial(uplink_spawn_loc))
|
||||
features["mcolor"] = sanitize_hexcolor(features["mcolor"], 3, 0)
|
||||
features["mcolor"] = sanitize_hexcolor(features["mcolor"], 6, FALSE)
|
||||
features["tail_lizard"] = sanitize_inlist(features["tail_lizard"], GLOB.tails_list_lizard)
|
||||
features["tail_human"] = sanitize_inlist(features["tail_human"], GLOB.tails_list_human)
|
||||
features["snout"] = sanitize_inlist(features["snout"], GLOB.snouts_list)
|
||||
@@ -699,10 +703,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
features["cock_shape"] = sanitize_inlist(features["cock_shape"], GLOB.cock_shapes_list, DEF_COCK_SHAPE)
|
||||
features["balls_shape"] = sanitize_inlist(features["balls_shape"], GLOB.balls_shapes_list, DEF_BALLS_SHAPE)
|
||||
features["vag_shape"] = sanitize_inlist(features["vag_shape"], GLOB.vagina_shapes_list, DEF_VAGINA_SHAPE)
|
||||
features["breasts_color"] = sanitize_hexcolor(features["breasts_color"], 3, FALSE, "FFF")
|
||||
features["cock_color"] = sanitize_hexcolor(features["cock_color"], 3, FALSE, "FFF")
|
||||
features["balls_color"] = sanitize_hexcolor(features["balls_color"], 3, FALSE, "FFF")
|
||||
features["vag_color"] = sanitize_hexcolor(features["vag_color"], 3, FALSE, "FFF")
|
||||
features["breasts_color"] = sanitize_hexcolor(features["breasts_color"], 6, FALSE, "FFFFFF")
|
||||
features["cock_color"] = sanitize_hexcolor(features["cock_color"], 6, FALSE, "FFFFFF")
|
||||
features["balls_color"] = sanitize_hexcolor(features["balls_color"], 6, FALSE, "FFFFFF")
|
||||
features["vag_color"] = sanitize_hexcolor(features["vag_color"], 6, FALSE, "FFFFFF")
|
||||
features["breasts_visibility"] = sanitize_inlist(features["breasts_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["cock_visibility"] = sanitize_inlist(features["cock_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["balls_visibility"] = sanitize_inlist(features["balls_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
var/blockTracking = 0 //For AI tracking
|
||||
var/can_toggle = null
|
||||
dynamic_hair_suffix = "+generic"
|
||||
var/datum/beepsky_fashion/beepsky_fashion //the associated datum for applying this to a secbot
|
||||
|
||||
/obj/item/clothing/head/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
icon_state = "chef"
|
||||
item_state = "chef"
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/chef
|
||||
beepsky_fashion = /datum/beepsky_fashion/chef
|
||||
|
||||
/obj/item/clothing/head/collectable/paper
|
||||
name = "collectable paper hat"
|
||||
@@ -42,6 +44,8 @@
|
||||
icon_state = "tophat"
|
||||
item_state = "that"
|
||||
|
||||
beepsky_fashion = /datum/beepsky_fashion/tophat
|
||||
|
||||
/obj/item/clothing/head/collectable/captain
|
||||
name = "collectable captain's hat"
|
||||
desc = "A collectable hat that'll make you look just like a real comdom!"
|
||||
@@ -49,6 +53,7 @@
|
||||
item_state = "caphat"
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/captain
|
||||
beepsky_fashion = /datum/beepsky_fashion/captain
|
||||
|
||||
/obj/item/clothing/head/collectable/police
|
||||
name = "collectable police officer's hat"
|
||||
@@ -91,6 +96,7 @@
|
||||
item_state = "pirate"
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/pirate
|
||||
beepsky_fashion = /datum/beepsky_fashion/pirate
|
||||
|
||||
/obj/item/clothing/head/collectable/kitty
|
||||
name = "collectable kitty ears"
|
||||
@@ -100,6 +106,7 @@
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/kitty
|
||||
beepsky_fashion = /datum/beepsky_fashion/cat
|
||||
|
||||
/obj/item/clothing/head/collectable/rabbitears
|
||||
name = "collectable rabbit ears"
|
||||
@@ -116,6 +123,7 @@
|
||||
icon_state = "wizard"
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/blue_wizard
|
||||
beepsky_fashion = /datum/beepsky_fashion/wizard
|
||||
|
||||
/obj/item/clothing/head/collectable/hardhat
|
||||
name = "collectable hard hat"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
dynamic_hair_suffix = "+generic"
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head
|
||||
beepsky_fashion = /datum/beepsky_fashion/engineer
|
||||
|
||||
|
||||
/obj/item/clothing/head/hardhat/ComponentInitialize()
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
strip_delay = 10
|
||||
equip_delay_other = 10
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/chef
|
||||
beepsky_fashion = /datum/beepsky_fashion/chef
|
||||
|
||||
/obj/item/clothing/head/chefhat/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] is donning [src]! It looks like [user.p_theyre()] trying to become a chef.</span>")
|
||||
@@ -33,7 +35,9 @@
|
||||
flags_inv = 0
|
||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
strip_delay = 60
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/captain
|
||||
beepsky_fashion = /datum/beepsky_fashion/captain
|
||||
|
||||
//Captain: This is no longer space-worthy
|
||||
/obj/item/clothing/head/caphat/parade
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
desc = "It's an amish looking hat."
|
||||
icon_state = "tophat"
|
||||
item_state = "that"
|
||||
dog_fashion = /datum/dog_fashion/head
|
||||
throwforce = 1
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head
|
||||
beepsky_fashion = /datum/beepsky_fashion/tophat
|
||||
|
||||
/obj/item/clothing/head/canada
|
||||
name = "striped red tophat"
|
||||
desc = "It smells like fresh donut holes. / <i>Il sent comme des trous de beignets frais.</i>"
|
||||
@@ -126,7 +128,9 @@
|
||||
desc = "Yarr."
|
||||
icon_state = "pirate"
|
||||
item_state = "pirate"
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/pirate
|
||||
beepsky_fashion = /datum/beepsky_fashion/pirate
|
||||
|
||||
/obj/item/clothing/head/pirate/captain
|
||||
name = "pirate captain hat"
|
||||
@@ -189,6 +193,8 @@
|
||||
desc = "A really cool hat if you're a mobster. A really lame hat if you're not."
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small
|
||||
|
||||
beepsky_fashion = /datum/beepsky_fashion/fedora
|
||||
|
||||
/obj/item/clothing/head/fedora/suicide_act(mob/user)
|
||||
if(user.gender == FEMALE)
|
||||
return 0
|
||||
@@ -205,7 +211,9 @@
|
||||
item_state = "sombrero"
|
||||
desc = "You can practically taste the fiesta."
|
||||
flags_inv = HIDEHAIR
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/sombrero
|
||||
beepsky_fashion = /datum/beepsky_fashion/sombrero
|
||||
|
||||
/obj/item/clothing/head/sombrero/green
|
||||
name = "green sombrero"
|
||||
@@ -213,6 +221,7 @@
|
||||
item_state = "greensombrero"
|
||||
desc = "As elegant as a dancing cactus."
|
||||
flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
|
||||
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/clothing/head/sombrero/shamebrero
|
||||
@@ -220,6 +229,7 @@
|
||||
icon_state = "shamebrero"
|
||||
item_state = "shamebrero"
|
||||
desc = "Once it's on, it never comes off."
|
||||
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/clothing/head/sombrero/shamebrero/Initialize()
|
||||
@@ -248,7 +258,9 @@
|
||||
item_state = "that"
|
||||
cold_protection = HEAD
|
||||
min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/santa
|
||||
beepsky_fashion = /datum/beepsky_fashion/santa
|
||||
|
||||
/obj/item/clothing/head/jester
|
||||
name = "jester hat"
|
||||
@@ -286,6 +298,8 @@
|
||||
resistance_flags = FIRE_PROOF
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
beepsky_fashion = /datum/beepsky_fashion/king
|
||||
|
||||
/obj/item/clothing/head/crown/fancy
|
||||
name = "magnificent crown"
|
||||
desc = "A crown worn by only the highest emperors of the <s>land</s> space."
|
||||
@@ -391,7 +405,9 @@
|
||||
name = "cowboy hat"
|
||||
desc = "A standard brown cowboy hat, yeehaw."
|
||||
icon_state = "cowboyhat"
|
||||
item_state= "cowboyhat"
|
||||
item_state = "cowboyhat"
|
||||
|
||||
beepsky_fashion = /datum/beepsky_fashion/cowboy
|
||||
|
||||
/obj/item/clothing/head/cowboyhat/black
|
||||
name = "black cowboy hat"
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
flags_cover = HEADCOVERSEYES
|
||||
heat = 1000
|
||||
|
||||
beepsky_fashion = /datum/beepsky_fashion/cake
|
||||
|
||||
/obj/item/clothing/head/hardhat/cakehat/process()
|
||||
var/turf/location = src.loc
|
||||
if(ishuman(location))
|
||||
@@ -131,6 +133,7 @@
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/kitty
|
||||
beepsky_fashion = /datum/beepsky_fashion/cat
|
||||
|
||||
/obj/item/clothing/head/kitty/equipped(mob/living/carbon/human/user, slot)
|
||||
if(ishuman(user) && slot == SLOT_HEAD)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
var/modifies_speech = FALSE
|
||||
var/mask_adjusted = 0
|
||||
var/adjusted_flags = null
|
||||
var/datum/beepsky_fashion/beepsky_fashion //the associated datum for applying this to a secbot
|
||||
|
||||
/obj/item/clothing/mask/attack_self(mob/user)
|
||||
if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
equip_delay_other = 50
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
dog_fashion = /datum/dog_fashion/head/blue_wizard
|
||||
beepsky_fashion = /datum/beepsky_fashion/wizard
|
||||
var/magic_flags = SPELL_WIZARD_HAT
|
||||
|
||||
/obj/item/clothing/head/wizard/ComponentInitialize()
|
||||
|
||||
@@ -163,8 +163,8 @@
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!</B>\n"
|
||||
else
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!</B>\n"
|
||||
for(var/datum/wound/W in BP.wounds)
|
||||
msg += "[W.get_examine_description(user)]\n"
|
||||
for(var/datum/wound/W in BP.wounds)
|
||||
msg += "[W.get_examine_description(user)]\n"
|
||||
|
||||
for(var/X in disabled)
|
||||
var/obj/item/bodypart/BP = X
|
||||
|
||||
@@ -7,7 +7,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/id // if the game needs to manually check your race to do something not included in a proc here, it will use this
|
||||
var/limbs_id //this is used if you want to use a different species limb sprites. Mainly used for angels as they look like humans.
|
||||
var/name // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever
|
||||
var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
|
||||
var/default_color = "#FFFFFF" // if alien colors are disabled, this is the color that will be used by that race
|
||||
|
||||
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
|
||||
var/has_field_of_vision = TRUE
|
||||
@@ -854,10 +854,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/g = (H.dna.features["body_model"] == FEMALE) ? "f" : "m"
|
||||
var/list/colorlist = list()
|
||||
var/husk = HAS_TRAIT(H, TRAIT_HUSK)
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") :ReadRGB("[H.dna.features["mcolor"]]0")
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") :ReadRGB("[H.dna.features["mcolor2"]]0")
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor3"]]0")
|
||||
colorlist += list(0,0,0, hair_alpha)
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor"]]00")
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor2"]]00")
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor3"]]00")
|
||||
colorlist += husk ? list(0, 0, 0) : list(0, 0, 0, hair_alpha)
|
||||
for(var/index in 1 to colorlist.len)
|
||||
colorlist[index] /= 255
|
||||
|
||||
@@ -1031,7 +1031,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
H.apply_overlay(BODY_FRONT_LAYER)
|
||||
H.apply_overlay(HORNS_LAYER)
|
||||
|
||||
|
||||
/*
|
||||
* Equip the outfit required for life. Replaces items currently worn.
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
default_color = "00FF00"
|
||||
species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR,CAN_SCAR)
|
||||
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
|
||||
mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_tail" = "None", "mam_ears" = "None",
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None",
|
||||
"insect_wings" = "None", "insect_fluff" = "None", "mam_snouts" = "None", "taur" = "None", "insect_markings" = "None")
|
||||
attack_verb = "slash"
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR,CAN_SCAR)
|
||||
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BEAST
|
||||
mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None",
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None",
|
||||
"mam_body_markings" = "Husky", "taur" = "None", "horns" = "None", "legs" = "Plantigrade", "meat_type" = "Mammalian")
|
||||
attack_verb = "claw"
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
default_color = "FFFFFF"
|
||||
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR,CAN_SCAR)
|
||||
mutant_bodyparts = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None")
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None")
|
||||
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
|
||||
skinned_type = /obj/item/stack/sheet/animalhide/human
|
||||
disliked_food = GROSS | RAW
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR)
|
||||
mutantlungs = /obj/item/organ/lungs/slime
|
||||
mutant_heart = /obj/item/organ/heart/slime
|
||||
mutant_bodyparts = list("mcolor" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None")
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None")
|
||||
inherent_traits = list(TRAIT_TOXINLOVER)
|
||||
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime
|
||||
gib_types = list(/obj/effect/gibspawner/slime, /obj/effect/gibspawner/slime/bodypartless)
|
||||
@@ -443,7 +443,7 @@
|
||||
default_color = "00FFFF"
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
|
||||
inherent_traits = list(TRAIT_TOXINLOVER)
|
||||
mutant_bodyparts = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None")
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None")
|
||||
say_mod = "says"
|
||||
hair_color = "mutcolor"
|
||||
hair_alpha = 160 //a notch brighter so it blends better.
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
name = "Anthromorphic Plant"
|
||||
id = "podweak"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS)
|
||||
mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
|
||||
limbs_id = "pod"
|
||||
light_nutrition_gain_factor = 3
|
||||
light_bruteheal = -0.2
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD)
|
||||
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
|
||||
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
|
||||
mutant_bodyparts = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None")
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None")
|
||||
exotic_bloodtype = "U"
|
||||
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
|
||||
mutant_heart = /obj/item/organ/heart/vampire
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Splits off into PhysicalLife() and BiologicalLife(). Override those instead of this.
|
||||
*/
|
||||
/mob/living/proc/Life(seconds, times_fired)
|
||||
set waitfor = FALSE // yeah hey we're kind of on a subsystem, no sleeping will be tolerated here!
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
if(mob_transforming)
|
||||
return
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
handle_diginvis() //AI becomes unable to see mob
|
||||
|
||||
if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating
|
||||
float(on = TRUE)
|
||||
INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE)
|
||||
|
||||
if(!loc)
|
||||
return FALSE
|
||||
|
||||
@@ -803,7 +803,7 @@
|
||||
else
|
||||
throw_alert("gravity", /obj/screen/alert/weightless)
|
||||
if(!override && !is_flying())
|
||||
float(!has_gravity)
|
||||
INVOKE_ASYNC(src, /atom/movable.proc/float, !has_gravity)
|
||||
|
||||
/mob/living/float(on)
|
||||
if(throwing)
|
||||
|
||||
@@ -102,6 +102,10 @@
|
||||
var/can_salute = TRUE
|
||||
var/salute_delay = 60 SECONDS
|
||||
|
||||
//emotes/speech stuff
|
||||
var/patrol_emote = "Engaging patrol mode."
|
||||
var/patrol_fail_emote = "Unable to start patrol."
|
||||
|
||||
/mob/living/simple_animal/bot/proc/get_mode()
|
||||
if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player.
|
||||
if(paicard)
|
||||
@@ -611,7 +615,7 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
if(tries >= BOT_STEP_MAX_RETRIES) //Bot is trapped, so stop trying to patrol.
|
||||
auto_patrol = 0
|
||||
tries = 0
|
||||
speak("Unable to start patrol.")
|
||||
speak(patrol_fail_emote)
|
||||
|
||||
return
|
||||
|
||||
@@ -627,7 +631,7 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
return
|
||||
mode = BOT_PATROL
|
||||
else // no patrol target, so need a new one
|
||||
speak("Engaging patrol mode.")
|
||||
speak(patrol_emote)
|
||||
find_patrol_target()
|
||||
tries++
|
||||
return
|
||||
|
||||
@@ -33,6 +33,20 @@
|
||||
var/check_records = TRUE //Does it check security records?
|
||||
var/arrest_type = FALSE //If true, don't handcuff
|
||||
|
||||
var/obj/item/clothing/head/bot_accessory
|
||||
var/datum/beepsky_fashion/stored_fashion
|
||||
|
||||
//emotes (BOT is replaced with bot name, CRIMINAL with criminal name, THREAT_LEVEL with threat level)
|
||||
var/death_emote = "BOT blows apart!"
|
||||
var/capture_one = "BOT is trying to put zipties on CRIMINAL!"
|
||||
var/capture_two = "BOT is trying to put zipties on you!"
|
||||
var/infraction = "Level THREAT_LEVEL infraction alert!"
|
||||
var/taunt = "<b>BOT</b> points at CRIMINAL!"
|
||||
var/attack_one = "BOT has stunned CRIMINAL!"
|
||||
var/attack_two = "BOT has stunned you!"
|
||||
var/list/arrest_texts = list("Detaining", "Arresting")
|
||||
var/arrest_emote = "ARREST_TYPE level THREAT_LEVEL scumbag CRIMINAL in LOCATION."
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/beepsky
|
||||
name = "Officer Beep O'sky"
|
||||
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
|
||||
@@ -49,6 +63,103 @@
|
||||
resize = 0.8
|
||||
update_transform()
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/process_emote(var/emote_type, var/atom/criminal, var/threat, var/arrest = -1, var/location)
|
||||
var/emote = "The continuity of space itself collapses around [src]. You should probably report that to someone higher up."
|
||||
switch(emote_type)
|
||||
if("DEATH")
|
||||
emote = death_emote
|
||||
if("CAPTURE_ONE")
|
||||
emote = capture_one
|
||||
if("CAPTURE_TWO")
|
||||
emote = capture_two
|
||||
if("INFRACTION")
|
||||
emote = infraction
|
||||
if("TAUNT")
|
||||
emote = taunt
|
||||
if("ATTACK_ONE")
|
||||
emote = attack_one
|
||||
if("ATTACK_TWO")
|
||||
emote = attack_two
|
||||
if("ARREST")
|
||||
emote = arrest_emote
|
||||
|
||||
//now replace pieces of the text with the information we have
|
||||
if(emote_type != "TAUNT" && emote_type != "ARREST")
|
||||
emote = replacetext(emote, "BOT", name)
|
||||
else
|
||||
emote = replacetext(emote, "BOT", "<b>[name]</b>") //needs to be bold if its a taunt or an arrest text
|
||||
if(criminal)
|
||||
emote = replacetext(emote, "CRIMINAL", criminal.name)
|
||||
if(num2text(threat)) //because a threat of 0 will be false
|
||||
emote = replacetext(emote, "THREAT_LEVEL", threat)
|
||||
if(arrest > -1)
|
||||
emote = replacetext(emote, "ARREST_TYPE", arrest_texts[arrest + 1])
|
||||
if(location)
|
||||
emote = replacetext(emote, "LOCATION", location)
|
||||
return emote
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/apply_fashion(var/datum/beepsky_fashion/fashion)
|
||||
stored_fashion = new fashion
|
||||
if(stored_fashion.name)
|
||||
name = stored_fashion.name
|
||||
|
||||
if(stored_fashion.desc)
|
||||
desc = stored_fashion.desc
|
||||
|
||||
if(stored_fashion.death_emote)
|
||||
death_emote = stored_fashion.death_emote
|
||||
|
||||
if(stored_fashion.capture_one)
|
||||
capture_one = stored_fashion.capture_one
|
||||
|
||||
if(stored_fashion.capture_two)
|
||||
capture_two = stored_fashion.capture_two
|
||||
|
||||
if(stored_fashion.infraction)
|
||||
infraction = stored_fashion.infraction
|
||||
|
||||
if(stored_fashion.taunt)
|
||||
taunt = stored_fashion.taunt
|
||||
|
||||
if(stored_fashion.attack_one)
|
||||
attack_one = stored_fashion.attack_one
|
||||
|
||||
if(stored_fashion.attack_two)
|
||||
attack_two = stored_fashion.attack_two
|
||||
|
||||
if(stored_fashion.patrol_emote)
|
||||
patrol_emote = stored_fashion.patrol_emote
|
||||
|
||||
if(stored_fashion.patrol_fail_emote)
|
||||
patrol_fail_emote = stored_fashion.patrol_fail_emote
|
||||
|
||||
if(stored_fashion.arrest_texts)
|
||||
arrest_texts = stored_fashion.arrest_texts
|
||||
|
||||
if(stored_fashion.arrest_emote)
|
||||
arrest_emote = stored_fashion.arrest_emote
|
||||
|
||||
regenerate_icons()
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/reset_fashion()
|
||||
bot_accessory.forceMove(get_turf(src))
|
||||
//reset all emotes/sounds and name/desc
|
||||
name = initial(name)
|
||||
desc = initial(desc)
|
||||
death_emote = initial(death_emote)
|
||||
capture_one = initial(capture_one)
|
||||
capture_two = initial(capture_two)
|
||||
infraction = initial(infraction)
|
||||
taunt = initial(taunt)
|
||||
attack_one = initial(attack_one)
|
||||
attack_two = initial(attack_two)
|
||||
arrest_texts = initial(arrest_texts)
|
||||
arrest_emote = initial(arrest_emote)
|
||||
patrol_emote = initial(patrol_emote)
|
||||
arrest_texts = initial(arrest_texts)
|
||||
arrest_emote = initial(arrest_emote)
|
||||
bot_accessory = null
|
||||
regenerate_icons()
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/beepsky/explode()
|
||||
var/atom/Tsec = drop_location()
|
||||
@@ -178,6 +289,11 @@ Auto Patrol: []"},
|
||||
retaliate(H)
|
||||
if(special_retaliate_after_attack(H))
|
||||
return
|
||||
if(H.a_intent == INTENT_HELP && bot_accessory)
|
||||
|
||||
to_chat(H, "<span class='warning'>You knock [bot_accessory] off of [src]'s head!</span>")
|
||||
reset_fashion()
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -185,11 +301,48 @@ Auto Patrol: []"},
|
||||
..()
|
||||
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) // Any intent but harm will heal, so we shouldn't get angry.
|
||||
return
|
||||
if(istype(W, /obj/item/clothing/head))
|
||||
attempt_place_on_head(user, W)
|
||||
return
|
||||
if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
|
||||
retaliate(user)
|
||||
if(special_retaliate_after_attack(user))
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/attempt_place_on_head(mob/user, obj/item/clothing/head/H)
|
||||
if(user && !user.temporarilyRemoveItemFromInventory(H))
|
||||
to_chat(user, "<span class='warning'>\The [H] is stuck to your hand, you cannot put it on [src]'s head!</span>")
|
||||
return
|
||||
if(bot_accessory)
|
||||
to_chat("<span class='warning'>\[src] already has an accessory, and the laws of physics disallow him from wearing a second!</span>")
|
||||
return
|
||||
|
||||
if(H.beepsky_fashion)
|
||||
to_chat(user, "<span class='warning'>You set [H] on [src].</span>")
|
||||
bot_accessory = H
|
||||
H.forceMove(src)
|
||||
apply_fashion(H.beepsky_fashion)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You set [H] on [src]'s head, but it falls off!</span>")
|
||||
H.forceMove(drop_location())
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/regenerate_icons()
|
||||
..()
|
||||
if(bot_accessory)
|
||||
if(!stored_fashion)
|
||||
stored_fashion = new bot_accessory.beepsky_fashion
|
||||
if(!stored_fashion.obj_icon_state)
|
||||
stored_fashion.obj_icon_state = bot_accessory.icon_state
|
||||
if(!stored_fashion.obj_alpha)
|
||||
stored_fashion.obj_alpha = bot_accessory.alpha
|
||||
if(!stored_fashion.obj_color)
|
||||
stored_fashion.obj_color = bot_accessory.color
|
||||
add_overlay(stored_fashion.get_overlay())
|
||||
else
|
||||
if(stored_fashion)
|
||||
cut_overlay(stored_fashion.get_overlay())
|
||||
stored_fashion = null
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(emagged == 2)
|
||||
@@ -233,8 +386,8 @@ Auto Patrol: []"},
|
||||
/mob/living/simple_animal/bot/secbot/proc/cuff(mob/living/carbon/C)
|
||||
mode = BOT_ARREST
|
||||
playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2)
|
||||
C.visible_message("<span class='danger'>[src] is trying to put zipties on [C]!</span>",\
|
||||
"<span class='userdanger'>[src] is trying to put zipties on you!</span>")
|
||||
C.visible_message("<span class='danger'>[process_emote("CAPTURE_ONE", C)]</span>",\
|
||||
"<span class='userdanger'>[process_emote("CAPTURE_TWO", C)]</span>")
|
||||
if(do_after(src, 60, FALSE, C))
|
||||
attempt_handcuff(C)
|
||||
|
||||
@@ -249,16 +402,22 @@ Auto Patrol: []"},
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/C)
|
||||
var/judgement_criteria = judgement_criteria()
|
||||
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
|
||||
icon_state = "secbot-c"
|
||||
addtimer(CALLBACK(src, /atom/.proc/update_icon), 2)
|
||||
var/threat = 5
|
||||
if(ishuman(C))
|
||||
if(stored_fashion)
|
||||
stored_fashion.stun_attack(C)
|
||||
if(stored_fashion.stun_sounds && !stored_fashion.ignore_sound)
|
||||
playsound(src, pick(stored_fashion.stun_sounds), 50, TRUE, -1)
|
||||
else
|
||||
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
|
||||
C.stuttering = 5
|
||||
C.DefaultCombatKnockdown(100)
|
||||
var/mob/living/carbon/human/H = C
|
||||
threat = H.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons))
|
||||
else
|
||||
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
|
||||
C.DefaultCombatKnockdown(100)
|
||||
C.stuttering = 5
|
||||
threat = C.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons))
|
||||
@@ -266,9 +425,9 @@ Auto Patrol: []"},
|
||||
log_combat(src,C,"stunned")
|
||||
if(declare_arrests)
|
||||
var/area/location = get_area(src)
|
||||
speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag <b>[C]</b> in [location].", radio_channel)
|
||||
C.visible_message("<span class='danger'>[src] has stunned [C]!</span>",\
|
||||
"<span class='userdanger'>[src] has stunned you!</span>")
|
||||
speak(process_emote("ARREST", C, threat, arrest_type, location), radio_channel)
|
||||
C.visible_message("<span class='danger'>[process_emote("ATTACK_ONE", C)]</span>",\
|
||||
"<span class='userdanger'>[process_emote("ATTACK_TWO", C)]</span>")
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/handle_automated_action()
|
||||
if(!..())
|
||||
@@ -355,7 +514,6 @@ Auto Patrol: []"},
|
||||
look_for_perp()
|
||||
bot_patrol()
|
||||
|
||||
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/back_to_idle()
|
||||
@@ -391,9 +549,9 @@ Auto Patrol: []"},
|
||||
else if(threatlevel >= 4)
|
||||
target = C
|
||||
oldtarget_name = C.name
|
||||
speak("Level [threatlevel] infraction alert!")
|
||||
speak(process_emote("INFRACTION", target, threatlevel))
|
||||
playsound(loc, pick('sound/voice/beepsky/criminal.ogg', 'sound/voice/beepsky/justice.ogg', 'sound/voice/beepsky/freeze.ogg'), 50, FALSE)
|
||||
visible_message("<b>[src]</b> points at [C.name]!")
|
||||
visible_message(process_emote("TAUNT", target, threatlevel))
|
||||
mode = BOT_HUNT
|
||||
INVOKE_ASYNC(src, .proc/handle_automated_action)
|
||||
break
|
||||
@@ -408,7 +566,7 @@ Auto Patrol: []"},
|
||||
/mob/living/simple_animal/bot/secbot/explode()
|
||||
|
||||
walk_to(src,0)
|
||||
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
|
||||
visible_message("<span class='boldannounce'>[process_emote("DEATH")]</span>")
|
||||
var/atom/Tsec = drop_location()
|
||||
|
||||
var/obj/item/bot_assembly/secbot/Sa = new (Tsec)
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
/obj/structure/leaper_bubble/Initialize()
|
||||
. = ..()
|
||||
float(on = TRUE)
|
||||
INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE)
|
||||
QDEL_IN(src, 100)
|
||||
|
||||
/obj/structure/leaper_bubble/Destroy()
|
||||
|
||||
@@ -932,6 +932,9 @@
|
||||
return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])"
|
||||
|
||||
/obj/machinery/power/apc/proc/update()
|
||||
var/old_light = area.power_light
|
||||
var/old_equip = area.power_equip
|
||||
var/old_environ = area.power_environ
|
||||
if(operating && !shorted && !failure_timer)
|
||||
area.power_light = (lighting > 1)
|
||||
area.power_equip = (equipment > 1)
|
||||
@@ -940,7 +943,8 @@
|
||||
area.power_light = FALSE
|
||||
area.power_equip = FALSE
|
||||
area.power_environ = FALSE
|
||||
area.power_change()
|
||||
if(old_light != area.power_light || old_equip != area.power_equip || old_environ != area.power_environ)
|
||||
area.power_change()
|
||||
|
||||
/obj/machinery/power/apc/proc/can_use(mob/user, loud = 0) //used by attack_hand() and Topic()
|
||||
if(IsAdminGhost(user))
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
var/pixel_move_interrupted = FALSE
|
||||
|
||||
/// Pixels moved per second.
|
||||
var/pixels_per_second = TILES_TO_PIXELS(12.5)
|
||||
var/pixels_per_second = TILES_TO_PIXELS(17.5)
|
||||
/// The number of pixels we increment by. THIS IS NOT SPEED, DO NOT TOUCH THIS UNLESS YOU KNOW WHAT YOU ARE DOING. In general, lower values means more linetrace accuracy up to a point at cost of performance.
|
||||
var/pixel_increment_amount
|
||||
|
||||
|
||||
@@ -2336,3 +2336,53 @@
|
||||
reagent_state = SOLID
|
||||
color = "#E6E6DA"
|
||||
taste_mult = 0
|
||||
|
||||
|
||||
/datum/reagent/hairball
|
||||
name = "Hairball"
|
||||
description = "A bundle of keratinous bits and fibers, not easily digestible."
|
||||
reagent_state = SOLID
|
||||
can_synth = FALSE
|
||||
metabolization_rate = 0.05 * REAGENTS_METABOLISM
|
||||
taste_description = "wet hair"
|
||||
var/amount = 0
|
||||
var/knotted = FALSE
|
||||
|
||||
/datum/reagent/hairball/on_mob_life(mob/living/carbon/M)
|
||||
amount = M.reagents.get_reagent_amount(/datum/reagent/hairball)
|
||||
|
||||
if(amount < 10)
|
||||
if(prob(10))
|
||||
M.losebreath += 1
|
||||
M.emote("cough")
|
||||
to_chat(M, "<span class='notice'>You clear your throat.</span>")
|
||||
else
|
||||
if(!knotted)
|
||||
to_chat(M, "<span class='notice'>You feel a knot in your stomach.</span>")
|
||||
knotted = TRUE
|
||||
|
||||
if(prob(5 + amount * 0.5)) // don't want this to cause too much damage
|
||||
M.losebreath += 2
|
||||
to_chat(M, "<span class='notice'>You feel a knot in your throat.</span>")
|
||||
M.emote("cough")
|
||||
|
||||
else if(prob(amount - 4))
|
||||
to_chat(M, "<span class='warning'>Your stomach feels awfully bloated.</span>")
|
||||
playsound(M,'sound/voice/catpeople/distressed.ogg', 50, FALSE)
|
||||
M.visible_message("<span class='warning'>[M] seems distressed!.</span>", ignored_mobs=M)
|
||||
|
||||
else if(prob(amount - 8))
|
||||
knotted = FALSE
|
||||
playsound(M,'sound/voice/catpeople/puking.ogg', 110, FALSE)
|
||||
M.Immobilize(30)
|
||||
sleep(30) //snowflake but it works, don't wanna proc this
|
||||
if(QDELETED(M) || QDELETED(src)) //this handles race conditions about m or src not existing.
|
||||
return
|
||||
M.visible_message("<span class='warning'>[M] throws up a hairball! Disgusting!</span>", ignored_mobs=M)
|
||||
new /obj/item/toy/plush/hairball(get_turf(M))
|
||||
to_chat(M, "<span class='notice'>Aaaah that's better!</span>")
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "cleared_stomach", /datum/mood_event/cleared_stomach, name)
|
||||
M.reagents.del_reagent(/datum/reagent/hairball)
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
@@ -490,9 +490,9 @@
|
||||
//body marking memes
|
||||
var/list/colorlist = list()
|
||||
colorlist.Cut()
|
||||
colorlist += ReadRGB("[H.dna.features["mcolor"]]0")
|
||||
colorlist += ReadRGB("[H.dna.features["mcolor2"]]0")
|
||||
colorlist += ReadRGB("[H.dna.features["mcolor3"]]0")
|
||||
colorlist += ReadRGB("[H.dna.features["mcolor"]]00")
|
||||
colorlist += ReadRGB("[H.dna.features["mcolor2"]]00")
|
||||
colorlist += ReadRGB("[H.dna.features["mcolor3"]]00")
|
||||
colorlist += list(0,0,0, S.hair_alpha)
|
||||
for(var/index=1, index<=colorlist.len, index++)
|
||||
colorlist[index] = colorlist[index]/255
|
||||
|
||||
Reference in New Issue
Block a user