Updates and replaces simple_animal constructs

This commit is contained in:
Anewbe
2018-07-25 17:28:17 -05:00
parent 64d16a0a56
commit 807a765c56
19 changed files with 754 additions and 772 deletions

View File

@@ -277,10 +277,10 @@
if("coffee") M.change_mob_type( /mob/living/simple_animal/crab/Coffee , null, null, delmob )
if("parrot") M.change_mob_type( /mob/living/simple_animal/parrot , null, null, delmob )
if("polyparrot") M.change_mob_type( /mob/living/simple_animal/parrot/Poly , null, null, delmob )
if("constructarmoured") M.change_mob_type( /mob/living/simple_animal/construct/armoured , null, null, delmob )
if("constructbuilder") M.change_mob_type( /mob/living/simple_animal/construct/builder , null, null, delmob )
if("constructwraith") M.change_mob_type( /mob/living/simple_animal/construct/wraith , null, null, delmob )
if("shade") M.change_mob_type( /mob/living/simple_animal/shade , null, null, delmob )
if("constructarmoured") M.change_mob_type( /mob/living/simple_mob/construct/juggernaut , null, null, delmob )
if("constructbuilder") M.change_mob_type( /mob/living/simple_mob/construct/artificer , null, null, delmob )
if("constructwraith") M.change_mob_type( /mob/living/simple_mob/construct/wraith , null, null, delmob )
if("shade") M.change_mob_type( /mob/living/simple_mob/construct/shade , null, null, delmob )
/////////////////////////////////////new ban stuff

View File

@@ -28,7 +28,7 @@
/mob/living/simple_animal/seen_cult_turfs()
return seen_turfs_in_range(src, 1)
/mob/living/simple_animal/shade/narsie/seen_cult_turfs()
/mob/living/simple_mob/construct/shade/seen_cult_turfs()
return view(2, src)
/proc/seen_turfs_in_range(var/source, var/range)

View File

