[Cult 4] Part #4-1: Constructs Changes Part 1 (#28806)

* WraithChanges

* well this took longer than expected

* there goes my Saturday

* artificer HUD adjustment

* aight good

* hue

* oh you

* fixes
This commit is contained in:
DeityLink
2021-02-12 16:02:53 +01:00
committed by GitHub
parent 7ad539a7ab
commit 73515e284d
18 changed files with 460 additions and 169 deletions

View File

@@ -170,6 +170,10 @@
#define TOME_CLOSED 1 #define TOME_CLOSED 1
#define TOME_OPEN 2 #define TOME_OPEN 2
#define RUNE_WRITE_CANNOT 0
#define RUNE_WRITE_COMPLETE 1
#define RUNE_WRITE_CONTINUE 2
#define RUNE_CAN_ATTUNE 0 #define RUNE_CAN_ATTUNE 0
#define RUNE_CAN_IMBUE 1 #define RUNE_CAN_IMBUE 1
#define RUNE_CANNOT 2 #define RUNE_CANNOT 2

View File

@@ -271,7 +271,7 @@
* unstick * unstick
* /artificerray * /artificerray
-> visual ray that appears when artificers -> visual ray that appears when artificers heal mobs
[bloodcult_narsie.dm] [bloodcult_narsie.dm]

View File

@@ -107,123 +107,21 @@
icon_living = "wraith2" icon_living = "wraith2"
icon_dead = "wraith2" icon_dead = "wraith2"
see_in_dark = 7 see_in_dark = 7
construct_spells = list(/spell/targeted/ethereal_jaunt/shift/alt) construct_spells = list(
var/ranged_cooldown = 0 /spell/targeted/ethereal_jaunt/shift/alt,
var/ammo = 3 /spell/wraith_warp,
var/ammo_recharge = 0 /spell/aoe_turf/conjure/path_entrance,
/spell/aoe_turf/conjure/path_exit,
)
var/warp_ready = FALSE
/mob/living/simple_animal/construct/wraith/perfect/New() /mob/living/simple_animal/construct/wraith/perfect/New()
..() ..()
setupfloat() setupfloat()
/mob/living/simple_animal/construct/wraith/perfect/Life() /mob/living/simple_animal/construct/wraith/perfect/toggle_throw_mode()
if(timestopped) var/spell/wraith_warp/WW = locate() in spell_list
return 0 WW.perform(src)
. = ..()
ranged_cooldown = max(0,ranged_cooldown-1)
if (ammo < 3)
ammo_recharge++
if (ammo_recharge >= 3)
ammo_recharge = 0
ammo++
/mob/living/simple_animal/construct/wraith/perfect/RangedAttack(var/atom/A, var/params)
if(ranged_cooldown <= 0 && ammo)
ammo--
generic_projectile_fire(A, src, /obj/item/projectile/wraithnail, 'sound/weapons/hivehand.ogg', src)
return ..()
/obj/item/projectile/wraithnail
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "wraithnail"
damage = 5
/obj/item/projectile/wraithnail/to_bump(var/atom/A)
if(bumped)
return 0
bumped = 1
if(A)
setDensity(FALSE)
invisibility = 101
kill_count = 0
var/obj/effect/overlay/wraithnail/nail = new (A.loc)
nail.transform = transform
if(isliving(A))
nail.stick_to(A)
var/mob/living/L = A
L.take_overall_damage(damage,0)
else if(loc)
var/turf/T = get_turf(src)
nail.stick_to(T,get_dir(src,A))
bullet_die()
/obj/item/projectile/wraithnail/bump_original_check()
if(!bumped)
if(loc == get_turf(original))
if(!(original in permutated))
to_bump(original)
/obj/effect/overlay/wraithnail
name = "red bolt"
desc = "A pointy red nail, appearing to pierce not through what it rests upon, but through the fabric of reality itself."
icon = 'icons/effects/effects.dmi'
icon_state = "wraithnail"
anchored = 1
density = 0
plane = ABOVE_HUMAN_PLANE
layer = CLOSED_CURTAIN_LAYER
var/atom/stuck_to = null
var/duration = 100
/obj/effect/overlay/wraithnail/New()
..()
pixel_x = rand(-4, 4) * PIXEL_MULTIPLIER
pixel_y = rand(-4, 4) * PIXEL_MULTIPLIER
/obj/effect/overlay/wraithnail/Destroy()
if(stuck_to)
unlock_atom(stuck_to)
stuck_to = null
..()
/obj/effect/overlay/wraithnail/proc/stick_to(var/atom/A, var/side = null)
pixel_x = rand(-4, 4) * PIXEL_MULTIPLIER
pixel_y = rand(-4, 4) * PIXEL_MULTIPLIER
playsound(A, 'sound/items/metal_impact.ogg', 30, 1)
var/turf/T = get_turf(A)
loc = T
playsound(T, 'sound/weapons/hivehand_empty.ogg', 75, 1)
if(isturf(A))
switch(side)
if(NORTH)
pixel_y = WORLD_ICON_SIZE/2
if(SOUTH)
pixel_y = -WORLD_ICON_SIZE/2
if(EAST)
pixel_x = WORLD_ICON_SIZE/2
if(WEST)
pixel_x = -WORLD_ICON_SIZE/2
else if(isliving(A) && !isspace(T))
stuck_to = A
visible_message("<span class='warning'>\the [src] nails \the [A] to \the [T].</span>")
lock_atom(A, /datum/locking_category/buckle)
spawn(duration)
qdel(src)
/obj/effect/overlay/wraithnail/attack_hand(var/mob/user)
if (do_after(user,src,15))
unstick()
/obj/effect/overlay/wraithnail/proc/unstick()
if(stuck_to)
unlock_atom(stuck_to)
qdel(src)
////////////////////Artificer///////////////////////// ////////////////////Artificer/////////////////////////
@@ -405,7 +303,7 @@
if(layer != MOB_LAYER) // ie it's hiding if(layer != MOB_LAYER) // ie it's hiding
overlay_layer = FLOAT_LAYER overlay_layer = FLOAT_LAYER
overlay_plane = FLOAT_PLANE overlay_plane = FLOAT_PLANE
var/icon/glowicon = icon(icon,"glow-[icon_state]") var/icon/glowicon = icon(icon,"glow-[icon_state]")
glowicon.Blend(glowcolor, ICON_ADD) glowicon.Blend(glowcolor, ICON_ADD)
var/image/glow = image(icon = glowicon, layer = overlay_layer) var/image/glow = image(icon = glowicon, layer = overlay_layer)

