mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-08-30 16:48:12 +01:00
[MIRROR] Completes the /datum/component/shadekin work (#11148)
Co-authored-by: Cameron Lennox <killer65311@gmail.com> Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
co-authored by
Cameron Lennox
Kashargul
parent
52b6360a09
commit
3e095bf5db
@@ -838,8 +838,9 @@
|
||||
#define COMSIG_GARGOYLE_CHECK_ENERGY "gargoyle_check_energy"
|
||||
|
||||
// Species Components
|
||||
///from /datum/species/xenochimera/handle_environment_special()
|
||||
///from /datum/species/proc/handle_species_components()
|
||||
#define COMSIG_XENOCHIMERA_COMPONENT "xenochimera_component"
|
||||
#define COMSIG_SHADEKIN_COMPONENT "shadekin_component"
|
||||
|
||||
// Hose Connector Component
|
||||
#define COMSIG_HOSE_FORCEPUMP "hose_force_pump"
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
#define NOT_WHILE_SHIFTED 1
|
||||
#define ONLY_WHILE_SHIFTED 2
|
||||
#define SHIFTED_OR_NOT 3
|
||||
|
||||
#define AB_PHASE_SHIFTED 0x1
|
||||
#define AB_PHASE_SHIFTING 0x2
|
||||
#define AB_SHADE_REGEN 0x4
|
||||
#define AB_DARK_TUNNEL 0x40 //CHOMPEdit Add - Dark Tunneling
|
||||
#define AB_DARK_RESPITE 0x80 //CHOMPEdit Add - Dark Respite
|
||||
|
||||
//Porting over the type system of the mobs
|
||||
#define BLUE_EYES 1
|
||||
#define RED_EYES 2
|
||||
|
||||
@@ -11,8 +11,13 @@ GLOBAL_LIST_EMPTY(everyone_traits_neutral) // Neutral traits available to all sp
|
||||
GLOBAL_LIST_EMPTY(everyone_traits_negative) // Neutral traits available to all species, indexed by path
|
||||
GLOBAL_LIST_EMPTY(traits_costs) // Just path = cost list, saves time in char setup
|
||||
GLOBAL_LIST_EMPTY(all_traits) // All of 'em at once (same instances)
|
||||
GLOBAL_LIST_EMPTY(active_ghost_pods)
|
||||
|
||||
GLOBAL_LIST_EMPTY(active_ghost_pods) //NYI - Used downstream
|
||||
GLOBAL_LIST_EMPTY(latejoin_gatewaystation) //NYI - Used downstream
|
||||
GLOBAL_LIST_EMPTY(latejoin_plainspath) //NYI - Used downstream
|
||||
GLOBAL_LIST_EMPTY(latejoin_fueldepot) //NYI - Used downstream
|
||||
GLOBAL_LIST_EMPTY(latejoin_tyrvillage) //NYI - Used downstream
|
||||
GLOBAL_LIST_EMPTY(latejoin_thedark) //NYI - Used downstream
|
||||
//Global vars for making the overmap_renamer subsystem.
|
||||
//Collects all instances by reference of visitable overmap objects of /obj/effect/overmap/visitable like the debris field.
|
||||
GLOBAL_LIST_EMPTY(visitable_overmap_object_instances)
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
return
|
||||
if(!Adjacent(usr) || !over.Adjacent(usr))
|
||||
return // should stop you from dragging through windows
|
||||
if(is_incorporeal(usr))
|
||||
return
|
||||
|
||||
INVOKE_ASYNC(over, TYPE_PROC_REF(/atom, MouseDrop_T), src, usr, src_location, over_location, src_control, over_control, params)
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
showing = 0
|
||||
overlays.len = 0
|
||||
overlays.Add(closed_state)
|
||||
else if(forced_state != 1) // We're opening it, show the icons.
|
||||
else if(forced_state != 1) // We're opening it, show the icons. OR, if forced_state == 2, we're forcing it to open it.
|
||||
open_ability_master()
|
||||
update_abilities(1)
|
||||
showing = 1
|
||||
@@ -84,6 +84,7 @@
|
||||
A.screen_loc = "[encode_screen_X(xpos)]:[x_pix],[encode_screen_Y(ypos)]:[y_pix]"
|
||||
if(my_mob && my_mob.client)
|
||||
my_mob.client.screen += A
|
||||
my_mob.client.screen |= src
|
||||
// A.handle_icon_updates = 1
|
||||
|
||||
/obj/screen/movable/ability_master/proc/update_abilities(forced = 0, mob/user)
|
||||
@@ -177,12 +178,12 @@
|
||||
/mob/Login()
|
||||
..()
|
||||
if(ability_master)
|
||||
ability_master.toggle_open(1)
|
||||
client.screen -= ability_master
|
||||
ability_master.toggle_open(2) //Force it to open on login.
|
||||
//client.screen -= ability_master
|
||||
|
||||
/mob/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!ability_master) //VOREStation Edit: S H A D E K I N
|
||||
if(!ability_master)
|
||||
ability_master = new /obj/screen/movable/ability_master(src)
|
||||
|
||||
///////////ACTUAL ABILITIES////////////
|
||||
|
||||
@@ -547,6 +547,31 @@ GLOBAL_LIST_INIT(global_huds, list(
|
||||
/mob/new_player/add_click_catcher()
|
||||
return
|
||||
|
||||
/mob/living/create_mob_hud(datum/hud/HUD, apply_to_client = TRUE)
|
||||
..()
|
||||
|
||||
var/list/hud_elements = list()
|
||||
shadekin_display = new /obj/screen/shadekin()
|
||||
shadekin_display.screen_loc = ui_shadekin_display
|
||||
shadekin_display.icon_state = "shadekin"
|
||||
hud_elements |= shadekin_display
|
||||
|
||||
xenochimera_danger_display = new /obj/screen/xenochimera/danger_level()
|
||||
xenochimera_danger_display.screen_loc = ui_xenochimera_danger_display
|
||||
xenochimera_danger_display.icon_state = "danger00"
|
||||
hud_elements |= xenochimera_danger_display
|
||||
|
||||
lleill_display = new /obj/screen/lleill()
|
||||
lleill_display.screen_loc = ui_lleill_display
|
||||
lleill_display.icon_state = "lleill"
|
||||
hud_elements |= lleill_display
|
||||
|
||||
if(client)
|
||||
client.screen = list()
|
||||
|
||||
client.screen += hud_elements
|
||||
client.screen += client.void
|
||||
|
||||
/* TGMC Ammo HUD Port
|
||||
* These procs call to screen_objects.dm's respective procs.
|
||||
* All these do is manage the amount of huds on screen and set the HUD.
|
||||
|
||||
@@ -321,22 +321,10 @@
|
||||
using.alpha = HUD.ui_alpha
|
||||
adding |= using
|
||||
|
||||
//VOREStation Addition begin
|
||||
shadekin_display = new /obj/screen/shadekin()
|
||||
shadekin_display.screen_loc = ui_shadekin_display
|
||||
shadekin_display.icon_state = "shadekin"
|
||||
//Component hud elements. Made in /mob/living/create_mob_hud
|
||||
hud_elements |= shadekin_display
|
||||
|
||||
xenochimera_danger_display = new /obj/screen/xenochimera/danger_level()
|
||||
xenochimera_danger_display.screen_loc = ui_xenochimera_danger_display
|
||||
xenochimera_danger_display.icon_state = "danger00"
|
||||
hud_elements |= xenochimera_danger_display
|
||||
|
||||
lleill_display = new /obj/screen/lleill()
|
||||
lleill_display.screen_loc = ui_lleill_display
|
||||
lleill_display.icon_state = "lleill"
|
||||
hud_elements |= lleill_display
|
||||
//VOREStation Addition end
|
||||
|
||||
ling_chem_display = new /obj/screen/ling/chems()
|
||||
ling_chem_display.screen_loc = ui_ling_chemical_display
|
||||
|
||||
@@ -623,7 +623,7 @@
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
AI.view_images()
|
||||
else
|
||||
return attempt_vr(src,"Click_vr",list(location,control,params)) //VOREStation Add - Additional things.
|
||||
return attempt_vr(src,"Click_vr",list(location,control,params))
|
||||
return 1
|
||||
|
||||
/obj/screen/inventory/Click()
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
/obj/screen/proc/Click_vr(location, control, params)
|
||||
if(!usr) return 1
|
||||
switch(name)
|
||||
|
||||
//Shadekin
|
||||
if("darkness")
|
||||
var/turf/T = get_turf(usr)
|
||||
var/darkness = round(1 - T.get_lumcount(),0.1)
|
||||
to_chat(usr,span_notice(span_bold("Darkness:") + " [darkness]"))
|
||||
if("energy")
|
||||
var/mob/living/simple_mob/shadekin/SK = usr
|
||||
if(istype(SK))
|
||||
to_chat(usr,span_notice(span_bold("Energy:") + " [SK.comp.dark_energy] ([SK.dark_gains])"))
|
||||
if("shadekin status")
|
||||
var/turf/T = get_turf(usr)
|
||||
if(T)
|
||||
var/darkness = round(1 - T.get_lumcount(),0.1)
|
||||
to_chat(usr,span_notice(span_bold("Darkness:") + " [darkness]"))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(istype(H) && istype(H.species, /datum/species/shadekin))
|
||||
to_chat(usr,span_notice(span_bold("Energy:") + " [H.shadekin_get_energy(H)]"))
|
||||
var/mob/living/H = usr
|
||||
if(ismob(H))
|
||||
var/datum/component/shadekin/SK = H.get_shadekin_component()
|
||||
if(SK)
|
||||
to_chat(usr,span_notice(span_bold("Energy:") + " [SK.shadekin_get_energy()]"))
|
||||
if("glamour")
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(istype(H))
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/datum/component/shadekin
|
||||
var/dark_energy = 100
|
||||
var/max_dark_energy = 100
|
||||
var/dark_energy_infinite = FALSE
|
||||
|
||||
/datum/component/shadekin/Initialize()
|
||||
if(!ishuman(parent) && !issimplekin(parent)) //Both humankin and simplekin can have this component
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
@@ -0,0 +1,213 @@
|
||||
///Returns the shadekin component of the given mob
|
||||
/mob/living/proc/get_shadekin_component()
|
||||
var/datum/component/shadekin/SK = GetComponent(/datum/component/shadekin)
|
||||
if(SK)
|
||||
return SK
|
||||
|
||||
///Handles the shadekin's HUD updates.
|
||||
/datum/component/shadekin/proc/update_shadekin_hud()
|
||||
var/turf/T = get_turf(owner)
|
||||
if(owner.shadekin_display)
|
||||
var/l_icon = 0
|
||||
var/e_icon = 0
|
||||
|
||||
owner.shadekin_display.invisibility = INVISIBILITY_NONE
|
||||
if(T)
|
||||
var/brightness = T.get_lumcount() //Brightness in 0.0 to 1.0
|
||||
var/darkness = 1-brightness //Invert
|
||||
switch(darkness)
|
||||
if(0.80 to 1.00)
|
||||
l_icon = 0
|
||||
if(0.60 to 0.80)
|
||||
l_icon = 1
|
||||
if(0.40 to 0.60)
|
||||
l_icon = 2
|
||||
if(0.20 to 0.40)
|
||||
l_icon = 3
|
||||
if(0.00 to 0.20)
|
||||
l_icon = 4
|
||||
|
||||
switch(shadekin_get_energy())
|
||||
if(0 to 24)
|
||||
e_icon = 0
|
||||
if(25 to 49)
|
||||
e_icon = 1
|
||||
if(50 to 74)
|
||||
e_icon = 2
|
||||
if(75 to 99)
|
||||
e_icon = 3
|
||||
if(100 to INFINITY)
|
||||
e_icon = 4
|
||||
|
||||
owner.shadekin_display.icon_state = "shadekin-[l_icon]-[e_icon]"
|
||||
return
|
||||
|
||||
///For simplekin or those that have a pre-defined eye color
|
||||
/datum/component/shadekin/proc/set_eye_energy()
|
||||
if(!eye_color_influences_energy)
|
||||
return
|
||||
switch(eye_color)
|
||||
//Blue has constant, steady (slow) regen and ignores darkness.
|
||||
if(BLUE_EYES)
|
||||
set_light_and_darkness(0.75,0.75)
|
||||
nutrition_conversion_scaling = 0.5
|
||||
if(RED_EYES)
|
||||
set_light_and_darkness(-0.5,0.5)
|
||||
nutrition_conversion_scaling = 2
|
||||
if(PURPLE_EYES)
|
||||
set_light_and_darkness(-0.5,1)
|
||||
nutrition_conversion_scaling = 1
|
||||
if(YELLOW_EYES)
|
||||
set_light_and_darkness(-2,3)
|
||||
nutrition_conversion_scaling = 0.5
|
||||
if(GREEN_EYES)
|
||||
set_light_and_darkness(0.125,2)
|
||||
nutrition_conversion_scaling = 0.5
|
||||
if(ORANGE_EYES)
|
||||
set_light_and_darkness(-0.25,0.75)
|
||||
nutrition_conversion_scaling = 1.5
|
||||
|
||||
///Sets our eye color.
|
||||
/datum/component/shadekin/proc/set_shadekin_eyecolor()
|
||||
if(!ishuman(owner))
|
||||
return eye_color //revert to default if we're not a human
|
||||
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/eyecolor_rgb = rgb(H.r_eyes, H.g_eyes, H.b_eyes)
|
||||
|
||||
var/list/hsv_color = rgb2num(eyecolor_rgb, COLORSPACE_HSV)
|
||||
var/eyecolor_hue = hsv_color[1]
|
||||
var/eyecolor_sat = hsv_color[2]
|
||||
var/eyecolor_val = hsv_color[3]
|
||||
|
||||
//First, clamp the saturation/value to prevent black/grey/white eyes
|
||||
if(eyecolor_sat < 10)
|
||||
eyecolor_sat = 10
|
||||
if(eyecolor_val < 40)
|
||||
eyecolor_val = 40
|
||||
|
||||
eyecolor_rgb = rgb(eyecolor_hue, eyecolor_sat, eyecolor_val, space=COLORSPACE_HSV)
|
||||
|
||||
var/list/rgb_color = rgb2num(eyecolor_rgb)
|
||||
H.r_eyes = rgb_color[1]
|
||||
H.g_eyes = rgb_color[2]
|
||||
H.b_eyes = rgb_color[3]
|
||||
|
||||
//Now determine what color we fall into.
|
||||
switch(eyecolor_hue)
|
||||
if(0 to 20)
|
||||
eye_color = RED_EYES
|
||||
if(21 to 50)
|
||||
eye_color = ORANGE_EYES
|
||||
if(51 to 70)
|
||||
eye_color = YELLOW_EYES
|
||||
if(71 to 160)
|
||||
eye_color = GREEN_EYES
|
||||
if(161 to 260)
|
||||
eye_color = BLUE_EYES
|
||||
if(261 to 340)
|
||||
eye_color = PURPLE_EYES
|
||||
if(341 to 360)
|
||||
eye_color = RED_EYES
|
||||
return eye_color
|
||||
|
||||
///Adds the shadekin abilities to the owner.
|
||||
/datum/component/shadekin/proc/add_shadekin_abilities()
|
||||
if(!owner.ability_master || !istype(owner.ability_master, /obj/screen/movable/ability_master/shadekin))
|
||||
owner.ability_master = null
|
||||
owner.ability_master = new /obj/screen/movable/ability_master/shadekin(owner)
|
||||
for(var/datum/power/shadekin/P in shadekin_ability_datums)
|
||||
if(!(P.verbpath in owner.verbs))
|
||||
add_verb(owner, P.verbpath)
|
||||
owner.ability_master.add_shadekin_ability(
|
||||
object_given = owner,
|
||||
verb_given = P.verbpath,
|
||||
name_given = P.name,
|
||||
ability_icon_given = P.ability_icon_state,
|
||||
arguments = list()
|
||||
)
|
||||
|
||||
//wait, it's all light?
|
||||
///Allows setting the light and darkness gain.
|
||||
///@Args: light_gain, dark_gain
|
||||
/datum/component/shadekin/proc/set_light_and_darkness(light_gain, dark_gain)
|
||||
if(light_gain)
|
||||
energy_light = light_gain
|
||||
if(dark_gain)
|
||||
energy_dark = dark_gain
|
||||
|
||||
|
||||
//ENERGY HELPERS
|
||||
|
||||
/// Returns the shadekin's current energy.
|
||||
/// Returns max_energy if dark_energy_infinite is set to TRUE.
|
||||
/datum/component/shadekin/proc/shadekin_get_energy()
|
||||
if(dark_energy_infinite)
|
||||
return max_dark_energy
|
||||
return dark_energy
|
||||
|
||||
/// Returns the shadekin's maximum energy.
|
||||
/datum/component/shadekin/proc/shadekin_get_max_energy()
|
||||
return max_dark_energy
|
||||
|
||||
///Sets the shadekin's energy TO the given value.
|
||||
/datum/component/shadekin/proc/shadekin_set_energy(var/new_energy)
|
||||
if(!isnum(new_energy))
|
||||
return
|
||||
dark_energy = CLAMP(new_energy, 0, max_dark_energy)
|
||||
|
||||
///Sets the shadekin's maximum energy.
|
||||
/datum/component/shadekin/proc/shadekin_set_max_energy(var/new_max_energy)
|
||||
if(!isnum(new_max_energy))
|
||||
return //No.
|
||||
max_dark_energy = new_max_energy
|
||||
|
||||
///Adjusts the shadekin's energy by the given amount.
|
||||
/datum/component/shadekin/proc/shadekin_adjust_energy(var/amount)
|
||||
if(!isnum(amount))
|
||||
return //No
|
||||
shadekin_set_energy(dark_energy + amount)
|
||||
|
||||
/datum/component/shadekin/proc/handle_nutrition_conversion(dark_gains)
|
||||
if(!nutrition_energy_conversion)
|
||||
return
|
||||
if(shadekin_get_energy() == 100 && dark_gains > 0)
|
||||
owner.nutrition += dark_gains * 5 * nutrition_conversion_scaling
|
||||
else if(shadekin_get_energy() < 50 && owner.nutrition > 500)
|
||||
owner.nutrition -= nutrition_conversion_scaling * 50
|
||||
dark_gains += nutrition_conversion_scaling
|
||||
|
||||
/datum/component/shadekin/proc/attack_dephase(var/turf/T = null, atom/dephaser)
|
||||
// no assigned dephase-target, just use our own
|
||||
if(!T)
|
||||
T = get_turf(owner)
|
||||
|
||||
if(!in_phase || doing_phase)
|
||||
return FALSE
|
||||
|
||||
// make sure it's possible to be dephased (and we're in phase)
|
||||
if(!T || !T.CanPass(owner,T))
|
||||
return FALSE
|
||||
|
||||
|
||||
log_admin("[key_name_admin(owner)] was stunned out of phase at [T.x],[T.y],[T.z] by [dephaser.name], last touched by [dephaser.forensic_data?.get_lastprint()].")
|
||||
message_admins("[key_name_admin(owner)] was stunned out of phase at [T.x],[T.y],[T.z] by [dephaser.name], last touched by [dephaser.forensic_data?.get_lastprint()]. (<A href='byond://?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</a>)", 1)
|
||||
// start the dephase
|
||||
owner.phase_in(T, src)
|
||||
shadekin_adjust_energy(-20) // loss of energy for the interception
|
||||
// apply a little extra stun for good measure
|
||||
owner.Weaken(3)
|
||||
|
||||
/mob/living/carbon/human/is_incorporeal()
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(SK && SK.in_phase) //Shadekin
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
///Proc that takes in special considerations, such as 'no abilities in VR' and the such
|
||||
///Returns TRUE if we try to do something forbidden
|
||||
/datum/component/shadekin/proc/special_considerations(allow_vr)
|
||||
if(!allow_vr && istype(get_area(owner), /area/vr))
|
||||
to_chat(owner, span_danger("The VR systems cannot comprehend this power! This is useless to you!"))
|
||||
return TRUE
|
||||
return FALSE
|
||||
@@ -0,0 +1,68 @@
|
||||
//////////////////////
|
||||
/// CREATE SHADE ///
|
||||
//////////////////////
|
||||
/datum/power/shadekin/create_shade
|
||||
name = "Create Shade (25)"
|
||||
desc = "Create a field of darkness that follows you."
|
||||
verbpath = /mob/living/proc/create_shade
|
||||
ability_icon_state = "create_shade"
|
||||
|
||||
/mob/living/proc/create_shade()
|
||||
set name = "Create Shade (25)"
|
||||
set desc = "Create a field of darkness that follows you."
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/ability_cost = 25
|
||||
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!istype(SK))
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
else if(SK.special_considerations(TRUE))
|
||||
return FALSE
|
||||
else if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
else if(SK.shadekin_get_energy() < ability_cost)
|
||||
to_chat(src, span_warning("Not enough energy for that ability!"))
|
||||
return FALSE
|
||||
else if(SK.in_phase)
|
||||
to_chat(src, span_warning("You can't use that while phase shifted!"))
|
||||
return FALSE
|
||||
|
||||
playsound(src, 'sound/effects/bamf.ogg', 75, 1)
|
||||
|
||||
add_modifier(/datum/modifier/shadekin/create_shade,20 SECONDS)
|
||||
SK.shadekin_adjust_energy(-ability_cost)
|
||||
return TRUE
|
||||
|
||||
/datum/modifier/shadekin/create_shade
|
||||
name = "Shadekin Shadegen"
|
||||
desc = "Darkness envelops you."
|
||||
mob_overlay_state = ""
|
||||
|
||||
on_created_text = span_notice("You drag part of The Dark into realspace, enveloping yourself.")
|
||||
on_expired_text = span_warning("You lose your grasp on The Dark and realspace reasserts itself.")
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
var/mob/living/simple_mob/shadekin/my_kin
|
||||
|
||||
/datum/modifier/shadekin/create_shade/tick()
|
||||
var/datum/component/shadekin/SK = my_kin.get_shadekin_component()
|
||||
if(SK && SK.in_phase)
|
||||
expire()
|
||||
|
||||
/datum/modifier/shadekin/create_shade/on_applied()
|
||||
my_kin = holder
|
||||
holder.glow_toggle = TRUE
|
||||
holder.glow_range = 8
|
||||
holder.glow_intensity = -10
|
||||
holder.glow_color = "#FFFFFF"
|
||||
holder.set_light(8, -10, "#FFFFFF")
|
||||
|
||||
/datum/modifier/shadekin/create_shade/on_expire()
|
||||
holder.glow_toggle = initial(holder.glow_toggle)
|
||||
holder.glow_range = initial(holder.glow_range)
|
||||
holder.glow_intensity = initial(holder.glow_intensity)
|
||||
holder.glow_color = initial(holder.glow_color)
|
||||
holder.set_light(0)
|
||||
my_kin = null
|
||||
@@ -0,0 +1,207 @@
|
||||
/datum/power/shadekin/dark_maw
|
||||
name = "Dark Maw (20)"
|
||||
desc = "Create a trap to capture others, or steal people from phase"
|
||||
verbpath = /mob/living/proc/dark_maw
|
||||
ability_icon_state = "dark_maw_ic"
|
||||
|
||||
/mob/living/proc/dark_maw()
|
||||
set name = "Dark Maw (20)"
|
||||
set desc = "Create a trap to capture others, or steal people from phase"
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/ability_cost = 20
|
||||
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
return FALSE
|
||||
if(SK.special_considerations())
|
||||
return FALSE
|
||||
if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
|
||||
if(SK.shadekin_get_energy() < ability_cost)
|
||||
to_chat(src, span_warning("Not enough energy for that ability!"))
|
||||
return FALSE
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
to_chat(src, span_warning("You don't seem to be able to set a trap here!"))
|
||||
return FALSE
|
||||
|
||||
if(T.get_lumcount() >= 0.5)
|
||||
to_chat(src, span_warning("There is too much light here for your trap to last!"))
|
||||
return FALSE
|
||||
|
||||
if(do_after(src, 10))
|
||||
if(SK.in_phase)
|
||||
new /obj/effect/abstract/dark_maw(loc, src, TRUE)
|
||||
else
|
||||
new /obj/effect/abstract/dark_maw(loc, src)
|
||||
SK.shadekin_adjust_energy(-ability_cost)
|
||||
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/proc/clear_dark_maws()
|
||||
set name = "Dispel dark maws"
|
||||
set desc = "Dispel any active dark maws in place"
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
|
||||
for(var/obj/effect/abstract/dark_maw/dm in SK.active_dark_maws)
|
||||
dm.dispel()
|
||||
|
||||
/obj/effect/abstract/dark_maw
|
||||
var/mob/living/owner = null
|
||||
var/obj/belly/target = null
|
||||
var/has_signal = FALSE
|
||||
icon = 'icons/obj/Shadekin_powers.dmi'
|
||||
icon_state = "dark_maw_waiting"
|
||||
|
||||
/obj/effect/abstract/dark_maw/Initialize(mapload, var/mob/user, var/trigger_now = FALSE)
|
||||
. = ..()
|
||||
if(!isturf(loc))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
var/datum/component/shadekin/SK
|
||||
if(user && isliving(user))
|
||||
owner = user
|
||||
if(owner.vore_selected)
|
||||
target = owner.vore_selected
|
||||
RegisterSignal(owner, COMSIG_PARENT_QDELETING, PROC_REF(drop_everything_and_delete))
|
||||
has_signal = TRUE
|
||||
SK = owner.get_shadekin_component()
|
||||
|
||||
var/turf/T = loc
|
||||
if(T.get_lumcount() >= 0.5)
|
||||
visible_message(span_notice("A set of shadowy lines flickers away in the light."))
|
||||
icon_state = "dark_maw_used"
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
|
||||
var/mob/living/target_user = null
|
||||
for(var/mob/living/L in T)
|
||||
if(L != owner && !L.is_incorporeal())
|
||||
target_user = L
|
||||
break
|
||||
|
||||
if(istype(target_user))
|
||||
triggered_by(target_user, 1)
|
||||
// to trigger rebuild
|
||||
else if(trigger_now)
|
||||
icon_state = "dark_maw_used"
|
||||
flick("dark_maw_tr", src)
|
||||
visible_message(span_warning("A set of crystals suddenly springs from the ground and shadowy tendrils wrap around nothing before vanishing."))
|
||||
QDEL_IN(src, 3 SECONDS)
|
||||
else
|
||||
if(SK)
|
||||
SK.active_dark_maws += src
|
||||
flick("dark_maw", src)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
///Called when we get a signal that our owner is being qdel'd
|
||||
/obj/effect/abstract/dark_maw/proc/drop_everything_and_delete()
|
||||
SIGNAL_HANDLER
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/abstract/dark_maw/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(owner)
|
||||
if(has_signal)
|
||||
UnregisterSignal(owner, COMSIG_PARENT_QDELETING)
|
||||
var/datum/component/shadekin/SK = owner.get_shadekin_component()
|
||||
if(SK)
|
||||
SK.active_dark_maws -= src
|
||||
owner = null
|
||||
target = null
|
||||
return ..()
|
||||
|
||||
/obj/effect/abstract/dark_maw/Crossed(O)
|
||||
. = ..()
|
||||
if(!isliving(O))
|
||||
return
|
||||
if(icon_state != "dark_maw_waiting")
|
||||
return
|
||||
var/mob/living/L = O
|
||||
if(!L.is_incorporeal() && (!owner || L != owner))
|
||||
triggered_by(L)
|
||||
|
||||
/obj/effect/abstract/dark_maw/process()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T) || T.get_lumcount() >= 0.5)
|
||||
dispel()
|
||||
|
||||
/obj/effect/abstract/dark_maw/proc/dispel()
|
||||
if(icon_state == "dark_maw_waiting")
|
||||
visible_message(span_notice("A set of shadowy lines flickers away in the light."))
|
||||
else
|
||||
visible_message(span_notice("The crystals and shadowy tendrils dissipate with the light shone on it."))
|
||||
icon_state = "dark_maw_used"
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/abstract/dark_maw/proc/triggered_by(var/mob/living/L, var/triggered_instantly = 0)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
icon_state = "dark_maw_used"
|
||||
flick("dark_maw_tr", src)
|
||||
L.AdjustStunned(4)
|
||||
visible_message(span_warning("A set of crystals spring out of the ground and shadowy tendrils start wrapping around [L]."))
|
||||
if(owner && !triggered_instantly)
|
||||
to_chat(owner, span_warning("A dark maw you deployed has triggered!"))
|
||||
addtimer(CALLBACK(src, PROC_REF(do_trigger), L), 1 SECOND, TIMER_DELETE_ME)
|
||||
|
||||
/obj/effect/abstract/dark_maw/proc/do_trigger(var/mob/living/L)
|
||||
var/will_vore = 1
|
||||
|
||||
if(!owner || !(target in owner) || !L.devourable || !L.can_be_drop_prey || !owner.can_be_drop_pred || !L.phase_vore)
|
||||
will_vore = 0
|
||||
|
||||
if(!src || src.gc_destroyed)
|
||||
//We got deleted probably, do nothing more
|
||||
return
|
||||
|
||||
if(L.loc != get_turf(src))
|
||||
visible_message(span_notice("The shadowy tendrils fail to catch anything and dissipate."))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(will_vore)
|
||||
visible_message(span_warning("The shadowy tendrils grab around [L] and drag them into the floor, leaving nothing behind."))
|
||||
L.forceMove(target)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
var/obj/effect/energy_net/dark/net = new /obj/effect/energy_net/dark(get_turf(src))
|
||||
if(net.buckle_mob(L))
|
||||
visible_message(span_warning("The shadowy tendrils wrap around [L] and traps them in a net of dark energy."))
|
||||
else
|
||||
visible_message(span_notice("The shadowy tendrils wrap around [L] and then dissipate, leaving them in place."))
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/energy_net/dark
|
||||
name = "dark net"
|
||||
desc = "It's a net made of dark energy."
|
||||
icon = 'icons/obj/Shadekin_powers.dmi'
|
||||
icon_state = "dark_net"
|
||||
|
||||
escape_time = 30 SECONDS
|
||||
|
||||
/obj/effect/energy_net/dark/user_unbuckle_mob(mob/living/buckled_mob, mob/user)
|
||||
if(isliving(user))
|
||||
var/mob/living/unbuckler = user
|
||||
var/datum/component/shadekin/SK = unbuckler.get_shadekin_component()
|
||||
if(SK)
|
||||
visible_message(span_danger("[user] dissipates \the [src] with a touch!"))
|
||||
unbuckle_mob(buckled_mob)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/effect/energy_net/dark/process()
|
||||
. = ..()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T) || T.get_lumcount() >= 0.6)
|
||||
visible_message(span_notice("The tangle of dark tendrils fades away in the light."))
|
||||
qdel(src)
|
||||
@@ -0,0 +1,107 @@
|
||||
//Non-Canon on Virgo. Used downstream.
|
||||
|
||||
/datum/power/shadekin/dark_respite
|
||||
name = "Dark Respite (Only in Dark)"
|
||||
desc = "Focus yourself on healing any injuries sustained."
|
||||
verbpath = /mob/living/proc/dark_respite
|
||||
ability_icon_state = "dark_respite"
|
||||
|
||||
/mob/living/proc/dark_respite()
|
||||
set name = "Dark Respite (Only in Dark)"
|
||||
set desc = "Focus yourself on healing any injuries sustained."
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
return FALSE
|
||||
if(SK.special_considerations())
|
||||
return FALSE
|
||||
if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
|
||||
if(!istype(get_area(src), /area/shadekin))
|
||||
to_chat(src, span_warning("Can only trigger Dark Respite in the Dark!"))
|
||||
return FALSE
|
||||
|
||||
if(SK.in_dark_respite)
|
||||
to_chat(src, span_warning("You can't use that so soon after an emergency warp!"))
|
||||
return FALSE
|
||||
|
||||
if(has_modifier_of_type(/datum/modifier/dark_respite) && !SK.manual_respite)
|
||||
to_chat(src, span_warning("You cannot manually end a Dark Respite triggered by an emergency warp!"))
|
||||
|
||||
if(SK.in_phase)
|
||||
to_chat(src, span_warning("You can't use that while phase shifted!"))
|
||||
return FALSE
|
||||
|
||||
if(has_modifier_of_type(/datum/modifier/dark_respite))
|
||||
to_chat(src, span_notice("You stop focusing the Dark on healing yourself."))
|
||||
SK.manual_respite = FALSE
|
||||
remove_a_modifier_of_type(/datum/modifier/dark_respite)
|
||||
return TRUE
|
||||
to_chat(src, span_notice("You start focusing the Dark on healing yourself. (Leave the dark or trigger the ability again to end this.)"))
|
||||
SK.manual_respite = TRUE
|
||||
add_modifier(/datum/modifier/dark_respite)
|
||||
return TRUE
|
||||
|
||||
/datum/modifier/dark_respite
|
||||
name = "Dark Respite"
|
||||
pain_immunity = 1
|
||||
var/datum/component/shadekin/SK
|
||||
|
||||
// Override this for special effects when it gets added to the mob.
|
||||
/datum/modifier/dark_respite/on_applied()
|
||||
SK = holder.get_shadekin_component()
|
||||
if(!SK)
|
||||
expire()
|
||||
return
|
||||
|
||||
/datum/modifier/dark_respite/tick()
|
||||
if(!SK)
|
||||
expire()
|
||||
return
|
||||
var/mob/living/carbon/human/H
|
||||
if(istype(holder, /mob/living/carbon/human))
|
||||
H = holder
|
||||
if(H.nutrition)
|
||||
H.add_chemical_effect(CE_BLOODRESTORE, 5)
|
||||
|
||||
if(istype(get_area(H), /area/shadekin))
|
||||
pain_immunity = TRUE
|
||||
//Very good healing, but only in the Dark.
|
||||
holder.adjustFireLoss((-0.25))
|
||||
holder.adjustBruteLoss((-0.25))
|
||||
holder.adjustToxLoss((-0.25))
|
||||
holder.heal_organ_damage(3, 0)
|
||||
if(H)
|
||||
H.add_chemical_effect(CE_ANTIBIOTIC, ANTIBIO_SUPER)
|
||||
for(var/obj/item/organ/I in H.internal_organs)
|
||||
if(I.robotic >= ORGAN_ROBOT)
|
||||
continue
|
||||
if(I.damage > 0)
|
||||
I.damage = max(I.damage - 0.25, 0)
|
||||
if(I.damage <= 5 && I.organ_tag == O_EYES)
|
||||
H.sdisabilities &= ~BLIND
|
||||
for(var/obj/item/organ/external/O in H.organs)
|
||||
if(O.status & ORGAN_BROKEN)
|
||||
O.mend_fracture() //Only works if the bone won't rebreak, as usual
|
||||
for(var/datum/wound/W in O.wounds)
|
||||
if(W.bleeding())
|
||||
W.damage = max(W.damage - 3, 0)
|
||||
if(W.damage <= 0)
|
||||
O.wounds -= W
|
||||
if(W.internal)
|
||||
W.damage = max(W.damage - 3, 0)
|
||||
if(W.damage <= 0)
|
||||
O.wounds -= W
|
||||
else
|
||||
if(SK.manual_respite)
|
||||
to_chat(holder, span_notice("As you leave the Dark, you stop focusing the Dark on healing yourself."))
|
||||
SK.manual_respite = FALSE
|
||||
expire()
|
||||
if(pain_immunity)
|
||||
pain_immunity = 0
|
||||
|
||||
/datum/modifier/dark_respite/on_expire()
|
||||
SK = null
|
||||
+35
-67
@@ -1,11 +1,8 @@
|
||||
// Kind of like a combination of all the teleporter stuff all in one package.
|
||||
// And without the power requirements or accuracy loss,
|
||||
// though it requires a shadekin to open the minion portals.
|
||||
|
||||
// Also yes this needs to be outside of modular chomp because there are variables that have to be map overriden.
|
||||
GLOBAL_LIST_BOILERPLATE(all_darkportal_hubs, /obj/structure/dark_portal/hub)
|
||||
GLOBAL_LIST_BOILERPLATE(all_darkportal_minions, /obj/structure/dark_portal/minion)
|
||||
/obj/structure/dark_portal
|
||||
name = "Dark portal"
|
||||
icon = 'modular_chomp/icons/obj/shadekin_portal.dmi'
|
||||
icon = 'icons/obj/shadekin_portal.dmi'
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
var/locked = null
|
||||
@@ -16,51 +13,15 @@
|
||||
/obj/structure/dark_portal/proc/close_portal()
|
||||
return
|
||||
|
||||
/obj/structure/dark_portal/proc/is_shadekin(mob/shade_maybe)
|
||||
if(istype(shade_maybe, /mob/living/simple_mob/shadekin))
|
||||
return TRUE
|
||||
else if(istype(shade_maybe, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/carbonkin_maybe = shade_maybe
|
||||
if(carbonkin_maybe.get_species() == SPECIES_SHADEKIN)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/structure/dark_portal/proc/get_ability_flags(mob/shade_maybe)
|
||||
if(istype(shade_maybe, /mob/living/simple_mob/shadekin))
|
||||
var/mob/living/simple_mob/shadekin/shadekin = shade_maybe
|
||||
return shadekin.ability_flags
|
||||
else if(istype(shade_maybe, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/carbonkin_maybe = shade_maybe
|
||||
return carbonkin_maybe.ability_flags
|
||||
return 0
|
||||
|
||||
/obj/structure/dark_portal/proc/get_shadekin_energy(mob/shade_maybe)
|
||||
if(istype(shade_maybe, /mob/living/simple_mob/shadekin))
|
||||
var/mob/living/simple_mob/shadekin/shadekin = shade_maybe
|
||||
return shadekin.comp.dark_energy
|
||||
else if(istype(shade_maybe, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/carbonkin_maybe = shade_maybe
|
||||
return carbonkin_maybe.shadekin_get_energy()
|
||||
return 0
|
||||
|
||||
/obj/structure/dark_portal/proc/adjust_shadekin_energy(mob/shade_maybe, amount)
|
||||
if(istype(shade_maybe, /mob/living/simple_mob/shadekin))
|
||||
var/mob/living/simple_mob/shadekin/shadekin = shade_maybe
|
||||
shadekin.comp.dark_energy += amount
|
||||
return
|
||||
else if(istype(shade_maybe, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/carbonkin_maybe = shade_maybe
|
||||
return carbonkin_maybe.shadekin_adjust_energy(amount)
|
||||
return 0
|
||||
|
||||
/obj/structure/dark_portal/proc/teleport(atom/movable/M as mob|obj)
|
||||
if(!locked)
|
||||
return
|
||||
if(is_shadekin(M))
|
||||
if(get_ability_flags(M) & AB_DARK_RESPITE)
|
||||
if(isliving(M))
|
||||
var/mob/living/to_check = M
|
||||
var/datum/component/shadekin/SK = to_check.GetComponent(/datum/component/shadekin)
|
||||
if(SK && SK.in_dark_respite)
|
||||
to_chat(M, span_warning("You can't go through this portal so soon after an emergency warp!"))
|
||||
var/mob/living/user = M
|
||||
user.Stun(10)
|
||||
to_check.Stun(10)
|
||||
return
|
||||
|
||||
do_teleport(M, locked, precision, local = FALSE, bohsafe = TRUE)
|
||||
@@ -77,8 +38,6 @@
|
||||
var/list/destination_station_areas // Override this in map files!
|
||||
var/list/destination_wilderness_areas // Override this in map files!
|
||||
|
||||
GLOBAL_LIST_BOILERPLATE(all_darkportal_hubs, /obj/structure/dark_portal/hub)
|
||||
|
||||
/obj/structure/dark_portal/hub/Initialize(mapload)
|
||||
. = ..()
|
||||
locked = src
|
||||
@@ -93,12 +52,15 @@ GLOBAL_LIST_BOILERPLATE(all_darkportal_hubs, /obj/structure/dark_portal/hub)
|
||||
locked_name = src.name
|
||||
precision = 1
|
||||
|
||||
/obj/structure/dark_portal/hub/attack_hand(mob/user)
|
||||
if(is_shadekin(user))
|
||||
if(get_ability_flags(user) & AB_DARK_RESPITE)
|
||||
/obj/structure/dark_portal/hub/attack_hand(mob/living/user)
|
||||
if(!isliving(user))
|
||||
return
|
||||
var/datum/component/shadekin/SK = user.GetComponent(/datum/component/shadekin)
|
||||
if(SK)
|
||||
if(SK.in_dark_respite)
|
||||
to_chat(user, span_warning("You can't use this so soon after an emergency warp!"))
|
||||
return
|
||||
if(get_ability_flags(user) & AB_PHASE_SHIFTED)
|
||||
if(SK.in_phase)
|
||||
to_chat(user, span_warning("You can't use this while phase shifted!"))
|
||||
return
|
||||
if(locked != src)
|
||||
@@ -172,20 +134,21 @@ GLOBAL_LIST_BOILERPLATE(all_darkportal_hubs, /obj/structure/dark_portal/hub)
|
||||
/obj/structure/dark_portal/minion
|
||||
icon_state = "minion0"
|
||||
|
||||
GLOBAL_LIST_BOILERPLATE(all_darkportal_minions, /obj/structure/dark_portal/minion)
|
||||
|
||||
/obj/structure/dark_portal/minion/close_portal()
|
||||
locked = null
|
||||
locked_name = ""
|
||||
precision = 1
|
||||
icon_state = "minion0"
|
||||
|
||||
/obj/structure/dark_portal/minion/attack_hand(mob/user)
|
||||
if(is_shadekin(user))
|
||||
if(get_ability_flags(user) & AB_DARK_RESPITE)
|
||||
/obj/structure/dark_portal/minion/attack_hand(mob/living/user)
|
||||
if(!isliving(user))
|
||||
return
|
||||
var/datum/component/shadekin/SK = user.GetComponent(/datum/component/shadekin)
|
||||
if(SK)
|
||||
if(SK.in_dark_respite)
|
||||
to_chat(user, span_warning("You can't use this so soon after an emergency warp!"))
|
||||
return FALSE
|
||||
if(get_ability_flags(user) & AB_PHASE_SHIFTED)
|
||||
if(SK.in_phase)
|
||||
to_chat(user, span_warning("You can't use this while phase shifted!"))
|
||||
return FALSE
|
||||
if(icon_state == "minion1")
|
||||
@@ -195,21 +158,19 @@ GLOBAL_LIST_BOILERPLATE(all_darkportal_minions, /obj/structure/dark_portal/minio
|
||||
if(confirm == "Yes")
|
||||
close_portal()
|
||||
return
|
||||
if(get_shadekin_energy(user) < 10)
|
||||
if(SK.shadekin_get_energy() < 10)
|
||||
to_chat(user, span_warning("Not enough energy to open up the portal! (10 required)"))
|
||||
return
|
||||
if(!LAZYLEN(GLOB.all_darkportal_hubs))
|
||||
to_chat(user, span_warning("No hub portals exist!"))
|
||||
return
|
||||
if(LAZYLEN(GLOB.all_darkportal_hubs) == 1)
|
||||
adjust_shadekin_energy(user, -10)
|
||||
SK.shadekin_adjust_energy(user, -10)
|
||||
var/obj/structure/dark_portal/target = GLOB.all_darkportal_hubs[1]
|
||||
locked = target
|
||||
locked_name = target.name
|
||||
icon_state = "minion1"
|
||||
spawn(3000)
|
||||
if(locked == target)
|
||||
close_portal()
|
||||
addtimer(CALLBACK(src, PROC_REF(check_to_close),target), 5 MINUTES, TIMER_DELETE_ME)
|
||||
return
|
||||
var/list/L = list()
|
||||
for(var/obj/structure/dark_portal/hub/H in GLOB.all_darkportal_hubs)
|
||||
@@ -220,9 +181,8 @@ GLOBAL_LIST_BOILERPLATE(all_darkportal_minions, /obj/structure/dark_portal/minio
|
||||
locked = L[desc]
|
||||
locked_name = desc
|
||||
icon_state = "minion1"
|
||||
spawn(3000)
|
||||
if(locked == L[desc])
|
||||
close_portal()
|
||||
addtimer(CALLBACK(src, PROC_REF(check_to_close_desc),locked), 5 MINUTES, TIMER_DELETE_ME)
|
||||
return
|
||||
else if(!istype(user, /mob/living))
|
||||
return
|
||||
else if(icon_state == "minion0")
|
||||
@@ -230,6 +190,14 @@ GLOBAL_LIST_BOILERPLATE(all_darkportal_minions, /obj/structure/dark_portal/minio
|
||||
else
|
||||
to_chat(user, span_notice("You touch the portal, your hand able to pass through without harm."))
|
||||
|
||||
/obj/structure/dark_portal/proc/check_to_close(var/obj/structure/dark_portal/target)
|
||||
if(locked == target)
|
||||
close_portal()
|
||||
|
||||
/obj/structure/dark_portal/proc/check_to_close_desc(var/old_locked)
|
||||
if(locked == old_locked)
|
||||
close_portal()
|
||||
|
||||
/obj/structure/dark_portal/minion/Bumped(M as mob|obj)
|
||||
spawn()
|
||||
if(icon_state == "minion1")
|
||||
@@ -0,0 +1,93 @@
|
||||
//Non-Canon on Virgo. Used downstream.
|
||||
|
||||
/datum/power/shadekin/dark_tunneling
|
||||
name = "Dark Tunneling (100) (Once)"
|
||||
desc = "Make a passage to the dark."
|
||||
verbpath = /mob/living/proc/dark_tunneling
|
||||
ability_icon_state = "minion0"
|
||||
|
||||
/mob/living/proc/dark_tunneling()
|
||||
set name = "Dark Tunneling (100) (Once)"
|
||||
set desc = "Make a passage to the dark."
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/template_id = "dark_portal"
|
||||
var/datum/map_template/shelter/template
|
||||
|
||||
var/ability_cost = 100
|
||||
var/tunnel_time = 60 SECONDS
|
||||
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
return FALSE
|
||||
if(SK.special_considerations())
|
||||
return FALSE
|
||||
if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
|
||||
if(SK.in_phase)
|
||||
to_chat(src, span_warning("You can't use that while phase shifted!"))
|
||||
return FALSE
|
||||
|
||||
if(SK.created_dark_tunnel)
|
||||
to_chat(src, span_warning("You have already made a tunnel to the Dark!"))
|
||||
return FALSE
|
||||
|
||||
if(!template)
|
||||
template = SSmapping.shelter_templates[template_id]
|
||||
if(!template)
|
||||
throw EXCEPTION("Shelter template ([template_id]) not found!")
|
||||
return FALSE
|
||||
|
||||
var/turf/deploy_location = get_turf(src)
|
||||
var/status = template.check_deploy(deploy_location)
|
||||
|
||||
switch(status)
|
||||
//Not allowed due to /area technical reasons
|
||||
if(SHELTER_DEPLOY_BAD_AREA)
|
||||
to_chat(src, span_warning("A tunnel to the Dark will not function in this area."))
|
||||
|
||||
//Anchored objects or no space
|
||||
if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS)
|
||||
var/width = template.width
|
||||
var/height = template.height
|
||||
to_chat(src, span_warning("There is not enough open area for a tunnel to the Dark to form! You need to clear a [width]x[height] area!"))
|
||||
|
||||
if(status != SHELTER_DEPLOY_ALLOWED)
|
||||
return FALSE
|
||||
|
||||
var/turf/T = deploy_location
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.attach(T)
|
||||
smoke.set_up(10, 0, T)
|
||||
smoke.start()
|
||||
|
||||
src.visible_message(span_notice("[src] begins pulling dark energies around themselves."))
|
||||
if(do_after(src, tunnel_time))
|
||||
if(SK.created_dark_tunnel) //check again because the user may have queued this up multiple times.
|
||||
to_chat(src, span_warning("You have already made a tunnel to the Dark!"))
|
||||
return FALSE
|
||||
playsound(src, 'sound/effects/phasein.ogg', 100, 1)
|
||||
src.visible_message(span_notice("[src] finishes pulling dark energies around themselves, creating a portal."))
|
||||
|
||||
log_and_message_admins("[key_name_admin(src)] created a tunnel to the dark at [get_area(T)]!")
|
||||
template.annihilate_plants(deploy_location)
|
||||
template.load(deploy_location, centered = TRUE)
|
||||
template.update_lighting(deploy_location)
|
||||
SK.created_dark_tunnel = TRUE
|
||||
SK.shadekin_adjust_energy(-(ability_cost - 10)) //Leaving enough energy to actually activate the portal
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/map_template/shelter/dark_portal
|
||||
name = "Dark Portal"
|
||||
shelter_id = "dark_portal"
|
||||
description = "A portal to a section of the Dark"
|
||||
mappath = "maps/submaps/shelters/dark_portal.dmm"
|
||||
|
||||
/datum/map_template/shelter/dark_portal/New()
|
||||
. = ..()
|
||||
blacklisted_turfs = typecacheof(list(/turf/unsimulated))
|
||||
GLOB.blacklisted_areas = typecacheof(list(/area/centcom, /area/shadekin))
|
||||
@@ -27,6 +27,8 @@
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
return FALSE
|
||||
if(SK.special_considerations())
|
||||
return FALSE
|
||||
if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
@@ -50,10 +52,24 @@
|
||||
darkness = 1-brightness //Invert
|
||||
|
||||
var/watcher = 0
|
||||
for(var/mob/living/carbon/human/watchers in oview(7,src )) // If we can see them...
|
||||
if(watchers in oviewers(7,src)) // And they can see us...
|
||||
if(!(watchers.stat) && !isbelly(watchers.loc) && !istype(watchers.loc, /obj/item/holder)) // And they are alive and not being held by someone...
|
||||
watcher++ // They are watching us!
|
||||
for(var/mob/living/thing in orange(7, src)) //Fun fact, doing two typed loops is faster than doing one untyped loop. Check it with Tracy!
|
||||
if(istype(thing, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/watchers = thing
|
||||
if(watchers in oviewers(7,src))
|
||||
var/datum/component/shadekin/watcher_SK = watchers.get_shadekin_component()
|
||||
if(!watcher_SK && !(watchers.stat) && !isbelly(watchers.loc) && !istype(watchers.loc, /obj/item/holder)) // And they are alive and not being held by someone...
|
||||
watcher++ //They are watching us!
|
||||
if(istype(thing, /mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/watchers = thing
|
||||
var/datum/component/shadekin/watcher_SK = watchers.get_shadekin_component() //you never know, man.
|
||||
if(watchers in oviewers(7,src))
|
||||
if(!watcher_SK && !watchers.stat && !isbelly(watchers.loc))
|
||||
watcher++ //The robot is watching us!
|
||||
if(SK.camera_counts_as_watcher)
|
||||
for(var/obj/machinery/camera/watchers in orange(7, src))
|
||||
if(watchers.can_use())
|
||||
if(src in watchers.can_see())
|
||||
watcher++ //The camera is watching us!
|
||||
|
||||
ability_cost = CLAMP(ability_cost/(0.01+darkness*2),50, 80)//This allows for 1 watcher in full light
|
||||
if(watcher>0)
|
||||
@@ -163,6 +179,8 @@
|
||||
held_lights.update_brightness()
|
||||
|
||||
SK.doing_phase = FALSE
|
||||
if(SK.flicker_time < 5 || SK.flicker_distance < 5 || SK.flicker_break_chance < 5)
|
||||
Stun(SK.calculate_stun())
|
||||
if(!SK.flicker_time)
|
||||
return //Early return. No time, no flickering.
|
||||
//Affect nearby lights
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
//////////////////////////
|
||||
/// REGENERATE OTHER ///
|
||||
//////////////////////////
|
||||
/datum/power/shadekin/regenerate_other
|
||||
name = "Regenerate Other (50)"
|
||||
desc = "Spend energy to heal physical wounds in another creature."
|
||||
verbpath = /mob/living/proc/regenerate_other
|
||||
ability_icon_state = "shadekin_regen"
|
||||
|
||||
/mob/living/proc/regenerate_other()
|
||||
set name = "Regenerate Other (50)"
|
||||
set desc = "Spend energy to heal physical wounds in another creature."
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/ability_cost = 50
|
||||
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
return FALSE
|
||||
if(SK.special_considerations())
|
||||
return FALSE
|
||||
if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
else if(SK.shadekin_get_energy() < ability_cost)
|
||||
to_chat(src, span_warning("Not enough energy for that ability!"))
|
||||
return FALSE
|
||||
else if(SK.in_phase)
|
||||
to_chat(src, span_warning("You can't use that while phase shifted!"))
|
||||
return FALSE
|
||||
|
||||
var/list/viewed = oview(1)
|
||||
var/list/targets = list()
|
||||
for(var/mob/living/L in viewed)
|
||||
targets += L
|
||||
if(!targets.len)
|
||||
to_chat(src,span_warning("Nobody nearby to mend!"))
|
||||
return FALSE
|
||||
|
||||
var/mob/living/target = tgui_input_list(src,"Pick someone to mend:","Mend Other", targets)
|
||||
if(!target)
|
||||
return FALSE
|
||||
|
||||
target.add_modifier(/datum/modifier/shadekin/heal_boop,1 MINUTE)
|
||||
playsound(src, 'sound/effects/EMPulse.ogg', 75, 1)
|
||||
SK.shadekin_adjust_energy(-ability_cost)
|
||||
visible_message(span_notice("\The [src] gently places a hand on \the [target]..."))
|
||||
face_atom(target)
|
||||
return TRUE
|
||||
|
||||
/datum/modifier/shadekin/heal_boop
|
||||
name = "Shadekin Regen"
|
||||
desc = "You feel serene and well rested."
|
||||
mob_overlay_state = "green_sparkles"
|
||||
|
||||
on_created_text = span_notice("Sparkles begin to appear around you, and all your ills seem to fade away.")
|
||||
on_expired_text = span_notice("The sparkles have faded, although you feel much healthier than before.")
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
|
||||
/datum/modifier/shadekin/heal_boop/tick()
|
||||
if(!holder.getBruteLoss() && !holder.getFireLoss() && !holder.getToxLoss() && !holder.getOxyLoss() && !holder.getCloneLoss()) // No point existing if the spell can't heal.
|
||||
expire()
|
||||
return
|
||||
holder.adjustBruteLoss(-2)
|
||||
holder.adjustFireLoss(-2)
|
||||
holder.adjustToxLoss(-2)
|
||||
holder.adjustOxyLoss(-2)
|
||||
holder.adjustCloneLoss(-2)
|
||||
@@ -0,0 +1,281 @@
|
||||
//See comp_helpers.dm for helper procs.
|
||||
/datum/component/shadekin
|
||||
VAR_PRIVATE/mob/living/owner
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE
|
||||
|
||||
//Energy Vars
|
||||
///How much energy we have RIGHT NOW
|
||||
var/dark_energy = 100
|
||||
///How much energy we can have
|
||||
var/max_dark_energy = 100
|
||||
///Always be at our max_dark_energy
|
||||
var/dark_energy_infinite = FALSE
|
||||
///How much energy we generate in the dark
|
||||
var/energy_dark = 0.75
|
||||
///How much energy we generate in the light
|
||||
var/energy_light = 0.25
|
||||
///If we care about eye color when it comes to factoring in energy
|
||||
var/eye_color_influences_energy = TRUE
|
||||
///Energy gain from nutrition
|
||||
var/nutrition_conversion_scaling = 0.5
|
||||
///If we convert nutrition to energy
|
||||
var/nutrition_energy_conversion = FALSE
|
||||
|
||||
//Phase Vars
|
||||
///Are we currently in a phase transition?
|
||||
var/doing_phase = FALSE
|
||||
///Are we currently phased?
|
||||
var/in_phase = FALSE
|
||||
///Chance to break lights on phase-in
|
||||
var/flicker_break_chance = 0
|
||||
///Color that lights will flicker to on phase-in. Off by default.
|
||||
var/flicker_color
|
||||
///Time that lights will flicker on phase-in. Default is 10 times.
|
||||
var/flicker_time = 10
|
||||
///Range that we flicker lights. Default is 10.
|
||||
var/flicker_distance = 10
|
||||
///If we can get the 'phase debuff' applied to us. (No using guns, dropping things in hands, etc).
|
||||
var/normal_phase = TRUE
|
||||
///If we drop items on phase.
|
||||
var/drop_items_on_phase = FALSE
|
||||
///If cameras count as watchers for us
|
||||
var/camera_counts_as_watcher = FALSE
|
||||
|
||||
//Dark Respite Vars (Unused on Virgo)
|
||||
///If we are in dark respite or not
|
||||
var/in_dark_respite = FALSE
|
||||
var/manual_respite = FALSE
|
||||
var/respite_activating = FALSE
|
||||
|
||||
//Dark Tunneling Vars (Unused on Virgo)
|
||||
///If we have already made a dark tunnel
|
||||
var/created_dark_tunnel = FALSE
|
||||
|
||||
//Dark Maw Vars (Unused on Virgo)
|
||||
///Our current active dark maws
|
||||
var/list/active_dark_maws = list()
|
||||
|
||||
//Ability Vars
|
||||
///The innate abilities we start with
|
||||
var/list/shadekin_abilities = list(/datum/power/shadekin/phase_shift,
|
||||
/datum/power/shadekin/regenerate_other,
|
||||
/datum/power/shadekin/create_shade)
|
||||
///Datum holder. Largely ignore this.
|
||||
var/list/shadekin_ability_datums = list()
|
||||
|
||||
//Misc Vars
|
||||
///Eyecolor
|
||||
var/eye_color = BLUE_EYES
|
||||
///For downstream. Enables some extra verbs. Causes things to drop in hand when you phase.
|
||||
var/extended_kin = FALSE
|
||||
|
||||
/datum/component/shadekin/phase_only
|
||||
shadekin_abilities = list(/datum/power/shadekin/phase_shift)
|
||||
|
||||
/datum/component/shadekin/full
|
||||
shadekin_abilities = list(/datum/power/shadekin/phase_shift,
|
||||
/datum/power/shadekin/regenerate_other,
|
||||
/datum/power/shadekin/create_shade,
|
||||
/datum/power/shadekin/dark_maw,
|
||||
/datum/power/shadekin/dark_respite,
|
||||
/datum/power/shadekin/dark_tunneling)
|
||||
extended_kin = TRUE
|
||||
drop_items_on_phase = TRUE
|
||||
camera_counts_as_watcher = TRUE
|
||||
|
||||
/datum/component/shadekin/full/rakshasa
|
||||
flicker_time = 0 //Rakshasa don't flicker lights when they phase in.
|
||||
dark_energy_infinite = TRUE
|
||||
normal_phase = FALSE
|
||||
|
||||
/datum/component/shadekin/Initialize()
|
||||
//normal component bs
|
||||
if(!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
owner = parent
|
||||
add_shadekin_abilities(owner)
|
||||
if(ishuman(owner))
|
||||
RegisterSignal(owner, COMSIG_SHADEKIN_COMPONENT, PROC_REF(handle_comp)) //Happens every species tick.
|
||||
else
|
||||
RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(handle_comp)) //Happens every life tick (mobs)
|
||||
|
||||
//generates powers and then adds them
|
||||
for(var/power in shadekin_abilities)
|
||||
var/datum/power/shadekin/SKP = new power(src)
|
||||
shadekin_ability_datums.Add(SKP)
|
||||
add_shadekin_abilities()
|
||||
|
||||
handle_comp() //First hit is free!
|
||||
|
||||
//decides what 'eye color' we are and how much energy we should get
|
||||
set_shadekin_eyecolor() //Gets what eye color we are.
|
||||
set_eye_energy() //Sets the energy values based on our eye color.
|
||||
|
||||
//Misc stuff we need to do
|
||||
if(extended_kin)
|
||||
add_verb(owner, /mob/living/proc/nutrition_conversion_toggle)
|
||||
add_verb(owner, /mob/living/proc/flicker_adjustment)
|
||||
|
||||
/datum/component/shadekin/Destroy(force)
|
||||
if(ishuman(owner))
|
||||
UnregisterSignal(owner, COMSIG_SHADEKIN_COMPONENT)
|
||||
else
|
||||
UnregisterSignal(owner, COMSIG_LIVING_LIFE)
|
||||
if(extended_kin)
|
||||
remove_verb(owner, /mob/living/proc/nutrition_conversion_toggle)
|
||||
remove_verb(owner, /mob/living/proc/flicker_adjustment)
|
||||
for(var/datum/power in shadekin_ability_datums)
|
||||
qdel(power)
|
||||
for(var/obj/effect/abstract/dark_maw/dm as anything in active_dark_maws) //if the component gets destroyed so does your precious maws
|
||||
if(!QDELETED(dm))
|
||||
qdel(dm)
|
||||
active_dark_maws.Cut()
|
||||
shadekin_abilities.Cut()
|
||||
shadekin_ability_datums.Cut()
|
||||
owner = null
|
||||
. = ..()
|
||||
|
||||
/datum/component/shadekin/proc/recalc_values()
|
||||
set_shadekin_eyecolor() //Gets what eye color we are.
|
||||
set_eye_energy() //Sets the energy values based on our eye color.
|
||||
|
||||
///Handles the component running.
|
||||
/datum/component/shadekin/proc/handle_comp()
|
||||
SIGNAL_HANDLER
|
||||
if(QDELETED(parent))
|
||||
return
|
||||
if(owner.stat == DEAD) //dead, don't process.
|
||||
return
|
||||
handle_shade()
|
||||
|
||||
///Handles the shadekin's energy gain and loss.
|
||||
/datum/component/shadekin/proc/handle_shade()
|
||||
//Shifted kin don't gain/lose energy (and save time if we're at the cap)
|
||||
var/darkness = 1
|
||||
var/dark_gains = 0
|
||||
|
||||
var/turf/T = get_turf(owner)
|
||||
if(!T)
|
||||
dark_gains = 0
|
||||
return
|
||||
|
||||
var/brightness = T.get_lumcount() //Brightness in 0.0 to 1.0
|
||||
darkness = 1-brightness //Invert
|
||||
var/is_dark = (darkness >= 0.5)
|
||||
|
||||
if(in_phase)
|
||||
dark_gains = 0
|
||||
else
|
||||
//Heal (very) slowly in good darkness
|
||||
if(is_dark)
|
||||
//The below sends a DB query...This needs to be fixed before this can be enabled as we're now dealing with signal handlers.
|
||||
//Reenable once that mess is taken care of.
|
||||
owner.adjustFireLoss((-0.10)*darkness)
|
||||
owner.adjustBruteLoss((-0.10)*darkness)
|
||||
owner.adjustToxLoss((-0.10)*darkness)
|
||||
//energy_dark and energy_light are set by the shadekin eye traits.
|
||||
//These are balanced around their playstyles and 2 planned new aggressive abilities
|
||||
dark_gains = energy_dark
|
||||
else
|
||||
dark_gains = energy_light
|
||||
|
||||
handle_nutrition_conversion(dark_gains)
|
||||
|
||||
shadekin_adjust_energy(dark_gains)
|
||||
|
||||
//Update huds
|
||||
update_shadekin_hud()
|
||||
|
||||
/datum/component/shadekin/proc/calculate_stun()
|
||||
var/stun_time = 3
|
||||
if(flicker_time > 0)
|
||||
stun_time -= min(flicker_time / 5, 1)
|
||||
if(flicker_distance > 0)
|
||||
stun_time -= min(flicker_distance / 5, 1)
|
||||
if(flicker_break_chance > 0)
|
||||
stun_time -= min(flicker_break_chance / 5, 1)
|
||||
return stun_time
|
||||
|
||||
/datum/component/shadekin/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ShadekinConfig", "Shadekin Config")
|
||||
ui.open()
|
||||
|
||||
/datum/component/shadekin/tgui_data(mob/user)
|
||||
var/data = list(
|
||||
"stun_time" = calculate_stun(),
|
||||
"flicker_time" = flicker_time,
|
||||
"flicker_color" = flicker_color,
|
||||
"flicker_break_chance" = flicker_break_chance,
|
||||
"flicker_distance" = flicker_distance,
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
/datum/component/shadekin/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
switch(action)
|
||||
if("adjust_time")
|
||||
var/new_time = text2num(params["val"])
|
||||
new_time = CLAMP(new_time, 2, 20)
|
||||
if(!isnum(new_time))
|
||||
return FALSE
|
||||
flicker_time = new_time
|
||||
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_time, new_time)
|
||||
return TRUE
|
||||
if("adjust_color")
|
||||
var/set_new_color = tgui_color_picker(ui.user, "Select a color you wish the lights to flicker as (Default is #E0EFF0)", "Color Selector", flicker_color)
|
||||
if(!set_new_color)
|
||||
return FALSE
|
||||
flicker_color = set_new_color
|
||||
ui.user.write_preference_directly(/datum/preference/color/living/flicker_color, set_new_color)
|
||||
return TRUE
|
||||
if("adjust_break")
|
||||
var/new_break_chance = text2num(params["val"])
|
||||
new_break_chance = CLAMP(new_break_chance, 0, 25)
|
||||
if(!isnum(new_break_chance))
|
||||
return FALSE
|
||||
flicker_break_chance = new_break_chance
|
||||
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_break_chance, new_break_chance)
|
||||
return TRUE
|
||||
if("adjust_distance")
|
||||
var/new_distance = text2num(params["val"])
|
||||
new_distance = CLAMP(new_distance, 4, 10)
|
||||
if(!isnum(new_distance))
|
||||
return FALSE
|
||||
flicker_distance = new_distance
|
||||
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_distance, new_distance)
|
||||
return TRUE
|
||||
|
||||
/mob/living/proc/nutrition_conversion_toggle()
|
||||
set name = "Toggle Energy <-> Nutrition conversions"
|
||||
set desc = "Toggle dark energy and nutrition being converted into each other when full"
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
|
||||
if(SK.nutrition_energy_conversion)
|
||||
to_chat(src, span_notice("Nutrition and dark energy conversions disabled."))
|
||||
SK.nutrition_energy_conversion = 0
|
||||
else
|
||||
to_chat(src, span_notice("Nutrition and dark energy conversions enabled."))
|
||||
SK.nutrition_energy_conversion = 1
|
||||
|
||||
/mob/living/proc/flicker_adjustment()
|
||||
set name = "Adjust Light Flicker"
|
||||
set desc = "Allows you to adjust the settings of the light flicker when you phase in!"
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
|
||||
SK.tgui_interact(src)
|
||||
@@ -6,7 +6,7 @@ var/bluespace_item_types = newlist(/obj/item/storage/backpack/holding,
|
||||
)
|
||||
|
||||
//wrapper
|
||||
/proc/do_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, local=TRUE, bohsafe=FALSE) //CHOMPStation Edit
|
||||
/proc/do_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, local=TRUE, bohsafe=FALSE)
|
||||
new /datum/teleport/instant/science(arglist(args))
|
||||
return
|
||||
|
||||
@@ -19,17 +19,17 @@ var/bluespace_item_types = newlist(/obj/item/storage/backpack/holding,
|
||||
var/soundin //soundfile to play before teleportation
|
||||
var/soundout //soundfile to play after teleportation
|
||||
var/force_teleport = 1 //if false, teleport will use Move() proc (dense objects will prevent teleportation)
|
||||
var/local = TRUE //VOREStation Add - If false, can teleport from/to any z-level
|
||||
var/bohsafe = FALSE //CHOMP Add - if true, can teleport safely with a BoH
|
||||
var/local = TRUE //If false, can teleport from/to any z-level
|
||||
var/bohsafe = FALSE //If true, can teleport safely with a BoH
|
||||
|
||||
|
||||
/datum/teleport/New(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, local=TRUE, bohsafe=FALSE) //CHOMPStation Edit
|
||||
/datum/teleport/New(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, local=TRUE, bohsafe=FALSE)
|
||||
..()
|
||||
if(!initTeleport(arglist(args)))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/teleport/proc/initTeleport(ateleatom,adestination,aprecision,afteleport,aeffectin,aeffectout,asoundin,asoundout,local,bohsafe) //CHOMPStation Edit
|
||||
/datum/teleport/proc/initTeleport(ateleatom,adestination,aprecision,afteleport,aeffectin,aeffectout,asoundin,asoundout,local,bohsafe)
|
||||
if(!setTeleatom(ateleatom))
|
||||
return 0
|
||||
if(!setDestination(adestination))
|
||||
@@ -40,7 +40,7 @@ var/bluespace_item_types = newlist(/obj/item/storage/backpack/holding,
|
||||
setEffects(aeffectin,aeffectout)
|
||||
setForceTeleport(afteleport)
|
||||
setSounds(asoundin,asoundout)
|
||||
src.local = local // VOREStation Add
|
||||
src.local = local
|
||||
return 1
|
||||
|
||||
//must succeed
|
||||
@@ -123,7 +123,7 @@ var/bluespace_item_types = newlist(/obj/item/storage/backpack/holding,
|
||||
var/mob/living/L = teleatom
|
||||
if(L.buckled)
|
||||
C = L.buckled
|
||||
if(attempt_vr(src,"try_televore",args)) return //VOREStation Edit - Telenoms.
|
||||
if(attempt_vr(src,"try_televore",args)) return
|
||||
if(force_teleport)
|
||||
teleatom.forceMove(destturf)
|
||||
playSpecials(destturf,effectout,soundout)
|
||||
@@ -142,7 +142,7 @@ var/bluespace_item_types = newlist(/obj/item/storage/backpack/holding,
|
||||
|
||||
/datum/teleport/instant //teleports when datum is created
|
||||
|
||||
/datum/teleport/instant/New(ateleatom, adestination, aprecision=0, afteleport=1, bohsafe=0, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null) //CHOMP edit
|
||||
/datum/teleport/instant/New(ateleatom, adestination, aprecision=0, afteleport=1, bohsafe=0, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null)
|
||||
if(..())
|
||||
teleport()
|
||||
return
|
||||
@@ -152,20 +152,18 @@ var/bluespace_item_types = newlist(/obj/item/storage/backpack/holding,
|
||||
if(!aeffectin || !aeffectout)
|
||||
var/datum/effect/effect/system/spark_spread/aeffect = new
|
||||
aeffect.set_up(5, 1, teleatom)
|
||||
//CHOMP add start
|
||||
var/datum/effect/effect/system/spark_spread/aeffect2 = new
|
||||
aeffect2.set_up(5, 1, teleatom) //This looks stupid, but it doesn't work unless I do
|
||||
//CHOMP add end
|
||||
aeffect2.set_up(5, 1, teleatom)
|
||||
effectin = effectin || aeffect
|
||||
effectout = effectout || aeffect2 //CHOMP edit
|
||||
effectout = effectout || aeffect2
|
||||
return 1
|
||||
else
|
||||
return ..()
|
||||
|
||||
/datum/teleport/instant/science/setPrecision(aprecision)
|
||||
..()
|
||||
if(bohsafe) //CHOMPedit
|
||||
return 1 //CHOMPedit
|
||||
if(bohsafe)
|
||||
return 1
|
||||
|
||||
var/list/bluespace_things = newlist()
|
||||
|
||||
@@ -174,14 +172,12 @@ var/bluespace_item_types = newlist(/obj/item/storage/backpack/holding,
|
||||
precision = rand(1, 100)
|
||||
bluespace_things |= teleatom.search_contents_for(item)
|
||||
|
||||
//VOREStation Addition Start: Prevent taurriding abuse
|
||||
if(isliving(teleatom))
|
||||
var/mob/living/L = teleatom
|
||||
if(LAZYLEN(L.buckled_mobs))
|
||||
for(var/mob/rider in L.buckled_mobs)
|
||||
for (var/item in bluespace_item_types)
|
||||
bluespace_things |= rider.search_contents_for(item)
|
||||
//VOREStation Addition End: Prevent taurriding abuse
|
||||
|
||||
if(bluespace_things.len)
|
||||
precision = max(rand(1,100)*bluespace_things.len,100)
|
||||
@@ -202,17 +198,6 @@ var/bluespace_item_types = newlist(/obj/item/storage/backpack/holding,
|
||||
else
|
||||
teleatom.visible_message(span_danger("\The [teleatom] bounces off of the portal!"))
|
||||
return 0
|
||||
/* VOREStation Removal
|
||||
if(destination.z in using_map.admin_levels) //CentCom z-level
|
||||
if(istype(teleatom, /obj/mecha))
|
||||
var/obj/mecha/MM = teleatom
|
||||
to_chat(MM.occupant, span_danger("\The [MM] would not survive the jump to a location so far away!"))
|
||||
return 0
|
||||
if(!isemptylist(teleatom.search_contents_for(/obj/item/storage/backpack/holding)))
|
||||
teleatom.visible_message(span_danger("\The [teleatom] bounces off of the portal!"))
|
||||
return 0
|
||||
*/ //VOREStation Removal End
|
||||
//VOREStation Edit Start
|
||||
var/obstructed = 0
|
||||
var/turf/dest_turf = get_turf(destination)
|
||||
if(local && !(dest_turf.z in using_map.player_levels))
|
||||
@@ -239,4 +224,3 @@ var/bluespace_item_types = newlist(/obj/item/storage/backpack/holding,
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
//VOREStation Edit End
|
||||
|
||||
@@ -2693,6 +2693,12 @@ var/list/the_station_areas = list (
|
||||
dynamic_lighting = 0
|
||||
requires_power = 0
|
||||
|
||||
/area/shadekin
|
||||
name = "\improper Shadekin Retreat"
|
||||
icon_state = "blue"
|
||||
requires_power = 0
|
||||
ambience = AMBIENCE_OTHERWORLDLY
|
||||
flags = RAD_SHIELDED | AREA_FLAG_IS_NOT_PERSISTENT | BLUE_SHIELDED | AREA_ALLOW_LARGE_SIZE | AREA_LIMIT_DARK_RESPITE | AREA_ALLOW_CLOCKOUT
|
||||
|
||||
//CHOMPSTATION AREAS
|
||||
//Moved hangars to here from Southern cross areas.
|
||||
|
||||
@@ -73,13 +73,6 @@
|
||||
name = "\improper Particle Accelerator Lab"
|
||||
icon_state = "toxlab"
|
||||
|
||||
/area/shadekin
|
||||
name = "\improper Shadekin Retreat"
|
||||
icon_state = "blue"
|
||||
requires_power = 0
|
||||
ambience = AMBIENCE_OTHERWORLDLY
|
||||
flags = RAD_SHIELDED | AREA_FLAG_IS_NOT_PERSISTENT | BLUE_SHIELDED | AREA_ALLOW_LARGE_SIZE | AREA_LIMIT_DARK_RESPITE | AREA_ALLOW_CLOCKOUT
|
||||
|
||||
/area/security/nuke_storage
|
||||
flags = PHASE_SHIELDED
|
||||
|
||||
|
||||
+5
-12
@@ -563,23 +563,16 @@ GLOBAL_DATUM(spoiler_obfuscation_image, /image)
|
||||
return (flags & flag) == flag
|
||||
return flags & flag
|
||||
|
||||
// RS Port #658 Start
|
||||
/area/proc/check_phase_shift(var/mob/ourmob)
|
||||
/area/proc/check_phase_shift(var/mob/living/ourmob)
|
||||
if(!flag_check(AREA_BLOCK_PHASE_SHIFT) || !ourmob.is_incorporeal())
|
||||
return
|
||||
if(!isliving(ourmob))
|
||||
return
|
||||
if(check_rights_for(ourmob.client, R_HOLDER))
|
||||
if(check_rights_for(ourmob.client, R_HOLDER)) //If we're an admin, we don't get affected by phase blockers.
|
||||
return
|
||||
if(issimplekin(ourmob))
|
||||
var/mob/living/simple_mob/shadekin/SK = ourmob
|
||||
if(SK.ability_flags & AB_PHASE_SHIFTED)
|
||||
SK.phase_in(SK.loc)
|
||||
if(ishuman(ourmob))
|
||||
var/mob/living/carbon/human/SK = ourmob
|
||||
if(SK.ability_flags & AB_PHASE_SHIFTED)
|
||||
SK.phase_in(SK.loc)
|
||||
// RS Port #658 End
|
||||
var/datum/component/shadekin/SK = ourmob.get_shadekin_component()
|
||||
if(SK && SK.in_phase)
|
||||
SK.attack_dephase(ourmob.loc, src)
|
||||
|
||||
/area/proc/isAlwaysIndoors()
|
||||
return FALSE
|
||||
|
||||
@@ -1015,6 +1015,8 @@ About the new airlock wires panel:
|
||||
|
||||
/obj/machinery/door/airlock/CtrlClick(mob/user) //Hold door open
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
if(user.is_incorporeal())
|
||||
return
|
||||
if(!Adjacent(user))
|
||||
return
|
||||
if(user.a_intent == I_HURT)
|
||||
|
||||
@@ -25,9 +25,11 @@ GLOBAL_LIST_BOILERPLATE(all_portals, /obj/effect/portal)
|
||||
if(AM.is_incorporeal())
|
||||
if(!event)
|
||||
return
|
||||
if(iscarbon(AM))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
H.attack_dephase(null, src)
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
var/datum/component/shadekin/SK = L.get_shadekin_component()
|
||||
if(SK)
|
||||
SK.attack_dephase(null, src)
|
||||
if(ismob(AM) && !(isliving(AM)))
|
||||
return //do not send ghosts, zshadows, ai eyes, etc
|
||||
spawn(0)
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
var/cell_type = /obj/item/cell/device
|
||||
var/power_usage = 1
|
||||
var/power_use = 1
|
||||
var/flickering = FALSE
|
||||
pickup_sound = 'sound/items/pickup/device.ogg'
|
||||
drop_sound = 'sound/items/drop/device.ogg'
|
||||
|
||||
@@ -88,6 +89,9 @@
|
||||
. += "It appears to have a high amount of power remaining."
|
||||
|
||||
/obj/item/flashlight/attack_self(mob/user)
|
||||
if(flickering)
|
||||
to_chat(user, "The light is currently malfunctioning and you're unable to adjust it!") //To prevent some lighting anomalities.
|
||||
return
|
||||
if(power_use)
|
||||
if(!isturf(user.loc))
|
||||
to_chat(user, "You cannot turn the light on while in this [user.loc].") //To prevent some lighting anomalities.
|
||||
@@ -240,6 +244,48 @@
|
||||
var/turf/T = get_turf(target)
|
||||
OL.place_directional_light(T)
|
||||
|
||||
/obj/item/flashlight/proc/flicker(var/amount = rand(10, 20), var/flicker_color, var/forced)
|
||||
if(flickering)
|
||||
return
|
||||
if(!flicker_color)
|
||||
flicker_color = light_color //If we don't have a flicker color, use our current light color.
|
||||
if((!power_use && !forced) || (!power_usage && !forced))
|
||||
return //We don't use power / have no power, so we're probably a flare or dead.
|
||||
flickering = TRUE
|
||||
var/original_color = light_color
|
||||
var/original_on = on
|
||||
var/datum/component/overlay_lighting/OL = GetComponent(/datum/component/overlay_lighting) //BEWARE, ESOTERIC BULLSHIT HERE.
|
||||
if(flicker_color && light_color != flicker_color)
|
||||
set_light_color(flicker_color)
|
||||
OL.directional_atom.color = flicker_color
|
||||
do_flicker(amount, flicker_color, original_color, original_on, OL, 1)
|
||||
|
||||
|
||||
/// Args:
|
||||
/// amount is how many timer to flicker.
|
||||
/// flicker_color is what to set the flashlight to when we flicker.
|
||||
/// original_color is what our original color was prior to flickering
|
||||
/// original_on is if we were originally on or not.
|
||||
/// OL is our overlay for lighting.
|
||||
/// ticker is how many times we have flickered so far.
|
||||
/obj/item/flashlight/proc/do_flicker(var/amount = rand(10, 20), var/flicker_color, var/original_color, var/original_on, var/datum/component/overlay_lighting/OL, var/ticker)
|
||||
if(ticker >= amount) //We have flickered enough times. Terminate the cycle.
|
||||
finish_flicker(original_color, original_on, OL)
|
||||
return
|
||||
on = !on
|
||||
update_brightness()
|
||||
if(!on) // Only play when the light turns off.
|
||||
playsound(src, 'sound/effects/light_flicker.ogg', 50, 1)
|
||||
addtimer(CALLBACK(src, PROC_REF(do_flicker), amount, flicker_color, original_color, original_on, OL, ++ticker), rand(5,15), TIMER_DELETE_ME)
|
||||
|
||||
/obj/item/flashlight/proc/finish_flicker(var/original_color, var/original_on, var/datum/component/overlay_lighting/OL)
|
||||
set_light_color(original_color)
|
||||
OL.directional_atom.color = original_color
|
||||
on = original_on
|
||||
flickering = FALSE
|
||||
update_brightness()
|
||||
|
||||
|
||||
/obj/item/flashlight/pen
|
||||
name = "penlight"
|
||||
desc = "A pen-sized light, used by medical staff."
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/datum/preference/color/living/flicker_color
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "flicker_color"
|
||||
can_randomize = FALSE
|
||||
|
||||
/datum/preference/color/living/flicker_color/create_default_value()
|
||||
return "#E0EFF0"
|
||||
|
||||
/datum/preference/color/living/flicker_color/apply_to_living(mob/living/target, value)
|
||||
var/datum/component/shadekin/our_SK = target.get_shadekin_component()
|
||||
if(our_SK)
|
||||
our_SK.flicker_color = value
|
||||
|
||||
/datum/preference/numeric/living/flicker_time
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "flicker_time"
|
||||
can_randomize = FALSE
|
||||
minimum = 2
|
||||
maximum = 20
|
||||
|
||||
/datum/preference/numeric/living/flicker_time/create_default_value()
|
||||
return 10
|
||||
|
||||
/datum/preference/numeric/living/flicker_time/apply_to_living(mob/living/target, value)
|
||||
var/datum/component/shadekin/our_SK = target.get_shadekin_component()
|
||||
if(our_SK)
|
||||
our_SK.flicker_time = value
|
||||
|
||||
/datum/preference/numeric/living/flicker_break_chance
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "flicker_break_chance"
|
||||
can_randomize = FALSE
|
||||
minimum = 0
|
||||
maximum = 25
|
||||
|
||||
/datum/preference/numeric/living/flicker_break_chance/create_default_value()
|
||||
return 0
|
||||
|
||||
/datum/preference/numeric/living/flicker_break_chance/apply_to_living(mob/living/target, value)
|
||||
var/datum/component/shadekin/our_SK = target.get_shadekin_component()
|
||||
if(our_SK)
|
||||
our_SK.flicker_break_chance = value
|
||||
|
||||
/datum/preference/numeric/living/flicker_distance
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "flicker_distance"
|
||||
can_randomize = FALSE
|
||||
minimum = 4
|
||||
maximum = 10
|
||||
|
||||
/datum/preference/numeric/living/flicker_distance/create_default_value()
|
||||
return 4
|
||||
|
||||
/datum/preference/numeric/living/flicker_distance/apply_to_living(mob/living/target, value)
|
||||
var/datum/component/shadekin/our_SK = target.get_shadekin_component()
|
||||
if(our_SK)
|
||||
our_SK.flicker_distance = value
|
||||
@@ -287,3 +287,41 @@
|
||||
emote_message_1p_target = "You prbt at TARGET."
|
||||
emote_message_3p_target = "prbts at TARGET."
|
||||
emote_sound = 'sound/voice/prbt.ogg'
|
||||
|
||||
//Some Spooky sounds.
|
||||
/decl/emote/audible/evil_laugh
|
||||
key = "evillaugh"
|
||||
emote_message_3p = "laughs!"
|
||||
emote_sound = 'sound/mob/spooky/laugh.ogg'
|
||||
|
||||
/decl/emote/audible/evil_no
|
||||
key = "evilno"
|
||||
emote_message_3p = "says no!"
|
||||
emote_sound = 'sound/mob/spooky/no.ogg'
|
||||
|
||||
/decl/emote/audible/evil_breathing
|
||||
key = "evilbreath"
|
||||
emote_message_3p = "breaths heavily!"
|
||||
emote_sound = 'sound/mob/spooky/breath1.ogg'
|
||||
|
||||
/decl/emote/audible/evil_breathing_2
|
||||
key = "evilbreath2"
|
||||
emote_message_3p = "breaths heavily!"
|
||||
emote_sound = 'sound/mob/spooky/breath2.ogg'
|
||||
|
||||
/decl/emote/audible/goodripsound
|
||||
key = "goodripsound"
|
||||
emote_message_3p = "drips goo."
|
||||
|
||||
/decl/emote/audible/goodripsound/do_extra(var/mob/user)
|
||||
..()
|
||||
var/goo_sounds = list (
|
||||
'sound/mob/spooky/decay1.ogg',
|
||||
'sound/mob/spooky/decay2.ogg',
|
||||
'sound/mob/spooky/decay3.ogg',
|
||||
'sound/mob/spooky/corrosion1.ogg',
|
||||
'sound/mob/spooky/corrosion2.ogg',
|
||||
'sound/mob/spooky/corrosion3.ogg'
|
||||
)
|
||||
var/sound = pick(goo_sounds)
|
||||
playsound(user.loc, sound, 100, 1)
|
||||
|
||||
@@ -331,3 +331,18 @@
|
||||
/decl/emote/visible/tilt
|
||||
key = "tilt"
|
||||
emote_message_3p = "tilts USER_THEIR head."
|
||||
|
||||
/decl/emote/visible/goodrip
|
||||
key = "goodrip"
|
||||
emote_message_3p = "drips goo."
|
||||
|
||||
/decl/emote/visible/goodrip/do_extra(var/mob/user)
|
||||
..()
|
||||
new /obj/effect/decal/cleanable/blood/oil(user)
|
||||
var/goo_sounds = list (
|
||||
'sound/mob/spooky/decay1.ogg',
|
||||
'sound/mob/spooky/decay2.ogg',
|
||||
'sound/mob/spooky/decay3.ogg'
|
||||
)
|
||||
var/sound = pick(goo_sounds)
|
||||
playsound(user.loc, sound, 100, 1)
|
||||
|
||||
@@ -27,15 +27,12 @@
|
||||
if(world.time < next_emote)
|
||||
to_chat(src, span_warning("You cannot use another emote yet."))
|
||||
return
|
||||
//VOREStation Addition Start
|
||||
if(forced_psay)
|
||||
pme(message)
|
||||
return
|
||||
if(autowhisper)
|
||||
return me_verb_subtle(message)
|
||||
|
||||
//VOREStation Addition End
|
||||
|
||||
if(act == "help")
|
||||
if(world.time >= next_emote_refresh)
|
||||
var/list/usable_emotes = list()
|
||||
|
||||
@@ -332,12 +332,13 @@
|
||||
return if_no_id
|
||||
|
||||
//repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a seperate proc as it'll be useful elsewhere
|
||||
/mob/living/carbon/human/proc/get_visible_name()
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
/mob/living/carbon/human/get_visible_name()
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(SK && SK.in_phase)
|
||||
return "Something" // Something
|
||||
if( wear_mask && (wear_mask.flags_inv&HIDEFACE) ) //Wearing a mask which hides our face, use id-name if possible
|
||||
if(wear_mask && (wear_mask.flags_inv&HIDEFACE)) //Wearing a mask which hides our face, use id-name if possible
|
||||
return get_id_name("Unknown")
|
||||
if( head && (head.flags_inv&HIDEFACE) )
|
||||
if(head && (head.flags_inv&HIDEFACE))
|
||||
return get_id_name("Unknown") //Likewise for hats
|
||||
var/face_name = get_face_name()
|
||||
var/id_name = get_id_name("")
|
||||
|
||||
@@ -14,43 +14,3 @@
|
||||
tail_alt = TAIL_UPPER_LAYER // not a toggle for humans but a pointer for what layer the tail should be when facing North/East/West
|
||||
|
||||
var/list/body_writing // assoc list by BP_ key
|
||||
|
||||
/mob/living/carbon/human/proc/shadekin_get_energy()
|
||||
var/datum/species/shadekin/SK = species
|
||||
|
||||
if(!istype(SK))
|
||||
return 0
|
||||
|
||||
return SK.get_energy(src)
|
||||
|
||||
/mob/living/carbon/human/proc/shadekin_get_max_energy()
|
||||
var/datum/species/shadekin/SK = species
|
||||
|
||||
if(!istype(SK))
|
||||
return 0
|
||||
|
||||
return SK.get_max_energy(src)
|
||||
|
||||
/mob/living/carbon/human/proc/shadekin_set_energy(var/new_energy)
|
||||
var/datum/species/shadekin/SK = species
|
||||
|
||||
if(!istype(SK))
|
||||
return 0
|
||||
|
||||
SK.set_energy(src, new_energy)
|
||||
|
||||
/mob/living/carbon/human/proc/shadekin_set_max_energy(var/new_max_energy)
|
||||
var/datum/species/shadekin/SK = species
|
||||
|
||||
if(!istype(SK))
|
||||
return 0
|
||||
|
||||
SK.set_max_energy(src, new_max_energy)
|
||||
|
||||
/mob/living/carbon/human/proc/shadekin_adjust_energy(var/amount)
|
||||
var/datum/species/shadekin/SK = species
|
||||
|
||||
if(!istype(SK))
|
||||
return 0
|
||||
|
||||
SK.set_energy(src, SK.get_energy(src) + amount)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/mob/living/carbon/human/GetAltName()
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(SK && SK.in_phase)
|
||||
return ""
|
||||
if(name != GetVoice())
|
||||
return " (as [get_id_name("Unknown")])"
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
but next to no verifiable evidence to their existence. However, they have recently been more verifiably \
|
||||
documented in the Virgo system, following a mining bombardment of Virgo 3. The crew of NSB Adephagia have \
|
||||
taken to calling these creatures 'Shadekin', and the name has generally stuck and spread. " //TODO: Something that's not wiki copypaste
|
||||
//CHOMPStation Removal TFF 12/24/19 - Wikilinks removed
|
||||
// wikilink = "https://wiki.vore-station.net/Shadekin"
|
||||
wikilink = "https://wiki.vore-station.net/Shadekin"
|
||||
catalogue_data = list(/datum/category_item/catalogue/fauna/shadekin)
|
||||
|
||||
language = LANGUAGE_SHADEKIN
|
||||
@@ -22,9 +21,6 @@
|
||||
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/shadekin, /datum/unarmed_attack/bite/sharp/shadekin)
|
||||
rarity_value = 15 //INTERDIMENSIONAL FLUFFERS
|
||||
|
||||
// male_scream_sound = null //CHOMPedit
|
||||
// female_scream_sound = null //CHOMPedit
|
||||
|
||||
inherent_verbs = list(/mob/proc/adjust_hive_range)
|
||||
|
||||
siemens_coefficient = 1
|
||||
@@ -62,7 +58,7 @@
|
||||
|
||||
// has_glowing_eyes = TRUE //Applicable through neutral taits.
|
||||
|
||||
//death_message = "phases to somewhere far away!" //CHOMPEdit Removed
|
||||
death_message = "phases to somewhere far away!"
|
||||
speech_bubble_appearance = "ghost"
|
||||
|
||||
genders = list(MALE, FEMALE, PLURAL, NEUTER)
|
||||
@@ -72,7 +68,6 @@
|
||||
breath_type = null
|
||||
poison_type = null
|
||||
water_breather = TRUE //They don't quite breathe
|
||||
var/doing_phase = FALSE // Prevent bugs when spamming phase button
|
||||
|
||||
vision_flags = SEE_SELF|SEE_MOBS
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_SKIN_COLOR | HAS_EYE_COLOR | HAS_UNDERWEAR
|
||||
@@ -105,164 +100,116 @@
|
||||
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
|
||||
)
|
||||
|
||||
//SHADEKIN-UNIQUE STUFF GOES HERE
|
||||
var/list/shadekin_abilities = list(/datum/power/shadekin/phase_shift,
|
||||
/datum/power/shadekin/regenerate_other,
|
||||
/datum/power/shadekin/create_shade,
|
||||
/datum/power/shadekin/dark_tunneling, //CHOMPEdit Add - Dark Tunneling
|
||||
/datum/power/shadekin/dark_respite, //CHOMPEdit Add - Dark Respite
|
||||
/datum/power/shadekin/dark_maw) //CHOMPEdit Add - Dark Maw
|
||||
var/list/shadekin_ability_datums = list()
|
||||
var/list/active_dark_maws = list() //CHOMPEdit - Add dark maws
|
||||
var/kin_type
|
||||
var/energy_light = 0.25
|
||||
var/energy_dark = 0.75
|
||||
var/nutrition_conversion_scaling = 0.5 //CHOMPEdit - Add nutrition <-> dark energy conversion
|
||||
var/phase_gentle = TRUE //CHOMPEdit - Add gentle phasing, defaults to on.
|
||||
var/manual_respite = FALSE //CHOMPEdit - Dark Respite
|
||||
var/respite_activating = FALSE //CHOMPEdit - Dark Respite
|
||||
var/nutrition_energy_conversion = TRUE //CHOMPEdit - Add toggle to nutrition and energy conversions
|
||||
species_component = /datum/component/shadekin
|
||||
species_component = /datum/component/shadekin/full //CHOMPEdit: Enabling full shadekin.
|
||||
component_requires_late_recalc = TRUE
|
||||
|
||||
/datum/species/shadekin/New()
|
||||
..()
|
||||
for(var/power in shadekin_abilities)
|
||||
var/datum/power/shadekin/SKP = new power(src)
|
||||
shadekin_ability_datums.Add(SKP)
|
||||
|
||||
//CHOMPEdit Begin - Actually phase to the Dark on death
|
||||
/datum/species/shadekin/handle_death(var/mob/living/carbon/human/H)
|
||||
H.clear_dark_maws() //CHOMPEdit - clear dark maws on death or similar
|
||||
if(respite_activating)
|
||||
return TRUE
|
||||
var/area/current_area = get_area(H)
|
||||
if((H.ability_flags & AB_DARK_RESPITE) || H.has_modifier_of_type(/datum/modifier/dark_respite) || current_area.flag_check(AREA_LIMIT_DARK_RESPITE))
|
||||
return
|
||||
if(!LAZYLEN(GLOB.latejoin_thedark))
|
||||
log_and_message_admins("[H] died outside of the dark but there were no valid floors to warp to")
|
||||
return
|
||||
|
||||
H.visible_message("<b>\The [H.name]</b> phases to somewhere far away!")
|
||||
var/obj/effect/temp_visual/shadekin/phase_out/phaseanimout = new /obj/effect/temp_visual/shadekin/phase_out(H.loc)
|
||||
phaseanimout.dir = H.dir
|
||||
respite_activating = TRUE
|
||||
|
||||
H.drop_l_hand()
|
||||
H.drop_r_hand()
|
||||
|
||||
H.shadekin_set_energy(0)
|
||||
H.ability_flags |= AB_DARK_RESPITE
|
||||
H.invisibility = INVISIBILITY_SHADEKIN
|
||||
|
||||
H.adjustFireLoss(-(H.getFireLoss() * 0.75))
|
||||
H.adjustBruteLoss(-(H.getBruteLoss() * 0.75))
|
||||
H.adjustToxLoss(-(H.getToxLoss() * 0.75))
|
||||
H.adjustCloneLoss(-(H.getCloneLoss() * 0.75))
|
||||
H.germ_level = 0 // CHOMPAdd - Take away the germs, or we'll die AGAIN
|
||||
H.vessel.add_reagent(REAGENT_ID_BLOOD,blood_volume-H.vessel.total_volume)
|
||||
for(var/obj/item/organ/external/bp in H.organs)
|
||||
bp.bandage()
|
||||
bp.disinfect()
|
||||
H.nutrition = 0
|
||||
H.invisibility = INVISIBILITY_SHADEKIN
|
||||
BITRESET(H.hud_updateflag, HEALTH_HUD)
|
||||
BITRESET(H.hud_updateflag, STATUS_HUD)
|
||||
BITRESET(H.hud_updateflag, LIFE_HUD)
|
||||
|
||||
if(istype(H.loc, /obj/belly))
|
||||
//Yay digestion... presumably...
|
||||
var/obj/belly/belly = H.loc
|
||||
add_attack_logs(belly.owner, H, "Digested in [lowertext(belly.name)]")
|
||||
to_chat(belly.owner, span_notice("\The [H.name] suddenly vanishes within your [belly.name]"))
|
||||
H.forceMove(pick(GLOB.latejoin_thedark))
|
||||
if(H.ability_flags & AB_PHASE_SHIFTED)
|
||||
H.phase_shift()
|
||||
else
|
||||
var/obj/effect/temp_visual/shadekin/phase_in/phaseanim = new /obj/effect/temp_visual/shadekin/phase_in(H.loc)
|
||||
phaseanim.dir = H.dir
|
||||
H.invisibility = initial(H.invisibility)
|
||||
respite_activating = FALSE
|
||||
belly.owner.handle_belly_update() // CHOMPEdit
|
||||
H.clear_fullscreen("belly")
|
||||
if(H.hud_used)
|
||||
if(!H.hud_used.hud_shown)
|
||||
H.toggle_hud_vis()
|
||||
H.stop_sound_channel(CHANNEL_PREYLOOP)
|
||||
H.add_modifier(/datum/modifier/dark_respite, 10 MINUTES)
|
||||
H.muffled = FALSE
|
||||
H.forced_psay = FALSE
|
||||
|
||||
|
||||
spawn(5 MINUTES)
|
||||
H.ability_flags &= ~AB_DARK_RESPITE
|
||||
to_chat(H, span_notice("You feel like you can leave the Dark again"))
|
||||
var/special_handling = TRUE //varswitch for downstream //CHOMPEdit - Enable.
|
||||
H.clear_dark_maws() //clear dark maws on death or similar
|
||||
if(!special_handling)
|
||||
spawn(1)
|
||||
for(var/obj/item/W in H)
|
||||
H.drop_from_inventory(W)
|
||||
qdel(H)
|
||||
else
|
||||
H.add_modifier(/datum/modifier/dark_respite, 25 MINUTES)
|
||||
var/datum/component/shadekin/SK = H.get_shadekin_component()
|
||||
if(!SK)
|
||||
return
|
||||
if(SK.respite_activating)
|
||||
return TRUE
|
||||
var/area/current_area = get_area(H)
|
||||
if((SK.in_dark_respite) || H.has_modifier_of_type(/datum/modifier/dark_respite) || current_area.flag_check(AREA_LIMIT_DARK_RESPITE))
|
||||
return
|
||||
if(!LAZYLEN(GLOB.latejoin_thedark))
|
||||
log_and_message_admins("[H] died outside of the dark but there were no valid floors to warp to")
|
||||
return
|
||||
|
||||
spawn(1 SECOND)
|
||||
H.visible_message("<b>\The [H.name]</b> phases to somewhere far away!")
|
||||
var/obj/effect/temp_visual/shadekin/phase_out/phaseanimout = new /obj/effect/temp_visual/shadekin/phase_out(H.loc)
|
||||
phaseanimout.dir = H.dir
|
||||
SK.respite_activating = TRUE
|
||||
|
||||
H.drop_l_hand()
|
||||
H.drop_r_hand()
|
||||
|
||||
SK.shadekin_set_energy(0)
|
||||
SK.in_dark_respite = TRUE
|
||||
H.invisibility = INVISIBILITY_SHADEKIN
|
||||
|
||||
H.adjustFireLoss(-(H.getFireLoss() * 0.75))
|
||||
H.adjustBruteLoss(-(H.getBruteLoss() * 0.75))
|
||||
H.adjustToxLoss(-(H.getToxLoss() * 0.75))
|
||||
H.adjustCloneLoss(-(H.getCloneLoss() * 0.75))
|
||||
H.germ_level = 0 //Take away the germs, or we'll die AGAIN
|
||||
H.vessel.add_reagent(REAGENT_ID_BLOOD,blood_volume-H.vessel.total_volume)
|
||||
for(var/obj/item/organ/external/bp in H.organs)
|
||||
bp.bandage()
|
||||
bp.disinfect()
|
||||
for(var/obj/item/organ/internal/I in H.internal_organs) //other wise their organs stay mush
|
||||
I.damage = 0
|
||||
I.status = 0
|
||||
if(I.organ_tag == O_EYES)
|
||||
H.sdisabilities &= ~BLIND
|
||||
if(I.organ_tag == O_LUNGS)
|
||||
H.SetLosebreath(0)
|
||||
H.nutrition = 0
|
||||
H.invisibility = INVISIBILITY_SHADEKIN
|
||||
BITRESET(H.hud_updateflag, HEALTH_HUD)
|
||||
BITRESET(H.hud_updateflag, STATUS_HUD)
|
||||
BITRESET(H.hud_updateflag, LIFE_HUD)
|
||||
|
||||
if(istype(H.loc, /obj/belly))
|
||||
//Yay digestion... presumably...
|
||||
var/obj/belly/belly = H.loc
|
||||
add_attack_logs(belly.owner, H, "Digested in [lowertext(belly.name)]")
|
||||
to_chat(belly.owner, span_notice("\The [H.name] suddenly vanishes within your [belly.name]"))
|
||||
H.forceMove(pick(GLOB.latejoin_thedark))
|
||||
if(H.ability_flags & AB_PHASE_SHIFTED)
|
||||
if(SK.in_phase)
|
||||
H.phase_shift()
|
||||
else
|
||||
var/obj/effect/temp_visual/shadekin/phase_in/phaseanim = new /obj/effect/temp_visual/shadekin/phase_in(H.loc)
|
||||
phaseanim.dir = H.dir
|
||||
H.invisibility = initial(H.invisibility)
|
||||
respite_activating = FALSE
|
||||
SK.respite_activating = FALSE
|
||||
belly.owner.handle_belly_update()
|
||||
H.clear_fullscreen("belly")
|
||||
if(H.hud_used)
|
||||
if(!H.hud_used.hud_shown)
|
||||
H.toggle_hud_vis()
|
||||
H.stop_sound_channel(CHANNEL_PREYLOOP)
|
||||
H.add_modifier(/datum/modifier/dark_respite, 10 MINUTES)
|
||||
H.muffled = FALSE
|
||||
H.forced_psay = FALSE
|
||||
|
||||
spawn(15 MINUTES)
|
||||
H.ability_flags &= ~AB_DARK_RESPITE
|
||||
to_chat(H, span_notice("You feel like you can leave the Dark again"))
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/modifier/dark_respite
|
||||
name = "Dark Respite"
|
||||
pain_immunity = 1
|
||||
|
||||
/datum/modifier/dark_respite/tick()
|
||||
if(istype(src.holder, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = src.holder
|
||||
if(H.nutrition)
|
||||
H.add_chemical_effect(CE_BLOODRESTORE, 5)
|
||||
H.nutrition = max(H.nutrition - 5, 0)
|
||||
|
||||
if(istype(get_area(H), /area/shadekin))
|
||||
if(!src.pain_immunity)
|
||||
src.pain_immunity = 1
|
||||
//Very good healing, but only in the Dark.
|
||||
H.adjustFireLoss((-0.25))
|
||||
H.adjustBruteLoss((-0.25))
|
||||
H.adjustToxLoss((-0.25))
|
||||
H.heal_organ_damage(3, 0)
|
||||
H.add_chemical_effect(CE_ANTIBIOTIC, ANTIBIO_SUPER) //CHOMP Edit - increased ANTIBIO from Normal to Super
|
||||
for(var/obj/item/organ/I in H.internal_organs)
|
||||
if(I.robotic >= ORGAN_ROBOT)
|
||||
continue
|
||||
if(I.damage > 0)
|
||||
I.damage = max(I.damage - 0.25, 0)
|
||||
if(I.damage <= 5 && I.organ_tag == O_EYES)
|
||||
H.sdisabilities &= ~BLIND
|
||||
for(var/obj/item/organ/external/O in H.organs)
|
||||
if(O.status & ORGAN_BROKEN)
|
||||
O.mend_fracture() //Only works if the bone won't rebreak, as usual
|
||||
for(var/datum/wound/W in O.wounds)
|
||||
if(W.bleeding())
|
||||
W.damage = max(W.damage - 3, 0)
|
||||
if(W.damage <= 0)
|
||||
O.wounds -= W
|
||||
if(W.internal)
|
||||
W.damage = max(W.damage - 3, 0)
|
||||
if(W.damage <= 0)
|
||||
O.wounds -= W
|
||||
addtimer(CALLBACK(H, TYPE_PROC_REF(/mob/living, can_leave_dark)), 5 MINUTES, TIMER_DELETE_ME)
|
||||
else
|
||||
var/datum/species/shadekin/SK = H.species
|
||||
if(SK.manual_respite)
|
||||
to_chat(H, span_notice("As you leave the Dark, you stop focusing the Dark on healing yourself."))
|
||||
SK.manual_respite = FALSE
|
||||
src.expire()
|
||||
if(src.pain_immunity)
|
||||
src.pain_immunity = 0
|
||||
//CHOMPEdit End
|
||||
H.add_modifier(/datum/modifier/dark_respite, 25 MINUTES)
|
||||
|
||||
addtimer(CALLBACK(H, TYPE_PROC_REF(/mob/living, enter_the_dark)), 1 SECOND, TIMER_DELETE_ME)
|
||||
|
||||
addtimer(CALLBACK(H, TYPE_PROC_REF(/mob/living, can_leave_dark)), 15 MINUTES, TIMER_DELETE_ME)
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/proc/enter_the_dark()
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
return
|
||||
SK.respite_activating = FALSE
|
||||
SK.in_dark_respite = TRUE
|
||||
|
||||
forceMove(pick(GLOB.latejoin_thedark))
|
||||
invisibility = initial(invisibility)
|
||||
SK.respite_activating = FALSE
|
||||
|
||||
/mob/living/proc/can_leave_dark()
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
return
|
||||
SK.in_dark_respite = FALSE
|
||||
to_chat(src, span_notice("You feel like you can leave the Dark again"))
|
||||
|
||||
/datum/species/shadekin/get_bodytype()
|
||||
return SPECIES_SHADEKIN
|
||||
@@ -270,241 +217,33 @@
|
||||
/datum/species/shadekin/get_random_name()
|
||||
return "shadekin"
|
||||
|
||||
/datum/species/shadekin/handle_environment_special(var/mob/living/carbon/human/H)
|
||||
handle_shade(H)
|
||||
..()
|
||||
|
||||
/datum/species/shadekin/add_inherent_verbs(var/mob/living/carbon/human/H)
|
||||
..()
|
||||
add_shadekin_abilities(H)
|
||||
|
||||
/datum/species/shadekin/proc/add_shadekin_abilities(var/mob/living/carbon/human/H)
|
||||
if(!H.ability_master || !istype(H.ability_master, /obj/screen/movable/ability_master/shadekin))
|
||||
H.ability_master = null
|
||||
H.ability_master = new /obj/screen/movable/ability_master/shadekin(H)
|
||||
for(var/datum/power/shadekin/P in shadekin_ability_datums)
|
||||
if(!(P.verbpath in H.verbs))
|
||||
add_verb(H, P.verbpath)
|
||||
H.ability_master.add_shadekin_ability(
|
||||
object_given = H,
|
||||
verb_given = P.verbpath,
|
||||
name_given = P.name,
|
||||
ability_icon_given = P.ability_icon_state,
|
||||
arguments = list()
|
||||
)
|
||||
add_verb(H,/mob/living/carbon/human/proc/phase_strength_toggle ) //CHOMPEdit - Add gentle phasing //CHOMPEdit
|
||||
add_verb(H,/mob/living/carbon/human/proc/nutrition_conversion_toggle ) //CHOMPEdit - Add nutrition conversion toggle //CHOMPEdit
|
||||
add_verb(H,/mob/living/carbon/human/proc/clear_dark_maws ) //CHOMPEdit - Add Dark maw clearing //CHOMPEdit
|
||||
|
||||
/datum/species/shadekin/proc/handle_shade(var/mob/living/carbon/human/H)
|
||||
//CHOMPEdit begin - No energy during dark respite
|
||||
if(H.has_modifier_of_type(/datum/modifier/dark_respite))
|
||||
set_energy(H, 0)
|
||||
update_shadekin_hud(H)
|
||||
return
|
||||
//CHOMPEdit End
|
||||
|
||||
//Shifted kin don't gain/lose energy (and save time if we're at the cap)
|
||||
var/darkness = 1
|
||||
var/dark_gains = 0
|
||||
|
||||
var/turf/T = get_turf(H)
|
||||
if(!T)
|
||||
dark_gains = 0
|
||||
return
|
||||
|
||||
var/brightness = T.get_lumcount() //Brightness in 0.0 to 1.0
|
||||
//CHOMPEdit begin - dark in bellies
|
||||
if(isbelly(H.loc))
|
||||
brightness = 0
|
||||
//CHOMPEdit end
|
||||
darkness = 1-brightness //Invert
|
||||
var/is_dark = (darkness >= 0.5) || istype(get_area(H), /area/shadekin) //CHOMPEdit - Dark provides health
|
||||
|
||||
if(H.ability_flags & AB_PHASE_SHIFTED)
|
||||
dark_gains = 0
|
||||
else
|
||||
//Heal (very) slowly in good darkness
|
||||
if(is_dark)
|
||||
H.adjustFireLoss((-0.10)*darkness)
|
||||
H.adjustBruteLoss((-0.10)*darkness)
|
||||
H.adjustToxLoss((-0.10)*darkness)
|
||||
//energy_dark and energy_light are set by the shadekin eye traits.
|
||||
//These are balanced around their playstyles and 2 planned new aggressive abilities
|
||||
dark_gains = energy_dark
|
||||
else
|
||||
dark_gains = energy_light
|
||||
//CHOMPEdit begin - Energy <-> nutrition conversion
|
||||
if(nutrition_energy_conversion && get_energy(H) == 100 && dark_gains > 0)
|
||||
H.nutrition += dark_gains * 5 * nutrition_conversion_scaling
|
||||
else if(nutrition_energy_conversion && get_energy(H) < 50 && H.nutrition > 500)
|
||||
H.nutrition -= nutrition_conversion_scaling * 50
|
||||
dark_gains += nutrition_conversion_scaling
|
||||
//CHOMPEdit end
|
||||
|
||||
set_energy(H, get_energy(H) + dark_gains)
|
||||
|
||||
//Update huds
|
||||
update_shadekin_hud(H)
|
||||
|
||||
/datum/species/shadekin/proc/get_energy(var/mob/living/carbon/human/H)
|
||||
var/datum/component/shadekin/comp = H.GetComponent(/datum/component/shadekin)
|
||||
if(!comp)
|
||||
return FALSE //No component, no energy to be had.
|
||||
//CHOMPEdit - Dark Respite
|
||||
if(H.ability_flags & AB_DARK_RESPITE || H.has_modifier_of_type(/datum/modifier/dark_respite))
|
||||
return FALSE
|
||||
//CHOMPEdit - Dark Respite
|
||||
if(comp.dark_energy_infinite)
|
||||
return comp.max_dark_energy
|
||||
|
||||
return comp.dark_energy
|
||||
|
||||
/datum/species/shadekin/proc/get_max_energy(var/mob/living/carbon/human/H)
|
||||
var/datum/component/shadekin/comp = H.GetComponent(/datum/component/shadekin)
|
||||
if(!comp)
|
||||
return FALSE //No component, no energy to be had.
|
||||
return comp.max_dark_energy
|
||||
|
||||
/datum/species/shadekin/proc/set_energy(var/mob/living/carbon/human/H, var/new_energy)
|
||||
var/datum/component/shadekin/comp = H.GetComponent(/datum/component/shadekin)
|
||||
if(!comp)
|
||||
return FALSE //No component, no energy to be had.
|
||||
|
||||
comp.dark_energy = CLAMP(new_energy, 0, get_max_energy(H))
|
||||
|
||||
/datum/species/shadekin/proc/set_max_energy(var/mob/living/carbon/human/H, var/new_max_energy)
|
||||
var/datum/component/shadekin/comp = H.GetComponent(/datum/component/shadekin)
|
||||
if(!comp)
|
||||
return FALSE //No component, no energy to be had.
|
||||
|
||||
comp.max_dark_energy = new_max_energy
|
||||
|
||||
/datum/species/shadekin/proc/update_shadekin_hud(var/mob/living/carbon/human/H)
|
||||
var/turf/T = get_turf(H)
|
||||
if(H.shadekin_display)
|
||||
var/l_icon = 0
|
||||
var/e_icon = 0
|
||||
|
||||
H.shadekin_display.invisibility = INVISIBILITY_NONE
|
||||
if(T)
|
||||
var/brightness = T.get_lumcount() //Brightness in 0.0 to 1.0
|
||||
var/darkness = 1-brightness //Invert
|
||||
switch(darkness)
|
||||
if(0.80 to 1.00)
|
||||
l_icon = 0
|
||||
if(0.60 to 0.80)
|
||||
l_icon = 1
|
||||
if(0.40 to 0.60)
|
||||
l_icon = 2
|
||||
if(0.20 to 0.40)
|
||||
l_icon = 3
|
||||
if(0.00 to 0.20)
|
||||
l_icon = 4
|
||||
|
||||
switch(get_energy(H))
|
||||
if(0 to 24)
|
||||
e_icon = 0
|
||||
if(25 to 49)
|
||||
e_icon = 1
|
||||
if(50 to 74)
|
||||
e_icon = 2
|
||||
if(75 to 99)
|
||||
e_icon = 3
|
||||
if(100 to INFINITY)
|
||||
e_icon = 4
|
||||
|
||||
H.shadekin_display.icon_state = "shadekin-[l_icon]-[e_icon]"
|
||||
return
|
||||
|
||||
/datum/species/shadekin/proc/get_shadekin_eyecolor(var/mob/living/carbon/human/H)
|
||||
var/eyecolor_rgb = rgb(H.r_eyes, H.g_eyes, H.b_eyes)
|
||||
|
||||
var/eyecolor_hue = rgb2num(eyecolor_rgb, COLORSPACE_HSV)[1]
|
||||
var/eyecolor_sat = rgb2num(eyecolor_rgb, COLORSPACE_HSV)[2]
|
||||
var/eyecolor_val = rgb2num(eyecolor_rgb, COLORSPACE_HSV)[3]
|
||||
|
||||
//First, clamp the saturation/value to prevent black/grey/white eyes
|
||||
if(eyecolor_sat < 10)
|
||||
eyecolor_sat = 10
|
||||
if(eyecolor_val < 40)
|
||||
eyecolor_val = 40
|
||||
|
||||
eyecolor_rgb = rgb(eyecolor_hue, eyecolor_sat, eyecolor_val, space=COLORSPACE_HSV)
|
||||
|
||||
H.r_eyes = rgb2num(eyecolor_rgb)[1]
|
||||
H.g_eyes = rgb2num(eyecolor_rgb)[2]
|
||||
H.b_eyes = rgb2num(eyecolor_rgb)[3]
|
||||
|
||||
//Now determine what color we fall into.
|
||||
var/eyecolor_type = BLUE_EYES
|
||||
switch(eyecolor_hue)
|
||||
if(0 to 20)
|
||||
eyecolor_type = RED_EYES
|
||||
if(21 to 50)
|
||||
eyecolor_type = ORANGE_EYES
|
||||
if(51 to 70)
|
||||
eyecolor_type = YELLOW_EYES
|
||||
if(71 to 160)
|
||||
eyecolor_type = GREEN_EYES
|
||||
if(161 to 260)
|
||||
eyecolor_type = BLUE_EYES
|
||||
if(261 to 340)
|
||||
eyecolor_type = PURPLE_EYES
|
||||
if(341 to 360)
|
||||
eyecolor_type = RED_EYES
|
||||
|
||||
return eyecolor_type
|
||||
|
||||
/datum/species/shadekin/post_spawn_special(var/mob/living/carbon/human/H)
|
||||
.=..()
|
||||
|
||||
var/eyecolor_type = get_shadekin_eyecolor(H)
|
||||
var/datum/component/shadekin/SK = H.get_shadekin_component()
|
||||
if(!SK)
|
||||
CRASH("A shadekin [H] somehow is missing their shadekin component post-spawn!")
|
||||
|
||||
switch(eyecolor_type)
|
||||
switch(SK.eye_color)
|
||||
if(BLUE_EYES)
|
||||
total_health = 75 //ChompEDIT - balance tweaks
|
||||
energy_light = 0.5
|
||||
energy_dark = 0.5
|
||||
nutrition_conversion_scaling = 0.5 //CHOMPEdit - Add nutrition <-> dark energy conversion
|
||||
total_health = 75 //CHOMPEdit
|
||||
if(RED_EYES)
|
||||
total_health = 150 //ChompEDIT - balance tweaks
|
||||
energy_light = -1
|
||||
energy_dark = 0.5 //ChompEDIT
|
||||
nutrition_conversion_scaling = 2 //CHOMPEdit - Add nutrition <-> dark energy conversion
|
||||
total_health = 150 //CHOMPEdit
|
||||
if(PURPLE_EYES)
|
||||
total_health = 100 //ChompEDIT - balance tweaks
|
||||
energy_light = -0.5
|
||||
energy_dark = 1
|
||||
nutrition_conversion_scaling = 1 //CHOMPEdit - Add nutrition <-> dark energy conversion
|
||||
total_health = 150
|
||||
if(YELLOW_EYES)
|
||||
total_health = 50 //ChompEDIT - balance tweaks
|
||||
energy_light = -2
|
||||
energy_dark = 3
|
||||
nutrition_conversion_scaling = 0.5 //CHOMPEdit - Add nutrition <-> dark energy conversion
|
||||
total_health = 50 //CHOMPEdit
|
||||
if(GREEN_EYES)
|
||||
total_health = 100 //ChompEDIT - balance tweaks
|
||||
energy_light = 0.125
|
||||
energy_dark = 2
|
||||
nutrition_conversion_scaling = 0.5 //CHOMPEdit - Add nutrition <-> dark energy conversion
|
||||
total_health = 100
|
||||
if(ORANGE_EYES)
|
||||
total_health = 125 //ChompEDIT - balance tweaks
|
||||
energy_light = -0.5
|
||||
energy_dark = 0.5 //ChompEDIT
|
||||
nutrition_conversion_scaling = 1.5 //CHOMPEdit - Add nutrition <-> dark energy conversion
|
||||
total_health = 125 //CHOMPEdit
|
||||
|
||||
H.maxHealth = total_health
|
||||
|
||||
H.health = H.getMaxHealth()
|
||||
|
||||
/datum/species/shadekin/produceCopy(var/list/traits, var/mob/living/carbon/human/H, var/custom_base, var/reset_dna = TRUE) // Traitgenes reset_dna flag required, or genes get reset on resleeve
|
||||
|
||||
var/datum/species/shadekin/new_copy = ..()
|
||||
|
||||
new_copy.total_health = total_health
|
||||
|
||||
new_copy.energy_light = energy_light
|
||||
|
||||
new_copy.energy_dark = energy_dark
|
||||
|
||||
return new_copy
|
||||
|
||||
@@ -1,473 +1,5 @@
|
||||
/datum/power/shadekin
|
||||
|
||||
/mob/living/carbon/human/is_incorporeal()
|
||||
if(ability_flags & AB_PHASE_SHIFTED) //Shadekin
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(SK && SK.in_phase) //Shadekin
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/////////////////////
|
||||
/// PHASE SHIFT ///
|
||||
/////////////////////
|
||||
//Visual effect for phase in/out
|
||||
/obj/effect/temp_visual/shadekin
|
||||
randomdir = FALSE
|
||||
duration = 5
|
||||
icon = 'icons/mob/vore_shadekin.dmi'
|
||||
|
||||
/obj/effect/temp_visual/shadekin/phase_in
|
||||
icon_state = "tp_in"
|
||||
|
||||
/obj/effect/temp_visual/shadekin/phase_out
|
||||
icon_state = "tp_out"
|
||||
|
||||
/datum/power/shadekin/phase_shift
|
||||
name = "Phase Shift (100)"
|
||||
desc = "Shift yourself out of alignment with realspace to travel quickly to different areas."
|
||||
verbpath = /mob/living/carbon/human/proc/phase_shift
|
||||
ability_icon_state = "tech_passwall"
|
||||
|
||||
/mob/living/carbon/human/proc/phase_shift()
|
||||
set name = "Phase Shift (100)"
|
||||
set desc = "Shift yourself out of alignment with realspace to travel quickly to different areas."
|
||||
set category = "Abilities.Shadekin"
|
||||
/* //CHOMPEdit - Moved below //RS Port #658 Start
|
||||
var/area/A = get_area(src)
|
||||
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
|
||||
*/ //CHOMPEdit End
|
||||
var/ability_cost = 100
|
||||
|
||||
var/darkness = 1
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
to_chat(src,span_warning("You can't use that here!"))
|
||||
return FALSE
|
||||
if((get_area(src).flags & PHASE_SHIELDED)) //CHOMPEdit Start - Mapping tools to control phasing
|
||||
to_chat(src,span_warning("This area is preventing you from phasing!"))
|
||||
return FALSE
|
||||
//RS Port #658 Start
|
||||
var/area/A = get_area(src)
|
||||
if(!client?.holder && A.flag_check(AREA_BLOCK_PHASE_SHIFT))
|
||||
to_chat(src, span_warning("You can't do that here!"))
|
||||
return FALSE
|
||||
//RS Port #658 End //CHOMPEdit End
|
||||
|
||||
if(ability_flags & AB_PHASE_SHIFTING)
|
||||
return FALSE
|
||||
|
||||
var/brightness = T.get_lumcount() //Brightness in 0.0 to 1.0
|
||||
darkness = 1-brightness //Invert
|
||||
|
||||
var/watcher = 0
|
||||
//CHOMPEdit Start - Nerf to phasing
|
||||
for(var/thing in orange(7, src))
|
||||
if(istype(thing, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/watchers = thing
|
||||
if((watchers in oviewers(7,src)) && watchers.species != SPECIES_SHADEKIN) // And they can see us... (And aren't themselves a shadekin)
|
||||
if(!(watchers.stat) && !isbelly(watchers.loc) && !istype(watchers.loc, /obj/item/holder)) // And they are alive and not being held by someone...
|
||||
watcher++ // They are watching us!
|
||||
else if(istype(thing, /mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/watchers = thing
|
||||
if(watchers in oviewers(7,src))
|
||||
if(!watchers.stat && !isbelly(watchers.loc))
|
||||
watcher++ //The robot is watching us!
|
||||
else if(istype(thing, /obj/machinery/camera))
|
||||
var/obj/machinery/camera/watchers = thing
|
||||
if(watchers.can_use())
|
||||
if(src in watchers.can_see())
|
||||
watcher++ //CHOMPEdit End - The camera is watching us!
|
||||
|
||||
|
||||
ability_cost = CLAMP(ability_cost/(0.01+darkness*2),50, 80)//This allows for 1 watcher in full light
|
||||
if(watcher>0)
|
||||
ability_cost = ability_cost + ( 15 * watcher )
|
||||
if(!(ability_flags & AB_PHASE_SHIFTED))
|
||||
log_debug("[src] attempted to shift with [watcher] observers with a cost of [ability_cost] in a darkness level of [darkness]") //CHOMPEdit Start - More clear phase info.
|
||||
// inform about the observers affecting phasing
|
||||
if(darkness<=0.4 && watcher>=2)
|
||||
to_chat(src, span_warning("You have a few observers in a well-lit area! This may prevent phasing. (Working cameras count towards observers)"))
|
||||
else if(watcher>=3)
|
||||
to_chat(src, span_warning("You have a large number of observers! This may prevent phasing. (Working cameras count towards observers)")) //CHOMPEdit End
|
||||
|
||||
|
||||
var/datum/species/shadekin/SK = species
|
||||
/* if(!istype(SK)) //CHOMPEdit Removal - Moved to shadekin_ability_check
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
else if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!")) */ //CHOMPEdit End
|
||||
if(!shadekin_ability_check())
|
||||
return FALSE
|
||||
// Prevent bugs when spamming phase button
|
||||
else if(SK.doing_phase)
|
||||
to_chat(src, span_warning("You are already trying to phase!"))
|
||||
return FALSE
|
||||
|
||||
else if(shadekin_get_energy() < ability_cost && !(ability_flags & AB_PHASE_SHIFTED))
|
||||
to_chat(src, span_warning("Not enough energy for that ability!"))
|
||||
return FALSE
|
||||
|
||||
if(!(ability_flags & AB_PHASE_SHIFTED))
|
||||
shadekin_adjust_energy(-ability_cost)
|
||||
playsound(src, 'sound/effects/stealthoff.ogg', 75, 1)
|
||||
|
||||
if(!T.CanPass(src,T) || loc != T)
|
||||
to_chat(src,span_warning("You can't use that here!"))
|
||||
return FALSE
|
||||
|
||||
SK.doing_phase = TRUE // Prevent bugs when spamming phase button
|
||||
//Shifting in
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
phase_in(T)
|
||||
//Shifting out
|
||||
else
|
||||
phase_out(T)
|
||||
SK.doing_phase = FALSE // Prevent bugs when spamming phase button
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/phase_in(var/turf/T)
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
|
||||
// pre-change
|
||||
forceMove(T)
|
||||
var/original_canmove = canmove
|
||||
SetStunned(0)
|
||||
SetWeakened(0)
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
|
||||
// change
|
||||
canmove = FALSE
|
||||
ability_flags &= ~AB_PHASE_SHIFTED
|
||||
ability_flags |= AB_PHASE_SHIFTING
|
||||
throwpass = FALSE
|
||||
name = get_visible_name()
|
||||
for(var/obj/belly/B as anything in vore_organs)
|
||||
B.escapable = initial(B.escapable)
|
||||
|
||||
//cut_overlays()
|
||||
invisibility = initial(invisibility)
|
||||
see_invisible = initial(see_invisible)
|
||||
see_invisible_default = initial(see_invisible_default) //CHOMPEdit Add - Allow seeing phased entities while phased. (Port upstream)
|
||||
incorporeal_move = initial(incorporeal_move)
|
||||
density = initial(density)
|
||||
force_max_speed = initial(force_max_speed)
|
||||
can_pull_size = initial(can_pull_size) //CHOMPEdit Start - Resetting pull ability after phasing back in (Port upstream)
|
||||
can_pull_mobs = initial(can_pull_mobs)
|
||||
hovering = initial(hovering) //CHOMPEdit End
|
||||
update_icon()
|
||||
|
||||
//Cosmetics mostly
|
||||
var/obj/effect/temp_visual/shadekin/phase_in/phaseanim = new /obj/effect/temp_visual/shadekin/phase_in(src.loc)
|
||||
phaseanim.pixel_y = (src.size_multiplier - 1) * 16 // Pixel shift for the animation placement
|
||||
phaseanim.adjust_scale(src.size_multiplier, src.size_multiplier)
|
||||
phaseanim.dir = dir
|
||||
alpha = 0
|
||||
automatic_custom_emote(VISIBLE_MESSAGE,"phases in!")
|
||||
|
||||
addtimer(CALLBACK(src, PROC_REF(shadekin_complete_phase_in), original_canmove), 5, TIMER_DELETE_ME)
|
||||
|
||||
/mob/living/carbon/human/proc/shadekin_complete_phase_in(var/original_canmove)
|
||||
var/datum/species/shadekin/SK = species //CHOMPEdit Add - Eye check. (Port upstream)
|
||||
canmove = original_canmove
|
||||
alpha = initial(alpha)
|
||||
remove_modifiers_of_type(/datum/modifier/shadekin_phase_vision)
|
||||
remove_modifiers_of_type(/datum/modifier/shadekin_phase) //CHOMPEdit Add - Shadekin probably shouldn't be hit while phasing (Port upstream)
|
||||
|
||||
//Potential phase-in vore
|
||||
if(can_be_drop_pred || can_be_drop_prey) //Toggleable in vore panel //CHOMPEdit Start - Dropprey and phasevore checks. (Port upstream when possible)
|
||||
var/list/potentials = living_mobs(0)
|
||||
if(potentials.len)
|
||||
var/mob/living/target = pick(potentials)
|
||||
if(can_be_drop_pred && istype(target) && target.devourable && target.can_be_drop_prey && target.phase_vore && vore_selected && phase_vore)
|
||||
target.forceMove(vore_selected)
|
||||
to_chat(target, span_vwarning("\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!"))
|
||||
to_chat(src, span_vwarning("You phase around [target], [vore_selected.vore_verb]ing them into your [vore_selected.name]!"))
|
||||
else if(can_be_drop_prey && istype(target) && devourable && target.can_be_drop_pred && target.phase_vore && target.vore_selected && phase_vore)
|
||||
forceMove(target.vore_selected)
|
||||
to_chat(target, span_vwarning("\The [src] phases into you, [target.vore_selected.vore_verb]ing them into your [target.vore_selected.name]!"))
|
||||
to_chat(src, span_vwarning("You phase into [target], having them [target.vore_selected.vore_verb] you into their [target.vore_selected.name]!")) //CHOMPEdit End - Dropprey and phasevore checks.
|
||||
|
||||
ability_flags &= ~AB_PHASE_SHIFTING
|
||||
|
||||
//Affect nearby lights
|
||||
var/destroy_lights = 0
|
||||
|
||||
//CHOMPEdit Start - Add back light destruction & gentle phasing (Port upstream but replace with my variable toggle for full 100% control over chance, color, etc ~Diana)
|
||||
if(SK.get_shadekin_eyecolor(src) == RED_EYES)
|
||||
destroy_lights = 80
|
||||
else if(SK.get_shadekin_eyecolor(src) == PURPLE_EYES)
|
||||
destroy_lights = 25
|
||||
|
||||
// Add gentle phasing
|
||||
if(SK.phase_gentle) // gentle case: No light destruction. Flicker in 4 tile radius once.
|
||||
for(var/obj/machinery/light/L in GLOB.machines)
|
||||
if(L.z != z || get_dist(src,L) > 4)
|
||||
continue
|
||||
L.flicker(1)
|
||||
Stun(1)
|
||||
else //CHOMPEdit End
|
||||
for(var/obj/machinery/light/L in GLOB.machines)
|
||||
if(L.z != z || get_dist(src,L) > 10)
|
||||
continue
|
||||
|
||||
if(prob(destroy_lights))
|
||||
addtimer(CALLBACK(L, TYPE_PROC_REF(/obj/machinery/light, broken)), rand(5,25), TIMER_DELETE_ME)
|
||||
else
|
||||
L.flicker(10)
|
||||
|
||||
/mob/living/carbon/human/proc/phase_out(var/turf/T)
|
||||
if(!(ability_flags & AB_PHASE_SHIFTED))
|
||||
// pre-change
|
||||
forceMove(T)
|
||||
var/original_canmove = canmove
|
||||
SetStunned(0)
|
||||
SetWeakened(0)
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
canmove = FALSE
|
||||
|
||||
var/list/allowed_implants = list( //CHOMPEdit Start - Implant dropping
|
||||
/obj/item/implant/sizecontrol,
|
||||
/obj/item/implant/compliance,
|
||||
)
|
||||
for(var/obj/item/organ/external/organ in organs)
|
||||
for(var/obj/item/O in organ.implants)
|
||||
if(is_type_in_list(O, allowed_implants))
|
||||
continue
|
||||
if(O == nif)
|
||||
nif.unimplant(src)
|
||||
O.forceMove(drop_location())
|
||||
organ.implants -= O
|
||||
if(!has_embedded_objects())
|
||||
clear_alert("embeddedobject")
|
||||
//CHOMPEdit End
|
||||
// change
|
||||
ability_flags |= AB_PHASE_SHIFTED
|
||||
ability_flags |= AB_PHASE_SHIFTING
|
||||
throwpass = TRUE
|
||||
automatic_custom_emote(VISIBLE_MESSAGE,"phases out!")
|
||||
name = get_visible_name()
|
||||
|
||||
//CHOMPEdit Start - Unequipping slots when phasing in, and preventing pulling stuff while phased.
|
||||
if(l_hand)
|
||||
unEquip(l_hand)
|
||||
if(r_hand)
|
||||
unEquip(r_hand)
|
||||
if(back)
|
||||
unEquip(back)
|
||||
|
||||
can_pull_size = 0
|
||||
can_pull_mobs = MOB_PULL_NONE
|
||||
hovering = TRUE
|
||||
//CHOMPEdit End
|
||||
for(var/obj/belly/B as anything in vore_organs)
|
||||
B.escapable = FALSE
|
||||
|
||||
var/obj/effect/temp_visual/shadekin/phase_out/phaseanim = new /obj/effect/temp_visual/shadekin/phase_out(src.loc)
|
||||
phaseanim.pixel_y = (src.size_multiplier - 1) * 16 // Pixel shift for the animation placement
|
||||
phaseanim.adjust_scale(src.size_multiplier, src.size_multiplier)
|
||||
phaseanim.dir = dir
|
||||
alpha = 0
|
||||
add_modifier(/datum/modifier/shadekin_phase_vision)
|
||||
add_modifier(/datum/modifier/shadekin_phase) //CHOMPEdit Add - Shadekin probably shouldn't be hit while phasing
|
||||
sleep(5)
|
||||
invisibility = INVISIBILITY_SHADEKIN
|
||||
see_invisible = INVISIBILITY_SHADEKIN
|
||||
see_invisible_default = INVISIBILITY_SHADEKIN // Allow seeing phased entities while phased.
|
||||
//cut_overlays()
|
||||
update_icon()
|
||||
alpha = 127
|
||||
|
||||
canmove = original_canmove
|
||||
incorporeal_move = TRUE
|
||||
density = FALSE
|
||||
force_max_speed = TRUE
|
||||
ability_flags &= ~AB_PHASE_SHIFTING
|
||||
|
||||
|
||||
/datum/modifier/shadekin_phase_vision
|
||||
name = "Shadekin Phase Vision"
|
||||
vision_flags = SEE_THRU
|
||||
|
||||
//////////////////////////
|
||||
/// REGENERATE OTHER ///
|
||||
//////////////////////////
|
||||
/datum/power/shadekin/regenerate_other
|
||||
name = "Regenerate Other (50)"
|
||||
desc = "Spend energy to heal physical wounds in another creature."
|
||||
verbpath = /mob/living/carbon/human/proc/regenerate_other
|
||||
ability_icon_state = "tech_biomedaura"
|
||||
|
||||
/mob/living/carbon/human/proc/regenerate_other()
|
||||
set name = "Regenerate Other (50)"
|
||||
set desc = "Spend energy to heal physical wounds in another creature."
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/ability_cost = 50
|
||||
|
||||
/* CHOMPEdit Start - general shadekin ability check
|
||||
var/datum/species/shadekin/SK = species
|
||||
if(!istype(SK))
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
else if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
//CHOMPEdit Start - Dark Respite
|
||||
else if((ability_flags & AB_DARK_RESPITE || has_modifier_of_type(/datum/modifier/dark_respite)) && !(ability_flags & AB_PHASE_SHIFTED))
|
||||
to_chat(src, span_warning("You can't use that so soon after an emergency warp!"))
|
||||
return FALSE
|
||||
*/
|
||||
if(!shadekin_ability_check())
|
||||
return FALSE
|
||||
//CHOMPEdit End
|
||||
else if(shadekin_get_energy() < ability_cost)
|
||||
to_chat(src, span_warning("Not enough energy for that ability!"))
|
||||
return FALSE
|
||||
else if(ability_flags & AB_PHASE_SHIFTED)
|
||||
to_chat(src, span_warning("You can't use that while phase shifted!"))
|
||||
return FALSE
|
||||
|
||||
var/list/viewed = oview(1)
|
||||
var/list/targets = list()
|
||||
for(var/mob/living/L in viewed)
|
||||
targets += L
|
||||
if(!targets.len)
|
||||
to_chat(src,span_warning("Nobody nearby to mend!"))
|
||||
return FALSE
|
||||
|
||||
var/mob/living/target = tgui_input_list(src,"Pick someone to mend:","Mend Other", targets)
|
||||
if(!target)
|
||||
return FALSE
|
||||
|
||||
target.add_modifier(/datum/modifier/shadekin/heal_boop,1 MINUTE)
|
||||
playsound(src, 'sound/effects/EMPulse.ogg', 75, 1)
|
||||
shadekin_adjust_energy(-ability_cost)
|
||||
visible_message(span_notice("\The [src] gently places a hand on \the [target]..."))
|
||||
face_atom(target)
|
||||
return TRUE
|
||||
|
||||
/datum/modifier/shadekin/heal_boop
|
||||
name = "Shadekin Regen"
|
||||
desc = "You feel serene and well rested."
|
||||
mob_overlay_state = "green_sparkles"
|
||||
|
||||
on_created_text = span_notice("Sparkles begin to appear around you, and all your ills seem to fade away.")
|
||||
on_expired_text = span_notice("The sparkles have faded, although you feel much healthier than before.")
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
|
||||
/datum/modifier/shadekin/heal_boop/tick()
|
||||
if(!holder.getBruteLoss() && !holder.getFireLoss() && !holder.getToxLoss() && !holder.getOxyLoss() && !holder.getCloneLoss()) // No point existing if the spell can't heal.
|
||||
expire()
|
||||
return
|
||||
holder.adjustBruteLoss(-2)
|
||||
holder.adjustFireLoss(-2)
|
||||
holder.adjustToxLoss(-2)
|
||||
holder.adjustOxyLoss(-2)
|
||||
holder.adjustCloneLoss(-2)
|
||||
|
||||
|
||||
//////////////////////
|
||||
/// CREATE SHADE ///
|
||||
//////////////////////
|
||||
/datum/power/shadekin/create_shade
|
||||
name = "Create Shade (25)"
|
||||
desc = "Create a field of darkness that follows you."
|
||||
verbpath = /mob/living/carbon/human/proc/create_shade
|
||||
ability_icon_state = "tech_dispelold"
|
||||
|
||||
/mob/living/carbon/human/proc/create_shade()
|
||||
set name = "Create Shade (25)"
|
||||
set desc = "Create a field of darkness that follows you."
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/ability_cost = 25
|
||||
|
||||
/* CHOMPEdit Start - general shadekin ability check
|
||||
var/datum/species/shadekin/SK = species
|
||||
if(!istype(SK))
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
else if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
//CHOMPEdit Start - Dark Respite
|
||||
else if((ability_flags & AB_DARK_RESPITE || has_modifier_of_type(/datum/modifier/dark_respite)) && !(ability_flags & AB_PHASE_SHIFTED))
|
||||
to_chat(src, span_warning("You can't use that so soon after an emergency warp!"))
|
||||
return FALSE
|
||||
*/
|
||||
if(!shadekin_ability_check())
|
||||
return FALSE
|
||||
//CHOMPEdit End
|
||||
else if(shadekin_get_energy() < ability_cost)
|
||||
to_chat(src, span_warning("Not enough energy for that ability!"))
|
||||
return FALSE
|
||||
else if(ability_flags & AB_PHASE_SHIFTED)
|
||||
to_chat(src, span_warning("You can't use that while phase shifted!"))
|
||||
return FALSE
|
||||
|
||||
playsound(src, 'sound/effects/bamf.ogg', 75, 1)
|
||||
|
||||
add_modifier(/datum/modifier/shadekin/create_shade,20 SECONDS)
|
||||
shadekin_adjust_energy(-ability_cost)
|
||||
return TRUE
|
||||
|
||||
/datum/modifier/shadekin/create_shade
|
||||
name = "Shadekin Shadegen"
|
||||
desc = "Darkness envelops you."
|
||||
mob_overlay_state = ""
|
||||
|
||||
on_created_text = span_notice("You drag part of The Dark into realspace, enveloping yourself.")
|
||||
on_expired_text = span_warning("You lose your grasp on The Dark and realspace reasserts itself.")
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
var/mob/living/simple_mob/shadekin/my_kin
|
||||
|
||||
/datum/modifier/shadekin/create_shade/tick()
|
||||
if(my_kin.ability_flags & AB_PHASE_SHIFTED)
|
||||
expire()
|
||||
|
||||
/datum/modifier/shadekin/create_shade/on_applied()
|
||||
my_kin = holder
|
||||
holder.glow_toggle = TRUE
|
||||
holder.glow_range = 8
|
||||
holder.glow_intensity = -10
|
||||
holder.glow_color = "#FFFFFF"
|
||||
holder.set_light(8, -10, "#FFFFFF")
|
||||
|
||||
/datum/modifier/shadekin/create_shade/on_expire()
|
||||
holder.glow_toggle = initial(holder.glow_toggle)
|
||||
holder.glow_range = initial(holder.glow_range)
|
||||
holder.glow_intensity = initial(holder.glow_intensity)
|
||||
holder.glow_color = initial(holder.glow_color)
|
||||
holder.set_light(0)
|
||||
my_kin = null
|
||||
|
||||
// force dephase proc, to be called by other procs to dephase the shadekin. T is the target to force dephase them to.
|
||||
/mob/living/carbon/human/proc/attack_dephase(var/turf/T = null, atom/dephaser)
|
||||
var/datum/species/shadekin/SK = species
|
||||
|
||||
// no assigned dephase-target, just use our own
|
||||
if(!T)
|
||||
T = get_turf(src)
|
||||
|
||||
// make sure it's possible to be dephased (and we're in phase)
|
||||
if(!istype(SK) || SK.doing_phase || !T.CanPass(src,T) || loc != T || !(ability_flags & AB_PHASE_SHIFTED) )
|
||||
return FALSE
|
||||
|
||||
|
||||
log_admin("[key_name_admin(src)] was stunned out of phase at [T.x],[T.y],[T.z] by [dephaser.name], last touched by [dephaser.forensic_data?.get_lastprint()].")
|
||||
message_admins("[key_name_admin(src)] was stunned out of phase at [T.x],[T.y],[T.z] by [dephaser.name], last touched by [dephaser.forensic_data?.get_lastprint()]. (<A href='byond://?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</a>)", 1)
|
||||
// start the dephase
|
||||
phase_in(T)
|
||||
shadekin_adjust_energy(-20) // loss of energy for the interception
|
||||
// apply a little extra stun for good measure
|
||||
src.Weaken(3)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
/obj/screen/ability/verb_based/shadekin
|
||||
icon_state = "grey_spell_base"
|
||||
background_base_state = "grey"
|
||||
icon = 'icons/mob/shadekin_abilities.dmi'
|
||||
|
||||
/obj/screen/movable/ability_master/proc/add_shadekin_ability(var/object_given, var/verb_given, var/name_given, var/ability_icon_given, var/arguments)
|
||||
if(!object_given)
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/datum/species/shadekin_yw
|
||||
name = SPECIES_SHADEKIN_YW
|
||||
name_plural = "Shadekin"
|
||||
icobase = 'icons/mob/human_races/r_shadekin_vr.dmi'
|
||||
deform = 'icons/mob/human_races/r_shadekin_vr.dmi'
|
||||
tail = "tail"
|
||||
icobase_tail = 1
|
||||
blurb = "A shadekin, where their powers have been stripped down, their access to the bluespace warp, removed."
|
||||
catalogue_data = list(/datum/category_item/catalogue/fauna/shadekin)
|
||||
|
||||
language = LANGUAGE_SHADEKIN
|
||||
assisted_langs = list()
|
||||
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/shadekin, /datum/unarmed_attack/bite/sharp/shadekin)
|
||||
rarity_value = 10 //INTERDIMENSIONAL FLUFFERS
|
||||
|
||||
darksight = 10
|
||||
|
||||
slowdown = -0.5
|
||||
|
||||
brute_mod = 0.9 // Naturally sturdy.
|
||||
burn_mod = 1.2 // Furry
|
||||
|
||||
warning_low_pressure = 50
|
||||
hazard_low_pressure = -1
|
||||
|
||||
warning_high_pressure = 300
|
||||
hazard_high_pressure = INFINITY
|
||||
|
||||
cold_level_1 = -1 //Immune to cold
|
||||
cold_level_2 = -1
|
||||
cold_level_3 = -1
|
||||
|
||||
flags = NO_SCAN
|
||||
spawn_flags = SPECIES_CAN_JOIN
|
||||
|
||||
reagent_tag = IS_SHADEKIN // for shadekin-unqiue chem interactions
|
||||
|
||||
flesh_color = "#FFC896"
|
||||
blood_color = "#A10808"
|
||||
base_color = "#f0f0f0"
|
||||
color_mult = 1
|
||||
|
||||
has_glowing_eyes = TRUE
|
||||
|
||||
male_cough_sounds = null
|
||||
female_cough_sounds = null
|
||||
//male_sneeze_sound = null //CHOMPStation Edit Disable
|
||||
//female_sneeze_sound = null //CHOMPStation Edit Disable
|
||||
|
||||
speech_bubble_appearance = "ghost"
|
||||
|
||||
genders = list(PLURAL, NEUTER) //no sexual dymorphism
|
||||
ambiguous_genders = TRUE //but just in case
|
||||
|
||||
breath_type = null
|
||||
poison_type = null
|
||||
|
||||
vision_flags = SEE_SELF
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_SKIN_COLOR | HAS_EYE_COLOR | HAS_UNDERWEAR
|
||||
|
||||
move_trail = /obj/effect/decal/cleanable/blood/tracks/paw
|
||||
|
||||
has_organ = list(
|
||||
O_HEART = /obj/item/organ/internal/heart,
|
||||
O_VOICE = /obj/item/organ/internal/voicebox,
|
||||
O_LIVER = /obj/item/organ/internal/liver,
|
||||
O_KIDNEYS = /obj/item/organ/internal/kidneys,
|
||||
O_BRAIN = /obj/item/organ/internal/brain/shadekin,
|
||||
O_EYES = /obj/item/organ/internal/eyes,
|
||||
O_STOMACH = /obj/item/organ/internal/stomach,
|
||||
O_INTESTINE = /obj/item/organ/internal/intestine
|
||||
)
|
||||
|
||||
has_limbs = list(
|
||||
BP_TORSO = list("path" = /obj/item/organ/external/chest),
|
||||
BP_GROIN = list("path" = /obj/item/organ/external/groin),
|
||||
BP_HEAD = list("path" = /obj/item/organ/external/head/vr/shadekin),
|
||||
BP_L_ARM = list("path" = /obj/item/organ/external/arm),
|
||||
BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
|
||||
BP_L_LEG = list("path" = /obj/item/organ/external/leg),
|
||||
BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
|
||||
BP_L_HAND = list("path" = /obj/item/organ/external/hand),
|
||||
BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
|
||||
BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
|
||||
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
|
||||
)
|
||||
|
||||
/datum/species/shadekin_yw/get_bodytype()
|
||||
return SPECIES_SHADEKIN
|
||||
|
||||
/datum/species/shadekin_yw/get_random_name()
|
||||
return "shadekin"
|
||||
|
||||
/datum/species/shadekin_yw/can_breathe_water()
|
||||
return TRUE //they dont quite breathe
|
||||
@@ -1,19 +0,0 @@
|
||||
//This file is so i can make upates to shadekin and easily push to vorestation, just a main override file
|
||||
|
||||
/datum/species/shadekin/handle_environment_special(var/mob/living/carbon/human/H)
|
||||
handle_shade(H)
|
||||
handle_phased(H)
|
||||
|
||||
//Slippery fingers, if we ever make some update that makes all held items non useable for kins we can remove this.
|
||||
/datum/species/shadekin/proc/handle_phased(var/mob/living/carbon/human/shadekin/H)
|
||||
if(H.ability_flags & AB_PHASE_SHIFTED)
|
||||
if(H.l_hand)
|
||||
H.drop_l_hand()
|
||||
|
||||
if(H.r_hand)
|
||||
H.drop_r_hand()
|
||||
|
||||
return 1 //we are phased and applied all handling
|
||||
|
||||
else
|
||||
return 0 //we aren't phased ignore all
|
||||
@@ -359,6 +359,7 @@
|
||||
var/food_preference_bonus = 0
|
||||
|
||||
var/datum/component/species_component = null // The component that this species uses. Example: Xenochimera use /datum/component/xenochimera
|
||||
var/component_requires_late_recalc = FALSE // If TRUE, the component will do special recalculation stuff at the end of update_icons_body()
|
||||
|
||||
// For Lleill and Hanner
|
||||
var/lleill_energy = 200
|
||||
@@ -595,12 +596,11 @@
|
||||
SEND_SIGNAL(H, COMSIG_XENOCHIMERA_COMPONENT)
|
||||
|
||||
//Shadekin Species Component.
|
||||
/* //For when shadekin actually have their component control everything.
|
||||
var/datum/component/shadekin/sk = H.get_xenochimera_component()
|
||||
//For when shadekin actually have their component control everything.
|
||||
var/datum/component/shadekin/sk = H.get_shadekin_component()
|
||||
if(sk)
|
||||
if(!H.stat || !(xc.revive_ready == REVIVING_NOW || xc.revive_ready == REVIVING_DONE))
|
||||
if(!H.stat)
|
||||
SEND_SIGNAL(H, COMSIG_SHADEKIN_COMPONENT)
|
||||
*/
|
||||
|
||||
// Used to update alien icons for aliens.
|
||||
/datum/species/proc/handle_login_special(var/mob/living/carbon/human/H)
|
||||
|
||||
@@ -153,14 +153,18 @@
|
||||
/datum/unarmed_attack/claws/shadekin/apply_effects(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
|
||||
..()
|
||||
if(!(target == user))
|
||||
user.shadekin_adjust_energy(attack_damage)
|
||||
var/datum/component/shadekin/SK = user.get_shadekin_component()
|
||||
if(SK)
|
||||
SK.shadekin_adjust_energy(attack_damage)
|
||||
|
||||
/datum/unarmed_attack/bite/sharp/shadekin
|
||||
|
||||
/datum/unarmed_attack/bite/sharp/shadekin/apply_effects(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
|
||||
..()
|
||||
if(!(target == user))
|
||||
user.shadekin_adjust_energy(attack_damage)
|
||||
var/datum/component/shadekin/SK = user.get_shadekin_component()
|
||||
if(SK)
|
||||
SK.shadekin_adjust_energy(attack_damage)
|
||||
|
||||
/datum/unarmed_attack/claws/chimera //special feral attack that gets stronger as they get angrier
|
||||
|
||||
|
||||
@@ -376,6 +376,10 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) //see UpdateDamageIcon()
|
||||
update_wing_showing()
|
||||
update_vore_belly_sprite()
|
||||
update_vore_tail_sprite()
|
||||
if(species && species.component_requires_late_recalc)
|
||||
var/datum/component/shadekin/SK = GetComponent(/datum/component/shadekin)
|
||||
if(SK)
|
||||
SK.recalc_values()
|
||||
|
||||
/mob/living/carbon/human/proc/update_skin()
|
||||
if(QDESTROYING(src))
|
||||
|
||||
@@ -18,6 +18,15 @@
|
||||
|
||||
selected_image = image(icon = GLOB.buildmode_hud, loc = src, icon_state = "ai_sel")
|
||||
|
||||
/mob/living/proc/get_visible_name()
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(SK && SK.in_phase)
|
||||
return "Something"
|
||||
if(real_name)
|
||||
return real_name
|
||||
else
|
||||
return name
|
||||
|
||||
/mob/living/Destroy()
|
||||
SSradiation.listeners -= src
|
||||
remove_all_modifiers(TRUE)
|
||||
@@ -1255,7 +1264,7 @@
|
||||
swap_hand()
|
||||
|
||||
/mob/living/throw_item(atom/target)
|
||||
if(incapacitated() || !target || istype(target, /obj/screen))
|
||||
if(incapacitated() || !target || istype(target, /obj/screen) || is_incorporeal())
|
||||
return FALSE
|
||||
|
||||
var/atom/movable/item = src.get_active_hand()
|
||||
|
||||
@@ -417,9 +417,10 @@
|
||||
|
||||
if(get_dist(get_turf(T), get_turf(src)) > leap_distance) return
|
||||
|
||||
if(ishuman(T))
|
||||
var/mob/living/carbon/human/H = T
|
||||
if(H.get_species() == SPECIES_SHADEKIN && (H.ability_flags & AB_PHASE_SHIFTED))
|
||||
if(isliving(T))
|
||||
var/mob/living/M = T
|
||||
var/datum/component/shadekin/SK = M.get_shadekin_component()
|
||||
if(SK && SK.in_phase)
|
||||
power_cost *= 2
|
||||
|
||||
if(!use_direct_power(power_cost, minimum_power - power_cost))
|
||||
|
||||
@@ -419,18 +419,18 @@
|
||||
for(var/datum/matter_synth/our_synth in module.synths)
|
||||
switch(our_synth.name)
|
||||
if(METAL_SYNTH)
|
||||
if(has_glass)
|
||||
possible_synths[/obj/item/stack/material/cyborg/glass/reinforced] = list(our_synth, has_glass)
|
||||
possible_synths += list(/obj/item/stack/material/cyborg/steel = list(our_synth))
|
||||
possible_synths += list(/obj/item/stack/tile/floor/cyborg = list(our_synth))
|
||||
possible_synths += list(/obj/item/stack/rods/cyborg = list(our_synth))
|
||||
possible_synths += list(/obj/item/stack/tile/roofing/cyborg = list(our_synth))
|
||||
if(has_glass)
|
||||
possible_synths |= list(/obj/item/stack/material/cyborg/glass/reinforced = list(our_synth, has_glass))
|
||||
if(PLASTEEL_SYNTH)
|
||||
possible_synths += list(/obj/item/stack/material/cyborg/plasteel = list(our_synth))
|
||||
if(GLASS_SYNTH)
|
||||
possible_synths += list(/obj/item/stack/material/cyborg/glass = list(our_synth))
|
||||
if(has_steel)
|
||||
possible_synths |= list(/obj/item/stack/material/cyborg/glass/reinforced = list(our_synth, has_steel))
|
||||
possible_synths[/obj/item/stack/material/cyborg/glass/reinforced] = list(our_synth, has_steel)
|
||||
possible_synths += list(/obj/item/stack/material/cyborg/glass = list(our_synth))
|
||||
if(WOOD_SYNTH)
|
||||
possible_synths += list(/obj/item/stack/tile/wood/cyborg = list(our_synth))
|
||||
possible_synths += list(/obj/item/stack/material/cyborg/wood = list(our_synth))
|
||||
|
||||
@@ -105,6 +105,8 @@
|
||||
|
||||
if(in_stasis)
|
||||
return 1 // return early to skip atmos checks
|
||||
if(is_incorporeal())
|
||||
return 1
|
||||
|
||||
var/atom/A = src.loc
|
||||
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
zone_sel.update_icon()
|
||||
hud_elements |= zone_sel
|
||||
|
||||
//Component hud elements. Made in /mob/living/create_mob_hud
|
||||
hud_elements |= shadekin_display
|
||||
hud_elements |= xenochimera_danger_display
|
||||
hud_elements |= lleill_display
|
||||
|
||||
//Hand things
|
||||
if(has_hands)
|
||||
//Drop button
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
density = FALSE
|
||||
force_max_speed = TRUE
|
||||
|
||||
/mob/living/simple_mob/vore/demon/verb/phase_shift()
|
||||
/mob/living/simple_mob/vore/demon/verb/demonic_phase_shift()
|
||||
set name = "Phase Shift"
|
||||
set desc = "Shift out of reality temporarily"
|
||||
set category = "Abilities.Demon"
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
/mob/living/simple_mob/clowns/big/c_shift/Initialize(mapload)
|
||||
. = ..()
|
||||
add_verb(src, /mob/living/simple_mob/clowns/big/c_shift/proc/phase_shift)
|
||||
comp = LoadComponent(comp)
|
||||
|
||||
@@ -1,92 +1,20 @@
|
||||
/mob/living/simple_mob/clowns/big/c_shift
|
||||
var/ability_flags = 0 //Flags for active abilities
|
||||
|
||||
// Phase shifting procs (and related procs)
|
||||
/mob/living/simple_mob/clowns/big/c_shift/proc/phase_shift()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T.CanPass(src,T) || loc != T)
|
||||
to_chat(src,span_warning("You can't use that here!"))
|
||||
return FALSE
|
||||
|
||||
forceMove(T)
|
||||
var/original_canmove = canmove
|
||||
SetStunned(0)
|
||||
SetWeakened(0)
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
canmove = FALSE
|
||||
|
||||
//Shifting in
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
ability_flags &= ~AB_PHASE_SHIFTED
|
||||
mouse_opacity = 2
|
||||
name = real_name
|
||||
|
||||
|
||||
cut_overlays()
|
||||
alpha = initial(alpha)
|
||||
invisibility = initial(invisibility)
|
||||
see_invisible = initial(see_invisible)
|
||||
incorporeal_move = initial(incorporeal_move)
|
||||
density = initial(density)
|
||||
force_max_speed = initial(force_max_speed)
|
||||
|
||||
//Cosmetics mostly
|
||||
flick("tp_in",src)
|
||||
automatic_custom_emote(VISIBLE_MESSAGE,"phases in!")
|
||||
sleep(5) //The duration of the TP animation
|
||||
canmove = original_canmove
|
||||
|
||||
// Do this after the potential vore, so we get the belly
|
||||
update_icon()
|
||||
|
||||
//Affect nearby lights
|
||||
|
||||
|
||||
for(var/obj/machinery/light/L in GLOB.machines)
|
||||
if(L.z != z || get_dist(src,L) > 10)
|
||||
continue
|
||||
|
||||
L.flicker(10)
|
||||
|
||||
//Shifting out
|
||||
else
|
||||
ability_flags |= AB_PHASE_SHIFTED
|
||||
mouse_opacity = 0
|
||||
automatic_custom_emote(VISIBLE_MESSAGE,"phases out!")
|
||||
real_name = name
|
||||
name = "Something"
|
||||
|
||||
cut_overlays()
|
||||
flick("tp_out",src)
|
||||
sleep(5)
|
||||
invisibility = INVISIBILITY_LEVEL_TWO
|
||||
see_invisible = INVISIBILITY_LEVEL_TWO
|
||||
update_icon()
|
||||
alpha = 127
|
||||
|
||||
canmove = original_canmove
|
||||
incorporeal_move = TRUE
|
||||
density = FALSE
|
||||
force_max_speed = TRUE
|
||||
var/datum/component/shadekin/comp = /datum/component/shadekin/phase_only //Component that holds all the shadekin vars.
|
||||
|
||||
/mob/living/simple_mob/clowns/big/c_shift/UnarmedAttack()
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
if(comp.in_phase)
|
||||
return FALSE //Nope.
|
||||
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_mob/clowns/big/c_shift/can_fall()
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
if(comp.in_phase)
|
||||
return FALSE //Nope!
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/clowns/big/c_shift/zMove(direction)
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
if(comp.in_phase)
|
||||
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
|
||||
if(destination)
|
||||
forceMove(destination)
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
|
||||
/obj/effect/shadekin_ability/proc/atom_button_text()
|
||||
var/shift_denial
|
||||
|
||||
if(shift_mode == NOT_WHILE_SHIFTED && (my_kin.ability_flags & AB_PHASE_SHIFTED))
|
||||
if(shift_mode == NOT_WHILE_SHIFTED && my_kin.comp.in_phase)
|
||||
shift_denial = "Physical Only"
|
||||
else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.ability_flags & AB_PHASE_SHIFTED))
|
||||
else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.comp.in_phase))
|
||||
shift_denial = "Shifted Only"
|
||||
|
||||
if(shift_denial)
|
||||
@@ -47,15 +46,10 @@
|
||||
if(my_kin.stat)
|
||||
to_chat(my_kin,span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
//CHOMPEdit Begin - Dark Respite
|
||||
if(my_kin.ability_flags & AB_DARK_RESPITE)
|
||||
to_chat(src, span_warning("You can't use that so soon after an emergency warp!"))
|
||||
return FALSE
|
||||
//CHOMPEdit End
|
||||
if(shift_mode == NOT_WHILE_SHIFTED && (my_kin.ability_flags & AB_PHASE_SHIFTED))
|
||||
if(shift_mode == NOT_WHILE_SHIFTED && (my_kin.comp.in_phase))
|
||||
to_chat(my_kin,span_warning("Can't use that ability while phase shifted!"))
|
||||
return FALSE
|
||||
else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.ability_flags & AB_PHASE_SHIFTED))
|
||||
else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.comp.in_phase))
|
||||
to_chat(my_kin,span_warning("Can only use that ability while phase shifted!"))
|
||||
return FALSE
|
||||
else if(my_kin.comp.dark_energy < cost)
|
||||
@@ -80,7 +74,7 @@
|
||||
if(!..())
|
||||
return
|
||||
my_kin.phase_shift()
|
||||
if(my_kin.ability_flags & AB_PHASE_SHIFTED)
|
||||
if(my_kin.comp.in_phase)
|
||||
cost = 0 //Shifting back is free (but harmful in light)
|
||||
else
|
||||
cost = initial(cost)
|
||||
@@ -141,7 +135,7 @@
|
||||
var/mob/living/simple_mob/shadekin/my_kin
|
||||
|
||||
/datum/modifier/shadekin/create_shade/tick()
|
||||
if(my_kin.ability_flags & AB_PHASE_SHIFTED)
|
||||
if(my_kin.comp.in_phase)
|
||||
expire()
|
||||
|
||||
/datum/modifier/shadekin/create_shade/on_applied()
|
||||
@@ -172,38 +166,3 @@
|
||||
if(!..())
|
||||
return
|
||||
*/
|
||||
|
||||
//CHOMPEdit start - Add dark tunneling ability
|
||||
/obj/effect/shadekin_ability/dark_tunneling
|
||||
ability_name = "Dark Tunneling"
|
||||
desc = "Make a passage to the dark. (Once)"
|
||||
icon_state = "minion0"
|
||||
cost = 100
|
||||
shift_mode = NOT_WHILE_SHIFTED
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/shadekin_ability/dark_tunneling/do_ability()
|
||||
if(my_kin.ability_flags & AB_DARK_TUNNEL)
|
||||
to_chat(src, span_warning("You have already made a tunnel to the Dark!"))
|
||||
return FALSE
|
||||
if(!..())
|
||||
return
|
||||
if(!my_kin.dark_tunneling())
|
||||
my_kin.comp.dark_energy += cost //Refund due to abort
|
||||
else
|
||||
my_kin.comp.dark_energy += 10 //Refund enough to open the dark portal
|
||||
//CHOMPEdit End
|
||||
|
||||
//CHOMPEdit start - Add Dark Maw ability
|
||||
/obj/effect/shadekin_ability/dark_maw
|
||||
ability_name = "Dark Maw"
|
||||
desc = "Create a trap to capture others, or steal people from phase"
|
||||
icon_state = "ling_absorb_dna"
|
||||
cost = 20
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/shadekin_ability/dark_maw/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
if(!my_kin.dark_maw())
|
||||
my_kin.comp.dark_energy += cost //Refund due to abort
|
||||
//CHOMPEdit End
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
// Phase shifting procs (and related procs)
|
||||
/mob/living/simple_mob/shadekin/proc/phase_shift()
|
||||
/mob/living/simple_mob/shadekin/phase_shift()
|
||||
var/turf/T = get_turf(src)
|
||||
var/area/A = T.loc //RS Port #658
|
||||
var/area/A = T.loc
|
||||
if(!T.CanPass(src,T) || loc != T)
|
||||
to_chat(src,span_warning("You can't use that here!"))
|
||||
return FALSE
|
||||
//CHOMPAdd Start
|
||||
if((get_area(src).flags & PHASE_SHIELDED))
|
||||
to_chat(src,span_warning("This area is preventing you from phasing!"))
|
||||
return FALSE
|
||||
//CHOMPAdd End
|
||||
//RS Port #658 Start
|
||||
if(!check_rights_for(client, R_HOLDER) && A.flag_check(AREA_BLOCK_PHASE_SHIFT))
|
||||
to_chat(src,span_warning("You can't use that here!"))
|
||||
return FALSE
|
||||
//RS Port #658 End
|
||||
|
||||
else if(doing_phase)
|
||||
to_chat(src, span_warning("You are already trying to phase!"))
|
||||
@@ -22,136 +15,27 @@
|
||||
|
||||
doing_phase = TRUE
|
||||
//Shifting in
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
if(comp.in_phase)
|
||||
phase_in(T)
|
||||
//Shifting out
|
||||
else
|
||||
phase_out(T)
|
||||
doing_phase = FALSE
|
||||
|
||||
/mob/living/simple_mob/shadekin/proc/phase_in(var/turf/T)
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
|
||||
// pre-change
|
||||
forceMove(T)
|
||||
var/original_canmove = canmove
|
||||
SetStunned(0)
|
||||
SetWeakened(0)
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
canmove = FALSE
|
||||
|
||||
// change
|
||||
ability_flags &= ~AB_PHASE_SHIFTED
|
||||
throwpass = FALSE
|
||||
name = real_name
|
||||
for(var/obj/belly/B as anything in vore_organs)
|
||||
B.escapable = initial(B.escapable)
|
||||
|
||||
cut_overlays()
|
||||
alpha = initial(alpha)
|
||||
invisibility = initial(invisibility)
|
||||
see_invisible = initial(see_invisible)
|
||||
incorporeal_move = initial(incorporeal_move)
|
||||
density = initial(density)
|
||||
force_max_speed = initial(force_max_speed)
|
||||
|
||||
//Cosmetics mostly
|
||||
flick("tp_in",src)
|
||||
automatic_custom_emote(VISIBLE_MESSAGE,"phases in!")
|
||||
|
||||
addtimer(CALLBACK(src, PROC_REF(shadekin_complete_phase_in), original_canmove), 5, TIMER_DELETE_ME)
|
||||
|
||||
|
||||
/mob/living/simple_mob/shadekin/proc/shadekin_complete_phase_in(var/original_canmove)
|
||||
canmove = original_canmove
|
||||
|
||||
//Potential phase-in vore
|
||||
if(can_be_drop_pred) //Toggleable in vore panel
|
||||
var/list/potentials = living_mobs(0)
|
||||
if(potentials.len)
|
||||
var/mob/living/target = pick(potentials)
|
||||
if(istype(target) && target.devourable && target.can_be_drop_prey && vore_selected)
|
||||
target.forceMove(vore_selected)
|
||||
to_chat(target,span_vwarning("\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!"))
|
||||
|
||||
// Do this after the potential vore, so we get the belly
|
||||
update_icon()
|
||||
|
||||
/* CHOMPRemove Start
|
||||
//Affect nearby lights
|
||||
var/destroy_lights = 0
|
||||
if(eye_state == RED_EYES)
|
||||
destroy_lights = 80
|
||||
if(eye_state == PURPLE_EYES)
|
||||
destroy_lights = 25
|
||||
|
||||
for(var/obj/machinery/light/L in GLOB.machines)
|
||||
if(L.z != z || get_dist(src,L) > 10)
|
||||
continue
|
||||
|
||||
if(prob(destroy_lights))
|
||||
addtimer(CALLBACK(L, TYPE_PROC_REF(/obj/machinery/light, broken)), rand(5,25), TIMER_DELETE_ME)
|
||||
else
|
||||
L.flicker(10)
|
||||
*/// CHOMPRemove End
|
||||
handle_phasein_flicker() // CHOMPEdit, special handle for phase-in light flicker
|
||||
|
||||
/mob/living/simple_mob/shadekin/proc/phase_out(var/turf/T)
|
||||
if(!(ability_flags & AB_PHASE_SHIFTED))
|
||||
|
||||
// pre-change
|
||||
forceMove(T)
|
||||
var/original_canmove = canmove
|
||||
SetStunned(0)
|
||||
SetWeakened(0)
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
canmove = FALSE
|
||||
|
||||
// change
|
||||
ability_flags |= AB_PHASE_SHIFTED
|
||||
throwpass = TRUE
|
||||
automatic_custom_emote(VISIBLE_MESSAGE,"phases out!")
|
||||
real_name = name
|
||||
name = "Something"
|
||||
|
||||
for(var/obj/belly/B as anything in vore_organs)
|
||||
B.escapable = FALSE
|
||||
|
||||
cut_overlays()
|
||||
flick("tp_out",src)
|
||||
sleep(5)
|
||||
invisibility = INVISIBILITY_LEVEL_TWO
|
||||
see_invisible = INVISIBILITY_LEVEL_TWO
|
||||
update_icon()
|
||||
alpha = 127
|
||||
|
||||
canmove = original_canmove
|
||||
incorporeal_move = TRUE
|
||||
density = FALSE
|
||||
force_max_speed = TRUE
|
||||
|
||||
/mob/living/simple_mob/shadekin/UnarmedAttack()
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
if(comp.in_phase)
|
||||
return FALSE //Nope.
|
||||
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_mob/shadekin/can_fall()
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
if(comp.in_phase)
|
||||
return FALSE //Nope!
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_mob/shadekin/zMove(direction)
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
if(comp.in_phase)
|
||||
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
|
||||
if(destination)
|
||||
forceMove(destination)
|
||||
|
||||
@@ -1,454 +0,0 @@
|
||||
/mob/living/simple_mob/shadekin/Initialize(mapload)
|
||||
var/list/ability_types = subtypesof(/obj/effect/shadekin_ability)
|
||||
if(name == "Rakshasa")
|
||||
ability_types += subtypesof(/obj/effect/rakshasa_ability)
|
||||
shadekin_abilities = list()
|
||||
for(var/type in ability_types)
|
||||
shadekin_abilities += new type(src)
|
||||
|
||||
update_icon()
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/effect/rakshasa_ability
|
||||
name = ""
|
||||
desc = ""
|
||||
icon = 'icons/mob/screen_spells.dmi'
|
||||
var/ability_name = "FIX ME"
|
||||
var/cost = 50
|
||||
var/mob/living/simple_mob/shadekin/my_kin
|
||||
var/shift_mode = NOT_WHILE_SHIFTED
|
||||
var/ab_sound
|
||||
|
||||
/obj/effect/rakshasa_ability/Initialize(mapload)
|
||||
. = ..()
|
||||
my_kin = loc
|
||||
if(!istype(my_kin))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
loc = null
|
||||
|
||||
/obj/effect/rakshasa_ability/Destroy()
|
||||
my_kin = null
|
||||
return ..()
|
||||
|
||||
/obj/effect/rakshasa_ability/proc/atom_button_text()
|
||||
var/shift_denial
|
||||
|
||||
if(shift_mode == NOT_WHILE_SHIFTED && (my_kin.ability_flags & AB_PHASE_SHIFTED))
|
||||
shift_denial = "Physical Only"
|
||||
else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.ability_flags & AB_PHASE_SHIFTED))
|
||||
shift_denial = "Shifted Only"
|
||||
|
||||
if(shift_denial)
|
||||
name = shift_denial
|
||||
else
|
||||
name = my_kin.comp.dark_energy >= cost ? "Activate" : "No Energy"
|
||||
return src
|
||||
|
||||
/obj/effect/rakshasa_ability/Click(var/location, var/control, var/params)
|
||||
if(my_kin.stat) return
|
||||
|
||||
var/list/clickprops = params2list(params)
|
||||
var/opts = clickprops["shift"]
|
||||
|
||||
if(opts)
|
||||
to_chat(my_kin,span_notice("<b>[name]</b> (Cost: [cost]%) - [desc]"))
|
||||
else
|
||||
do_ability(my_kin)
|
||||
|
||||
/obj/effect/rakshasa_ability/proc/do_ability()
|
||||
if(my_kin.stat)
|
||||
to_chat(my_kin,span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
if(shift_mode == NOT_WHILE_SHIFTED && (my_kin.ability_flags & AB_PHASE_SHIFTED))
|
||||
to_chat(my_kin,span_warning("Can't use that ability while phase shifted!"))
|
||||
return FALSE
|
||||
else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.ability_flags & AB_PHASE_SHIFTED))
|
||||
to_chat(my_kin,span_warning("Can only use that ability while phase shifted!"))
|
||||
return FALSE
|
||||
else if(my_kin.comp.dark_energy < cost)
|
||||
to_chat(my_kin,span_warning("Not enough energy for that ability!"))
|
||||
return FALSE
|
||||
|
||||
my_kin.comp.dark_energy -= cost
|
||||
if(ab_sound)
|
||||
playsound(src,ab_sound,75,1)
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/effect/rakshasa_ability/phase_shift2
|
||||
ability_name = "Goo Shift"
|
||||
desc = "Shift yourself with goopy effects."
|
||||
icon_state = "tech_passwall"
|
||||
cost = 100
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/phase_shift2/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
new /obj/effect/decal/cleanable/blood/oil(loc, src)
|
||||
playsound(src, 'sound/rakshasa/Corrosion1.ogg', 100, 1)
|
||||
my_kin.rakshasa_shift()
|
||||
if(my_kin.ability_flags & AB_PHASE_SHIFTED)
|
||||
cost = 0 //Shifting back is free (but harmful in light)
|
||||
new /obj/effect/decal/cleanable/blood/oil(my_kin.loc)
|
||||
var/goo_sounds = list (
|
||||
'sound/rakshasa/Decay1.ogg',
|
||||
'sound/rakshasa/Decay2.ogg',
|
||||
'sound/rakshasa/Decay3.ogg'
|
||||
)
|
||||
var/sound = pick(goo_sounds)
|
||||
playsound(my_kin.loc, sound, 100, 1)
|
||||
else
|
||||
cost = initial(cost)
|
||||
new /obj/effect/decal/cleanable/blood/oil(my_kin.loc)
|
||||
playsound(my_kin.loc, 'sound/rakshasa/Emerge0.ogg', 100, 1)
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/obj/effect/rakshasa_ability/phase_shift3
|
||||
ability_name = "Goo Shift No Emerge"
|
||||
desc = "Shift yourself with goopy effects."
|
||||
icon_state = "tech_passwall"
|
||||
cost = 100
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/phase_shift3/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
new /obj/effect/decal/cleanable/blood/oil(loc, src)
|
||||
playsound(src, 'sound/rakshasa/Corrosion1.ogg', 100, 1)
|
||||
my_kin.rakshasa_shift()
|
||||
if(my_kin.ability_flags & AB_PHASE_SHIFTED)
|
||||
cost = 0 //Shifting back is free (but harmful in light)
|
||||
new /obj/effect/decal/cleanable/blood/oil(my_kin.loc)
|
||||
var/goo_sounds = list (
|
||||
'sound/rakshasa/Decay1.ogg',
|
||||
'sound/rakshasa/Decay2.ogg',
|
||||
'sound/rakshasa/Decay3.ogg'
|
||||
)
|
||||
var/sound = pick(goo_sounds)
|
||||
playsound(my_kin.loc, sound, 100, 1)
|
||||
else
|
||||
cost = initial(cost)
|
||||
new /obj/effect/decal/cleanable/blood/oil(my_kin.loc)
|
||||
var/goo_sounds = list (
|
||||
'sound/rakshasa/Decay1.ogg',
|
||||
'sound/rakshasa/Decay2.ogg',
|
||||
'sound/rakshasa/Decay3.ogg'
|
||||
)
|
||||
var/sound = pick(goo_sounds)
|
||||
playsound(my_kin.loc, sound, 100, 1)
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/obj/effect/rakshasa_ability/phase_shift4
|
||||
ability_name = "Stealth Shift"
|
||||
desc = "Stealthy. No light effects, no goo."
|
||||
icon_state = "tech_passwall"
|
||||
cost = 100
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/phase_shift4/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
my_kin.stealth_shift()
|
||||
if(my_kin.ability_flags & AB_PHASE_SHIFTED)
|
||||
cost = 0 //Shifting back is free (but harmful in light)
|
||||
else
|
||||
cost = initial(cost)
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/obj/effect/rakshasa_ability/drip_oil
|
||||
ability_name = "Goo Drip"
|
||||
desc = "Drip some goo."
|
||||
icon_state = ""
|
||||
cost = 0
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/drip_oil/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
new /obj/effect/decal/cleanable/blood/oil(my_kin.loc)
|
||||
var/goo_sounds = list (
|
||||
'sound/rakshasa/Decay1.ogg',
|
||||
'sound/rakshasa/Decay2.ogg',
|
||||
'sound/rakshasa/Decay3.ogg'
|
||||
)
|
||||
var/sound = pick(goo_sounds)
|
||||
playsound(my_kin.loc, sound, 100, 1)
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/obj/effect/rakshasa_ability/laugh
|
||||
ability_name = "Laugh"
|
||||
desc = "Laugh."
|
||||
icon_state = ""
|
||||
cost = 0
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/laugh/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
playsound(my_kin.loc, 'sound/rakshasa/Laugh.ogg', 100, 1)
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/obj/effect/rakshasa_ability/no
|
||||
ability_name = "Say No"
|
||||
desc = "Say no!"
|
||||
icon_state = ""
|
||||
cost = 0
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/no/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
playsound(my_kin.loc, 'sound/rakshasa/No.ogg', 100, 1)
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/obj/effect/rakshasa_ability/emergesound
|
||||
ability_name = "Heavy Breathing"
|
||||
desc = "Heavy Breathing."
|
||||
icon_state = ""
|
||||
cost = 0
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/emergesound/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
playsound(my_kin.loc, 'sound/rakshasa/Breath1.ogg', 100, 1)
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/obj/effect/rakshasa_ability/trapsound
|
||||
ability_name = "Raspy Breathing"
|
||||
desc = "Raspy Breathing."
|
||||
icon_state = ""
|
||||
cost = 0
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/trapsound/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
var/goo_sounds = list (
|
||||
'sound/rakshasa/Breath2.ogg'
|
||||
)
|
||||
var/sound = pick(goo_sounds)
|
||||
playsound(my_kin.loc, sound, 100, 1)
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/obj/effect/rakshasa_ability/dripsound
|
||||
ability_name = "Goop Drip Sound"
|
||||
desc = "Do the drip sound without actually dripping."
|
||||
icon_state = ""
|
||||
cost = 0
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/dripsound/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
var/goo_sounds = list (
|
||||
'sound/rakshasa/Decay1.ogg',
|
||||
'sound/rakshasa/Decay2.ogg',
|
||||
'sound/rakshasa/Decay3.ogg',
|
||||
'sound/rakshasa/Corrosion1.ogg',
|
||||
'sound/rakshasa/Corrosion2.ogg',
|
||||
'sound/rakshasa/Corrosion3.ogg'
|
||||
)
|
||||
var/sound = pick(goo_sounds)
|
||||
playsound(my_kin.loc, sound, 100, 1)
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/obj/effect/rakshasa_ability/trap
|
||||
ability_name = "Lay Trap"
|
||||
desc = "Lay a trap that will notify you when someone steps in it."
|
||||
icon_state = ""
|
||||
cost = 0
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/trap/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
var/goo_sounds = list (
|
||||
'sound/rakshasa/Corrosion1.ogg',
|
||||
'sound/rakshasa/Corrosion2.ogg',
|
||||
'sound/rakshasa/Corrosion3.ogg'
|
||||
)
|
||||
var/sound = pick(goo_sounds)
|
||||
playsound(my_kin.loc, sound, 100, 1)
|
||||
new /obj/structure/gootrap (my_kin.loc)
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/obj/effect/rakshasa_ability/flicker
|
||||
ability_name = "Flicker Lights"
|
||||
desc = "Flicker the lights."
|
||||
icon_state = ""
|
||||
cost = 0
|
||||
shift_mode = SHIFTED_OR_NOT
|
||||
ab_sound = 'sound/effects/stealthoff.ogg'
|
||||
/obj/effect/rakshasa_ability/flicker/do_ability()
|
||||
if(!..())
|
||||
return
|
||||
my_kin.rakshasa_flicker()
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//PROCS
|
||||
//PHASE SHIFTING
|
||||
////////////////////////////////////////////////////////////////
|
||||
//Rakshasa's phase shifts are now more stealthy. No announcement on them phasing in or out. Also, an extra phaseshift with no lights flickering. For flavor. There's probably a better way of doing this, butt fuck it.
|
||||
/mob/living/simple_mob/shadekin/proc/rakshasa_shift()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T.CanPass(src,T) || loc != T)
|
||||
to_chat(src,span_warning("You can't use that here!"))
|
||||
return FALSE
|
||||
|
||||
forceMove(T)
|
||||
var/original_canmove = canmove
|
||||
SetStunned(0)
|
||||
SetWeakened(0)
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
canmove = FALSE
|
||||
|
||||
//Shifting in
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
ability_flags &= ~AB_PHASE_SHIFTED
|
||||
name = real_name
|
||||
for(var/belly in vore_organs)
|
||||
var/obj/belly/B = belly
|
||||
B.escapable = initial(B.escapable)
|
||||
|
||||
overlays.Cut()
|
||||
alpha = initial(alpha)
|
||||
invisibility = initial(invisibility)
|
||||
see_invisible = initial(see_invisible)
|
||||
incorporeal_move = initial(incorporeal_move)
|
||||
density = initial(density)
|
||||
force_max_speed = initial(force_max_speed)
|
||||
|
||||
//Cosmetics mostly
|
||||
flick("tp_in",src)
|
||||
sleep(5) //The duration of the TP animation
|
||||
canmove = original_canmove
|
||||
|
||||
//Potential phase-in vore
|
||||
if(can_be_drop_pred) //Toggleable in vore panel
|
||||
var/list/potentials = living_mobs(0)
|
||||
if(potentials.len)
|
||||
var/mob/living/target = pick(potentials)
|
||||
if(istype(target) && target.devourable && target.can_be_drop_prey && vore_selected)
|
||||
target.forceMove(vore_selected)
|
||||
to_chat(target,span_warning("\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!"))
|
||||
|
||||
// Do this after the potential vore, so we get the belly
|
||||
update_icon()
|
||||
|
||||
//Affect nearby lights
|
||||
for(var/obj/machinery/light/L in GLOB.machines)
|
||||
if(L.z != z || get_dist(src,L) > 10)
|
||||
continue
|
||||
L.flicker(10)
|
||||
|
||||
//Shifting out
|
||||
else
|
||||
ability_flags |= AB_PHASE_SHIFTED
|
||||
real_name = name
|
||||
name = "Something"
|
||||
|
||||
for(var/belly in vore_organs)
|
||||
var/obj/belly/B = belly
|
||||
B.escapable = FALSE
|
||||
|
||||
overlays.Cut()
|
||||
flick("tp_out",src)
|
||||
sleep(5)
|
||||
invisibility = INVISIBILITY_LEVEL_TWO
|
||||
see_invisible = INVISIBILITY_LEVEL_TWO
|
||||
update_icon()
|
||||
alpha = 127
|
||||
|
||||
canmove = original_canmove
|
||||
incorporeal_move = TRUE
|
||||
density = FALSE
|
||||
force_max_speed = TRUE
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/mob/living/simple_mob/shadekin/proc/stealth_shift()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T.CanPass(src,T) || loc != T)
|
||||
to_chat(src,span_warning("You can't use that here!"))
|
||||
return FALSE
|
||||
|
||||
forceMove(T)
|
||||
var/original_canmove = canmove
|
||||
SetStunned(0)
|
||||
SetWeakened(0)
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob()
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
stop_pulling()
|
||||
canmove = FALSE
|
||||
|
||||
//Shifting in
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
ability_flags &= ~AB_PHASE_SHIFTED
|
||||
name = real_name
|
||||
for(var/belly in vore_organs)
|
||||
var/obj/belly/B = belly
|
||||
B.escapable = initial(B.escapable)
|
||||
|
||||
overlays.Cut()
|
||||
alpha = initial(alpha)
|
||||
invisibility = initial(invisibility)
|
||||
see_invisible = initial(see_invisible)
|
||||
incorporeal_move = initial(incorporeal_move)
|
||||
density = initial(density)
|
||||
force_max_speed = initial(force_max_speed)
|
||||
|
||||
//Cosmetics mostly
|
||||
flick("tp_in",src)
|
||||
sleep(5) //The duration of the TP animation
|
||||
canmove = original_canmove
|
||||
|
||||
//Potential phase-in vore
|
||||
if(can_be_drop_pred) //Toggleable in vore panel
|
||||
var/list/potentials = living_mobs(0)
|
||||
if(potentials.len)
|
||||
var/mob/living/target = pick(potentials)
|
||||
if(istype(target) && target.devourable && target.can_be_drop_prey && vore_selected)
|
||||
target.forceMove(vore_selected)
|
||||
to_chat(target,span_warning("\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!"))
|
||||
|
||||
// Do this after the potential vore, so we get the belly
|
||||
update_icon()
|
||||
|
||||
//Shifting out
|
||||
else
|
||||
ability_flags |= AB_PHASE_SHIFTED
|
||||
real_name = name
|
||||
name = "Something"
|
||||
|
||||
for(var/belly in vore_organs)
|
||||
var/obj/belly/B = belly
|
||||
B.escapable = FALSE
|
||||
|
||||
overlays.Cut()
|
||||
flick("tp_out",src)
|
||||
sleep(5)
|
||||
invisibility = INVISIBILITY_LEVEL_TWO
|
||||
see_invisible = INVISIBILITY_LEVEL_TWO
|
||||
update_icon()
|
||||
alpha = 127
|
||||
|
||||
canmove = original_canmove
|
||||
incorporeal_move = TRUE
|
||||
density = FALSE
|
||||
force_max_speed = TRUE
|
||||
|
||||
|
||||
//LIGHT FLICKERING
|
||||
////////////////////////////////////////////////////////////////
|
||||
//A flicker proc. Because apparently putting this straight into the ability button doesn't work.
|
||||
/mob/living/simple_mob/shadekin/proc/rakshasa_flicker()
|
||||
for(var/obj/machinery/light/L in GLOB.machines)
|
||||
if(L.z != z || get_dist(src,L) > 10)
|
||||
continue
|
||||
L.flicker(10)
|
||||
@@ -71,17 +71,12 @@
|
||||
var/datum/component/shadekin/comp = /datum/component/shadekin //Component that holds all the shadekin vars.
|
||||
var/dark_gains = 0 //Last tick's change in energy
|
||||
var/ability_flags = 0 //Flags for active abilities
|
||||
var/obj/screen/darkhud //Holder to update this icon
|
||||
var/obj/screen/energyhud //Holder to update this icon
|
||||
|
||||
var/list/shadekin_abilities
|
||||
var/check_for_observer = FALSE
|
||||
var/check_timer = 0
|
||||
var/doing_phase = FALSE // Prevent bugs when spamming phase button
|
||||
|
||||
var/respite_activating = FALSE //CHOMPEdit - Dark Respite
|
||||
var/list/active_dark_maws = list()
|
||||
|
||||
/mob/living/simple_mob/shadekin/Initialize(mapload)
|
||||
//You spawned the prototype, and want a totally random one.
|
||||
if(type == /mob/living/simple_mob/shadekin)
|
||||
@@ -100,6 +95,7 @@
|
||||
flags |= ATOM_INITIALIZED
|
||||
return INITIALIZE_HINT_QDEL
|
||||
comp = LoadComponent(comp)
|
||||
set_eye_energy()
|
||||
|
||||
if(icon_state == "map_example")
|
||||
icon_state = pick("white","dark","brown")
|
||||
@@ -128,11 +124,6 @@
|
||||
if(eye_desc)
|
||||
desc += " This one has [eye_desc]!"
|
||||
|
||||
var/list/ability_types = subtypesof(/obj/effect/shadekin_ability)
|
||||
shadekin_abilities = list()
|
||||
for(var/type in ability_types)
|
||||
shadekin_abilities += new type(src)
|
||||
|
||||
update_icon()
|
||||
|
||||
add_verb(src, /mob/proc/adjust_hive_range)
|
||||
@@ -204,11 +195,11 @@
|
||||
|
||||
/mob/living/simple_mob/shadekin/Life()
|
||||
. = ..()
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
if(comp.in_phase)
|
||||
density = FALSE
|
||||
|
||||
//Convert spare nutrition into energy at a certain ratio
|
||||
if(. && nutrition > initial(nutrition) && comp.dark_energy < 100 && !(ability_flags | AB_DARK_RESPITE)) //CHOMPEdit - Dark Respite
|
||||
if(. && nutrition > initial(nutrition) && comp.dark_energy < 100)
|
||||
nutrition = max(0, nutrition-5)
|
||||
comp.dark_energy = min(100,comp.dark_energy+1)
|
||||
if(!client && check_for_observer && check_timer++ > 5)
|
||||
@@ -218,9 +209,9 @@
|
||||
if(!issimplekin(M))
|
||||
non_kin_count ++
|
||||
// Technically can be combined with ||, they call the same function, but readability is poor
|
||||
if(!non_kin_count && (ability_flags & AB_PHASE_SHIFTED))
|
||||
if(!non_kin_count && (comp.in_phase))
|
||||
phase_shift() // shifting back in, nobody present
|
||||
else if (non_kin_count && !(ability_flags & AB_PHASE_SHIFTED))
|
||||
else if (non_kin_count && !(comp.in_phase))
|
||||
phase_shift() // shifting out, scaredy
|
||||
|
||||
/mob/living/simple_mob/shadekin/update_icon()
|
||||
@@ -233,100 +224,91 @@
|
||||
add_overlay(tailimage)
|
||||
add_overlay(eye_icon_state)
|
||||
|
||||
/mob/living/simple_mob/shadekin/update_misc_tabs()
|
||||
..()
|
||||
var/list/L = list()
|
||||
for(var/obj/effect/shadekin_ability/A as anything in shadekin_abilities)
|
||||
var/client/C = client
|
||||
var/img
|
||||
if(C && istype(C)) //sanity checks
|
||||
if(A.ability_name in C.misc_cache)
|
||||
img = C.misc_cache[A.ability_name]
|
||||
else
|
||||
img = icon2html(A,C,sourceonly=TRUE)
|
||||
C.misc_cache[A.ability_name] = img
|
||||
|
||||
L[++L.len] = list("[A.ability_name]", A.ability_name, img, A.atom_button_text(), REF(A))
|
||||
misc_tabs["Shadekin"] = L
|
||||
|
||||
//They phase back to the dark when killed
|
||||
/mob/living/simple_mob/shadekin/death(gibbed, deathmessage = "phases to somewhere far away!")
|
||||
//CHOMPEdit Begin - Dark Respite
|
||||
if(respite_activating)
|
||||
return
|
||||
//CHOMPEdit End
|
||||
cut_overlays()
|
||||
flick("tp_out",src)
|
||||
|
||||
//CHOMPEdit Begin - Actually phase to the dark on death
|
||||
var/area/current_area = get_area(src)
|
||||
if((ability_flags & AB_DARK_RESPITE) || current_area.flag_check(AREA_LIMIT_DARK_RESPITE))
|
||||
var/special_handling = TRUE //varswitch for downstream
|
||||
if(!special_handling)
|
||||
cut_overlays()
|
||||
icon_state = ""
|
||||
spawn(1 SECOND)
|
||||
qdel(src) //Back from whence you came!
|
||||
|
||||
return ..(FALSE, deathmessage)
|
||||
|
||||
|
||||
if(!LAZYLEN(GLOB.latejoin_thedark))
|
||||
log_and_message_admins("[src] died outside of the dark but there were no valid floors to warp to")
|
||||
icon_state = ""
|
||||
spawn(1 SECOND)
|
||||
qdel(src) //Back from whence you came!
|
||||
|
||||
return ..(FALSE, deathmessage)
|
||||
|
||||
src.visible_message("<b>\The [src.name]</b> [deathmessage]")
|
||||
respite_activating = TRUE
|
||||
|
||||
drop_l_hand()
|
||||
drop_r_hand()
|
||||
|
||||
comp.dark_energy = 0
|
||||
ability_flags |= AB_DARK_RESPITE
|
||||
invisibility = INVISIBILITY_LEVEL_TWO
|
||||
|
||||
adjustFireLoss(-(getFireLoss() / 2))
|
||||
adjustBruteLoss(-(getBruteLoss() / 2))
|
||||
adjustToxLoss(-(getToxLoss() / 2))
|
||||
Stun(10)
|
||||
movement_cooldown = 5
|
||||
nutrition = 0
|
||||
|
||||
if(istype(src.loc, /obj/belly))
|
||||
//Yay digestion... presumably...
|
||||
var/obj/belly/belly = src.loc
|
||||
add_attack_logs(belly.owner, src, "Digested in [lowertext(belly.name)]")
|
||||
to_chat(belly.owner, span_notice("\The [src.name] suddenly vanishes within your [belly.name]"))
|
||||
forceMove(pick(GLOB.latejoin_thedark))
|
||||
flick("tp_in",src)
|
||||
respite_activating = FALSE
|
||||
belly.owner.handle_belly_update() // CHOMPEdit
|
||||
clear_fullscreen("belly")
|
||||
if(hud_used)
|
||||
if(!hud_used.hud_shown)
|
||||
toggle_hud_vis()
|
||||
stop_sound_channel(CHANNEL_PREYLOOP)
|
||||
|
||||
|
||||
spawn(10 MINUTES)
|
||||
ability_flags &= ~AB_DARK_RESPITE
|
||||
movement_cooldown = initial(movement_cooldown)
|
||||
to_chat(src, span_notice("You feel like you can leave the Dark again"))
|
||||
flick("tp_out",src)
|
||||
QDEL_IN(src, 1 SECOND)
|
||||
. = ..(FALSE, deathmessage)
|
||||
else
|
||||
spawn(1 SECOND)
|
||||
respite_activating = FALSE
|
||||
forceMove(pick(GLOB.latejoin_thedark))
|
||||
update_icon()
|
||||
flick("tp_in",src)
|
||||
invisibility = initial(invisibility)
|
||||
respite_activating = FALSE
|
||||
if(comp.respite_activating)
|
||||
return
|
||||
cut_overlays()
|
||||
flick("tp_out",src)
|
||||
|
||||
var/area/current_area = get_area(src)
|
||||
if((comp.in_dark_respite) || current_area.flag_check(AREA_LIMIT_DARK_RESPITE))
|
||||
icon_state = ""
|
||||
spawn(1 SECOND)
|
||||
qdel(src) //Back from whence you came!
|
||||
|
||||
return ..(FALSE, deathmessage)
|
||||
|
||||
|
||||
if(!LAZYLEN(GLOB.latejoin_thedark))
|
||||
log_and_message_admins("[src] died outside of the dark but there were no valid floors to warp to")
|
||||
icon_state = ""
|
||||
spawn(1 SECOND)
|
||||
qdel(src) //Back from whence you came!
|
||||
|
||||
return ..(FALSE, deathmessage)
|
||||
|
||||
visible_message("<b>\The [src.name]</b> [deathmessage]")
|
||||
comp.respite_activating = TRUE
|
||||
|
||||
drop_l_hand()
|
||||
drop_r_hand()
|
||||
|
||||
comp.dark_energy = 0
|
||||
comp.in_dark_respite = TRUE
|
||||
invisibility = INVISIBILITY_LEVEL_TWO
|
||||
|
||||
adjustFireLoss(-(getFireLoss() / 2))
|
||||
adjustBruteLoss(-(getBruteLoss() / 2))
|
||||
adjustToxLoss(-(getToxLoss() / 2))
|
||||
Stun(10)
|
||||
movement_cooldown = 5
|
||||
nutrition = 0
|
||||
|
||||
if(istype(src.loc, /obj/belly))
|
||||
//Yay digestion... presumably...
|
||||
var/obj/belly/belly = src.loc
|
||||
add_attack_logs(belly.owner, src, "Digested in [lowertext(belly.name)]")
|
||||
to_chat(belly.owner, span_notice("\The [src.name] suddenly vanishes within your [belly.name]"))
|
||||
forceMove(pick(GLOB.latejoin_thedark))
|
||||
flick("tp_in",src)
|
||||
comp.respite_activating = FALSE
|
||||
comp.in_dark_respite = TRUE
|
||||
belly.owner.handle_belly_update()
|
||||
clear_fullscreen("belly")
|
||||
if(hud_used)
|
||||
if(!hud_used.hud_shown)
|
||||
toggle_hud_vis()
|
||||
stop_sound_channel(CHANNEL_PREYLOOP)
|
||||
|
||||
addtimer(CALLBACK(src, PROC_REF(can_leave_dark)), 10 MINUTES, TIMER_DELETE_ME)
|
||||
else
|
||||
addtimer(CALLBACK(src, PROC_REF(enter_the_dark)), 1 SECOND, TIMER_DELETE_ME)
|
||||
addtimer(CALLBACK(src, PROC_REF(can_leave_dark)), 15 MINUTES, TIMER_DELETE_ME)
|
||||
|
||||
/mob/living/simple_mob/shadekin/enter_the_dark()
|
||||
comp.respite_activating = FALSE
|
||||
comp.in_dark_respite = TRUE
|
||||
|
||||
forceMove(pick(GLOB.latejoin_thedark))
|
||||
update_icon()
|
||||
flick("tp_in",src)
|
||||
invisibility = initial(invisibility)
|
||||
comp.respite_activating = FALSE
|
||||
|
||||
/mob/living/simple_mob/shadekin/can_leave_dark()
|
||||
comp.in_dark_respite = FALSE
|
||||
movement_cooldown = initial(movement_cooldown)
|
||||
to_chat(src, span_notice("You feel like you can leave the Dark again"))
|
||||
|
||||
spawn(15 MINUTES)
|
||||
ability_flags &= ~AB_DARK_RESPITE
|
||||
movement_cooldown = initial(movement_cooldown)
|
||||
to_chat(src, span_notice("You feel like you can leave the Dark again"))
|
||||
//CHOMPEdit End
|
||||
|
||||
/* //VOREStation AI Temporary Removal
|
||||
//Blue-eyes want to nom people to heal them
|
||||
@@ -342,101 +324,40 @@
|
||||
//They reach nutritional equilibrium (important for blue-eyes healbelly)
|
||||
/mob/living/simple_mob/shadekin/Life()
|
||||
if((. = ..()))
|
||||
handle_shade()
|
||||
comp.handle_comp()
|
||||
|
||||
/mob/living/simple_mob/shadekin/proc/set_eye_energy()
|
||||
switch(eye_state)
|
||||
//Blue has constant, steady (slow) regen and ignores darkness.
|
||||
if(BLUE_EYES)
|
||||
comp.set_light_and_darkness(0.75,0.75)
|
||||
comp.nutrition_conversion_scaling = 0.5
|
||||
if(RED_EYES)
|
||||
comp.set_light_and_darkness(-0.5,0.5)
|
||||
comp.nutrition_conversion_scaling = 2
|
||||
if(PURPLE_EYES)
|
||||
comp.set_light_and_darkness(-0.5,1)
|
||||
comp.nutrition_conversion_scaling = 1
|
||||
if(YELLOW_EYES)
|
||||
comp.set_light_and_darkness(-2,3)
|
||||
comp.nutrition_conversion_scaling = 0.5
|
||||
if(GREEN_EYES)
|
||||
comp.set_light_and_darkness(0.125,2)
|
||||
comp.nutrition_conversion_scaling = 0.5
|
||||
if(ORANGE_EYES)
|
||||
comp.set_light_and_darkness(-0.25,0.75)
|
||||
comp.nutrition_conversion_scaling = 1.5
|
||||
|
||||
/mob/living/simple_mob/shadekin/is_incorporeal()
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
if(comp.in_phase)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_mob/shadekin/handle_atmos()
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
if(comp.in_phase)
|
||||
return
|
||||
else
|
||||
return .=..()
|
||||
|
||||
/mob/living/simple_mob/shadekin/proc/handle_shade()
|
||||
//Shifted kin don't gain/lose energy (and save time if we're at the cap)
|
||||
var/darkness = 1
|
||||
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
dark_gains = 0
|
||||
return
|
||||
|
||||
var/brightness = T.get_lumcount() //Brightness in 0.0 to 1.0
|
||||
darkness = 1-brightness //Invert
|
||||
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
dark_gains = 0
|
||||
else
|
||||
//Heal (very) slowly in good darkness
|
||||
if(darkness >= 0.75)
|
||||
adjustFireLoss(-0.05)
|
||||
adjustBruteLoss(-0.05)
|
||||
adjustToxLoss(-0.05)
|
||||
|
||||
switch(eye_state)
|
||||
//Blue has constant, steady (slow) regen and ignores darkness.
|
||||
if(BLUE_EYES)
|
||||
dark_gains = 0.5
|
||||
//Red has extremely tiny energy buildup in dark, none in light, and hunts for energy.
|
||||
if(RED_EYES)
|
||||
if(darkness >= 0.75)
|
||||
dark_gains = 0.25
|
||||
//Purple eyes have moderate gains in darkness and loss in light.
|
||||
if(PURPLE_EYES)
|
||||
dark_gains = round((darkness - 0.5) * 2, 0.1)
|
||||
//Yellow has extreme gains in darkness and loss in light.
|
||||
if(YELLOW_EYES)
|
||||
dark_gains = round((darkness - 0.5) * 4, 0.1)
|
||||
//Similar to blues, but passive is less, and affected by dark
|
||||
if(GREEN_EYES)
|
||||
dark_gains = 0.25
|
||||
dark_gains += round((darkness - 0.5), 0.1)
|
||||
//More able to get energy out of the dark, worse attack gains tho
|
||||
if(ORANGE_EYES)
|
||||
if(darkness >= 0.65)
|
||||
dark_gains = 0.30
|
||||
|
||||
comp.dark_energy = max(0,min(initial(comp.dark_energy),comp.dark_energy + dark_gains))
|
||||
|
||||
//CHOMPEdit Begin - Dark Respite
|
||||
if(ability_flags & AB_DARK_RESPITE)
|
||||
comp.dark_energy = 0
|
||||
//CHOMPEdit End
|
||||
if(comp.dark_energy_infinite)
|
||||
comp.dark_energy = 100
|
||||
|
||||
//Update turf darkness hud
|
||||
if(darkhud)
|
||||
switch(darkness)
|
||||
if(0.80 to 1.00)
|
||||
darkhud.icon_state = "dark2"
|
||||
if(0.60 to 0.80)
|
||||
darkhud.icon_state = "dark1"
|
||||
if(0.40 to 0.60)
|
||||
darkhud.icon_state = "dark"
|
||||
if(0.20 to 0.40)
|
||||
darkhud.icon_state = "dark-1"
|
||||
if(0.00 to 0.20)
|
||||
darkhud.icon_state = "dark-2"
|
||||
|
||||
//Update energy storage hud
|
||||
if(energyhud)
|
||||
switch(comp.dark_energy)
|
||||
if(80 to INFINITY)
|
||||
energyhud.icon_state = "energy0"
|
||||
if(60 to 80)
|
||||
energyhud.icon_state = "energy1"
|
||||
if(40 to 60)
|
||||
energyhud.icon_state = "energy2"
|
||||
if(20 to 40)
|
||||
energyhud.icon_state = "energy3"
|
||||
if(0 to 20)
|
||||
energyhud.icon_state = "energy4"
|
||||
|
||||
/* //VOREStation AI Removal
|
||||
//Friendly ones wander towards people, maybe shy-ly if they are set to shy
|
||||
/mob/living/simple_mob/shadekin/handle_wander_movement()
|
||||
@@ -519,26 +440,6 @@
|
||||
|
||||
comp.dark_energy += gains
|
||||
|
||||
//Special hud elements for darkness and energy gains
|
||||
/mob/living/simple_mob/shadekin/extra_huds(var/datum/hud/hud,var/icon/ui_style,var/list/hud_elements)
|
||||
//Darkness hud
|
||||
darkhud = new /obj/screen()
|
||||
darkhud.icon = ui_style
|
||||
darkhud.icon_state = "dark"
|
||||
darkhud.name = "darkness"
|
||||
darkhud.screen_loc = "CENTER-2:16,SOUTH:5" //Left of the left hand
|
||||
darkhud.alpha = 150
|
||||
hud_elements |= darkhud
|
||||
|
||||
//Energy hud
|
||||
energyhud = new /obj/screen()
|
||||
energyhud.icon = ui_style
|
||||
energyhud.icon_state = "energy0"
|
||||
energyhud.name = "energy"
|
||||
energyhud.screen_loc = "CENTER+1:16,SOUTH:5" //Right of the right hand
|
||||
energyhud.alpha = 150
|
||||
hud_elements |= energyhud
|
||||
|
||||
// When someone clicks us with an empty hand
|
||||
/mob/living/simple_mob/shadekin/attack_hand(mob/living/carbon/human/M as mob)
|
||||
. = ..()
|
||||
|
||||
@@ -56,17 +56,26 @@
|
||||
The hot goop you float in makes it hard to breathe; all consuming of space and light. \
|
||||
Your body feels hot, growing weaker, more tired. Draining. Darkness coming. \
|
||||
You struggle to stay awake while floating helplessly in the goo."
|
||||
player_msg = "You are Rakshasa. You are not to directly harm crew, only consume. You never speak a language."
|
||||
player_msg = "You are Rakshasa. You are not to directly harm crew, only consume. You never speak a language. You have special emotes: 'evillaugh', 'evilno', 'evilbreath', 'evilbreath2', and 'goodripsound'"
|
||||
maxHealth = 1000000000000
|
||||
health = 1000000000000
|
||||
eye_state = "BLUE EYES"
|
||||
eye_icon_state = "e_rakshasa"
|
||||
comp = /datum/component/shadekin/full/rakshasa
|
||||
|
||||
/mob/living/simple_mob/shadekin/red/rakshasa/Initialize(mapload)
|
||||
. = ..()
|
||||
if(comp)
|
||||
comp.dark_energy_infinite = TRUE
|
||||
|
||||
/mob/living/simple_mob/shadekin/red/rakshasa/get_available_emotes()
|
||||
. = global._simple_mob_default_emotes.Copy()
|
||||
. += /decl/emote/audible/evil_laugh
|
||||
. += /decl/emote/audible/evil_no
|
||||
. += /decl/emote/audible/evil_breathing
|
||||
. += /decl/emote/audible/evil_breathing_2
|
||||
. += /decl/emote/audible/goodripsound
|
||||
|
||||
/mob/living/simple_mob/shadekin/blue/luna
|
||||
name = "Luna"
|
||||
desc = "She appears to be a fuzzy critter of some sort. Her eyes shimmer a dark blue, glancing around curiously."
|
||||
|
||||
@@ -409,6 +409,7 @@ var/global/list/light_type_cache = list()
|
||||
else
|
||||
base_state = "flamp"
|
||||
..()
|
||||
|
||||
/obj/machinery/light/proc/set_alert_atmos()
|
||||
if(!shows_alerts)
|
||||
return
|
||||
@@ -736,27 +737,35 @@ var/global/list/light_type_cache = list()
|
||||
set_light(brightness_range * bulb_emergency_brightness_mul, max(bulb_emergency_pow_min, bulb_emergency_pow_mul * (cell.charge / cell.maxcharge)), bulb_emergency_colour)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
|
||||
/obj/machinery/light/proc/flicker(var/amount = rand(10, 20), var/flicker_color)
|
||||
if(flickering) return
|
||||
if(on && status == LIGHT_OK)
|
||||
flickering = 1
|
||||
do_flicker(amount)
|
||||
do_flicker(amount, flicker_color, brightness_color, brightness_color_ns)
|
||||
|
||||
/obj/machinery/light/proc/do_flicker(remaining_flicks)
|
||||
/obj/machinery/light/proc/do_flicker(remaining_flicks, flicker_color, original_color, original_color_ns)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
PRIVATE_PROC(TRUE)
|
||||
if(status != LIGHT_OK)
|
||||
flickering = 0
|
||||
return
|
||||
on = !on
|
||||
if(flicker_color && brightness_color != flicker_color)
|
||||
brightness_color = flicker_color
|
||||
brightness_color_ns = flicker_color
|
||||
update(0) //Yes. This is done here and then immediately followed up with another update(0). Why does it need that? I have no clue. But a single update(0) does not work.
|
||||
update(0)
|
||||
if(!on) // Only play when the light turns off.
|
||||
playsound(src, 'sound/effects/light_flicker.ogg', 50, 1)
|
||||
if(remaining_flicks > 0)
|
||||
remaining_flicks--
|
||||
addtimer(CALLBACK(src, PROC_REF(do_flicker), remaining_flicks), rand(5, 15), TIMER_DELETE_ME)
|
||||
addtimer(CALLBACK(src, PROC_REF(do_flicker), remaining_flicks, flicker_color, original_color, original_color_ns), rand(5, 15), TIMER_DELETE_ME)
|
||||
return
|
||||
//All this happens after our final flicker.
|
||||
on = (status == LIGHT_OK)
|
||||
brightness_color = original_color
|
||||
brightness_color_ns = original_color_ns
|
||||
update(0)
|
||||
update(0)
|
||||
flickering = 0
|
||||
|
||||
|
||||
@@ -174,46 +174,46 @@
|
||||
/obj/item/gun/proc/special_check(var/mob/user)
|
||||
|
||||
if(!isliving(user))
|
||||
return 0
|
||||
return FALSE
|
||||
if(!user.IsAdvancedToolUser())
|
||||
return 0
|
||||
return FALSE
|
||||
if(isanimal(user))
|
||||
var/mob/living/simple_mob/S = user
|
||||
if(!S.IsHumanoidToolUser(src))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/mob/living/M = user
|
||||
if(istype(M))
|
||||
if(M.has_modifier_of_type(/datum/modifier/underwater_stealth))
|
||||
to_chat(user,span_warning("You cannot use guns whilst hiding underwater!"))
|
||||
return 0
|
||||
to_chat(user, span_warning("You cannot use guns whilst hiding underwater!"))
|
||||
return FALSE
|
||||
else if(M.has_modifier_of_type(/datum/modifier/phased_out))
|
||||
to_chat(user, span_warning("You cannot use guns whilst incorporeal!"))
|
||||
return FALSE
|
||||
else if(M.has_modifier_of_type(/datum/modifier/rednet))
|
||||
to_chat(user,span_warning("Your gun refuses to fire!"))
|
||||
return 0
|
||||
to_chat(user, span_warning("Your gun refuses to fire!"))
|
||||
return FALSE
|
||||
else if(M.has_modifier_of_type(/datum/modifier/trait/thickdigits))
|
||||
to_chat(user,span_warning("Your hands can't pull the trigger!!"))
|
||||
return 0
|
||||
to_chat(user, span_warning("Your hands can't pull the trigger!!"))
|
||||
return FALSE
|
||||
else if(M.has_modifier_of_type(/datum/modifier/shield_projection/melee_focus))
|
||||
to_chat(user,span_warning("The shield projection around you prevents you from using anything but melee!!"))
|
||||
return 0
|
||||
to_chat(user, span_warning("The shield projection around you prevents you from using anything but melee!!"))
|
||||
return FALSE
|
||||
if(dna_lock && attached_lock.stored_dna)
|
||||
if(!authorized_user(user))
|
||||
if(attached_lock.safety_level == 0)
|
||||
to_chat(M, span_danger("\The [src] buzzes in dissapointment and displays an invalid DNA symbol."))
|
||||
return 0
|
||||
return FALSE
|
||||
if(!attached_lock.exploding)
|
||||
if(attached_lock.safety_level == 1)
|
||||
to_chat(M, span_danger("\The [src] hisses in dissapointment."))
|
||||
visible_message(span_game(span_say(span_name("\The [src]") + " announces, \"Self-destruct occurring in ten seconds.\"")), span_game(span_say(span_name("\The [src]") + " announces, \"Self-destruct occurring in ten seconds.\"")))
|
||||
attached_lock.exploding = 1
|
||||
spawn(100)
|
||||
explosion(src, 0, 0, 3, 4)
|
||||
sleep(1)
|
||||
qdel(src)
|
||||
return 0
|
||||
addtimer(CALLBACK(src, PROC_REF(lock_explosion)), 10 SECONDS, TIMER_DELETE_ME)
|
||||
return FALSE
|
||||
if(HULK in M.mutations)
|
||||
to_chat(M, span_danger("Your fingers are much too large for the trigger guard!"))
|
||||
return 0
|
||||
return FALSE
|
||||
if((CLUMSY in M.mutations) && prob(40)) //Clumsy handling
|
||||
var/obj/P = consume_next_projectile()
|
||||
if(P)
|
||||
@@ -227,8 +227,12 @@
|
||||
M.drop_item()
|
||||
else
|
||||
handle_click_empty(user)
|
||||
return 0
|
||||
return 1
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/gun/proc/lock_explosion()
|
||||
explosion(src, 0, 0, 3, 4)
|
||||
QDEL_IN(src, 1)
|
||||
|
||||
/obj/item/gun/emp_act(severity)
|
||||
for(var/obj/O in contents)
|
||||
|
||||
@@ -53,9 +53,11 @@
|
||||
return 1
|
||||
|
||||
/obj/structure/table/MouseDrop_T(obj/O, mob/user, src_location, over_location, src_control, over_control, params)
|
||||
if(user.is_incorporeal())
|
||||
if(user.stat)
|
||||
return
|
||||
if(ismob(O.loc)) //If placing an item
|
||||
if(can_reinforce && isliving(user) && istype(O, /obj/item/stack/material) && user.get_active_hand() == O && Adjacent(user))
|
||||
reinforce_table(O, user)
|
||||
else if(ismob(O.loc)) //If placing an item
|
||||
if(!isitem(O) || user.get_active_hand() != O)
|
||||
return ..()
|
||||
if(isrobot(user))
|
||||
|
||||
@@ -193,12 +193,6 @@ var/list/table_icon_cache = list()
|
||||
visible_message(span_infoplain(span_bold("\The [user]") + " scratches at \the [src]!"))
|
||||
return ..()
|
||||
|
||||
/obj/structure/table/MouseDrop_T(obj/item/stack/material/what, mob/user)
|
||||
if(can_reinforce && isliving(user) && (!user.stat) && istype(what) && user.get_active_hand() == what && Adjacent(user))
|
||||
reinforce_table(what, user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/table/proc/reinforce_table(obj/item/stack/material/S, mob/user)
|
||||
if(reinforced)
|
||||
to_chat(user, span_warning("\The [src] is already reinforced!"))
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,47 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"B" = (
|
||||
/turf/simulated/floor/weird_things/dark,
|
||||
/area/template_noop)
|
||||
"O" = (
|
||||
/obj/structure/dark_portal/minion,
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
|
||||
(1,1,1) = {"
|
||||
a
|
||||
B
|
||||
B
|
||||
a
|
||||
a
|
||||
"}
|
||||
(2,1,1) = {"
|
||||
B
|
||||
a
|
||||
B
|
||||
B
|
||||
B
|
||||
"}
|
||||
(3,1,1) = {"
|
||||
B
|
||||
B
|
||||
O
|
||||
B
|
||||
a
|
||||
"}
|
||||
(4,1,1) = {"
|
||||
B
|
||||
B
|
||||
B
|
||||
B
|
||||
a
|
||||
"}
|
||||
(5,1,1) = {"
|
||||
B
|
||||
a
|
||||
B
|
||||
B
|
||||
a
|
||||
"}
|
||||
@@ -57,13 +57,11 @@
|
||||
last_pulse = world.time
|
||||
use_power(1500)
|
||||
|
||||
for (var/mob/O in viewers(src, null))
|
||||
if(get_dist(src, O) > range)
|
||||
for(var/mob/living/O in range(range, src))
|
||||
var/datum/component/shadekin/SK = O.get_shadekin_component()
|
||||
if(!SK)
|
||||
continue
|
||||
if(ishuman(O))
|
||||
var/mob/living/carbon/human/H = O
|
||||
if(H.get_species() == SPECIES_SHADEKIN && (H.ability_flags & AB_PHASE_SHIFTED))
|
||||
H.attack_dephase(null, src)
|
||||
SK.attack_dephase(null, src) //Won't dephase them if they're not in phase. It has built in checks.
|
||||
|
||||
/obj/machinery/bluespace_denier/emp_act(severity)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
|
||||
@@ -2,8 +2,3 @@
|
||||
GLOBAL_LIST_INIT(shell_module_blacklist, list(
|
||||
"Sci-borg", "Research"
|
||||
))
|
||||
GLOBAL_LIST_EMPTY(latejoin_gatewaystation)
|
||||
GLOBAL_LIST_EMPTY(latejoin_plainspath)
|
||||
GLOBAL_LIST_EMPTY(latejoin_fueldepot)
|
||||
GLOBAL_LIST_EMPTY(latejoin_tyrvillage)
|
||||
GLOBAL_LIST_EMPTY(latejoin_thedark)
|
||||
|
||||
-386
@@ -1,386 +0,0 @@
|
||||
/mob/living/carbon/human/proc/shadekin_ability_check()
|
||||
var/datum/species/shadekin/SK = species
|
||||
if(!istype(SK))
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
|
||||
if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
|
||||
if((ability_flags & AB_DARK_RESPITE || has_modifier_of_type(/datum/modifier/dark_respite)) && !(ability_flags & AB_PHASE_SHIFTED))
|
||||
to_chat(src, span_warning("You can't use that so soon after an emergency warp!"))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//toggle proc for toggling gentle/normal phasing
|
||||
/mob/living/carbon/human/proc/phase_strength_toggle()
|
||||
set name = "Toggle Phase Strength"
|
||||
set desc = "Toggle strength of phase. Gentle but slower, or faster but destructive to lights."
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/datum/species/shadekin/SK = species
|
||||
if(!istype(SK))
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
|
||||
if(SK.phase_gentle)
|
||||
to_chat(src, span_notice("Phasing toggled to Normal. You may damage lights."))
|
||||
SK.phase_gentle = 0
|
||||
else
|
||||
to_chat(src, span_notice("Phasing toggled to Gentle. You won't damage lights, but concentrating on that incurs a short stun."))
|
||||
SK.phase_gentle = 1
|
||||
|
||||
/datum/power/shadekin/dark_tunneling
|
||||
name = "Dark Tunneling (100) (Once)"
|
||||
desc = "Make a passage to the dark."
|
||||
verbpath = /mob/living/carbon/human/proc/dark_tunneling
|
||||
ability_icon_state = "minion0"
|
||||
|
||||
/mob/living/carbon/human/proc/dark_tunneling()
|
||||
set name = "Dark Tunneling (100) (Once)"
|
||||
set desc = "Make a passage to the dark."
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/template_id = "dark_portal"
|
||||
var/datum/map_template/shelter/template
|
||||
|
||||
var/ability_cost = 100
|
||||
var/tunnel_time = 60 SECONDS
|
||||
|
||||
if(!shadekin_ability_check())
|
||||
return FALSE
|
||||
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
to_chat(src, span_warning("You can't use that while phase shifted!"))
|
||||
return FALSE
|
||||
|
||||
if(ability_flags & AB_DARK_TUNNEL)
|
||||
to_chat(src, span_warning("You have already made a tunnel to the Dark!"))
|
||||
return FALSE
|
||||
|
||||
if(!template)
|
||||
template = SSmapping.shelter_templates[template_id]
|
||||
if(!template)
|
||||
throw EXCEPTION("Shelter template ([template_id]) not found!")
|
||||
return FALSE
|
||||
|
||||
var/turf/deploy_location = get_turf(src)
|
||||
var/status = template.check_deploy(deploy_location)
|
||||
|
||||
switch(status)
|
||||
//Not allowed due to /area technical reasons
|
||||
if(SHELTER_DEPLOY_BAD_AREA)
|
||||
to_chat(src, span_warning("A tunnel to the Dark will not function in this area."))
|
||||
|
||||
//Anchored objects or no space
|
||||
if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS)
|
||||
var/width = template.width
|
||||
var/height = template.height
|
||||
to_chat(src, span_warning("There is not enough open area for a tunnel to the Dark to form! You need to clear a [width]x[height] area!"))
|
||||
|
||||
if(status != SHELTER_DEPLOY_ALLOWED)
|
||||
return FALSE
|
||||
|
||||
var/turf/T = deploy_location
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.attach(T)
|
||||
smoke.set_up(10, 0, T)
|
||||
smoke.start()
|
||||
|
||||
src.visible_message(span_notice("[src] begins pulling dark energies around themselves."))
|
||||
if(do_after(src, tunnel_time))
|
||||
playsound(src, 'sound/effects/phasein.ogg', 100, 1)
|
||||
src.visible_message(span_notice("[src] finishes pulling dark energies around themselves, creating a portal."))
|
||||
|
||||
log_and_message_admins("[key_name_admin(src)] created a tunnel to the dark at [get_area(T)]!")
|
||||
template.annihilate_plants(deploy_location)
|
||||
template.load(deploy_location, centered = TRUE)
|
||||
template.update_lighting(deploy_location)
|
||||
ability_flags |= AB_DARK_TUNNEL
|
||||
shadekin_adjust_energy(-(ability_cost - 10)) //Leaving enough energy to actually activate the portal
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/power/shadekin/dark_respite
|
||||
name = "Dark Respite (Only in Dark)"
|
||||
desc = "Focus yourself on healing any injuries sustained."
|
||||
verbpath = /mob/living/carbon/human/proc/dark_respite
|
||||
ability_icon_state = "ling_anatomic_panacea"
|
||||
|
||||
/mob/living/carbon/human/proc/dark_respite()
|
||||
set name = "Dark Respite (Only in Dark)"
|
||||
set desc = "Focus yourself on healing any injuries sustained."
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/datum/species/shadekin/SK = species
|
||||
if(!istype(SK))
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
|
||||
if(!istype(get_area(src), /area/shadekin))
|
||||
to_chat(src, span_warning("Can only trigger Dark Respite in the Dark!"))
|
||||
return FALSE
|
||||
|
||||
if(stat)
|
||||
to_chat(src, span_warning("Can't use that ability in your state!"))
|
||||
return FALSE
|
||||
|
||||
if(ability_flags & AB_DARK_RESPITE)
|
||||
to_chat(src, span_warning("You can't use that so soon after an emergency warp!"))
|
||||
return FALSE
|
||||
|
||||
if(has_modifier_of_type(/datum/modifier/dark_respite) && !SK.manual_respite)
|
||||
to_chat(src, span_warning("You cannot manually end a Dark Respite triggered by an emergency warp!"))
|
||||
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
to_chat(src, span_warning("You can't use that while phase shifted!"))
|
||||
return FALSE
|
||||
|
||||
if(has_modifier_of_type(/datum/modifier/dark_respite))
|
||||
to_chat(src, span_notice("You stop focusing the Dark on healing yourself."))
|
||||
SK.manual_respite = FALSE
|
||||
remove_a_modifier_of_type(/datum/modifier/dark_respite)
|
||||
return TRUE
|
||||
to_chat(src, span_notice("You start focusing the Dark on healing yourself. (Leave the dark or trigger the ability again to end this.)"))
|
||||
SK.manual_respite = TRUE
|
||||
add_modifier(/datum/modifier/dark_respite)
|
||||
return TRUE
|
||||
|
||||
/datum/map_template/shelter/dark_portal
|
||||
name = "Dark Portal"
|
||||
shelter_id = "dark_portal"
|
||||
description = "A portal to a section of the Dark"
|
||||
mappath = "modular_chomp/maps/submaps/shelters/dark_portal.dmm"
|
||||
|
||||
/datum/map_template/shelter/dark_portal/New()
|
||||
. = ..()
|
||||
blacklisted_turfs = typecacheof(list(/turf/unsimulated))
|
||||
GLOB.blacklisted_areas = typecacheof(list(/area/centcom, /area/shadekin))
|
||||
|
||||
/obj/effect/abstract/dark_maw
|
||||
var/mob/living/owner = null
|
||||
var/obj/belly/target = null
|
||||
icon = 'modular_chomp/icons/obj/Shadekin_powers_2.dmi'
|
||||
icon_state = "dark_maw_waiting"
|
||||
|
||||
/obj/effect/abstract/dark_maw/Initialize(mapload, var/mob/living/user, var/trigger_now = 0)
|
||||
. = ..()
|
||||
|
||||
if(!isturf(loc))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
var/turf/T = loc
|
||||
if(T.get_lumcount() >= 0.5)
|
||||
visible_message(span_notice("A set of shadowy lines flickers away in the light."))
|
||||
icon_state = "dark_maw_used"
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
if(istype(user))
|
||||
owner = user
|
||||
target = owner.vore_selected
|
||||
|
||||
var/mob/living/target_user = null
|
||||
for(var/mob/living/L in T)
|
||||
if(L != owner && !L.incorporeal_move)
|
||||
target_user = L
|
||||
break
|
||||
|
||||
if(istype(target_user))
|
||||
triggered_by(target_user, 1)
|
||||
// to trigger rebuild
|
||||
else if(trigger_now)
|
||||
icon_state = "dark_maw_used"
|
||||
flick("dark_maw_tr", src)
|
||||
visible_message(span_warning("A set of crystals suddenly springs from the ground and shadowy tendrils wrap around nothing before vanishing."))
|
||||
QDEL_IN(src, 3 SECONDS)
|
||||
else
|
||||
var/mob/living/carbon/human/carbon_owner = owner
|
||||
var/mob/living/simple_mob/shadekin/sm_owner = owner
|
||||
if(istype(carbon_owner))
|
||||
var/datum/species/shadekin/SK = carbon_owner.species
|
||||
if(istype(SK))
|
||||
SK.active_dark_maws += src
|
||||
else if(istype(sm_owner))
|
||||
sm_owner.active_dark_maws += src
|
||||
flick("dark_maw", src)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/effect/abstract/dark_maw/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(istype(owner))
|
||||
var/mob/living/carbon/human/carbon_owner = owner
|
||||
var/mob/living/simple_mob/shadekin/sm_owner = owner
|
||||
if(istype(carbon_owner))
|
||||
var/datum/species/shadekin/SK = carbon_owner.species
|
||||
if(istype(SK))
|
||||
SK.active_dark_maws -= src
|
||||
else if(istype(sm_owner))
|
||||
sm_owner.active_dark_maws -= src
|
||||
target = null
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/obj/effect/abstract/dark_maw/Crossed(O)
|
||||
. = ..()
|
||||
if(!isliving(O))
|
||||
return
|
||||
if(icon_state != "dark_maw_waiting")
|
||||
return
|
||||
var/mob/living/L = O
|
||||
if(!L.incorporeal_move && (!owner || L != owner))
|
||||
triggered_by(L)
|
||||
|
||||
/obj/effect/abstract/dark_maw/process()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T) || T.get_lumcount() >= 0.5)
|
||||
dispel()
|
||||
|
||||
/obj/effect/abstract/dark_maw/proc/dispel()
|
||||
if(icon_state == "dark_maw_waiting")
|
||||
visible_message(span_notice("A set of shadowy lines flickers away in the light."))
|
||||
else
|
||||
visible_message(span_notice("The crystals and shadowy tendrils dissipate with the light shone on it."))
|
||||
icon_state = "dark_maw_used"
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/abstract/dark_maw/proc/triggered_by(var/mob/living/L, var/triggered_instantly = 0)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
icon_state = "dark_maw_used"
|
||||
flick("dark_maw_tr", src)
|
||||
L.AdjustStunned(4)
|
||||
visible_message(span_warning("A set of crystals spring out of the ground and shadowy tendrils start wrapping around [L]."))
|
||||
if(owner && !triggered_instantly)
|
||||
to_chat(owner, span_warning("A dark maw you deployed has triggered!"))
|
||||
addtimer(CALLBACK(src, PROC_REF(do_trigger), L), 1 SECOND, TIMER_DELETE_ME)
|
||||
|
||||
/obj/effect/abstract/dark_maw/proc/do_trigger(var/mob/living/L)
|
||||
var/will_vore = 1
|
||||
|
||||
if(!owner || !(target in owner) || !L.devourable || !L.can_be_drop_prey || !owner.can_be_drop_pred || !L.phase_vore)
|
||||
will_vore = 0
|
||||
|
||||
if(!src || src.gc_destroyed)
|
||||
//We got deleted probably, do nothing more
|
||||
return
|
||||
|
||||
if(L.loc != get_turf(src))
|
||||
visible_message(span_notice("The shadowy tendrils fail to catch anything and dissipate."))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(will_vore)
|
||||
visible_message(span_warning("The shadowy tendrils grab around [L] and drag them into the floor, leaving nothing behind."))
|
||||
L.forceMove(target)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
var/obj/effect/energy_net/dark/net = new /obj/effect/energy_net/dark(get_turf(src))
|
||||
if(net.buckle_mob(L))
|
||||
visible_message(span_warning("The shadowy tendrils wrap around [L] and traps them in a net of dark energy."))
|
||||
else
|
||||
visible_message(span_notice("The shadowy tendrils wrap around [L] and then dissipate, leaving them in place."))
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/energy_net/dark
|
||||
name = "dark net"
|
||||
desc = "It's a net made of dark energy."
|
||||
icon = 'modular_chomp/icons/obj/Shadekin_powers_2.dmi'
|
||||
icon_state = "dark_net"
|
||||
|
||||
escape_time = 30 SECONDS
|
||||
|
||||
/obj/effect/energy_net/dark/user_unbuckle_mob(mob/living/buckled_mob, mob/user)
|
||||
if(istype(user,/mob/living/simple_mob/shadekin))
|
||||
visible_message(span_danger("[user] dissipates \the [src] with a touch!"))
|
||||
unbuckle_mob(buckled_mob)
|
||||
return
|
||||
|
||||
if(istype(user,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/datum/species/shadekin/SK = H.species
|
||||
if(istype(SK))
|
||||
visible_message(span_danger("[user] dissipates \the [src] with a touch!"))
|
||||
unbuckle_mob(buckled_mob)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/effect/energy_net/dark/process()
|
||||
. = ..()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T) || T.get_lumcount() >= 0.6)
|
||||
visible_message(span_notice("The tangle of dark tendrils fades away in the light."))
|
||||
qdel(src)
|
||||
|
||||
/datum/power/shadekin/dark_maw
|
||||
name = "Dark Maw (20)"
|
||||
desc = "Create a trap to capture others, or steal people from phase"
|
||||
verbpath = /mob/living/carbon/human/proc/dark_maw
|
||||
ability_icon_state = "dark_maw_ic"
|
||||
|
||||
/mob/living/carbon/human/proc/dark_maw()
|
||||
set name = "Dark Maw (20)"
|
||||
set desc = "Create a trap to capture others, or steal people from phase"
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/ability_cost = 20
|
||||
|
||||
if(!shadekin_ability_check())
|
||||
return FALSE
|
||||
|
||||
if(shadekin_get_energy() < ability_cost)
|
||||
to_chat(src, span_warning("Not enough energy for that ability!"))
|
||||
return FALSE
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
to_chat(src, span_warning("You don't seem to be able to set a trap here!"))
|
||||
return FALSE
|
||||
|
||||
if(T.get_lumcount() >= 0.5)
|
||||
to_chat(src, span_warning("There is too much light here for your trap to last!"))
|
||||
return FALSE
|
||||
|
||||
if(do_after(src, 10))
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
new /obj/effect/abstract/dark_maw(loc, src, 1)
|
||||
else
|
||||
new /obj/effect/abstract/dark_maw(loc, src)
|
||||
shadekin_adjust_energy(-ability_cost)
|
||||
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/proc/clear_dark_maws()
|
||||
set name = "Dispel dark maws"
|
||||
set desc = "Dispel any active dark maws in place"
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/datum/species/shadekin/SK = species
|
||||
if(!istype(SK))
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
|
||||
for(var/obj/effect/abstract/dark_maw/dm in SK.active_dark_maws)
|
||||
dm.dispel()
|
||||
|
||||
/mob/living/carbon/human/proc/nutrition_conversion_toggle()
|
||||
set name = "Toggle Energy <-> Nutrition conversions"
|
||||
set desc = "Toggle dark energy and nutrition being converted into each other when full"
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
var/datum/species/shadekin/SK = species
|
||||
if(!istype(SK))
|
||||
to_chat(src, span_warning("Only a shadekin can use that!"))
|
||||
return FALSE
|
||||
|
||||
if(SK.nutrition_energy_conversion)
|
||||
to_chat(src, span_notice("Nutrition and dark energy conversions disabled."))
|
||||
SK.nutrition_energy_conversion = 0
|
||||
else
|
||||
to_chat(src, span_notice("Nutrition and dark energy conversions enabled."))
|
||||
SK.nutrition_energy_conversion = 1
|
||||
|
||||
/datum/modifier/shadekin_phase
|
||||
name = "Shadekin Phasing"
|
||||
evasion = 100
|
||||
@@ -1,113 +0,0 @@
|
||||
/mob/living/simple_mob/shadekin
|
||||
var/phase_gentle = 0
|
||||
|
||||
/mob/living/simple_mob/shadekin/Login()
|
||||
. = ..()
|
||||
add_verb(src,/mob/living/simple_mob/shadekin/proc/phase_strength_toggle)
|
||||
|
||||
/mob/living/simple_mob/shadekin/proc/dark_tunneling()
|
||||
var/template_id = "dark_portal"
|
||||
var/datum/map_template/shelter/template
|
||||
|
||||
if(!template)
|
||||
template = SSmapping.shelter_templates[template_id]
|
||||
if(!template)
|
||||
throw EXCEPTION("Shelter template ([template_id]) not found!")
|
||||
return FALSE
|
||||
|
||||
var/turf/deploy_location = get_turf(src)
|
||||
var/status = template.check_deploy(deploy_location)
|
||||
|
||||
switch(status)
|
||||
//Not allowed due to /area technical reasons
|
||||
if(SHELTER_DEPLOY_BAD_AREA)
|
||||
to_chat(src, span_warning("A tunnel to the Dark will not function in this area."))
|
||||
|
||||
//Anchored objects or no space
|
||||
if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS)
|
||||
var/width = template.width
|
||||
var/height = template.height
|
||||
to_chat(src, span_warning("There is not enough open area for a tunnel to the Dark to form! You need to clear a [width]x[height] area!"))
|
||||
|
||||
if(status != SHELTER_DEPLOY_ALLOWED)
|
||||
return FALSE
|
||||
|
||||
var/turf/T = deploy_location
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.attach(T)
|
||||
smoke.set_up(10, 0, T)
|
||||
smoke.start()
|
||||
|
||||
src.visible_message(span_notice("[src] begins pulling dark energies around themselves."))
|
||||
if(do_after(src, 600)) //60 seconds
|
||||
playsound(src, 'sound/effects/phasein.ogg', 100, 1)
|
||||
src.visible_message(span_notice("[src] finishes pulling dark energies around themselves, creating a portal."))
|
||||
|
||||
log_and_message_admins("[key_name_admin(src)] created a tunnel to the dark at [get_area(T)]!")
|
||||
template.annihilate_plants(deploy_location)
|
||||
template.load(deploy_location, centered = TRUE)
|
||||
template.update_lighting(deploy_location)
|
||||
ability_flags &= AB_DARK_TUNNEL
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_mob/shadekin/proc/dark_maw()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
to_chat(src, span_warning("You don't seem to be able to set a trap here!"))
|
||||
return FALSE
|
||||
else if(T.get_lumcount() >= 0.5)
|
||||
to_chat(src, span_warning("There is too much light here for your trap to last!"))
|
||||
return FALSE
|
||||
|
||||
if(do_after(src, 10))
|
||||
if(ability_flags & AB_PHASE_SHIFTED)
|
||||
new /obj/effect/abstract/dark_maw(loc, src, 1)
|
||||
else
|
||||
new /obj/effect/abstract/dark_maw(loc, src)
|
||||
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
// Allow horizontal resting
|
||||
/mob/living/simple_mob/shadekin/update_transform()
|
||||
update_transform_horizontal()
|
||||
|
||||
//custom light flicker proc
|
||||
/mob/living/simple_mob/shadekin/proc/handle_phasein_flicker()
|
||||
if(phase_gentle) // gentle case: No light destruction. Flicker in 4 tile radius for 3s. Weaken for 3sec after
|
||||
for(var/obj/machinery/light/L in GLOB.machines)
|
||||
if(L.z != z || get_dist(src,L) > 4)
|
||||
continue
|
||||
L.flicker(3)
|
||||
src.Stun(3)
|
||||
else //normal case. Flicker in 10 tile radius for 10s. chance to destroy light based on eye type.
|
||||
var/destroy_lights = 0
|
||||
if(eye_state == RED_EYES)
|
||||
destroy_lights = 80
|
||||
if(eye_state == PURPLE_EYES)
|
||||
destroy_lights = 25
|
||||
|
||||
for(var/obj/machinery/light/L in GLOB.machines)
|
||||
if(L.z != z || get_dist(src,L) > 10)
|
||||
continue
|
||||
|
||||
if(prob(destroy_lights))
|
||||
addtimer(CALLBACK(L, TYPE_PROC_REF(/obj/machinery/light, broken)), rand(5,25), TIMER_DELETE_ME)
|
||||
else
|
||||
L.flicker(10)
|
||||
|
||||
//toggle proc for toggling gentle/normal phasing
|
||||
/mob/living/simple_mob/shadekin/proc/phase_strength_toggle()
|
||||
set name = "Toggle Phase Strength"
|
||||
set desc = "Toggle strength of phase. Gentle but slower, or faster but destructive to lights."
|
||||
set category = "Abilities.Shadekin"
|
||||
|
||||
if(phase_gentle)
|
||||
to_chat(src, span_notice("Phasing toggled to Normal. You may damage lights."))
|
||||
phase_gentle = 0
|
||||
else
|
||||
to_chat(src, span_notice("Phasing toggled to Gentle. You won't damage lights, but concentrating on that incurs a short stun."))
|
||||
phase_gentle = 1
|
||||
@@ -1,24 +1,24 @@
|
||||
// This proc turns the BSC or arti-BSC into a phased-creature mine.
|
||||
/obj/item/bluespace_crystal/Crossed(atom/movable/M)
|
||||
. = ..()
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.get_species() == SPECIES_SHADEKIN && (H.ability_flags & AB_PHASE_SHIFTED))
|
||||
if(istype(M, /mob/living))
|
||||
var/mob/living/L = M
|
||||
var/datum/component/shadekin/SK = L.get_shadekin_component()
|
||||
if(SK && SK.in_phase)
|
||||
var/turf/T = get_turf(src)
|
||||
visible_message(span_notice("[src] fizzles and disappears as something interacts with it!"))
|
||||
playsound(src, pick('sound/effects/Glassbr1.ogg', 'sound/effects/Glassbr2.ogg', 'sound/effects/Glassbr3.ogg'), 50, 1)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
s.set_up(5, 1, T)
|
||||
s.start()
|
||||
H.attack_dephase(T, src)
|
||||
SK.attack_dephase(T, src)
|
||||
qdel(src)
|
||||
|
||||
|
||||
// This proc is the 'Dephase grenade' check. range is changeable. 0=self, 1=3x3, 2=5x5, 3=7x7...
|
||||
/obj/item/bluespace_crystal/proc/dephase_shadekin()
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/thing in range(3, T))
|
||||
if(istype(thing, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(H.get_species() == SPECIES_SHADEKIN && (H.ability_flags & AB_PHASE_SHIFTED))
|
||||
H.attack_dephase(null, src)
|
||||
for(var/mob/living/living in range(3, T))
|
||||
var/datum/component/shadekin/SK = living.get_shadekin_component()
|
||||
if(SK && SK.in_phase)
|
||||
SK.attack_dephase(null, src)
|
||||
|
||||
@@ -17,20 +17,6 @@
|
||||
. = ..()
|
||||
GLOB.blacklisted_areas = typecacheof(list(/area/centcom, /area/shadekin, /area/vr))
|
||||
|
||||
/mob/living/carbon/human/shadekin_ability_check()
|
||||
. = ..()
|
||||
if(. && istype(get_area(src), /area/vr))
|
||||
to_chat(src, span_danger("The VR systems cannot comprehend this power! This is useless to you!"))
|
||||
. = FALSE
|
||||
|
||||
/obj/effect/shadekin_ability/dark_tunneling/do_ability()
|
||||
if(istype(get_area(my_kin), /area/vr))
|
||||
to_chat(my_kin, span_danger("The VR systems cannot comprehend this power! This is useless to you!"))
|
||||
return FALSE
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/disposable_teleporter/attack_self(mob/user as mob)//Prevents people from using technomancer gear to escape to station from the VR pods.
|
||||
if(istype(get_area(user), /area/vr))
|
||||
to_chat(user, span_danger("\The [src] does not appear to work in VR! This is useless to you!"))
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,132 @@
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Window } from 'tgui/layouts';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ColorBox,
|
||||
LabeledList,
|
||||
NoticeBox,
|
||||
NumberInput,
|
||||
Section,
|
||||
Stack,
|
||||
Tooltip,
|
||||
} from 'tgui-core/components';
|
||||
|
||||
type Data = {
|
||||
stun_time: number;
|
||||
flicker_time: number;
|
||||
flicker_color: string | null;
|
||||
flicker_break_chance: number;
|
||||
flicker_distance: number;
|
||||
};
|
||||
|
||||
export const ShadekinConfig = (props) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
|
||||
const {
|
||||
stun_time,
|
||||
flicker_time,
|
||||
flicker_color,
|
||||
flicker_break_chance,
|
||||
flicker_distance,
|
||||
} = data;
|
||||
|
||||
const isSubtle =
|
||||
flicker_time < 5 || flicker_break_chance < 5 || flicker_distance < 5;
|
||||
|
||||
return (
|
||||
<Window width={300} height={isSubtle ? 220 : 190} theme="abductor">
|
||||
<Window.Content>
|
||||
<Stack fill vertical g={0}>
|
||||
{isSubtle && (
|
||||
<Stack.Item>
|
||||
<NoticeBox>Subtle Phasing, causes {stun_time} s stun.</NoticeBox>
|
||||
</Stack.Item>
|
||||
)}
|
||||
<Stack.Item>
|
||||
<Section fill title="Shadekin Settings">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Flicker Count">
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<NumberInput
|
||||
step={1}
|
||||
minValue={2}
|
||||
maxValue={20}
|
||||
value={flicker_time}
|
||||
onChange={(value) => act('adjust_time', { val: value })}
|
||||
unit="x"
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Tooltip content="Adjust how long lights flicker when you phase in! (Min 10 Max 20 times!)">
|
||||
<Box className="VorePanel__floatingButton">?</Box>
|
||||
</Tooltip>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Flicker Color">
|
||||
<Stack align="center">
|
||||
<Stack.Item>
|
||||
<Button
|
||||
onClick={() => act('adjust_color')}
|
||||
tooltip="Select a color you wish the lights to flicker as (Default is #E0EFF0)"
|
||||
>
|
||||
Set Color
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<ColorBox color={flicker_color || '#E0EFF0'} />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Flicker Light Break Chance">
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<NumberInput
|
||||
step={1}
|
||||
minValue={0}
|
||||
maxValue={25}
|
||||
value={flicker_break_chance}
|
||||
onChange={(value) =>
|
||||
act('adjust_break', { val: value })
|
||||
}
|
||||
unit="%"
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Tooltip content="Adjust the % chance for lights to break when you phase in! (Default 0. Min 0. Max 25)">
|
||||
<Box className="VorePanel__floatingButton">?</Box>
|
||||
</Tooltip>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Flicker Distance">
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<NumberInput
|
||||
step={1}
|
||||
minValue={4}
|
||||
maxValue={10}
|
||||
value={flicker_distance}
|
||||
onChange={(value) =>
|
||||
act('adjust_distance', { val: value })
|
||||
}
|
||||
unit="tiles"
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Tooltip content="Adjust the range in which lights flicker when you phase in! (Default 4. Min 4. Max 10)">
|
||||
<Box className="VorePanel__floatingButton">?</Box>
|
||||
</Tooltip>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
+10
-6
@@ -611,8 +611,16 @@
|
||||
#include "code\datums\components\reagent_hose\datum.dm"
|
||||
#include "code\datums\components\reagent_hose\inflation.dm"
|
||||
#include "code\datums\components\reagent_hose\item.dm"
|
||||
#include "code\datums\components\species\shadekin.dm"
|
||||
#include "code\datums\components\species\xenochimera.dm"
|
||||
#include "code\datums\components\species\shadekin\shadekin.dm"
|
||||
#include "code\datums\components\species\shadekin\helpers\comp_helpers.dm"
|
||||
#include "code\datums\components\species\shadekin\powers\create_shade.dm"
|
||||
#include "code\datums\components\species\shadekin\powers\dark_maw.dm"
|
||||
#include "code\datums\components\species\shadekin\powers\dark_respite.dm"
|
||||
#include "code\datums\components\species\shadekin\powers\phase_shift.dm"
|
||||
#include "code\datums\components\species\shadekin\powers\regenerate_other.dm"
|
||||
#include "code\datums\components\species\shadekin\powers\dark_tunnel\dark_tunnel_structures.dm"
|
||||
#include "code\datums\components\species\shadekin\powers\dark_tunnel\dark_tunneling.dm"
|
||||
#include "code\datums\components\traits\burninlight.dm"
|
||||
#include "code\datums\components\traits\drippy.dm"
|
||||
#include "code\datums\components\traits\gargoyle.dm"
|
||||
@@ -2333,6 +2341,7 @@
|
||||
#include "code\modules\client\preferences\types\character\antagonism\01_basic.dm"
|
||||
#include "code\modules\client\preferences\types\character\general\01_basic.dm"
|
||||
#include "code\modules\client\preferences\types\character\general\03_body.dm"
|
||||
#include "code\modules\client\preferences\types\character\general\06_special.dm"
|
||||
#include "code\modules\client\preferences\types\game\admin.dm"
|
||||
#include "code\modules\client\preferences\types\game\adult.dm"
|
||||
#include "code\modules\client\preferences\types\game\auto_fit_viewport.dm"
|
||||
@@ -3357,7 +3366,6 @@
|
||||
#include "code\modules\mob\living\carbon\human\species\outsider\shadow.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\outsider\skeleton.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\outsider\vox.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\shadekin\dark_portal_ch.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\shadekin\shadekin.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\shadekin\shadekin_abilities.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\shadekin\shadekin_hud.dm"
|
||||
@@ -3783,9 +3791,7 @@
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\vore\mobs_monsters\clowns\honkelemental.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\vore\mobs_monsters\clowns\regularclowns.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\vore\morph\morph.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\vore\shadekin\ability_objects.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\vore\shadekin\ability_procs.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\vore\shadekin\rakshasa_abilities.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\vore\shadekin\rakshasa_trap.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\vore\shadekin\shadekin.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\vore\shadekin\types.dm"
|
||||
@@ -5044,7 +5050,6 @@
|
||||
#include "modular_chomp\code\modules\mob\living\carbon\human\species\species.dm"
|
||||
#include "modular_chomp\code\modules\mob\living\carbon\human\species\species_shapeshift_ch.dm"
|
||||
#include "modular_chomp\code\modules\mob\living\carbon\human\species\outsider\vox.dm"
|
||||
#include "modular_chomp\code\modules\mob\living\carbon\human\species\shadekin\shadekin_abilities.dm"
|
||||
#include "modular_chomp\code\modules\mob\living\carbon\human\species\station\prommie_blob.dm"
|
||||
#include "modular_chomp\code\modules\mob\living\carbon\human\species\station\species_attack.dm"
|
||||
#include "modular_chomp\code\modules\mob\living\carbon\human\species\station\station.dm"
|
||||
@@ -5143,7 +5148,6 @@
|
||||
#include "modular_chomp\code\modules\mob\living\simple_mob\subtypes\vore\xeyakin.dm"
|
||||
#include "modular_chomp\code\modules\mob\living\simple_mob\subtypes\vore\gateway\candy.dm"
|
||||
#include "modular_chomp\code\modules\mob\living\simple_mob\subtypes\vore\plants\pitcher.dm"
|
||||
#include "modular_chomp\code\modules\mob\living\simple_mob\subtypes\vore\shadekin\shadekin.dm"
|
||||
#include "modular_chomp\code\modules\mob\new_player\sprite_accessories.dm"
|
||||
#include "modular_chomp\code\modules\mob\new_player\sprite_accessories_ear.dm"
|
||||
#include "modular_chomp\code\modules\mob\new_player\sprite_accessories_extra.dm"
|
||||
|
||||
Reference in New Issue
Block a user