Chameleon overhaul

This commit is contained in:
Mark van Alphen
2019-05-01 20:59:41 +02:00
parent 3ce39ba6ea
commit e9d39b0d27
33 changed files with 646 additions and 209 deletions
@@ -4123,7 +4123,7 @@
/turf/simulated/floor/plasteel,
/area/awaymission/arrivalblock)
"kG" = (
/obj/item/clothing/shoes/syndigaloshes,
/obj/item/clothing/shoes/chameleon/noslip,
/obj/item/clothing/under/syndicate,
/obj/effect/decal/remains/human{
desc = "This guy seemed to have died in terrible way! Half his remains are dust.";
@@ -13398,7 +13398,7 @@
/area/awaymission/UO71/loot)
"zt" = (
/obj/structure/chair/wood/normal,
/obj/item/clothing/shoes/syndigaloshes,
/obj/item/clothing/shoes/chameleon/noslip,
/turf/simulated/floor/carpet,
/area/awaymission/UO71/loot)
"zu" = (
+4 -4
View File
@@ -8543,7 +8543,7 @@
pixel_y = 3
},
/obj/item/clothing/mask/gas/cyborg,
/obj/item/clothing/mask/gas/voice,
/obj/item/clothing/mask/chameleon,
/obj/item/clothing/mask/balaclava{
pixel_x = 3;
pixel_y = -3
@@ -8729,7 +8729,7 @@
/area/admin)
"uY" = (
/obj/structure/rack,
/obj/item/clothing/under/chameleon/all{
/obj/item/clothing/mask/chameleon{
pixel_x = -3;
pixel_y = 3
},
@@ -9036,7 +9036,7 @@
pixel_y = 3
},
/obj/item/clothing/shoes/centcom,
/obj/item/clothing/shoes/syndigaloshes{
/obj/item/clothing/shoes/chameleon/noslip{
pixel_x = 3;
pixel_y = -3
},
@@ -12275,7 +12275,7 @@
"Hv" = (
/obj/structure/rack,
/obj/item/katana/energy,
/obj/item/clothing/mask/gas/voice/space_ninja,
/obj/item/clothing/mask/gas/space_ninja,
/turf/unsimulated/floor{
icon_state = "engine"
},
+8 -1
View File
@@ -401,4 +401,11 @@
#define GHOST_ORBIT_TRIANGLE "triangle"
#define GHOST_ORBIT_HEXAGON "hexagon"
#define GHOST_ORBIT_SQUARE "square"
#define GHOST_ORBIT_PENTAGON "pentagon"
#define GHOST_ORBIT_PENTAGON "pentagon"
//suit sensors: sensor_mode defines
#define SENSOR_OFF 0
#define SENSOR_LIVING 1
#define SENSOR_VITALS 2
#define SENSOR_COORDS 3
+11 -4
View File
@@ -124,9 +124,13 @@
. += A
//Like typesof() or subtypesof(), but returns a typecache instead of a list
/proc/typecacheof(path, ignore_root_path)
/proc/typecacheof(path, ignore_root_path, only_root_path = FALSE)
if(ispath(path))
var/list/types = ignore_root_path ? subtypesof(path) : typesof(path)
var/list/types = list()
if(only_root_path)
types = list(path)
else
types = ignore_root_path ? subtypesof(path) : typesof(path)
var/list/L = list()
for(var/T in types)
L[T] = TRUE
@@ -140,8 +144,11 @@
L[T] = TRUE
else
for(var/P in pathlist)
for(var/T in typesof(P))
L[T] = TRUE
if(only_root_path)
L[P] = TRUE
else
for(var/T in typesof(P))
L[T] = TRUE
return L
//Removes any null entries from the list
+14
View File
@@ -107,6 +107,7 @@
/datum/action/item_action
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_CONSCIOUS
var/use_itemicon = TRUE
/datum/action/item_action/New(Target, custom_icon, custom_icon_state)
..()
var/obj/item/I = target
@@ -406,6 +407,19 @@
name = "Use [target.name]"
button.name = name
/datum/action/item_action/voice_changer/toggle
name = "Toggle Voice Changer"
/datum/action/item_action/voice_changer/voice
name = "Set Voice"
/datum/action/item_action/voice_changer/voice/Trigger()
if(!IsAvailable())
return FALSE
var/obj/item/voice_changer/V = target
V.set_voice(usr)
// for clothing accessories like holsters
/datum/action/item_action/accessory
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_CONSCIOUS
+8 -1
View File
@@ -25,6 +25,7 @@
var/list/implants = null
var/list/cybernetic_implants = null
var/list/chameleon_extras //extra types for chameleon outfit changes, mostly guns
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for customization depending on client prefs,species etc
@@ -151,4 +152,10 @@
H.r_store.add_fingerprint(H, 1)
if(H.wear_pda)
H.wear_pda.add_fingerprint(H, 1)
return 1
return 1
/datum/outfit/proc/get_chameleon_disguise_info()
var/list/types = list(uniform, suit, back, belt, gloves, shoes, head, mask, l_ear, r_ear, glasses, id, l_pocket, r_pocket, suit_store, r_hand, l_hand, pda)
types += chameleon_extras
listclearnulls(types)
return types
+4 -4
View File
@@ -123,7 +123,7 @@
/datum/outfit/admin/syndicate/spy
name = "Syndicate Spy"
uniform = /obj/item/clothing/under/suit_jacket/really_black
shoes = /obj/item/clothing/shoes/syndigaloshes/black
shoes = /obj/item/clothing/shoes/chameleon/noslip
uplink_uses = 40
id_access = "Syndicate Agent"
@@ -228,7 +228,7 @@
back = /obj/item/storage/backpack
belt = /obj/item/storage/belt/utility/full/multitool
gloves = /obj/item/clothing/gloves/combat
shoes = /obj/item/clothing/shoes/syndigaloshes/black
shoes = /obj/item/clothing/shoes/chameleon/noslip
l_ear = /obj/item/radio/headset/centcom
id = /obj/item/card/id
pda = /obj/item/pda
@@ -990,7 +990,7 @@
suit = /obj/item/clothing/suit/hooded/chaplain_hoodie
back = /obj/item/storage/backpack
gloves = /obj/item/clothing/gloves/combat
shoes = /obj/item/clothing/shoes/syndigaloshes/black
shoes = /obj/item/clothing/shoes/chameleon/noslip
l_ear = /obj/item/radio/headset/syndicate
id = /obj/item/card/id/syndicate
l_hand = /obj/item/twohanded/dualsaber/red
@@ -1021,7 +1021,7 @@
suit = /obj/item/clothing/suit/draculacoat
back = /obj/item/storage/backpack
gloves = /obj/item/clothing/gloves/combat
shoes = /obj/item/clothing/shoes/syndigaloshes/black
shoes = /obj/item/clothing/shoes/chameleon/noslip
l_ear = /obj/item/radio/headset/syndicate
id = /obj/item/card/id
backpack_contents = list(
+14 -14
View File
@@ -1092,20 +1092,19 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
surplus = 35
/datum/uplink_item/stealthy_tools/syndigaloshes
name = "No-Slip Syndicate Shoes"
desc = "These allow you to run on wet floors. They do not work on lubricated surfaces."
name = "No-Slip Chameleon Shoes"
desc = "These shoes will allow the wearer to run on wet floors and slippery objects without falling down. \
They do not work on heavily lubricated surfaces."
reference = "NSSS"
item = /obj/item/clothing/shoes/syndigaloshes
item = /obj/item/clothing/shoes/chameleon/noslip
cost = 2
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_tools/syndigaloshes/nuke
name = "Tactical No-Slip Brown Shoes"
desc = "These allow you to run on wet floors. They do not work on lubricated surfaces, and the maker swears they're better than normal ones, somehow."
reference = "NNSSS"
reference = "TNSSS"
cost = 4 //but they aren't
gamemodes = list(/datum/game_mode/nuclear)
excludefrom = list()
gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_tools/chamsechud
name = "Chameleon Security HUD"
@@ -1146,12 +1145,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/card/id/syndicate
cost = 2
/datum/uplink_item/stealthy_tools/voice_changer
name = "Voice Changer"
desc = "A conspicuous gas mask that mimics the voice named on your identification card. When no identification is worn, the mask will render your voice unrecognisable."
reference = "VC"
item = /obj/item/clothing/mask/gas/voice
cost = 3
/datum/uplink_item/stealthy_tools/chameleon
name = "Chameleon Kit"
desc = "A set of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more! \
Due to budget cuts, the shoes don't provide protection against slipping."
reference = "CHAM"
item = /obj/item/storage/box/syndie_kit/chameleon
cost = 2
/datum/uplink_item/stealthy_tools/chameleon_proj
name = "Chameleon-Projector"
@@ -1210,7 +1210,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/stealthy_tools/clownkit
name = "Honk Brand Infiltration Kit"
desc = "All the tools you need to play the best prank Nanotrasen has ever seen. Includes a voice changer clown mask, magnetic clown shoes, and standard clown outfit, tools, and backpack."
desc = "All the tools you need to play the best prank Nanotrasen has ever seen. Includes a voice changer mask, magnetic clown shoes, and standard clown outfit, tools, and backpack."
reference = "HBIK"
item = /obj/item/storage/backpack/clown/syndie
cost = 6
@@ -140,8 +140,8 @@
/obj/item/suppressor = 4,
/obj/item/clothing/under/chameleon = 2,
/obj/item/stamp/chameleon = 2,
/obj/item/clothing/shoes/syndigaloshes = 5,
/obj/item/clothing/mask/gas/voice = 2,
/obj/item/clothing/shoes/chameleon/noslip = 5,
/obj/item/clothing/mask/chameleon = 2,
/obj/item/dnascrambler = 1,
/obj/item/storage/backpack/satchel_flat = 2,
/obj/item/storage/toolbox/syndicate = 2,
@@ -214,7 +214,7 @@
/obj/item/storage/pill_bottle/zoom = 1,
/obj/item/storage/pill_bottle/random_drug_bottle = 2,
/obj/item/storage/backpack/duffel/syndie/surgery = 1,
/obj/item/clothing/shoes/syndigaloshes = 1,
/obj/item/clothing/shoes/chameleon/noslip = 1,
/obj/item/storage/belt/military = 1,
/obj/item/clothing/under/chameleon = 1,
/obj/item/storage/backpack/satchel_flat = 1,
+6
View File
@@ -600,3 +600,9 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
/obj/item/MouseExited()
deltimer(tip_timer) //delete any in-progress timer if the mouse is moved off the item before it finishes
closeToolTip(usr)
/obj/item/proc/update_slot_icon()
if(!ismob(loc))
return
var/mob/owner = loc
owner.regenerate_icons()
+1 -1
View File
@@ -35,7 +35,7 @@
return
if(H.mind)
span = H.mind.speech_span
if((COMIC in H.mutations) || H.get_int_organ(/obj/item/organ/internal/cyberimp/brain/clown_voice) || istype(H.get_item_by_slot(slot_wear_mask), /obj/item/clothing/mask/gas/voice/clown))
if((COMIC in H.mutations) || H.get_int_organ(/obj/item/organ/internal/cyberimp/brain/clown_voice))
span = "sans"
if(spamcheck)
to_chat(user, "<span class='warning'>\The [src] needs to recharge!</span>")
@@ -397,7 +397,6 @@ var/global/list/default_medbay_channels = list(
var/mob/living/carbon/human/H = M
displayname = H.voice
if(H.voice != real_name)
jobname = "Unknown"
voicemask = TRUE
if(syndiekey && syndiekey.change_voice && connection.frequency == SYND_FREQ)
+44
View File
@@ -0,0 +1,44 @@
/obj/item/voice_changer
name = "voice changer"
desc = "A voice scrambling module."
icon = 'icons/obj/device.dmi'
icon_state = "voice_changer_off"
actions_types = list(/datum/action/item_action/voice_changer/toggle, /datum/action/item_action/voice_changer/voice)
var/obj/item/parent
var/voice
var/active
/obj/item/voice_changer/New()
. = ..()
if(isitem(loc))
parent = loc
parent.actions |= actions
/obj/item/voice_changer/Destroy()
if(isitem(parent))
parent.actions -= actions
return ..()
/obj/item/voice_changer/attack_self(mob/user)
active = !active
icon_state = "voice_changer_[active ? "on" : "off"]"
to_chat(user, "<span class='notice'>You toggle [src] [active ? "on" : "off"].</span>")
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
/obj/item/voice_changer/proc/set_voice(mob/user)
var/chosen_voice = input(user, "What voice would you like to mimic? Leave this empty to use the voice on your ID card.", "Set Voice Changer", voice) as text
if(!chosen_voice)
voice = null
to_chat(user, "<span class='notice'>You are now mimicking the voice on your ID card.</span>")
return
voice = sanitize(copytext(chosen_voice, 1, MAX_MESSAGE_LEN))
to_chat(user, "<span class='notice'>You are now mimicking <b>[voice]</b>.</span>")
@@ -668,4 +668,27 @@
/obj/item/dnainjector/m2h/Initialize()
block = MONKEYBLOCK
..()
/obj/item/dnainjector/comic
name = "DNA-Injector (Comic)"
desc = "Honk!"
datatype = DNA2_BUF_SE
value = 0xFFF
forcedmutation = TRUE
/obj/item/dnainjector/comic/Initialize()
block = COMIC
..()
/obj/item/dnainjector/anticomic
name = "DNA-Injector (Ant-Comic)"
desc = "Honk...?"
datatype = DNA2_BUF_SE
value = 0x001
forcedmutation = TRUE
/obj/item/dnainjector/anticomic/Initialize()
block = COMIC
..()
@@ -112,7 +112,7 @@
..()
new /obj/item/clothing/under/rank/clown(src)
new /obj/item/clothing/shoes/magboots/clown(src)
new /obj/item/clothing/mask/gas/voice/clown(src)
new /obj/item/clothing/mask/chameleon(src)
new /obj/item/radio/headset/headset_service(src)
new /obj/item/pda/clown(src)
new /obj/item/storage/box/survival(src)
@@ -124,6 +124,7 @@
new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(src)
new /obj/item/instrument/bikehorn(src)
new /obj/item/bikehorn(src)
new /obj/item/dnainjector/comic(src)
/obj/item/storage/backpack/mime
name = "Parcel Parceaux"
@@ -170,7 +170,7 @@ var/global/sent_syndicate_infiltration_team = 0
equip_or_collect(new /obj/item/pda(src), slot_in_backpack)
// Other gear
equip_to_slot_or_del(new /obj/item/clothing/shoes/syndigaloshes(src), slot_shoes)
equip_to_slot_or_del(new /obj/item/clothing/shoes/chameleon/noslip(src), slot_shoes)
var/obj/item/card/id/syndicate/W = new(src)
if (flag_mgmt)
+5 -3
View File
@@ -574,8 +574,9 @@ BLIND // can't see anything
"Drask" = 'icons/mob/species/drask/uniform.dmi',
"Grey" = 'icons/mob/species/grey/uniform.dmi'
)
var/has_sensor = 1//For the crew computer 2 = unable to change mode
var/sensor_mode = 0
var/has_sensor = TRUE//For the crew computer 2 = unable to change mode
var/sensor_mode = SENSOR_OFF
var/random_sensor = TRUE
/*
1 = Report living/dead
2 = Report detailed damages
@@ -587,7 +588,8 @@ BLIND // can't see anything
var/basecolor
/obj/item/clothing/under/rank/New()
sensor_mode = pick(0,1,2,3)
if(random_sensor)
sensor_mode = pick(SENSOR_OFF, SENSOR_LIVING, SENSOR_VITALS, SENSOR_COORDS)
..()
/obj/item/clothing/under/Destroy()
-5
View File
@@ -162,11 +162,6 @@
item_state = "sexymime"
burn_state = FLAMMABLE
/obj/item/clothing/mask/gas/death_commando
name = "Death Commando Mask"
icon_state = "death_commando_mask"
item_state = "death_commando_mask"
/obj/item/clothing/mask/gas/cyborg
name = "cyborg visor"
desc = "Beep boop"
-38
View File
@@ -1,38 +0,0 @@
/obj/item/voice_changer
name = "voice changer"
desc = "A voice scrambling module. If you can see this, report it as a bug on the tracker."
var/voice //If set and item is present in mask/suit, this name will be used for the wearer's speech.
var/active
/obj/item/clothing/mask/gas/voice
name = "gas mask"
// desc = "A face-covering mask that can be connected to an air supply. It seems to house some odd electronics."
var/obj/item/voice_changer/changer
burn_state = FIRE_PROOF
/obj/item/clothing/mask/gas/voice/verb/Toggle_Voice_Changer()
set category = "Object"
set src in usr
changer.active = !changer.active
to_chat(usr, "<span class='notice'>You [changer.active ? "enable" : "disable"] the voice-changing module in \the [src].</span>")
/obj/item/clothing/mask/gas/voice/verb/Set_Voice(name as text)
set category = "Object"
set src in usr
var/voice = sanitize(copytext(name,1,MAX_MESSAGE_LEN))
if(!voice || !length(voice)) return
changer.voice = voice
to_chat(usr, "<span class='notice'>You are now mimicking <B>[changer.voice]</B>.</span>")
/obj/item/clothing/mask/gas/voice/New()
..()
changer = new(src)
/obj/item/clothing/mask/gas/voice/clown
name = "clown wig and mask"
desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask."
icon_state = "clown"
item_state = "clown_hat"
flags = BLOCK_GAS_SMOKE_EFFECT | AIRTIGHT | BLOCKHAIR
@@ -1,21 +1,3 @@
/obj/item/clothing/shoes/syndigaloshes
desc = "A pair of brown shoes. They seem to have extra grip."
name = "brown shoes"
icon_state = "brown"
item_state = "brown"
permeability_coefficient = 0.05
flags = NOSLIP
origin_tech = "syndicate=2"
burn_state = FIRE_PROOF
var/list/clothing_choices = list()
silence_steps = 1
/obj/item/clothing/shoes/syndigaloshes/black
name = "black shoes"
icon_state = "black"
item_color = "black"
desc = "A pair of black shoes. They seem to have extra grip."
/obj/item/clothing/shoes/mime
name = "mime shoes"
icon_state = "mime"
@@ -269,14 +269,13 @@
/obj/item/rig_module/voice/New()
..()
voice_holder = new(src)
voice_holder.active = 0
voice_holder.active = FALSE
/obj/item/rig_module/voice/installed()
..()
holder.speech = src
/obj/item/rig_module/voice/engage()
if(!..())
return 0
@@ -287,17 +286,17 @@
switch(choice)
if("Enable")
active = 1
voice_holder.active = 1
active = TRUE
voice_holder.active = TRUE
to_chat(usr, "<font color='blue'>You enable the speech synthesiser.</font>")
if("Disable")
active = 0
voice_holder.active = 0
active = FALSE
voice_holder.active = FALSE
to_chat(usr, "<font color='blue'>You disable the speech synthesiser.</font>")
if("Set Name")
var/raw_choice = sanitize(input(usr, "Please enter a new name.") as text|null, MAX_NAME_LEN)
if(!raw_choice)
return 0
return FALSE
voice_holder.voice = raw_choice
to_chat(usr, "<font color='blue'>You are now mimicking <B>[voice_holder.voice]</B>.</font>")
return 1
+457 -65
View File
@@ -1,86 +1,478 @@
#define EMP_RANDOMISE_TIME 300
/datum/action/chameleon_outfit
name = "Select Chameleon Outfit"
button_icon_state = "chameleon_outfit"
var/list/outfit_options //By default, this list is shared between all instances. It is not static because if it were, subtypes would not be able to have their own. If you ever want to edit it, copy it first.
/datum/action/chameleon_outfit/New()
..()
initialize_outfits()
/datum/action/chameleon_outfit/proc/initialize_outfits()
var/static/list/standard_outfit_options
if(!standard_outfit_options)
standard_outfit_options = list()
for(var/path in subtypesof(/datum/outfit/job))
var/datum/outfit/O = path
standard_outfit_options[initial(O.name)] = path
sortTim(standard_outfit_options, /proc/cmp_text_asc)
outfit_options = standard_outfit_options
/datum/action/chameleon_outfit/Trigger()
return select_outfit(owner)
/datum/action/chameleon_outfit/proc/select_outfit(mob/user)
if(!user || !IsAvailable())
return FALSE
var/selected = input("Select outfit to change into", "Chameleon Outfit") as null|anything in outfit_options
if(!IsAvailable() || QDELETED(src) || QDELETED(user))
return FALSE
var/outfit_type = outfit_options[selected]
if(!outfit_type)
return FALSE
var/datum/outfit/O = new outfit_type()
var/list/outfit_types = O.get_chameleon_disguise_info()
for(var/V in user.chameleon_item_actions)
var/datum/action/item_action/chameleon/change/A = V
var/done = FALSE
for(var/T in outfit_types)
for(var/name in A.chameleon_list)
if(A.chameleon_list[name] == T)
A.update_look(user, T)
outfit_types -= T
done = TRUE
break
if(done)
break
//hardsuit helmets/suit hoods
if(ispath(O.suit, /obj/item/clothing/suit/hooded) && ishuman(user))
var/mob/living/carbon/human/H = user
//make sure they are actually wearing the suit, not just holding it, and that they have a chameleon hat
if(istype(H.wear_suit, /obj/item/clothing/suit/chameleon) && istype(H.head, /obj/item/clothing/head/chameleon))
var/helmet_type
var/obj/item/clothing/suit/hooded/hooded = O.suit
helmet_type = initial(hooded.hoodtype)
if(helmet_type)
var/obj/item/clothing/head/chameleon/hat = H.head
hat.chameleon_action.update_look(user, helmet_type)
qdel(O)
return TRUE
/datum/action/item_action/chameleon/change
name = "Chameleon Change"
var/list/chameleon_blacklist = list() //This is a typecache
var/list/chameleon_list = list()
var/chameleon_type = null
var/chameleon_name = "Item"
var/emp_timer
/datum/action/item_action/chameleon/change/Grant(mob/M)
if(M && (owner != M))
if(!M.chameleon_item_actions)
M.chameleon_item_actions = list(src)
var/datum/action/chameleon_outfit/O = new /datum/action/chameleon_outfit()
O.Grant(M)
else
M.chameleon_item_actions |= src
..()
/datum/action/item_action/chameleon/change/Remove(mob/M)
if(M && (M == owner))
LAZYREMOVE(M.chameleon_item_actions, src)
if(!LAZYLEN(M.chameleon_item_actions))
var/datum/action/chameleon_outfit/O = locate(/datum/action/chameleon_outfit) in M.actions
qdel(O)
..()
/datum/action/item_action/chameleon/change/proc/initialize_disguises()
if(button)
button.name = "Change [chameleon_name] Appearance"
chameleon_blacklist |= typecacheof(target.type)
for(var/V in typesof(chameleon_type))
if(ispath(V) && ispath(V, /obj/item))
var/obj/item/I = V
if(chameleon_blacklist[V] || (initial(I.flags) & ABSTRACT) || !initial(I.icon_state))
continue
var/chameleon_item_name = "[initial(I.name)] ([initial(I.icon_state)])"
chameleon_list[chameleon_item_name] = I
/datum/action/item_action/chameleon/change/proc/select_look(mob/user)
var/obj/item/picked_item
var/picked_name
picked_name = input("Select [chameleon_name] to change into", "Chameleon [chameleon_name]", picked_name) as null|anything in chameleon_list
if(!picked_name)
return
picked_item = chameleon_list[picked_name]
if(!picked_item)
return
update_look(user, picked_item)
/datum/action/item_action/chameleon/change/proc/random_look(mob/user)
var/picked_name = pick(chameleon_list)
// If a user is provided, then this item is in use, and we
// need to update our icons and stuff
if(user)
update_look(user, chameleon_list[picked_name])
// Otherwise, it's likely a random initialisation, so we
// don't have to worry
else
update_item(chameleon_list[picked_name])
/datum/action/item_action/chameleon/change/proc/update_look(mob/user, obj/item/picked_item)
if(isliving(user))
var/mob/living/C = user
if(C.stat != CONSCIOUS)
return
update_item(picked_item)
var/obj/item/thing = target
thing.update_slot_icon()
UpdateButtonIcon()
/datum/action/item_action/chameleon/change/proc/update_item(obj/item/picked_item)
target.name = initial(picked_item.name)
target.desc = initial(picked_item.desc)
target.icon_state = initial(picked_item.icon_state)
if(isitem(target))
var/obj/item/I = target
I.item_state = initial(picked_item.item_state)
I.item_color = initial(picked_item.item_color)
if(istype(I, /obj/item/clothing) && istype(initial(picked_item), /obj/item/clothing))
var/obj/item/clothing/CL = I
var/obj/item/clothing/PCL = picked_item
CL.flags_cover = initial(PCL.flags_cover)
target.icon = initial(picked_item.icon)
/datum/action/item_action/chameleon/change/Trigger()
if(!IsAvailable())
return
select_look(owner)
return 1
/datum/action/item_action/chameleon/change/proc/emp_randomise(var/amount = EMP_RANDOMISE_TIME)
START_PROCESSING(SSprocessing, src)
random_look(owner)
var/new_value = world.time + amount
if(new_value > emp_timer)
emp_timer = new_value
/datum/action/item_action/chameleon/change/process()
if(world.time > emp_timer)
STOP_PROCESSING(SSprocessing, src)
return
random_look(owner)
/obj/item/clothing/under/chameleon
//starts off as black
name = "black jumpsuit"
icon_state = "black"
item_state = "bl_suit"
item_color = "black"
desc = "It's a plain jumpsuit. It seems to have a small dial on the wrist."
origin_tech = "syndicate=2"
var/list/clothing_choices = list()
burn_state = FIRE_PROOF
armor = list(melee = 10, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0)
desc = "It's a plain jumpsuit. It has a small dial on the wrist."
sensor_mode = SENSOR_OFF //Hey who's this guy on the Syndicate Shuttle??
random_sensor = FALSE
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
New()
..()
var/blocked = list(/obj/item/clothing/under/color/random, /obj/item/clothing/under/rank/centcom) // Stops random coloured jumpsuit and undefined centcomm suit appearing in the list.
for(var/U in subtypesof(/obj/item/clothing/under/color) - blocked)
var/obj/item/clothing/under/V = new U
src.clothing_choices += V
var/datum/action/item_action/chameleon/change/chameleon_action
for(var/U in subtypesof(/obj/item/clothing/under/rank) - blocked)
var/obj/item/clothing/under/V = new U
src.clothing_choices += V
return
/obj/item/clothing/under/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/under
chameleon_action.chameleon_name = "Jumpsuit"
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/under, /obj/item/clothing/under/color, /obj/item/clothing/under/rank), only_root_path = TRUE)
chameleon_action.initialize_disguises()
/obj/item/clothing/under/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
attackby(obj/item/clothing/under/U as obj, mob/user as mob, params)
..()
if(istype(U, /obj/item/clothing/under/chameleon))
to_chat(user, "<span class='warning'>Nothing happens.</span>")
return
if(istype(U, /obj/item/clothing/under))
if(src.clothing_choices.Find(U))
to_chat(user, "<span class='warning'>Pattern is already recognised by the suit.</span>")
return
src.clothing_choices += U
to_chat(user, "<span class='warning'>Pattern absorbed by the suit.</span>")
/obj/item/clothing/under/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/suit/chameleon
name = "armor"
desc = "A slim armored vest that protects against most types of damage."
icon_state = "armor"
item_state = "armor"
blood_overlay_type = "armor"
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
emp_act(severity)
name = "psychedelic"
desc = "Groovy!"
icon_state = "psyche"
item_color = "psyche"
usr.update_inv_w_uniform()
spawn(200)
name = initial(name)
icon_state = initial(icon_state)
item_color = initial(item_color)
desc = initial(desc)
usr.update_inv_w_uniform()
..()
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/suit/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/suit
chameleon_action.chameleon_name = "Suit"
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/suit/armor/abductor), only_root_path = TRUE)
chameleon_action.initialize_disguises()
verb/change()
set name = "Change Color"
set category = "Object"
set src in usr
/obj/item/clothing/suit/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
if(icon_state == "psyche")
to_chat(usr, "<span class='warning'>Your suit is malfunctioning</span>")
return
/obj/item/clothing/suit/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
var/obj/item/clothing/under/A
A = input("Select Colour to change it to", "BOOYEA", A) in clothing_choices
if(!A)
return
/obj/item/clothing/glasses/chameleon
name = "Optical Meson Scanner"
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition."
icon_state = "meson"
item_state = "meson"
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
desc = null
permeability_coefficient = 0.90
var/datum/action/item_action/chameleon/change/chameleon_action
desc = A.desc
name = A.name
icon_state = A.icon_state
item_state = A.item_state
item_color = A.item_color
usr.update_inv_w_uniform() //so our overlays update.
/obj/item/clothing/glasses/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/glasses
chameleon_action.chameleon_name = "Glasses"
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
/obj/item/clothing/glasses/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/clothing/glasses/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/under/chameleon/all/New()
..()
var/blocked = list(/obj/item/clothing/under/chameleon, /obj/item/clothing/under/chameleon/all)
//to prevent an infinite loop
for(var/U in typesof(/obj/item/clothing/under)-blocked)
var/obj/item/clothing/under/V = new U
src.clothing_choices += V
/obj/item/clothing/gloves/chameleon
desc = "These gloves will protect the wearer from electric shock."
name = "insulated gloves"
icon_state = "yellow"
item_state = "ygloves"
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/gloves/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/gloves
chameleon_action.chameleon_name = "Gloves"
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/gloves, /obj/item/clothing/gloves/color), only_root_path = TRUE)
chameleon_action.initialize_disguises()
/obj/item/clothing/gloves/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/clothing/gloves/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/head/chameleon
name = "grey cap"
desc = "It's a baseball hat in a tasteful grey colour."
icon_state = "greysoft"
item_color = "grey"
resistance_flags = NONE
armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/head/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/head
chameleon_action.chameleon_name = "Hat"
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
/obj/item/clothing/head/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/clothing/head/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/mask/chameleon
name = "gas mask"
desc = "A face-covering mask that can be connected to an air supply. While good for concealing your identity, it isn't good for blocking gas flow." //More accurate
icon_state = "gas_alt"
item_state = "gas_alt"
resistance_flags = NONE
armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
flags = AIRTIGHT | BLOCK_GAS_SMOKE_EFFECT
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.01
flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH
var/obj/item/voice_changer/voice_changer
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/mask/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/mask
chameleon_action.chameleon_name = "Mask"
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
voice_changer = new(src)
/obj/item/clothing/mask/chameleon/Destroy()
QDEL_NULL(voice_changer)
return ..()
/obj/item/clothing/mask/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/clothing/mask/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/shoes/chameleon
name = "black shoes"
icon_state = "black"
item_color = "black"
desc = "A pair of black shoes."
permeability_coefficient = 0.05
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/shoes/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/shoes
chameleon_action.chameleon_name = "Shoes"
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
/obj/item/clothing/shoes/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/clothing/shoes/chameleon/noslip
name = "black shoes"
icon_state = "black"
item_color = "black"
desc = "A pair of black shoes."
flags = NOSLIP
/obj/item/clothing/shoes/chameleon/noslip/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/storage/backpack/chameleon
name = "backpack"
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/storage/backpack/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/storage/backpack
chameleon_action.chameleon_name = "Backpack"
chameleon_action.initialize_disguises()
/obj/item/storage/backpack/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/storage/backpack/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/storage/belt/chameleon
name = "toolbelt"
desc = "Holds tools."
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/storage/belt/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/storage/belt
chameleon_action.chameleon_name = "Belt"
chameleon_action.initialize_disguises()
/obj/item/storage/belt/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/storage/belt/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/radio/headset/chameleon
name = "radio headset"
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/radio/headset/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/radio/headset
chameleon_action.chameleon_name = "Headset"
chameleon_action.initialize_disguises()
/obj/item/radio/headset/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/radio/headset/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/pda/chameleon
name = "PDA"
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/pda/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/pda
chameleon_action.chameleon_name = "PDA"
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/pda/heads), only_root_path = TRUE)
chameleon_action.initialize_disguises()
/obj/item/pda/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/pda/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/stamp/chameleon
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/stamp/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/stamp
chameleon_action.chameleon_name = "Stamp"
chameleon_action.initialize_disguises()
/obj/item/stamp/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
+2 -2
View File
@@ -671,8 +671,8 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_
/obj/item/gun/energy/kinetic_accelerator/crossbow,\
/obj/item/storage/box/syndicate, /obj/item/storage/box/emps,\
/obj/item/cartridge/syndicate, /obj/item/clothing/under/chameleon,\
/obj/item/clothing/shoes/syndigaloshes, /obj/item/card/id/syndicate,\
/obj/item/clothing/mask/gas/voice, /obj/item/clothing/glasses/thermal,\
/obj/item/clothing/shoes/chameleon/noslip, /obj/item/card/id/syndicate,\
/obj/item/clothing/mask/chameleon, /obj/item/clothing/glasses/thermal,\
/obj/item/chameleon, /obj/item/card/emag,\
/obj/item/storage/toolbox/syndicate, /obj/item/aiModule,\
/obj/item/radio/headset/syndicate, /obj/item/grenade/plastic/c4,\
+16 -6
View File
@@ -62,27 +62,38 @@
return ..()
/mob/living/carbon/human/proc/HasVoiceChanger()
if(istype(back,/obj/item/rig))
if(istype(back, /obj/item/rig))
var/obj/item/rig/rig = back
if(rig.speech && rig.speech.voice_holder && rig.speech.voice_holder.active && rig.speech.voice_holder.voice)
return rig.speech.voice_holder.voice
for(var/obj/item/gear in list(wear_mask,wear_suit,head))
for(var/obj/item/gear in list(wear_mask, wear_suit, head))
if(!gear)
continue
var/obj/item/voice_changer/changer = locate() in gear
if(changer && changer.active && changer.voice)
return changer.voice
return 0
if(changer && changer.active)
if(changer.voice)
return changer.voice
else if(wear_id)
var/obj/item/card/id/idcard = wear_id.GetID()
if(istype(idcard))
return idcard.registered_name
return FALSE
/mob/living/carbon/human/GetVoice()
var/has_changer = HasVoiceChanger()
if(has_changer)
return has_changer
if(mind && mind.changeling && mind.changeling.mimicing)
return mind.changeling.mimicing
if(GetSpecialVoice())
return GetSpecialVoice()
return real_name
/mob/living/carbon/human/IsVocal()
@@ -124,7 +135,6 @@
span = mind.speech_span
if((COMIC in mutations) \
|| (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) \
|| istype(get_item_by_slot(slot_wear_mask), /obj/item/clothing/mask/gas/voice/clown) \
|| GetComponent(/datum/component/jestosterone))
span = "sans"
+1
View File
@@ -196,6 +196,7 @@
var/list/permanent_huds = list()
var/list/actions = list()
var/list/datum/action/chameleon_item_actions
var/list/progressbars = null //for stacking do_after bars
+11 -1
View File
@@ -6,7 +6,7 @@ Contents:
*/
/obj/item/clothing/mask/gas/voice/space_ninja
/obj/item/clothing/mask/gas/space_ninja
name = "ninja mask"
desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement."
icon_state = "s-ninja(norm)"
@@ -19,3 +19,13 @@ Contents:
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi'
)
var/obj/item/voice_changer/voice_changer
/obj/item/clothing/mask/gas/space_ninja/Initialize(mapload)
. = ..()
voice_changer = new(src)
/obj/item/clothing/mask/gas/space_ninja/Destroy()
QDEL_NULL(voice_changer)
return ..()
+2 -2
View File
@@ -24,7 +24,7 @@ Contents:
var/obj/item/clothing/head/helmet/space/space_ninja/suitHood
var/obj/item/clothing/gloves/space_ninja/suitGloves
var/obj/item/clothing/shoes/space_ninja/suitShoes
var/obj/item/clothing/mask/gas/voice/space_ninja/suitMask
var/obj/item/clothing/mask/gas/space_ninja/suitMask
var/mob/living/carbon/human/suitOccupant
/obj/item/clothing/suit/space/space_ninja/proc/toggle_suit_lock(mob/living/carbon/human/user)
@@ -41,7 +41,7 @@ Contents:
if(!istype(user.shoes, /obj/item/clothing/shoes/space_ninja))
to_chat(user, "<span style='color: #ff0000;'><b>ERROR:</b> Unable to locate foot gear.\nABORTING...</span>")
return 0
if(!istype(user.wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja))
if(!istype(user.wear_mask, /obj/item/clothing/mask/gas/space_ninja))
to_chat(user, "<span style='color: #ff0000;'><b>ERROR:</b> Unable to locate mask.\nABORTING...</span>")
return 0
-24
View File
@@ -92,27 +92,3 @@
icon_state = "stamp-syndicate"
item_color = "syndicate"
// Syndicate stamp to forge documents.
/obj/item/stamp/chameleon/attack_self(mob/user as mob)
var/list/stamp_types = typesof(/obj/item/stamp) - src.type // Get all stamp types except our own
var/list/stamps = list()
// Generate them into a list
for(var/stamp_type in stamp_types)
var/obj/item/stamp/S = new stamp_type
stamps[capitalize(S.name)] = S
var/list/show_stamps = list("EXIT" = null) + sortList(stamps) // the list that will be shown to the user to pick from
var/input_stamp = input(user, "Choose a stamp to disguise as.", "Choose a stamp.") in show_stamps
if(user && src in user.contents)
var/obj/item/stamp/chosen_stamp = stamps[capitalize(input_stamp)]
if(chosen_stamp)
name = chosen_stamp.name
icon_state = chosen_stamp.icon_state
item_color = chosen_stamp.item_color
Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 41 KiB

+1 -1
View File
@@ -853,6 +853,7 @@
#include "code\game\objects\items\devices\traitordevices.dm"
#include "code\game\objects\items\devices\transfer_valve.dm"
#include "code\game\objects\items\devices\uplinks.dm"
#include "code\game\objects\items\devices\voice.dm"
#include "code\game\objects\items\devices\whistle.dm"
#include "code\game\objects\items\devices\radio\beacon.dm"
#include "code\game\objects\items\devices\radio\electropack.dm"
@@ -1319,7 +1320,6 @@
#include "code\modules\clothing\masks\breath.dm"
#include "code\modules\clothing\masks\gasmask.dm"
#include "code\modules\clothing\masks\miscellaneous.dm"
#include "code\modules\clothing\masks\voice.dm"
#include "code\modules\clothing\patreon\glasses.dm"
#include "code\modules\clothing\patreon\hats.dm"
#include "code\modules\clothing\shoes\colour.dm"