@@ -1,488 +0,0 @@
/mob/living/simple_animal/construct
name = "Construct"
real_name = "Construct"
var/construct_type = "shade"
desc = ""
speak_emote = list("hisses")
emote_hear = list("wails","screeches")
ui_icons = 'icons/mob/screen1_construct.dmi'
has_hands = 1
hand_form = "stone manipulators"
response_help = "thinks better of touching"
response_disarm = "flailed at"
response_harm = "punched"
intelligence_level = SA_HUMANOID // Player controlled.
hovering = TRUE
softfall = TRUE //Beings made of Hellmarble and powered by the tears of the damned are not concerned with mortal things such as 'gravity'.
parachuting = TRUE
icon_dead = "shade_dead"
var/do_glow = 1
speed = -1
a_intent = I_HURT
stop_automated_movement = 1
status_flags = CANPUSH
universal_speak = 0
universal_understand = 1
attack_sound = 'sound/weapons/spiderlunge.ogg'
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
minbodytemp = 0
show_stat_health = 1
faction = "cult"
supernatural = 1
see_invisible = SEE_INVISIBLE_NOLIGHTING
see_in_dark = 7
var/nullblock = 0
mob_swap_flags = HUMAN|SIMPLE_ANIMAL|SLIME|MONKEY
mob_push_flags = ALLMOBS
var/list/construct_spells = list()
can_be_antagged = TRUE
taser_kill = 0 // no
shock_resistance = 0.9 //Electricity isn't very effective on stone, especially that from hell.
armor = list(
"melee" = 10,
"bullet" = 10,
"laser" = 10,
"energy" = 10,
"bomb" = 10,
"bio" = 100,
"rad" = 100)
/mob/living/simple_animal/construct/place_spell_in_hand(var/path)
if(!path || !ispath(path))
return 0
//var/obj/item/weapon/spell/S = new path(src)
var/obj/item/weapon/spell/construct/S = new path(src)
//No hands needed for innate casts.
if(S.cast_methods & CAST_INNATE)
if(S.run_checks())
S.on_innate_cast(src)
if(l_hand && r_hand) //Make sure our hands aren't full.
if(istype(r_hand, /obj/item/weapon/spell)) //If they are full, perhaps we can still be useful.
var/obj/item/weapon/spell/r_spell = r_hand
if(r_spell.aspect == ASPECT_CHROMATIC) //Check if we can combine the new spell with one in our hands.
r_spell.on_combine_cast(S, src)
else if(istype(l_hand, /obj/item/weapon/spell))
var/obj/item/weapon/spell/l_spell = l_hand
if(l_spell.aspect == ASPECT_CHROMATIC) //Check the other hand too.
l_spell.on_combine_cast(S, src)
else //Welp
to_chat(src, "<span class='warning'>You require a free manipulator to use this power.</span>")
return 0
if(S.run_checks())
put_in_hands(S)
return 1
else
qdel(S)
return 0
/mob/living/simple_animal/construct/cultify()
return
/mob/living/simple_animal/construct/New()
..()
name = text("[initial(name)] ([rand(1, 1000)])")
real_name = name
add_language("Cult")
add_language("Occult")
for(var/spell in construct_spells)
src.add_spell(new spell, "const_spell_ready")
updateicon()
/mob/living/simple_animal/construct/updateicon()
overlays.Cut()
..()
if(do_glow)
add_glow()
/mob/living/simple_animal/construct/update_icon()
..()
if(do_glow)
add_glow()
/mob/living/simple_animal/construct/death()
new /obj/item/weapon/ectoplasm (src.loc)
..(null,"collapses in a shattered heap.")
ghostize()
qdel(src)
/mob/living/simple_animal/construct/attack_generic(var/mob/user)
if(istype(user, /mob/living/simple_animal/construct/builder))
var/mob/living/simple_animal/construct/builder/B = user
if(health < getMaxHealth())
var/repair_lower_bound = B.melee_damage_lower * -1
var/repair_upper_bound = B.melee_damage_upper * -1
adjustBruteLoss(rand(repair_lower_bound, repair_upper_bound))
adjustFireLoss(rand(repair_lower_bound, repair_upper_bound))
user.visible_message("<span class='notice'>\The [user] mends some of \the [src]'s wounds.</span>")
else
to_chat(user, "<span class='notice'>\The [src] is undamaged.</span>")
return
return ..()
/mob/living/simple_animal/construct/examine(mob/user)
..(user)
var/msg = "<span cass='info'>*---------*\nThis is \icon[src] \a <EM>[src]</EM>!\n"
if (src.health < src.getMaxHealth())
msg += "<span class='warning'>"
if (src.health >= src.getMaxHealth()/2)
msg += "It looks slightly dented.\n"
else
msg += "<B>It looks severely dented!</B>\n"
msg += "</span>"
msg += "*---------*</span>"
user << msg
/mob/living/simple_animal/construct/Process_Spacemove()
return 1 //Constructs levitate, can fall from a shuttle with no harm, and are piloted by either damned spirits or some otherworldly entity. It's not hard to believe.
/////////////////Juggernaut///////////////
/mob/living/simple_animal/construct/armoured
name = "Juggernaut"
real_name = "Juggernaut"
construct_type = "juggernaut"
desc = "A possessed suit of armour driven by the will of the restless dead"
icon = 'icons/mob/mob.dmi'
icon_state = "behemoth"
icon_living = "behemoth"
maxHealth = 300
health = 300
response_harm = "harmlessly punches"
harm_intent_damage = 0
melee_damage_lower = 30
melee_damage_upper = 40
attack_armor_pen = 60 //Being punched by a living, floating statue.
attacktext = list("smashed their armoured gauntlet into")
friendly = list("pats")
mob_size = MOB_HUGE
speed = 2 //Not super fast, but it might catch up to someone in armor who got punched once or twice.
environment_smash = 2
attack_sound = 'sound/weapons/heavysmash.ogg'
status_flags = 0
resistance = 10
construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser,
/spell/targeted/fortify,
/spell/targeted/construct_advanced/slam
)
armor = list(
"melee" = 70,
"bullet" = 30,
"laser" = 30,
"energy" = 30,
"bomb" = 10,
"bio" = 100,
"rad" = 100)
/mob/living/simple_animal/construct/armoured/Life()
weakened = 0
..()
/mob/living/simple_animal/construct/armoured/bullet_act(var/obj/item/projectile/P)
// if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) //If it's going to be slow, it's probably going to need every reflect it can get.
var/reflectchance = 80 - round(P.damage/3)
if(prob(reflectchance))
var/damage_mod = rand(2,4)
var/projectile_dam_type = P.damage_type
var/incoming_damage = (round(P.damage / damage_mod) - (round((P.damage / damage_mod) * 0.3)))
var/armorcheck = run_armor_check(null, P.check_armour)
var/soakedcheck = get_armor_soak(null, P.check_armour)
if(!(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)))
visible_message("<span class='danger'>The [P.name] bounces off of [src]'s shell!</span>", \
"<span class='userdanger'>The [P.name] bounces off of [src]'s shell!</span>")
new /obj/item/weapon/material/shard/shrapnel(src.loc)
if(!(P.damage_type == BRUTE || P.damage_type == BURN))
projectile_dam_type = BRUTE
incoming_damage = round(incoming_damage / 4) //Damage from strange sources is converted to brute for physical projectiles, though severely decreased.
apply_damage(incoming_damage, projectile_dam_type, null, armorcheck, soakedcheck, is_sharp(P), has_edge(P), P)
return -1 //Doesn't reflect non-beams or non-energy projectiles. They just smack and drop with little to no effect.
else
visible_message("<span class='danger'>The [P.name] gets reflected by [src]'s shell!</span>", \
"<span class='userdanger'>The [P.name] gets reflected by [src]'s shell!</span>")
damage_mod = rand(3,5)
incoming_damage = (round(P.damage / damage_mod) - (round((P.damage / damage_mod) * 0.3)))
if(!(P.damage_type == BRUTE || P.damage_type == BURN))
projectile_dam_type = BURN
incoming_damage = round(incoming_damage / 4) //Damage from strange sources is converted to burn for energy-type projectiles, though severely decreased.
apply_damage(incoming_damage, P.damage_type, null, armorcheck, soakedcheck, is_sharp(P), has_edge(P), P)
// Find a turf near or on the original location to bounce to
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
var/turf/curloc = get_turf(src)
// redirect the projectile
P.redirect(new_x, new_y, curloc, src)
P.reflected = 1
return -1 // complete projectile permutation
return (..(P))
////////////////////////Wraith/////////////////////////////////////////////
/mob/living/simple_animal/construct/wraith
name = "Wraith"
real_name = "Wraith"
construct_type = "wraith"
desc = "A wicked bladed shell contraption piloted by a bound spirit."
icon = 'icons/mob/mob.dmi'
icon_state = "floating"
icon_living = "floating"
maxHealth = 200
health = 200
melee_damage_lower = 25
melee_damage_upper = 30
attack_armor_pen = 15
attack_sharp = 1
attack_edge = 1
attacktext = list("slashed")
friendly = list("pinches")
speed = -1
environment_smash = 1
attack_sound = 'sound/weapons/rapidslice.ogg'
construct_spells = list(/spell/targeted/ethereal_jaunt/shift,
/spell/targeted/ambush_mode
)
/mob/living/simple_animal/construct/wraith/DoPunch(var/atom/A)
. = ..()
if(. && isliving(A))
var/mob/living/L = A
L.add_modifier(/datum/modifier/deep_wounds, 30 SECONDS)
/////////////////////////////Artificer/////////////////////////
/mob/living/simple_animal/construct/builder
name = "Artificer"
real_name = "Artificer"
construct_type = "artificer"
desc = "A bulbous construct dedicated to building and maintaining temples to their otherworldly lords."
icon = 'icons/mob/mob.dmi'
icon_state = "artificer"
icon_living = "artificer"
maxHealth = 150
health = 150
response_harm = "viciously beaten"
harm_intent_damage = 5
melee_damage_lower = 15 //It's not the strongest of the bunch, but that doesn't mean it can't hurt you.
melee_damage_upper = 20
attacktext = list("rammed")
speed = 0
environment_smash = 2
attack_sound = 'sound/weapons/rapidslice.ogg'
construct_spells = list(/spell/aoe_turf/conjure/construct/lesser,
/spell/aoe_turf/conjure/wall,
/spell/aoe_turf/conjure/floor,
/spell/aoe_turf/conjure/soulstone,
/spell/aoe_turf/conjure/pylon,
/spell/aoe_turf/conjure/door,
/spell/aoe_turf/conjure/grille,
/spell/targeted/occult_repair_aura,
/spell/targeted/construct_advanced/mend_acolyte
)
/////////////////////////////Behemoth/////////////////////////
/*
* The Behemoth. Admin-allowance only, still try to keep it in some guideline of 'Balanced', even if it means Security has to be fully geared to be so.
*/
/mob/living/simple_animal/construct/behemoth
name = "Behemoth"
real_name = "Behemoth"
construct_type = "juggernaut"
desc = "The pinnacle of occult technology, Behemoths are nothing shy of both an Immovable Object, and Unstoppable Force."
icon = 'icons/mob/mob.dmi'
icon_state = "behemoth"
icon_living = "behemoth"
maxHealth = 750
health = 750
speak_emote = list("rumbles")
response_harm = "harmlessly punched"
harm_intent_damage = 0
melee_damage_lower = 50
melee_damage_upper = 50
attacktext = list("brutally crushed")
friendly = list("pokes") //Anything nice the Behemoth would do would still Kill the Human. Leave it at poke.
speed = 5
environment_smash = 2
attack_sound = 'sound/weapons/heavysmash.ogg'
resistance = 10
icon_scale = 2
var/energy = 0
var/max_energy = 1000
armor = list(
"melee" = 60,
"bullet" = 60,
"laser" = 60,
"energy" = 30,
"bomb" = 10,
"bio" = 100,
"rad" = 100)
construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser,
/spell/targeted/fortify,
/spell/targeted/construct_advanced/slam
)
/mob/living/simple_animal/construct/behemoth/bullet_act(var/obj/item/projectile/P)
var/reflectchance = 80 - round(P.damage/3)
if(prob(reflectchance))
visible_message("<span class='danger'>The [P.name] gets reflected by [src]'s shell!</span>", \
"<span class='userdanger'>The [P.name] gets reflected by [src]'s shell!</span>")
// Find a turf near or on the original location to bounce to
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
var/turf/curloc = get_turf(src)
// redirect the projectile
P.redirect(new_x, new_y, curloc, src)
P.reflected = 1
return -1 // complete projectile permutation
return (..(P))
////////////////////////Harvester////////////////////////////////
/*
* Master of Spells and Ranged Abilities. Not as fragile as the Wraith, but nowhere near as maneuverable and deadly in melee.
*/
/mob/living/simple_animal/construct/harvester
name = "Harvester"
real_name = "Harvester"
construct_type = "harvester"
desc = "A tendril-laden construct piloted by a chained mind."
icon = 'icons/mob/mob.dmi'
icon_state = "harvester"
icon_living = "harvester"
maxHealth = 150
health = 150
melee_damage_lower = 20
melee_damage_upper = 25
attack_sharp = 1
attacktext = list("violently stabbed")
friendly = list("caresses")
speed = 0
environment_smash = 1
attack_sound = 'sound/weapons/pierce.ogg'
armor = list(
"melee" = 10,
"bullet" = 20,
"laser" = 20,
"energy" = 20,
"bomb" = 20,
"bio" = 100,
"rad" = 100)
construct_spells = list(
/spell/aoe_turf/knock/harvester,
/spell/targeted/construct_advanced/inversion_beam,
/spell/targeted/construct_advanced/agonizing_sphere,
/spell/rune_write
)
////////////////Glow//////////////////
/mob/living/simple_animal/construct/proc/add_glow()
var/image/eye_glow = image(icon,"glow-[icon_state]")
eye_glow.plane = PLANE_LIGHTING_ABOVE
overlays += eye_glow
set_light(2, -2, l_color = "#FFFFFF")
/mob/living/simple_animal/construct/proc/remove_glow()
overlays.Cut()
////////////////HUD//////////////////////
/mob/living/simple_animal/construct/Life()
. = ..()
if(.)
if(fire)
if(fire_alert) fire.icon_state = "fire1"
else fire.icon_state = "fire0"
if(pullin)
if(pulling) pullin.icon_state = "pull1"
else pullin.icon_state = "pull0"
if(purged)
if(purge > 0) purged.icon_state = "purge1"
else purged.icon_state = "purge0"
silence_spells(purge)
/mob/living/simple_animal/construct/updatehealth() //Special icons.
health = getMaxHealth() - getToxLoss() - getFireLoss() - getBruteLoss()
//Alive, becoming dead
if((stat < DEAD) && (health <= 0))
death()
//Overhealth
if(health > getMaxHealth())
health = getMaxHealth()
//Update our hud if we have one
if(healths)
if(stat != DEAD)
var/heal_per = (health / getMaxHealth()) * 100
switch(heal_per)
if(100 to INFINITY)
healths.icon_state = "[construct_type]_health0"
if(80 to 100)
healths.icon_state = "[construct_type]_health1"
if(60 to 80)
healths.icon_state = "[construct_type]_health2"
if(40 to 60)
healths.icon_state = "[construct_type]_health3"
if(20 to 40)
healths.icon_state = "[construct_type]_health4"
if(0 to 20)
healths.icon_state = "[construct_type]_health5"
else
healths.icon_state = "[construct_type]_health6"
else
healths.icon_state = "[construct_type]_health7"