View File

@@ -230,7 +230,7 @@
////////////////////////////// //////////////////////////////
// // // //
// BLOOD DAGGER /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // BLOOD NAIL ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //Used when a cultist throws a blood dagger // //Used when a cultist throws a blood dagger
////////////////////////////// //////////////////////////////
@@ -260,7 +260,26 @@
forceMove(A.loc) forceMove(A.loc)
var/mob/living/M = A var/mob/living/M = A
if (!iscultist(M)) if (!iscultist(M))
..() setDensity(FALSE)
invisibility = 101
kill_count = 0
var/obj/effect/overlay/bloodnail/nail = new (A.loc)
nail.transform = transform
if (color)
nail.color = color
else
nail.color = DEFAULT_BLOOD
if(isliving(A))
nail.stick_to(A)
var/mob/living/L = A
L.take_overall_damage(damage,0)
to_chat(L, "<span class='warning'>\The [src] stabs your body, sticking you in place.</span>")
to_chat(L, "<span class='danger'>Resist or click the nail to dislodge it.</span>")
else if(loc)
var/turf/T = get_turf(src)
nail.stick_to(T,get_dir(src,A))
bullet_die()
return
else if (ishuman(M)) else if (ishuman(M))
var/mob/living/carbon/human/H = M var/mob/living/carbon/human/H = M
var/datum/reagent/blood/B = get_blood(H.vessel) var/datum/reagent/blood/B = get_blood(H.vessel)
@@ -286,5 +305,64 @@
return 0 return 0
return 1 return 1
/obj/item/projectile/blooddagger/bump_original_check()
if(!bumped)
if(loc == get_turf(original))
if(!(original in permutated))
to_bump(original)
/obj/item/projectile/blooddagger/cultify() /obj/item/projectile/blooddagger/cultify()
return return
/obj/effect/overlay/bloodnail
name = "blood nail"
desc = "A pointy red nail, appearing to pierce not through what it rests upon, but through the fabric of reality itself."
icon = 'icons/effects/effects.dmi'
icon_state = "bloodnail"
anchored = 1
density = 0
plane = ABOVE_HUMAN_PLANE
layer = CLOSED_CURTAIN_LAYER
var/atom/stuck_to = null
var/duration = 100
/obj/effect/overlay/bloodnail/New()
..()
pixel_x = rand(-4, 4) * PIXEL_MULTIPLIER
pixel_y = rand(-4, 4) * PIXEL_MULTIPLIER
/obj/effect/overlay/bloodnail/Destroy()
if(stuck_to)
unlock_atom(stuck_to)
stuck_to = null
..()
/obj/effect/overlay/bloodnail/cultify()
return
/obj/effect/overlay/bloodnail/proc/stick_to(var/atom/A, var/side = null)
pixel_x = rand(-4, 4) * PIXEL_MULTIPLIER
pixel_y = rand(-4, 4) * PIXEL_MULTIPLIER
playsound(A, 'sound/items/metal_impact.ogg', 30, 1)
var/turf/T = get_turf(A)
playsound(T, 'sound/weapons/hivehand_empty.ogg', 75, 1)
if(isliving(A) && !isspace(T))//can't nail people down unless there's a turf to nail them to.
stuck_to = A
visible_message("<span class='warning'>\the [src] nails \the [A] to \the [T].</span>")
lock_atom(A, /datum/locking_category/buckle)
spawn(duration)
qdel(src)
/obj/effect/overlay/bloodnail/attack_hand(var/mob/user)
if (do_after(user,src,15))
unstick()
/obj/effect/overlay/bloodnail/proc/unstick()
if(stuck_to)
unlock_atom(stuck_to)
qdel(src)

