mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-26 13:39:16 +01:00
Completes the /datum/component/shadekin work (#17895)
* Makes shadekin a component * Update shadekin.dm * Update human.dm * a * i love typos * Update life.dm * guh * Upports the shadekin stuff Also fixes an 8 year bug where the ability master would delete itself * boh * flashlight flickering * flickery * Update flashlight.dm * i hate lightcode * no clue * reenable * more changes * evil * Update living.dm * simplekin fix * yeah * maw fixes
This commit is contained in:
@@ -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("")
|
||||
|
||||
@@ -12,43 +12,3 @@
|
||||
var/low_sorting_priority = FALSE
|
||||
|
||||
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
|
||||
|
||||
/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")])"
|
||||
|
||||
@@ -68,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
|
||||
@@ -101,22 +100,8 @@
|
||||
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)
|
||||
var/list/shadekin_ability_datums = list()
|
||||
var/kin_type
|
||||
var/energy_light = 0.25
|
||||
var/energy_dark = 0.75
|
||||
species_component = /datum/component/shadekin
|
||||
|
||||
/datum/species/shadekin/New()
|
||||
..()
|
||||
for(var/power in shadekin_abilities)
|
||||
var/datum/power/shadekin/SKP = new power(src)
|
||||
shadekin_ability_datums.Add(SKP)
|
||||
|
||||
/datum/species/shadekin/handle_death(var/mob/living/carbon/human/H)
|
||||
spawn(1)
|
||||
for(var/obj/item/W in H)
|
||||
@@ -129,212 +114,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()
|
||||
)
|
||||
|
||||
/datum/species/shadekin/proc/handle_shade(var/mob/living/carbon/human/H)
|
||||
//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
|
||||
darkness = 1-brightness //Invert
|
||||
var/is_dark = (darkness >= 0.5)
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
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 = 100
|
||||
energy_light = 0.5
|
||||
energy_dark = 0.5
|
||||
if(RED_EYES)
|
||||
total_health = 200
|
||||
energy_light = -1
|
||||
energy_dark = 0.1
|
||||
if(PURPLE_EYES)
|
||||
total_health = 150
|
||||
energy_light = -0.5
|
||||
energy_dark = 1
|
||||
if(YELLOW_EYES)
|
||||
total_health = 100
|
||||
energy_light = -2
|
||||
energy_dark = 3
|
||||
if(GREEN_EYES)
|
||||
total_health = 100
|
||||
energy_light = 0.125
|
||||
energy_dark = 2
|
||||
if(ORANGE_EYES)
|
||||
total_health = 175
|
||||
energy_light = -0.5
|
||||
energy_dark = 0.25
|
||||
|
||||
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,364 +1,22 @@
|
||||
/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"
|
||||
|
||||
//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
|
||||
|
||||
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(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
|
||||
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!
|
||||
|
||||
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] visible Carbons with a cost of [ability_cost] in a darkness level of [darkness]")
|
||||
|
||||
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
|
||||
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)
|
||||
incorporeal_move = initial(incorporeal_move)
|
||||
density = initial(density)
|
||||
force_max_speed = initial(force_max_speed)
|
||||
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)
|
||||
canmove = original_canmove
|
||||
alpha = initial(alpha)
|
||||
remove_modifiers_of_type(/datum/modifier/shadekin_phase_vision)
|
||||
|
||||
//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 && 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]!"))
|
||||
|
||||
ability_flags &= ~AB_PHASE_SHIFTING
|
||||
|
||||
//Affect nearby lights
|
||||
var/destroy_lights = 0
|
||||
|
||||
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
|
||||
|
||||
// change
|
||||
ability_flags |= AB_PHASE_SHIFTED
|
||||
ability_flags |= AB_PHASE_SHIFTING
|
||||
throwpass = TRUE
|
||||
automatic_custom_emote(VISIBLE_MESSAGE,"phases out!")
|
||||
name = get_visible_name()
|
||||
|
||||
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)
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
var/datum/component/shadekin/SK = get_shadekin_component()
|
||||
if(!SK)
|
||||
return FALSE
|
||||
// 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) )
|
||||
if(SK.doing_phase || !T.CanPass(src,T) || loc != T || !(SK.in_phase) )
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -366,6 +24,6 @@
|
||||
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
|
||||
SK.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)
|
||||
|
||||
@@ -594,12 +594,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
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -1257,7 +1266,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()
|
||||
|
||||
@@ -345,9 +345,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
|
||||
|
||||
@@ -105,7 +105,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,10 +46,10 @@
|
||||
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))
|
||||
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)
|
||||
@@ -75,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)
|
||||
@@ -136,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()
|
||||
|
||||
@@ -1,15 +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
|
||||
//RS Port #658 Start
|
||||
if(!client?.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!"))
|
||||
@@ -17,133 +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()
|
||||
|
||||
//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)
|
||||
|
||||
/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)
|
||||
|
||||
@@ -71,8 +71,6 @@
|
||||
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
|
||||
@@ -97,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")
|
||||
@@ -201,7 +200,7 @@
|
||||
|
||||
/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
|
||||
@@ -215,9 +214,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()
|
||||
@@ -248,13 +247,89 @@
|
||||
|
||||
//They phase back to the dark when killed
|
||||
/mob/living/simple_mob/shadekin/death(gibbed, deathmessage = "phases to somewhere far away!")
|
||||
cut_overlays()
|
||||
icon_state = ""
|
||||
flick("tp_out",src)
|
||||
spawn(1 SECOND)
|
||||
qdel(src) //Back from whence you came!
|
||||
var/special_handling = FALSE //varswitch for downstream
|
||||
if(!special_handling)
|
||||
cut_overlays()
|
||||
icon_state = ""
|
||||
flick("tp_out",src)
|
||||
QDEL_IN(src, 1 SECOND)
|
||||
. = ..(FALSE, deathmessage)
|
||||
else
|
||||
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/proc/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/proc/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"))
|
||||
|
||||
. = ..(FALSE, deathmessage)
|
||||
|
||||
/* //VOREStation AI Temporary Removal
|
||||
//Blue-eyes want to nom people to heal them
|
||||
@@ -270,97 +345,34 @@
|
||||
//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)
|
||||
if(RED_EYES)
|
||||
comp.set_light_and_darkness(-0.5,0.5)
|
||||
if(PURPLE_EYES)
|
||||
comp.set_light_and_darkness(-0.5,1)
|
||||
if(YELLOW_EYES)
|
||||
comp.set_light_and_darkness(-2,3)
|
||||
if(GREEN_EYES)
|
||||
comp.set_light_and_darkness(0.125,2)
|
||||
if(ORANGE_EYES)
|
||||
comp.set_light_and_darkness(-0.25,0.75)
|
||||
|
||||
/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))
|
||||
|
||||
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()
|
||||
@@ -443,26 +455,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)
|
||||
. = ..()
|
||||
|
||||
Reference in New Issue
Block a user