View File

@@ -1,242 +0,0 @@
/obj/item/device/soulstone/cultify()
return
/obj/item/device/soulstone
name = "Soul Stone Shard"
icon = 'icons/obj/wizard.dmi'
icon_state = "soulstone"
item_state = "electronic"
desc = "A fragment of the legendary treasure known simply as the 'Soul Stone'. The shard still flickers with a fraction of the full artefacts power."
w_class = ITEMSIZE_SMALL
slot_flags = SLOT_BELT
origin_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 4)
var/imprinted = "empty"
var/possible_constructs = list("Juggernaut","Wraith","Artificer","Harvester")
//////////////////////////////Capturing////////////////////////////////////////////////////////
/obj/item/device/soulstone/attack(mob/living/carbon/human/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/human))//If target is not a human.
return ..()
if(istype(M, /mob/living/carbon/human/dummy))
return..()
if(jobban_isbanned(M, "cultist"))
user << "<span class='warning'>This person's soul is too corrupt and cannot be captured!</span>"
return..()
if(M.has_brain_worms()) //Borer stuff - RR
user << "<span class='warning'>This being is corrupted by an alien intelligence and cannot be soul trapped.</span>"
return..()
add_attack_logs(user,M,"Soulstone'd with [src.name]")
transfer_soul("VICTIM", M, user)
return
///////////////////Options for using captured souls///////////////////////////////////////
/obj/item/device/soulstone/attack_self(mob/user)
if (!in_range(src, user))
return
user.set_machine(src)
var/dat = "<TT><B>Soul Stone</B><BR>"
for(var/mob/living/simple_animal/shade/A in src)
dat += "Captured Soul: [A.name]<br>"
dat += {"<A href='byond://?src=\ref[src];choice=Summon'>Summon Shade</A>"}
dat += "<br>"
dat += {"<a href='byond://?src=\ref[src];choice=Close'> Close</a>"}
user << browse(dat, "window=aicard")
onclose(user, "aicard")
return
/obj/item/device/soulstone/Topic(href, href_list)
var/mob/U = usr
if (!in_range(src, U)||U.machine!=src)
U << browse(null, "window=aicard")
U.unset_machine()
return
add_fingerprint(U)
U.set_machine(src)
switch(href_list["choice"])//Now we switch based on choice.
if ("Close")
U << browse(null, "window=aicard")
U.unset_machine()
return
if ("Summon")
for(var/mob/living/simple_animal/shade/A in src)
A.status_flags &= ~GODMODE
A.canmove = 1
A << "<b>You have been released from your prison, but you are still bound to [U.name]'s will. Help them suceed in their goals at all costs.</b>"
A.forceMove(U.loc)
A.cancel_camera()
src.icon_state = "soulstone"
attack_self(U)
///////////////////////////Transferring to constructs/////////////////////////////////////////////////////
/obj/structure/constructshell
name = "empty shell"
icon = 'icons/obj/wizard.dmi'
icon_state = "construct"
desc = "A wicked machine used by those skilled in magical arts. It is inactive."
/obj/structure/constructshell/cultify()
return
/obj/structure/constructshell/cult
icon_state = "construct-cult"
desc = "This eerie contraption looks like it would come alive if supplied with a missing ingredient."
/obj/structure/constructshell/attackby(obj/item/O as obj, mob/user as mob)
if(istype(O, /obj/item/device/soulstone))
var/obj/item/device/soulstone/S = O;
S.transfer_soul("CONSTRUCT",src,user)
////////////////////////////Proc for moving soul in and out off stone//////////////////////////////////////
/obj/item/device/soulstone/proc/transfer_human(var/mob/living/carbon/human/T,var/mob/U)
if(!istype(T))
return;
if(src.imprinted != "empty")
U << "<span class='danger'>Capture failed!</span>: The soul stone has already been imprinted with [src.imprinted]'s mind!"
return
if ((T.health + T.halloss) > config.health_threshold_crit && T.stat != DEAD)
U << "<span class='danger'>Capture failed!</span>: Kill or maim the victim first!"
return
if(T.client == null)
U << "<span class='danger'>Capture failed!</span>: The soul has already fled it's mortal frame."
return
if(src.contents.len)
U << "<span class='danger'>Capture failed!</span>: The soul stone is full! Use or free an existing soul to make room."
return
for(var/obj/item/W in T)
T.drop_from_inventory(W)
new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton
T.invisibility = 101
var/atom/movable/overlay/animation = new /atom/movable/overlay( T.loc )
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = T
flick("dust-h", animation)
qdel(animation)
var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade( T.loc )
S.forceMove(src) //put shade in stone
S.status_flags |= GODMODE //So they won't die inside the stone somehow
S.canmove = 0//Can't move out of the soul stone
S.name = "Shade of [T.real_name]"
S.real_name = "Shade of [T.real_name]"
S.icon = T.icon
S.icon_state = T.icon_state
S.overlays = T.overlays
S.color = rgb(254,0,0)
S.alpha = 127
if (T.client)
T.client.mob = S
S.cancel_camera()
src.icon_state = "soulstone2"
src.name = "Soul Stone: [S.real_name]"
to_chat(S, "Your soul has been captured! You are now bound to [U.name]'s will, help them suceed in their goals at all costs.")
to_chat(U, "<span class='notice'>Capture successful!</span> : [T.real_name]'s soul has been ripped from their body and stored within the soul stone.")
to_chat(U, "The soulstone has been imprinted with [S.real_name]'s mind, it will no longer react to other souls.")
src.imprinted = "[S.name]"
qdel(T)
/obj/item/device/soulstone/proc/transfer_shade(var/mob/living/simple_animal/shade/T,var/mob/U)
if(!istype(T))
return;
if (T.stat == DEAD)
to_chat(U, "<span class='danger'>Capture failed!</span>: The shade has already been banished!")
return
if(src.contents.len)
to_chat(U, "<span class='danger'>Capture failed!</span>: The soul stone is full! Use or free an existing soul to make room.")
return
if(T.name != src.imprinted)
to_chat(U, "<span class='danger'>Capture failed!</span>: The soul stone has already been imprinted with [src.imprinted]'s mind!")
return
T.forceMove(src) //put shade in stone
T.status_flags |= GODMODE
T.canmove = 0
T.health = T.getMaxHealth()
src.icon_state = "soulstone2"
to_chat(T, "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form")
to_chat(U, "<span class='notice'>Capture successful!</span> : [T.name]'s has been recaptured and stored within the soul stone.")
/obj/item/device/soulstone/proc/transfer_construct(var/obj/structure/constructshell/T,var/mob/U)
var/mob/living/simple_animal/shade/A = locate() in src
if(!A)
to_chat(U,"<span class='danger'>Capture failed!</span>: The soul stone is empty! Go kill someone!")
return;
var/construct_class = input(U, "Please choose which type of construct you wish to create.") as null|anything in possible_constructs
switch(construct_class)
if("Juggernaut")
var/mob/living/simple_animal/construct/armoured/Z = new /mob/living/simple_animal/construct/armoured (get_turf(T.loc))
Z.key = A.key
if(iscultist(U))
cult.add_antagonist(Z.mind)
qdel(T)
to_chat(Z,"<B>You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike.</B>")
to_chat(Z,"<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>")
Z.cancel_camera()
qdel(src)
if("Wraith")
var/mob/living/simple_animal/construct/wraith/Z = new /mob/living/simple_animal/construct/wraith (get_turf(T.loc))
Z.key = A.key
if(iscultist(U))
cult.add_antagonist(Z.mind)
qdel(T)
to_chat(Z,"<B>You are playing a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.</B>")
to_chat(Z,"<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>")
Z.cancel_camera()
qdel(src)
if("Artificer")
var/mob/living/simple_animal/construct/builder/Z = new /mob/living/simple_animal/construct/builder (get_turf(T.loc))
Z.key = A.key
if(iscultist(U))
cult.add_antagonist(Z.mind)
qdel(T)
to_chat(Z,"<B>You are playing an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, repair allied constructs (by clicking on them), and even create new constructs</B>")
to_chat(Z,"<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>")
Z.cancel_camera()
qdel(src)
if("Harvester")
var/mob/living/simple_animal/construct/harvester/Z = new /mob/living/simple_animal/construct/harvester (get_turf(T.loc))
Z.key = A.key
if(iscultist(U))
cult.add_antagonist(Z.mind)
qdel(T)
to_chat(Z,"<B>You are playing a Harvester. You are relatively weak, but your physical frailty is made up for by your ranged abilities.</B>")
to_chat(Z,"<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>")
Z.cancel_camera()
qdel(src)
if("Behemoth")
var/mob/living/simple_animal/construct/behemoth/Z = new /mob/living/simple_animal/construct/behemoth (get_turf(T.loc))
Z.key = A.key
if(iscultist(U))
cult.add_antagonist(Z.mind)
qdel(T)
to_chat(Z,"<B>You are playing a Behemoth. You are incredibly slow, though your slowness is made up for by the fact your shell is far larger than any of your bretheren. You are the Unstoppable Force, and Immovable Object.</B>")
to_chat(Z,"<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>")
Z.cancel_camera()
qdel(src)
/obj/item/device/soulstone/proc/transfer_soul(var/choice as text, var/target, var/mob/U as mob)
switch(choice)
if("VICTIM")
transfer_human(target,U)
if("SHADE")
transfer_shade(target,U)
if("CONSTRUCT")
transfer_construct(target,U)