View File

@@ -500,23 +500,31 @@
"Oh just fuck off",)].</span></span>") "Oh just fuck off",)].</span></span>")
/proc/write_rune_word(var/turf/T,var/datum/reagent/blood/source, var/word = null, var/mob/caster = null) /proc/write_rune_word(var/turf/T, var/word = null, var/datum/reagent/blood/source, var/mob/caster = null)
if (!word) if (!word)
return 0 return RUNE_WRITE_CANNOT
if (!source)
source = new
//Add word to a rune if there is one, otherwise create one. However, there can be no more than 3 words. //Add word to a rune if there is one, otherwise create one. However, there can be no more than 3 words.
//Returns 0 if failure, 1 if finished a rune, 2 if success but rune still has room for words. //Returns 0 if failure, 1 if finished a rune, 2 if success but rune still has room for words.
var/newrune = FALSE
var/obj/effect/rune/rune = locate() in T var/obj/effect/rune/rune = locate() in T
if(!rune) if(!rune)
var/datum/runeword/rune_typecast = word var/datum/runeword/rune_typecast = word
if(rune_typecast.identifier == "blood_cult") //Lazy fix because I'm not sure how to modularize this automatically. Fix if you want to. if(rune_typecast.identifier == "blood_cult") //Lazy fix because I'm not sure how to modularize this automatically. Fix if you want to.//WHYYYYYYYYYYY
rune = new /obj/effect/rune/blood_cult(T) rune = new /obj/effect/rune/blood_cult(T)
newrune = TRUE
if (rune.word1 && rune.word2 && rune.word3) if (rune.word1 && rune.word2 && rune.word3)
return 0 return RUNE_WRITE_CANNOT
if (caster) if (caster)
if (newrune)
log_admin("BLOODCULT: [key_name(caster)] has created a new rune at [T.loc] (@[T.x],[T.y],[T.z]).")
message_admins("BLOODCULT: [key_name(caster)] has created a new rune at [formatJumpTo(T)].")
rune.add_hiddenprint(caster) rune.add_hiddenprint(caster)
if (!rune.word1) if (!rune.word1)
@@ -577,8 +585,8 @@
rune.update_icon() rune.update_icon()
if (rune.blood3) if (rune.blood3)
return 1 return RUNE_WRITE_COMPLETE
return 2 return RUNE_WRITE_CONTINUE
/proc/erase_rune_word(var/turf/T) /proc/erase_rune_word(var/turf/T)

View File

@@ -51,7 +51,7 @@ var/list/uristrune_cache = list()
to_chat(user, "<span class='warning'>This type of rune is incompatible with the one on the ground.</span>") to_chat(user, "<span class='warning'>This type of rune is incompatible with the one on the ground.</span>")
return return
var/datum/runeset/rune_set = global_runesets[runeset_identifier] var/datum/runeset/rune_set = global_runesets[runeset_identifier]
if(write_rune_word(get_turf(user), data["blood"], word = rune_set.words[word], caster = user) > 1) if(write_rune_word(get_turf(user), rune_set.words[word], data["blood"], caster = user) == RUNE_WRITE_CONTINUE)
continue_drawing = 1 continue_drawing = 1
perform(user) //Recursion for drawing runes in a row with tome. perform(user) //Recursion for drawing runes in a row with tome.
@@ -198,7 +198,7 @@ var/list/uristrune_cache = list()
to_chat(user, "<span class='warning'>This type of rune is incompatible with the one on the ground.</span>") to_chat(user, "<span class='warning'>This type of rune is incompatible with the one on the ground.</span>")
return return
var/datum/runeset/rune_set = global_runesets[runeset_identifier] var/datum/runeset/rune_set = global_runesets[runeset_identifier]
if(write_rune_word(get_turf(user), data["blood"], word = rune_set.words[word], caster = user) > 1) if(write_rune_word(get_turf(user), rune_set.words[word], data["blood"], caster = user) == RUNE_WRITE_CONTINUE)
continue_drawing = 1 continue_drawing = 1
perform(user) //Recursion for drawing runes in a row with tome. perform(user) //Recursion for drawing runes in a row with tome.
else else

View File

