mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-22 04:28:33 +01:00
Merge branch 'master' into reagentToDefines
This commit is contained in:
@@ -18,7 +18,6 @@
|
||||
#define CONTACT_GENERAL (1<<5)
|
||||
#define AIRBORNE (1<<6)
|
||||
|
||||
|
||||
//Severity Defines
|
||||
#define NONTHREAT "No threat"
|
||||
#define MINOR "Minor"
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
#define FACTION_WOLFTAUR "wolftaur"
|
||||
#define FACTION_WORM "worm"
|
||||
#define FACTION_XENO "xeno"
|
||||
#define FACTION_CORGI "corgi"
|
||||
|
||||
#define FACTION_PLANTS "plants"
|
||||
|
||||
|
||||
@@ -40,11 +40,12 @@
|
||||
//VOREStation Add
|
||||
#define BE_LOSTDRONE 0x10000
|
||||
#define BE_MAINTPRED 0x20000
|
||||
#define BE_MORPH 0x40000
|
||||
#define BE_CORGI 0x80000
|
||||
#define BE_CURSEDSWORD 0x100000
|
||||
#define BE_SURVIVOR 0x200000
|
||||
#define BE_EVENT 0x400000
|
||||
#define BE_MAINTLURKER 0x40000
|
||||
#define BE_MORPH 0x80000
|
||||
#define BE_CORGI 0x100000
|
||||
#define BE_CURSEDSWORD 0x200000
|
||||
#define BE_SURVIVOR 0x400000
|
||||
#define BE_EVENT 0x800000
|
||||
//VOREStation Add End
|
||||
|
||||
var/list/be_special_flags = list(
|
||||
@@ -67,6 +68,7 @@ var/list/be_special_flags = list(
|
||||
//VOREStation Add
|
||||
"Lost Drone" = BE_LOSTDRONE,
|
||||
"Maint Pred" = BE_MAINTPRED,
|
||||
"Maint Lurker" = BE_MAINTLURKER,
|
||||
"Morph" = BE_MORPH,
|
||||
"Corgi" = BE_CORGI,
|
||||
"Cursed Sword" = BE_CURSEDSWORD,
|
||||
|
||||
@@ -420,3 +420,4 @@
|
||||
#define JOB_XENOMORPH "Xenomorph"
|
||||
#define JOB_BORER "Borer"
|
||||
#define JOB_EMERGENCY_RESPONSE_TEAM "Emergency Response Team"
|
||||
#define JOB_MAINT_LURKER "Maintenance Lurker"
|
||||
|
||||
+13
-5
@@ -48,10 +48,6 @@
|
||||
|
||||
#define CLIENT_FROM_VAR(I) (ismob(I) ? I:client : (isclient(I) ? I : null))
|
||||
|
||||
|
||||
//Persistence
|
||||
#define AREA_FLAG_IS_NOT_PERSISTENT 8 // SSpersistence will not track values from this area.
|
||||
|
||||
// Shuttles.
|
||||
|
||||
// These define the time taken for the shuttle to get to the space station, and the time before it leaves again.
|
||||
@@ -99,7 +95,19 @@
|
||||
#define DEFAULT_JOB_TYPE /datum/job/assistant
|
||||
|
||||
//Area flags, possibly more to come
|
||||
#define RAD_SHIELDED 1 //shielded from radiation, clearly
|
||||
#define RAD_SHIELDED 0x1 //shielded from radiation, clearly
|
||||
#define BLUE_SHIELDED 0x2 // Shield from bluespace teleportation (telescience)
|
||||
#define AREA_SECRET_NAME 0x4 // This tells certain things that display areas' names that they shouldn't display this area's name.
|
||||
#define AREA_FLAG_IS_NOT_PERSISTENT 0x8 // SSpersistence will not track values from this area.
|
||||
#define AREA_FORBID_EVENTS 0x10 // random events will not start inside this area.
|
||||
#define AREA_FORBID_SINGULO 0x20 // singulo will not move in.
|
||||
#define AREA_NO_SPOILERS 0x40 // makes it much more difficult to see what is inside an area with things like mesons.
|
||||
#define AREA_SOUNDPROOF 0x80 // blocks sounds from other areas and prevents hearers on other areas from hearing the sounds within.
|
||||
#define AREA_BLOCK_PHASE_SHIFT 0x100 // Stops phase shifted mobs from entering
|
||||
#define AREA_BLOCK_GHOSTS 0x200 // Stops ghosts from entering
|
||||
#define AREA_ALLOW_LARGE_SIZE 0x400 // If mob size is limited in the area.
|
||||
#define AREA_BLOCK_SUIT_SENSORS 0x800 // If suit sensors are blocked in the area.
|
||||
#define AREA_BLOCK_TRACKING 0x1000 // If camera tracking is blocked in the area.
|
||||
|
||||
// OnTopic return values
|
||||
#define TOPIC_NOACTION 0
|
||||
|
||||
@@ -40,8 +40,6 @@
|
||||
//Shuttle madness!
|
||||
#define SHUTTLE_CRASHED 3 // Yup that can happen now
|
||||
|
||||
#define BLUE_SHIELDED 2 // Shield from bluespace teleportation (telescience)
|
||||
|
||||
//Herm Gender
|
||||
#define HERM "herm"
|
||||
|
||||
|
||||
@@ -328,6 +328,7 @@
|
||||
#define SPECIES_XENO_HUNTER "Xenomorph Hunter"
|
||||
#define SPECIES_XENO_SENTINEL "Xenomorph Sentinel"
|
||||
#define SPECIES_XENO_QUEEN "Xenomorph Queen"
|
||||
#define SPECIES_XENOMORPH_HYBRID "Xenomorph Hybrid"
|
||||
|
||||
// Misc species. Mostly unused but might as well be complete.
|
||||
#define SPECIES_SHADOW "Shadow"
|
||||
@@ -456,3 +457,6 @@
|
||||
#define VISIBLE_GENDER_FORCE_PLURAL 1 // Used by get_visible_gender to return PLURAL
|
||||
#define VISIBLE_GENDER_FORCE_IDENTIFYING 2 // Used by get_visible_gender to return the mob's identifying gender
|
||||
#define VISIBLE_GENDER_FORCE_BIOLOGICAL 3 // Used by get_visible_gender to return the mob's biological gender
|
||||
|
||||
// Default name for accesories
|
||||
#define DEVELOPER_WARNING_NAME "you should not see this..."
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#define LANGUAGE_ANIMAL "Animal"
|
||||
#define LANGUAGE_TEPPI "Teppi"
|
||||
#define LANGUAGE_MOUSE "Mouse"
|
||||
#define LANNGUAGE_DRAKE "Drake"
|
||||
|
||||
#define LANGUAGE_SHADEKIN "Shadekin Empathy"
|
||||
#define LANGUAGE_LLEILL "Glamour Speak"
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
|
||||
|
||||
var/list/talk_sound_map = rlist(
|
||||
list(
|
||||
"beep-boop",
|
||||
"goon speak 1",
|
||||
"goon speak 2",
|
||||
"goon speak 3",
|
||||
"goon speak 4",
|
||||
"goon speak blub",
|
||||
"goon speak bottalk",
|
||||
"goon speak buwoo",
|
||||
"goon speak cow",
|
||||
"goon speak lizard",
|
||||
"goon speak pug",
|
||||
"goon speak pugg",
|
||||
"goon speak roach",
|
||||
"goon speak skelly",
|
||||
// "xeno speak" // Does not exist on virgo
|
||||
),
|
||||
list(
|
||||
talk_sound,
|
||||
goon_speak_one_sound,
|
||||
goon_speak_two_sound,
|
||||
goon_speak_three_sound,
|
||||
goon_speak_four_sound,
|
||||
goon_speak_blub_sound,
|
||||
goon_speak_bottalk_sound,
|
||||
goon_speak_buwoo_sound,
|
||||
goon_speak_cow_sound,
|
||||
goon_speak_lizard_sound,
|
||||
goon_speak_pug_sound,
|
||||
goon_speak_pugg_sound,
|
||||
goon_speak_roach_sound,
|
||||
goon_speak_skelly_sound,
|
||||
// xeno_speak_sound // Does not exist on virgo
|
||||
)
|
||||
)
|
||||
|
||||
/proc/get_talk_sound(var/voice_sound)
|
||||
if(!voice_sound)
|
||||
return talk_sound_map[1]
|
||||
return talk_sound_map[2][voice_sound]
|
||||
|
||||
/proc/rlist(var/list/keys,var/list/values) //short for reversible list generator
|
||||
var/list/rlist = list(list(),list(),FALSE,0)
|
||||
var/i = 0
|
||||
for(i = 1, i <= LAZYLEN(keys), i++)
|
||||
to_chat(world,keys[i])
|
||||
rlist[1] += keys[i]
|
||||
rlist[2][keys[i]] = values[i]
|
||||
rlist += TRUE
|
||||
rlist += i
|
||||
return rlist
|
||||
|
||||
/proc/arlist(var/list/altlist)
|
||||
var/list/rlist = list(list(),list(),FALSE,0)
|
||||
var/i = 0
|
||||
for(i = 1, i <= LAZYLEN(altlist), i++)
|
||||
rlist[(i % 2) +1] += altlist[i]
|
||||
rlist += TRUE
|
||||
rlist += i/2
|
||||
return rlist
|
||||
@@ -19,7 +19,7 @@
|
||||
if(vent.welded)
|
||||
continue
|
||||
var/area/A = get_area(vent)
|
||||
if(A.forbid_events)
|
||||
if(A.flag_check(AREA_FORBID_EVENTS))
|
||||
continue
|
||||
vent_list += vent
|
||||
if(!vent_list.len)
|
||||
|
||||
@@ -33,7 +33,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
return
|
||||
|
||||
var/area/A = get_area(T)
|
||||
if(!A || (A.flags & AREA_FLAG_IS_NOT_PERSISTENT))
|
||||
if(!A || (A.flag_check(AREA_FLAG_IS_NOT_PERSISTENT)))
|
||||
return
|
||||
|
||||
if(!(T.z in using_map.persist_levels))
|
||||
|
||||
@@ -73,7 +73,7 @@ SUBSYSTEM_DEF(radiation)
|
||||
|
||||
if(source.respect_maint)
|
||||
var/area/A = T.loc
|
||||
if(A.flags & RAD_SHIELDED)
|
||||
if(A.flag_check(RAD_SHIELDED))
|
||||
continue // In shielded area
|
||||
|
||||
var/dist = get_dist(source.source_turf, T)
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
|
||||
/datum/component/resize_guard/proc/check_resize()
|
||||
var/area/A = get_area(parent)
|
||||
if(A?.limit_mob_size)
|
||||
var/mob/living/L = parent
|
||||
L.resize(L.size_multiplier, ignore_prefs = TRUE)
|
||||
qdel(src)
|
||||
if(A?.flag_check(AREA_ALLOW_LARGE_SIZE))
|
||||
return
|
||||
var/mob/living/L = parent
|
||||
L.resize(L.size_multiplier, ignore_prefs = TRUE)
|
||||
qdel(src)
|
||||
|
||||
@@ -3,8 +3,8 @@ GLOBAL_LIST_EMPTY(archive_diseases)
|
||||
GLOBAL_LIST_INIT(advance_cures, list(
|
||||
REAGENT_ID_SODIUMCHLORIDE, REAGENT_ID_SUGAR, "orangejuice",
|
||||
"spaceacillin", "glucose", REAGENT_ID_ETHANOL,
|
||||
"dyloteane", "impedrezene", "hepanephrodaxon",
|
||||
"gold", "silver"
|
||||
"leporazine", "impedrezene", "hepanephrodaxon",
|
||||
"silver", "gold"
|
||||
))
|
||||
|
||||
/datum/disease/advance
|
||||
@@ -236,6 +236,13 @@ GLOBAL_LIST_INIT(advance_cures, list(
|
||||
Refresh(1)
|
||||
return
|
||||
|
||||
/datum/disease/advance/proc/PickyEvolve(var/list/datum/symptom/D)
|
||||
var/s = safepick(D)
|
||||
if(s)
|
||||
AddSymptom(new s)
|
||||
Refresh(1)
|
||||
return
|
||||
|
||||
// Randomly remove a symptom.
|
||||
/datum/disease/advance/proc/Devolve()
|
||||
if(length(symptoms) > 1)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Deafness
|
||||
|
||||
Slightly hidden.
|
||||
Lowers resistance.
|
||||
Increases stage speed slightly.
|
||||
Decreases transmittablity.
|
||||
Intense Level.
|
||||
|
||||
Bonus
|
||||
Causes intermittent loss of hearing.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/deafness
|
||||
name = "Deafness"
|
||||
stealth = 1
|
||||
resistance = -2
|
||||
stage_speed = 1
|
||||
transmittable = -3
|
||||
level = 4
|
||||
severity = 3
|
||||
|
||||
/datum/symptom/deafness/Activate(datum/disease/advance/A)
|
||||
..()
|
||||
if(prob(SYMPTOM_ACTIVATION_PROB))
|
||||
var/mob/living/M = A.affected_mob
|
||||
|
||||
switch(A.stage)
|
||||
if(3, 4)
|
||||
to_chat(M, span_warning("[pick("you hear a ringing in your ear.", "You ears pop.")]"))
|
||||
if(5)
|
||||
to_chat(M, span_userdanger("You ear pop and begin ringing loudly!"))
|
||||
M.ear_deaf += 20
|
||||
return
|
||||
@@ -6,7 +6,7 @@ Necrotizing Fasciitis (AKA Flesh-Eating Disease)
|
||||
Very very noticable.
|
||||
Lowers resistance tremendously.
|
||||
No changes to stage speed.
|
||||
Decreases transmittablity temrendously.
|
||||
Decreases transmittablity tremendously.
|
||||
Fatal Level.
|
||||
|
||||
Bonus
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Flippinov
|
||||
|
||||
Slightly hidden.
|
||||
No change to resistance.
|
||||
Increases stage speed.
|
||||
Little transmittable.
|
||||
Low Level.
|
||||
|
||||
BONUS
|
||||
Makes the host FLIP.
|
||||
Should be used for buffing your disease.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/spyndrome
|
||||
name = "Flippinov"
|
||||
stealth = 2
|
||||
resistance = 0
|
||||
stage_speed = 3
|
||||
transmittable = 1
|
||||
level = 1
|
||||
severity = 1
|
||||
|
||||
/datum/symptom/spyndrome/Activate(datum/disease/advance/A)
|
||||
..()
|
||||
|
||||
if(prob(SYMPTOM_ACTIVATION_PROB))
|
||||
var/mob/living/L = A.affected_mob
|
||||
L.emote("flip")
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
Alopecia
|
||||
|
||||
Noticable.
|
||||
Decreases resistance slightly.
|
||||
Reduces stage speed slightly.
|
||||
Transmittable.
|
||||
Intense Level.
|
||||
|
||||
BONUS
|
||||
Makes the mob lose hair.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/shedding
|
||||
name = "Alopecia"
|
||||
stealth = -1
|
||||
resistance = -1
|
||||
stage_speed = -1
|
||||
transmittable = 2
|
||||
level = 4
|
||||
severity = 1
|
||||
|
||||
/datum/symptom/shedding/Activate(datum/disease/advance/A)
|
||||
..()
|
||||
if(!prob(SYMPTOM_ACTIVATION_PROB))
|
||||
return
|
||||
if(ishuman(A.affected_mob))
|
||||
return
|
||||
var/mob/living/carbon/human/H = A.affected_mob
|
||||
var/obj/item/organ/external/head/head_organ = H.get_organ(BP_HEAD)
|
||||
if(!istype(head_organ))
|
||||
return
|
||||
to_chat(H, span_warning("[pick("Your scalp itches.", "Your skin feels flakey.")]"))
|
||||
|
||||
switch(A.stage)
|
||||
if(3, 4)
|
||||
if(H.h_style != "Bald" && H.h_style != "Balding Hair")
|
||||
to_chat(H, span_warning("Your hair starts to fall out in clumps..."))
|
||||
addtimer(CALLBACK(src, PROC_REF(change_hair), H, null, "Balding Hair"), 5 SECONDS)
|
||||
if(5)
|
||||
if(H.h_style != "Shaved" && H.h_style != "Bald")
|
||||
to_chat(H, span_warning("Your hair starts to fall out in clumps..."))
|
||||
addtimer(CALLBACK(src, PROC_REF(change_hair), H, "Shaved", "Bald"), 5 SECONDS)
|
||||
return
|
||||
|
||||
/datum/symptom/shedding/proc/change_hair(var/mob/living/carbon/human/H, f_style, h_style)
|
||||
if(!H)
|
||||
return
|
||||
if(f_style)
|
||||
H.f_style = f_style
|
||||
if(h_style)
|
||||
H.h_style = h_style
|
||||
return
|
||||
@@ -130,7 +130,7 @@ Bonus
|
||||
Very high level.
|
||||
|
||||
Bonus
|
||||
Heals brain damage, treats radiation.
|
||||
Heals clone damage, treats radiation.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Hematophagy
|
||||
|
||||
Little bit hidden.
|
||||
Decreases resistance slightly.
|
||||
Decreases stage speed tremendously.
|
||||
Slightly increased transmittablity.
|
||||
Intense level.
|
||||
|
||||
BONUS
|
||||
The host must feed on BLOOD
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/hematophagy
|
||||
name = "Hematophagy"
|
||||
stealth = 1
|
||||
resistance = -1
|
||||
resistance = -4
|
||||
transmittable = 1
|
||||
level = 4
|
||||
|
||||
/datum/symptom/hematophagy/Start(datum/disease/advance/A)
|
||||
if(ishuman(A.affected_mob))
|
||||
var/mob/living/carbon/human/H = A.affected_mob
|
||||
|
||||
H.species.organic_food_coeff = 0
|
||||
H.species.bloodsucker = TRUE
|
||||
|
||||
add_verb(H, /mob/living/carbon/human/proc/bloodsuck)
|
||||
|
||||
/datum/symptom/hematophagy/End(datum/disease/advance/A)
|
||||
if(ishuman(A.affected_mob))
|
||||
var/mob/living/carbon/human/H = A.affected_mob
|
||||
|
||||
H.species.organic_food_coeff = initial(H.species.organic_food_coeff)
|
||||
H.species.bloodsucker = initial(H.species.bloodsucker)
|
||||
|
||||
remove_verb(H, /mob/living/carbon/human/proc/bloodsuck)
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Photosensitivity
|
||||
|
||||
Noticable.
|
||||
Increases resistance.
|
||||
Increases stage speed slightly.
|
||||
Decreases transmittablity tremendously.
|
||||
Fatal Level.
|
||||
|
||||
Bonus
|
||||
Deals brute damage over time.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/photosensitivity
|
||||
name = "Photosensitivity"
|
||||
stealth = -2
|
||||
resistance = 2
|
||||
stage_speed = 1
|
||||
transmittable = -4
|
||||
level = 6
|
||||
severity = 5
|
||||
|
||||
/datum/symptom/photosensitivity/Activate(datum/disease/advance/A)
|
||||
..()
|
||||
|
||||
if(prob(SYMPTOM_ACTIVATION_PROB))
|
||||
var/mob/living/carbon/human/H = A.affected_mob
|
||||
var/turf/T = get_turf(H)
|
||||
switch(A.stage)
|
||||
if(3)
|
||||
if(T.get_lumcount() > 0.5)
|
||||
to_chat(H, span_danger("Your skin itches under the light..."))
|
||||
if(4, 5)
|
||||
if(T.get_lumcount() > 0.5)
|
||||
to_chat(H, span_danger("Your skin feels like burning!"))
|
||||
H.adjustFireLoss(T.get_lumcount())
|
||||
return
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Pica
|
||||
|
||||
Not noticable or unnoticable.
|
||||
Decreases resistance.
|
||||
Increases stage speed.
|
||||
Little transmittable.
|
||||
Low Level.
|
||||
|
||||
BONUS
|
||||
The host gains hunger for any kind of object.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/pica
|
||||
name = "Pica"
|
||||
stealth = 0
|
||||
resistance = -2
|
||||
stage_speed = 3
|
||||
transmittable = 1
|
||||
level = 1
|
||||
severity = 1
|
||||
|
||||
/datum/symptom/pica/Start(datum/disease/advance/A)
|
||||
add_verb(A.affected_mob, /mob/living/proc/eat_trash)
|
||||
add_verb(A.affected_mob, /mob/living/proc/toggle_trash_catching)
|
||||
|
||||
/datum/symptom/pica/End(datum/disease/advance/A)
|
||||
remove_verb(A.affected_mob, /mob/living/proc/eat_trash)
|
||||
remove_verb(A.affected_mob, /mob/living/proc/toggle_trash_catching)
|
||||
|
||||
/datum/symptom/pica/Activate(datum/disease/advance/A)
|
||||
..()
|
||||
|
||||
if(prob(SYMPTOM_ACTIVATION_PROB))
|
||||
var/list/nearby = oview(5, A.affected_mob)
|
||||
to_chat(A.affected_mob, span_warning("You could go fo a bite of [pick(nearby)]..."))
|
||||
else if (prob(SYMPTOM_ACTIVATION_PROB))
|
||||
if(ishuman(A.affected_mob))
|
||||
var/mob/living/carbon/human/H = A.affected_mob
|
||||
var/list/item = H.get_equipped_items()
|
||||
to_chat(H, span_warning("[pick(item)] looks oddly [pick("delicious", "tasty", "scrumptious", "inviting")]..."))
|
||||
return
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Mass Revectoring
|
||||
|
||||
Very noticeable.
|
||||
Increases resistance slightly.
|
||||
Increases stage speed.
|
||||
Decreases transmittablity
|
||||
Intense level.
|
||||
|
||||
BONUS
|
||||
Changes the size of the host.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/size
|
||||
name = "Mass Revectoring"
|
||||
stealth = -4
|
||||
resistance = 1
|
||||
stage_speed = 2
|
||||
transmittable = -2
|
||||
level = 4
|
||||
severity = 1
|
||||
|
||||
/datum/symptom/size/Activate(datum/disease/advance/A)
|
||||
..()
|
||||
if(prob(SYMPTOM_ACTIVATION_PROB))
|
||||
var/mob/living/M = A.affected_mob
|
||||
|
||||
switch(A.stage)
|
||||
if(4, 5)
|
||||
M.emote("twitch")
|
||||
Resize(M, rand(25, 200))
|
||||
|
||||
/datum/symptom/size/proc/Resize(mob/living/M, var/size)
|
||||
M.resize(size+M.size_multiplier/100)
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Enlargement Disorder
|
||||
|
||||
Very noticeable.
|
||||
Increases resistance slightly.
|
||||
Increases stage speed.
|
||||
Decreases transmittablity
|
||||
Intense level.
|
||||
|
||||
BONUS
|
||||
Grows the host to bigger sizes
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/size/grow
|
||||
name = "Enlargement Disorder"
|
||||
|
||||
/datum/symptom/size/Activate(datum/disease/advance/A)
|
||||
..()
|
||||
if(prob(SYMPTOM_ACTIVATION_PROB))
|
||||
var/mob/living/M = A.affected_mob
|
||||
|
||||
switch(A.stage)
|
||||
if(4, 5)
|
||||
M.emote("twitch")
|
||||
Resize(M, rand(100, 200))
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Dwindling Malady
|
||||
|
||||
Very noticeable.
|
||||
Increases resistance slightly.
|
||||
Increases stage speed.
|
||||
Decreases transmittablity
|
||||
Intense level.
|
||||
|
||||
BONUS
|
||||
Shrinks the host to small sizes
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/size/shrink
|
||||
name = "Dwindling Malady"
|
||||
|
||||
/datum/symptom/size/Activate(datum/disease/advance/A)
|
||||
..()
|
||||
if(prob(SYMPTOM_ACTIVATION_PROB))
|
||||
var/mob/living/M = A.affected_mob
|
||||
|
||||
switch(A.stage)
|
||||
if(4, 5)
|
||||
M.emote("twitch")
|
||||
Resize(M, rand(25, 100))
|
||||
@@ -42,3 +42,78 @@ Bonus
|
||||
icky.viruses |= A.Copy()
|
||||
|
||||
return
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Bluespace Sneezing
|
||||
|
||||
Very Noticable.
|
||||
Resistant
|
||||
Doesn't increase stage speed.
|
||||
Little transmittable.
|
||||
Low Level.
|
||||
|
||||
Bonus
|
||||
Forces a spread type of AIRBORNE
|
||||
with extra range AND teleports the mob
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/sneeze/bluespace
|
||||
name = "Bluespace Sneezing"
|
||||
stealth = -2
|
||||
resistance = 3
|
||||
stage_speed = 0
|
||||
transmittable = 1
|
||||
level = 4
|
||||
severity = 1
|
||||
|
||||
/datum/symptom/sneeze/bluespace/Activate(datum/disease/advance/A)
|
||||
..()
|
||||
if(prob(SYMPTOM_ACTIVATION_PROB))
|
||||
var/mob/living/M = A.affected_mob
|
||||
switch(A.stage)
|
||||
if(1, 2, 3)
|
||||
M.emote("sniff")
|
||||
else
|
||||
SneezeTeleport(A, M)
|
||||
A.spread(A.stage)
|
||||
if(prob(30))
|
||||
var/obj/effect/decal/cleanable/mucus/icky = new(get_turf(M))
|
||||
icky.viruses |= A.Copy()
|
||||
|
||||
return
|
||||
|
||||
/datum/symptom/sneeze/bluespace/proc/SneezeTeleport(datum/disease/advance/A, var/mob/living/M)
|
||||
var/list/destination = list()
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/place
|
||||
|
||||
for(var/mob/living/carbon/human/B in range(A.stage, M))
|
||||
if(B.can_be_drop_pred && H.can_be_drop_prey && H.devourable)
|
||||
destination += B.vore_selected
|
||||
|
||||
for(var/turf/T in range(A.stage, H))
|
||||
if(istype(T, /turf/space)) // No danger, this is just a fun/vore symptom
|
||||
continue
|
||||
destination += T
|
||||
|
||||
if(isemptylist(destination))
|
||||
to_chat(H, span_warning("You go to sneeze, but can't."))
|
||||
return FALSE
|
||||
|
||||
place = safepick(destination)
|
||||
|
||||
var/mob/living/carbon/human/unlucky = locate() in place
|
||||
|
||||
if(unlucky)
|
||||
if(unlucky.can_be_drop_pred && H.can_be_drop_prey && H.devourable)
|
||||
place = unlucky.vore_selected
|
||||
else if(unlucky.devourable && unlucky.can_be_drop_prey && H.can_be_drop_pred)
|
||||
unlucky.forceMove(H.vore_selected)
|
||||
|
||||
H.emote("sneeze")
|
||||
do_teleport(H, place)
|
||||
return TRUE
|
||||
|
||||
@@ -16,7 +16,7 @@ BONUS
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/mlem
|
||||
/datum/symptom/spyndrome
|
||||
name = "Spyndrome"
|
||||
stealth = 2
|
||||
resistance = 0
|
||||
@@ -24,9 +24,8 @@ BONUS
|
||||
transmittable = 1
|
||||
level = 1
|
||||
severity = 1
|
||||
var/list/directions = list(2,4,1,8,2,4,1,8,2,4,1,8,2,4,1,8,2,4,1,8)
|
||||
|
||||
/datum/symptom/mlem/Activate(var/datum/disease/advance/A)
|
||||
/datum/symptom/spyndrome/Activate(var/datum/disease/advance/A)
|
||||
..()
|
||||
|
||||
if(prob(SYMPTOM_ACTIVATION_PROB))
|
||||
@@ -34,7 +33,5 @@ BONUS
|
||||
to_chat(viewers(A.affected_mob), span_warning("[A.affected_mob.name] struggles violently against their restraints!"))
|
||||
else
|
||||
to_chat(viewers(A.affected_mob), span_warning("[A.affected_mob.name] spins around violently!"))
|
||||
for(var/D in directions)
|
||||
A.affected_mob.dir = D
|
||||
A.affected_mob.dir = pick(2,4,1,8)
|
||||
A.affected_mob.emote("spin")
|
||||
return
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Healing
|
||||
|
||||
No change to stealth.
|
||||
Slightly decreases resistance.
|
||||
Increases stage speed.
|
||||
Decreases transmittablity considerably.
|
||||
Moderate Level.
|
||||
|
||||
Bonus
|
||||
Heals toxins in the affected mob's blood stream.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/stimulant
|
||||
name = "Overactive Adrenal Gland"
|
||||
stealth = 0
|
||||
resistance = -1
|
||||
stage_speed = 2
|
||||
transmittable = -3
|
||||
level = 3
|
||||
severity = 1
|
||||
|
||||
/datum/symptom/stimulant/Activate(datum/disease/advance/A)
|
||||
..()
|
||||
|
||||
if(prob(SYMPTOM_ACTIVATION_PROB))
|
||||
var/mob/living/L = A.affected_mob
|
||||
to_chat(L, span_notice("You feel a rush of energy inside you!"))
|
||||
switch(A.stage)
|
||||
if(1, 2)
|
||||
L.jitteriness += 5
|
||||
if(3, 4)
|
||||
L.jitteriness += 10
|
||||
else
|
||||
if(L.reagents.get_reagent_amount("hyperzine" < 10))
|
||||
L.reagents.add_reagent("hyperzine", 5)
|
||||
if(prob(30))
|
||||
L.jitteriness += 15
|
||||
return
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
|
||||
Sneezing
|
||||
Synthetic Infection
|
||||
|
||||
Slightly hidden.
|
||||
Increases resistance.
|
||||
@@ -23,7 +23,6 @@ Bonus
|
||||
transmittable = 1
|
||||
level = 5
|
||||
severity = 3
|
||||
id = "synthetic_infection"
|
||||
|
||||
/datum/symptom/infect_synthetics/Start(datum/disease/advance/A)
|
||||
A.infect_synthetics = TRUE
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/datum/disease/appendicitis
|
||||
form = "Condition"
|
||||
name = "Appendicitis"
|
||||
max_stages = 3
|
||||
spread_text = "Non-contagius"
|
||||
spread_flags = NON_CONTAGIOUS
|
||||
cure_text = "Surgery"
|
||||
agent = "Shitty Appendix"
|
||||
viable_mobtypes = list(/mob/living/carbon/human)
|
||||
desc = "If left untreated the subject will become very weak, and may vomit often."
|
||||
severity = MINOR
|
||||
disease_flags = CAN_CARRY|CAN_CARRY
|
||||
visibility_flags = HIDDEN_PANDEMIC
|
||||
required_organs = list(/obj/item/organ/internal/appendix)
|
||||
bypasses_immunity = TRUE
|
||||
virus_heal_resistant = TRUE
|
||||
|
||||
/datum/disease/appendicitis/stage_act()
|
||||
if(!..())
|
||||
return
|
||||
switch(stage)
|
||||
if(1)
|
||||
if(prob(5))
|
||||
affected_mob.adjustToxLoss(1)
|
||||
if(2)
|
||||
var/obj/item/organ/internal/appendix/A = affected_mob.internal_organs_by_name[O_APPENDIX]
|
||||
if(A)
|
||||
A.inflamed = TRUE
|
||||
if(prob(3))
|
||||
to_chat(affected_mob, span_warning("You feel a stabbing pain in your abdomen!"))
|
||||
affected_mob.custom_emote(VISIBLE_MESSAGE, "winces painfully.")
|
||||
affected_mob.Stun(rand(4, 6))
|
||||
affected_mob.adjustToxLoss(1)
|
||||
if(3)
|
||||
if(prob(1))
|
||||
to_chat(affected_mob, span_danger("Your abdomen is a world of pain!"))
|
||||
affected_mob.custom_emote(VISIBLE_MESSAGE, "winces painfully.")
|
||||
affected_mob.Weaken(10)
|
||||
if(prob(1))
|
||||
affected_mob.vomit(95)
|
||||
if(prob(5))
|
||||
to_chat(affected_mob, span_warning("You feel a stabbing pain in your abdomen!"))
|
||||
affected_mob.custom_emote(VISIBLE_MESSAGE, "winces painfully.")
|
||||
affected_mob.Stun(rand(4, 6))
|
||||
affected_mob.adjustToxLoss(2)
|
||||
@@ -0,0 +1,32 @@
|
||||
/datum/disease/fake_gbs
|
||||
name = "GBS"
|
||||
max_stages = 5
|
||||
spread_text = "On contact"
|
||||
spread_flags = CONTACT_GENERAL
|
||||
cure_text = "Adranol & Sulfur"
|
||||
cures = list("adranol", "sulfur")
|
||||
agent = "Gravitokinetic Bipotential SADS-"
|
||||
viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
|
||||
desc = "if left untreated death will occur."
|
||||
severity = BIOHAZARD // Mimics real GBS
|
||||
|
||||
/datum/disease/fake_gbs/stage_act()
|
||||
if(!..())
|
||||
return FALSE
|
||||
switch(stage)
|
||||
if(2)
|
||||
if(prob(1))
|
||||
affected_mob.emote("sneeze")
|
||||
if(3)
|
||||
if(prob(5))
|
||||
affected_mob.emote("cough")
|
||||
else if(prob(5))
|
||||
affected_mob.emote("gasp")
|
||||
if(prob(10))
|
||||
to_chat(span_danger("You're starting to feel very weak..."))
|
||||
if(4)
|
||||
if(prob(10))
|
||||
affected_mob.emote("cough")
|
||||
if(5)
|
||||
if(prob(10))
|
||||
affected_mob.emote("cough")
|
||||
@@ -0,0 +1,49 @@
|
||||
/datum/disease/gbs
|
||||
name = "GBS"
|
||||
max_stages = 5
|
||||
spread_text = "On contact"
|
||||
spread_flags = CONTACT_GENERAL
|
||||
cure_text = "Adranol & Sulfur"
|
||||
cures = list("adranol", "sulfur")
|
||||
cure_chance = 15
|
||||
agent = "Gravitokinetic Bipotential SADS+"
|
||||
viable_mobtypes = list(/mob/living/carbon/human)
|
||||
severity = BIOHAZARD
|
||||
|
||||
/datum/disease/gbs/stage_act()
|
||||
if(!..())
|
||||
return FALSE
|
||||
switch(stage)
|
||||
if(2)
|
||||
if(prob(45))
|
||||
affected_mob.adjustToxLoss(5)
|
||||
if(prob(1))
|
||||
affected_mob.emote("sneeze")
|
||||
if(3)
|
||||
if(prob(5))
|
||||
affected_mob.emote("cough")
|
||||
else if(prob(5))
|
||||
affected_mob.emote("gasp")
|
||||
if(prob(10))
|
||||
to_chat(affected_mob, span_danger("You're starting to feel very weak..."))
|
||||
if(4)
|
||||
if(prob(10))
|
||||
affected_mob.emote("cough")
|
||||
affected_mob.adjustToxLoss(5)
|
||||
if(5)
|
||||
to_chat(affected_mob, span_danger("Your body feels as if it's trying to rip itself open..."))
|
||||
if(prob(50))
|
||||
affected_mob.delayed_gib()
|
||||
else
|
||||
return
|
||||
|
||||
/datum/disease/gbs/curable
|
||||
name = "Non-Contagious GBS"
|
||||
stage_prob = 5
|
||||
spread_text = "Non-contagious"
|
||||
spread_flags = NON_CONTAGIOUS
|
||||
cure_text = "Cryoxadone"
|
||||
cures = list("cryoxadone")
|
||||
cure_chance = 10
|
||||
agent = "gibbis"
|
||||
disease_flags = CURABLE
|
||||
@@ -7,5 +7,11 @@
|
||||
/datum/ghost_query/maints_pred
|
||||
role_name = "Maintenance Predator"
|
||||
be_special_flag = BE_MAINTPRED
|
||||
question = "It appears a predatory critter is lurking in the maintenance. Do you want to play as it? ((You get to choose type of critter. Expect to be treated as vore predator.))"
|
||||
cutoff_number = 1
|
||||
question = "It appears a predatory critter is lurking in maintenance. Do you want to play as it? ((You get to choose type of critter. Expect to be treated as vore predator.))"
|
||||
cutoff_number = 1
|
||||
|
||||
/datum/ghost_query/maints_lurker
|
||||
role_name = "Maintenance Lurker"
|
||||
be_special_flag = BE_MAINTLURKER
|
||||
question = "It appears a strange individual is lurking in maintenance. Do you want to play as them? ((You can spawn as your currently loaded character slot. Expect to be treated as vore predator.))"
|
||||
cutoff_number = 1
|
||||
|
||||
@@ -63,4 +63,16 @@
|
||||
/decl/hierarchy/outfit/zaddat
|
||||
name = "Zaddat Suit"
|
||||
suit = /obj/item/clothing/suit/space/void/zaddat/
|
||||
mask = /obj/item/clothing/mask/gas/zaddat
|
||||
mask = /obj/item/clothing/mask/gas/zaddat
|
||||
|
||||
/decl/hierarchy/outfit/maint_lurker
|
||||
name = "Maintenance Lurker Outfit"
|
||||
id_slot = slot_wear_id
|
||||
id_type = /obj/item/card/id/civilian/lurker
|
||||
pda_slot = slot_belt
|
||||
pda_type = /obj/item/pda
|
||||
id_pda_assignment = "NO DATA"
|
||||
|
||||
headset = /obj/item/radio/headset
|
||||
headset_alt = /obj/item/radio/headset/alt
|
||||
headset_earbud = /obj/item/radio/headset/earbud
|
||||
|
||||
@@ -25,7 +25,7 @@ var/global/datum/repository/crew/crew_repository = new()
|
||||
for(var/obj/item/clothing/under/C in tracked)
|
||||
var/turf/pos = get_turf(C)
|
||||
var/area/B = pos?.loc //VOREStation Add: No sensor in Dorm
|
||||
if((C.has_sensor) && (pos?.z == zLevel) && (C.sensor_mode != SUIT_SENSOR_OFF) && !(B.block_suit_sensors) && !(is_jammed(C)) && !(is_vore_jammed(C))) //VOREStation Edit
|
||||
if((C.has_sensor) && (pos?.z == zLevel) && (C.sensor_mode != SUIT_SENSOR_OFF) && !(B.flag_check(AREA_BLOCK_SUIT_SENSORS)) && !(is_jammed(C)) && !(is_vore_jammed(C))) //VOREStation Edit
|
||||
if(istype(C.loc, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = C.loc
|
||||
if(H.w_uniform != C)
|
||||
|
||||
@@ -13,9 +13,8 @@
|
||||
//////// Abductor Areas ////////
|
||||
/area/unknown
|
||||
requires_power = 0
|
||||
flags = RAD_SHIELDED
|
||||
flags = RAD_SHIELDED | AREA_ALLOW_LARGE_SIZE
|
||||
icon_state = "red2"
|
||||
limit_mob_size = FALSE
|
||||
|
||||
/area/unknown/dorm1
|
||||
name = "Unknown Dorm 1"
|
||||
|
||||
@@ -69,10 +69,9 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
|
||||
/area/shuttle
|
||||
requires_power = 0
|
||||
flags = RAD_SHIELDED | AREA_FLAG_IS_NOT_PERSISTENT
|
||||
flags = RAD_SHIELDED | AREA_FLAG_IS_NOT_PERSISTENT | AREA_FORBID_EVENTS
|
||||
sound_env = SMALL_ENCLOSED
|
||||
base_turf = /turf/space
|
||||
forbid_events = TRUE
|
||||
|
||||
/area/shuttle/arrival
|
||||
name = "\improper Arrival Shuttle"
|
||||
@@ -830,7 +829,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "construction"
|
||||
|
||||
/area/hallway/secondary/entry
|
||||
forbid_events = TRUE
|
||||
flags = AREA_FORBID_EVENTS
|
||||
|
||||
/area/hallway/secondary/entry/fore
|
||||
name = "\improper Shuttle Dock Hallway - Mid"
|
||||
@@ -1007,10 +1006,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
/area/crew_quarters
|
||||
name = "\improper Dormitories"
|
||||
icon_state = "Sleep"
|
||||
flags = RAD_SHIELDED
|
||||
flags = RAD_SHIELDED | AREA_FORBID_EVENTS | AREA_FORBID_SINGULO
|
||||
ambience = AMBIENCE_GENERIC
|
||||
forbid_events = TRUE
|
||||
forbid_singulo = TRUE
|
||||
|
||||
/area/crew_quarters/toilet
|
||||
name = "\improper Dormitory Toilets"
|
||||
@@ -1313,8 +1310,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "Holodeck"
|
||||
dynamic_lighting = 0
|
||||
sound_env = LARGE_ENCLOSED
|
||||
forbid_events = TRUE
|
||||
flags = AREA_FLAG_IS_NOT_PERSISTENT
|
||||
flags = AREA_FLAG_IS_NOT_PERSISTENT | AREA_FORBID_EVENTS
|
||||
|
||||
/area/holodeck/alphadeck
|
||||
name = "\improper Holodeck Alpha"
|
||||
@@ -1390,10 +1386,10 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
ambience = AMBIENCE_ENGINEERING
|
||||
|
||||
/area/engineering/atmos
|
||||
name = "\improper Atmospherics"
|
||||
icon_state = "atmos"
|
||||
sound_env = LARGE_ENCLOSED
|
||||
ambience = AMBIENCE_ATMOS
|
||||
name = "\improper Atmospherics"
|
||||
icon_state = "atmos"
|
||||
sound_env = LARGE_ENCLOSED
|
||||
ambience = AMBIENCE_ATMOS
|
||||
|
||||
/area/engineering/atmos/monitoring
|
||||
name = "\improper Atmospherics Monitoring Room"
|
||||
@@ -1419,7 +1415,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
name = "\improper Engine Room"
|
||||
icon_state = "engine"
|
||||
sound_env = LARGE_ENCLOSED
|
||||
forbid_events = TRUE
|
||||
flags = AREA_FORBID_EVENTS
|
||||
|
||||
/area/engineering/engine_airlock
|
||||
name = "\improper Engine Room Airlock"
|
||||
@@ -2633,4 +2629,4 @@ var/list/the_station_areas = list (
|
||||
icon_state = "yellow"
|
||||
luminosity = 1
|
||||
dynamic_lighting = 0
|
||||
requires_power = 0
|
||||
requires_power = 0
|
||||
|
||||
+9
-11
@@ -40,7 +40,6 @@ GLOBAL_LIST_EMPTY(areas_by_type)
|
||||
|
||||
var/music = null
|
||||
var/has_gravity = 1 // Don't check this var directly; use get_gravity() instead
|
||||
var/secret_name = FALSE // This tells certain things that display areas' names that they shouldn't display this area's name.
|
||||
var/obj/machinery/power/apc/apc = null
|
||||
var/no_air = null
|
||||
// var/list/lights // list of all lights on this area
|
||||
@@ -52,12 +51,6 @@ GLOBAL_LIST_EMPTY(areas_by_type)
|
||||
var/list/forced_ambience = null
|
||||
var/sound_env = STANDARD_STATION
|
||||
var/turf/base_turf //The base turf type of the area, which can be used to override the z-level's base turf
|
||||
var/forbid_events = FALSE // If true, random events will not start inside this area.
|
||||
var/forbid_singulo = FALSE // If true singulo will not move in.
|
||||
var/no_spoilers = FALSE // If true, makes it much more difficult to see what is inside an area with things like mesons.
|
||||
var/soundproofed = FALSE // If true, blocks sounds from other areas and prevents hearers on other areas from hearing the sounds within.
|
||||
var/block_phase_shift = FALSE //Stops phase shifted mobs from entering // RS Port #658
|
||||
var/block_ghosts = FALSE //Stops ghosts from entering //RS Port #658
|
||||
|
||||
/area/New()
|
||||
// Used by the maploader, this must be done in New, not init
|
||||
@@ -76,7 +69,7 @@ GLOBAL_LIST_EMPTY(areas_by_type)
|
||||
power_equip = 0
|
||||
power_environ = 0
|
||||
power_change() // all machines set to current power level, also updates lighting icon
|
||||
if(no_spoilers)
|
||||
if(flag_check(AREA_NO_SPOILERS))
|
||||
set_spoiler_obfuscation(TRUE)
|
||||
|
||||
// Changes the area of T to A. Do not do this manually.
|
||||
@@ -398,7 +391,7 @@ var/list/mob/living/forced_ambiance_list = new
|
||||
L.lastarea = src
|
||||
L.lastareachange = world.time
|
||||
play_ambience(L, initial = TRUE)
|
||||
if(no_spoilers)
|
||||
if(flag_check(AREA_NO_SPOILERS))
|
||||
L.disable_spoiler_vision()
|
||||
check_phase_shift(M) //RS Port #658
|
||||
|
||||
@@ -542,7 +535,7 @@ var/list/ghostteleportlocs = list()
|
||||
return 1
|
||||
|
||||
/area/proc/get_name()
|
||||
if(secret_name)
|
||||
if(flag_check(AREA_SECRET_NAME))
|
||||
return "Unknown Area"
|
||||
return name
|
||||
|
||||
@@ -558,9 +551,14 @@ GLOBAL_DATUM(spoiler_obfuscation_image, /image)
|
||||
else
|
||||
cut_overlay(GLOB.spoiler_obfuscation_image)
|
||||
|
||||
/area/proc/flag_check(var/flag, var/match_all = FALSE)
|
||||
if(match_all)
|
||||
return (flags & flag) == flag
|
||||
return flags & flag
|
||||
|
||||
// RS Port #658 Start
|
||||
/area/proc/check_phase_shift(var/mob/ourmob)
|
||||
if(!block_phase_shift || !ourmob.incorporeal_move)
|
||||
if(!flag_check(AREA_BLOCK_PHASE_SHIFT) || !ourmob.incorporeal_move)
|
||||
return
|
||||
if(!isliving(ourmob))
|
||||
return
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/area
|
||||
var/enter_message
|
||||
var/exit_message
|
||||
var/limit_mob_size = TRUE //If mob size is limited in the area.
|
||||
var/block_suit_sensors = FALSE //If suit sensors are blocked in the area.
|
||||
var/block_tracking = FALSE //If camera tracking is blocked in the area.
|
||||
var/turf/ceiling_type
|
||||
|
||||
// Size of the area in open turfs, only calculated for indoors areas.
|
||||
@@ -71,5 +68,5 @@
|
||||
power_equip = 0
|
||||
power_environ = 0
|
||||
power_change() // all machines set to current power level, also updates lighting icon
|
||||
if(no_spoilers)
|
||||
if(flag_check(AREA_NO_SPOILERS))
|
||||
set_spoiler_obfuscation(TRUE)
|
||||
|
||||
@@ -350,8 +350,8 @@
|
||||
title_blurb = "A " + JOB_ALT_COMEDIAN + " will focus on making people laugh with the power of wit! Telling jokes, stand-up comedy, you are here to make others smile!"
|
||||
|
||||
/datum/alt_title/tragedian
|
||||
title = JOB_ALT_ARTIST
|
||||
title_blurb = "A " + JOB_ALT_ARTIST + " will focus on making people think about life and world around them! Life is a tragedy, and who's better to convey its emotions than you?"
|
||||
title = JOB_ALT_TRAGEDIAN
|
||||
title_blurb = "A " + JOB_ALT_TRAGEDIAN + " will focus on making people think about life and world around them! Life is a tragedy, and who's better to convey its emotions than you?"
|
||||
|
||||
/datum/alt_title/artist
|
||||
title = JOB_ALT_ARTIST
|
||||
|
||||
@@ -108,3 +108,25 @@
|
||||
return list(access_maint_tunnels, access_entertainment, access_tomfoolery, access_mime)
|
||||
else
|
||||
return list(access_entertainment, access_tomfoolery, access_mime)
|
||||
|
||||
/obj/item/card/id/civilian/lurker
|
||||
desc = "A rather old and scuffed-looking ID. It seems legit, but something also seems very off somehow. Say, what's the issue/expiry date..?"
|
||||
assignment = "NO DATA"
|
||||
rank = JOB_MAINT_LURKER
|
||||
|
||||
/datum/job/maint_lurker
|
||||
title = JOB_MAINT_LURKER
|
||||
departments = list(DEPARTMENT_CIVILIAN)
|
||||
faction = FACTION_STATION
|
||||
total_positions = -1
|
||||
spawn_positions = -1
|
||||
supervisors = "nobody save your own common sense and good judgement, though Security may get upset if you're not careful"
|
||||
selection_color = "#515151"
|
||||
account_allowed = FALSE //let's not give the game away by creating accounts that someone might stumble across
|
||||
job_description = "You are a maintenance lurker! You shouldn't be able to see this description anyway! Go prank the CMO or eat the RD's hat or something instead of looking at this."
|
||||
whitelist_only = 1
|
||||
latejoin_only = 1
|
||||
requestable = FALSE
|
||||
outfit_type = /decl/hierarchy/outfit/maint_lurker
|
||||
access = list(access_maint_tunnels)
|
||||
minimal_access = list(access_maint_tunnels)
|
||||
|
||||
@@ -801,7 +801,7 @@
|
||||
apply_danger_level(0)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/alarm/attackby(obj/item/W as obj, mob/user as mob)
|
||||
/obj/machinery/alarm/attackby(obj/item/W as obj, mob/user)
|
||||
add_fingerprint(user)
|
||||
if(alarm_deconstruction_screwdriver(user, W))
|
||||
return
|
||||
@@ -809,10 +809,10 @@
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))// trying to unlock the interface with an ID card
|
||||
togglelock()
|
||||
togglelock(user)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/alarm/verb/togglelock(mob/user as mob)
|
||||
/obj/machinery/alarm/proc/togglelock(mob/user)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
to_chat(user, "It does nothing.")
|
||||
return
|
||||
@@ -824,9 +824,9 @@
|
||||
to_chat(user, span_warning("Access denied."))
|
||||
return
|
||||
|
||||
/obj/machinery/alarm/AltClick()
|
||||
/obj/machinery/alarm/AltClick(mob/user)
|
||||
..()
|
||||
togglelock()
|
||||
togglelock(user)
|
||||
|
||||
/obj/machinery/alarm/power_change()
|
||||
..()
|
||||
|
||||
@@ -230,7 +230,7 @@
|
||||
return TRACKING_TERMINATE
|
||||
var/turf/pos = get_turf(src)
|
||||
var/area/B = pos?.loc // No cam tracking in dorms!
|
||||
if(InvalidPlayerTurf(pos) || B.block_tracking)
|
||||
if(InvalidPlayerTurf(pos) || B.flag_check(AREA_BLOCK_TRACKING))
|
||||
return TRACKING_TERMINATE
|
||||
if(invisibility >= INVISIBILITY_LEVEL_ONE) //cloaked
|
||||
return TRACKING_TERMINATE
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/obj/machinery/computer/pandemic
|
||||
name = "PanD.E.M.I.C 2200"
|
||||
desc = "Used to work with viruses."
|
||||
circuit = /obj/item/circuitboard/pandemic
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
icon = 'icons/obj/pandemic.dmi'
|
||||
@@ -325,7 +326,7 @@
|
||||
printing = 1
|
||||
var/obj/item/paper/P = new /obj/item/paper(loc)
|
||||
visible_message(span_notice("[src] rattles and prints out a sheet of paper."))
|
||||
// playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
playsound(loc, 'sound/machines/printer.ogg', 50, 1)
|
||||
|
||||
P.info = "<U><font size=\"4\"><B><center> Releasing Virus </B></center></font></U>"
|
||||
P.info += "<HR>"
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
if(in_use)
|
||||
return
|
||||
var/area/A = get_area(usr)
|
||||
if(A.flags & BLUE_SHIELDED)
|
||||
if(A.flag_check(BLUE_SHIELDED))
|
||||
to_chat(usr, span_warning("You cannot edit restricted areas."))
|
||||
return
|
||||
in_use = TRUE
|
||||
@@ -156,7 +156,7 @@
|
||||
return
|
||||
in_use = TRUE
|
||||
var/area/A = create_area_whole(usr, src)
|
||||
if(A && (A.flags & BLUE_SHIELDED))
|
||||
if(A?.flag_check(BLUE_SHIELDED))
|
||||
to_chat(usr, span_warning("You cannot edit restricted areas."))
|
||||
in_use = FALSE
|
||||
return
|
||||
@@ -485,7 +485,7 @@
|
||||
var/area/place = get_area(turfs[i])
|
||||
if(blacklisted_areas[place.type])
|
||||
continue
|
||||
if(!place.requires_power || (place.flags & BLUE_SHIELDED))
|
||||
if(!place.requires_power || (place.flag_check(BLUE_SHIELDED)))
|
||||
continue // No expanding powerless rooms etc
|
||||
areas[place.name] = place
|
||||
|
||||
@@ -587,7 +587,7 @@
|
||||
continue
|
||||
if(!BUILDABLE_AREA_TYPES[place.type]) //TODOTODOTODO
|
||||
can_make_new_area = 0
|
||||
if(!place.requires_power || (place.flags & BLUE_SHIELDED))
|
||||
if(!place.requires_power || (place.flag_check(BLUE_SHIELDED)))
|
||||
continue // No expanding powerless rooms etc
|
||||
areas[place.name] = place
|
||||
|
||||
|
||||
@@ -539,7 +539,7 @@
|
||||
//Misc belts. Admin-spawn only atm.
|
||||
|
||||
/obj/item/personal_shield_generator/belt/adminbus
|
||||
desc = "You should not see this. You REALLY should not see this. If you do, you have either been blessed or are about to be the target of some sick prank."
|
||||
desc = DEVELOPER_WARNING_NAME + " You REALLY should not see this. If you do, you have either been blessed or are about to be the target of some sick prank."
|
||||
modifier_type = /datum/modifier/shield_projection/admin
|
||||
generator_hit_cost = 0
|
||||
generator_active_cost = 0
|
||||
|
||||
@@ -466,6 +466,7 @@
|
||||
/obj/item/radio/headset/alt/ert
|
||||
name = "emergency response team bowman headset"
|
||||
icon_state = "com_headset_alt"
|
||||
centComm = 1
|
||||
ks2type = /obj/item/encryptionkey/ert
|
||||
|
||||
/obj/item/radio/headset/ia
|
||||
@@ -493,6 +494,8 @@
|
||||
/obj/item/radio/headset/alt/centcom
|
||||
name = "centcom bowman headset"
|
||||
icon_state = "com_headset_alt"
|
||||
centComm = 1
|
||||
ks2type = /obj/item/encryptionkey/ert
|
||||
|
||||
/obj/item/radio/headset/nanotrasen
|
||||
name = "\improper NT radio headset"
|
||||
@@ -503,6 +506,8 @@
|
||||
/obj/item/radio/headset/alt/nanotrasen
|
||||
name = "\improper NT bowman headset"
|
||||
icon_state = "nt_headset_alt"
|
||||
centComm = 1
|
||||
ks2type = /obj/item/encryptionkey/ert
|
||||
|
||||
/obj/item/radio/headset/pathfinder
|
||||
name = "pathfinder's headset"
|
||||
@@ -513,6 +518,8 @@
|
||||
/obj/item/radio/headset/alt/pathfinder
|
||||
name = "pathfinder's bowman headset"
|
||||
icon_state = "exp_headset_alt"
|
||||
adhoc_fallback = TRUE
|
||||
ks2type = /obj/item/encryptionkey/pathfinder
|
||||
|
||||
/obj/item/radio/headset/pilot
|
||||
name = "pilot's headset"
|
||||
@@ -522,6 +529,7 @@
|
||||
/obj/item/radio/headset/alt/pilot
|
||||
name = "pilot's bowman headset"
|
||||
icon_state = "pilot_headset_alt"
|
||||
adhoc_fallback = TRUE
|
||||
|
||||
/obj/item/radio/headset/explorer
|
||||
name = "away team member's headset"
|
||||
@@ -532,6 +540,8 @@
|
||||
/obj/item/radio/headset/alt/explorer
|
||||
name = "away team's bowman headset"
|
||||
icon_state = "exp_headset_alt"
|
||||
adhoc_fallback = TRUE
|
||||
ks2type = /obj/item/encryptionkey/explorer
|
||||
|
||||
/obj/item/radio/headset/sar
|
||||
name = "search and rescue headset"
|
||||
@@ -635,4 +645,4 @@
|
||||
/obj/item/radio/headset/heads/ai_integrated/receive_range(freq, level)
|
||||
if (disabledAi)
|
||||
return -1 //Transciever Disabled.
|
||||
return ..(freq, level, 1)
|
||||
return ..(freq, level, 1)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/obj/effect/falling_effect
|
||||
name = "you should not see this"
|
||||
name = DEVELOPER_WARNING_NAME
|
||||
desc = "no data"
|
||||
invisibility = 101
|
||||
anchored = TRUE
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef T_BOARD
|
||||
#error T_BOARD macro is not defined but we need it!
|
||||
#endif
|
||||
|
||||
/obj/item/circuitboard/pandemic
|
||||
name = T_BOARD("pandemic")
|
||||
build_path = /obj/machinery/computer/pandemic
|
||||
board_type = new /datum/frame/frame_types/computer
|
||||
origin_tech = list(TECH_DATA = 2, TECH_BIO = 2)
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/matter_bin = 2,
|
||||
/obj/item/stock_parts/scanning_module = 1,
|
||||
/obj/item/stock_parts/manipulator = 1,
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/stock_parts/capacitor = 1
|
||||
)
|
||||
@@ -336,3 +336,9 @@
|
||||
/obj/item/card/id/syndicate/officer
|
||||
name = "Syndicate Officer ID"
|
||||
initial_sprite_stack = list("base-stamp-dark", "top-syndicate", "stamp-s", "pips-gold", "stripe-gold")
|
||||
|
||||
//Special
|
||||
|
||||
/obj/item/card/id/civilian/lurker
|
||||
name = "Outdated ID"
|
||||
initial_sprite_stack = list("base-stamp", "stamp-silhouette", "top-olive", "digested")
|
||||
|
||||
@@ -133,7 +133,7 @@ It also makes it so a ghost wont know where all the goodies/mobs are.
|
||||
name = "Corgi Lazy Spawner"
|
||||
desc = "This is a proof of concept, not sure why you would use this one"
|
||||
spawn_delay = 3 MINUTES
|
||||
mob_faction = "Corgi"
|
||||
mob_faction = FACTION_CORGI
|
||||
spawn_types = list(
|
||||
/mob/living/simple_mob/animal/passive/dog/corgi = 75,
|
||||
/mob/living/simple_mob/animal/passive/dog/corgi/puppy = 50
|
||||
@@ -150,7 +150,7 @@ It also makes it so a ghost wont know where all the goodies/mobs are.
|
||||
spawn_delay = 10 MINUTES
|
||||
range = 10
|
||||
simultaneous_spawns = 1
|
||||
mob_faction = "wild animal"
|
||||
mob_faction = FACTION_WILD_ANIMAL
|
||||
total_spawns = -1
|
||||
destructible = 0
|
||||
anchored = TRUE
|
||||
@@ -167,7 +167,7 @@ It also makes it so a ghost wont know where all the goodies/mobs are.
|
||||
spawn_delay = 10 MINUTES
|
||||
range = 10
|
||||
simultaneous_spawns = 1
|
||||
mob_faction = "xeno"
|
||||
mob_faction = FACTION_XENO
|
||||
total_spawns = -1
|
||||
destructible = 1
|
||||
health = 50
|
||||
@@ -186,7 +186,7 @@ It also makes it so a ghost wont know where all the goodies/mobs are.
|
||||
spawn_delay = 10 MINUTES
|
||||
range = 10
|
||||
simultaneous_spawns = 1
|
||||
mob_faction = "xeno"
|
||||
mob_faction = FACTION_XENO
|
||||
total_spawns = 1
|
||||
destructible = 1
|
||||
health = 50
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
overwrite_hostility = 1
|
||||
|
||||
mob_faction = "malf_drone"
|
||||
mob_faction = FACTION_MALF_DRONE
|
||||
mob_returns_home = 1
|
||||
mob_wander = 1
|
||||
mob_wander_distance = 5
|
||||
@@ -203,7 +203,7 @@
|
||||
|
||||
overwrite_hostility = 1
|
||||
|
||||
mob_faction = "malf_drone"
|
||||
mob_faction = FACTION_MALF_DRONE
|
||||
mob_returns_home = 1
|
||||
mob_wander = 1
|
||||
mob_wander_distance = 5
|
||||
@@ -220,7 +220,7 @@
|
||||
desc = "This is a random hivebot."
|
||||
icon_state = "robot"
|
||||
|
||||
mob_faction = "hivebot"
|
||||
mob_faction = FACTION_HIVEBOT
|
||||
|
||||
/obj/random/mob/robotic/hivebot/item_to_spawn()
|
||||
return pick(prob(10);/mob/living/simple_mob/mechanical/hivebot,
|
||||
@@ -292,7 +292,7 @@
|
||||
desc = "This is a random PoI mercenary."
|
||||
icon_state = "humanoid"
|
||||
|
||||
mob_faction = "syndicate"
|
||||
mob_faction = FACTION_SYNDICATE
|
||||
mob_returns_home = 1
|
||||
mob_wander_distance = 7 // People like to wander, and these people probably have a lot of stuff to guard.
|
||||
|
||||
|
||||
@@ -26,6 +26,14 @@
|
||||
toggle()
|
||||
..()
|
||||
|
||||
/obj/structure/curtain/attack_ai(mob/user)
|
||||
if(!Adjacent(user))
|
||||
return
|
||||
if(!isrobot((user)))
|
||||
return
|
||||
playsound(src, "rustle", 15, 1, -5)
|
||||
toggle()
|
||||
|
||||
/obj/structure/curtain/proc/toggle()
|
||||
set_opacity(!opacity)
|
||||
if(opacity)
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
//newPred.movement_cooldown = 0 // The "needless artificial speed cap" exists for a reason
|
||||
if(M.mind)
|
||||
M.mind.transfer_to(newPred)
|
||||
to_chat(M, span_notice("You are <b>[newPred]</b>, somehow having gotten aboard the station in search of food. \
|
||||
to_chat(M, span_notice("You are " + span_bold(newPred) + ", somehow having gotten aboard the station in search of food. \
|
||||
You are wary of environment around you, but you do feel rather peckish. Stick around dark, secluded places to avoid danger or, \
|
||||
if you are cute enough, try to make friends with this place's inhabitants."))
|
||||
to_chat(M, span_critical("Please be advised, this role is NOT AN ANTAGONIST."))
|
||||
@@ -144,7 +144,7 @@
|
||||
var/mob/living/simple_mob/vore/morph/newMorph = new /mob/living/simple_mob/vore/morph(get_turf(src))
|
||||
if(M.mind)
|
||||
M.mind.transfer_to(newMorph)
|
||||
to_chat(M, span_notice("You are a <b>Morph</b>, somehow having gotten aboard the station in your wandering. \
|
||||
to_chat(M, span_notice("You are a " + span_bold("Morph") + ", somehow having gotten aboard the station in your wandering. \
|
||||
You are wary of environment around you, but your primal hunger still calls for you to find prey. Seek a convincing disguise, \
|
||||
using your amorphous form to traverse vents to find and consume weak prey."))
|
||||
to_chat(M, span_notice("You can use shift + click on objects to disguise yourself as them, but your strikes are nearly useless when you are disguised. \
|
||||
@@ -172,3 +172,82 @@
|
||||
..()
|
||||
if(!(src in active_ghost_pods))
|
||||
active_ghost_pods += src
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/maint_lurker
|
||||
name = "strange maintenance hole"
|
||||
desc = "This is my hole! It was made for me!"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "tunnel_hole"
|
||||
icon_state_opened = "tunnel_hole"
|
||||
density = FALSE
|
||||
ghost_query_type = /datum/ghost_query/maints_lurker
|
||||
anchored = TRUE
|
||||
invisibility = INVISIBILITY_OBSERVER
|
||||
spawn_active = TRUE
|
||||
|
||||
//override the standard attack_ghost proc for custom messages
|
||||
/obj/structure/ghost_pod/ghost_activated/maint_lurker/attack_ghost(var/mob/observer/dead/user)
|
||||
if(jobban_isbanned(user, JOB_GHOSTROLES))
|
||||
to_chat(user, span_warning("You cannot use this spawnpoint because you are banned from playing ghost roles."))
|
||||
return
|
||||
|
||||
//No whitelist
|
||||
if(!is_alien_whitelisted(user, GLOB.all_species[user.client.prefs.species]))
|
||||
to_chat(user, span_warning("You cannot use this spawnpoint to spawn as a species you are not whitelisted for!"))
|
||||
return
|
||||
|
||||
//No OOC notes/FT
|
||||
if(not_has_ooc_text(user))
|
||||
//to_chat(user, span_warning("You must have proper out-of-character notes and flavor text configured for your current character slot to use this spawnpoint."))
|
||||
return
|
||||
|
||||
var/choice = tgui_alert(user, "Using this spawner will spawn you as your currently loaded character slot in a special role. It should not be used with characters you regularly play on station. Are you absolutely sure you wish to continue?", "Maint Lurker Spawner", list("Yes", "No"))
|
||||
|
||||
if(!choice || choice == "No")
|
||||
return
|
||||
|
||||
create_occupant(user)
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/maint_lurker/create_occupant(var/mob/M)
|
||||
..()
|
||||
|
||||
var/picked_ckey = M.ckey
|
||||
var/picked_slot = M.client.prefs.default_slot
|
||||
|
||||
var/mob/living/carbon/human/new_character = new(src.loc)
|
||||
if(!new_character)
|
||||
to_chat(M, span_warning("Something went wrong and spawning failed. Please check your character slot doesn't have any obvious errors, then either try again or send an adminhelp!"))
|
||||
reset_ghostpod()
|
||||
return
|
||||
log_and_message_admins("successfully used a Maintenance Lurker spawnpoint and became their loaded character.")
|
||||
|
||||
M.client.prefs.copy_to(new_character)
|
||||
new_character.dna.ResetUIFrom(new_character)
|
||||
new_character.sync_organ_dna()
|
||||
new_character.key = M.key
|
||||
new_character.mind.loaded_from_ckey = picked_ckey
|
||||
new_character.mind.loaded_from_slot = picked_slot
|
||||
|
||||
job_master.EquipRank(new_character, JOB_MAINT_LURKER, 1)
|
||||
|
||||
for(var/lang in new_character.client.prefs.alternate_languages)
|
||||
var/datum/language/chosen_language = GLOB.all_languages[lang]
|
||||
if(chosen_language)
|
||||
if(is_lang_whitelisted(src,chosen_language) || (new_character.species && (chosen_language.name in new_character.species.secondary_langs)))
|
||||
new_character.add_language(lang)
|
||||
|
||||
new_character.regenerate_icons()
|
||||
|
||||
new_character.update_transform()
|
||||
|
||||
to_chat(new_character, span_notice("You are a " + span_bold(JOB_MAINT_LURKER) + ", a loose end... you have no special advantages compared to the rest of the crew, so be cautious! You have spawned with an ID that will allow you free access to maintenance areas along with any of your chosen loadout items that are not role restricted, and can make use of anything you can find in maintenance."))
|
||||
to_chat(new_character, span_critical("Please be advised, this role is " + span_bold("NOT AN ANTAGONIST.")))
|
||||
to_chat(new_character, span_notice("Whoever or whatever your chosen character slot is, your role is to facilitate roleplay focused around that character; this role is not free license to attack and murder people without provocation or explicit out-of-character consent. You should probably be cautious around high-traffic and highly sensitive areas (e.g. Telecomms) as Security personnel would be well within their rights to treat you as a trespasser. That said, good luck!"))
|
||||
|
||||
new_character.visible_message(span_warning("[new_character] appears to crawl out of somewhere."))
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/ghost_pod/ghost_activated/maint_lurker/Initialize()
|
||||
..()
|
||||
if(!(src in active_ghost_pods))
|
||||
active_ghost_pods += src
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
var/glass = 1
|
||||
var/datum/tgui_module/appearance_changer/mirror/M
|
||||
|
||||
/obj/structure/mirror/Initialize(mapload, var/dir, var/building = 0, mob/user as mob)
|
||||
/obj/structure/mirror/Initialize(mapload, var/dir, var/building = 0)
|
||||
M = new(src, null)
|
||||
if(building)
|
||||
glass = 0
|
||||
@@ -24,12 +24,18 @@
|
||||
QDEL_NULL(M)
|
||||
. = ..()
|
||||
|
||||
/obj/structure/mirror/attack_hand(mob/user as mob)
|
||||
/obj/structure/mirror/attack_hand(mob/user)
|
||||
if(!glass) return
|
||||
if(shattered) return
|
||||
|
||||
if(ishuman(user))
|
||||
M.tgui_interact(user)
|
||||
M.tgui_interact(user)
|
||||
|
||||
/obj/structure/mirror/attack_ai(mob/user)
|
||||
if(!glass) return
|
||||
if(shattered) return
|
||||
if(!Adjacent(user)) return
|
||||
|
||||
M.tgui_interact(user)
|
||||
|
||||
/obj/structure/mirror/proc/shatter()
|
||||
if(!glass) return
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
if(!T)
|
||||
continue
|
||||
var/area/A = T.loc
|
||||
if((A.soundproofed || area_source.soundproofed) && (A != area_source))
|
||||
if((A.flag_check(AREA_SOUNDPROOF) || area_source.flag_check(AREA_SOUNDPROOF)) && (A != area_source))
|
||||
continue
|
||||
var/distance = get_dist(T, turf_source)
|
||||
|
||||
|
||||
@@ -92,6 +92,13 @@
|
||||
toggle_open(user)
|
||||
return 0
|
||||
|
||||
/turf/simulated/wall/attack_ai(var/mob/user)
|
||||
if(!Adjacent(user))
|
||||
return
|
||||
if(!isrobot((user)))
|
||||
return
|
||||
var/rotting = (locate(/obj/effect/overlay/wallrot) in src)
|
||||
try_touch(user, rotting)
|
||||
|
||||
/turf/simulated/wall/attack_hand(var/mob/user)
|
||||
|
||||
|
||||
@@ -196,7 +196,8 @@ var/list/admin_verbs_spawn = list(
|
||||
/client/proc/create_gm_message,
|
||||
/client/proc/remove_gm_message,
|
||||
/client/proc/AdminCreateVirus,
|
||||
/client/proc/ReleaseVirus
|
||||
/client/proc/ReleaseVirus,
|
||||
/client/proc/spawn_reagent
|
||||
)
|
||||
|
||||
var/list/admin_verbs_server = list(
|
||||
@@ -283,7 +284,8 @@ var/list/admin_verbs_debug = list(
|
||||
/client/proc/admin_give_modifier,
|
||||
/client/proc/simple_DPS,
|
||||
/datum/admins/proc/view_feedback,
|
||||
/client/proc/stop_sounds
|
||||
/client/proc/stop_sounds,
|
||||
/client/proc/spawn_reagent
|
||||
)
|
||||
|
||||
var/list/admin_verbs_paranoid_debug = list(
|
||||
|
||||
@@ -535,3 +535,18 @@
|
||||
set category = "Debug.Misc"
|
||||
|
||||
src.stat_panel.send_message("create_debug")
|
||||
|
||||
/client/proc/spawn_reagent()
|
||||
set name = "Spawn Reagent"
|
||||
set category = "Debug.Game"
|
||||
|
||||
if(!check_rights(R_ADMIN|R_EVENT)) return
|
||||
var/datum/reagent/R = tgui_input_list(usr, "Select a reagent to spawn", "Reagent Spawner", subtypesof(/datum/reagent))
|
||||
if(!R)
|
||||
return
|
||||
|
||||
var/obj/item/reagent_containers/glass/bottle/B = new(usr.loc)
|
||||
|
||||
B.icon_state = "bottle-1"
|
||||
B.reagents.add_reagent(R.id, 60)
|
||||
B.name = "[B.name] of [R.name]"
|
||||
|
||||
@@ -662,12 +662,14 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
//New message handling
|
||||
post_comm_message(customname, replacetext(input, "\n", "<br/>"))
|
||||
|
||||
switch(tgui_alert(usr, "Should this be announced to the general population?","Show world?",list("Yes","No")))
|
||||
if("Yes")
|
||||
command_announcement.Announce(input, customname, new_sound = 'sound/AI/commandreport.ogg', msg_sanitized = 1);
|
||||
if("No")
|
||||
to_world(span_red("New [using_map.company_name] Update available at all communication consoles."))
|
||||
world << sound('sound/AI/commandreport.ogg')
|
||||
var/confirm = tgui_alert(usr, "Should this be announced to the general population?","Show world?",list("Yes","No"))
|
||||
if(!confirm)
|
||||
return
|
||||
if(confirm == "Yes")
|
||||
command_announcement.Announce(input, customname, new_sound = 'sound/AI/commandreport.ogg', msg_sanitized = 1);
|
||||
else
|
||||
to_world(span_red("New [using_map.company_name] Update available at all communication consoles."))
|
||||
world << sound('sound/AI/commandreport.ogg')
|
||||
|
||||
log_admin("[key_name(src)] has created a command report: [input]")
|
||||
message_admins("[key_name_admin(src)] has created a command report", 1)
|
||||
|
||||
@@ -3,14 +3,18 @@
|
||||
desc = "An updated, modular intercom that fits over the head with extra comfortable for the hardworking casino luxury crew. Has encryption key for scamm-... Kind casino staff channel."
|
||||
icon = 'icons/obj/casino.dmi'
|
||||
icon_state = "headset"
|
||||
adhoc_fallback = TRUE
|
||||
origin_tech = list(TECH_ILLEGAL = 1)
|
||||
ks1type = /obj/item/encryptionkey/casino
|
||||
|
||||
/obj/item/radio/headset/casino/bowman
|
||||
/obj/item/radio/headset/alt/casino
|
||||
name = "casino bowman headset"
|
||||
desc = "An updated, modular intercom that fits over the head with extra comfortable for the hardworking casino luxury crew. Has encryption key for scamm-... Kind casino staff channel."
|
||||
icon = 'icons/obj/casino.dmi'
|
||||
icon_state = "headset_alt"
|
||||
adhoc_fallback = TRUE
|
||||
origin_tech = list(TECH_ILLEGAL = 2)
|
||||
ks1type = /obj/item/encryptionkey/casino
|
||||
|
||||
/obj/item/encryptionkey/casino
|
||||
icon = 'icons/obj/casino.dmi'
|
||||
|
||||
@@ -20,10 +20,11 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set
|
||||
//VOREStation Add
|
||||
"lost drone" = 1, // 16
|
||||
"maint pred" = 1, // 17
|
||||
"morph" = 1, // 18
|
||||
"corgi" = 1, // 19
|
||||
"cursed sword" = 1, // 20
|
||||
"Ship Survivor" = 1, // 21
|
||||
"maint lurker" = 1, // 18
|
||||
"morph" = 1, // 19
|
||||
"corgi" = 1, // 20
|
||||
"cursed sword" = 1, // 21
|
||||
"Ship Survivor" = 1, // 22
|
||||
//VOREStation Add End
|
||||
)
|
||||
|
||||
|
||||
@@ -68,35 +68,7 @@
|
||||
if(!pref.voice_sound)
|
||||
character.voice_sounds_list = talk_sound
|
||||
else
|
||||
switch(pref.voice_sound)
|
||||
if("beep-boop")
|
||||
character.voice_sounds_list = talk_sound
|
||||
if("goon speak 1")
|
||||
character.voice_sounds_list = goon_speak_one_sound
|
||||
if("goon speak 2")
|
||||
character.voice_sounds_list = goon_speak_two_sound
|
||||
if("goon speak 3")
|
||||
character.voice_sounds_list = goon_speak_three_sound
|
||||
if("goon speak 4")
|
||||
character.voice_sounds_list = goon_speak_four_sound
|
||||
if("goon speak blub")
|
||||
character.voice_sounds_list = goon_speak_blub_sound
|
||||
if("goon speak bottalk")
|
||||
character.voice_sounds_list = goon_speak_bottalk_sound
|
||||
if("goon speak buwoo")
|
||||
character.voice_sounds_list = goon_speak_buwoo_sound
|
||||
if("goon speak cow")
|
||||
character.voice_sounds_list = goon_speak_cow_sound
|
||||
if("goon speak lizard")
|
||||
character.voice_sounds_list = goon_speak_lizard_sound
|
||||
if("goon speak pug")
|
||||
character.voice_sounds_list = goon_speak_pug_sound
|
||||
if("goon speak pugg")
|
||||
character.voice_sounds_list = goon_speak_pugg_sound
|
||||
if("goon speak roach")
|
||||
character.voice_sounds_list = goon_speak_roach_sound
|
||||
if("goon speak skelly")
|
||||
character.voice_sounds_list = goon_speak_skelly_sound
|
||||
character.voice_sounds_list = get_talk_sound(pref.voice_sound)
|
||||
character.custom_speech_bubble = pref.custom_speech_bubble
|
||||
|
||||
/datum/category_item/player_setup_item/vore/size/content(var/mob/user)
|
||||
|
||||
@@ -482,3 +482,243 @@ var/list/preferences_datums = list()
|
||||
save_character()
|
||||
attempt_vr(user.client?.prefs_vr,"load_vore","")
|
||||
ShowChoices(user)
|
||||
|
||||
/datum/preferences/proc/vanity_copy_to(var/mob/living/carbon/human/character, var/copy_name, var/copy_flavour = TRUE, var/copy_ooc_notes = FALSE, var/convert_to_prosthetics = FALSE)
|
||||
//snowflake copy_to, does not copy anything but the vanity things
|
||||
//does not check if the name is the same, do that in any proc that calls this proc
|
||||
/*
|
||||
name, nickname, flavour, OOC notes
|
||||
gender, sex
|
||||
custom species name, custom bodytype, weight, scale, scaling center, sound type, sound freq
|
||||
custom say verbs
|
||||
ears, wings, tail, hair, facial hair
|
||||
ears colors, wings colors, tail colors
|
||||
body color, prosthetics (if they're a protean) (convert to DSI if protean and not prosthetic), eye color, hair color etc
|
||||
markings
|
||||
custom synth markings toggle, custom synth color toggle
|
||||
digitigrade
|
||||
blood color
|
||||
*/
|
||||
if (copy_name)
|
||||
if(CONFIG_GET(flag/humans_need_surnames))
|
||||
var/firstspace = findtext(real_name, " ")
|
||||
var/name_length = length(real_name)
|
||||
if(!firstspace) //we need a surname
|
||||
real_name += " [pick(last_names)]"
|
||||
else if(firstspace == name_length)
|
||||
real_name += "[pick(last_names)]"
|
||||
character.real_name = real_name
|
||||
character.name = character.real_name
|
||||
if(character.dna)
|
||||
character.dna.real_name = character.real_name
|
||||
character.nickname = nickname
|
||||
character.gender = biological_gender
|
||||
character.identifying_gender = identifying_gender
|
||||
|
||||
character.r_eyes = r_eyes
|
||||
character.g_eyes = g_eyes
|
||||
character.b_eyes = b_eyes
|
||||
character.h_style = h_style
|
||||
character.r_hair = r_hair
|
||||
character.g_hair = g_hair
|
||||
character.b_hair = b_hair
|
||||
character.r_grad = r_grad
|
||||
character.g_grad = g_grad
|
||||
character.b_grad = b_grad
|
||||
character.f_style = f_style
|
||||
character.r_facial = r_facial
|
||||
character.g_facial = g_facial
|
||||
character.b_facial = b_facial
|
||||
character.r_skin = r_skin
|
||||
character.g_skin = g_skin
|
||||
character.b_skin = b_skin
|
||||
character.s_tone = s_tone
|
||||
character.h_style = h_style
|
||||
character.grad_style= grad_style
|
||||
character.f_style = f_style
|
||||
character.grad_style= grad_style
|
||||
character.b_type = b_type
|
||||
character.synth_color = synth_color
|
||||
character.r_synth = r_synth
|
||||
character.g_synth = g_synth
|
||||
character.b_synth = b_synth
|
||||
character.synth_markings = synth_markings
|
||||
|
||||
var/list/ear_styles = get_available_styles(global.ear_styles_list)
|
||||
character.ear_style = ear_styles[ear_style]
|
||||
character.r_ears = r_ears
|
||||
character.b_ears = b_ears
|
||||
character.g_ears = g_ears
|
||||
character.r_ears2 = r_ears2
|
||||
character.b_ears2 = b_ears2
|
||||
character.g_ears2 = g_ears2
|
||||
character.r_ears3 = r_ears3
|
||||
character.b_ears3 = b_ears3
|
||||
character.g_ears3 = g_ears3
|
||||
|
||||
character.ear_secondary_style = ear_styles[ear_secondary_style]
|
||||
character.ear_secondary_colors = SANITIZE_LIST(ear_secondary_colors)
|
||||
|
||||
var/list/tail_styles = get_available_styles(global.tail_styles_list)
|
||||
character.tail_style = tail_styles[tail_style]
|
||||
character.r_tail = r_tail
|
||||
character.b_tail = b_tail
|
||||
character.g_tail = g_tail
|
||||
character.r_tail2 = r_tail2
|
||||
character.b_tail2 = b_tail2
|
||||
character.g_tail2 = g_tail2
|
||||
character.r_tail3 = r_tail3
|
||||
character.b_tail3 = b_tail3
|
||||
character.g_tail3 = g_tail3
|
||||
|
||||
var/list/wing_styles = get_available_styles(global.wing_styles_list)
|
||||
character.wing_style = wing_styles[wing_style]
|
||||
character.r_wing = r_wing
|
||||
character.b_wing = b_wing
|
||||
character.g_wing = g_wing
|
||||
character.r_wing2 = r_wing2
|
||||
character.b_wing2 = b_wing2
|
||||
character.g_wing2 = g_wing2
|
||||
character.r_wing3 = r_wing3
|
||||
character.b_wing3 = b_wing3
|
||||
character.g_wing3 = g_wing3
|
||||
|
||||
character.set_gender(biological_gender)
|
||||
|
||||
// Destroy/cyborgize organs and limbs.
|
||||
if (convert_to_prosthetics) //should only really be run for proteans
|
||||
var/list/organs_to_edit = list()
|
||||
for (var/name in list(BP_TORSO, BP_HEAD, BP_GROIN, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT))
|
||||
var/obj/item/organ/external/O = character.organs_by_name[name]
|
||||
if (O)
|
||||
var/x = organs_to_edit.Find(O.parent_organ)
|
||||
if (x == 0)
|
||||
organs_to_edit += name
|
||||
else
|
||||
organs_to_edit.Insert(x+(O.robotic == ORGAN_NANOFORM ? 1 : 0), name)
|
||||
for(var/name in organs_to_edit)
|
||||
var/status = organ_data[name]
|
||||
var/obj/item/organ/external/O = character.organs_by_name[name]
|
||||
if(O)
|
||||
if(status == "amputated")
|
||||
continue
|
||||
else if(status == "cyborg")
|
||||
O.robotize(rlimb_data[name])
|
||||
else
|
||||
var/bodytype
|
||||
var/datum/species/selected_species = GLOB.all_species[species]
|
||||
if(selected_species.selects_bodytype)
|
||||
bodytype = custom_base
|
||||
else
|
||||
bodytype = selected_species.get_bodytype()
|
||||
var/dsi_company = GLOB.dsi_to_species[bodytype]
|
||||
if (!dsi_company)
|
||||
dsi_company = "DSI - Adaptive"
|
||||
O.robotize(dsi_company)
|
||||
|
||||
for(var/N in character.organs_by_name)
|
||||
var/obj/item/organ/external/O = character.organs_by_name[N]
|
||||
O.markings.Cut()
|
||||
|
||||
var/priority = 0
|
||||
for(var/M in body_markings)
|
||||
priority += 1
|
||||
var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[M]
|
||||
|
||||
for(var/BP in mark_datum.body_parts)
|
||||
var/obj/item/organ/external/O = character.organs_by_name[BP]
|
||||
if(O)
|
||||
O.markings[M] = list("color" = body_markings[M][BP]["color"], "datum" = mark_datum, "priority" = priority, "on" = body_markings[M][BP]["on"])
|
||||
character.markings_len = priority
|
||||
|
||||
var/list/last_descriptors = list()
|
||||
if(islist(body_descriptors))
|
||||
last_descriptors = body_descriptors.Copy()
|
||||
body_descriptors = list()
|
||||
|
||||
var/datum/species/mob_species = GLOB.all_species[species]
|
||||
if(LAZYLEN(mob_species.descriptors))
|
||||
for(var/entry in mob_species.descriptors)
|
||||
var/datum/mob_descriptor/descriptor = mob_species.descriptors[entry]
|
||||
if(istype(descriptor))
|
||||
if(isnull(last_descriptors[entry]))
|
||||
body_descriptors[entry] = descriptor.default_value // Species datums have initial default value.
|
||||
else
|
||||
body_descriptors[entry] = CLAMP(last_descriptors[entry], 1, LAZYLEN(descriptor.standalone_value_descriptors))
|
||||
character.descriptors = body_descriptors
|
||||
|
||||
if (copy_flavour)
|
||||
character.flavor_texts["general"] = flavor_texts["general"]
|
||||
character.flavor_texts["head"] = flavor_texts["head"]
|
||||
character.flavor_texts["face"] = flavor_texts["face"]
|
||||
character.flavor_texts["eyes"] = flavor_texts["eyes"]
|
||||
character.flavor_texts["torso"] = flavor_texts["torso"]
|
||||
character.flavor_texts["arms"] = flavor_texts["arms"]
|
||||
character.flavor_texts["hands"] = flavor_texts["hands"]
|
||||
character.flavor_texts["legs"] = flavor_texts["legs"]
|
||||
character.flavor_texts["feet"] = flavor_texts["feet"]
|
||||
if (copy_ooc_notes)
|
||||
character.ooc_notes = metadata
|
||||
|
||||
character.weight = weight_vr
|
||||
character.weight_gain = weight_gain
|
||||
character.weight_loss = weight_loss
|
||||
character.fuzzy = fuzzy
|
||||
character.offset_override = offset_override
|
||||
character.voice_freq = voice_freq
|
||||
character.resize(size_multiplier, animate = FALSE, ignore_prefs = TRUE)
|
||||
|
||||
var/list/traits_to_copy = list(/datum/trait/neutral/tall,
|
||||
/datum/trait/neutral/taller,
|
||||
/datum/trait/neutral/short,
|
||||
/datum/trait/neutral/shorter,
|
||||
/datum/trait/neutral/obese,
|
||||
/datum/trait/neutral/fat,
|
||||
/datum/trait/neutral/thin,
|
||||
/datum/trait/neutral/thinner,
|
||||
/datum/trait/neutral/micro_size_down,
|
||||
/datum/trait/neutral/micro_size_up)
|
||||
//reset all the above trait vars
|
||||
if (character.species)
|
||||
character.species.micro_size_mod = 0
|
||||
character.species.icon_scale_x = 1
|
||||
character.species.icon_scale_y = 1
|
||||
for (var/trait in neu_traits)
|
||||
if (trait in traits_to_copy)
|
||||
var/datum/trait/instance = all_traits[trait]
|
||||
if (!instance)
|
||||
continue
|
||||
for (var/to_edit in instance.var_changes)
|
||||
character.species.vars[to_edit] = instance.var_changes[to_edit]
|
||||
character.update_transform()
|
||||
if(!voice_sound)
|
||||
character.voice_sounds_list = talk_sound
|
||||
else
|
||||
character.voice_sounds_list = get_talk_sound(voice_sound)
|
||||
|
||||
character.species?.blood_color = blood_color
|
||||
|
||||
var/datum/species/selected_species = GLOB.all_species[species]
|
||||
var/bodytype_selected
|
||||
if(selected_species.selects_bodytype)
|
||||
bodytype_selected = custom_base
|
||||
else
|
||||
bodytype_selected = selected_species.get_bodytype(character)
|
||||
|
||||
character.dna.base_species = bodytype_selected
|
||||
character.species.base_species = bodytype_selected
|
||||
character.species.vanity_base_fit = bodytype_selected
|
||||
if (istype(character.species, /datum/species/shapeshifter))
|
||||
wrapped_species_by_ref["\ref[character]"] = bodytype_selected
|
||||
|
||||
character.custom_species = custom_species
|
||||
character.custom_say = lowertext(trim(custom_say))
|
||||
character.custom_ask = lowertext(trim(custom_ask))
|
||||
character.custom_whisper = lowertext(trim(custom_whisper))
|
||||
character.custom_exclaim = lowertext(trim(custom_exclaim))
|
||||
|
||||
character.digitigrade = selected_species.digi_allowed ? digitigrade : 0
|
||||
|
||||
character.dna.ResetUIFrom(character)
|
||||
character.force_update_limbs()
|
||||
character.regenerate_icons()
|
||||
|
||||
@@ -48,7 +48,7 @@ BLIND // can't see anything
|
||||
// Prevent people from just turning their goggles back on.
|
||||
if(!active && (vision_flags & (SEE_TURFS|SEE_OBJS)))
|
||||
var/area/A = get_area(src)
|
||||
if(A.no_spoilers)
|
||||
if(A.flag_check(AREA_NO_SPOILERS))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
A collection of Protean rigsuit modules, intended to encourage Symbiotic relations with a host.
|
||||
All of these should require someone else to be wearing the Protean to function.
|
||||
These should come standard with the Protean rigsuit, unless you want them to work for some upgrades.
|
||||
*/
|
||||
|
||||
|
||||
//This rig module feeds nutrition directly from the wearer to the Protean, to help them stay charged while worn.
|
||||
/obj/item/rig_module/protean
|
||||
permanent = 1
|
||||
|
||||
/obj/item/rig_module/protean/syphon
|
||||
name = "Protean Metabolic Syphon"
|
||||
desc = "This should never be outside of a RIG."
|
||||
icon_state = "flash"
|
||||
interface_name = "Protean Metabolic Syphon"
|
||||
interface_desc = "Toggle to drain nutrition/power from the user directly into the Protean's own energy stores."
|
||||
toggleable = 1
|
||||
activate_string = "Enable Syphon"
|
||||
deactivate_string = "Disable Syphon"
|
||||
|
||||
/obj/item/rig_module/protean/syphon/activate()
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
if(H)
|
||||
to_chat(usr, span_boldnotice("You activate the suit's energy syphon."))
|
||||
to_chat(H, span_warning("Your suit begins to sap at your own energy stores."))
|
||||
active = 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/protean/syphon/deactivate(var/forced)
|
||||
if(!..())
|
||||
return 0
|
||||
if(forced)
|
||||
active = 0
|
||||
return
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
if(H)
|
||||
to_chat(usr, span_boldnotice("You deactivate the suit's energy syphon."))
|
||||
to_chat(H, span_warning("Your suit ceases from sapping your own energy."))
|
||||
active = 0
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/protean/syphon/process()
|
||||
if(active)
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
var/mob/living/P = holder?:myprotean
|
||||
if(istype(H.species, /datum/species/protean))
|
||||
to_chat(H, span_warning("Your Protean modules do not function on yourself."))
|
||||
deactivate(1)
|
||||
else
|
||||
P = P?:humanform
|
||||
if((H.nutrition >= 100) && (P.nutrition <= 5000))
|
||||
H.nutrition -= 10
|
||||
P.nutrition += 10
|
||||
|
||||
//This rig module allows a worn Protean to toggle and configure its armor settings.
|
||||
/obj/item/rig_module/protean/armor
|
||||
name = "Protean Adaptive Armor"
|
||||
desc = "This should never be outside of a RIG."
|
||||
interface_name = "Protean Adaptive Armor"
|
||||
interface_desc = "Adjusts the proteans deployed armor values to fit the needs of the wearer."
|
||||
usable = 1
|
||||
toggleable = 1
|
||||
activate_string = "Enable Armor"
|
||||
deactivate_string = "Disable Armor"
|
||||
engage_string = "Configure Armor"
|
||||
var/list/armor_settings = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0)
|
||||
var/armor_weight_ratio = 0.01 //This amount of slowdown per 1% of armour. 3 slowdown at the max armour.
|
||||
|
||||
/obj/item/rig_module/protean/armor/engage()
|
||||
var/armor_chosen = input(usr, "Which armor to adjust?", "Protean Armor") as null|anything in armor_settings
|
||||
if(armor_chosen)
|
||||
var/armorvalue = tgui_input_number(usr, "Set armour reduction value (Max of 60%)", "Protean Armor",0,60)
|
||||
if(isnum(armorvalue))
|
||||
armor_settings[armor_chosen] = armorvalue
|
||||
interface_desc = initial(interface_desc)
|
||||
slowdown = 0
|
||||
for(var/entry in armor_settings) //This is dumb and ugly but I dont feel like rewriting rig TGUI just to make this a pretty list
|
||||
interface_desc += " [entry]: [armor_settings[entry]]"
|
||||
slowdown += armor_settings[entry]*armor_weight_ratio
|
||||
interface_desc += " Slowdown: [slowdown]"
|
||||
|
||||
/obj/item/rig_module/protean/armor/activate()
|
||||
if(holder?:assimilated_rig)
|
||||
to_chat(usr, span_bolddanger("Armor module non-functional while a RIG is assimilated."))
|
||||
return
|
||||
if(!..(1))
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
if(H)
|
||||
var/list/temparmor = list("bio" = 100, "rad" = 100)
|
||||
temparmor = armor_settings + temparmor
|
||||
to_chat(usr, span_boldnotice("You signal the suit to harden."))
|
||||
to_chat(H, span_notice("Your suit hardens in response to physical trauma."))
|
||||
holder.armor = temparmor.Copy()
|
||||
for(var/obj/item/piece in list(holder.gloves,holder.helmet,holder.boots,holder.chest))
|
||||
piece.armor = temparmor.Copy()
|
||||
holder.slowdown = slowdown
|
||||
active = 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/protean/armor/deactivate(var/forced)
|
||||
if(!..(1))
|
||||
return 0
|
||||
if(forced)
|
||||
holder.armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100)
|
||||
for(var/obj/item/piece in list(holder.gloves,holder.helmet,holder.boots,holder.chest))
|
||||
piece.armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100)
|
||||
holder.slowdown = initial(slowdown)
|
||||
active = 0
|
||||
return
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
if(H)
|
||||
to_chat(usr, span_boldnotice("You signal the suit to relax."))
|
||||
to_chat(H, span_warning("Your suit softens."))
|
||||
holder.armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100)
|
||||
for(var/obj/item/piece in list(holder.gloves,holder.helmet,holder.boots,holder.chest))
|
||||
piece.armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100)
|
||||
holder.slowdown = initial(slowdown)
|
||||
active = 0
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/protean/armor/process()
|
||||
if(active)
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
if(istype(H.species, /datum/species/protean))
|
||||
to_chat(H, span_warning("Your Protean modules do not function on yourself."))
|
||||
deactivate(1)
|
||||
|
||||
|
||||
//This rig module lets a Protean expend its metal stores to heal its host
|
||||
/obj/item/rig_module/protean/healing
|
||||
name = "Protean Restorative Nanites"
|
||||
desc = "This should never be outside of a RIG."
|
||||
interface_name = "Protean Restorative Nanites"
|
||||
interface_desc = "Utilises stored steel from the Protean to slowly heal and repair the wearer."
|
||||
toggleable = 1
|
||||
activate_string = "Enable Healing"
|
||||
deactivate_string = "Disable Healing"
|
||||
var/datum/modifier/healing
|
||||
|
||||
/obj/item/rig_module/protean/healing/activate()
|
||||
if(!..(1))
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
var/mob/living/P = holder?:myprotean
|
||||
if(H && P)
|
||||
if(istype(H.species, /datum/species/protean))
|
||||
to_chat(H, span_warning("Your Protean modules do not function on yourself."))
|
||||
return 0
|
||||
var/obj/item/organ/internal/nano/refactory/R = P.nano_get_refactory()
|
||||
if(R.get_stored_material(MAT_STEEL) >= 100)
|
||||
healing = holder.wearer.add_modifier(/datum/modifier/protean/steel, origin = R)
|
||||
to_chat(usr, span_boldnotice("You activate the suit's restorative nanites."))
|
||||
to_chat(H, span_warning("Your suit begins mending your injuries."))
|
||||
active = 1
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/protean/healing/deactivate()
|
||||
if(!..(1))
|
||||
return 0
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
if(H)
|
||||
to_chat(usr, span_boldnotice("You deactivate the suit's restorative nanites."))
|
||||
to_chat(H, span_warning("Your suit is no longer mending your injuries."))
|
||||
active = 0
|
||||
if(healing)
|
||||
healing.expire()
|
||||
healing = null
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/protean/healing/process()
|
||||
if(active)
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
var/mob/living/P = holder?:myprotean
|
||||
if((istype(H.species, /datum/species/protean)) || !H || !P)
|
||||
to_chat(H, span_warning("Your Protean modules do not function on yourself."))
|
||||
deactivate()
|
||||
return
|
||||
var/obj/item/organ/internal/nano/refactory/R = P.nano_get_refactory()
|
||||
if((!R.get_stored_material(MAT_STEEL)))
|
||||
to_chat(H, span_warning("Your [holder] is out of steel."))
|
||||
deactivate()
|
||||
return
|
||||
|
||||
/obj/item/rig_module/protean/healing/accepts_item(var/obj/item/stack/material/steel/S, var/mob/living/user)
|
||||
|
||||
if(!istype(S) || !istype(user))
|
||||
return 0
|
||||
|
||||
var/mob/living/P = holder?:myprotean
|
||||
var/obj/item/organ/internal/nano/refactory/R = P?.nano_get_refactory()
|
||||
|
||||
if(R?.add_stored_material(S.material.name,1*S.perunit) && S.use(1))
|
||||
to_chat(user, span_boldnotice("You directly feed some steel to the [holder]."))
|
||||
return 1
|
||||
return 0
|
||||
@@ -100,6 +100,11 @@
|
||||
// Action button
|
||||
actions_types = list(/datum/action/item_action/hardsuit_interface)
|
||||
|
||||
// Protean
|
||||
var/protean = 0
|
||||
var/obj/item/storage/backpack/rig_storage
|
||||
permeability_coefficient = 0 //Protect the squishies, after all this shit should be waterproof.
|
||||
|
||||
/obj/item/rig/New()
|
||||
..()
|
||||
|
||||
@@ -538,7 +543,8 @@
|
||||
offline = 0
|
||||
if(istype(wearer) && !wearer.wearing_rig)
|
||||
wearer.wearing_rig = src
|
||||
slowdown = initial(slowdown)
|
||||
if(!istype(src,/obj/item/rig/protean)) // Stupid snowflake protean special check for rig assimilation code
|
||||
slowdown = initial(slowdown)
|
||||
|
||||
if(offline)
|
||||
if(offline == 1)
|
||||
@@ -914,15 +920,24 @@
|
||||
wearer.lay_down()
|
||||
to_chat(user, span_notice("\The [wearer] is now [wearer.resting ? "resting" : "getting up"]."))
|
||||
|
||||
/obj/item/rig/proc/forced_move(var/direction, var/mob/user)
|
||||
/obj/item/rig/proc/forced_move(var/direction, var/mob/user, var/ai_moving = TRUE)
|
||||
|
||||
// Why is all this shit in client/Move()? Who knows?
|
||||
if(world.time < wearer_move_delay)
|
||||
return
|
||||
|
||||
if(!wearer || !wearer.loc || !ai_can_move_suit(user, check_user_module = 1))
|
||||
if(!wearer || !wearer.loc) // Removed some stuff for protean living hardsuit
|
||||
return
|
||||
|
||||
// Added this for protean living hardsuit
|
||||
wearer_move_delay = world.time + 2
|
||||
if(ai_moving)
|
||||
if(!ai_can_move_suit(user, check_user_module = 1))
|
||||
return
|
||||
// AIs are a bit slower than regular and ignore move intent.
|
||||
// Moved this to where it's relevant
|
||||
wearer_move_delay = world.time + ai_controlled_move_delay
|
||||
|
||||
//This is sota the goto stop mobs from moving var
|
||||
if(wearer.transforming || !wearer.canmove)
|
||||
return
|
||||
@@ -953,9 +968,6 @@
|
||||
to_chat(src, span_notice("Your host is pinned to a wall by [wearer.pinned[1]]!"))
|
||||
return 0
|
||||
|
||||
// AIs are a bit slower than regular and ignore move intent.
|
||||
wearer_move_delay = world.time + ai_controlled_move_delay
|
||||
|
||||
if(istype(wearer.buckled, /obj/vehicle))
|
||||
//manually set move_delay for vehicles so we don't inherit any mob movement penalties
|
||||
//specific vehicle move delays are set in code\modules\vehicles\vehicle.dm
|
||||
@@ -980,7 +992,10 @@
|
||||
wearer_move_delay += 2
|
||||
return wearer.buckled.relaymove(wearer,direction)
|
||||
|
||||
cell.use(200) //Arbitrary, TODO
|
||||
var/power_cost = 200
|
||||
if(!ai_moving)
|
||||
power_cost = 20
|
||||
cell.use(power_cost) //Arbitrary, TODO
|
||||
wearer.Move(get_step(get_turf(wearer),direction),direction)
|
||||
|
||||
// This returns the rig if you are contained inside one, but not if you are wearing it
|
||||
|
||||
@@ -8,7 +8,7 @@ var/global/list/env_messages = list()
|
||||
mouse_opacity = TRUE
|
||||
anchored = TRUE
|
||||
var/list/message_list = list()
|
||||
var/combined_message = "You should not see this"
|
||||
var/combined_message = DEVELOPER_WARNING_NAME
|
||||
|
||||
/obj/effect/env_message/Initialize(mapload)
|
||||
.=..()
|
||||
|
||||
@@ -3,7 +3,8 @@ GLOBAL_LIST_EMPTY(current_pending_diseases)
|
||||
var/datum/disease/chosen_disease
|
||||
var/list/disease_blacklist = list(
|
||||
/datum/disease/advance,
|
||||
/datum/disease/food_poisoning
|
||||
/datum/disease/food_poisoning,
|
||||
/datum/disease/gbs // Terrible. It's only in the code to scare people.
|
||||
)
|
||||
var/static/list/transmissable_symptoms = list()
|
||||
var/static/list/diseases_minor = list()
|
||||
@@ -44,7 +45,7 @@ GLOBAL_LIST_EMPTY(current_pending_diseases)
|
||||
continue
|
||||
if(!(A.z in using_map.station_levels))
|
||||
continue
|
||||
if(A.flags & RAD_SHIELDED)
|
||||
if(A.flag_check(RAD_SHIELDED))
|
||||
continue
|
||||
if(isbelly(G.loc))
|
||||
continue
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines)
|
||||
var/area/A = get_area(temp_vent)
|
||||
if(A.forbid_events)
|
||||
if(A.flag_check(AREA_FORBID_EVENTS))
|
||||
continue
|
||||
if(!temp_vent.welded && temp_vent.network && (temp_vent.loc.z in using_map.station_levels))
|
||||
if(temp_vent.network.normal_members.len > 50)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
if(!(T.z in using_map.station_levels))
|
||||
continue
|
||||
var/area/A = get_area(T)
|
||||
if(A.flags & RAD_SHIELDED || A.flags & BLUE_SHIELDED)
|
||||
if(A.flag_check(RAD_SHIELDED | BLUE_SHIELDED))
|
||||
continue
|
||||
place_ian(T)
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
if(!(S.z in affecting_z))
|
||||
continue
|
||||
var/area/A = get_area(S)
|
||||
if(!A || A.flags & RAD_SHIELDED) // Rad shielding will protect from ions too
|
||||
if(!A || A.flag_check(RAD_SHIELDED)) // Rad shielding will protect from ions too
|
||||
continue
|
||||
to_chat(S, span_warning("Your integrated sensors detect an ionospheric anomaly. Your systems will be impacted as you begin a partial restart."))
|
||||
var/ionbug = rand(3, 9)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/datum/event/maintenance_lurker
|
||||
startWhen = 1
|
||||
endWhen = 30
|
||||
|
||||
/datum/event/maintenance_lurker/start()
|
||||
|
||||
var/obj/effect/landmark/spawnspot = null
|
||||
var/list/possibleSpawnspots = list()
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name == "maint_pred")
|
||||
possibleSpawnspots += L
|
||||
if(possibleSpawnspots.len)
|
||||
spawnspot = pick(possibleSpawnspots)
|
||||
else
|
||||
kill() // To prevent fake announcements
|
||||
return
|
||||
|
||||
if(!spawnspot)
|
||||
kill() // To prevent fake announcements
|
||||
return
|
||||
|
||||
new /obj/structure/ghost_pod/ghost_activated/maint_lurker(get_turf(spawnspot))
|
||||
@@ -39,7 +39,7 @@
|
||||
var/area/A = get_area(C)
|
||||
if(!A)
|
||||
continue
|
||||
if(A.flags & RAD_SHIELDED)
|
||||
if(A.flag_check(RAD_SHIELDED))
|
||||
continue
|
||||
if(istype(C,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = C
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
if(!temp_vent.welded && temp_vent.network && (temp_vent.loc.z in using_map.station_levels))
|
||||
if(temp_vent.network.normal_members.len > 50)
|
||||
var/area/A = get_area(temp_vent)
|
||||
if(!(A.forbid_events))
|
||||
if(!(A.flag_check(AREA_FORBID_EVENTS)))
|
||||
vents += temp_vent
|
||||
|
||||
while((spawncount >= 1) && vents.len)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
continue
|
||||
if(!(A.z in using_map.station_levels))
|
||||
continue
|
||||
if(A.flags & RAD_SHIELDED)
|
||||
if(A.flag_check(RAD_SHIELDED))
|
||||
continue
|
||||
if(isbelly(H.loc))
|
||||
continue
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
if(istype(candidate, /turf/simulated/wall))
|
||||
center = candidate
|
||||
var/area/A = get_area(candidate)
|
||||
if(!A.forbid_events)
|
||||
if(!A.flag_check(AREA_FORBID_EVENTS))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -35,4 +35,4 @@
|
||||
|
||||
// Only rot up to severity walls
|
||||
if(rotcount >= actual_severity)
|
||||
break
|
||||
break
|
||||
|
||||
@@ -81,4 +81,16 @@
|
||||
|
||||
/obj/item/storage/box/glasses/coffeemug
|
||||
name = "box of coffee mugs"
|
||||
starts_with = list(/obj/item/reagent_containers/food/drinks/glass2/coffeemug = 7)
|
||||
starts_with = list(/obj/item/reagent_containers/food/drinks/glass2/coffeemug = 7)
|
||||
|
||||
/obj/item/storage/box/glasses/coffeecup_tall
|
||||
name = "box of tall cups"
|
||||
starts_with = list(/obj/item/reagent_containers/food/drinks/tall = 7)
|
||||
|
||||
/obj/item/storage/box/glasses/coffeecup_grande
|
||||
name = "box of grande cups"
|
||||
starts_with = list(/obj/item/reagent_containers/food/drinks/grande = 7)
|
||||
|
||||
/obj/item/storage/box/glasses/coffeecup_venti
|
||||
name = "box of venti cups"
|
||||
starts_with = list(/obj/item/reagent_containers/food/drinks/venti = 7)
|
||||
|
||||
@@ -17,7 +17,12 @@
|
||||
icon_state = "cup_brown"
|
||||
|
||||
if(R.cup_name)
|
||||
name = R.cup_name
|
||||
var/prefix = " "
|
||||
for(var/datum/reagent/S in reagents.reagent_list)
|
||||
if(S.cup_prefix)
|
||||
var/current_prefix = prefix
|
||||
prefix = "[current_prefix][S.cup_prefix] "
|
||||
name = "cup of[prefix][R.cup_name]"
|
||||
else
|
||||
name = "Cup of.. what?"
|
||||
|
||||
|
||||
@@ -67,7 +67,12 @@
|
||||
icon_state = "cup_brown"
|
||||
|
||||
if(R.cup_name)
|
||||
name = R.cup_name
|
||||
var/prefix = " "
|
||||
for(var/datum/reagent/S in reagents.reagent_list)
|
||||
if(S.cup_prefix)
|
||||
var/current_prefix = prefix
|
||||
prefix = "[current_prefix][S.cup_prefix] "
|
||||
name = "cup of[prefix][R.cup_name]"
|
||||
else
|
||||
name = "Cup of.. what?"
|
||||
|
||||
@@ -161,3 +166,147 @@
|
||||
reagents.add_reagent(REAGENT_ID_IRON, 10)
|
||||
reagents.add_reagent("protein", 15)
|
||||
reagents.add_reagent(REAGENT_ID_WATER, 45)
|
||||
|
||||
|
||||
////////////////Fancy coffee cups
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/tall
|
||||
name = "tall cup"
|
||||
desc = "A larger coffee cup."
|
||||
icon_state = "tall_cup_empty"
|
||||
amount_per_transfer_from_this = 5
|
||||
volume = 40
|
||||
center_of_mass = list("x"=16, "y"=16)
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/tall/on_reagent_change()
|
||||
if (!length(reagents?.reagent_list))
|
||||
icon_state = "tall_cup_empty"
|
||||
name = "tall cup"
|
||||
desc = "A larger coffee cup."
|
||||
center_of_mass = list("x"=16, "y"=16)
|
||||
return
|
||||
var/datum/reagent/R = reagents.get_master_reagent()
|
||||
|
||||
if(R.cup_icon_state)
|
||||
icon_state = "tall_[R.cup_icon_state]"
|
||||
else
|
||||
icon_state = "tall_cup_brown"
|
||||
|
||||
if(R.cup_name)
|
||||
var/prefix = " "
|
||||
for(var/datum/reagent/S in reagents.reagent_list)
|
||||
if(S.cup_prefix)
|
||||
var/current_prefix = prefix
|
||||
prefix = "[current_prefix][S.cup_prefix] "
|
||||
name = "tall[prefix][R.cup_name]"
|
||||
else
|
||||
name = "tall.. what?"
|
||||
|
||||
if(R.cup_desc)
|
||||
desc = R.cup_desc
|
||||
else
|
||||
desc = "You can't really tell what this is."
|
||||
|
||||
if(R.cup_center_of_mass)
|
||||
center_of_mass = R.cup_center_of_mass
|
||||
else
|
||||
center_of_mass = list("x"=16, "y"=16)
|
||||
|
||||
if(R.price_tag)
|
||||
price_tag = R.price_tag
|
||||
else
|
||||
price_tag = null
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/grande
|
||||
name = "grande cup"
|
||||
desc = "A much taller coffee cup for people who really need their coffee."
|
||||
icon_state = "grande_cup_empty"
|
||||
amount_per_transfer_from_this = 5
|
||||
volume = 50
|
||||
center_of_mass = list("x"=16, "y"=16)
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/grande/on_reagent_change()
|
||||
if (!length(reagents?.reagent_list))
|
||||
icon_state = "grande_cup_empty"
|
||||
name = "grande cup"
|
||||
desc = "A much taller coffee cup for people who really need their coffee."
|
||||
center_of_mass = list("x"=16, "y"=16)
|
||||
return
|
||||
var/datum/reagent/R = reagents.get_master_reagent()
|
||||
|
||||
if(R.cup_icon_state)
|
||||
icon_state = "grande_[R.cup_icon_state]"
|
||||
else
|
||||
icon_state = "grande_cup_brown"
|
||||
|
||||
if(R.cup_name)
|
||||
var/prefix = " "
|
||||
for(var/datum/reagent/S in reagents.reagent_list)
|
||||
if(S.cup_prefix)
|
||||
var/current_prefix = prefix
|
||||
prefix = "[current_prefix][S.cup_prefix] "
|
||||
name = "grande[prefix][R.cup_name]"
|
||||
else
|
||||
name = "grande.. what?"
|
||||
|
||||
if(R.cup_desc)
|
||||
desc = R.cup_desc
|
||||
else
|
||||
desc = "You can't really tell what this is."
|
||||
|
||||
if(R.cup_center_of_mass)
|
||||
center_of_mass = R.cup_center_of_mass
|
||||
else
|
||||
center_of_mass = list("x"=16, "y"=16)
|
||||
|
||||
if(R.price_tag)
|
||||
price_tag = R.price_tag
|
||||
else
|
||||
price_tag = null
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/venti
|
||||
name = "venti cup"
|
||||
desc = "A huge coffee cup for people who literally cannot function without it."
|
||||
icon_state = "venti_cup_empty"
|
||||
amount_per_transfer_from_this = 5
|
||||
volume = 60
|
||||
center_of_mass = list("x"=16, "y"=16)
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/venti/on_reagent_change()
|
||||
if (!length(reagents?.reagent_list))
|
||||
icon_state = "venti_cup_empty"
|
||||
name = "venti cup"
|
||||
desc = "A huge coffee cup for people who literally cannot function without it."
|
||||
center_of_mass = list("x"=16, "y"=16)
|
||||
return
|
||||
var/datum/reagent/R = reagents.get_master_reagent()
|
||||
|
||||
if(R.cup_icon_state)
|
||||
icon_state = "venti_[R.cup_icon_state]"
|
||||
else
|
||||
icon_state = "venti_cup_brown"
|
||||
|
||||
if(R.cup_name)
|
||||
var/prefix = " "
|
||||
for(var/datum/reagent/S in reagents.reagent_list)
|
||||
if(S.cup_prefix)
|
||||
var/current_prefix = prefix
|
||||
prefix = "[current_prefix][S.cup_prefix] "
|
||||
name = "venti[prefix][R.cup_name]"
|
||||
else
|
||||
name = "venti.. what?"
|
||||
|
||||
if(R.cup_desc)
|
||||
desc = R.cup_desc
|
||||
else
|
||||
desc = "You can't really tell what this is."
|
||||
|
||||
if(R.cup_center_of_mass)
|
||||
center_of_mass = R.cup_center_of_mass
|
||||
else
|
||||
center_of_mass = list("x"=16, "y"=16)
|
||||
|
||||
if(R.price_tag)
|
||||
price_tag = R.price_tag
|
||||
else
|
||||
price_tag = null
|
||||
|
||||
@@ -107,7 +107,7 @@ This allows for events that have their announcement happen after the end itself.
|
||||
var/list/area/grand_list_of_areas = get_all_existing_areas_of_types(specific_areas)
|
||||
. = list()
|
||||
for(var/area/A as anything in shuffle(grand_list_of_areas))
|
||||
if(A.forbid_events)
|
||||
if(A.flag_check(AREA_FORBID_EVENTS))
|
||||
continue
|
||||
if(!(A.z in get_location_z_levels()))
|
||||
continue
|
||||
|
||||
@@ -196,7 +196,7 @@ Works together with spawning an observer, noted above.
|
||||
if(!isturf(loc))
|
||||
return
|
||||
var/area/A = get_area(src)
|
||||
if(A.block_ghosts)
|
||||
if(A.flag_check(AREA_BLOCK_GHOSTS))
|
||||
to_chat(src, span_warning("Ghosts can't enter this location."))
|
||||
return_to_spawn()
|
||||
|
||||
@@ -452,7 +452,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
|
||||
//RS Port #658 Start
|
||||
var/area/A = get_area(destination)
|
||||
if(A.block_ghosts)
|
||||
if(A.flag_check(AREA_BLOCK_GHOSTS))
|
||||
to_chat(src,span_warning("Sorry, that area does not allow ghosts."))
|
||||
if(following)
|
||||
stop_following()
|
||||
|
||||
@@ -373,3 +373,26 @@ var/list/holder_mob_icon_cache = list()
|
||||
icon = 'icons/mob/holder_complex.dmi'
|
||||
var/list/generate_for_slots = list(slot_l_hand_str, slot_r_hand_str, slot_back_str)
|
||||
slot_flags = SLOT_BACK
|
||||
|
||||
/obj/item/holder/proc/sync(var/mob/living/M)
|
||||
dir = 2
|
||||
overlays.Cut()
|
||||
if(M.item_state)
|
||||
item_state = M.item_state
|
||||
color = M.color
|
||||
name = M.name
|
||||
desc = M.desc
|
||||
overlays |= M.overlays
|
||||
|
||||
/obj/item/holder/protoblob
|
||||
slot_flags = SLOT_HEAD | SLOT_OCLOTHING | SLOT_HOLSTER | SLOT_ICLOTHING | SLOT_ID | SLOT_EARS
|
||||
w_class = ITEMSIZE_TINY
|
||||
allowed = list(/obj/item/gun,/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/melee/baton)
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/lefthand_holder.dmi',
|
||||
slot_r_hand_str = 'icons/mob/righthand_holder.dmi',
|
||||
slot_head_str = 'icons/mob/head.dmi',
|
||||
slot_w_uniform_str = 'icons/mob/uniform.dmi',
|
||||
slot_wear_suit_str = 'icons/mob/suit.dmi',
|
||||
slot_r_ear_str = 'icons/mob/ears.dmi',
|
||||
slot_l_ear_str = 'icons/mob/ears.dmi')
|
||||
|
||||
@@ -296,9 +296,9 @@
|
||||
if(href_list["default_lang"])
|
||||
if(href_list["default_lang"] == "reset")
|
||||
if (species_language)
|
||||
set_default_language(GLOB.all_languages[species_language])
|
||||
apply_default_language(GLOB.all_languages[species_language])
|
||||
else
|
||||
set_default_language(GLOB.all_languages[LANGUAGE_GIBBERISH])
|
||||
apply_default_language(GLOB.all_languages[LANGUAGE_GIBBERISH])
|
||||
else
|
||||
var/datum/language/L = locate(href_list["default_lang"])
|
||||
if(L && (L in languages))
|
||||
|
||||
@@ -126,11 +126,155 @@ var/static/icon/ingame_hud_med_vr = icon('icons/mob/hud_med_vr.dmi')
|
||||
//does not really need to happen, that kinda thing will only happen when putting another person's limb onto your own body
|
||||
return sorted
|
||||
|
||||
/mob/living/carbon/human/proc/transform_into_other_human(var/mob/living/carbon/human/character, var/copy_name, var/copy_flavour = TRUE, var/convert_to_prosthetics = FALSE)
|
||||
/*
|
||||
name, nickname, flavour, OOC notes
|
||||
gender, sex
|
||||
custom species name, custom bodytype, weight, scale, scaling center, sound type, sound freq
|
||||
custom say verbs
|
||||
ears, wings, tail, hair, facial hair
|
||||
ears colors, wings colors, tail colors
|
||||
body color, prosthetics (if they're a protean) (convert to DSI if protean and not prosthetic), eye color, hair color etc
|
||||
markings
|
||||
custom synth markings toggle, custom synth color toggle
|
||||
digitigrade
|
||||
blood color
|
||||
*/
|
||||
if (copy_name)
|
||||
name = character.name
|
||||
nickname = character.nickname
|
||||
gender = character.gender
|
||||
identifying_gender = character.identifying_gender
|
||||
|
||||
r_eyes = character.r_eyes
|
||||
g_eyes = character.g_eyes
|
||||
b_eyes = character.b_eyes
|
||||
h_style = character.h_style
|
||||
r_hair = character.r_hair
|
||||
g_hair = character.g_hair
|
||||
b_hair = character.b_hair
|
||||
r_grad = character.r_grad
|
||||
g_grad = character.g_grad
|
||||
b_grad = character.b_grad
|
||||
f_style = character.f_style
|
||||
r_facial = character.r_facial
|
||||
g_facial = character.g_facial
|
||||
b_facial = character.b_facial
|
||||
r_skin = character.r_skin
|
||||
g_skin = character.g_skin
|
||||
b_skin = character.b_skin
|
||||
s_tone = character.s_tone
|
||||
h_style = character.h_style
|
||||
grad_style = character.grad_style
|
||||
f_style = character.f_style
|
||||
grad_style = character.grad_style
|
||||
b_type = character.b_type
|
||||
synth_color = character.synth_color
|
||||
r_synth = character.r_synth
|
||||
g_synth = character.g_synth
|
||||
b_synth = character.b_synth
|
||||
synth_markings = character.synth_markings
|
||||
|
||||
ear_style = character.ear_style
|
||||
r_ears = character.r_ears
|
||||
b_ears = character.b_ears
|
||||
g_ears = character.g_ears
|
||||
r_ears2 = character.r_ears2
|
||||
b_ears2 = character.b_ears2
|
||||
g_ears2 = character.g_ears2
|
||||
r_ears3 = character.r_ears3
|
||||
b_ears3 = character.b_ears3
|
||||
g_ears3 = character.g_ears3
|
||||
|
||||
tail_style = character.tail_style
|
||||
r_tail = character.r_tail
|
||||
b_tail = character.b_tail
|
||||
g_tail = character.g_tail
|
||||
r_tail2 = character.r_tail2
|
||||
b_tail2 = character.b_tail2
|
||||
g_tail2 = character.g_tail2
|
||||
r_tail3 = character.r_tail3
|
||||
b_tail3 = character.b_tail3
|
||||
g_tail3 = character.g_tail3
|
||||
|
||||
wing_style = character.wing_style
|
||||
r_wing = character.r_wing
|
||||
b_wing = character.b_wing
|
||||
g_wing = character.g_wing
|
||||
r_wing2 = character.r_wing2
|
||||
b_wing2 = character.b_wing2
|
||||
g_wing2 = character.g_wing2
|
||||
r_wing3 = character.r_wing3
|
||||
b_wing3 = character.b_wing3
|
||||
g_wing3 = character.g_wing3
|
||||
|
||||
|
||||
var/bodytype = character.species?.get_bodytype()
|
||||
|
||||
if (convert_to_prosthetics) //should only really be run for proteans
|
||||
var/list/organs_to_edit = list()
|
||||
for (var/name in list(BP_TORSO, BP_HEAD, BP_GROIN, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT))
|
||||
var/obj/item/organ/external/O = character.organs_by_name[name]
|
||||
if (O)
|
||||
var/x = organs_to_edit.Find(O.parent_organ)
|
||||
if (x == 0)
|
||||
organs_to_edit += name
|
||||
else
|
||||
organs_to_edit.Insert(x+(O.robotic == ORGAN_NANOFORM ? 1 : 0), name)
|
||||
for(var/name in organs_to_edit)
|
||||
var/obj/item/organ/external/I = character.organs_by_name[name]
|
||||
var/obj/item/organ/external/O = organs_by_name[name]
|
||||
if(O)
|
||||
if(I.robotic >= ORGAN_ROBOT)
|
||||
O.robotize(I.model)
|
||||
else
|
||||
var/dsi_company = GLOB.dsi_to_species[bodytype]
|
||||
if (!dsi_company)
|
||||
dsi_company = "DSI - Adaptive"
|
||||
O.robotize(dsi_company)
|
||||
|
||||
for(var/N in character.organs_by_name)
|
||||
var/obj/item/organ/external/O = organs_by_name[N]
|
||||
var/obj/item/organ/external/I = character.organs_by_name[N]
|
||||
O.markings = I.markings.Copy()
|
||||
|
||||
markings_len = character.markings_len
|
||||
|
||||
descriptors = character.descriptors?.Copy()
|
||||
|
||||
if (copy_flavour)
|
||||
flavor_texts = character.flavor_texts?.Copy()
|
||||
|
||||
weight = character.weight
|
||||
weight_gain = character.weight_gain
|
||||
weight_loss = character.weight_loss
|
||||
fuzzy = character.fuzzy
|
||||
offset_override = character.offset_override
|
||||
voice_freq = character.voice_freq
|
||||
if (species && character.species)
|
||||
species.micro_size_mod = character.species.micro_size_mod
|
||||
species.icon_scale_x = character.species.icon_scale_x
|
||||
species.icon_scale_y = character.species.icon_scale_y
|
||||
update_transform()
|
||||
resize(character.size_multiplier, animate = TRUE, ignore_prefs = TRUE)
|
||||
voice_sounds_list = character.voice_sounds_list
|
||||
|
||||
species?.blood_color = character.species?.blood_color
|
||||
|
||||
dna?.base_species = bodytype
|
||||
species?.base_species = bodytype
|
||||
species?.vanity_base_fit = bodytype
|
||||
if (istype(species, /datum/species/shapeshifter))
|
||||
wrapped_species_by_ref["\ref[src]"] = bodytype
|
||||
|
||||
custom_species = character.custom_species
|
||||
custom_say = character.custom_say
|
||||
custom_ask = character.custom_ask
|
||||
custom_whisper = character.custom_whisper
|
||||
custom_exclaim = character.custom_exclaim
|
||||
|
||||
digitigrade = character.digitigrade
|
||||
|
||||
dna?.ResetUIFrom(src)
|
||||
force_update_limbs()
|
||||
regenerate_icons()
|
||||
|
||||
@@ -1631,7 +1631,7 @@
|
||||
|
||||
// Do this early so certain stuff gets turned off before vision is assigned.
|
||||
var/area/A = get_area(src)
|
||||
if(A?.no_spoilers)
|
||||
if(A?.flag_check(AREA_NO_SPOILERS))
|
||||
disable_spoiler_vision()
|
||||
|
||||
if(XRAY in mutations)
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
//RS Port #658 Start
|
||||
var/area/A = get_area(src)
|
||||
if(!client?.holder && A.block_phase_shift)
|
||||
if(!client?.holder && A.flag_check(AREA_BLOCK_PHASE_SHIFT))
|
||||
to_chat(src, span_warning("You can't do that here!"))
|
||||
return
|
||||
//RS Port #658 End
|
||||
|
||||
@@ -225,6 +225,8 @@
|
||||
var/rarity_value = 1 // Relative rarity/collector value for this species.
|
||||
var/economic_modifier = 2 // How much money this species makes
|
||||
|
||||
var/vanity_base_fit //when shapeshifting using vanity_copy_to, this allows you to have add something so they can go back to their original species fit
|
||||
|
||||
var/vore_belly_default_variant = "H"
|
||||
|
||||
// Determines the organs that the species spawns with and
|
||||
|
||||
@@ -16,7 +16,7 @@ var/list/wrapped_species_by_ref = list()
|
||||
//var/default_form = SPECIES_HUMAN //VOREStation edit
|
||||
|
||||
/datum/species/shapeshifter/get_valid_shapeshifter_forms(var/mob/living/carbon/human/H)
|
||||
return valid_transform_species
|
||||
return list(vanity_base_fit)|valid_transform_species
|
||||
|
||||
/datum/species/shapeshifter/get_icobase(var/mob/living/carbon/human/H, var/get_deform)
|
||||
if(!H) return ..(null, get_deform)
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_secondary_ears()
|
||||
set name = "Select Secondary Ears"
|
||||
set category = "Abilities"
|
||||
set category = "Abilities.Shapeshift"
|
||||
|
||||
if(stat || world.time < last_special)
|
||||
return
|
||||
@@ -78,12 +78,13 @@
|
||||
ear_secondary_style = ear_styles_list[pretty_ear_styles[new_ear_style]]
|
||||
|
||||
// Handle color picks
|
||||
var/list/new_colors = list()
|
||||
for(var/channel in 1 to ear_secondary_style.get_color_channel_count())
|
||||
var/channel_name = GLOB.fancy_sprite_accessory_color_channel_names[channel]
|
||||
var/default = LAZYACCESS(ear_secondary_colors, channel) || "#ffffff"
|
||||
var/new_color = input(usr, "Pick [channel_name]", "Ear Color ([channel_name])", default) as color | null
|
||||
new_colors += new_color || default
|
||||
if(ear_secondary_style)
|
||||
var/list/new_colors = list()
|
||||
for(var/channel in 1 to ear_secondary_style.get_color_channel_count())
|
||||
var/channel_name = GLOB.fancy_sprite_accessory_color_channel_names[channel]
|
||||
var/default = LAZYACCESS(ear_secondary_colors, channel) || "#ffffff"
|
||||
var/new_color = input(usr, "Pick [channel_name]", "Ear Color ([channel_name])", default) as color | null
|
||||
new_colors += new_color || default
|
||||
|
||||
update_hair()
|
||||
|
||||
|
||||
@@ -12,13 +12,15 @@
|
||||
//appearance_flags = RADIATION_GLOWS
|
||||
shock_resist = 0 // Lets not be immune to zaps.
|
||||
friendly = list("nuzzles", "glomps", "snuggles", "cuddles", "squishes") // lets be cute :3
|
||||
melee_damage_upper = 0
|
||||
melee_damage_lower = 0
|
||||
harm_intent_damage = 3
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 5
|
||||
player_msg = "You're a little squisher! Your cuteness level has increased tenfold."
|
||||
heat_damage_per_tick = 20 // Hot and cold are bad, but cold is AS bad for prommies as it is for slimes.
|
||||
cold_damage_per_tick = 20
|
||||
//glow_range = 0
|
||||
//glow_intensity = 0
|
||||
has_hands = 1 // brings in line with Proteans' own blob form.
|
||||
|
||||
var/mob/living/carbon/human/humanform
|
||||
var/datum/modifier/healing
|
||||
@@ -86,6 +88,13 @@
|
||||
humanform.species.update_misc_tabs(src)
|
||||
|
||||
/mob/living/simple_mob/slime/promethean/handle_special() // Should disable default slime healing, we'll use nutrition based heals instead.
|
||||
// They already heal from their carbon form while even in slime form, but this is for a small bonus healing for being unformed.
|
||||
adjustOxyLoss(-0.2)
|
||||
adjustToxLoss(-0.2)
|
||||
adjustFireLoss(-0.2)
|
||||
adjustCloneLoss(-0.2)
|
||||
adjustBruteLoss(-0.2)
|
||||
adjustHalLoss(-6) // HalLoss ticks down FAST
|
||||
if(rad_glow)
|
||||
rad_glow = CLAMP(rad_glow,0,250)
|
||||
set_light(max(1,min(5,rad_glow/15)), max(1,min(10,rad_glow/25)), color)
|
||||
@@ -368,25 +377,14 @@
|
||||
drop_from_inventory(H)
|
||||
things_to_drop -= H
|
||||
|
||||
for(var/obj/item/I in things_to_drop) //rip hoarders
|
||||
drop_from_inventory(I)
|
||||
|
||||
if(w_uniform && istype(w_uniform,/obj/item/clothing)) //No webbings tho. We do this after in case a suit was in the way
|
||||
var/obj/item/clothing/uniform = w_uniform
|
||||
if(LAZYLEN(uniform.accessories))
|
||||
for(var/obj/item/clothing/accessory/A in uniform.accessories)
|
||||
if(is_type_in_list(A, disallowed_protean_accessories))
|
||||
uniform.remove_accessory(null,A) //First param is user, but adds fingerprints and messages
|
||||
|
||||
//Size update
|
||||
blob.transform = matrix()*size_multiplier
|
||||
blob.size_multiplier = size_multiplier
|
||||
|
||||
if(l_hand) blob.prev_left_hand = l_hand //Won't save them if dropped above, but necessary if handdrop is disabled.
|
||||
if(r_hand) blob.prev_right_hand = r_hand
|
||||
if(l_hand) drop_from_inventory(l_hand)
|
||||
if(r_hand) drop_from_inventory(r_hand)
|
||||
|
||||
//Put our owner in it (don't transfer var/mind)
|
||||
blob.Weaken(2)
|
||||
blob.transforming = TRUE
|
||||
blob.ckey = ckey
|
||||
blob.ooc_notes = ooc_notes
|
||||
@@ -394,6 +392,7 @@
|
||||
blob.ooc_notes_dislikes = ooc_notes_dislikes
|
||||
blob.transforming = FALSE
|
||||
blob.name = name
|
||||
blob.real_name = real_name
|
||||
blob.nutrition = nutrition
|
||||
blob.color = rgb(r_skin, g_skin, b_skin)
|
||||
playsound(src.loc, "sound/effects/slime_squish.ogg", 15)
|
||||
@@ -411,6 +410,18 @@
|
||||
remove_verb(blob, /mob/living/proc/ventcrawl) // Absolutely not.
|
||||
remove_verb(blob, /mob/living/simple_mob/proc/set_name) // We already have a name.
|
||||
temporary_form = blob
|
||||
|
||||
var/obj/item/radio/R = null
|
||||
if(isradio(l_ear))
|
||||
R = l_ear
|
||||
if(isradio(r_ear))
|
||||
R = r_ear
|
||||
if(R)
|
||||
blob.mob_radio = R
|
||||
R.forceMove(blob)
|
||||
if(wear_id)
|
||||
blob.myid = wear_id.GetID()
|
||||
|
||||
//Mail them to nullspace
|
||||
moveToNullspace()
|
||||
|
||||
@@ -460,7 +471,6 @@
|
||||
forceMove(reform_spot)
|
||||
|
||||
//Put our owner in it (don't transfer var/mind)
|
||||
Weaken(2)
|
||||
playsound(src.loc, "sound/effects/slime_squish.ogg", 15)
|
||||
transforming = TRUE
|
||||
ckey = blob.ckey
|
||||
@@ -493,8 +503,15 @@
|
||||
B.owner = src
|
||||
|
||||
//vore_organs.Cut()
|
||||
if(blob.prev_left_hand) put_in_l_hand(blob.prev_left_hand) //The restore for when reforming.
|
||||
if(blob.prev_right_hand) put_in_r_hand(blob.prev_right_hand)
|
||||
|
||||
if(blob.l_hand) blob.drop_from_inventory(blob.l_hand)
|
||||
if(blob.r_hand) blob.drop_from_inventory(blob.r_hand)
|
||||
|
||||
if(blob.mob_radio)
|
||||
blob.mob_radio.forceMove(src)
|
||||
blob.mob_radio = null
|
||||
if(blob.myid)
|
||||
blob.myid = null
|
||||
|
||||
Life(1) //Fix my blindness right meow //Has to be moved up here, there exists a circumstance where blob could be deleted without vore organs moving right.
|
||||
|
||||
@@ -522,3 +539,8 @@
|
||||
else if(humanform.say_understands(other, speaking)) //So they're speaking something other than promethean or sign, let's just ask our original mob if it understands
|
||||
return TRUE
|
||||
else return FALSE
|
||||
|
||||
/mob/living/simple_mob/slime/promethean/character_directory_species()
|
||||
if (humanform)
|
||||
return "[humanform.custom_species ? humanform.custom_species : (humanform.species ? humanform.species.name : "Promethean Blob")]"
|
||||
return "Promethean Blob"
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
tt_desc = "Animated nanogoop"
|
||||
icon = 'icons/mob/species/protean/protean.dmi'
|
||||
icon_state = "to_puddle"
|
||||
icon_living = "puddle2"
|
||||
icon_rest = "rest"
|
||||
icon_dead = "puddle"
|
||||
icon_living = "puddle0-eyes" //Null icon, since we're made of overlays now.
|
||||
icon_rest = "puddle0-eyes"
|
||||
icon_dead = "puddle0-eyes"
|
||||
|
||||
faction = FACTION_NEUTRAL
|
||||
maxHealth = 200
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
show_stat_health = FALSE //We will do it ourselves
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "hits"
|
||||
response_help = "pets the"
|
||||
response_disarm = "gently pushes aside the "
|
||||
response_harm = "hits the"
|
||||
|
||||
harm_intent_damage = 2
|
||||
harm_intent_damage = 3
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 5
|
||||
attacktext = list("slashed")
|
||||
@@ -34,22 +34,32 @@
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 900
|
||||
movement_cooldown = -0.5 // Should mean that the little blurb about being quicker in blobform rings true. May need further adjusting.
|
||||
maxbodytemp = 1100
|
||||
movement_cooldown = 0
|
||||
hunger_rate = 0
|
||||
|
||||
var/mob/living/carbon/human/humanform
|
||||
var/obj/item/organ/internal/nano/refactory/refactory
|
||||
var/datum/modifier/healing
|
||||
|
||||
var/obj/prev_left_hand
|
||||
var/obj/prev_right_hand
|
||||
|
||||
var/human_brute = 0
|
||||
var/human_burn = 0
|
||||
|
||||
player_msg = "In this form, you can move a little faster, your health will regenerate as long as you have metal in you, and you can ventcrawl!"
|
||||
player_msg = "In this form, your health will regenerate as long as you have metal in you."
|
||||
|
||||
can_buckle = TRUE //Blobsurfing
|
||||
can_buckle = 1
|
||||
buckle_lying = 1
|
||||
mount_offset_x = 0
|
||||
mount_offset_y = 0
|
||||
has_hands = 1
|
||||
shock_resist = 1
|
||||
nameset = 1
|
||||
holder_type = /obj/item/holder/protoblob
|
||||
var/hiding = 0
|
||||
vore_icons = 1
|
||||
vore_active = 1
|
||||
|
||||
plane = ABOVE_MOB_PLANE //Necessary for overlay based icons
|
||||
|
||||
/datum/say_list/protean_blob
|
||||
speak = list("Blrb?","Sqrsh.","Glrsh!")
|
||||
@@ -63,14 +73,88 @@
|
||||
humanform = H
|
||||
updatehealth()
|
||||
refactory = locate() in humanform.internal_organs
|
||||
add_verb(src, /mob/living/proc/ventcrawl)
|
||||
add_verb(src, /mob/living/proc/hide)
|
||||
add_verb(src,/mob/living/proc/ventcrawl)
|
||||
add_verb(src,/mob/living/proc/usehardsuit)
|
||||
add_verb(src,/mob/living/simple_mob/protean_blob/proc/nano_partswap)
|
||||
add_verb(src,/mob/living/simple_mob/protean_blob/proc/nano_regenerate)
|
||||
add_verb(src,/mob/living/simple_mob/protean_blob/proc/nano_metalnom)
|
||||
add_verb(src,/mob/living/simple_mob/protean_blob/proc/nano_blobform)
|
||||
add_verb(src,/mob/living/simple_mob/protean_blob/proc/nano_rig_transform)
|
||||
add_verb(src,/mob/living/simple_mob/protean_blob/proc/appearance_switch)
|
||||
add_verb(src,/mob/living/simple_mob/protean_blob/proc/nano_latch)
|
||||
else
|
||||
update_icon()
|
||||
add_verb(src,/mob/living/simple_mob/proc/animal_mount)
|
||||
add_verb(src,/mob/living/proc/toggle_rider_reins)
|
||||
|
||||
//Hidden verbs for macro hotkeying
|
||||
/mob/living/simple_mob/protean_blob/proc/nano_partswap()
|
||||
set name = "Ref - Single Limb"
|
||||
set desc = "Allows you to replace and reshape your limbs as you see fit."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
humanform.nano_partswap()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/proc/nano_regenerate()
|
||||
set name = "Total Reassembly (wip)"
|
||||
set desc = "Completely reassemble yourself from whatever save slot you have loaded in preferences. Assuming you meet the requirements."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
humanform.nano_regenerate()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/proc/nano_blobform()
|
||||
set name = "Toggle Blobform"
|
||||
set desc = "Switch between amorphous and humanoid forms."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
humanform.nano_blobform()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/proc/nano_metalnom()
|
||||
set name = "Ref - Store Metals"
|
||||
set desc = "If you're holding a stack of material, you can consume some and store it for later."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
humanform.nano_metalnom()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/proc/nano_rig_transform()
|
||||
set name = "Modify Form - Hardsuit"
|
||||
set desc = "Allows a protean to retract its mass into its hardsuit module at will."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
humanform.nano_rig_transform()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/proc/appearance_switch()
|
||||
set name = "Switch Blob Appearance"
|
||||
set desc = "Allows a protean blob to switch its outwards appearance."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
humanform.appearance_switch()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/proc/nano_latch()
|
||||
set name = "Latch/Unlatch host"
|
||||
set desc = "Allows a protean to forcibly latch or unlatch from a host."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
humanform.nano_latch()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/Login()
|
||||
. = ..()
|
||||
copy_from_prefs_vr(bellies = FALSE) //Load vore prefs
|
||||
..()
|
||||
plane_holder.set_vis(VIS_AUGMENTED, 1)
|
||||
plane_holder.set_vis(VIS_CH_HEALTH_VR, 1)
|
||||
plane_holder.set_vis(VIS_CH_ID, 1)
|
||||
plane_holder.set_vis(VIS_CH_STATUS_R, 1)
|
||||
plane_holder.set_vis(VIS_CH_BACKUP, 1) //Gonna need these so we can see the status of our host. Could probably write it so this only happens when worn, but eeehhh
|
||||
if(!riding_datum)
|
||||
riding_datum = new /datum/riding/simple_mob/protean_blob(src)
|
||||
|
||||
/datum/riding/simple_mob/protean_blob/handle_vehicle_layer()
|
||||
ridden.layer = OBJ_LAYER
|
||||
|
||||
/mob/living/simple_mob/protean_blob/MouseDrop_T()
|
||||
return
|
||||
|
||||
/mob/living/simple_mob/protean_blob/runechat_y_offset(width, height)
|
||||
return (..()) - (20*size_multiplier)
|
||||
|
||||
/mob/living/simple_mob/protean_blob/Destroy()
|
||||
humanform = null
|
||||
@@ -90,60 +174,44 @@
|
||||
/mob/living/simple_mob/protean_blob/speech_bubble_appearance()
|
||||
return "synthetic"
|
||||
|
||||
/mob/living/simple_mob/protean_blob/get_available_emotes()
|
||||
return global._robot_default_emotes.Copy()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/init_vore()
|
||||
return //Don't make a random belly, don't waste your time
|
||||
|
||||
/mob/living/simple_mob/protean_blob/isSynthetic()
|
||||
return TRUE // yup
|
||||
|
||||
/mob/living/simple_mob/protean_blob/get_available_emotes()
|
||||
var/list/fulllist = global._robot_default_emotes.Copy()
|
||||
fulllist |= global._human_default_emotes //they're living nanites, they can make whatever sounds they want
|
||||
return fulllist
|
||||
|
||||
/mob/living/simple_mob/protean_blob/update_misc_tabs()
|
||||
. = ..()
|
||||
if(humanform)
|
||||
humanform.species.update_misc_tabs(src)
|
||||
|
||||
/mob/living/simple_mob/protean_blob/update_icon()
|
||||
if(humanform)
|
||||
//Still have a refactory
|
||||
if(istype(refactory))
|
||||
icon_living = "puddle2"
|
||||
|
||||
//Else missing one
|
||||
else
|
||||
icon_living = "puddle1"
|
||||
|
||||
//Not human-based
|
||||
else
|
||||
icon_living = "puddle0"
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/updatehealth()
|
||||
if(humanform.nano_dead_check(src))
|
||||
return
|
||||
if(!humanform)
|
||||
return ..()
|
||||
|
||||
//Set the max
|
||||
maxHealth = humanform.getMaxHealth()*2 //HUMANS, and their 'double health', bleh.
|
||||
//Set us to their health, but, human health ignores robolimbs so we do it 'the hard way'
|
||||
human_brute = humanform.getActualBruteLoss()
|
||||
human_burn = humanform.getActualFireLoss()
|
||||
health = maxHealth - humanform.getOxyLoss() - humanform.getToxLoss() - humanform.getCloneLoss() - human_brute - human_burn
|
||||
health = maxHealth - humanform.getOxyLoss() - humanform.getToxLoss() - humanform.getCloneLoss() - humanform.getBruteLoss() - humanform.getFireLoss()
|
||||
|
||||
//Alive, becoming dead
|
||||
if((stat < DEAD) && (health <= 0))
|
||||
death()
|
||||
humanform.death()
|
||||
|
||||
nutrition = humanform.nutrition
|
||||
|
||||
//Overhealth
|
||||
if(health > getMaxHealth())
|
||||
health = getMaxHealth()
|
||||
|
||||
//Grab any other interesting values
|
||||
confused = humanform.confused
|
||||
radiation = humanform.radiation
|
||||
paralysis = humanform.paralysis
|
||||
|
||||
//Update our hud if we have one
|
||||
if(healths)
|
||||
if(stat != DEAD)
|
||||
@@ -174,14 +242,12 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/adjustBruteLoss(var/amount,var/include_robo)
|
||||
amount *= 1.5
|
||||
if(humanform)
|
||||
return humanform.adjustBruteLoss(amount)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/adjustFireLoss(var/amount,var/include_robo)
|
||||
amount *= 1.5
|
||||
if(humanform)
|
||||
return humanform.adjustFireLoss(amount)
|
||||
else
|
||||
@@ -211,6 +277,12 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/adjust_nutrition(amount)
|
||||
if(humanform)
|
||||
return humanform.adjust_nutrition(amount)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/emp_act(severity)
|
||||
if(humanform)
|
||||
return humanform.emp_act(severity)
|
||||
@@ -224,8 +296,10 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/rad_act(severity)
|
||||
if(istype(loc, /obj/item/rig))
|
||||
return //Don't irradiate us while we're in rig mode
|
||||
if(humanform)
|
||||
return humanform.ex_act(severity)
|
||||
return humanform.rad_act(severity)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -235,38 +309,55 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/death(gibbed, deathmessage = "dissolves away, leaving only a few spare parts!")
|
||||
/mob/living/simple_mob/protean_blob/death(gibbed, deathmessage = "Coalesces inwards, retreating into their core componants")
|
||||
if(humanform)
|
||||
humanform.death(gibbed, deathmessage)
|
||||
else
|
||||
animate(src, alpha = 0, time = 2 SECONDS)
|
||||
sleep(2 SECONDS)
|
||||
|
||||
if(!QDELETED(src)) // Human's handle death should have taken us, but maybe we were adminspawned or something without a human counterpart
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_mob/protean_blob/Life()
|
||||
. = ..()
|
||||
if(. && istype(refactory) && humanform)
|
||||
if(!healing && (human_brute || human_burn) && refactory.get_stored_material(MAT_STEEL) >= 100)
|
||||
healing = humanform.add_modifier(/datum/modifier/protean/steel, origin = refactory)
|
||||
else if(healing && !(human_brute || human_burn))
|
||||
if(!humanform.nano_dead_check(src))
|
||||
if(. && istype(refactory) && humanform)
|
||||
if(!healing && (human_brute || human_burn) && refactory.get_stored_material(MAT_STEEL) >= 100)
|
||||
healing = humanform.add_modifier(/datum/modifier/protean/steel, origin = refactory)
|
||||
else if(healing && !(human_brute || human_burn))
|
||||
healing.expire()
|
||||
healing = null
|
||||
else
|
||||
if(healing)
|
||||
healing.expire()
|
||||
healing = null
|
||||
|
||||
/mob/living/simple_mob/protean_blob/lay_down()
|
||||
var/obj/item/rig/rig = src.get_rig()
|
||||
if(rig)
|
||||
rig.force_rest(src)
|
||||
return
|
||||
..()
|
||||
if(resting)
|
||||
animate(src,alpha = 40,time = 1 SECOND)
|
||||
|
||||
/mob/living/simple_mob/protean_blob/verb/prot_hide()
|
||||
set name = "Hide Self"
|
||||
set desc = "Disperses your mass into a thin veil, making a trap to snatch prey with, or simply hide."
|
||||
set category = "Abilities.Protean"
|
||||
|
||||
if(!hiding)
|
||||
cut_overlays()
|
||||
icon = 'icons/mob/species/protean/protean.dmi'
|
||||
icon_state = "hide"
|
||||
sleep(7)
|
||||
mouse_opacity = 0
|
||||
plane = ABOVE_OBJ_PLANE
|
||||
hiding = 1
|
||||
else
|
||||
icon = 'icons/mob/species/protean/protean.dmi'
|
||||
mouse_opacity = 1
|
||||
icon_state = "wake"
|
||||
animate(src,alpha = 255,time = 1 SECOND)
|
||||
plane = MOB_PLANE
|
||||
plane = initial(plane)
|
||||
sleep(7)
|
||||
update_icon()
|
||||
hiding = 0
|
||||
//Potential glob noms
|
||||
if(can_be_drop_pred) //Toggleable in vore panel
|
||||
var/list/potentials = living_mobs(0)
|
||||
@@ -276,21 +367,15 @@
|
||||
if(target.buckled)
|
||||
target.buckled.unbuckle_mob(target, force = TRUE)
|
||||
target.forceMove(vore_selected)
|
||||
to_chat(target,span_vwarning("\The [src] quickly engulfs you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!"))
|
||||
to_chat(target,span_warning("\The [src] quickly engulfs you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!"))
|
||||
update_canmove()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/attack_target(var/atom/A)
|
||||
if(refactory && istype(A,/obj/item/stack/material))
|
||||
var/obj/item/stack/material/S = A
|
||||
var/substance = S.material.name
|
||||
var allowed = FALSE
|
||||
for(var/material in PROTEAN_EDIBLE_MATERIALS)
|
||||
if(material == substance) allowed = TRUE
|
||||
if(!allowed)
|
||||
return
|
||||
if(refactory.add_stored_material(S.material.name,1*S.perunit) && S.use(1))
|
||||
visible_message(span_infoplain(span_bold("[name]") + " gloms over some of \the [S], absorbing it."))
|
||||
/mob/living/simple_mob/protean_blob/update_canmove()
|
||||
if(hiding)
|
||||
canmove = 0
|
||||
return canmove
|
||||
else
|
||||
return ..()
|
||||
..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/attackby(var/obj/item/O, var/mob/user)
|
||||
if(refactory && istype(O,/obj/item/stack/material))
|
||||
@@ -306,104 +391,115 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/attack_hand(mob/living/L)
|
||||
if(L.get_effective_size() >= (src.get_effective_size() + 0.5) )
|
||||
src.get_scooped(L)
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/MouseDrop(var/atom/over_object)
|
||||
if(ishuman(over_object) && usr == src && src.Adjacent(over_object))
|
||||
var/mob/living/carbon/human/H = over_object
|
||||
get_scooped(H, TRUE)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/MouseEntered(location,control,params)
|
||||
if(resting)
|
||||
return
|
||||
..()
|
||||
|
||||
var/global/list/disallowed_protean_accessories = list(
|
||||
/obj/item/clothing/accessory/holster,
|
||||
/obj/item/clothing/accessory/storage,
|
||||
/obj/item/clothing/accessory/armor
|
||||
)
|
||||
/mob/living/simple_mob/protean_blob/character_directory_species()
|
||||
if (humanform)
|
||||
return "[humanform.custom_species ? humanform.custom_species : (humanform.species ? humanform.species.name : "Protean")]"
|
||||
return "Protean"
|
||||
|
||||
// Helpers - Unsafe, WILL perform change.
|
||||
/mob/living/carbon/human/proc/nano_intoblob(force)
|
||||
if(!force && !isturf(loc))
|
||||
if(!force && !isturf(loc) && !loc == /obj/item/rig/protean)
|
||||
to_chat(src,span_warning("You can't change forms while inside something."))
|
||||
return
|
||||
to_chat(src, span_notice("You rapidly disassociate your form."))
|
||||
if(force || do_after(src,20,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
handle_grasp() //It's possible to blob out before some key parts of the life loop. This results in things getting dropped at null. TODO: Fix the code so this can be done better.
|
||||
remove_micros(src, src) //Living things don't fare well in roblobs.
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(LAZYLEN(buckled_mobs))
|
||||
for(var/buckledmob in buckled_mobs)
|
||||
riding_datum.force_dismount(buckledmob)
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
|
||||
handle_grasp() //It's possible to blob out before some key parts of the life loop. This results in things getting dropped at null. TODO: Fix the code so this can be done better.
|
||||
remove_micros(src, src) //Living things don't fare well in roblobs.
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(LAZYLEN(buckled_mobs))
|
||||
for(var/buckledmob in buckled_mobs)
|
||||
riding_datum.force_dismount(buckledmob)
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
var/client/C = client
|
||||
|
||||
//Record where they should go
|
||||
var/atom/creation_spot = drop_location()
|
||||
//Record where they should go
|
||||
var/atom/creation_spot = drop_location()
|
||||
|
||||
//Create our new blob
|
||||
var/mob/living/simple_mob/protean_blob/blob = new(creation_spot,src)
|
||||
//Create our new blob
|
||||
var/mob/living/simple_mob/protean_blob/blob = new(creation_spot,src)
|
||||
|
||||
//Drop all our things
|
||||
var/list/things_to_drop = contents.Copy()
|
||||
var/list/things_to_not_drop = list(w_uniform,nif,l_store,r_store,wear_id,l_ear,r_ear) //And whatever else we decide for balancing.
|
||||
//Size update
|
||||
blob.transform = matrix()*size_multiplier
|
||||
blob.size_multiplier = size_multiplier
|
||||
|
||||
/* No for now, because insta-pepperspray or flash on unblob
|
||||
if(l_hand && l_hand.w_class <= ITEMSIZE_SMALL) //Hands but only if small or smaller
|
||||
things_to_not_drop += l_hand
|
||||
if(r_hand && r_hand.w_class <= ITEMSIZE_SMALL)
|
||||
things_to_not_drop += r_hand
|
||||
*/
|
||||
//dir update
|
||||
blob.dir = dir
|
||||
|
||||
things_to_drop -= things_to_not_drop //Crunch the lists
|
||||
things_to_drop -= organs //Mah armbs
|
||||
things_to_drop -= internal_organs //Mah sqeedily spooch
|
||||
if(l_hand) drop_l_hand()
|
||||
if(r_hand) drop_r_hand()
|
||||
|
||||
for(var/obj/item/I in things_to_drop) //rip hoarders
|
||||
if(I.protean_drop_whitelist)
|
||||
continue
|
||||
drop_from_inventory(I)
|
||||
//Put our owner in it (don't transfer var/mind)
|
||||
blob.ckey = ckey
|
||||
blob.ooc_notes = ooc_notes
|
||||
blob.ooc_notes_likes = ooc_notes_likes
|
||||
blob.ooc_notes_dislikes = ooc_notes_dislikes
|
||||
temporary_form = blob
|
||||
var/obj/item/radio/R = null
|
||||
if(isradio(l_ear))
|
||||
R = l_ear
|
||||
if(isradio(r_ear))
|
||||
R = r_ear
|
||||
if(R)
|
||||
blob.mob_radio = R
|
||||
R.forceMove(blob)
|
||||
if(wear_id)
|
||||
blob.myid = wear_id.GetID()
|
||||
|
||||
if(w_uniform && istype(w_uniform,/obj/item/clothing)) //No webbings tho. We do this after in case a suit was in the way
|
||||
var/obj/item/clothing/uniform = w_uniform
|
||||
if(LAZYLEN(uniform.accessories))
|
||||
for(var/obj/item/clothing/accessory/A in uniform.accessories)
|
||||
if(is_type_in_list(A, disallowed_protean_accessories))
|
||||
uniform.remove_accessory(null,A) //First param is user, but adds fingerprints and messages
|
||||
//Mail them to nullspace
|
||||
moveToNullspace()
|
||||
|
||||
//Size update
|
||||
blob.transform = matrix()*size_multiplier
|
||||
blob.size_multiplier = size_multiplier
|
||||
//Message
|
||||
blob.visible_message(span_infoplain(span_bold("[src.name]") + " collapses into a gooey blob!"))
|
||||
|
||||
if(l_hand) blob.prev_left_hand = l_hand //Won't save them if dropped above, but necessary if handdrop is disabled.
|
||||
if(r_hand) blob.prev_right_hand = r_hand
|
||||
//Duration of the to_puddle iconstate that the blob starts with
|
||||
sleep(13)
|
||||
blob.update_icon() //Will remove the collapse anim
|
||||
|
||||
//Put our owner in it (don't transfer var/mind)
|
||||
blob.ckey = ckey
|
||||
blob.ooc_notes = ooc_notes
|
||||
blob.ooc_notes_likes = ooc_notes_likes
|
||||
blob.ooc_notes_dislikes = ooc_notes_dislikes
|
||||
temporary_form = blob
|
||||
//Transfer vore organs
|
||||
blob.vore_organs = vore_organs.Copy()
|
||||
blob.vore_selected = vore_selected
|
||||
for(var/obj/belly/B as anything in vore_organs)
|
||||
B.forceMove(blob)
|
||||
B.owner = blob
|
||||
vore_organs.Cut()
|
||||
|
||||
//Mail them to nullspace
|
||||
moveToNullspace()
|
||||
//We can still speak our languages!
|
||||
blob.languages = languages.Copy()
|
||||
blob.name = real_name
|
||||
blob.real_name = real_name
|
||||
blob.voice_name = name
|
||||
|
||||
//Message
|
||||
blob.visible_message(span_infoplain(span_bold("[src.name]") + " collapses into a gooey blob!"))
|
||||
blob.update_icon(1)
|
||||
|
||||
//Duration of the to_puddle iconstate that the blob starts with
|
||||
sleep(13)
|
||||
blob.update_icon() //Will remove the collapse anim
|
||||
//Flip them to the protean panel
|
||||
addtimer(CALLBACK(src, PROC_REF(nano_set_panel), C), 4)
|
||||
|
||||
//Transfer vore organs
|
||||
blob.vore_organs = vore_organs
|
||||
blob.vore_selected = vore_selected
|
||||
for(var/obj/belly/B as anything in vore_organs)
|
||||
B.forceMove(blob)
|
||||
B.owner = blob
|
||||
|
||||
//We can still speak our languages!
|
||||
blob.languages = languages.Copy()
|
||||
|
||||
|
||||
//Return our blob in case someone wants it
|
||||
return blob
|
||||
//Return our blob in case someone wants it
|
||||
return blob
|
||||
else
|
||||
to_chat(src, span_warning("You must remain still to blobform!"))
|
||||
|
||||
//For some reason, there's no way to force drop all the mobs grabbed. This ought to fix that. And be moved elsewhere. Call with caution, doesn't handle cycles.
|
||||
/proc/remove_micros(var/src, var/mob/root)
|
||||
@@ -412,74 +508,126 @@ var/global/list/disallowed_protean_accessories = list(
|
||||
if(istype(I, /obj/item/holder))
|
||||
root.remove_from_mob(I)
|
||||
|
||||
/mob/living/proc/usehardsuit()
|
||||
set name = "Utilize Hardsuit Interface"
|
||||
set desc = "Allows a protean blob to open hardsuit interface."
|
||||
set category = "Abilities.Protean"
|
||||
|
||||
if(istype(loc, /obj/item/rig/protean))
|
||||
var/obj/item/rig/protean/prig = loc
|
||||
to_chat(src, "You attempt to interface with the [prig].")
|
||||
prig.tgui_interact(src)
|
||||
else
|
||||
to_chat(src, "You are not in RIG form.")
|
||||
|
||||
/mob/living/carbon/human/proc/nano_outofblob(var/mob/living/simple_mob/protean_blob/blob, force)
|
||||
if(!istype(blob))
|
||||
return
|
||||
|
||||
if(blob.loc == /obj/item/rig/protean)
|
||||
return
|
||||
if(!force && !isturf(blob.loc))
|
||||
to_chat(blob,span_warning("You can't change forms while inside something."))
|
||||
return
|
||||
to_chat(src, span_notice("You rapidly reassemble your form."))
|
||||
if(force || do_after(blob,20,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(LAZYLEN(buckled_mobs))
|
||||
for(var/buckledmob in buckled_mobs)
|
||||
riding_datum.force_dismount(buckledmob)
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(LAZYLEN(buckled_mobs))
|
||||
for(var/buckledmob in buckled_mobs)
|
||||
riding_datum.force_dismount(buckledmob)
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
var/client/C = blob.client
|
||||
|
||||
//Stop healing if we are
|
||||
if(blob.healing)
|
||||
blob.healing.expire()
|
||||
//Stop healing if we are
|
||||
if(blob.healing)
|
||||
blob.healing.expire()
|
||||
|
||||
//Play the animation
|
||||
blob.icon_state = "from_puddle"
|
||||
if(blob.mob_radio)
|
||||
blob.mob_radio.forceMove(src)
|
||||
blob.mob_radio = null
|
||||
if(blob.myid)
|
||||
blob.myid = null
|
||||
|
||||
//Message
|
||||
blob.visible_message(span_infoplain(span_bold("[src.name]") + " reshapes into a humanoid appearance!"))
|
||||
//Play the animation
|
||||
blob.icon_state = "from_puddle"
|
||||
|
||||
//Duration of above animation
|
||||
sleep(8)
|
||||
//Message
|
||||
blob.visible_message(span_infoplain(span_bold("[src.name]") + " reshapes into a humanoid appearance!"))
|
||||
|
||||
//Record where they should go
|
||||
var/atom/reform_spot = blob.drop_location()
|
||||
//Size update
|
||||
resize(blob.size_multiplier, FALSE, TRUE, ignore_prefs = TRUE)
|
||||
|
||||
//Size update
|
||||
resize(blob.size_multiplier, FALSE, ignore_prefs = TRUE)
|
||||
//Duration of above animation
|
||||
sleep(8)
|
||||
|
||||
//Move them back where the blob was
|
||||
forceMove(reform_spot)
|
||||
//Record where they should go
|
||||
var/atom/reform_spot = blob.drop_location()
|
||||
|
||||
//Put our owner in it (don't transfer var/mind)
|
||||
ckey = blob.ckey
|
||||
ooc_notes = blob.ooc_notes // Lets give the protean any updated notes from blob form.
|
||||
ooc_notes_likes = blob.ooc_notes_likes
|
||||
ooc_notes_dislikes = blob.ooc_notes_dislikes
|
||||
temporary_form = null
|
||||
//dir update
|
||||
dir = blob.dir
|
||||
|
||||
//Transfer vore organs
|
||||
vore_selected = blob.vore_selected
|
||||
for(var/obj/belly/B as anything in blob.vore_organs)
|
||||
B.forceMove(src)
|
||||
B.owner = src
|
||||
//Move them back where the blob was
|
||||
forceMove(reform_spot)
|
||||
|
||||
if(blob.prev_left_hand) put_in_l_hand(blob.prev_left_hand) //The restore for when reforming.
|
||||
if(blob.prev_right_hand) put_in_r_hand(blob.prev_right_hand)
|
||||
if(blob.l_hand) blob.drop_l_hand()
|
||||
if(blob.r_hand) blob.drop_r_hand()
|
||||
|
||||
Life(1) //Fix my blindness right meow //Has to be moved up here, there exists a circumstance where blob could be deleted without vore organs moving right.
|
||||
//Put our owner in it (don't transfer var/mind)
|
||||
ckey = blob.ckey
|
||||
ooc_notes = blob.ooc_notes // Lets give the protean any updated notes from blob form.
|
||||
ooc_notes_likes = blob.ooc_notes_likes
|
||||
ooc_notes_dislikes = blob.ooc_notes_dislikes
|
||||
temporary_form = null
|
||||
|
||||
//Get rid of friend blob
|
||||
qdel(blob)
|
||||
//Transfer vore organs
|
||||
vore_organs = blob.vore_organs.Copy()
|
||||
vore_selected = blob.vore_selected
|
||||
for(var/obj/belly/B as anything in blob.vore_organs)
|
||||
B.forceMove(src)
|
||||
B.owner = src
|
||||
languages = blob.languages.Copy()
|
||||
|
||||
//Return ourselves in case someone wants it
|
||||
return src
|
||||
Life(1) //Fix my blindness right meow //Has to be moved up here, there exists a circumstance where blob could be deleted without vore organs moving right.
|
||||
|
||||
/mob/living/simple_mob/protean_blob/CanStumbleVore(mob/living/target)
|
||||
if(target == humanform)
|
||||
return FALSE
|
||||
return ..()
|
||||
//Get rid of friend blob
|
||||
qdel(blob)
|
||||
|
||||
//Flip them to the protean panel
|
||||
addtimer(CALLBACK(src, PROC_REF(nano_set_panel), C), 4)
|
||||
|
||||
//Return ourselves in case someone wants it
|
||||
return src
|
||||
else
|
||||
to_chat(src, span_warning("You must remain still to reshape yourself!"))
|
||||
|
||||
/mob/living/carbon/human/proc/nano_set_panel(var/client/C)
|
||||
if(C)
|
||||
C.statpanel = "Protean"
|
||||
|
||||
/mob/living/simple_mob/protean_blob/ClickOn(var/atom/A, var/params)
|
||||
if(istype(loc, /obj/item/rig/protean))
|
||||
HardsuitClickOn(A)
|
||||
..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/can_use_rig()
|
||||
return 1
|
||||
|
||||
/mob/living/simple_mob/protean_blob/HardsuitClickOn(var/atom/A, var/alert_ai = 0)
|
||||
if(istype(loc, /obj/item/rig/protean))
|
||||
var/obj/item/rig/protean/prig = loc
|
||||
if(istype(prig) && !prig.offline && prig.selected_module)
|
||||
if(!prig.ai_can_move_suit(src))
|
||||
return 0
|
||||
prig.selected_module.engage(A, alert_ai)
|
||||
if(ismob(A)) // No instant mob attacking - though modules have their own cooldowns
|
||||
setClickCooldown(get_attack_speed())
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Don't eat yourself, idiot
|
||||
/mob/living/simple_mob/protean_blob/CanStumbleVore(mob/living/target)
|
||||
if(target == humanform)
|
||||
return FALSE
|
||||
@@ -491,3 +639,110 @@ var/global/list/disallowed_protean_accessories = list(
|
||||
if(PB.humanform == src)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/handle_mutations_and_radiation()
|
||||
humanform.handle_mutations_and_radiation()
|
||||
|
||||
/mob/living/simple_mob/protean_blob/update_icon()
|
||||
..()
|
||||
if(humanform)
|
||||
vis_height = 32
|
||||
cut_overlays()
|
||||
var/list/wide_icons = list(
|
||||
"lizard",
|
||||
"rat",
|
||||
"wolf"
|
||||
)
|
||||
var/list/tall_icons = list(
|
||||
"drake",
|
||||
"teppi",
|
||||
"panther"
|
||||
)
|
||||
var/list/big_icons = list(
|
||||
"robodrgn"
|
||||
)
|
||||
var/datum/species/protean/S = humanform.species
|
||||
icon = 'icons/mob/species/protean/protean.dmi'
|
||||
default_pixel_x = 0
|
||||
pixel_x = 0
|
||||
vore_capacity = 1
|
||||
if(S.blob_appearance == "dragon")
|
||||
vore_capacity = 2
|
||||
icon = 'icons/mob/vore128x64.dmi'
|
||||
mount_offset_y = 32
|
||||
mount_offset_x = -16
|
||||
var/image/I = image(icon, "[S.dragon_overlays[1]][resting? "-rest" : (vore_fullness? "-[vore_fullness]" : null)]", pixel_x = -48)
|
||||
I.color = S.dragon_overlays[S.dragon_overlays[1]]
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
I.plane = MOB_PLANE
|
||||
I.layer = MOB_LAYER
|
||||
add_overlay(I)
|
||||
qdel(I)
|
||||
|
||||
I = image(icon, "[S.dragon_overlays[2]][resting? "-rest" : null]", pixel_x = -48)
|
||||
I.color = S.dragon_overlays[S.dragon_overlays[2]]
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
I.plane = MOB_PLANE
|
||||
I.layer = MOB_LAYER
|
||||
add_overlay(I)
|
||||
qdel(I)
|
||||
|
||||
I = image(icon, "[S.dragon_overlays[3]][resting? "-rest" : null]", pixel_x = -48)
|
||||
I.color = S.dragon_overlays[S.dragon_overlays[3]]
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
I.plane = MOB_PLANE
|
||||
I.layer = MOB_LAYER
|
||||
add_overlay(I)
|
||||
qdel(I)
|
||||
|
||||
I = image(icon, "[S.dragon_overlays[4]][resting? "-rest" : null]", pixel_x = -48)
|
||||
I.color = S.dragon_overlays[S.dragon_overlays[4]]
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
I.plane = MOB_PLANE
|
||||
I.layer = MOB_LAYER
|
||||
add_overlay(I)
|
||||
qdel(I)
|
||||
|
||||
I = image(icon, "[S.dragon_overlays[5]][resting? "-rest" : null]", pixel_x = -48)
|
||||
I.color = S.dragon_overlays[S.dragon_overlays[5]]
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
I.plane = MOB_PLANE
|
||||
I.layer = MOB_LAYER
|
||||
add_overlay(I)
|
||||
qdel(I)
|
||||
|
||||
I = image(icon, "[S.dragon_overlays[6]][resting? "-rest" : null]", pixel_x = -48)
|
||||
I.color = S.dragon_overlays[S.dragon_overlays[6]]
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
I.plane = PLANE_LIGHTING_ABOVE
|
||||
add_overlay(I)
|
||||
qdel(I)
|
||||
|
||||
//You know technically I could just put all the icons into the 128x64.dmi file and off-set them to fit..
|
||||
if(S.blob_appearance in wide_icons)
|
||||
icon = 'icons/mob/species/protean/protean64x32.dmi'
|
||||
default_pixel_x = -16
|
||||
pixel_x = -16
|
||||
if(S.blob_appearance in tall_icons)
|
||||
icon = 'icons/mob/species/protean/protean64x64.dmi'
|
||||
default_pixel_x = -16
|
||||
pixel_x = -16
|
||||
vis_height = 64
|
||||
if(S.blob_appearance in big_icons)
|
||||
icon = 'icons/mob/species/protean/protean128x64.dmi'
|
||||
default_pixel_x = -48
|
||||
pixel_x = -48
|
||||
vis_height = 64
|
||||
var/image/I = image(icon, S.blob_appearance+"[resting? "_rest":null][vore_fullness? "-[vore_fullness]" : null]")
|
||||
I.color = S.blob_color_1
|
||||
I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE)
|
||||
I.plane = MOB_PLANE
|
||||
I.layer = MOB_LAYER
|
||||
add_overlay(I)
|
||||
qdel(I)
|
||||
eye_layer = image(icon, "[S.blob_appearance][resting? "_rest" : null]-eyes")
|
||||
eye_layer.appearance_flags = appearance_flags
|
||||
eye_layer.color = S.blob_color_2
|
||||
eye_layer.plane = PLANE_LIGHTING_ABOVE
|
||||
add_overlay(eye_layer)
|
||||
qdel(eye_layer)
|
||||
|
||||
+535
-188
@@ -1,3 +1,4 @@
|
||||
//TODO: Replace ventcrawl with morphing. /mob/living/simple_mob/vore/hostile/morph
|
||||
#define PER_LIMB_STEEL_COST SHEET_MATERIAL_AMOUNT
|
||||
////
|
||||
// One-part Refactor
|
||||
@@ -5,33 +6,39 @@
|
||||
/mob/living/carbon/human/proc/nano_partswap()
|
||||
set name = "Ref - Single Limb"
|
||||
set desc = "Allows you to replace and reshape your limbs as you see fit."
|
||||
set category = "Abilities"
|
||||
set hidden = TRUE
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
|
||||
var/mob/living/caller = src
|
||||
if(temporary_form)
|
||||
caller = temporary_form
|
||||
if(nano_dead_check(caller))
|
||||
to_chat(caller, span_warning("You need to be repaired first before you can act!"))
|
||||
return
|
||||
if(stat)
|
||||
to_chat(src,span_warning("You must be awake and standing to perform this action!"))
|
||||
to_chat(caller,span_warning("You must be awake and standing to perform this action!"))
|
||||
return
|
||||
|
||||
if(!isturf(loc))
|
||||
to_chat(src,span_warning("You need more space to perform this action!"))
|
||||
if(!isturf(caller.loc))
|
||||
to_chat(caller,span_warning("You need more space to perform this action!"))
|
||||
return
|
||||
|
||||
var/obj/item/organ/internal/nano/refactory/refactory = nano_get_refactory()
|
||||
//Missing the organ that does this
|
||||
if(!istype(refactory))
|
||||
to_chat(src,span_warning("You don't have a working refactory module!"))
|
||||
to_chat(caller,span_warning("You don't have a working refactory module!"))
|
||||
return
|
||||
|
||||
var/choice = tgui_input_list(src,"Pick the bodypart to change:", "Refactor - One Bodypart", species.has_limbs)
|
||||
var/choice = tgui_input_list(caller,"Pick the bodypart to change:", "Refactor - One Bodypart", species.has_limbs)
|
||||
if(!choice)
|
||||
return
|
||||
|
||||
//Organ is missing, needs restoring
|
||||
if(!organs_by_name[choice] || istype(organs_by_name[choice], /obj/item/organ/external/stump)) //allows limb stumps to regenerate like removed limbs.
|
||||
if(refactory.get_stored_material(MAT_STEEL) < PER_LIMB_STEEL_COST)
|
||||
to_chat(src,span_warning("You're missing that limb, and need to store at least [PER_LIMB_STEEL_COST] steel to regenerate it."))
|
||||
to_chat(caller,span_warning("You're missing that limb, and need to store at least [PER_LIMB_STEEL_COST] steel to regenerate it."))
|
||||
return
|
||||
var/regen = tgui_alert(src,"That limb is missing, do you want to regenerate it in exchange for [PER_LIMB_STEEL_COST] steel?","Regenerate limb?",list("Yes","No"))
|
||||
var/regen = tgui_alert(caller,"That limb is missing, do you want to regenerate it in exchange for [PER_LIMB_STEEL_COST] steel?","Regenerate limb?",list("Yes","No"))
|
||||
if(regen != "Yes")
|
||||
return
|
||||
if(!refactory.use_stored_material(MAT_STEEL,PER_LIMB_STEEL_COST))
|
||||
@@ -40,10 +47,13 @@
|
||||
var/obj/item/organ/external/oldlimb = organs_by_name[choice]
|
||||
oldlimb.removed()
|
||||
qdel(oldlimb)
|
||||
|
||||
var/mob/living/simple_mob/protean_blob/blob = nano_intoblob()
|
||||
active_regen = TRUE
|
||||
if(do_after(blob,5 SECONDS))
|
||||
var/mob/living/simple_mob/protean_blob/blob
|
||||
if(!temporary_form)
|
||||
blob = nano_intoblob()
|
||||
else
|
||||
blob = temporary_form
|
||||
active_regen = 1
|
||||
if(do_after(blob,50,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
var/list/limblist = species.has_limbs[choice]
|
||||
var/limbpath = limblist["path"]
|
||||
var/obj/item/organ/external/new_eo = new limbpath(src)
|
||||
@@ -51,8 +61,7 @@
|
||||
new_eo.robotize(synthetic ? synthetic.company : null) //Use the base we started with
|
||||
new_eo.sync_colour_to_human(src)
|
||||
regenerate_icons()
|
||||
active_regen = FALSE
|
||||
nano_outofblob(blob)
|
||||
active_regen = 0
|
||||
return
|
||||
|
||||
//Organ exists, let's reshape it
|
||||
@@ -68,7 +77,7 @@
|
||||
usable_manufacturers[company] = M
|
||||
if(!usable_manufacturers.len)
|
||||
return
|
||||
var/manu_choice = tgui_input_list(src, "Which manufacturer do you wish to mimic for this limb?", "Manufacturer for [choice]", usable_manufacturers)
|
||||
var/manu_choice = tgui_input_list(caller, "Which manufacturer do you wish to mimic for this limb?", "Manufacturer for [choice]", usable_manufacturers)
|
||||
|
||||
if(!manu_choice)
|
||||
return //Changed mind
|
||||
@@ -78,177 +87,199 @@
|
||||
return //Lost it meanwhile
|
||||
|
||||
eo.robotize(manu_choice)
|
||||
visible_message(span_infoplain(span_bold("[src]") + "'s [choice] loses its shape, then reforms."))
|
||||
update_icons_body()
|
||||
|
||||
////
|
||||
// Full Refactor
|
||||
////
|
||||
/mob/living/carbon/human/proc/nano_regenerate() //fixed the proc, it used to leave active_regen true.
|
||||
set name = "Ref - Whole Body"
|
||||
set desc = "Allows you to regrow limbs and replace organs, given you have enough materials."
|
||||
set category = "Abilities"
|
||||
set hidden = TRUE
|
||||
|
||||
if(stat)
|
||||
to_chat(src,span_warning("You must be awake and standing to perform this action!"))
|
||||
/mob/living/carbon/human/proc/nano_regenerate()
|
||||
set name = "Total Reassembly"
|
||||
set desc = "Fully repair yourself or reload your appearance from whatever character slot you have loaded."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
var/mob/living/caller = src
|
||||
if(temporary_form)
|
||||
caller = temporary_form
|
||||
var/input = tgui_alert(caller,{"Do you want to rebuild or reassemble yourself?
|
||||
Rebuilding will cost 10,000 steel and will rebuild all of your limbs as well as repair all damage over a 40s period.
|
||||
Reassembling costs no steel and will copy the appearance data of your currently loaded save slot."},"Reassembly",list("Rebuild","Reassemble","Cancel"))
|
||||
if(input == "Cancel" || !input)
|
||||
return
|
||||
|
||||
if(!isturf(loc))
|
||||
to_chat(src,span_warning("You need more space to perform this action!"))
|
||||
return
|
||||
|
||||
var/obj/item/organ/internal/nano/refactory/refactory = nano_get_refactory()
|
||||
//Missing the organ that does this
|
||||
if(!istype(refactory))
|
||||
to_chat(src,span_warning("You don't have a working refactory module!"))
|
||||
return
|
||||
|
||||
//Already regenerating
|
||||
if(active_regen)
|
||||
to_chat(src, span_warning("You are already refactoring!"))
|
||||
return
|
||||
|
||||
var/swap_not_rebuild = tgui_alert(src,"Do you want to rebuild, or reshape?","Rebuild or Reshape",list("Reshape","Cancel","Rebuild"))
|
||||
if(!swap_not_rebuild || swap_not_rebuild == "Cancel")
|
||||
return
|
||||
if(swap_not_rebuild == "Reshape")
|
||||
var/list/usable_manufacturers = list()
|
||||
for(var/company in chargen_robolimbs)
|
||||
var/datum/robolimb/M = chargen_robolimbs[company]
|
||||
if(!(BP_TORSO in M.parts))
|
||||
continue
|
||||
if(species?.base_species in M.species_cannot_use)
|
||||
continue
|
||||
if(M.whitelisted_to && !(ckey in M.whitelisted_to))
|
||||
continue
|
||||
usable_manufacturers[company] = M
|
||||
if(!usable_manufacturers.len)
|
||||
return
|
||||
var/manu_choice = tgui_input_list(src, "Which manufacturer do you wish to mimic?", "Manufacturer", usable_manufacturers)
|
||||
|
||||
if(!manu_choice)
|
||||
return //Changed mind
|
||||
if(!organs_by_name[BP_TORSO])
|
||||
return //Ain't got a torso!
|
||||
|
||||
var/obj/item/organ/external/torso = organs_by_name[BP_TORSO]
|
||||
to_chat(src, span_danger("Remain still while the process takes place! It will take 5 seconds."))
|
||||
visible_message(span_infoplain(span_bold("[src]") + "'s form collapses into an amorphous blob of black ichor..."))
|
||||
|
||||
var/mob/living/simple_mob/protean_blob/blob = nano_intoblob()
|
||||
active_regen = TRUE
|
||||
if(do_after(blob,5 SECONDS))
|
||||
synthetic = usable_manufacturers[manu_choice]
|
||||
torso.robotize(manu_choice) //Will cascade to all other organs.
|
||||
regenerate_icons()
|
||||
visible_message(span_infoplain(span_bold("[src]") + "'s form reshapes into a new one..."))
|
||||
active_regen = FALSE
|
||||
nano_outofblob(blob)
|
||||
return
|
||||
|
||||
//Not enough resources (AND spends the resources, should be the last check)
|
||||
if(!refactory.use_stored_material(MAT_STEEL,refactory.max_storage))
|
||||
to_chat(src, span_warning("You need to be maxed out on normal metal to do this!"))
|
||||
return
|
||||
|
||||
var/delay_length = round(active_regen_delay * species.active_regen_mult)
|
||||
to_chat(src, span_danger("Remain still while the process takes place! It will take [delay_length/10] seconds."))
|
||||
visible_message(span_infoplain(span_bold("[src]") + "'s form begins to shift and ripple as if made of oil..."))
|
||||
active_regen = TRUE
|
||||
|
||||
var/mob/living/simple_mob/protean_blob/blob = nano_intoblob()
|
||||
if(do_after(blob, delay_length, null, 0))
|
||||
if(stat != DEAD && refactory)
|
||||
var/list/holder = refactory.materials
|
||||
species.create_organs(src)
|
||||
var/obj/item/organ/external/torso = organs_by_name[BP_TORSO]
|
||||
torso.robotize() //synthetic wasn't defined here.
|
||||
LAZYCLEARLIST(blood_DNA)
|
||||
LAZYCLEARLIST(feet_blood_DNA)
|
||||
blood_color = null
|
||||
feet_blood_color = null
|
||||
regenerate_icons() //Probably worth it, yeah.
|
||||
var/obj/item/organ/internal/nano/refactory/new_refactory = locate() in internal_organs
|
||||
if(!new_refactory)
|
||||
log_debug("[src] protean-regen'd but lacked a refactory when done.")
|
||||
else
|
||||
new_refactory.materials = holder
|
||||
to_chat(src, span_notice("Your refactoring is complete.")) //Guarantees the message shows no matter how bad the timing.
|
||||
to_chat(blob, span_notice("Your refactoring is complete!"))
|
||||
if(input == "Rebuild")
|
||||
var/obj/item/organ/internal/nano/refactory/refactory = nano_get_refactory()
|
||||
if(refactory.get_stored_material(MAT_STEEL) >= 10000)
|
||||
to_chat(caller, span_notify("You begin to rebuild. You will need to remain still."))
|
||||
if(do_after(caller, 400,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
if(species?:OurRig) //Unsafe, but we should only ever be using this with a Protean
|
||||
species?:OurRig?:make_alive(src,1) //Re-using this proc
|
||||
refactory.use_stored_material(MAT_STEEL,refactory.get_stored_material(MAT_STEEL)) //Use all of our steel
|
||||
else
|
||||
to_chat(caller, span_userdanger("Somehow, you are missing your protean rig. You are unable to rebuild without one."))
|
||||
else
|
||||
to_chat(src, span_critical("Your refactoring has failed."))
|
||||
to_chat(blob, span_critical("Your refactoring has failed!"))
|
||||
to_chat(caller, span_warning("You do not have enough steel stored for this operation."))
|
||||
else
|
||||
to_chat(src, span_critical("Your refactoring is interrupted."))
|
||||
to_chat(blob, span_critical("Your refactoring is interrupted!"))
|
||||
active_regen = FALSE
|
||||
nano_outofblob(blob)
|
||||
input = tgui_alert(caller,{"Include Flavourtext?"},"Reassembly",list("Yes","No","Cancel"))
|
||||
if(input == "Cancel" || !input)
|
||||
return
|
||||
var/flavour = 0
|
||||
if(input == "Yes")
|
||||
flavour = 1
|
||||
input = tgui_alert(caller,{"Include OOC notes?"},"Reassembly",list("Yes","No","Cancel"))
|
||||
if(input == "Cancel" || !input)
|
||||
return
|
||||
var/oocnotes = 0
|
||||
if(input == "Yes")
|
||||
oocnotes = 1
|
||||
to_chat(caller, span_notify("You begin to reassemble. You will need to remain still."))
|
||||
caller.visible_message(span_notify("[caller] rapidly contorts and shifts!"), span_danger("You begin to reassemble."))
|
||||
if(do_after(caller, 40,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
if(caller.client.prefs) //Make sure we didn't d/c
|
||||
var/obj/item/rig/protean/Rig = species?:OurRig
|
||||
caller.client.prefs.vanity_copy_to(src, FALSE, flavour, oocnotes, TRUE)
|
||||
species?:OurRig = Rig //Get a reference to our Rig and put it back after reassembling
|
||||
caller.visible_message(span_notify("[caller] adopts a new form!"), span_danger("You have reassembled."))
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/nano_copy_body()
|
||||
set name = "Copy Form"
|
||||
set desc = "If you are aggressively grabbing someone, with their consent, you can turn into a copy of them. (Without their name)."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
var/mob/living/caller = src
|
||||
if(temporary_form)
|
||||
caller = temporary_form
|
||||
|
||||
var/grabbing_but_not_enough
|
||||
var/mob/living/carbon/human/victim = null
|
||||
for(var/obj/item/grab/G in caller)
|
||||
if(G.state < GRAB_AGGRESSIVE)
|
||||
grabbing_but_not_enough = TRUE
|
||||
return
|
||||
else
|
||||
victim = G.affecting
|
||||
if (!victim)
|
||||
if (grabbing_but_not_enough)
|
||||
to_chat(caller, span_warning("You need a better grip to do that!"))
|
||||
else
|
||||
to_chat(caller, span_notice("You need to be aggressively grabbing someone before you can copy their form."))
|
||||
return
|
||||
if (!istype(victim))
|
||||
to_chat(caller, span_warning("You can only perform this on human mobs!"))
|
||||
return
|
||||
if (!victim.client)
|
||||
to_chat(caller, span_notice("The person you try this on must have a client!"))
|
||||
return
|
||||
|
||||
|
||||
to_chat(caller, span_notice("Waiting for other person's consent."))
|
||||
var/consent = tgui_alert(victim, "Allow [src] to copy what you look like?", "Consent", list("Yes", "No"))
|
||||
if (consent != "Yes")
|
||||
to_chat(caller, span_notice("They declined your request."))
|
||||
return
|
||||
|
||||
var/input = tgui_alert(caller,{"Copy [victim]'s flavourtext?"},"Copy Form",list("Yes","No","Cancel"))
|
||||
if(input == "Cancel" || !input)
|
||||
return
|
||||
var/flavour = 0
|
||||
if(input == "Yes")
|
||||
flavour = 1
|
||||
|
||||
var/checking = FALSE
|
||||
for(var/obj/item/grab/G in caller)
|
||||
if(G.affecting == victim && G.state >= GRAB_AGGRESSIVE)
|
||||
checking = TRUE
|
||||
if (!checking)
|
||||
to_chat(caller, span_warning("You lost your grip on [victim]!"))
|
||||
return
|
||||
|
||||
to_chat(caller, span_notify("You begin to reassemble into [victim]. You will need to remain still."))
|
||||
caller.visible_message(span_notify("[caller] rapidly contorts and shifts!"), span_danger("You begin to reassemble into [victim]."))
|
||||
if(do_after(caller, 40,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
checking = FALSE
|
||||
for(var/obj/item/grab/G in caller)
|
||||
if(G.affecting == victim && G.state >= GRAB_AGGRESSIVE)
|
||||
checking = TRUE
|
||||
if (!checking)
|
||||
to_chat(caller, span_warning("You lost your grip on [victim]!"))
|
||||
return
|
||||
if(caller.client) //Make sure we didn't d/c
|
||||
var/obj/item/rig/protean/Rig = species?:OurRig
|
||||
transform_into_other_human(victim, FALSE, flavour, TRUE)
|
||||
species?:OurRig = Rig //Get a reference to our Rig and put it back after reassembling
|
||||
caller.visible_message(span_notify("[caller] adopts the form of [victim]!"), span_danger("You have reassembled into [victim]."))
|
||||
|
||||
////
|
||||
// Storing metal
|
||||
////
|
||||
/mob/living/carbon/human/proc/nano_metalnom()
|
||||
set name = "Ref - Store Metals"
|
||||
set desc = "If you're holding a stack of material, you can consume some and store it for later."
|
||||
set category = "Abilities"
|
||||
set hidden = TRUE
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
|
||||
var/mob/living/caller = src
|
||||
if(temporary_form)
|
||||
caller = temporary_form
|
||||
if(nano_dead_check(caller))
|
||||
to_chat(caller, span_warning("You need to be repaired first before you can act!"))
|
||||
return
|
||||
|
||||
var/obj/item/organ/internal/nano/refactory/refactory = nano_get_refactory()
|
||||
//Missing the organ that does this
|
||||
if(!istype(refactory))
|
||||
to_chat(src,span_warning("You don't have a working refactory module!"))
|
||||
to_chat(caller,span_warning("You don't have a working refactory module!"))
|
||||
return
|
||||
|
||||
var/held = get_active_hand()
|
||||
var/held = caller.get_active_hand()
|
||||
if(!istype(held,/obj/item/stack/material))
|
||||
to_chat(src,span_warning("You aren't holding a stack of materials in your active hand...!"))
|
||||
to_chat(caller,span_warning("You aren't holding a stack of materials in your active hand!"))
|
||||
return
|
||||
|
||||
var/obj/item/stack/material/matstack = held
|
||||
var/substance = matstack.material.name
|
||||
var allowed = FALSE
|
||||
var allowed = 0
|
||||
for(var/material in PROTEAN_EDIBLE_MATERIALS)
|
||||
if(material == substance) allowed = TRUE
|
||||
if(material == substance) allowed = 1
|
||||
if(!allowed)
|
||||
to_chat(src,span_warning("You can't process [substance]!"))
|
||||
return //Only a few things matter, the rest are best not cluttering the lists.
|
||||
to_chat(caller,span_warning("You can't process [substance]!"))
|
||||
return
|
||||
|
||||
var/howmuch = tgui_input_number(src,"How much do you want to store? (0-[matstack.get_amount()])","Select amount",null,matstack.get_amount(),0)
|
||||
if(!howmuch || matstack != get_active_hand() || howmuch > matstack.get_amount())
|
||||
var/howmuch = tgui_input_number(caller,"How much do you want to store? (0-[matstack.get_amount()])","Select amount",null,matstack.get_amount())
|
||||
if(!howmuch || matstack != caller.get_active_hand() || howmuch > matstack.get_amount())
|
||||
return //Quietly fail
|
||||
|
||||
var/actually_added = refactory.add_stored_material(substance,howmuch*matstack.perunit)
|
||||
matstack.use(CEILING((actually_added/matstack.perunit), 1))
|
||||
if(actually_added && actually_added < howmuch)
|
||||
to_chat(src,span_warning("Your refactory module is now full, so only [actually_added] units were stored."))
|
||||
visible_message(span_notice("[src] nibbles some of the [substance] right off the stack!"))
|
||||
to_chat(caller,span_warning("Your refactory module is now full, so only [actually_added] units were stored."))
|
||||
visible_message(span_notice("[caller] nibbles some of the [substance] right off the stack!"))
|
||||
else if(actually_added)
|
||||
to_chat(src,span_notice("You store [actually_added] units of [substance]."))
|
||||
visible_message(span_notice("[src] devours some of the [substance] right off the stack!"))
|
||||
to_chat(caller,span_notice("You store [actually_added] units of [substance]."))
|
||||
visible_message(span_notice("[caller] devours some of the [substance] right off the stack!"))
|
||||
else
|
||||
to_chat(src,span_notice("You're completely capped out on [substance]!"))
|
||||
to_chat(caller,span_notice("You're completely capped out on [substance]!"))
|
||||
|
||||
////
|
||||
// Blob Form
|
||||
////
|
||||
/mob/living/carbon/human/proc/nano_blobform()
|
||||
/mob/living/carbon/human/proc/nano_blobform(var/forced)
|
||||
set name = "Toggle Blobform"
|
||||
set desc = "Switch between amorphous and humanoid forms."
|
||||
set category = "Abilities"
|
||||
set hidden = TRUE
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
|
||||
if(nano_dead_check(src))
|
||||
return
|
||||
if(forced)
|
||||
if(temporary_form)
|
||||
nano_outofblob(temporary_form, forced)
|
||||
else
|
||||
nano_intoblob(forced)
|
||||
return
|
||||
var/atom/movable/to_locate = temporary_form || src
|
||||
if(!isturf(to_locate.loc))
|
||||
if(!isturf(to_locate.loc) && !forced)
|
||||
to_chat(to_locate,span_warning("You need more space to perform this action!"))
|
||||
return
|
||||
|
||||
//Blob form
|
||||
if(temporary_form)
|
||||
if(health < maxHealth*0.5)
|
||||
to_chat(temporary_form,span_warning("You need to regenerate more nanites first!"))
|
||||
else if(temporary_form.stat)
|
||||
if(temporary_form.stat)
|
||||
to_chat(temporary_form,span_warning("You can only do this while not stunned."))
|
||||
else
|
||||
nano_outofblob(temporary_form)
|
||||
@@ -257,6 +288,9 @@
|
||||
else if(stat)
|
||||
to_chat(src,span_warning("You can only do this while not stunned."))
|
||||
return
|
||||
else if(handcuffed)
|
||||
to_chat(src, span_warning("You can't do this while handcuffed!"))
|
||||
return
|
||||
else
|
||||
nano_intoblob()
|
||||
|
||||
@@ -266,63 +300,300 @@
|
||||
/mob/living/carbon/human/proc/nano_change_fitting()
|
||||
set name = "Change Species Fit"
|
||||
set desc = "Tweak your shape to change what suits you fit into (and their sprites!)."
|
||||
set category = "Abilities"
|
||||
set category = "Abilities.Protean"
|
||||
|
||||
if(stat)
|
||||
to_chat(src,span_warning("You must be awake and standing to perform this action!"))
|
||||
return
|
||||
|
||||
var/new_species = tgui_input_list(src, "Please select a species to emulate.", "Shapeshifter Body", GLOB.playable_species)
|
||||
var/new_species = tgui_input_list(src, "Please select a species to emulate.", "Shapeshifter Body", list(species?.vanity_base_fit)|species?.get_valid_shapeshifter_forms())
|
||||
if(new_species)
|
||||
species?.base_species = new_species // Really though you better have a species
|
||||
regenerate_icons() //Expensive, but we need to recrunch all the icons we're wearing
|
||||
|
||||
////
|
||||
// Change size
|
||||
// Rig Transform
|
||||
////
|
||||
/mob/living/carbon/human/proc/nano_set_size()
|
||||
set name = "Adjust Volume"
|
||||
set category = "Abilities"
|
||||
set hidden = TRUE
|
||||
/mob/living/carbon/human/proc/nano_rig_transform(var/forced)
|
||||
set name = "Modify Form - Hardsuit"
|
||||
set desc = "Allows a protean to retract its mass into its hardsuit module at will."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
|
||||
var/mob/living/user = temporary_form || src
|
||||
|
||||
var/obj/item/organ/internal/nano/refactory/refactory = nano_get_refactory()
|
||||
//Missing the organ that does this
|
||||
if(!istype(refactory))
|
||||
to_chat(user,span_warning("You don't have a working refactory module!"))
|
||||
var/mob/living/caller = src
|
||||
if(temporary_form)
|
||||
caller = temporary_form
|
||||
if(nano_dead_check(src))
|
||||
to_chat(caller, span_warning("You need to be repaired first before you can act!"))
|
||||
return
|
||||
to_chat(caller, span_notice("You rapidly condense into your module."))
|
||||
if(forced || do_after(caller,20,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
if(!temporary_form) //If you're human, force you into blob form before rig'ing
|
||||
nano_blobform(forced)
|
||||
spawn(2)
|
||||
|
||||
var/nagmessage = "Adjust your mass to be a size between 25 to 200% (or between 1 to 600% in dorms area). Up-sizing consumes metal, downsizing returns metal."
|
||||
var/new_size = tgui_input_number(user, nagmessage, "Pick a Size", user.size_multiplier*100, 600, 1)
|
||||
if(!new_size || !size_range_check(new_size))
|
||||
return
|
||||
if(istype(src.species, /datum/species/protean))
|
||||
var/datum/species/protean/S = src.species
|
||||
var/mob/living/simple_mob/protean_blob/P = temporary_form
|
||||
if(S.OurRig) //Do we even have a RIG?
|
||||
if(P.loc == S.OurRig) //we're inside our own RIG
|
||||
if(ismob(S.OurRig.loc))
|
||||
var/mob/m = S.OurRig.loc
|
||||
m.drop_from_inventory(S.OurRig)
|
||||
if(S.OurRig.wearer) //We're being worn. Engulf em', if prefs align.. otherwise just drop off.
|
||||
var/mob/living/carbon/human/victim = S.OurRig.wearer
|
||||
if(P.can_be_drop_pred && victim.devourable && victim.can_be_drop_prey)
|
||||
if(P.vore_selected)
|
||||
perform_the_nom(P,victim,P,P.vore_selected,1)
|
||||
P.forceMove(get_turf(S.OurRig))
|
||||
S.OurRig.forceMove(src)
|
||||
S.OurRig.myprotean = src
|
||||
src.equip_to_slot_if_possible(S.OurRig, slot_back)
|
||||
S.OurRig.Moved()
|
||||
P.has_hands = 1
|
||||
else //We're not in our own RIG
|
||||
if(P.stat || P.resting && !forced)
|
||||
to_chat(P,span_warning("You can only do this while not stunned."))
|
||||
else
|
||||
if(P.l_hand)
|
||||
P.drop_l_hand()
|
||||
if(P.r_hand)
|
||||
P.drop_r_hand()
|
||||
P.has_hands = 0
|
||||
S.OurRig.myprotean = P
|
||||
src.drop_from_inventory(S.OurRig)
|
||||
P.forceMove(S.OurRig)
|
||||
S.OurRig.canremove = 1
|
||||
P.reset_view()
|
||||
else //Make one if not
|
||||
to_chat(temporary_form, span_warning("Somehow, your RIG got disconnected from your species. This may have been caused by an admin heal. A new one has been created for you, contact a coder."))
|
||||
new /obj/item/rig/protean(src,src)
|
||||
else
|
||||
to_chat(caller, span_warning("You must remain still to condense!"))
|
||||
|
||||
var/size_factor = new_size/100
|
||||
|
||||
//Will be: -1.75 for 200->25, and 1.75 for 25->200
|
||||
var/sizediff = size_factor - user.size_multiplier
|
||||
|
||||
//Negative if shrinking, positive if growing
|
||||
//Will be (PLSC*2)*-1.75 to 1.75
|
||||
//For 2000 PLSC that's -7000 to 7000
|
||||
var/cost = (PER_LIMB_STEEL_COST*2)*sizediff
|
||||
|
||||
//Sizing up
|
||||
if(cost > 0)
|
||||
if(refactory.use_stored_material(MAT_STEEL,cost))
|
||||
user.resize(size_factor, ignore_prefs = TRUE)
|
||||
/mob/living/carbon/human/proc/appearance_switch()
|
||||
set name = "Switch Blob Appearance"
|
||||
set desc = "Allows a protean blob to switch its outwards appearance."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
var/datum/species/protean/S = src.species
|
||||
var/mob/living/caller = src
|
||||
if(temporary_form)
|
||||
caller = temporary_form
|
||||
var/list/icon_choices = list(
|
||||
"Primary" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "primary"),
|
||||
"Highlight" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "highlight"),
|
||||
"puddle1" = image(icon = 'icons/mob/species/protean/protean_powers.dmi', icon_state = "blob"),
|
||||
"puddle0" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "puddle"),
|
||||
"shadow" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "shadow"),
|
||||
"clean" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "clean"),
|
||||
"swarm" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "swarm"),
|
||||
"slime" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "slime"),
|
||||
"chaos" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "chaos"),
|
||||
"cloud" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "cloud"),
|
||||
/*"catslug" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "catslug"),
|
||||
"cat" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "cat"),
|
||||
"mouse" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "mouse"),
|
||||
"rabbit" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "rabbit"),
|
||||
"bear" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "bear"),
|
||||
"fen" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "fen"),
|
||||
"fox" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "fox"),
|
||||
"raptor" = image(icon = 'icons/mob/species/protean/protean.dmi', icon_state = "raptor"),
|
||||
"rat" = image(icon = 'icons/mob/species/protean/protean64x32.dmi', icon_state = "rat", pixel_x = -16),
|
||||
"lizard" = image(icon = 'icons/mob/species/protean/protean64x32.dmi', icon_state = "lizard", pixel_x = -16),
|
||||
"wolf" = image(icon = 'icons/mob/species/protean/protean64x32.dmi', icon_state = "wolf", pixel_x = -16),
|
||||
//"drake" = image(icon = 'modular_chomp/icons/mob/species/protean/protean64x64.dmi', icon_state = "drake", pixel_x = -16),
|
||||
"teppi" = image(icon = 'icons/mob/species/protean/protean64x64.dmi', icon_state = "teppi", pixel_x = -16),
|
||||
"panther" = image(icon = 'icons/mob/species/protean/protean64x64.dmi', icon_state = "panther", pixel_x = -16),
|
||||
"robodrgn" = image(icon = 'icons/mob/species/protean/protean128x64.dmi', icon_state = "robodrgn", pixel_x = -48),
|
||||
"Dragon" = image(icon = 'icons/mob/bigdragon_small.dmi', icon_state = "dragon_small")*/
|
||||
)
|
||||
var/blobstyle = show_radial_menu(caller, caller, icon_choices, require_near = TRUE, tooltips = FALSE)
|
||||
if(!blobstyle || QDELETED(caller) || caller.incapacitated())
|
||||
return FALSE
|
||||
switch(blobstyle)
|
||||
if("Dragon") //Fuck it, we ball
|
||||
var/list/options = list("Underbelly","Body","Ears","Mane","Horns","Eyes")
|
||||
for(var/option in options)
|
||||
LAZYSET(options, option, image('icons/effects/bigdragon_labels.dmi', option))
|
||||
var/choice = show_radial_menu(caller, caller, options, radius = 60)
|
||||
if(!choice || QDELETED(caller) || caller.incapacitated())
|
||||
return FALSE
|
||||
. = TRUE
|
||||
var/list/underbelly_styles = list(
|
||||
"dragon_underSmooth",
|
||||
"dragon_underPlated"
|
||||
)
|
||||
var/list/body_styles = list(
|
||||
"dragon_bodySmooth",
|
||||
"dragon_bodyScaled"
|
||||
)
|
||||
var/list/ear_styles = list(
|
||||
"dragon_earsNormal"
|
||||
)
|
||||
var/list/mane_styles = list(
|
||||
"dragon_maneNone",
|
||||
"dragon_maneShaggy",
|
||||
"dragon_maneDorsalfin"
|
||||
)
|
||||
var/list/horn_styles = list(
|
||||
"dragon_hornsPointy",
|
||||
"dragon_hornsCurved",
|
||||
"dragon_hornsCurved2",
|
||||
"dragon_hornsJagged",
|
||||
"dragon_hornsCrown",
|
||||
"dragon_hornsSkull"
|
||||
)
|
||||
var/list/eye_styles = list(
|
||||
"dragon_eyesNormal"
|
||||
)
|
||||
switch(choice)
|
||||
if("Underbelly")
|
||||
options = underbelly_styles
|
||||
for(var/option in options)
|
||||
var/image/I = image('icons/mob/vore128x64.dmi', option, dir = 4, pixel_x = -48)
|
||||
LAZYSET(options, option, I)
|
||||
choice = show_radial_menu(caller, caller, options, radius = 90)
|
||||
if(!choice || QDELETED(caller) || caller.incapacitated())
|
||||
return 0
|
||||
var/new_color = input("Pick underbelly color:","Underbelly Color", S.dragon_overlays[1]) as null|color
|
||||
if(!new_color)
|
||||
return 0
|
||||
S.dragon_overlays[1] = choice
|
||||
S.dragon_overlays[S.dragon_overlays[1]] = new_color
|
||||
if("Body")
|
||||
options = body_styles
|
||||
for(var/option in options)
|
||||
var/image/I = image('icons/mob/vore128x64.dmi', option, dir = 4, pixel_x = -48)
|
||||
LAZYSET(options, option, I)
|
||||
choice = show_radial_menu(caller, caller, options, radius = 90)
|
||||
if(!choice || QDELETED(caller) || caller.incapacitated())
|
||||
return 0
|
||||
var/new_color = input("Pick body color:","Body Color", S.dragon_overlays[2]) as null|color
|
||||
if(!new_color)
|
||||
return 0
|
||||
S.dragon_overlays[2] = choice
|
||||
S.dragon_overlays[S.dragon_overlays[2]] = new_color
|
||||
if("Ears")
|
||||
options = ear_styles
|
||||
for(var/option in options)
|
||||
var/image/I = image('icons/mob/vore128x64.dmi', option, dir = 4, pixel_x = -76, pixel_y = -50)
|
||||
LAZYSET(options, option, I)
|
||||
choice = show_radial_menu(caller, caller, options, radius = 90)
|
||||
if(!choice || QDELETED(caller) || caller.incapacitated())
|
||||
return 0
|
||||
var/new_color = input("Pick ear color:","Ear Color", S.dragon_overlays[3]) as null|color
|
||||
if(!new_color)
|
||||
return 0
|
||||
S.dragon_overlays[3] = choice
|
||||
S.dragon_overlays[S.dragon_overlays[3]] = new_color
|
||||
if("Mane")
|
||||
options = mane_styles
|
||||
for(var/option in options)
|
||||
var/image/I = image('icons/mob/vore128x64.dmi', option, dir = 4, pixel_x = -76, pixel_y = -50)
|
||||
LAZYSET(options, option, I)
|
||||
choice = show_radial_menu(caller, caller, options, radius = 90)
|
||||
if(!choice || QDELETED(caller) || caller.incapacitated())
|
||||
return 0
|
||||
var/new_color = input("Pick mane color:","Mane Color", S.dragon_overlays[4]) as null|color
|
||||
if(!new_color)
|
||||
return 0
|
||||
S.dragon_overlays[4] = choice
|
||||
S.dragon_overlays[S.dragon_overlays[4]] = new_color
|
||||
if("Horns")
|
||||
options = horn_styles
|
||||
for(var/option in options)
|
||||
var/image/I = image('icons/mob/vore128x64.dmi', option, dir = 4, pixel_x = -86, pixel_y = -50)
|
||||
LAZYSET(options, option, I)
|
||||
choice = show_radial_menu(caller, caller, options, radius = 90)
|
||||
if(!choice || QDELETED(caller) || caller.incapacitated())
|
||||
return 0
|
||||
var/new_color = input("Pick horn color:","Horn Color", S.dragon_overlays[5]) as null|color
|
||||
if(!new_color)
|
||||
return 0
|
||||
S.dragon_overlays[5] = choice
|
||||
S.dragon_overlays[S.dragon_overlays[5]] = new_color
|
||||
if("Eyes")
|
||||
options = eye_styles
|
||||
for(var/option in options)
|
||||
var/image/I = image('icons/mob/vore128x64.dmi', option, dir = 2, pixel_x = -48, pixel_y = -50)
|
||||
LAZYSET(options, option, I)
|
||||
choice = show_radial_menu(caller, caller, options, radius = 90)
|
||||
if(!choice || QDELETED(caller) || caller.incapacitated())
|
||||
return 0
|
||||
var/new_color = input("Pick eye color:","Eye Color", S.dragon_overlays[6]) as null|color
|
||||
if(!new_color)
|
||||
return 0
|
||||
S.dragon_overlays[6] = choice
|
||||
S.dragon_overlays[S.dragon_overlays[6]] = new_color
|
||||
S.blob_appearance = "dragon"
|
||||
if("Primary")
|
||||
var/new_color = input("Pick primary color:","Protean Primary", "#FF0000") as null|color
|
||||
if(!new_color)
|
||||
return
|
||||
S.blob_color_1 = new_color
|
||||
if("Highlight")
|
||||
var/new_color = input("Pick highlight color:","Protean Highlight", "#FF0000") as null|color
|
||||
if(!new_color)
|
||||
return
|
||||
S.blob_color_2 = new_color
|
||||
else
|
||||
to_chat(user,span_warning("That size change would cost [cost] steel, which you don't have."))
|
||||
//Sizing down (or not at all)
|
||||
else if(cost <= 0)
|
||||
cost = abs(cost)
|
||||
var/actually_added = refactory.add_stored_material(MAT_STEEL,cost)
|
||||
user.resize(size_factor, ignore_prefs = TRUE)
|
||||
if(actually_added != cost)
|
||||
to_chat(user,span_warning("Unfortunately, [cost-actually_added] steel was lost due to lack of storage space."))
|
||||
S.blob_appearance = blobstyle
|
||||
if(temporary_form)
|
||||
if(blobstyle)
|
||||
temporary_form.update_icon()
|
||||
if(istype(temporary_form.loc, /obj/item/holder/protoblob))
|
||||
var/obj/item/holder/protoblob/PB = temporary_form.loc
|
||||
PB.item_state = S.blob_appearance
|
||||
|
||||
user.visible_message(span_notice("Black mist swirls around [user] as they change size."))
|
||||
/mob/living/carbon/human/proc/nano_latch()
|
||||
set name = "Latch/Unlatch host"
|
||||
set desc = "Allows a protean to forcibly latch or unlatch from a host."
|
||||
//set category = "Abilities.Protean"
|
||||
set hidden = 1
|
||||
var/mob/living/caller = src
|
||||
var/mob/living/carbon/human/target
|
||||
var/datum/species/protean/S = src.species
|
||||
if(nano_dead_check(src))
|
||||
return
|
||||
if(temporary_form)
|
||||
caller = temporary_form
|
||||
if(caller.loc == S.OurRig)
|
||||
target = S.OurRig.wearer
|
||||
if(target)
|
||||
target.drop_from_inventory(S.OurRig)
|
||||
to_chat(caller, span_notice("You detach from your host."))
|
||||
else
|
||||
to_chat(caller, span_warning("You aren't being worn, dummy."))
|
||||
return
|
||||
var/obj/held_item = caller.get_active_hand()
|
||||
if(istype(held_item,/obj/item/grab))
|
||||
var/obj/item/grab/G = held_item
|
||||
if(istype(G.affecting, /mob/living/carbon/human))
|
||||
target = G.affecting
|
||||
if(istype(target.species, /datum/species/protean))
|
||||
to_chat(caller, span_danger("You can't latch onto a fellow Protean!"))
|
||||
return
|
||||
if(G.loc == caller && G.state >= GRAB_AGGRESSIVE)
|
||||
caller.visible_message(span_warning("[caller] is attempting to latch onto [target]!"), span_danger("You attempt to latch onto [target]!"))
|
||||
if(do_after(caller, 50, target,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
if(G.loc == caller && G.state >= GRAB_AGGRESSIVE)
|
||||
target.drop_from_inventory(target.back)
|
||||
caller.visible_message(span_danger("[caller] latched onto [target]!"), span_danger("You latch yourself onto [target]!"))
|
||||
target.Weaken(3)
|
||||
nano_rig_transform(1)
|
||||
spawn(5) //Have to give time for the above proc to resolve
|
||||
//S.OurRig.forceMove(target)
|
||||
target.equip_to_slot(S.OurRig, slot_back)
|
||||
S.OurRig.Moved()
|
||||
spawn(1) //Same here :(
|
||||
S.OurRig.wearer = target
|
||||
else
|
||||
to_chat(caller, span_warning("You need a more aggressive grab to do this!"))
|
||||
else
|
||||
to_chat(caller, span_warning("You can only latch onto humanoid mobs!"))
|
||||
else
|
||||
to_chat(caller, span_warning("You need to be grabbing a humanoid mob aggressively to latch onto them."))
|
||||
|
||||
/// /// /// A helper to reuse
|
||||
/mob/living/proc/nano_get_refactory(obj/item/organ/internal/nano/refactory/R)
|
||||
@@ -340,7 +611,18 @@
|
||||
/mob/living/carbon/human/nano_get_refactory()
|
||||
return ..(locate(/obj/item/organ/internal/nano/refactory) in internal_organs)
|
||||
|
||||
//I hate this whole bit but I want proteans to be able to "die" and still be "alive" in their blob as a suit
|
||||
/mob/living/carbon/human/proc/nano_dead_check(var/mob/living/caller)
|
||||
if(istype(src.species, /datum/species/protean))
|
||||
var/datum/species/protean/S = src.species
|
||||
if(S.pseudodead)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/proc/nano_set_dead(var/num)
|
||||
if(istype(src.species, /datum/species/protean))
|
||||
var/datum/species/protean/S = src.species
|
||||
S.pseudodead = num
|
||||
|
||||
/// /// /// Ability objects for stat panel
|
||||
/obj/effect/protean_ability
|
||||
@@ -371,20 +653,20 @@
|
||||
/obj/effect/protean_ability/proc/do_ability(var/mob/living/L)
|
||||
if(istype(L))
|
||||
call(L,to_call)()
|
||||
return FALSE
|
||||
return 0
|
||||
|
||||
/// The actual abilities
|
||||
/obj/effect/protean_ability/into_blob
|
||||
ability_name = "Toggle Blobform"
|
||||
desc = "Discard your shape entirely, changing to a low-energy blob that can fit into small spaces. You'll consume steel to repair yourself in this form."
|
||||
desc = "Discard your shape entirely, changing to a low-energy blob. You'll consume steel to repair yourself in this form."
|
||||
icon_state = "blob"
|
||||
to_call = /mob/living/carbon/human/proc/nano_blobform
|
||||
|
||||
/obj/effect/protean_ability/change_volume
|
||||
ability_name = "Change Volume"
|
||||
desc = "Alter your size by consuming steel to produce additional nanites, or regain steel by reducing your size and reclaiming them."
|
||||
desc = "Alter your size between 25% and 200%."
|
||||
icon_state = "volume"
|
||||
to_call = /mob/living/carbon/human/proc/nano_set_size
|
||||
to_call = /mob/living/proc/set_size
|
||||
|
||||
/obj/effect/protean_ability/reform_limb
|
||||
ability_name = "Ref - Single Limb"
|
||||
@@ -393,15 +675,80 @@
|
||||
to_call = /mob/living/carbon/human/proc/nano_partswap
|
||||
|
||||
/obj/effect/protean_ability/reform_body
|
||||
ability_name = "Ref - Whole Body"
|
||||
desc = "Rebuild your entire body into whatever design you want, assuming you have 10,000 metal."
|
||||
ability_name = "Total Reassembly"
|
||||
desc = "Fully repair yourself or reload your appearance from whatever character slot you have loaded."
|
||||
icon_state = "body"
|
||||
to_call = /mob/living/carbon/human/proc/nano_regenerate
|
||||
|
||||
/obj/effect/protean_ability/metal_nom
|
||||
ability_name = "Ref - Store Metals"
|
||||
desc = "Store the metal you're holding. Your refactory can only store steel, and all other metals will be converted into nanites ASAP for various effects."
|
||||
desc = "Store the metal you're holding. Your refactory can only store steel."
|
||||
icon_state = "metal"
|
||||
to_call = /mob/living/carbon/human/proc/nano_metalnom
|
||||
|
||||
/obj/effect/protean_ability/hardsuit
|
||||
ability_name = "Hardsuit Transform"
|
||||
desc = "Coalesce your nanite swarm into their control module, allowing others to wear you."
|
||||
icon_state = "rig"
|
||||
to_call = /mob/living/carbon/human/proc/nano_rig_transform
|
||||
|
||||
/obj/effect/protean_ability/appearance_switch
|
||||
ability_name = "Blob Appearance"
|
||||
desc = "Toggle your blob appearance. Also affects your worn appearance."
|
||||
icon_state = "switch"
|
||||
to_call = /mob/living/carbon/human/proc/appearance_switch
|
||||
|
||||
/obj/effect/protean_ability/latch_host
|
||||
ability_name = "Latch Host"
|
||||
desc = "Forcibly latch or unlatch your RIG from a host mob."
|
||||
icon_state = "latch"
|
||||
to_call = /mob/living/carbon/human/proc/nano_latch
|
||||
|
||||
/obj/effect/protean_ability/copy_form
|
||||
ability_name = "Copy Form"
|
||||
desc = "If you are aggressively grabbing someone, with their consent, you can turn into a copy of them. (Without their name)."
|
||||
icon_state = "copy_form"
|
||||
to_call = /mob/living/carbon/human/proc/nano_copy_body
|
||||
|
||||
#undef PER_LIMB_STEEL_COST
|
||||
|
||||
/mob/living/carbon/human/proc/chest_transparency_toggle()
|
||||
set name = "transparency toggle (chest only)"
|
||||
set category = "Abilities.Protean"
|
||||
if(stat || world.time < last_special)
|
||||
return
|
||||
last_special = world.time + 50
|
||||
for(var/obj/item/organ/external/proteanlimbs as anything in src.organs)
|
||||
if(proteanlimbs.organ_tag == BP_HEAD)
|
||||
continue
|
||||
proteanlimbs.transparent = !proteanlimbs.transparent
|
||||
visible_message(span_notice("\The [src]'s internal composition seems to change."))
|
||||
update_icons_body()
|
||||
update_hair()
|
||||
|
||||
/obj/effect/protean_ability/chest_transparency
|
||||
ability_name = "body transparency toggle (All but head)"
|
||||
desc = "Makes everything but your head transparent!"
|
||||
icon = 'icons/obj/slimeborg/slimecore.dmi'
|
||||
icon_state = "core"
|
||||
to_call = /mob/living/carbon/human/proc/chest_transparency_toggle
|
||||
|
||||
/mob/living/carbon/human/proc/transparency_toggle()
|
||||
set name = "Toggle Transparency"
|
||||
set category = "Abilities.Protean"
|
||||
if(stat || world.time < last_special)
|
||||
return
|
||||
last_special = world.time + 50
|
||||
for(var/obj/item/organ/external/proteanlimbs as anything in src.organs)
|
||||
proteanlimbs.transparent = !proteanlimbs.transparent
|
||||
|
||||
visible_message(span_notice("\The [src]'s internal composition seems to change."))
|
||||
update_icons_body()
|
||||
update_hair()
|
||||
|
||||
/obj/effect/protean_ability/transparency_for_entire_body
|
||||
ability_name = "Toggle Transparency"
|
||||
desc = "transparency toggle for your entire body"
|
||||
icon = 'icons/obj/slimeborg/slimecore.dmi'
|
||||
icon_state = "core"
|
||||
to_call = /mob/living/carbon/human/proc/transparency_toggle
|
||||
|
||||
@@ -0,0 +1,609 @@
|
||||
/*
|
||||
proteans
|
||||
*/
|
||||
/obj/item/rig/protean
|
||||
name = "nanosuit control cluster"
|
||||
suit_type = "nanomachine"
|
||||
icon = 'icons/obj/rig_modules_vr.dmi'
|
||||
default_mob_icon = null //Actually having a forced sprite for Proteans is ugly af. I'm not gonna make this a toggle
|
||||
icon_state = "nanomachine_rig"
|
||||
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 100)
|
||||
siemens_coefficient= 1
|
||||
slowdown = 0
|
||||
offline_slowdown = 0
|
||||
seal_delay = 0
|
||||
var/mob/living/myprotean
|
||||
initial_modules = list(/obj/item/rig_module/protean/syphon, /obj/item/rig_module/protean/armor, /obj/item/rig_module/protean/healing)
|
||||
|
||||
helm_type = /obj/item/clothing/head/helmet/space/rig/protean //These are important for sprite pointers
|
||||
boot_type = /obj/item/clothing/shoes/magboots/rig/protean
|
||||
chest_type = /obj/item/clothing/suit/space/rig/protean
|
||||
glove_type = /obj/item/clothing/gloves/gauntlets/rig/protean
|
||||
protean = 1
|
||||
offline_vision_restriction = 0
|
||||
open = 1
|
||||
cell_type = /obj/item/cell/protean
|
||||
var/dead = 0
|
||||
//interface_path = "RIGSuit_protean"
|
||||
//ai_interface_path = "RIGSuit_protean"
|
||||
var/sealed = 0
|
||||
var/assimilated_rig
|
||||
var/can_assimilate_rig = FALSE
|
||||
|
||||
/obj/item/rig/protean/relaymove(mob/user, var/direction)
|
||||
if(user.stat || user.stunned)
|
||||
return
|
||||
forced_move(direction, user, 0)
|
||||
|
||||
/obj/item/rig/protean/check_suit_access(mob/living/user)
|
||||
if(user == myprotean)
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/obj/item/rig/protean/digest_act(atom/movable/item_storage = null)
|
||||
return 0
|
||||
|
||||
/obj/item/rig/protean/ex_act(severity)
|
||||
return
|
||||
|
||||
/obj/item/rig/protean/New(var/newloc, var/mob/living/carbon/human/P)
|
||||
if(P)
|
||||
var/datum/species/protean/S = P.species
|
||||
S.OurRig = src
|
||||
if(P.back)
|
||||
addtimer(CALLBACK(src, PROC_REF(AssimilateBag), P, 1, P.back), 3)
|
||||
myprotean = P
|
||||
else
|
||||
to_chat(P, span_notice("You should have spawned with a backpack to assimilate into your RIG. Try clicking it with a backpack."))
|
||||
..(newloc)
|
||||
|
||||
/obj/item/rig/protean/Destroy()
|
||||
if(myprotean)
|
||||
var/mob/living/carbon/human/P = myprotean
|
||||
var/datum/species/protean/S = P?.species
|
||||
S?.OurRig = null
|
||||
myprotean = null
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/item/rig/proc/AssimilateBag(var/mob/living/carbon/human/P, var/spawned, var/obj/item/storage/backpack/B)
|
||||
if(istype(B,/obj/item/storage/backpack))
|
||||
if(spawned)
|
||||
B = P.back
|
||||
P.unEquip(P.back)
|
||||
if(QDELETED(B)) // for mannequins or such
|
||||
return
|
||||
B.forceMove(src)
|
||||
rig_storage = B
|
||||
P.drop_item(B)
|
||||
to_chat(P, span_notice("[B] has been integrated into the [src]."))
|
||||
if(spawned) //This feels very dumb to have a second if but I'm lazy
|
||||
P.equip_to_slot_if_possible(src, slot_back)
|
||||
src.Moved()
|
||||
else
|
||||
to_chat(P,span_warning("Your rigsuit can only assimilate a backpack into itself. If you are seeing this message, and you do not have a rigsuit, tell a coder."))
|
||||
|
||||
/obj/item/rig/protean/verb/RemoveBag()
|
||||
set name = "Remove Stored Bag"
|
||||
set category = "Object"
|
||||
|
||||
if(rig_storage)
|
||||
usr.put_in_hands(rig_storage)
|
||||
rig_storage = null
|
||||
else
|
||||
to_chat(usr, "This Rig does not have a bag installed. Use a bag on it to install one.")
|
||||
|
||||
/obj/item/rig/protean/attack_hand(mob/user as mob)
|
||||
if (src.loc == user)
|
||||
if(rig_storage)
|
||||
src.rig_storage.open(user)
|
||||
else
|
||||
..()
|
||||
for(var/mob/M in range(1))
|
||||
if (M.s_active == src)
|
||||
src.rig_storage.close(M)
|
||||
src.add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/clothing/head/helmet/space/rig/protean
|
||||
name = "mass"
|
||||
desc = "A helmet-shaped clump of nanomachines."
|
||||
light_overlay = "should not use a light overlay"
|
||||
species_restricted = list(SPECIES_PROTEAN, SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_TAJ, SPECIES_UNATHI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_PROMETHEAN, SPECIES_XENOHYBRID, SPECIES_VOX, SPECIES_TESHARI, SPECIES_VASILISSAN, SPECIES_XENOMORPH_HYBRID)
|
||||
sprite_sheets = list(
|
||||
SPECIES_PROTEAN = 'icons/mob/head.dmi',
|
||||
SPECIES_HUMAN = 'icons/mob/head.dmi',
|
||||
SPECIES_TAJ = 'icons/mob/species/tajaran/helmet.dmi',
|
||||
SPECIES_SKRELL = 'icons/mob/species/skrell/helmet.dmi',
|
||||
SPECIES_UNATHI = 'icons/mob/species/unathi/helmet.dmi',
|
||||
SPECIES_XENOHYBRID = 'icons/mob/species/unathi/helmet.dmi',
|
||||
SPECIES_AKULA = 'icons/mob/species/akula/helmet.dmi',
|
||||
SPECIES_SERGAL = 'icons/mob/species/sergal/helmet.dmi',
|
||||
SPECIES_NEVREAN = 'icons/mob/species/sergal/helmet.dmi',
|
||||
SPECIES_VULPKANIN = 'icons/mob/species/vulpkanin/helmet.dmi',
|
||||
SPECIES_ZORREN_HIGH = 'icons/mob/species/fox/helmet.dmi',
|
||||
SPECIES_FENNEC = 'icons/mob/species/vulpkanin/helmet.dmi',
|
||||
SPECIES_PROMETHEAN = 'icons/mob/species/skrell/helmet.dmi',
|
||||
SPECIES_TESHARI = 'icons/mob/species/teshari/helmet.dmi',
|
||||
SPECIES_VASILISSAN = 'icons/mob/species/skrell/helmet.dmi',
|
||||
SPECIES_VOX = 'icons/mob/species/vox/head.dmi',
|
||||
SPECIES_XENOMORPH_HYBRID = 'icons/mob/species/xenomorph_hybrid/helmet.dmi'
|
||||
)
|
||||
|
||||
sprite_sheets_obj = list(
|
||||
SPECIES_PROTEAN = 'icons/mob/head.dmi',
|
||||
SPECIES_HUMAN = 'icons/mob/head.dmi',
|
||||
SPECIES_TAJ = 'icons/mob/head.dmi',
|
||||
SPECIES_SKRELL = 'icons/mob/head.dmi',
|
||||
SPECIES_UNATHI = 'icons/mob/head.dmi',
|
||||
SPECIES_XENOHYBRID = 'icons/mob/head.dmi',
|
||||
SPECIES_AKULA = 'icons/mob/head.dmi',
|
||||
SPECIES_SERGAL = 'icons/mob/head.dmi',
|
||||
SPECIES_NEVREAN = 'icons/mob/head.dmi',
|
||||
SPECIES_VULPKANIN = 'icons/mob/head.dmi',
|
||||
SPECIES_ZORREN_HIGH = 'icons/mob/head.dmi',
|
||||
SPECIES_FENNEC = 'icons/mob/head.dmi',
|
||||
SPECIES_PROMETHEAN = 'icons/mob/head.dmi',
|
||||
SPECIES_TESHARI = 'icons/mob/head.dmi',
|
||||
SPECIES_VASILISSAN = 'icons/mob/head.dmi',
|
||||
SPECIES_VOX = 'icons/mob/head.dmi',
|
||||
SPECIES_XENOMORPH_HYBRID = 'icons/mob/head.dmi'
|
||||
)
|
||||
icon = 'icons/mob/head.dmi'
|
||||
default_worn_icon = 'icons/mob/head.dmi'
|
||||
|
||||
/obj/item/clothing/gloves/gauntlets/rig/protean
|
||||
name = "mass"
|
||||
desc = "Glove-shaped clusters of nanomachines."
|
||||
siemens_coefficient= 0
|
||||
species_restricted = list(SPECIES_PROTEAN, SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_TAJ, SPECIES_UNATHI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_PROMETHEAN, SPECIES_XENOHYBRID, SPECIES_VOX, SPECIES_TESHARI, SPECIES_VASILISSAN, SPECIES_XENOMORPH_HYBRID)
|
||||
sprite_sheets = list(
|
||||
SPECIES_PROTEAN = 'icons/mob/hands.dmi',
|
||||
SPECIES_HUMAN = 'icons/mob/hands.dmi',
|
||||
SPECIES_TAJ = 'icons/mob/hands.dmi',
|
||||
SPECIES_SKRELL = 'icons/mob/hands.dmi',
|
||||
SPECIES_UNATHI = 'icons/mob/hands.dmi',
|
||||
SPECIES_XENOHYBRID = 'icons/mob/hands.dmi',
|
||||
SPECIES_AKULA = 'icons/mob/hands.dmi',
|
||||
SPECIES_SERGAL = 'icons/mob/hands.dmi',
|
||||
SPECIES_NEVREAN = 'icons/mob/hands.dmi',
|
||||
SPECIES_VULPKANIN = 'icons/mob/hands.dmi',
|
||||
SPECIES_ZORREN_HIGH = 'icons/mob/hands.dmi',
|
||||
SPECIES_FENNEC = 'icons/mob/hands.dmi',
|
||||
SPECIES_PROMETHEAN = 'icons/mob/hands.dmi',
|
||||
SPECIES_TESHARI = 'icons/mob/species/teshari/hands.dmi',
|
||||
SPECIES_VASILISSAN = 'icons/mob/hands.dmi',
|
||||
SPECIES_VOX = 'icons/mob/species/vox/gloves.dmi',
|
||||
SPECIES_XENOMORPH_HYBRID = 'icons/mob/species/xenomorph_hybrid/gloves.dmi'
|
||||
)
|
||||
|
||||
sprite_sheets_obj = list(
|
||||
SPECIES_HUMAN = 'icons/mob/hands.dmi',
|
||||
SPECIES_TAJ = 'icons/mob/hands.dmi',
|
||||
SPECIES_SKRELL = 'icons/mob/hands.dmi',
|
||||
SPECIES_UNATHI = 'icons/mob/hands.dmi',
|
||||
SPECIES_XENOHYBRID = 'icons/mob/hands.dmi',
|
||||
SPECIES_AKULA = 'icons/mob/hands.dmi',
|
||||
SPECIES_SERGAL = 'icons/mob/hands.dmi',
|
||||
SPECIES_NEVREAN = 'icons/mob/hands.dmi',
|
||||
SPECIES_VULPKANIN = 'icons/mob/hands.dmi',
|
||||
SPECIES_ZORREN_HIGH = 'icons/mob/hands.dmi',
|
||||
SPECIES_FENNEC = 'icons/mob/hands.dmi',
|
||||
SPECIES_PROMETHEAN = 'icons/mob/hands.dmi',
|
||||
SPECIES_TESHARI = 'icons/mob/hands.dmi',
|
||||
SPECIES_VASILISSAN = 'icons/mob/hands.dmi',
|
||||
SPECIES_VOX = 'icons/mob/hands.dmi',
|
||||
SPECIES_XENOMORPH_HYBRID = 'icons/mob/hands.dmi'
|
||||
)
|
||||
icon = 'icons/mob/hands.dmi'
|
||||
default_worn_icon = 'icons/mob/hands.dmi'
|
||||
|
||||
/obj/item/clothing/shoes/magboots/rig/protean
|
||||
name = "mass"
|
||||
desc = "Boot-shaped clusters of nanomachines."
|
||||
species_restricted = list(SPECIES_PROTEAN, SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_TAJ, SPECIES_UNATHI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_PROMETHEAN, SPECIES_XENOHYBRID, SPECIES_VOX, SPECIES_TESHARI, SPECIES_VASILISSAN, SPECIES_XENOMORPH_HYBRID)
|
||||
sprite_sheets = list(
|
||||
SPECIES_TESHARI = 'icons/mob/species/teshari/feet.dmi',
|
||||
SPECIES_VOX = 'icons/mob/species/vox/shoes.dmi',
|
||||
SPECIES_XENOMORPH_HYBRID = 'icons/mob/species/xenomorph_hybrid/shoes.dmi'
|
||||
)
|
||||
sprite_sheets_obj = list()
|
||||
icon = 'icons/mob/feet.dmi'
|
||||
default_worn_icon = 'icons/mob/feet.dmi'
|
||||
|
||||
/obj/item/clothing/suit/space/rig/protean
|
||||
name = "mass"
|
||||
desc = "A body-hugging mass of nanomachines."
|
||||
can_breach = 0
|
||||
species_restricted = list(SPECIES_PROTEAN, SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_TAJ, SPECIES_UNATHI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_PROMETHEAN, SPECIES_XENOHYBRID, SPECIES_VOX, SPECIES_TESHARI, SPECIES_VASILISSAN, SPECIES_XENOMORPH_HYBRID)
|
||||
allowed = list(
|
||||
/obj/item/gun,
|
||||
/obj/item/flashlight,
|
||||
/obj/item/tank,
|
||||
/obj/item/suit_cooling_unit,
|
||||
/obj/item/melee/baton,
|
||||
/obj/item/storage/backpack,
|
||||
)
|
||||
sprite_sheets = list(
|
||||
SPECIES_TESHARI = 'icons/mob/species/teshari/suit.dmi',
|
||||
SPECIES_VOX = 'icons/mob/species/vox/suit.dmi',
|
||||
SPECIES_XENOMORPH_HYBRID = 'icons/mob/species/xenomorph_hybrid/suit.dmi'
|
||||
)
|
||||
|
||||
sprite_sheets_obj = list()
|
||||
icon = 'icons/mob/spacesuit.dmi'
|
||||
default_worn_icon = 'icons/mob/spacesuit.dmi'
|
||||
|
||||
//Copy pasted most of this proc from base because I don't feel like rewriting the base proc with a shit load of exceptions
|
||||
/obj/item/rig/protean/attackby(obj/item/W as obj, mob/living/user as mob)
|
||||
if(!istype(user))
|
||||
return 0
|
||||
if(dead)
|
||||
switch(dead)
|
||||
if(1)
|
||||
if(W.is_screwdriver())
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
if(do_after(user,50,src,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
to_chat(user, span_notice("You unscrew the maintenace panel on the [src]."))
|
||||
dead +=1
|
||||
return
|
||||
if(2)
|
||||
if(istype(W, /obj/item/protean_reboot))//placeholder
|
||||
if(do_after(user,50,src,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
to_chat(user, span_notice("You carefully slot [W] in the [src]."))
|
||||
dead +=1
|
||||
qdel(W)
|
||||
return
|
||||
if(3)
|
||||
if(istype(W, /obj/item/stack/nanopaste))
|
||||
if(do_after(user,50,src,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
playsound(src, 'sound/effects/ointment.ogg', 50, 1)
|
||||
to_chat(user, span_notice("You slather the interior confines of the [src] with the [W]."))
|
||||
dead +=1
|
||||
W?:use(1)
|
||||
return
|
||||
if(4)
|
||||
if(istype(W, /obj/item/shockpaddles))
|
||||
if(W?:can_use(user))
|
||||
to_chat(user, span_notice("You hook up the [W] to the contact points in the maintenance assembly"))
|
||||
if(do_after(user,50,src,exclusive = TASK_ALL_EXCLUSIVE))
|
||||
playsound(src, 'sound/machines/defib_charge.ogg', 50, 0)
|
||||
if(do_after(user,10,src))
|
||||
playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
||||
playsound(src, 'sound/machines/defib_success.ogg', 50, 0)
|
||||
new /obj/effect/gibspawner/robot(src.loc)
|
||||
src.atom_say("Contact received! Reassembly nanites calibrated. Estimated time to resucitation: 1 minute 30 seconds")
|
||||
addtimer(CALLBACK(src, PROC_REF(make_alive), myprotean?:humanform), 900)
|
||||
return
|
||||
if(istype(W,/obj/item/rig))
|
||||
if(!assimilated_rig)
|
||||
AssimilateRig(user,W)
|
||||
if(istype(W,/obj/item/tank)) //Todo, some kind of check for suits without integrated air supplies.
|
||||
if(air_supply)
|
||||
to_chat(user, "\The [src] already has a tank installed.")
|
||||
return
|
||||
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
|
||||
air_supply = W
|
||||
W.forceMove(src)
|
||||
to_chat(user, "You slot [W] into [src] and tighten the connecting valve.")
|
||||
return
|
||||
|
||||
// Check if this is a hardsuit upgrade or a modification.
|
||||
else if(istype(W,/obj/item/rig_module))
|
||||
if(!installed_modules)
|
||||
installed_modules = list()
|
||||
if(installed_modules.len)
|
||||
for(var/obj/item/rig_module/installed_mod in installed_modules)
|
||||
if(!installed_mod.redundant && istype(installed_mod,W))
|
||||
to_chat(user, "The hardsuit already has a module of that class installed.")
|
||||
return 1
|
||||
|
||||
var/obj/item/rig_module/mod = W
|
||||
to_chat(user, "You begin installing \the [mod] into \the [src].")
|
||||
if(!do_after(user,40))
|
||||
return
|
||||
if(!user || !W)
|
||||
return
|
||||
if(!user.unEquip(mod))
|
||||
return
|
||||
to_chat(user, "You install \the [mod] into \the [src].")
|
||||
installed_modules |= mod
|
||||
mod.forceMove(src)
|
||||
mod.installed(src)
|
||||
update_icon()
|
||||
return 1
|
||||
else if(W.is_wrench())
|
||||
if(!air_supply)
|
||||
to_chat(user, "There is no tank to remove.")
|
||||
return
|
||||
|
||||
if(user.r_hand && user.l_hand)
|
||||
air_supply.forceMove(get_turf(user))
|
||||
else
|
||||
user.put_in_hands(air_supply)
|
||||
to_chat(user, "You detach and remove \the [air_supply].")
|
||||
air_supply = null
|
||||
return
|
||||
else if(W.is_screwdriver())
|
||||
var/list/possible_removals = list()
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
if(module.permanent)
|
||||
continue
|
||||
possible_removals[module.name] = module
|
||||
|
||||
if(!possible_removals.len)
|
||||
to_chat(user, "There are no installed modules to remove.")
|
||||
return
|
||||
|
||||
var/removal_choice = tgui_input_list(usr, "Which module would you like to remove?", "Removal Choice", possible_removals)
|
||||
if(!removal_choice)
|
||||
return
|
||||
|
||||
var/obj/item/rig_module/removed = possible_removals[removal_choice]
|
||||
to_chat(user, "You detach \the [removed] from \the [src].")
|
||||
removed.forceMove(get_turf(src))
|
||||
removed.removed()
|
||||
installed_modules -= removed
|
||||
update_icon()
|
||||
return
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
if(module.accepts_item(W,user)) //Item is handled in this proc
|
||||
return
|
||||
if(rig_storage)
|
||||
var/obj/item/storage/backpack = rig_storage
|
||||
if(backpack.can_be_inserted(W, 1))
|
||||
backpack.handle_item_insertion(W)
|
||||
else
|
||||
if(istype(W,/obj/item/storage/backpack))
|
||||
AssimilateBag(user,0,W)
|
||||
..()
|
||||
|
||||
/obj/item/rig/protean/proc/make_alive(var/mob/living/carbon/human/H, var/partial)
|
||||
if(H)
|
||||
H.setToxLoss(0)
|
||||
H.setOxyLoss(0)
|
||||
H.setCloneLoss(0)
|
||||
H.setBrainLoss(0)
|
||||
H.SetParalysis(0)
|
||||
H.SetStunned(0)
|
||||
H.SetWeakened(0)
|
||||
H.blinded = 0
|
||||
H.SetBlinded(0)
|
||||
H.eye_blurry = 0
|
||||
H.ear_deaf = 0
|
||||
H.ear_damage = 0
|
||||
H.heal_overall_damage(H.getActualBruteLoss(), H.getActualFireLoss(), 1)
|
||||
for(var/I in H.organs_by_name)
|
||||
if(!H.organs_by_name[I] || istype(H.organs_by_name[I], /obj/item/organ/external/stump))
|
||||
if(H.organs_by_name[I])
|
||||
var/obj/item/organ/external/oldlimb = H.organs_by_name[I]
|
||||
oldlimb.removed()
|
||||
qdel(oldlimb)
|
||||
var/list/organ_data = H.species.has_limbs[I]
|
||||
var/limb_path = organ_data["path"]
|
||||
var/obj/item/organ/external/new_eo = new limb_path(H)
|
||||
new_eo.robotize(H.synthetic ? H.synthetic.company : null)
|
||||
new_eo.sync_colour_to_human(H)
|
||||
if(!partial)
|
||||
dead_mob_list.Remove(H)
|
||||
living_mob_list += H
|
||||
H.tod = null
|
||||
H.timeofdeath = 0
|
||||
H.set_stat(CONSCIOUS)
|
||||
if(istype(H.species, /datum/species/protean))
|
||||
var/datum/species/protean/S
|
||||
S = H.species
|
||||
S.pseudodead = 0
|
||||
to_chat(myprotean, span_notice("You have finished reconstituting."))
|
||||
playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
|
||||
dead = 0
|
||||
|
||||
/obj/item/rig/protean/take_hit(damage, source, is_emp=0)
|
||||
return //We don't do that here
|
||||
|
||||
/obj/item/rig/protean/emp_act(severity_class)
|
||||
return //Same here
|
||||
|
||||
/obj/item/rig/protean/cut_suit()
|
||||
return //nope
|
||||
|
||||
/obj/item/rig/protean/force_rest(var/mob/user)
|
||||
wearer.lay_down()
|
||||
to_chat(user, span_notice("\The [wearer] is now [wearer.resting ? "resting" : "getting up"]."))
|
||||
|
||||
/obj/item/cell/protean
|
||||
name = "Protean power cell"
|
||||
desc = "Something terrible must have happened if you're managing to see this."
|
||||
maxcharge = 10000
|
||||
charge_amount = 100
|
||||
var/mob/living/carbon/human/charger
|
||||
|
||||
/obj/item/cell/protean/Initialize() //ChompEDIT New --> Initialize
|
||||
charge = maxcharge
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, PROC_REF(search_for_protean)), 60)
|
||||
|
||||
/obj/item/cell/protean/proc/search_for_protean()
|
||||
if(istype(src.loc, /obj/item/rig/protean))
|
||||
var/obj/item/rig/protean/prig = src.loc
|
||||
charger = prig.wearer
|
||||
if(charger)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/cell/protean/process()
|
||||
var/C = charge
|
||||
if(charger)
|
||||
if((world.time >= last_use + charge_delay) && charger.nutrition > 100)
|
||||
give(charge_amount)
|
||||
charger.nutrition -= ((1/200)*(charge - C)) //Take nutrition relative to charge. Change the 1/200 if you want to alter the nutrition to charge ratio
|
||||
else
|
||||
return PROCESS_KILL
|
||||
|
||||
|
||||
/obj/item/rig/protean/equipped(mob/living/carbon/human/M)
|
||||
..()
|
||||
if(dead)
|
||||
canremove = 1
|
||||
else
|
||||
canremove = 0
|
||||
|
||||
/obj/item/rig/protean/ai_can_move_suit(mob/user, check_user_module = 0, check_for_ai = 0)
|
||||
if(check_for_ai)
|
||||
return 0 //We don't do that here.
|
||||
if(offline || !cell || !cell.charge || locked_down)
|
||||
if(user)
|
||||
to_chat(user, span_warning("Your host rig is unpowered and unresponsive."))
|
||||
return 0
|
||||
if(!wearer || (wearer.back != src && wearer.belt != src))
|
||||
if(user)
|
||||
to_chat(user, span_warning("Your host rig is not being worn."))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/rig/protean/toggle_seals(mob/living/carbon/human/M, instant)
|
||||
M = src.wearer
|
||||
..()
|
||||
|
||||
/obj/item/rig/protean/toggle_cooling(mob/user)
|
||||
user = src.wearer
|
||||
..()
|
||||
|
||||
/obj/item/rig/protean/toggle_piece(piece, mob/living/carbon/human/H, deploy_mode, forced)
|
||||
H = src.wearer
|
||||
..()
|
||||
|
||||
/obj/item/rig/protean/get_description_interaction()
|
||||
if(dead)
|
||||
var/list/results = list()
|
||||
switch(dead)
|
||||
if(1)
|
||||
results += "Use a screwdriver to start repairs."
|
||||
if(2)
|
||||
results += "Insert a Protean Reboot Programmer, printed from a protolathe."
|
||||
if(3)
|
||||
results += "Use some Nanopaste."
|
||||
if(4)
|
||||
results += "Use either a defib or jumper cables to start the reboot sequence."
|
||||
return results
|
||||
|
||||
//Effectively a round about way of letting a Protean wear other rigs.
|
||||
/obj/item/rig/protean/proc/AssimilateRig(mob/user, var/obj/item/rig/R)
|
||||
if(!can_assimilate_rig)
|
||||
to_chat(user, span_warning("You can not place a rig into \the [src]"))
|
||||
return
|
||||
if(!R || assimilated_rig)
|
||||
return
|
||||
if(istype(R, /obj/item/rig/protean))
|
||||
to_chat(user, span_warning("The world is not ready for such a technological singularity."))
|
||||
return
|
||||
to_chat(user, span_notice("You assimilate the [R] into the [src]. Mimicking its stats and appearance."))
|
||||
for(var/obj/item/piece in list(gloves,helmet,boots,chest))
|
||||
piece.armor = R.armor.Copy()
|
||||
piece.max_pressure_protection = R.max_pressure_protection
|
||||
piece.max_heat_protection_temperature = R.max_heat_protection_temperature
|
||||
//I dislike this piece of code, but not every rig has the full set of parts
|
||||
if(R.gloves)
|
||||
gloves.sprite_sheets = R.gloves.sprite_sheets.Copy()
|
||||
gloves.sprite_sheets_obj = R.gloves.sprite_sheets.Copy()
|
||||
gloves.icon = R.gloves.icon
|
||||
gloves.icon_state = R.gloves.icon_state
|
||||
gloves.default_worn_icon = R.gloves.default_worn_icon
|
||||
if(R.helmet)
|
||||
helmet.sprite_sheets = R.helmet.sprite_sheets.Copy()
|
||||
helmet.sprite_sheets_obj = R.helmet.sprite_sheets.Copy()
|
||||
helmet.icon = R.helmet.icon
|
||||
helmet.icon_state = R.helmet.icon_state
|
||||
helmet.default_worn_icon = R.helmet.default_worn_icon
|
||||
if(R.boots)
|
||||
boots.sprite_sheets = R.boots.sprite_sheets.Copy()
|
||||
boots.sprite_sheets_obj = R.boots.sprite_sheets.Copy()
|
||||
boots.icon = R.boots.icon
|
||||
boots.icon_state = R.boots.icon_state
|
||||
boots.default_worn_icon = R.boots.default_worn_icon
|
||||
if(R.chest)
|
||||
chest.sprite_sheets = R.chest.sprite_sheets.Copy()
|
||||
chest.sprite_sheets_obj = R.chest.sprite_sheets.Copy()
|
||||
chest.icon = R.chest.icon
|
||||
chest.icon_state = R.chest.icon_state
|
||||
chest.default_worn_icon = R.chest.default_worn_icon
|
||||
|
||||
suit_state = R.suit_state
|
||||
name = R.name
|
||||
icon = R.icon
|
||||
icon_state = R.icon_state
|
||||
user.drop_item(R)
|
||||
contents += R
|
||||
assimilated_rig = R
|
||||
slowdown = (initial(R.slowdown) *0.5)
|
||||
offline_slowdown = slowdown
|
||||
|
||||
/obj/item/rig/protean/verb/RemoveRig()
|
||||
set name = "Remove Assimilated Rig"
|
||||
set category = "Object"
|
||||
|
||||
if(assimilated_rig)
|
||||
for(var/obj/item/piece in list(gloves,helmet,boots,chest))
|
||||
piece.armor = armor.Copy()
|
||||
piece.max_pressure_protection = initial(piece.max_pressure_protection)
|
||||
piece.max_heat_protection_temperature = initial(piece.max_heat_protection_temperature)
|
||||
piece.icon_state = src.icon_state
|
||||
piece.icon = initial(piece.icon)
|
||||
piece.default_worn_icon = initial(piece.default_worn_icon)
|
||||
|
||||
//Byond at this time does not support initial() on lists
|
||||
//So we have to create a new rig, just so we can copy the lists we're after
|
||||
//If someone figures out a smarter way to do this, please tell me
|
||||
var/obj/item/rig/tempRig = new /obj/item/rig/protean()
|
||||
gloves.sprite_sheets = tempRig.gloves.sprite_sheets.Copy()
|
||||
gloves.sprite_sheets_obj = tempRig.gloves.sprite_sheets.Copy()
|
||||
helmet.sprite_sheets = tempRig.helmet.sprite_sheets.Copy()
|
||||
helmet.sprite_sheets_obj = tempRig.helmet.sprite_sheets.Copy()
|
||||
boots.sprite_sheets = tempRig.boots.sprite_sheets.Copy()
|
||||
boots.sprite_sheets_obj = tempRig.boots.sprite_sheets.Copy()
|
||||
chest.sprite_sheets = tempRig.chest.sprite_sheets.Copy()
|
||||
chest.sprite_sheets_obj = tempRig.chest.sprite_sheets.Copy()
|
||||
slowdown = initial(slowdown)
|
||||
name = tempRig.name
|
||||
icon = tempRig.icon // Reset the icon back to its original
|
||||
icon_state = tempRig.icon_state
|
||||
suit_state = icon_state
|
||||
offline_slowdown = initial(offline_slowdown)
|
||||
usr.put_in_hands(assimilated_rig)
|
||||
assimilated_rig = null
|
||||
qdel(tempRig)
|
||||
else
|
||||
to_chat(usr, "[src] has not assimilated a RIG. Use one on it to assimilate.")
|
||||
|
||||
/obj/item/rig/protean/MouseDrop(obj/over_object as obj)
|
||||
if(!canremove)
|
||||
return
|
||||
|
||||
if (isliving(usr) || isobserver(usr))
|
||||
|
||||
if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
|
||||
return
|
||||
|
||||
if (!( istype(over_object, /obj/screen) ))
|
||||
return ..()
|
||||
|
||||
if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
|
||||
return
|
||||
|
||||
if (( usr.restrained() ) || ( usr.stat ))
|
||||
return
|
||||
|
||||
if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src))
|
||||
return
|
||||
|
||||
switch(over_object.name)
|
||||
if("r_hand")
|
||||
usr.unEquip(src)
|
||||
usr.put_in_r_hand(src)
|
||||
if("l_hand")
|
||||
usr.unEquip(src)
|
||||
usr.put_in_l_hand(src)
|
||||
src.add_fingerprint(usr)
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
It's a bit snowflake, but some rigsuit rewriting was necessary to achieved what I wanted
|
||||
for protean rigsuits, and rolling these changes into the base RIGsuit code would definitely create
|
||||
merge conflicts down the line.
|
||||
So here it sits, snowflake code for a single item.
|
||||
*/
|
||||
|
||||
/obj/item/rig/protean/tgui_state(mob/user)
|
||||
return GLOB.tgui_always_state
|
||||
|
||||
/obj/item/rig/protean/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
if(selected_module)
|
||||
data["primarysystem"] = "[selected_module.interface_name]"
|
||||
else
|
||||
data["primarysystem"] = null
|
||||
|
||||
if(loc != user)
|
||||
data["ai"] = TRUE
|
||||
else
|
||||
data["ai"] = FALSE
|
||||
|
||||
data["cooling"] = cooling_on
|
||||
data["sealed"] = !sealed
|
||||
data["sealing"] = sealing
|
||||
data["helmet"] = (helmet ? "[helmet.name]" : "None.")
|
||||
data["gauntlets"] = (gloves ? "[gloves.name]" : "None.")
|
||||
data["boots"] = (boots ? "[boots.name]" : "None.")
|
||||
data["chest"] = (chest ? "[chest.name]" : "None.")
|
||||
|
||||
data["helmetDeployed"] = (helmet && helmet.loc == loc)
|
||||
data["gauntletsDeployed"] = (gloves && gloves.loc == loc)
|
||||
data["bootsDeployed"] = (boots && boots.loc == loc)
|
||||
data["chestDeployed"] = (chest && chest.loc == loc)
|
||||
|
||||
data["charge"] = cell ? round(cell.charge,1) : 0
|
||||
data["maxcharge"] = cell ? cell.maxcharge : 0
|
||||
data["chargestatus"] = cell ? FLOOR((cell.charge/cell.maxcharge)*50, 1) : 0
|
||||
|
||||
data["emagged"] = subverted
|
||||
data["coverlock"] = locked
|
||||
data["interfacelock"] = interface_locked
|
||||
data["aicontrol"] = control_overridden
|
||||
data["aioverride"] = ai_override_enabled
|
||||
data["securitycheck"] = security_check_enabled
|
||||
data["malf"] = malfunction_delay
|
||||
|
||||
var/list/module_list = list()
|
||||
if(!canremove && !sealing)
|
||||
var/i = 1
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
var/list/module_data = list(
|
||||
"index" = i,
|
||||
"name" = "[module.interface_name]",
|
||||
"desc" = "[module.interface_desc]",
|
||||
"can_use" = module.usable,
|
||||
"can_select" = module.selectable,
|
||||
"can_toggle" = module.toggleable,
|
||||
"is_active" = module.active,
|
||||
"engagecost" = module.use_power_cost*10,
|
||||
"activecost" = module.active_power_cost*10,
|
||||
"passivecost" = module.passive_power_cost*10,
|
||||
"engagestring" = module.engage_string,
|
||||
"activatestring" = module.activate_string,
|
||||
"deactivatestring" = module.deactivate_string,
|
||||
"damage" = module.damage
|
||||
)
|
||||
|
||||
if(module.charges && module.charges.len)
|
||||
module_data["charges"] = list()
|
||||
var/datum/rig_charge/selected = module.charges["[module.charge_selected]"]
|
||||
module_data["realchargetype"] = module.charge_selected
|
||||
module_data["chargetype"] = selected ? "[selected.display_name]" : "none"
|
||||
|
||||
for(var/chargetype in module.charges)
|
||||
var/datum/rig_charge/charge = module.charges[chargetype]
|
||||
module_data["charges"] += list(list("caption" = "[charge.display_name] ([charge.charges])", "index" = "[chargetype]"))
|
||||
|
||||
module_list += list(module_data)
|
||||
i++
|
||||
|
||||
if(module_list.len)
|
||||
data["modules"] = module_list
|
||||
else
|
||||
data["modules"] = list()
|
||||
|
||||
return data
|
||||
/*
|
||||
/obj/item/rig/protean/tgui_act(action, params)
|
||||
switch(action)
|
||||
if("toggle_seals")
|
||||
toggle_seals(wearer)
|
||||
. = TRUE
|
||||
if("toggle_cooling")
|
||||
toggle_cooling(wearer)
|
||||
. = TRUE
|
||||
if("toggle_ai_control")
|
||||
to_chat(usr, span_notice("Proteans cannot be AI controlled."))
|
||||
. = TRUE
|
||||
if("toggle_suit_lock")
|
||||
locked = !locked
|
||||
. = TRUE
|
||||
if("toggle_piece")
|
||||
toggle_piece(params["piece"], wearer)
|
||||
. = TRUE
|
||||
if("interact_module")
|
||||
var/module_index = text2num(params["module"])
|
||||
|
||||
if(module_index > 0 && module_index <= installed_modules.len)
|
||||
var/obj/item/rig_module/module = installed_modules[module_index]
|
||||
switch(params["module_mode"])
|
||||
if("select")
|
||||
selected_module = module
|
||||
. = TRUE
|
||||
if("engage")
|
||||
module.engage()
|
||||
. = TRUE
|
||||
if("toggle")
|
||||
if(module.active)
|
||||
module.deactivate()
|
||||
else
|
||||
module.activate()
|
||||
. = TRUE
|
||||
if("select_charge_type")
|
||||
module.charge_selected = params["charge_type"]
|
||||
. = TRUE
|
||||
*/
|
||||
+133
-55
@@ -1,5 +1,4 @@
|
||||
#define DAM_SCALE_FACTOR 0.01
|
||||
#define METAL_PER_TICK 100
|
||||
#define METAL_PER_TICK SHEET_MATERIAL_AMOUNT/20
|
||||
/datum/species/protean
|
||||
name = SPECIES_PROTEAN
|
||||
name_plural = "Proteans"
|
||||
@@ -7,7 +6,7 @@
|
||||
" + span_italics("VERY") + " advanced civilizations have the option of 'nanoswarm' bodies. Effectively a single robot body comprised \
|
||||
of millions of tiny nanites working in concert to maintain cohesion."
|
||||
show_ssd = "totally quiescent"
|
||||
death_message = "rapidly loses cohesion, dissolving into a cloud of gray dust..."
|
||||
death_message = "rapidly loses cohesion, retreating into their hardened control module..."
|
||||
knockout_message = "collapses inwards, forming a disordered puddle of gray goo."
|
||||
remains_type = /obj/effect/decal/cleanable/ash
|
||||
|
||||
@@ -26,50 +25,52 @@
|
||||
num_alternate_languages = 3
|
||||
species_language = LANGUAGE_EAL
|
||||
assisted_langs = list(LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX)
|
||||
speech_bubble_appearance = "synthetic"
|
||||
color_mult = TRUE
|
||||
|
||||
breath_type = null
|
||||
poison_type = null
|
||||
|
||||
virus_immune = 1
|
||||
blood_volume = 0
|
||||
min_age = 18
|
||||
max_age = 200
|
||||
brute_mod = 0.8
|
||||
burn_mod = 1.5
|
||||
oxy_mod = 0
|
||||
item_slowdown_mod = 1.33
|
||||
// male_scream_sound = null
|
||||
// female_scream_sound = null
|
||||
|
||||
cold_level_1 = 280 //Default 260 - Lower is better
|
||||
cold_level_2 = 220 //Default 200
|
||||
cold_level_3 = 130 //Default 120
|
||||
|
||||
heat_level_1 = 320 //Default 360
|
||||
heat_level_2 = 370 //Default 400
|
||||
heat_level_3 = 600 //Default 1000
|
||||
virus_immune = 1
|
||||
blood_volume = 0
|
||||
min_age = 18
|
||||
max_age = 200
|
||||
oxy_mod = 0
|
||||
//radiation_mod = 0 //Can't be assed with fandangling rad protections while blob formed/suited
|
||||
siemens_coefficient = 2
|
||||
brute_mod = 0.8
|
||||
burn_mod = 1.5
|
||||
emp_dmg_mod = 0.8
|
||||
emp_sensitivity = EMP_BLIND | EMP_DEAFEN | EMP_BRUTE_DMG | EMP_BURN_DMG
|
||||
item_slowdown_mod = 1.5 //Gentle encouragement to let others wear you
|
||||
|
||||
hazard_low_pressure = -1 //Space doesn't bother them
|
||||
hazard_high_pressure = 200 //They can cope with slightly higher pressure
|
||||
|
||||
//Cold/heat does affect them, but it's done in special ways below
|
||||
cold_level_1 = -INFINITY
|
||||
cold_level_2 = -INFINITY
|
||||
cold_level_3 = -INFINITY
|
||||
heat_level_1 = INFINITY
|
||||
heat_level_2 = INFINITY
|
||||
heat_level_3 = INFINITY
|
||||
heat_level_1 = 420
|
||||
heat_level_2 = 480
|
||||
heat_level_3 = 1100
|
||||
|
||||
body_temperature = 290
|
||||
body_temperature = 290
|
||||
|
||||
siemens_coefficient = 1.5 //Very bad zappy times
|
||||
rarity_value = 5
|
||||
rarity_value = 5
|
||||
|
||||
// species_sounds = "Robotic"
|
||||
|
||||
// crit_mod = 4 //Unable to go crit
|
||||
var/obj/item/rig/protean/OurRig
|
||||
|
||||
genders = list(MALE, FEMALE, PLURAL, NEUTER)
|
||||
|
||||
has_organ = list(
|
||||
O_BRAIN = /obj/item/organ/internal/mmi_holder/posibrain/nano,
|
||||
O_ORCH = /obj/item/organ/internal/nano/orchestrator,
|
||||
O_FACT = /obj/item/organ/internal/nano/refactory
|
||||
O_FACT = /obj/item/organ/internal/nano/refactory,
|
||||
)
|
||||
has_limbs = list(
|
||||
BP_TORSO = list("path" = /obj/item/organ/external/chest/unbreakable/nano),
|
||||
@@ -85,7 +86,7 @@
|
||||
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/unbreakable/nano)
|
||||
)
|
||||
|
||||
heat_discomfort_strings = list("You feel too warm.")
|
||||
heat_discomfort_strings = list("WARNING: Temperature exceeding acceptable thresholds!.")
|
||||
cold_discomfort_strings = list("You feel too cool.")
|
||||
|
||||
//These verbs are hidden, for hotkey use only
|
||||
@@ -94,7 +95,11 @@
|
||||
/mob/living/carbon/human/proc/nano_partswap,
|
||||
/mob/living/carbon/human/proc/nano_metalnom,
|
||||
/mob/living/carbon/human/proc/nano_blobform,
|
||||
/mob/living/carbon/human/proc/nano_set_size,
|
||||
/mob/living/carbon/human/proc/nano_rig_transform,
|
||||
/mob/living/carbon/human/proc/nano_copy_body,
|
||||
/mob/living/carbon/human/proc/appearance_switch,
|
||||
/mob/living/carbon/human/proc/nano_latch,
|
||||
/mob/living/proc/set_size,
|
||||
/mob/living/carbon/human/proc/nano_change_fitting, //These verbs are displayed normally,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_hair,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_hair_colors,
|
||||
@@ -105,12 +110,29 @@
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_tail,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_ears,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_secondary_ears,
|
||||
)
|
||||
/mob/living/proc/flying_toggle,
|
||||
/mob/living/proc/flying_vore_toggle,
|
||||
/mob/living/proc/start_wings_hovering,
|
||||
) //removed fetish verbs, since non-customs can pick neutral traits now. Also added flight, cause shapeshifter can grow wings.
|
||||
|
||||
var/global/list/abilities = list()
|
||||
|
||||
var/monochromatic = FALSE //IGNORE ME
|
||||
|
||||
var/blob_appearance = "puddle1"
|
||||
var/blob_color_1 = "#363636"
|
||||
var/blob_color_2 = "#ba3636"
|
||||
var/list/dragon_overlays = list(
|
||||
"dragon_underSmooth" = "#FFFFFF",
|
||||
"dragon_bodySmooth" = "#FFFFFF",
|
||||
"dragon_earsNormal" = "#FFFFFF",
|
||||
"dragon_maneShaggy" = "#FFFFFF",
|
||||
"dragon_hornsPointy" = "#FFFFFF",
|
||||
"dragon_eyesNormal" = "#FFFFFF"
|
||||
)
|
||||
|
||||
var/pseudodead = 0
|
||||
|
||||
/datum/species/protean/New()
|
||||
..()
|
||||
if(!LAZYLEN(abilities))
|
||||
@@ -127,20 +149,62 @@
|
||||
if(saved_nif)
|
||||
saved_nif.quick_implant(H)
|
||||
|
||||
/datum/species/protean/get_race_key()
|
||||
var/datum/species/real = GLOB.all_species[base_species]
|
||||
return real.race_key
|
||||
|
||||
/datum/species/protean/get_bodytype(var/mob/living/carbon/human/H)
|
||||
if(!H || base_species == name) return ..()
|
||||
var/datum/species/S = GLOB.all_species[base_species]
|
||||
return S.get_bodytype(H)
|
||||
|
||||
/datum/species/protean/get_icobase(var/mob/living/carbon/human/H, var/get_deform)
|
||||
if(!H || base_species == name) return ..(null, get_deform)
|
||||
var/datum/species/S = GLOB.all_species[base_species]
|
||||
return S.get_icobase(H, get_deform)
|
||||
|
||||
/datum/species/protean/get_valid_shapeshifter_forms(var/mob/living/carbon/human/H)
|
||||
return GLOB.playable_species
|
||||
var/static/list/protean_shapeshifting_forms = GLOB.playable_species.Copy() - SPECIES_PROMETHEAN
|
||||
return protean_shapeshifting_forms
|
||||
|
||||
/datum/species/protean/get_tail(var/mob/living/carbon/human/H)
|
||||
if(!H || base_species == name) return ..()
|
||||
var/datum/species/S = GLOB.all_species[base_species]
|
||||
return S.get_tail(H)
|
||||
|
||||
/datum/species/protean/get_tail_animation(var/mob/living/carbon/human/H)
|
||||
if(!H || base_species == name) return ..()
|
||||
var/datum/species/S = GLOB.all_species[base_species]
|
||||
return S.get_tail_animation(H)
|
||||
|
||||
/datum/species/protean/get_tail_hair(var/mob/living/carbon/human/H)
|
||||
if(!H || base_species == name) return ..()
|
||||
var/datum/species/S = GLOB.all_species[base_species]
|
||||
return S.get_tail_hair(H)
|
||||
|
||||
/datum/species/protean/get_blood_mask(var/mob/living/carbon/human/H)
|
||||
if(!H || base_species == name) return ..()
|
||||
var/datum/species/S = GLOB.all_species[base_species]
|
||||
return S.get_blood_mask(H)
|
||||
|
||||
/datum/species/protean/get_damage_mask(var/mob/living/carbon/human/H)
|
||||
if(!H || base_species == name) return ..()
|
||||
var/datum/species/S = GLOB.all_species[base_species]
|
||||
return S.get_damage_mask(H)
|
||||
|
||||
/datum/species/protean/get_damage_overlays(var/mob/living/carbon/human/H)
|
||||
if(!H || base_species == name) return ..()
|
||||
var/datum/species/S = GLOB.all_species[base_species]
|
||||
return S.get_damage_overlays(H)
|
||||
|
||||
/datum/species/protean/handle_post_spawn(var/mob/living/carbon/human/H)
|
||||
..()
|
||||
H.synth_color = TRUE
|
||||
|
||||
/datum/species/protean/equip_survival_gear(var/mob/living/carbon/human/H)
|
||||
var/obj/item/stack/material/steel/metal_stack = new(null, 3)
|
||||
..()
|
||||
var/obj/item/stack/material/steel/metal_stack = new()
|
||||
metal_stack.set_amount(5)
|
||||
|
||||
var/obj/item/clothing/accessory/permit/nanotech/permit = new()
|
||||
permit.set_name(H.real_name)
|
||||
@@ -161,6 +225,8 @@
|
||||
else
|
||||
H.nif.durability = 25
|
||||
|
||||
new /obj/item/rig/protean(H,H)
|
||||
|
||||
/datum/species/protean/hug(var/mob/living/carbon/human/H, var/mob/living/target)
|
||||
return ..() //Wut
|
||||
|
||||
@@ -172,18 +238,22 @@
|
||||
|
||||
/datum/species/protean/handle_death(var/mob/living/carbon/human/H)
|
||||
if(!H)
|
||||
return // Iono!
|
||||
|
||||
return //No body?
|
||||
if(OurRig.dead)
|
||||
return
|
||||
OurRig.dead = 1
|
||||
var/mob/temp = H
|
||||
if(H.temporary_form)
|
||||
H.forceMove(H.temporary_form.drop_location())
|
||||
H.ckey = H.temporary_form.ckey
|
||||
QDEL_NULL(H.temporary_form)
|
||||
|
||||
to_chat(H, span_warning("You died as a Protean. Please sit out of the round for at least 60 minutes before respawning, to represent the time it would take to ship a new-you to the station."))
|
||||
|
||||
spawn(1)
|
||||
if(H)
|
||||
H.gib()
|
||||
temp = H.temporary_form
|
||||
playsound(temp, 'sound/voice/borg_deathsound.ogg', 50, 1)
|
||||
temp.visible_message(span_bold("[temp.name]") + " shudders and retreats inwards, coalescing into a single core componant!")
|
||||
to_chat(temp, span_warning("You've died as a Protean! While dead, you will be locked to your core RIG control module until you can be repaired. Instructions to your revival can be found in the Examine tab when examining your module."))
|
||||
if(H.temporary_form)
|
||||
if(!istype(H.temporary_form.loc, /obj/item/rig/protean))
|
||||
H.nano_rig_transform(1)
|
||||
else
|
||||
H.nano_rig_transform(1)
|
||||
pseudodead = 1
|
||||
|
||||
/datum/species/protean/handle_environment_special(var/mob/living/carbon/human/H)
|
||||
if((H.getActualBruteLoss() + H.getActualFireLoss()) > H.maxHealth*0.5 && isturf(H.loc)) //So, only if we're not a blob (we're in nullspace) or in someone (or a locker, really, but whatever)
|
||||
@@ -325,16 +395,26 @@
|
||||
material_name = MAT_STEEL
|
||||
|
||||
/datum/modifier/protean/steel/tick()
|
||||
holder.adjustBruteLoss(-1,include_robo = TRUE) //Modified by species resistances
|
||||
holder.adjustFireLoss(-0.5,include_robo = TRUE) //Modified by species resistances
|
||||
var/mob/living/carbon/human/H = holder
|
||||
for(var/obj/item/organ/O as anything in H.internal_organs)
|
||||
// Fix internal damage
|
||||
if(O.damage > 0)
|
||||
O.damage = max(0,O.damage-0.1)
|
||||
// If not damaged, but dead, fix it
|
||||
else if(O.status & ORGAN_DEAD)
|
||||
O.status &= ~ORGAN_DEAD //Unset dead if we repaired it entirely
|
||||
//Heal a random damaged limb by 1,1 per tick
|
||||
holder.adjustBruteLoss(-1,include_robo = TRUE)
|
||||
holder.adjustFireLoss(-1,include_robo = TRUE)
|
||||
holder.adjustToxLoss(-1)
|
||||
|
||||
var/mob/living/carbon/human/H
|
||||
if(ishuman(holder))
|
||||
H = holder
|
||||
|
||||
//Then heal every damaged limb by a smaller amount
|
||||
if(H)
|
||||
for(var/obj/item/organ/external/O in H.organs)
|
||||
O.heal_damage(0.5, 0.5, 0, 1)
|
||||
|
||||
//Heal the organs a little bit too, as a treat
|
||||
for(var/obj/item/organ/O as anything in H.internal_organs)
|
||||
if(O.damage > 0)
|
||||
O.damage = max(0,O.damage-0.3)
|
||||
else if(O.status & ORGAN_DEAD)
|
||||
O.status &= ~ORGAN_DEAD //Unset dead if we repaired it entirely
|
||||
|
||||
// PAN Card
|
||||
/obj/item/clothing/accessory/permit/nanotech
|
||||
@@ -357,6 +437,4 @@
|
||||
. = ..()
|
||||
. += validstring
|
||||
. += registring
|
||||
|
||||
#undef DAM_SCALE_FACTOR
|
||||
#undef METAL_PER_TICK
|
||||
|
||||
+1
-1
@@ -170,7 +170,7 @@
|
||||
update_canmove()
|
||||
weakened = 2
|
||||
|
||||
revive_ready = world.time + 10 MINUTES //set the cooldown CHOMPEdit: Reduced this to 10 minutes, you're playing with fire if you're reviving that often.
|
||||
revive_ready = world.time + 10 MINUTES //set the cooldown, Reduced this to 10 minutes, you're playing with fire if you're reviving that often.
|
||||
|
||||
/datum/modifier/resleeving_sickness/chimera //near identical to the regular version, just with different flavortexts
|
||||
name = "imperfect regeneration"
|
||||
|
||||
@@ -28,3 +28,9 @@
|
||||
S.sharer_died(gibbed)
|
||||
|
||||
. = ..()
|
||||
|
||||
/mob/living/proc/delayed_gib()
|
||||
visible_message(span_danger(span_bold("[src]") + " starts convulsing violently!"), span_danger("You feel as if your body is tearing itself apart!"))
|
||||
Weaken(30)
|
||||
make_jittery(1000)
|
||||
addtimer(CALLBACK(src, PROC_REF(gib)), rand(2 SECONDS, 10 SECONDS))
|
||||
|
||||
@@ -25,6 +25,17 @@
|
||||
else
|
||||
newitem.forceMove(S)
|
||||
return S
|
||||
|
||||
if(istype(src.back,/obj/item/rig)) //This would be much cooler if we had componentized storage datums
|
||||
var/obj/item/rig/R = src.back
|
||||
if(R.rig_storage)
|
||||
var/obj/item/storage/backpack = R.rig_storage
|
||||
if(backpack.can_be_inserted(newitem, 1))
|
||||
if(user_initiated)
|
||||
backpack.handle_item_insertion(newitem)
|
||||
else
|
||||
newitem.forceMove(src.back)
|
||||
return backpack
|
||||
return 0
|
||||
|
||||
//Returns the thing in our active hand
|
||||
|
||||
@@ -613,6 +613,11 @@
|
||||
L += D.wrapped
|
||||
if(istype(D.wrapped, /obj/item/storage)) //this should never happen
|
||||
L += get_contents(D.wrapped)
|
||||
|
||||
for(var/obj/item/rig/R in src.contents) //Check rigsuit storage for items
|
||||
if(R.rig_storage)
|
||||
L += get_contents(R.rig_storage)
|
||||
|
||||
return L
|
||||
|
||||
/mob/living/proc/check_contents_for(A)
|
||||
|
||||
@@ -140,50 +140,8 @@
|
||||
set desc = "Sets your voice style!"
|
||||
set category = "OOC.Game Settings"
|
||||
|
||||
var/list/possible_voice_types = list(
|
||||
"beep-boop",
|
||||
"goon speak 1",
|
||||
"goon speak 2",
|
||||
"goon speak 3",
|
||||
"goon speak 4",
|
||||
"goon speak blub",
|
||||
"goon speak bottalk",
|
||||
"goon speak buwoo",
|
||||
"goon speak cow",
|
||||
"goon speak lizard",
|
||||
"goon speak pug",
|
||||
"goon speak pugg",
|
||||
"goon speak roach",
|
||||
"goon speak skelly")
|
||||
var/list/possible_voice_types = get_talk_sound()
|
||||
var/choice = tgui_input_list(usr, "Which set of sounds would you like to use for your character's speech sounds?", "Voice Sounds", possible_voice_types)
|
||||
if(!choice)
|
||||
voice_sounds_list = talk_sound
|
||||
switch(choice)
|
||||
if("beep-boop")
|
||||
voice_sounds_list = talk_sound
|
||||
if("goon speak 1")
|
||||
voice_sounds_list = goon_speak_one_sound
|
||||
if("goon speak 2")
|
||||
voice_sounds_list = goon_speak_two_sound
|
||||
if("goon speak 3")
|
||||
voice_sounds_list = goon_speak_three_sound
|
||||
if("goon speak 4")
|
||||
voice_sounds_list = goon_speak_four_sound
|
||||
if("goon speak blub")
|
||||
voice_sounds_list = goon_speak_blub_sound
|
||||
if("goon speak bottalk")
|
||||
voice_sounds_list = goon_speak_bottalk_sound
|
||||
if("goon speak buwoo")
|
||||
voice_sounds_list = goon_speak_buwoo_sound
|
||||
if("goon speak cow")
|
||||
voice_sounds_list = goon_speak_cow_sound
|
||||
if("goon speak lizard")
|
||||
voice_sounds_list = goon_speak_lizard_sound
|
||||
if("goon speak pug")
|
||||
voice_sounds_list = goon_speak_pug_sound
|
||||
if("goon speak pugg")
|
||||
voice_sounds_list = goon_speak_pugg_sound
|
||||
if("goon speak roach")
|
||||
voice_sounds_list = goon_speak_roach_sound
|
||||
if("goon speak skelly")
|
||||
voice_sounds_list = goon_speak_skelly_sound
|
||||
voice_sounds_list = get_talk_sound(choice)
|
||||
|
||||
@@ -29,35 +29,7 @@
|
||||
if(!voice_sounds_list.len || !voice_sounds_list)
|
||||
if(client.prefs.voice_sound)
|
||||
var/prefsound = client.prefs.voice_sound
|
||||
switch(prefsound)
|
||||
if("beep-boop")
|
||||
voice_sounds_list = talk_sound
|
||||
if("goon speak 1")
|
||||
voice_sounds_list = goon_speak_one_sound
|
||||
if("goon speak 2")
|
||||
voice_sounds_list = goon_speak_two_sound
|
||||
if("goon speak 3")
|
||||
voice_sounds_list = goon_speak_three_sound
|
||||
if("goon speak 4")
|
||||
voice_sounds_list = goon_speak_four_sound
|
||||
if("goon speak blub")
|
||||
voice_sounds_list = goon_speak_blub_sound
|
||||
if("goon speak bottalk")
|
||||
voice_sounds_list = goon_speak_bottalk_sound
|
||||
if("goon speak buwoo")
|
||||
voice_sounds_list = goon_speak_buwoo_sound
|
||||
if("goon speak cow")
|
||||
voice_sounds_list = goon_speak_cow_sound
|
||||
if("goon speak lizard")
|
||||
voice_sounds_list = goon_speak_lizard_sound
|
||||
if("goon speak pug")
|
||||
voice_sounds_list = goon_speak_pug_sound
|
||||
if("goon speak pugg")
|
||||
voice_sounds_list = goon_speak_pugg_sound
|
||||
if("goon speak roach")
|
||||
voice_sounds_list = goon_speak_roach_sound
|
||||
if("goon speak skelly")
|
||||
voice_sounds_list = goon_speak_skelly_sound
|
||||
voice_sounds_list = get_talk_sound(prefsound)
|
||||
else
|
||||
voice_sounds_list = talk_sound
|
||||
//VOREStation Add End
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user