View File

@@ -10,9 +10,12 @@
hud_used.r_hand_hud_object.icon_state = "r_hand_active"
return
/mob/living/simple_mob/put_in_active_hand(var/obj/item/I)
if(!has_hands || !istype(I))
return
/mob/living/simple_mob/put_in_hands(var/obj/item/W) // No hands.
if(has_hands)
put_in_active_hand(W)
return 1
W.forceMove(get_turf(src))
return 1
//Puts the item into our active hand if possible. returns 1 on success.
/mob/living/simple_mob/put_in_active_hand(var/obj/item/W)
@@ -120,4 +123,21 @@
//If they can or cannot use tools/machines/etc
/mob/living/simple_mob/IsAdvancedToolUser()
return has_hands
return has_hands
/mob/living/simple_mob/proc/IsHumanoidToolUser(var/atom/tool)
if(!humanoid_hands)
var/display_name = null
if(tool)
display_name = tool
else
display_name = "object"
to_chat(src, "<span class='danger'>Your [hand_form] are not fit for use of \the [display_name].</span>")
return humanoid_hands
/mob/living/simple_mob/drop_from_inventory(var/obj/item/W, var/atom/target = null)
. = ..(W, target)
if(!target)
target = src.loc
if(.)
W.forceMove(src.loc)