@@ -15,6 +15,8 @@
anchored = 1.0 anchored = 1.0
w_type=NOT_RECYCLABLE w_type=NOT_RECYCLABLE
var/undergoing_deletion = 0 var/undergoing_deletion = 0
var/connects_atmos = TRUE//Set to FALSE to prevent portals from linking atmos
var/marke_sparks = TRUE//Set to FALSE to prevent portals from linking atmos
var/atmos_connected = FALSE var/atmos_connected = FALSE
var/connection/atmos_connection var/connection/atmos_connection
@@ -67,8 +69,9 @@
qdel(src) qdel(src)
return return
spawn(5) if (connects_atmos)
connect_atmospheres() spawn(5)
connect_atmospheres()
make_lifespan(lifespan) make_lifespan(lifespan)
@@ -125,7 +128,8 @@
else if(src == P.red_portal) else if(src == P.red_portal)
P.red_portal = null P.red_portal = null
P.sync_portals() P.sync_portals()
spark(loc, 5) if (marke_sparks)
spark(loc, 5)
..() ..()
/obj/effect/portal/cultify() /obj/effect/portal/cultify()
@@ -137,6 +141,9 @@
/obj/effect/portal/singularity_pull() /obj/effect/portal/singularity_pull()
return return
/obj/effect/portal/proc/portal_sickness(var/atom/movable/AM)
return
var/list/portal_cache = list() var/list/portal_cache = list()
@@ -167,6 +174,7 @@ var/list/portal_cache = list()
qdel(src) qdel(src)
else else
do_teleport(M, target, 0, 1, 1, 1, enter_sound, exit_sound) do_teleport(M, target, 0, 1, 1, 1, enter_sound, exit_sound)
portal_sickness(M)
if(ismob(M)) if(ismob(M))
var/mob/target = M var/mob/target = M
if(target.mind && owner) if(target.mind && owner)
@@ -240,6 +248,51 @@ var/list/portal_cache = list()
enter_sound = 'sound/effects/fall2.ogg' enter_sound = 'sound/effects/fall2.ogg'
exit_sound = 'sound/effects/fall2.ogg' exit_sound = 'sound/effects/fall2.ogg'
/obj/effect/portal/tear/blood
name = "bloody tear"
desc = "There's no shortcuts like ones that go through literal hellscapes."
close_sound = 'sound/effects/flesh_squelch.ogg'
icon_state = "bloodytear"
mask = "bloodytear_mask"
connects_atmos = FALSE
marke_sparks = FALSE
/obj/effect/portal/tear/blood/New(turf/loc,var/lifespan=300)
..()
if (loc && !istype(loc, /turf/space) && (!locate(/obj/effect/decal/cleanable/blood/splatter) in loc))
var/obj/effect/decal/cleanable/blood/splatter/S = new (loc)
S.amount = 1
/obj/effect/portal/tear/blood/Destroy()
if (loc)
anim(target = loc, a_icon = 'icons/obj/stationobjs.dmi', flick_anim = "bloodytear_close")
..()
/obj/effect/portal/tear/blood/portal_sickness(var/atom/movable/AM)
if (isliving(AM))
var/mob/living/L = AM
if (!iscultist(L) && iscarbon(L))
var/mob/living/carbon/C = L
new /obj/effect/cult_ritual/confusion(C,30,25,C)
C.reagents.add_reagent(TOXIN, 0.2)
C.reagents.add_reagent(INCENSE_MOONFLOWERS, 0.5)
C.hallucination = max(10,C.hallucination)
C.Dizzy(3)
C.Jitter(3)
C.reagents.update_total()
/obj/effect/portal/tear/blood/blend_icon(var/obj/effect/portal/P)
flick("bloodytear_open",src)
var/turf/T = P.loc
spawn(7)
if (!gcDestroyed && !P.gcDestroyed)
if(!("icon[initial(T.icon)]_iconstate[T.icon_state]_[type]" in portal_cache))//If the icon has not been added yet
var/icon/I1 = icon(icon,mask)//Generate it.
var/icon/I2 = icon(initial(T.icon),T.icon_state)
I1.Blend(I2,ICON_MULTIPLY)
portal_cache["icon[initial(T.icon)]_iconstate[T.icon_state]_[type]"] = I1 //And cache it!
overlays += portal_cache["icon[initial(T.icon)]_iconstate[T.icon_state]_[type]"]
/obj/effect/portal/permanent /obj/effect/portal/permanent
name = "stabilized portal" name = "stabilized portal"

View File

