12/21 modernizations from TG live (#103)
* sync (#3) * shuttle auto call * Merge /vore into /master (#39) * progress * Compile errors fixed No idea if it's test worthy tho as conflicts with race overhaul and narky removal. * Update admins.txt * efforts continue Fuck grab code, seriously * grab code is cancer * Execute the Narkism Do not hesitate. Show no mercy. * holy shit grab code is awful * have I bitched about grab code My bitching, let me show you it * código de agarre es una mierda No really it is * yeah I don't even know anymore. * Lolnope. Fuck grab code * I'm not even sure what to fix anymore * Self eating is not an acceptable fate * Taste the void, son. * My code doesn't pass it's own sanity check. Maybe it's a sign of things to come. * uncommented and notes * It Works and I Don't Know Why (#38) * shuttle auto call * it works and I don't know why * Subsystem 12/21 Most Recent TG subsystem folder * globalvars 12/21 Tossed out the flavor_misc and parallax files * Onclick 12/21 as well as .dme updates * _defines 12/21 ommited old _MC.dm * _HELPERS 12/21 Preserved snowflake placement of furry sprites * _defeines/genetics reapplied narkism holdover for snowflake races. * Oops forgot mutant colors * modules porting 12/21 + Sounds/icons Admin, Client and most of mob life files ommitted * enviroment file * Admin optimizations ahelp log system kept * Mob ports 12/21 Flavor text preserved * datums ported 12/21 * Game ported 12/21 * batch of duplicate fixes/dogborg work Dogborgs need to be modernized to refractored borg standards. * moar fixes * Maps and futher compile fixes
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
//an "overlay" used by clockwork walls and floors to appear normal to mesons.
|
||||
/obj/effect/clockwork/overlay
|
||||
mouse_opacity = 0
|
||||
var/atom/linked
|
||||
|
||||
/obj/effect/clockwork/overlay/examine(mob/user)
|
||||
if(linked)
|
||||
linked.examine(user)
|
||||
|
||||
/obj/effect/clockwork/overlay/ex_act()
|
||||
return FALSE
|
||||
|
||||
/obj/effect/clockwork/overlay/singularity_pull(S, current_size)
|
||||
return
|
||||
|
||||
/obj/effect/clockwork/overlay/Destroy()
|
||||
if(linked)
|
||||
linked = null
|
||||
..()
|
||||
return QDEL_HINT_PUTINPOOL
|
||||
|
||||
/obj/effect/clockwork/overlay/wall
|
||||
name = "clockwork wall"
|
||||
icon = 'icons/turf/walls/clockwork_wall.dmi'
|
||||
icon_state = "clockwork_wall"
|
||||
canSmoothWith = list(/obj/effect/clockwork/overlay/wall, /obj/structure/falsewall/brass)
|
||||
smooth = SMOOTH_TRUE
|
||||
layer = CLOSED_TURF_LAYER
|
||||
|
||||
/obj/effect/clockwork/overlay/wall/New()
|
||||
..()
|
||||
queue_smooth_neighbors(src)
|
||||
addtimer(GLOBAL_PROC, "queue_smooth", 1, TIMER_NORMAL, src)
|
||||
|
||||
/obj/effect/clockwork/overlay/wall/Destroy()
|
||||
queue_smooth_neighbors(src)
|
||||
..()
|
||||
return QDEL_HINT_QUEUE
|
||||
|
||||
/obj/effect/clockwork/overlay/floor
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "clockwork_floor"
|
||||
layer = TURF_LAYER
|
||||
|
||||
/obj/effect/clockwork/overlay/floor/bloodcult //this is used by BLOOD CULT, it shouldn't use such a path...
|
||||
icon_state = "cult"
|
||||
@@ -0,0 +1,392 @@
|
||||
//Sigils: Rune-like markings on the ground with various effects.
|
||||
/obj/effect/clockwork/sigil
|
||||
name = "sigil"
|
||||
desc = "A strange set of markings drawn on the ground."
|
||||
clockwork_desc = "A sigil of some purpose."
|
||||
icon_state = "sigil"
|
||||
layer = LOW_OBJ_LAYER
|
||||
alpha = 50
|
||||
resistance_flags = NONE
|
||||
var/affects_servants = FALSE
|
||||
var/stat_affected = CONSCIOUS
|
||||
var/sigil_name = "Sigil"
|
||||
var/resist_string = "glows blinding white" //string for when a null rod blocks its effects, "glows [resist_string]"
|
||||
|
||||
/obj/effect/clockwork/sigil/attackby(obj/item/I, mob/living/user, params)
|
||||
if(I.force && !is_servant_of_ratvar(user))
|
||||
user.visible_message("<span class='warning'>[user] scatters [src] with [I]!</span>", "<span class='danger'>You scatter [src] with [I]!</span>")
|
||||
qdel(src)
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/obj/effect/clockwork/sigil/attack_hand(mob/user)
|
||||
if(iscarbon(user) && !user.stat && (!is_servant_of_ratvar(user) || (is_servant_of_ratvar(user) && user.a_intent == INTENT_HARM)))
|
||||
user.visible_message("<span class='warning'>[user] stamps out [src]!</span>", "<span class='danger'>You stomp on [src], scattering it into thousands of particles.</span>")
|
||||
qdel(src)
|
||||
return 1
|
||||
..()
|
||||
|
||||
/obj/effect/clockwork/sigil/ex_act(severity)
|
||||
visible_message("<span class='warning'>[src] scatters into thousands of particles.</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/clockwork/sigil/Crossed(atom/movable/AM)
|
||||
..()
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(L.stat <= stat_affected)
|
||||
if((!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && affects_servants)) && L.mind && (!isdrone(L) || istype(L, /mob/living/simple_animal/drone/cogscarab)))
|
||||
var/obj/item/I = L.null_rod_check()
|
||||
if(I)
|
||||
L.visible_message("<span class='warning'>[L]'s [I.name] [resist_string], protecting them from [src]'s effects!</span>", \
|
||||
"<span class='userdanger'>Your [I.name] [resist_string], protecting you!</span>")
|
||||
return
|
||||
sigil_effects(L)
|
||||
|
||||
/obj/effect/clockwork/sigil/proc/sigil_effects(mob/living/L)
|
||||
|
||||
|
||||
//Sigil of Transgression: Stuns the first non-servant to walk on it and flashes all nearby non_servants. Nar-Sian cultists are damaged and knocked down for a longer stun
|
||||
/obj/effect/clockwork/sigil/transgression
|
||||
name = "dull sigil"
|
||||
desc = "A dull, barely-visible golden sigil. It's as though light was carved into the ground."
|
||||
icon = 'icons/effects/clockwork_effects.dmi'
|
||||
clockwork_desc = "A sigil that will stun the first non-servant to cross it. Nar-Sie's dogs will be knocked down."
|
||||
icon_state = "sigildull"
|
||||
color = "#FAE48C"
|
||||
sigil_name = "Sigil of Transgression"
|
||||
|
||||
/obj/effect/clockwork/sigil/transgression/sigil_effects(mob/living/L)
|
||||
var/target_flashed = L.flash_act()
|
||||
for(var/mob/living/M in viewers(5, src))
|
||||
if(!is_servant_of_ratvar(M) && M != L)
|
||||
M.flash_act()
|
||||
if(iscultist(L))
|
||||
L << "<span class='heavy_brass'>\"Watch your step, wretch.\"</span>"
|
||||
L.adjustBruteLoss(10)
|
||||
L.Weaken(7)
|
||||
L.visible_message("<span class='warning'>[src] appears around [L] in a burst of light!</span>", \
|
||||
"<span class='userdanger'>[target_flashed ? "An unseen force":"The glowing sigil around you"] holds you in place!</span>")
|
||||
L.Stun(5)
|
||||
PoolOrNew(/obj/effect/overlay/temp/ratvar/sigil/transgression, get_turf(src))
|
||||
qdel(src)
|
||||
|
||||
|
||||
//Sigil of Submission: After a short time, converts any non-servant standing on it. Knocks down and silences them for five seconds afterwards.
|
||||
/obj/effect/clockwork/sigil/submission
|
||||
name = "ominous sigil"
|
||||
desc = "A luminous golden sigil. Something about it really bothers you."
|
||||
clockwork_desc = "A sigil that will enslave the first person to cross it, provided they remain on it for seven seconds."
|
||||
icon_state = "sigilsubmission"
|
||||
color = "#FAE48C"
|
||||
alpha = 125
|
||||
stat_affected = UNCONSCIOUS
|
||||
resist_string = "glows faintly yellow"
|
||||
var/convert_time = 70
|
||||
var/glow_light = 2 //soft light
|
||||
var/glow_falloff = 1
|
||||
var/delete_on_finish = TRUE
|
||||
sigil_name = "Sigil of Submission"
|
||||
var/glow_type
|
||||
|
||||
/obj/effect/clockwork/sigil/submission/New()
|
||||
..()
|
||||
SetLuminosity(glow_light,glow_falloff)
|
||||
|
||||
/obj/effect/clockwork/sigil/submission/proc/post_channel(mob/living/L)
|
||||
|
||||
/obj/effect/clockwork/sigil/submission/sigil_effects(mob/living/L)
|
||||
L.visible_message("<span class='warning'>[src] begins to glow a piercing magenta!</span>", "<span class='sevtug'>You feel something start to invade your mind...</span>")
|
||||
var/oldcolor = color
|
||||
animate(src, color = "#AF0AAF", time = convert_time)
|
||||
var/obj/effect/overlay/temp/ratvar/sigil/glow
|
||||
if(glow_type)
|
||||
glow = PoolOrNew(glow_type, get_turf(src))
|
||||
animate(glow, alpha = 255, time = convert_time)
|
||||
var/I = 0
|
||||
while(I < convert_time && get_turf(L) == get_turf(src))
|
||||
I++
|
||||
sleep(1)
|
||||
if(get_turf(L) != get_turf(src))
|
||||
if(glow)
|
||||
qdel(glow)
|
||||
animate(src, color = oldcolor, time = 20)
|
||||
addtimer(src, "update_atom_colour", 20)
|
||||
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
|
||||
return
|
||||
post_channel(L)
|
||||
if(is_eligible_servant(L))
|
||||
L << "<span class='heavy_brass'>\"You belong to me now.\"</span>"
|
||||
add_servant_of_ratvar(L)
|
||||
L.Weaken(3) //Completely defenseless for about five seconds - mainly to give them time to read over the information they've just been presented with
|
||||
L.Stun(3)
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
C.silent += 5
|
||||
var/message = "[sigil_name] in [get_area(src)] <span class='sevtug'>[is_servant_of_ratvar(L) ? "successfully converted" : "failed to convert"]</span>"
|
||||
for(var/M in mob_list)
|
||||
if(isobserver(M))
|
||||
var/link = FOLLOW_LINK(M, L)
|
||||
M << "[link] <span class='heavy_brass'>[message] [L.real_name]!</span>"
|
||||
else if(is_servant_of_ratvar(M))
|
||||
if(M == L)
|
||||
M << "<span class='heavy_brass'>[message] you!</span>"
|
||||
else
|
||||
M << "<span class='heavy_brass'>[message] [L.real_name]!</span>"
|
||||
if(delete_on_finish)
|
||||
qdel(src)
|
||||
else
|
||||
animate(src, color = oldcolor, time = 20)
|
||||
addtimer(src, "update_atom_colour", 20)
|
||||
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
|
||||
|
||||
|
||||
//Sigil of Accession: After a short time, converts any non-servant standing on it though implants. Knocks down and silences them for five seconds afterwards.
|
||||
/obj/effect/clockwork/sigil/submission/accession
|
||||
name = "terrifying sigil"
|
||||
desc = "A luminous brassy sigil. Something about it makes you want to flee."
|
||||
clockwork_desc = "A sigil that will enslave any person who crosses it, provided they remain on it for seven seconds. \n\
|
||||
It can convert a mindshielded target once before disppearing, but can convert any number of non-implanted targets."
|
||||
icon_state = "sigiltransgression"
|
||||
color = "#A97F1B"
|
||||
alpha = 200
|
||||
glow_light = 4 //bright light
|
||||
glow_falloff = 3
|
||||
delete_on_finish = FALSE
|
||||
sigil_name = "Sigil of Accession"
|
||||
glow_type = /obj/effect/overlay/temp/ratvar/sigil/accession
|
||||
resist_string = "glows bright orange"
|
||||
|
||||
/obj/effect/clockwork/sigil/submission/accession/post_channel(mob/living/L)
|
||||
if(L.isloyal())
|
||||
var/mob/living/carbon/C = L
|
||||
delete_on_finish = TRUE
|
||||
C.visible_message("<span class='warning'>[C] visibly trembles!</span>", \
|
||||
"<span class='sevtug'>[text2ratvar("You will be mine and his. This puny trinket will not stop me.")]</span>")
|
||||
for(var/obj/item/weapon/implant/mindshield/M in C.implants)
|
||||
qdel(M)
|
||||
|
||||
|
||||
//Sigil of Transmission: Stores power for clockwork machinery, serving as a battery.
|
||||
/obj/effect/clockwork/sigil/transmission
|
||||
name = "suspicious sigil"
|
||||
desc = "A glowing orange sigil. The air around it feels staticky."
|
||||
clockwork_desc = "A sigil that will serve as a battery for clockwork structures. Use Volt Void while standing on it to charge it."
|
||||
icon_state = "sigiltransmission"
|
||||
color = "#EC8A2D"
|
||||
alpha = 50
|
||||
resist_string = "glows faintly"
|
||||
sigil_name = "Sigil of Transmission"
|
||||
affects_servants = TRUE
|
||||
var/power_charge = REPLICANT_ALLOY_POWER //starts with REPLICANT_ALLOY_POWER by default
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/ex_act(severity)
|
||||
if(severity == 3)
|
||||
modify_charge(-500)
|
||||
visible_message("<span class='warning'>[src] flares a brilliant orange!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/examine(mob/user)
|
||||
..()
|
||||
if(is_servant_of_ratvar(user) || isobserver(user))
|
||||
user << "<span class='[power_charge ? "brass":"alloy"]'>It is storing <b>[ratvar_awakens ? "INFINITY":"[power_charge]"]W</b> of power.</span>"
|
||||
if(iscyborg(user))
|
||||
user << "<span class='brass'>You can recharge from the [sigil_name] by crossing it.</span>"
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/sigil_effects(mob/living/L)
|
||||
if(is_servant_of_ratvar(L))
|
||||
if(iscyborg(L))
|
||||
charge_cyborg(L)
|
||||
else if(power_charge)
|
||||
L << "<span class='brass'>You feel a slight, static shock.</span>"
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/proc/charge_cyborg(mob/living/silicon/robot/cyborg)
|
||||
if(!cyborg_checks(cyborg))
|
||||
return
|
||||
cyborg << "<span class='brass'>You start to charge from the [sigil_name]...</span>"
|
||||
if(!do_after(cyborg, 50, target = src))
|
||||
return
|
||||
if(!cyborg_checks(cyborg))
|
||||
return
|
||||
var/giving_power = min(round((cyborg.cell.maxcharge - cyborg.cell.charge) * 0.02) * 50, power_charge) //give the borg either all our power or their missing power floored to 50
|
||||
if(modify_charge(giving_power))
|
||||
cyborg.visible_message("<span class='warning'>[cyborg] glows a brilliant orange!</span>")
|
||||
var/previous_color = cyborg.color
|
||||
cyborg.color = list("#EC8A2D", "#EC8A2D", "#EC8A2D", rgb(0,0,0))
|
||||
var/datum/status_effect/cyborg_power_regen/CPR = cyborg.apply_status_effect(STATUS_EFFECT_POWERREGEN)
|
||||
CPR.power_to_give = giving_power * 0.1 //ten ticks, restoring 10% each
|
||||
animate(cyborg, color = previous_color, time = 100)
|
||||
addtimer(cyborg, "update_atom_colour", 100)
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/proc/cyborg_checks(mob/living/silicon/robot/cyborg)
|
||||
if(!cyborg.cell)
|
||||
cyborg << "<span class='warning'>You have no cell!</span>"
|
||||
return FALSE
|
||||
if(!power_charge)
|
||||
cyborg << "<span class='warning'>The [sigil_name] has no stored power!</span>"
|
||||
return FALSE
|
||||
if(cyborg.cell.charge > cyborg.cell.maxcharge - MIN_CLOCKCULT_POWER)
|
||||
cyborg << "<span class='warning'>You are already at maximum charge!</span>"
|
||||
return FALSE
|
||||
if(cyborg.has_status_effect(STATUS_EFFECT_POWERREGEN))
|
||||
cyborg << "<span class='warning'>You are already regenerating power!</span>"
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/New()
|
||||
..()
|
||||
update_glow()
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/proc/modify_charge(amount)
|
||||
if(ratvar_awakens)
|
||||
update_glow()
|
||||
return TRUE
|
||||
if(power_charge - amount < 0)
|
||||
return FALSE
|
||||
power_charge -= amount
|
||||
update_glow()
|
||||
return TRUE
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/proc/update_glow()
|
||||
if(ratvar_awakens)
|
||||
alpha = 255
|
||||
else
|
||||
alpha = min(initial(alpha) + power_charge*0.02, 255)
|
||||
if(!power_charge)
|
||||
SetLuminosity(0)
|
||||
else
|
||||
SetLuminosity(round(alpha*0.03, 1), round(alpha*0.02, 1))
|
||||
|
||||
|
||||
//Vitality Matrix: Drains health from non-servants to heal or even revive servants.
|
||||
/obj/effect/clockwork/sigil/vitality
|
||||
name = "comforting sigil"
|
||||
desc = "A faint blue sigil. Looking at it makes you feel protected."
|
||||
clockwork_desc = "A sigil that will drain non-Servants that remain on it. Servants that remain on it will be healed if it has any vitality drained."
|
||||
icon_state = "sigilvitality"
|
||||
color = "#123456"
|
||||
alpha = 75
|
||||
affects_servants = TRUE
|
||||
stat_affected = DEAD
|
||||
resist_string = "glows shimmering yellow"
|
||||
sigil_name = "Vitality Matrix"
|
||||
var/vitality = 0
|
||||
var/base_revive_cost = 20
|
||||
var/sigil_active = FALSE
|
||||
var/animation_number = 3 //each cycle increments this by 1, at 4 it produces an animation and resets
|
||||
|
||||
/obj/effect/clockwork/sigil/vitality/examine(mob/user)
|
||||
..()
|
||||
if(is_servant_of_ratvar(user) || isobserver(user))
|
||||
user << "<span class='[vitality ? "inathneq_small":"alloy"]'>It is storing <b>[ratvar_awakens ? "INFINITE":"[vitality]"]</b> units of vitality.</span>"
|
||||
user << "<span class='inathneq_small'>It requires at least <b>[base_revive_cost]</b> units of vitality to revive dead Servants, in addition to any damage the Servant has.</span>"
|
||||
|
||||
/obj/effect/clockwork/sigil/vitality/sigil_effects(mob/living/L)
|
||||
if((is_servant_of_ratvar(L) && L.suiciding) || sigil_active)
|
||||
return
|
||||
visible_message("<span class='warning'>[src] begins to glow bright blue!</span>")
|
||||
animate(src, alpha = 255, time = 10)
|
||||
addtimer(src, "update_alpha", 10)
|
||||
sleep(10)
|
||||
//as long as they're still on the sigil and are either not a servant or they're a servant AND it has remaining vitality
|
||||
while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && vitality)) && get_turf(L) == get_turf(src))
|
||||
sigil_active = TRUE
|
||||
if(animation_number >= 4)
|
||||
PoolOrNew(/obj/effect/overlay/temp/ratvar/sigil/vitality, get_turf(src))
|
||||
animation_number = 0
|
||||
animation_number++
|
||||
if(!is_servant_of_ratvar(L))
|
||||
var/vitality_drained = 0
|
||||
if(L.stat == DEAD)
|
||||
vitality_drained = L.maxHealth
|
||||
var/obj/effect/overlay/temp/ratvar/sigil/vitality/V = PoolOrNew(/obj/effect/overlay/temp/ratvar/sigil/vitality, get_turf(src))
|
||||
animate(V, alpha = 0, transform = matrix()*2, time = 8)
|
||||
playsound(L, 'sound/magic/WandODeath.ogg', 50, 1)
|
||||
L.visible_message("<span class='warning'>[L] collapses in on [L.p_them()]self as [src] flares bright blue!</span>")
|
||||
L << "<span class='inathneq_large'>\"[text2ratvar("Your life will not be wasted.")]\"</span>"
|
||||
for(var/obj/item/W in L)
|
||||
if(!L.unEquip(W))
|
||||
qdel(W)
|
||||
L.dust()
|
||||
else
|
||||
vitality_drained = L.adjustToxLoss(1.5)
|
||||
if(vitality_drained)
|
||||
vitality += vitality_drained
|
||||
else
|
||||
break
|
||||
else
|
||||
var/clone_to_heal = L.getCloneLoss()
|
||||
var/tox_to_heal = L.getToxLoss()
|
||||
var/burn_to_heal = L.getFireLoss()
|
||||
var/brute_to_heal = L.getBruteLoss()
|
||||
var/oxy_to_heal = L.getOxyLoss()
|
||||
var/total_damage = clone_to_heal + tox_to_heal + burn_to_heal + brute_to_heal + oxy_to_heal
|
||||
if(L.stat == DEAD)
|
||||
var/revival_cost = base_revive_cost + total_damage - oxy_to_heal //ignores oxygen damage
|
||||
if(ratvar_awakens)
|
||||
revival_cost = 0
|
||||
var/mob/dead/observer/ghost = L.get_ghost(TRUE)
|
||||
if(vitality >= revival_cost && (ghost || (L.mind && L.mind.active)))
|
||||
if(ghost)
|
||||
ghost.reenter_corpse()
|
||||
L.revive(1, 1)
|
||||
playsound(L, 'sound/magic/Staff_Healing.ogg', 50, 1)
|
||||
L.visible_message("<span class='warning'>[L] suddenly gets back up, [L.p_their()] mouth dripping blue ichor!</span>", \
|
||||
"<span class='inathneq'>\"[text2ratvar("You will be okay, child.")]\"</span>")
|
||||
vitality -= revival_cost
|
||||
break
|
||||
if(!total_damage)
|
||||
break
|
||||
var/vitality_for_cycle = min(vitality, 3)
|
||||
var/vitality_used = 0
|
||||
if(ratvar_awakens)
|
||||
vitality_for_cycle = 3
|
||||
|
||||
if(clone_to_heal && vitality_for_cycle)
|
||||
var/healing = min(vitality_for_cycle, clone_to_heal)
|
||||
vitality_for_cycle -= healing
|
||||
L.adjustCloneLoss(-healing)
|
||||
vitality_used += healing
|
||||
|
||||
if(tox_to_heal && vitality_for_cycle)
|
||||
var/healing = min(vitality_for_cycle, tox_to_heal)
|
||||
vitality_for_cycle -= healing
|
||||
L.adjustToxLoss(-healing)
|
||||
vitality_used += healing
|
||||
|
||||
if(burn_to_heal && vitality_for_cycle)
|
||||
var/healing = min(vitality_for_cycle, burn_to_heal)
|
||||
vitality_for_cycle -= healing
|
||||
L.adjustFireLoss(-healing)
|
||||
vitality_used += healing
|
||||
|
||||
if(brute_to_heal && vitality_for_cycle)
|
||||
var/healing = min(vitality_for_cycle, brute_to_heal)
|
||||
vitality_for_cycle -= healing
|
||||
L.adjustBruteLoss(-healing)
|
||||
vitality_used += healing
|
||||
|
||||
if(oxy_to_heal && vitality_for_cycle)
|
||||
var/healing = min(vitality_for_cycle, oxy_to_heal)
|
||||
vitality_for_cycle -= healing
|
||||
L.adjustOxyLoss(-healing)
|
||||
vitality_used += healing
|
||||
|
||||
if(!ratvar_awakens)
|
||||
vitality -= vitality_used
|
||||
sleep(2)
|
||||
|
||||
if(sigil_active)
|
||||
animation_number = initial(animation_number)
|
||||
sigil_active = FALSE
|
||||
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
|
||||
if(sigil_active || alpha == 255)
|
||||
animate(src, alpha = initial(alpha), time = 10)
|
||||
addtimer(src, "update_alpha", 10)
|
||||
|
||||
/obj/effect/clockwork/sigil/vitality/proc/update_alpha()
|
||||
if(sigil_active)
|
||||
alpha = 255
|
||||
else
|
||||
alpha = initial(alpha)
|
||||
@@ -0,0 +1,57 @@
|
||||
//massive markers for Revenant and Judgement scripture.
|
||||
/obj/effect/clockwork/general_marker
|
||||
name = "general marker"
|
||||
desc = "Some big guy. For you."
|
||||
clockwork_desc = "One of Ratvar's generals."
|
||||
alpha = 200
|
||||
layer = MASSIVE_OBJ_LAYER
|
||||
|
||||
/obj/effect/clockwork/general_marker/New()
|
||||
..()
|
||||
animate(src, alpha = 0, time = 10)
|
||||
QDEL_IN(src, 10)
|
||||
|
||||
/obj/effect/clockwork/general_marker/inathneq
|
||||
name = "Inath-neq, the Resonant Cogwheel"
|
||||
desc = "A humanoid form blazing with blue fire. It radiates an aura of kindness and caring."
|
||||
clockwork_desc = "One of Ratvar's four generals. Before her current form, Inath-neq was a powerful warrior priestess commanding the Resonant Cogs, a sect of Ratvarian warriors renowned for \
|
||||
their prowess. After a lost battle with Nar-Sian cultists, Inath-neq was struck down and stated in her dying breath, \
|
||||
\"The Resonant Cogs shall not fall silent this day, but will come together to form a wheel that shall never stop turning.\" Ratvar, touched by this, granted Inath-neq an eternal body and \
|
||||
merged her soul with those of the Cogs slain with her on the battlefield."
|
||||
icon = 'icons/effects/187x381.dmi'
|
||||
icon_state = "inath-neq"
|
||||
pixel_x = -77
|
||||
pixel_y = -174
|
||||
|
||||
/obj/effect/clockwork/general_marker/nezbere
|
||||
name = "Nezbere, the Brass Eidolon"
|
||||
desc = "A towering colossus clad in nigh-impenetrable brass armor. Its gaze is stern yet benevolent, even upon you."
|
||||
clockwork_desc = "One of Ratvar's four generals. Nezbere is responsible for the design, testing, and creation of everything in Ratvar's domain, and his loyalty to Ratvar knows no bounds. \
|
||||
It is said that Ratvar once asked him to destroy the plans for a weapon Nezbere had made that could have harmed him and Nezbere responded by not only destroying the plans, \
|
||||
but by taking his own life so that the device could never be replicated. Nezbere's zealotry is unmatched."
|
||||
icon = 'icons/effects/340x428.dmi'
|
||||
icon_state = "nezbere"
|
||||
pixel_x = -154
|
||||
pixel_y = -198
|
||||
|
||||
/obj/effect/clockwork/general_marker/sevtug
|
||||
name = "Sevtug, the Formless Pariah"
|
||||
desc = "A sinister cloud of purple energy. Looking at it gives you a headache."
|
||||
clockwork_desc = "One of Ratvar's four generals. Sevtug taught him how to manipulate minds and is one of his oldest allies. Sevtug serves Ratvar loyally out of a hope that one day, he will \
|
||||
be able to use a moment of weakness in the Justicar to usurp him, but such a day will never come. And so, he serves with dedication, if not necessarily any sort of decorum, never aware he is \
|
||||
the one being made a fool of."
|
||||
icon = 'icons/effects/211x247.dmi'
|
||||
icon_state = "sevtug"
|
||||
pixel_x = -89
|
||||
pixel_y = -107
|
||||
|
||||
/obj/effect/clockwork/general_marker/nzcrentr
|
||||
name = "Nzcrentr, the Eternal Thunderbolt"
|
||||
desc = "A terrifying spiked construct crackling with limitless energy."
|
||||
clockwork_desc = "One of Ratvar's four generals. Before becoming one of Ratvar's generals, Nzcrentr sook out any and all sentient life to slaughter it for sport. \
|
||||
Nzcrentr was coerced by Ratvar into entering a shell constructed by Nezbere, ostensibly made to grant Nzcrentr more power. In reality, the shell was made to trap and control it. \
|
||||
Nzcrentr now serves loyally, though even one of Nezbere's finest creations was not enough to totally eliminate its will."
|
||||
icon = 'icons/effects/254x361.dmi'
|
||||
icon_state = "nzcrentr"
|
||||
pixel_x = -111
|
||||
pixel_y = -164
|
||||
@@ -0,0 +1,212 @@
|
||||
//Spatial gateway: A usually one-way rift to another location.
|
||||
/obj/effect/clockwork/spatial_gateway
|
||||
name = "spatial gateway"
|
||||
desc = "A gently thrumming tear in reality."
|
||||
clockwork_desc = "A gateway in reality."
|
||||
icon_state = "spatial_gateway"
|
||||
density = 1
|
||||
luminosity = 2
|
||||
var/sender = TRUE //If this gateway is made for sending, not receiving
|
||||
var/both_ways = FALSE
|
||||
var/lifetime = 25 //How many deciseconds this portal will last
|
||||
var/uses = 1 //How many objects or mobs can go through the portal
|
||||
var/obj/effect/clockwork/spatial_gateway/linked_gateway //The gateway linked to this one
|
||||
var/timerid
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/New()
|
||||
..()
|
||||
addtimer(src, "check_setup", 1)
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/Destroy()
|
||||
deltimer(timerid)
|
||||
return ..()
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/proc/check_setup()
|
||||
if(!linked_gateway)
|
||||
qdel(src)
|
||||
return
|
||||
if(both_ways)
|
||||
clockwork_desc = "A gateway in reality. It can both send and receive objects."
|
||||
else
|
||||
clockwork_desc = "A gateway in reality. It can only [sender ? "send" : "receive"] objects."
|
||||
timerid = QDEL_IN(src, lifetime)
|
||||
|
||||
//set up a gateway with another gateway
|
||||
/obj/effect/clockwork/spatial_gateway/proc/setup_gateway(obj/effect/clockwork/spatial_gateway/gatewayB, set_duration, set_uses, two_way)
|
||||
if(!gatewayB || !set_duration || !uses)
|
||||
return FALSE
|
||||
linked_gateway = gatewayB
|
||||
gatewayB.linked_gateway = src
|
||||
if(two_way)
|
||||
both_ways = TRUE
|
||||
gatewayB.both_ways = TRUE
|
||||
else
|
||||
sender = TRUE
|
||||
gatewayB.sender = FALSE
|
||||
gatewayB.density = FALSE
|
||||
lifetime = set_duration
|
||||
gatewayB.lifetime = set_duration
|
||||
uses = set_uses
|
||||
gatewayB.uses = set_uses
|
||||
return TRUE
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/examine(mob/user)
|
||||
..()
|
||||
if(is_servant_of_ratvar(user) || isobserver(user))
|
||||
user << "<span class='brass'>It has [uses] uses remaining.</span>"
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/attack_ghost(mob/user)
|
||||
if(linked_gateway)
|
||||
user.forceMove(get_turf(linked_gateway))
|
||||
..()
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/attack_hand(mob/living/user)
|
||||
if(!uses)
|
||||
return FALSE
|
||||
if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling))
|
||||
var/mob/living/L = user.pulling
|
||||
if(L.buckled || L.anchored || L.has_buckled_mobs())
|
||||
return FALSE
|
||||
user.visible_message("<span class='warning'>[user] shoves [L] into [src]!</span>", "<span class='danger'>You shove [L] into [src]!</span>")
|
||||
user.stop_pulling()
|
||||
pass_through_gateway(L)
|
||||
return TRUE
|
||||
if(!user.canUseTopic(src))
|
||||
return FALSE
|
||||
user.visible_message("<span class='warning'>[user] climbs through [src]!</span>", "<span class='danger'>You brace yourself and step through [src]...</span>")
|
||||
pass_through_gateway(user)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/attackby(obj/item/I, mob/living/user, params)
|
||||
if(istype(I, /obj/item/weapon/nullrod))
|
||||
user.visible_message("<span class='warning'>[user] dispels [src] with [I]!</span>", "<span class='danger'>You close [src] with [I]!</span>")
|
||||
qdel(linked_gateway)
|
||||
qdel(src)
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/clockwork/slab))
|
||||
user << "<span class='heavy_brass'>\"I don't think you want to drop your slab into that\".\n\"If you really want to, try throwing it.\"</span>"
|
||||
return TRUE
|
||||
if(user.drop_item() && uses)
|
||||
user.visible_message("<span class='warning'>[user] drops [I] into [src]!</span>", "<span class='danger'>You drop [I] into [src]!</span>")
|
||||
pass_through_gateway(I, TRUE)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/ex_act(severity)
|
||||
if(severity == 1 && uses)
|
||||
uses = 0
|
||||
visible_message("<span class='warning'>[src] is disrupted!</span>")
|
||||
animate(src, alpha = 0, transform = matrix()*2, time = 10)
|
||||
deltimer(timerid)
|
||||
timerid = QDEL_IN(src, 10)
|
||||
linked_gateway.uses = 0
|
||||
linked_gateway.visible_message("<span class='warning'>[linked_gateway] is disrupted!</span>")
|
||||
animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 10)
|
||||
deltimer(linked_gateway.timerid)
|
||||
linked_gateway.timerid = QDEL_IN(linked_gateway, 10)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/Bumped(atom/A)
|
||||
..()
|
||||
if(isliving(A) || istype(A, /obj/item))
|
||||
pass_through_gateway(A)
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/proc/pass_through_gateway(atom/movable/A, no_cost)
|
||||
if(!linked_gateway)
|
||||
qdel(src)
|
||||
return FALSE
|
||||
if(!sender)
|
||||
visible_message("<span class='warning'>[A] bounces off of [src]!</span>")
|
||||
return FALSE
|
||||
if(!uses)
|
||||
return FALSE
|
||||
if(isliving(A))
|
||||
var/mob/living/user = A
|
||||
user << "<span class='warning'><b>You pass through [src] and appear elsewhere!</b></span>"
|
||||
linked_gateway.visible_message("<span class='warning'>A shape appears in [linked_gateway] before emerging!</span>")
|
||||
playsound(src, 'sound/effects/EMPulse.ogg', 50, 1)
|
||||
playsound(linked_gateway, 'sound/effects/EMPulse.ogg', 50, 1)
|
||||
transform = matrix() * 1.5
|
||||
animate(src, transform = matrix() / 1.5, time = 10)
|
||||
linked_gateway.transform = matrix() * 1.5
|
||||
animate(linked_gateway, transform = matrix() / 1.5, time = 10)
|
||||
A.forceMove(get_turf(linked_gateway))
|
||||
if(!no_cost)
|
||||
uses = max(0, uses - 1)
|
||||
linked_gateway.uses = max(0, linked_gateway.uses - 1)
|
||||
addtimer(src, "check_uses", 10)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/clockwork/spatial_gateway/proc/check_uses()
|
||||
if(!uses)
|
||||
qdel(src)
|
||||
qdel(linked_gateway)
|
||||
|
||||
//This proc creates and sets up a gateway from invoker input.
|
||||
/atom/movable/proc/procure_gateway(mob/living/invoker, time_duration, gateway_uses, two_way)
|
||||
var/list/possible_targets = list()
|
||||
var/list/teleportnames = list()
|
||||
var/list/duplicatenamecount = list()
|
||||
|
||||
for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in all_clockwork_objects)
|
||||
if(!O.Adjacent(invoker) && O != src && (O.z <= ZLEVEL_SPACEMAX) && O.anchored) //don't list obelisks that we're next to
|
||||
var/area/A = get_area(O)
|
||||
var/locname = initial(A.name)
|
||||
var/resultkey = "[locname] [O.name]"
|
||||
if(resultkey in teleportnames) //why the fuck did you put two obelisks in the same area
|
||||
duplicatenamecount[resultkey]++
|
||||
resultkey = "[resultkey] ([duplicatenamecount[resultkey]])"
|
||||
else
|
||||
teleportnames.Add(resultkey)
|
||||
duplicatenamecount[resultkey] = 1
|
||||
possible_targets[resultkey] = O
|
||||
|
||||
for(var/mob/living/L in living_mob_list)
|
||||
if(!L.stat && is_servant_of_ratvar(L) && !L.Adjacent(invoker) && (L.z <= ZLEVEL_SPACEMAX)) //People right next to the invoker can't be portaled to, for obvious reasons
|
||||
var/resultkey = "[L.name] ([L.real_name])"
|
||||
if(resultkey in teleportnames)
|
||||
duplicatenamecount[resultkey]++
|
||||
resultkey = "[resultkey] ([duplicatenamecount[resultkey]])"
|
||||
else
|
||||
teleportnames.Add(resultkey)
|
||||
duplicatenamecount[resultkey] = 1
|
||||
possible_targets[resultkey] = L
|
||||
|
||||
if(!possible_targets.len)
|
||||
invoker << "<span class='warning'>There are no other eligible targets for a Spatial Gateway!</span>"
|
||||
return FALSE
|
||||
var/input_target_key = input(invoker, "Choose a target to form a rift to.", "Spatial Gateway") as null|anything in possible_targets
|
||||
var/atom/movable/target = possible_targets[input_target_key]
|
||||
if(!src || !target || !invoker || !invoker.canUseTopic(src, !issilicon(invoker)) || !is_servant_of_ratvar(invoker) || (istype(src, /obj/item) && invoker.get_active_held_item() != src) || !invoker.can_speak_vocal())
|
||||
return FALSE //if any of the involved things no longer exist, the invoker is stunned, too far away to use the object, or does not serve ratvar, or if the object is an item and not in the mob's active hand, fail
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
if(L.stat != CONSCIOUS)
|
||||
invoker << "<span class='warning'>That Servant is no longer conscious!</span>"
|
||||
return procure_gateway(invoker, time_duration, gateway_uses, two_way) //try again?
|
||||
if(!is_servant_of_ratvar(L))
|
||||
invoker << "<span class='warning'>That target is no longer a Servant!</span>"
|
||||
return procure_gateway(invoker, time_duration, gateway_uses, two_way)
|
||||
var/istargetobelisk = istype(target, /obj/structure/destructible/clockwork/powered/clockwork_obelisk)
|
||||
var/issrcobelisk = istype(src, /obj/structure/destructible/clockwork/powered/clockwork_obelisk)
|
||||
if(issrcobelisk && !anchored)
|
||||
invoker << "<span class='warning'>[src] is no longer secured!</span>"
|
||||
return FALSE
|
||||
if(istargetobelisk)
|
||||
if(!target.anchored)
|
||||
invoker << "<span class='warning'>That [target.name] is no longer secured!</span>"
|
||||
return procure_gateway(invoker, time_duration, gateway_uses, two_way)
|
||||
var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/CO = target
|
||||
var/efficiency = CO.get_efficiency_mod()
|
||||
gateway_uses = round(gateway_uses * (2 * efficiency), 1)
|
||||
time_duration = round(time_duration * (2 * efficiency), 1)
|
||||
invoker.visible_message("<span class='warning'>The air in front of [invoker] ripples before suddenly tearing open!</span>", \
|
||||
"<span class='brass'>With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [time_duration / 10] seconds and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].</span>")
|
||||
var/obj/effect/clockwork/spatial_gateway/S1 = new(issrcobelisk ? get_turf(src) : get_step(get_turf(invoker), invoker.dir))
|
||||
var/obj/effect/clockwork/spatial_gateway/S2 = new(istargetobelisk ? get_turf(target) : get_step(get_turf(target), target.dir))
|
||||
|
||||
//Set up the portals now that they've spawned
|
||||
S1.setup_gateway(S2, time_duration, gateway_uses, two_way)
|
||||
S2.visible_message("<span class='warning'>The air in front of [target] ripples before suddenly tearing open!</span>")
|
||||
return TRUE
|
||||
Reference in New Issue
Block a user