View File

@@ -17,6 +17,8 @@
//Settings for played mobs
var/show_stat_health = 1 // Does the percentage health show in the stat panel for the mob
var/has_hands = 0 // Set to 1 to enable the use of hands and the hands hud
var/humanoid_hands = 0 // Can a player in this mob use things like guns or AI cards?
var/hand_form = "hands" // Used in IsHumanoidToolUser. 'Your X are not fit-'.
var/list/hud_gears // Slots to show on the hud (typically none)
var/ui_icons // Icon file path to use for the HUD, otherwise generic icons are used
var/r_hand_sprite // If they have hands,
@@ -85,7 +87,6 @@
var/reload_time = 1 SECONDS // How long it takes for a mob to reload. This is to buy a player a bit of time to run or fight.
var/reload_sound = 'sound/weapons/flipblade.ogg' // What sound gets played when the mob successfully reloads. Defaults to the same sound as reloading guns. Can be null.
//Mob melee settings
var/melee_damage_lower = 2 // Lower bound of randomized melee damage
var/melee_damage_upper = 6 // Upper bound of randomized melee damage
@@ -237,10 +238,6 @@
return verb
/mob/living/simple_mob/put_in_hands(var/obj/item/W) // No hands.
W.forceMove(get_turf(src))
return 1
// Harvest an animal's delicious byproducts
/mob/living/simple_mob/proc/harvest(var/mob/user)
var/actual_meat_amount = max(1,(meat_amount/2))