@@ -525,9 +525,36 @@
else else
return ..() return ..()
/obj/structure/constructshell/attack_construct(var/mob/user)
if (istype(user, /mob/living/simple_animal/construct/builder))
for (var/obj/item/soulstone/gem/gem in range(1,user))
create_construct(gem, user)
return 1
to_chat(user, "<span class='warning'>If there was a soul gem near you, you could set it inside this shell.</span>")
return 1
return 0
/obj/structure/constructshell/proc/make_shade_beacon(var/obj/item/soulstone/stone, var/mob/user)
return FALSE
/obj/structure/constructshell/cult/alt/make_shade_beacon(var/obj/item/soulstone/gem/gem, var/mob/user)
if (istype(gem))
qdel(gem)
var/obj/structure/shadebeacon/newbeacon = new (loc)
if (fingerprints)
newbeacon.fingerprints = fingerprints.Copy()
to_chat(user, "<span class='notice'>You've set \the [gem] onto \the [src]. A wandering shade can use it to become a construct by itself.</span>")
return TRUE
return FALSE
//Making a Construct //Making a Construct
/obj/structure/constructshell/proc/create_construct(var/obj/item/soulstone/stone, var/mob/user) /obj/structure/constructshell/proc/create_construct(var/obj/item/soulstone/stone, var/mob/user)
if (!stone.shade) if (!stone.shade)
if (make_shade_beacon(stone,user))
qdel(src)
return
to_chat(user, "<span class='warning'>\The [stone] is empty! The shell doesn't react.</span>") to_chat(user, "<span class='warning'>\The [stone] is empty! The shell doesn't react.</span>")
return return
@@ -541,11 +568,11 @@
var/list/choices = list( var/list/choices = list(
list("Artificer", "radial_artificer[perfect ? "2" : ""]", "Though fragile, this construct can reshape its surroundings, conjuring walls, floors, and most importantly, repair other constructs. Additionally, they may operate some cult structures.[perfect ? " <b>Can open gateways to summon eldritch monsters from the realm of Nar-Sie.</b>" : ""]"), list("Artificer", "radial_artificer[perfect ? "2" : ""]", "Though fragile, this construct can reshape its surroundings, conjuring walls, floors, and most importantly, repair other constructs. Additionally, they may operate some cult structures.[perfect ? " <b>Can open gateways to summon eldritch monsters from the realm of Nar-Sie.</b>" : ""]"),
list("Wraith", "radial_wraith[perfect ? "2" : ""]", "The fastest of deadliest of constructs, at the cost of a relatively fragile build. Can easily scout and escape by phasing through the veil. Its claws can pry open unpowered airlocks.[perfect ? " <b>Can fire bolts that nail their victims to the floor.</b>" : ""]"), list("Wraith", "radial_wraith[perfect ? "2" : ""]", "The fastest of deadliest of constructs, at the cost of a relatively fragile build. Can easily scout and escape by phasing through the veil. Its claws can pry open unpowered airlocks.[perfect ? " <b>Can fire bolts that nail their victims to the floor.</b>" : ""]"),
list("Juggernaut", "radial_juggernaut[perfect ? "2" : ""]", "Sturdy, powerful, at the cost of a snail's pace. However, its fists can break walls apart, along with some machinery. Can conjure a temporary forcefield.[perfect ? " <b>Can dash forward over a large distance, knocking down anyone in front of them.</b>" : ""]"), list("Juggernaut", "radial_juggernaut[perfect ? "2" : ""]", "Sturdy, powerful, at the cost of a snail's pace. However, its fists can break walls apart, along with some machinery. Can conjure a temporary forcefield.[perfect ? " <b>Can dash forward over a small distance, knocking down anyone in front of them for a second.</b>" : ""]"),
) )
var/construct_class = show_radial_menu(user,src,choices,'icons/obj/cult_radial3.dmi',"radial-cult2") var/construct_class = show_radial_menu(user,src,choices,'icons/obj/cult_radial3.dmi',"radial-cult2")
if (!Adjacent(user) || (stone != user.get_active_hand()) || !construct_class || soul.loc != stone) if (!Adjacent(user) || (!isconstruct(user) && stone != user.get_active_hand()) || (isconstruct(user) && !stone.Adjacent(user)) || !construct_class || soul.loc != stone)
return//sanity check after we've picked a construct class return//sanity check after we've picked a construct class
switch(construct_class) switch(construct_class)
@@ -559,7 +586,7 @@
to_chat(new_construct, "<B>You are a Juggernaut. Though slow, your shell can withstand extreme punishment, your body can reflect energy and laser weapons, and you can create temporary shields that blocks pathing and projectiles. You fists can punch people and regular walls apart.</B>") to_chat(new_construct, "<B>You are a Juggernaut. Though slow, your shell can withstand extreme punishment, your body can reflect energy and laser weapons, and you can create temporary shields that blocks pathing and projectiles. You fists can punch people and regular walls apart.</B>")
if (perfect) if (perfect)
flick("make_juggernaut2", new_construct) flick("make_juggernaut2", new_construct)
to_chat(new_construct, "<B>You can dash over a large distance, knocking down anyone on your path.</B>") to_chat(new_construct, "<B>You can dash over a small distance, knocking down anyone on your path for a second.</B>")
to_chat(new_construct, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>") to_chat(new_construct, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>")
new_construct.cancel_camera() new_construct.cancel_camera()
@@ -606,3 +633,101 @@
qdel(A) qdel(A)
qdel(stone) qdel(stone)
qdel(src) qdel(src)
/////////////////////////////////////////SHADE BEACONS//////////////////////////////////////////////
//cult 3.0 shells with a gem already set on them, allowing shades to become constructs by themselves.
/obj/structure/shadebeacon
name = "shade beacon"
icon = 'icons/obj/cult.dmi'
icon_state = "beacon"
desc = "This shell has been fit with an empty soul gem. Maybe a shade could make use of it."
flags = FPRINT
/obj/structure/shadebeacon/cultify()
return
/obj/structure/shadebeacon/attack_hand(var/mob/user)
if (iscarbon(user))
user.put_in_active_hand(new /obj/item/soulstone/gem(loc))
var/obj/structure/constructshell/cult/alt/newshell = new (loc)
if (fingerprints)
newshell.fingerprints = fingerprints.Copy()
qdel(src)
return 1
return ..()
/obj/structure/shadebeacon/attack_animal(var/mob/user)
if (istype(user, /mob/living/simple_animal/construct/builder))
new /obj/item/soulstone/gem(loc)
var/obj/structure/constructshell/cult/alt/newshell = new (loc)
newshell.fingerprints = fingerprints.Copy()
qdel(src)
return 1
if (istype(user, /mob/living/simple_animal/shade))
create_construct(user)
return 0
/obj/structure/shadebeacon/proc/create_construct(var/mob/living/simple_animal/shade/user)
var/mob/living/simple_animal/construct/new_construct
var/list/choices = list(
list("Artificer", "radial_artificer2", "Though fragile, this construct can reshape its surroundings, conjuring walls, floors, and most importantly, repair other constructs. Additionally, they may operate some cult structures. <b>Can open gateways to summon eldritch monsters from the realm of Nar-Sie.</b>"),
list("Wraith", "radial_wraith2", "The fastest of deadliest of constructs, at the cost of a relatively fragile build. Can easily scout and escape by phasing through the veil. Its claws can pry open unpowered airlocks. <b>Can fire bolts that nail their victims to the floor.</b>"),
list("Juggernaut", "radial_juggernaut2", "Sturdy, powerful, at the cost of a snail's pace. However, its fists can break walls apart, along with some machinery. Can conjure a temporary forcefield. <b>Can dash forward over a small distance, knocking down anyone in front of them for a second.</b>"),
)
var/construct_class = show_radial_menu(user,src,choices,'icons/obj/cult_radial3.dmi',"radial-cult2")
if (!Adjacent(user) || !construct_class)
return
switch(construct_class)
if("Juggernaut")
new_construct = new /mob/living/simple_animal/construct/armoured/perfect(get_turf(src.loc))
new_construct.setup_type(user)
new_construct.real_name = user.real_name
user.mind.transfer_to(new_construct)
to_chat(new_construct, "<B>You are a Juggernaut. Though slow, your shell can withstand extreme punishment, your body can reflect energy and laser weapons, and you can create temporary shields that blocks pathing and projectiles. You fists can punch people and regular walls apart.</B>")
flick("make_juggernaut2", new_construct)
to_chat(new_construct, "<B>You can dash over a small distance, knocking down anyone on your path for a second.</B>")
to_chat(new_construct, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>")
if (!iscultist(new_construct))
to_chat(new_construct, "<B>As a self-made construct, you are unbounded from anyone's will.</B>")
new_construct.cancel_camera()
if("Wraith")
new_construct = new /mob/living/simple_animal/construct/wraith/perfect(get_turf(src.loc))
new_construct.setup_type(user)
new_construct.real_name = user.real_name
user.mind.transfer_to(new_construct)
to_chat(new_construct, "<B>You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls for a few seconds. Use it both for surprise attacks and strategic retreats.</B>")
flick("make_wraith2", new_construct)
to_chat(new_construct, "<B>You can fire red bolts that can temporarily prevent their victims from moving. You recharge a bolt every 5 seconds, up to 3 bolts.</B>")
to_chat(new_construct, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>")
if (!iscultist(new_construct))
to_chat(new_construct, "<B>As a self-made construct, you are unbounded from anyone's will.</B>")
new_construct.cancel_camera()
if("Artificer")
new_construct = new /mob/living/simple_animal/construct/builder/perfect(get_turf(src.loc))
new_construct.setup_type(user)
new_construct.real_name = user.real_name
user.mind.transfer_to(new_construct)
to_chat(new_construct, "<B>You are an Artificer. You are incredibly weak and fragile, but you can heal both yourself and other constructs (by clicking on yourself/them). You can build (and deconstruct) new walls and floors, or replace existing ones by clicking on them, as well as place pylons that act as light source (these block paths but can be easily broken),</B><I>and most important of all you can produce the tools to create new constructs</I><B> (remember to periodically produce new soulstones for your master, and place empty shells in your hideout or when asked.).</B>")
flick("make_artificer2", new_construct)
to_chat(new_construct, "<B>You can channel a gateway from the realm of Nar-Sie to summon a minion to protect an area.</B>")
if (!iscultist(new_construct))
to_chat(new_construct, "<B>As a self-made construct, you are unbounded from anyone's will.</B>")
new_construct.cancel_camera()
if (!new_construct)
return
new_construct.name = "[new_construct.real_name] the [construct_class]"
qdel(user)
qdel(src)

View File

@@ -115,6 +115,11 @@
construct_color = rgb(30,255,30) construct_color = rgb(30,255,30)
else else
construct_color = rgb(235,0,0) construct_color = rgb(235,0,0)
else if (istype(creator, /mob/living/simple_animal/shade))//shade beacon
if (iscultist(creator))
construct_color = rgb(235,0,0)
else
construct_color = rgb(0, 153, 255)
setupglow() setupglow()
/mob/living/simple_animal/construct/Login() /mob/living/simple_animal/construct/Login()
@@ -265,8 +270,8 @@
icon_living = "floating" icon_living = "floating"
maxHealth = 75 maxHealth = 75
health = 75 health = 75
melee_damage_lower = 25 melee_damage_lower = 15
melee_damage_upper = 25 melee_damage_upper = 15
attacktext = "slashes" attacktext = "slashes"
speed = 1 speed = 1
environment_smash_flags = SMASH_LIGHT_STRUCTURES | SMASH_CONTAINERS | OPEN_DOOR_WEAK environment_smash_flags = SMASH_LIGHT_STRUCTURES | SMASH_CONTAINERS | OPEN_DOOR_WEAK
@@ -301,8 +306,8 @@
icon = 'icons/mob/mob.dmi' icon = 'icons/mob/mob.dmi'
icon_state = "artificer" icon_state = "artificer"
icon_living = "artificer" icon_living = "artificer"
maxHealth = 50 maxHealth = 100
health = 50 health = 100
response_harm = "viciously beats" response_harm = "viciously beats"
harm_intent_damage = 5 harm_intent_damage = 5
melee_damage_lower = 5 melee_damage_lower = 5
@@ -503,19 +508,19 @@
if(healths) if(healths)
switch(health) switch(health)
if(50 to INFINITY) if(100 to INFINITY)
healths.icon_state = "artificer_health0" healths.icon_state = "artificer_health0"
if(42 to 49) if(84 to 99)
healths.icon_state = "artificer_health1" healths.icon_state = "artificer_health1"
if(34 to 41) if(68 to 83)
healths.icon_state = "artificer_health2" healths.icon_state = "artificer_health2"
if(26 to 33) if(52 to 67)
healths.icon_state = "artificer_health3" healths.icon_state = "artificer_health3"
if(18 to 25) if(36 to 51)
healths.icon_state = "artificer_health4" healths.icon_state = "artificer_health4"
if(10 to 17) if(20 to 35)
healths.icon_state = "artificer_health5" healths.icon_state = "artificer_health5"
if(1 to 9) if(1 to 19)
healths.icon_state = "artificer_health6" healths.icon_state = "artificer_health6"
else else
healths.icon_state = "artificer_health7" healths.icon_state = "artificer_health7"

View File

@@ -435,7 +435,7 @@ var/list/impact_master = list()
if(linear_movement) if(linear_movement)
var/matrix/projectile_matrix = turn(matrix(),target_angle+45) var/matrix/projectile_matrix = turn(matrix(),target_angle+45)
transform = projectile_matrix transform = projectile_matrix
icon_state = "[initial(icon_state)]_pixel" icon_state = "[icon_state]_pixel"
/* /*
//If the icon has not been added yet //If the icon has not been added yet
if( !("[icon_state]_angle[target_angle]" in bullet_master) ) if( !("[icon_state]_angle[target_angle]" in bullet_master) )

View File

@@ -336,32 +336,6 @@
side2 = null side2 = null
..() ..()
/spell/juggerdash
name = "Jugger-Dash"
desc = "Charge in a line and knock down anything in your way, even some walls."
user_type = USER_TYPE_CULT
hud_state = "const_juggdash"
override_base = "cult"
charge_max = 150
spell_flags = 0
var/dash_range = 4
/spell/juggerdash/choose_targets(var/mob/user = usr)
return list(user)
/spell/juggerdash/cast_check(var/skipcharge = FALSE, var/mob/user = usr)
if(user.throwing)
return FALSE
else
return ..()
/spell/juggerdash/cast(var/list/targets, var/mob/user)
playsound(user, 'sound/effects/juggerdash.ogg', 100, 1)
var/mob/living/simple_animal/construct/armoured/perfect/jugg = user
jugg.crashing = null
var/landing = get_distant_turf(get_turf(user), jugg.dir, dash_range)
jugg.throw_at(landing, dash_range , 2)
/spell/aoe_turf/conjure/hex /spell/aoe_turf/conjure/hex
name = "Conjure Hex" name = "Conjure Hex"
desc = "Build a lesser construct to defend an area." desc = "Build a lesser construct to defend an area."
@@ -452,6 +426,86 @@
summon_type = list(/obj/structure/cult/forge) summon_type = list(/obj/structure/cult/forge)
return 0 return 0
/spell/aoe_turf/conjure/path_entrance
name = "Path Entrance"
desc = "Place a shortcut through the veil between this world and the other one."
user_type = USER_TYPE_CULT
charge_max = 600
spell_flags = Z2NOCAST | CONSTRUCT_CHECK
invocation = "none"
invocation_type = SpI_NONE
range = 1
summon_type = list(/obj/effect/rune/blood_cult)
override_base = "cult"
hud_state = "const_entrance"
cast_sound = null
var/chosen_path = ""
/spell/aoe_turf/conjure/path_entrance/choose_targets(mob/user = usr)
return list(get_turf(user))
/spell/aoe_turf/conjure/path_entrance/before_channel(var/mob/user)
var/turf/T = get_turf(user)
var/obj/effect/rune/rune = locate() in T
if (rune)
to_chat(user,"<span class='warning'>You cannot draw on top of an already existing rune.</span>")
return 1
return 0
/spell/aoe_turf/conjure/path_entrance/on_creation(var/obj/effect/rune/R, var/mob/user)
var/turf/T = R.loc
log_admin("BLOODCULT: [key_name(user)] has created a new rune at [T.loc] (@[T.x],[T.y],[T.z]).")
message_admins("BLOODCULT: [key_name(user)] has created a new rune at [T.loc] <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a>.")
var/datum/runeset/rune_set = global_runesets["blood_cult"]
write_rune_word(R.loc, rune_set.words["travel"])
write_rune_word(R.loc, rune_set.words["self"])
write_rune_word(R.loc, rune_set.words["other"])
R.one_pulse()
/spell/aoe_turf/conjure/path_exit
name = "Path Entrance"
desc = "Place a shortcut through the veil between this world and the other one."
user_type = USER_TYPE_CULT
charge_max = 600
spell_flags = Z2NOCAST | CONSTRUCT_CHECK
invocation = "none"
invocation_type = SpI_NONE
range = 1
summon_type = list(/obj/effect/rune/blood_cult)
override_base = "cult"
hud_state = "const_exit"
cast_sound = null
var/chosen_path = ""
/spell/aoe_turf/conjure/path_exit/choose_targets(mob/user = usr)
return list(get_turf(user))
/spell/aoe_turf/conjure/path_exit/before_channel(var/mob/user)
var/turf/T = get_turf(user)
var/obj/effect/rune/rune = locate() in T
if (rune)
to_chat(user,"<span class='warning'>You cannot draw on top of an already existing rune.</span>")
return 1
return 0
/spell/aoe_turf/conjure/path_exit/on_creation(var/obj/effect/rune/R, var/mob/user)
var/turf/T = R.loc
log_admin("BLOODCULT: [key_name(user)] has created a new rune at [T.loc] (@[T.x],[T.y],[T.z]).")
message_admins("BLOODCULT: [key_name(user)] has created a new rune at [T.loc] <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a>.")
var/datum/runeset/rune_set = global_runesets["blood_cult"]
write_rune_word(R.loc, rune_set.words["travel"])
write_rune_word(R.loc, rune_set.words["other"])
write_rune_word(R.loc, rune_set.words["self"])
R.one_pulse()
/obj/effect/artificer_underlay /obj/effect/artificer_underlay
icon = 'icons/obj/cult.dmi' icon = 'icons/obj/cult.dmi'
icon_state = "build" icon_state = "build"

View File

@@ -10,3 +10,69 @@ proc/findNullRod(var/atom/target)
if(findNullRod(A)) if(findNullRod(A))
return 1 return 1
return 0 return 0
///////////////////////////////////JUGGERNAUT///////////////////////////////////////
/spell/juggerdash
name = "Jugger-Dash"
desc = "Charge in a line and knock down anything in your way, even some walls."
user_type = USER_TYPE_CULT
hud_state = "const_juggdash"
override_base = "cult"
charge_max = 150
spell_flags = 0
var/dash_range = 4
/spell/juggerdash/choose_targets(var/mob/user = usr)
return list(user)
/spell/juggerdash/cast_check(var/skipcharge = FALSE, var/mob/user = usr)
if(user.throwing)
return FALSE
else
return ..()
/spell/juggerdash/cast(var/list/targets, var/mob/user)
playsound(user, 'sound/effects/juggerdash.ogg', 100, 1)
var/mob/living/simple_animal/construct/armoured/perfect/jugg = user
jugg.crashing = null
var/landing = get_distant_turf(get_turf(user), jugg.dir, dash_range)
jugg.throw_at(landing, dash_range , 2)
///////////////////////////////////WRAITH///////////////////////////////////////
/spell/wraith_warp
name = "Wraith Tear"
desc = "This spell lets you cut through space itself to quickly get around. You can also perform a throw to cast this spell."
user_type = USER_TYPE_CULT
selection_type = "range"
charge_max = 75
spell_flags = Z2NOCAST | CONSTRUCT_CHECK | WAIT_FOR_CLICK
invocation = "none"
invocation_type = SpI_NONE
range = 7
override_base = "cult"
hud_state = "const_warp"
cast_sound = null
/spell/wraith_warp/channel_spell(mob/user = usr, skipcharge = 0, force_remove = 0)
if(!..())
return 0
return 1
/spell/wraith_warp/is_valid_target(var/target, mob/user, options)
return (target in view_or_range(range, user, selection_type))
/spell/wraith_warp/cast(list/targets, mob/user)
var/obj/effect/portal/tear/blood/P1 = new (get_turf(user),3 SECONDS)
var/obj/effect/portal/tear/blood/P2 = new (get_turf(pick(targets)),3 SECONDS)
P1.target = P2
P2.target = P1
P1.blend_icon(P2)
P2.blend_icon(P1)
P1.owner = user
P2.owner = user
P1.teleport(user)

View File

@@ -158,7 +158,7 @@
/spell/targeted/ethereal_jaunt/shift/alt /spell/targeted/ethereal_jaunt/shift/alt
desc = "Vibrate through the veil for about 5 seconds, letting you move around freely through any obstacle." desc = "Vibrate through the veil for about 5 seconds, letting you move around freely through any obstacle."
charge_max = 170 charge_max = 150
hud_state = "const_phase" hud_state = "const_phase"
enteranim = "wraith2_phaseenter" enteranim = "wraith2_phaseenter"
exitanim = "wraith2_phaseexit" exitanim = "wraith2_phaseexit"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 528 KiB

After

Width:  |  Height:  |  Size: 528 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 115 KiB