View File

@@ -0,0 +1,162 @@
////////////////////////////
// Base Construct
////////////////////////////
/mob/living/simple_mob/construct
name = "Construct"
real_name = "Construct"
desc = ""
tt_desc = "Error"
icon_living = "shade"
icon_dead = "shade_dead"
mob_class = MOB_CLASS_DEMONIC
ui_icons = 'icons/mob/screen1_construct.dmi'
has_hands = 1
hand_form = "stone manipulators"
response_help = "thinks better of touching"
response_disarm = "flailed at"
response_harm = "punched"
hovering = TRUE
softfall = TRUE //Beings made of Hellmarble and powered by the tears of the damned are not concerned with mortal things such as 'gravity'.
parachuting = TRUE
has_langs = list(LANGUAGE_GALCOM, LANGUAGE_CULT, LANGUAGE_OCCULT)
has_eye_glow = TRUE
taser_kill = FALSE
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
minbodytemp = 0
shock_resist = 0.1 //Electricity isn't very effective on stone, especially that from hell.
armor = list(
"melee" = 10,
"bullet" = 10,
"laser" = 10,
"energy" = 10,
"bomb" = 10,
"bio" = 100,
"rad" = 100)
can_be_antagged = TRUE
faction = "cult"
supernatural = TRUE
var/construct_type = "shade"
var/list/construct_spells = list()
// var/do_glow = TRUE
/mob/living/simple_mob/construct/place_spell_in_hand(var/path)
if(!path || !ispath(path))
return 0
//var/obj/item/weapon/spell/S = new path(src)
var/obj/item/weapon/spell/construct/S = new path(src)
//No hands needed for innate casts.
if(S.cast_methods & CAST_INNATE)
if(S.run_checks())
S.on_innate_cast(src)
if(l_hand && r_hand) //Make sure our hands aren't full.
if(istype(r_hand, /obj/item/weapon/spell)) //If they are full, perhaps we can still be useful.
var/obj/item/weapon/spell/r_spell = r_hand
if(r_spell.aspect == ASPECT_CHROMATIC) //Check if we can combine the new spell with one in our hands.
r_spell.on_combine_cast(S, src)
else if(istype(l_hand, /obj/item/weapon/spell))
var/obj/item/weapon/spell/l_spell = l_hand
if(l_spell.aspect == ASPECT_CHROMATIC) //Check the other hand too.
l_spell.on_combine_cast(S, src)
else //Welp
to_chat(src, "<span class='warning'>You require a free manipulator to use this power.</span>")
return 0
if(S.run_checks())
put_in_hands(S)
return 1
else
qdel(S)
return 0
/mob/living/simple_mob/construct/cultify()
return
/mob/living/simple_mob/construct/New()
..()
name = text("[initial(name)] ([rand(1, 1000)])")
real_name = name
for(var/spell in construct_spells)
src.add_spell(new spell, "const_spell_ready")
updateicon()
/*
/mob/living/simple_mob/construct/update_icon()
..()
if(do_glow)
add_glow()
*/
/mob/living/simple_mob/construct/death()
new /obj/item/weapon/ectoplasm (src.loc)
..(null,"collapses in a shattered heap.")
ghostize()
qdel(src)
/mob/living/simple_mob/construct/attack_generic(var/mob/user)
if(istype(user, /mob/living/simple_mob/construct/artificer))
var/mob/living/simple_mob/construct/artificer/A = user
if(health < getMaxHealth())
var/repair_lower_bound = A.melee_damage_lower * -1
var/repair_upper_bound = A.melee_damage_upper * -1
adjustBruteLoss(rand(repair_lower_bound, repair_upper_bound))
adjustFireLoss(rand(repair_lower_bound, repair_upper_bound))
user.visible_message("<span class='notice'>\The [user] mends some of \the [src]'s wounds.</span>")
else
to_chat(user, "<span class='notice'>\The [src] is undamaged.</span>")
return
return ..()
/mob/living/simple_mob/construct/examine(mob/user)
..(user)
var/msg = "<span cass='info'>*---------*\nThis is \icon[src] \a <EM>[src]</EM>!\n"
if (src.health < src.getMaxHealth())
msg += "<span class='warning'>"
if (src.health >= src.getMaxHealth()/2)
msg += "It looks slightly dented.\n"
else
msg += "<B>It looks severely dented!</B>\n"
msg += "</span>"
msg += "*---------*</span>"
user << msg
//Constructs levitate, can fall from a shuttle with no harm, and are piloted by either damned spirits or some otherworldly entity. Let 'em float in space.
/mob/living/simple_mob/construct/Process_Spacemove()
return 1
/*
// Glowing Procs
/mob/living/simple_mob/construct/proc/add_glow()
var/image/eye_glow = image(icon,"glow-[icon_state]")
eye_glow.plane = PLANE_LIGHTING_ABOVE
overlays += eye_glow
set_light(2, -2, l_color = "#FFFFFF")
/mob/living/simple_mob/construct/proc/remove_glow()
overlays.Cut()
*/

View File

@@ -0,0 +1,30 @@
////////////////////////////
// Artificer
////////////////////////////
/mob/living/simple_mob/construct/artificer
name = "Artificer"
real_name = "Artificer"
construct_type = "artificer"
desc = "A bulbous construct dedicated to building and maintaining temples to their otherworldly lords."
icon = 'icons/mob/mob.dmi'
icon_state = "artificer"
icon_living = "artificer"
maxHealth = 150
health = 150
response_harm = "viciously beaten"
harm_intent_damage = 5
melee_damage_lower = 15 //It's not the strongest of the bunch, but that doesn't mean it can't hurt you.
melee_damage_upper = 20
attacktext = list("rammed")
attack_sound = 'sound/weapons/rapidslice.ogg'
construct_spells = list(/spell/aoe_turf/conjure/construct/lesser,
/spell/aoe_turf/conjure/wall,
/spell/aoe_turf/conjure/floor,
/spell/aoe_turf/conjure/soulstone,
/spell/aoe_turf/conjure/pylon,
/spell/aoe_turf/conjure/door,
/spell/aoe_turf/conjure/grille,
/spell/targeted/occult_repair_aura,
/spell/targeted/construct_advanced/mend_acolyte
)

View File

@@ -0,0 +1,40 @@
////////////////////////////
// Harvester
////////////////////////////
/mob/living/simple_mob/construct/harvester
name = "Harvester"
real_name = "Harvester"
construct_type = "harvester"
desc = "A tendril-laden construct piloted by a chained mind."
icon = 'icons/mob/mob.dmi'
icon_state = "harvester"
icon_living = "harvester"
maxHealth = 150
health = 150
melee_damage_lower = 20
melee_damage_upper = 25
attack_sharp = 1
attacktext = list("violently stabbed")
friendly = list("caresses")
movement_cooldown = 0
// environment_smash = 1 // Whatever this gets renamed to, Harvesters need to break things
attack_sound = 'sound/weapons/pierce.ogg'
armor = list(
"melee" = 10,
"bullet" = 20,
"laser" = 20,
"energy" = 20,
"bomb" = 20,
"bio" = 100,
"rad" = 100)
construct_spells = list(
/spell/aoe_turf/knock/harvester,
/spell/targeted/construct_advanced/inversion_beam,
/spell/targeted/construct_advanced/agonizing_sphere,
/spell/rune_write
)

View File

@@ -0,0 +1,143 @@
////////////////////////////
// Juggernaut
////////////////////////////
/mob/living/simple_mob/construct/juggernaut
name = "Juggernaut"
real_name = "Juggernaut"
construct_type = "juggernaut"
desc = "A possessed suit of armour driven by the will of the restless dead"
icon = 'icons/mob/mob.dmi'
icon_state = "behemoth"
icon_living = "behemoth"
maxHealth = 300
health = 300
response_harm = "harmlessly punches"
harm_intent_damage = 0
melee_damage_lower = 30
melee_damage_upper = 40
attack_armor_pen = 60 //Being punched by a living, floating statue.
attacktext = list("smashed their armoured gauntlet into")
friendly = list("pats")
mob_size = MOB_HUGE
movement_cooldown = 6 //Not super fast, but it might catch up to someone in armor who got punched once or twice.
// environment_smash = 2 // Whatever this gets renamed to, Juggernauts need to break things
attack_sound = 'sound/weapons/heavysmash.ogg'
status_flags = 0
resistance = 10
construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser,
/spell/targeted/fortify,
/spell/targeted/construct_advanced/slam
)
armor = list(
"melee" = 70,
"bullet" = 30,
"laser" = 30,
"energy" = 30,
"bomb" = 10,
"bio" = 100,
"rad" = 100)
/mob/living/simple_mob/construct/juggernaut/Life()
weakened = 0
..()
/mob/living/simple_mob/construct/juggernaut/bullet_act(var/obj/item/projectile/P)
var/reflectchance = 80 - round(P.damage/3)
if(prob(reflectchance))
var/damage_mod = rand(2,4)
var/projectile_dam_type = P.damage_type
var/incoming_damage = (round(P.damage / damage_mod) - (round((P.damage / damage_mod) * 0.3)))
var/armorcheck = run_armor_check(null, P.check_armour)
var/soakedcheck = get_armor_soak(null, P.check_armour)
if(!(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)))
visible_message("<span class='danger'>The [P.name] bounces off of [src]'s shell!</span>", \
"<span class='userdanger'>The [P.name] bounces off of [src]'s shell!</span>")
new /obj/item/weapon/material/shard/shrapnel(src.loc)
if(!(P.damage_type == BRUTE || P.damage_type == BURN))
projectile_dam_type = BRUTE
incoming_damage = round(incoming_damage / 4) //Damage from strange sources is converted to brute for physical projectiles, though severely decreased.
apply_damage(incoming_damage, projectile_dam_type, null, armorcheck, soakedcheck, is_sharp(P), has_edge(P), P)
return -1 //Doesn't reflect non-beams or non-energy projectiles. They just smack and drop with little to no effect.
else
visible_message("<span class='danger'>The [P.name] gets reflected by [src]'s shell!</span>", \
"<span class='userdanger'>The [P.name] gets reflected by [src]'s shell!</span>")
damage_mod = rand(3,5)
incoming_damage = (round(P.damage / damage_mod) - (round((P.damage / damage_mod) * 0.3)))
if(!(P.damage_type == BRUTE || P.damage_type == BURN))
projectile_dam_type = BURN
incoming_damage = round(incoming_damage / 4) //Damage from strange sources is converted to burn for energy-type projectiles, though severely decreased.
apply_damage(incoming_damage, P.damage_type, null, armorcheck, soakedcheck, is_sharp(P), has_edge(P), P)
// Find a turf near or on the original location to bounce to
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
var/turf/curloc = get_turf(src)
// redirect the projectile
P.redirect(new_x, new_y, curloc, src)
P.reflected = 1
return -1 // complete projectile permutation
return (..(P))
/*
* The Behemoth. Admin-allowance only, still try to keep it in some guideline of 'Balanced', even if it means Security has to be fully geared to be so.
*/
/mob/living/simple_mob/construct/juggernaut/behemoth
name = "Behemoth"
real_name = "Behemoth"
desc = "The pinnacle of occult technology, Behemoths are nothing shy of both an Immovable Object, and Unstoppable Force."
maxHealth = 750
health = 750
speak_emote = list("rumbles")
melee_damage_lower = 50
melee_damage_upper = 50
attacktext = list("brutally crushed")
friendly = list("pokes") //Anything nice the Behemoth would do would still Kill the Human. Leave it at poke.
attack_sound = 'sound/weapons/heavysmash.ogg'
resistance = 10
icon_scale = 2
var/energy = 0
var/max_energy = 1000
armor = list(
"melee" = 60,
"bullet" = 60,
"laser" = 60,
"energy" = 30,
"bomb" = 10,
"bio" = 100,
"rad" = 100)
construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser,
/spell/targeted/fortify,
/spell/targeted/construct_advanced/slam
)
/mob/living/simple_mob/construct/juggernaut/behemoth/bullet_act(var/obj/item/projectile/P)
var/reflectchance = 80 - round(P.damage/3)
if(prob(reflectchance))
visible_message("<span class='danger'>The [P.name] gets reflected by [src]'s shell!</span>", \
"<span class='userdanger'>The [P.name] gets reflected by [src]'s shell!</span>")
// Find a turf near or on the original location to bounce to
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
var/turf/curloc = get_turf(src)
// redirect the projectile
P.redirect(new_x, new_y, curloc, src)
P.reflected = 1
return -1 // complete projectile permutation
return (..(P))

View File

@@ -0,0 +1,48 @@
////////////////////////////
// Shade
////////////////////////////
/mob/living/simple_mob/construct/shade
name = "Shade"
real_name = "Shade"
desc = "A bound spirit"
icon = 'icons/mob/mob.dmi'
icon_state = "shade"
icon_living = "shade"
icon_dead = "shade_dead"
response_help = "puts their hand through"
response_disarm = "flails at"
response_harm = "punches"
melee_damage_lower = 5
melee_damage_upper = 15
attack_armor_pen = 100 //It's a ghost/horror from beyond, I ain't gotta explain 100 AP
attacktext = list("drained the life from")
minbodytemp = 0
maxbodytemp = 4000
min_oxy = 0
max_co2 = 0
max_tox = 0
universal_speak = 1
loot_list = list(/obj/item/weapon/ectoplasm = 100)
/mob/living/simple_mob/construct/shade/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(istype(O, /obj/item/device/soulstone))
var/obj/item/device/soulstone/S = O;
S.transfer_soul("SHADE", src, user)
return
..()
/mob/living/simple_mob/construct/shade/death()
..()
for(var/mob/M in viewers(src, null))
if((M.client && !( M.blinded )))
M.show_message("<font color='red'>[src] lets out a contented sigh as their form unwinds.</font>")
ghostize()
qdel(src)
return

View File

@@ -0,0 +1,33 @@
////////////////////////////
// Wraith
////////////////////////////
/mob/living/simple_mob/construct/wraith
name = "Wraith"
real_name = "Wraith"
construct_type = "wraith"
desc = "A wicked bladed shell contraption piloted by a bound spirit."
icon = 'icons/mob/mob.dmi'
icon_state = "floating"
icon_living = "floating"
maxHealth = 200
health = 200
melee_damage_lower = 25
melee_damage_upper = 30
attack_armor_pen = 15
attack_sharp = 1
attack_edge = 1
attacktext = list("slashed")
friendly = list("pinches")
movement_cooldown = 0
attack_sound = 'sound/weapons/rapidslice.ogg'
construct_spells = list(/spell/targeted/ethereal_jaunt/shift,
/spell/targeted/ambush_mode
)
// environment_smash = 1 // Whatever this gets renamed to, Wraiths need to break things
/mob/living/simple_mob/construct/wraith/apply_melee_effects(var/atom/A)
if(isliving(A))
var/mob/living/L = A
L.add_modifier(/datum/modifier/deep_wounds, 30 SECONDS)

View File

@@ -300,18 +300,6 @@
if(ispath(MP, /mob/living/simple_animal/space_worm))
return 0 //Unfinished. Very buggy, they seem to just spawn additional space worms everywhere and eating your own tail results in new worms spawning.
if(ispath(MP, /mob/living/simple_animal/construct/behemoth))
return 0 //I think this may have been an unfinished WiP or something. These constructs should really have their own class simple_animal/construct/subtype
if(ispath(MP, /mob/living/simple_animal/construct/armoured))
return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype
if(ispath(MP, /mob/living/simple_animal/construct/wraith))
return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype
if(ispath(MP, /mob/living/simple_animal/construct/builder))
return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype
//Good mobs!
if(ispath(MP, /mob/living/simple_animal/cat))
return 1
@@ -321,7 +309,7 @@
return 1
if(ispath(MP, /mob/living/simple_animal/hostile/carp))
return 1
if(ispath(MP, /mob/living/simple_animal/shade))
if(ispath(MP, /mob/living/simple_mob/construct))
return 1
if(ispath(MP, /mob/living/simple_animal/hostile/tomato))
return 1