Constructs 2.0 - Living Stone (#5040)

* Construct Overhaul + Related Fixes/Tweaks
This commit is contained in:
Mechoid
2018-04-04 23:45:00 -07:00
committed by Atermonera
parent d5c5249327
commit 57ab0e715b
36 changed files with 1427 additions and 167 deletions

View File

@@ -93,9 +93,12 @@
return
/mob/living/simple_animal/construct/instantiate_hud(var/datum/hud/HUD)
HUD.construct_hud()
/mob/living/simple_animal/construct/instantiate_hud(var/datum/hud/HUD)
..(HUD)
// HUD.construct_hud() //Archaic.
/*
/datum/hud/proc/construct_hud()
var/constructtype
@@ -109,30 +112,28 @@
constructtype = "harvester"
if(constructtype)
mymob.fire = new /obj/screen()
mymob.fire.icon = 'icons/mob/screen1_construct.dmi'
mymob.fire.icon_state = "fire0"
mymob.fire.name = "fire"
mymob.fire.screen_loc = ui_construct_fire
mymob.healths = new /obj/screen()
mymob.healths.icon = 'icons/mob/screen1_construct.dmi'
mymob.healths.icon_state = "[constructtype]_health0"
mymob.healths.name = "health"
mymob.healths.screen_loc = ui_construct_health
mymob.pullin = new /obj/screen()
mymob.pullin.icon = 'icons/mob/screen1_construct.dmi'
mymob.pullin.icon_state = "pull0"
mymob.pullin.name = "pull"
mymob.pullin.screen_loc = ui_construct_pull
mymob.zone_sel = new /obj/screen/zone_sel()
mymob.zone_sel.icon = 'icons/mob/screen1_construct.dmi'
mymob.zone_sel.overlays.len = 0
mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]")
mymob.purged = new /obj/screen()
mymob.purged.icon = 'icons/mob/screen1_construct.dmi'
mymob.purged.icon_state = "purge0"
mymob.purged.name = "purged"
@@ -142,3 +143,4 @@
mymob.client.screen += list(mymob.fire, mymob.healths, mymob.pullin, mymob.zone_sel, mymob.purged)
mymob.client.screen += mymob.client.void
*/

View File

@@ -92,9 +92,11 @@
if(spattack_min_range <= 1)
SpecialAtkTarget()
else if(melee_damage_upper == 0 && istype(A,/mob/living))
custom_emote(1,"[pick(friendly)] [A]!")
else
DoPunch(A)

View File

@@ -0,0 +1,698 @@
//cast_method flags, needs to be up to date with Technomancer's. They were, for some reason, not working outside it.
#define CAST_USE 1 // Clicking the spell in your hand.
#define CAST_MELEE 2 // Clicking an atom in melee range.
#define CAST_RANGED 4 // Clicking an atom beyond melee range.
#define CAST_THROW 8 // Throwing the spell and hitting an atom.
#define CAST_COMBINE 16 // Clicking another spell with this spell.
#define CAST_INNATE 32 // Activates upon verb usage, used for mobs without hands.
//Aspects
#define ASPECT_FIRE "fire" //Damage over time and raising body-temp. Firesuits protect from this.
#define ASPECT_FROST "frost" //Slows down the affected, also involves imbedding with icicles. Winter coats protect from this.
#define ASPECT_SHOCK "shock" //Energy-expensive, usually stuns. Insulated armor protects from this.
#define ASPECT_AIR "air" //Mostly involves manipulation of atmos, useless in a vacuum. Magboots protect from this.
#define ASPECT_FORCE "force" //Manipulates gravity to push things away or towards a location.
#define ASPECT_TELE "tele" //Teleportation of self, other objects, or other people.
#define ASPECT_DARK "dark" //Makes all those photons vanish using magic-- WITH SCIENCE. Used for sneaky stuff.
#define ASPECT_LIGHT "light" //The opposite of dark, usually blinds, makes holo-illusions, or makes laser lightshows.
#define ASPECT_BIOMED "biomed" //Mainly concerned with healing and restoration.
#define ASPECT_EMP "emp" //Unused now.
#define ASPECT_UNSTABLE "unstable" //Heavily RNG-based, causes instability to the victim.
#define ASPECT_CHROMATIC "chromatic" //Used to combine with other spells.
#define ASPECT_UNHOLY "unholy" //Involves the dead, blood, and most things against divine beings.
//////////////////////////////Construct Spells/////////////////////////
proc/findNullRod(var/atom/target)
if(istype(target,/obj/item/weapon/nullrod))
return 1
else if(target.contents)
for(var/atom/A in target.contents)
if(findNullRod(A))
return 1
return 0
/spell/aoe_turf/conjure/construct
name = "Artificer"
desc = "This spell conjures a construct which may be controlled by Shades"
school = "conjuration"
charge_max = 600
spell_flags = 0
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/structure/constructshell)
hud_state = "artificer"
/spell/aoe_turf/conjure/construct/lesser
charge_max = 1800
summon_type = list(/obj/structure/constructshell/cult)
hud_state = "const_shell"
override_base = "const"
/spell/aoe_turf/conjure/floor
name = "Floor Construction"
desc = "This spell constructs a cult floor"
charge_max = 20
spell_flags = Z2NOCAST | CONSTRUCT_CHECK
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/turf/simulated/floor/cult)
hud_state = "const_floor"
/spell/aoe_turf/conjure/floor/conjure_animation(var/atom/movable/overlay/animation, var/turf/target)
animation.icon_state = "cultfloor"
flick("cultfloor",animation)
spawn(10)
qdel(animation)
/spell/aoe_turf/conjure/wall
name = "Lesser Construction"
desc = "This spell constructs a cult wall"
charge_max = 100
spell_flags = Z2NOCAST | CONSTRUCT_CHECK
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/turf/simulated/wall/cult)
hud_state = "const_wall"
/spell/aoe_turf/conjure/wall/conjure_animation(var/atom/movable/overlay/animation, var/turf/target)
animation.icon_state = "cultwall"
flick("cultwall",animation)
spawn(10)
qdel(animation)
/spell/aoe_turf/conjure/wall/reinforced
name = "Greater Construction"
desc = "This spell constructs a reinforced metal wall"
charge_max = 300
spell_flags = Z2NOCAST
invocation = "none"
invocation_type = SpI_NONE
range = 0
cast_delay = 50
summon_type = list(/turf/simulated/wall/r_wall)
/spell/aoe_turf/conjure/soulstone
name = "Summon Soulstone"
desc = "This spell reaches into Nar-Sie's realm, summoning one of the legendary fragments across time and space"
charge_max = 3000
spell_flags = 0
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/item/device/soulstone)
hud_state = "const_stone"
override_base = "const"
/spell/aoe_turf/conjure/pylon
name = "Red Pylon"
desc = "This spell conjures a fragile crystal from Nar-Sie's realm. Makes for a convenient light source."
charge_max = 200
spell_flags = CONSTRUCT_CHECK
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/structure/cult/pylon)
hud_state = "const_pylon"
/spell/aoe_turf/conjure/pylon/cast(list/targets)
..()
var/turf/spawn_place = pick(targets)
for(var/obj/structure/cult/pylon/P in spawn_place.contents)
if(P.isbroken)
P.repair(usr)
continue
return
/spell/aoe_turf/conjure/door
name = "Stone Door"
desc = "This spell conjures a massive stone door."
charge_max = 100
spell_flags = CONSTRUCT_CHECK
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/structure/simple_door/cult)
hud_state = "const_door"
/spell/aoe_turf/conjure/grille
name = "Arcane Grille"
desc = "This spell conjures an airtight grille."
charge_max = 100
spell_flags = CONSTRUCT_CHECK
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/structure/grille/cult)
hud_state = "const_grille"
/spell/aoe_turf/conjure/forcewall/lesser
name = "Shield"
desc = "Allows you to pull up a shield to protect yourself and allies from incoming threats"
charge_max = 300
spell_flags = 0
invocation = "none"
invocation_type = SpI_NONE
range = 0
summon_type = list(/obj/effect/forcefield/cult)
duration = 200
hud_state = "const_juggwall"
//Code for the Juggernaut construct's forcefield, that seemed like a good place to put it.
/obj/effect/forcefield/cult
desc = "That eerie looking obstacle seems to have been pulled from another dimension through sheer force"
name = "Juggerwall"
icon = 'icons/effects/effects.dmi'
icon_state = "m_shield_cult"
light_color = "#B40000"
light_range = 2
/obj/effect/forcefield/cult/cultify()
return
/spell/aoe_turf/knock/harvester
name = "Force Doors"
desc = "Mortal portals are no match for your occult might."
spell_flags = CONSTRUCT_CHECK
charge_max = 100
invocation = ""
invocation_type = "silent"
range = 4
hud_state = "const_knock"
/spell/aoe_turf/knock/harvester/cast(list/targets)
/* for(var/turf/T in targets) //Disintigrating doors is bad, okay.
for(var/obj/machinery/door/door in T.contents)
spawn door.cultify()
return */
for(var/turf/T in targets)
for(var/obj/machinery/door/door in T.contents)
spawn(1)
if(istype(door,/obj/machinery/door/airlock))
var/obj/machinery/door/airlock/AL = door
AL.locked = 0 //The spirits of the damned care not for your locks.
AL.welded = 0 //Or your welding tools.
else if(istype(door, /obj/machinery/door/firedoor))
var/obj/machinery/door/firedoor/FD = door
FD.blocked = 0
door.open(1)
return
/*
*
* Self-targeting spells. Modifiers, auras, instants, etc.
*
*/
/spell/targeted/ethereal_jaunt/shift
name = "Phase Shift"
desc = "This spell allows you to pass through walls"
charge_max = 200
spell_flags = Z2NOCAST | INCLUDEUSER | CONSTRUCT_CHECK
invocation_type = SpI_NONE
range = -1
duration = 50 //in deciseconds
hud_state = "const_shift"
/spell/targeted/ethereal_jaunt/shift/jaunt_disappear(var/atom/movable/overlay/animation, var/mob/living/target)
animation.icon_state = "phase_shift"
animation.dir = target.dir
flick("phase_shift",animation)
/spell/targeted/ethereal_jaunt/shift/jaunt_reappear(var/atom/movable/overlay/animation, var/mob/living/target)
animation.icon_state = "phase_shift2"
animation.dir = target.dir
flick("phase_shift2",animation)
/spell/targeted/ethereal_jaunt/shift/jaunt_steam(var/mobloc)
return
/*
* Harvest has been disabled due to the lack of Nar'Sie. Here for posterity / future rework.
*/
/*
/spell/targeted/harvest
name = "Harvest"
desc = "Back to where I come from, and you're coming with me."
school = "transmutation"
charge_max = 200
spell_flags = Z2NOCAST | CONSTRUCT_CHECK | INCLUDEUSER
invocation = ""
invocation_type = SpI_NONE
range = 0
max_targets = 0
overlay = 1
overlay_icon = 'icons/effects/effects.dmi'
overlay_icon_state = "rune_teleport"
overlay_lifespan = 0
hud_state = "const_harvest"
/spell/targeted/harvest/cast(list/targets, mob/user)//because harvest is already a proc
..()
var/destination = null
for(var/obj/singularity/narsie/large/N in narsie_list)
destination = N.loc
break
if(destination)
var/prey = 0
for(var/mob/living/M in targets)
if(!findNullRod(M))
M.forceMove(destination)
if(M != user)
prey = 1
user << "<span class='sinister'>You warp back to Nar-Sie[prey ? " along with your prey":""].</span>"
else
user << "<span class='danger'>...something's wrong!</span>"//There shouldn't be an instance of Harvesters when Nar-Sie isn't in the world.
*/
/spell/targeted/fortify
name = "Fortify Shell"
desc = "Emit a field of energy around your shell to reduce incoming damage incredibly, while decreasing your mobility."
range = -1
school = "evocation"
charge_type = Sp_RECHARGE
invocation_type = SpI_NONE
spell_flags = CONSTRUCT_CHECK | INCLUDEUSER
hud_state = "const_fortify"
smoke_amt = 0
charge_max = 600
/spell/targeted/fortify/cast(list/targets, mob/living/user)
if(findNullRod(user) || user.has_modifier_of_type(/datum/modifier/fortify))
charge_counter = 400
return
user.add_modifier(/datum/modifier/fortify, 1 MINUTES)
/spell/targeted/occult_repair_aura
name = "Repair Aura"
desc = "Emit a field of energy around your shell to repair nearby constructs at range."
range = -1
school = "evocation"
charge_type = Sp_RECHARGE
invocation_type = SpI_NONE
spell_flags = CONSTRUCT_CHECK | INCLUDEUSER
hud_state = "const_repairaura"
smoke_amt = 0
charge_max = 600
/spell/targeted/occult_repair_aura/cast(list/targets, mob/living/user)
if(findNullRod(user) || user.has_modifier_of_type(/datum/modifier/repair_aura))
charge_counter = 300
return
user.add_modifier(/datum/modifier/repair_aura, 30 SECONDS)
/spell/targeted/ambush_mode
name = "Toggle Ambush"
desc = "Phase yourself mostly out of this reality, minimizing your combat ability, but allowing for employance of ambush tactics."
range = -1
school = "evocation"
charge_type = Sp_RECHARGE
invocation_type = SpI_NONE
spell_flags = CONSTRUCT_CHECK | INCLUDEUSER
hud_state = "const_ambush"
smoke_amt = 0
charge_max = 100
/spell/targeted/ambush_mode/cast(list/targets, mob/living/user)
if(findNullRod(user))
charge_counter = 50
return
if(user.has_modifier_of_type(/datum/modifier/ambush))
user.remove_modifiers_of_type(/datum/modifier/ambush)
return
user.add_modifier(/datum/modifier/ambush, 0)
/*
*
* These are the spells that place spell-objects into the construct's hands akin to technomancers.
*
*/
/spell/targeted/construct_advanced
name = "Base Construct Spell"
desc = "If you see this, please tell a developer!"
range = -1
school = "evocation"
charge_type = Sp_RECHARGE
invocation_type = SpI_NONE
spell_flags = CONSTRUCT_CHECK | INCLUDEUSER
hud_state = "const_rune"
smoke_amt = 0
charge_max = 10
var/obj/item/weapon/spell/construct/spell_obj = null //This is the var that determines what Technomancer-style spell is put into their hands.
/spell/targeted/construct_advanced/cast(list/targets, mob/living/user)
if(!findNullRod(user))
user.place_spell_in_hand(spell_obj)
/spell/targeted/construct_advanced/inversion_beam
name = "Inversion Beam"
desc = "Fire a searing beam of darkness at your foes."
hud_state = "const_beam"
spell_obj = /obj/item/weapon/spell/construct/projectile/inverted_beam
/spell/targeted/construct_advanced/mend_acolyte
name = "Mend Acolyte"
desc = "Mend a target acolyte or construct over time."
charge_max = 100
hud_state = "const_mend"
spell_obj = /obj/item/weapon/spell/construct/mend_occult
/spell/targeted/construct_advanced/agonizing_sphere
name = "Sphere of Agony"
desc = "Rend a portal into a plane of naught but pain at the target location."
charge_max = 100
hud_state = "const_harvest"
spell_obj = /obj/item/weapon/spell/construct/spawner/agonizing_sphere
/spell/targeted/construct_advanced/slam
name = "Slam"
desc = "Empower your FIST."
charge_max = 300
hud_state = "const_fist"
spell_obj = /obj/item/weapon/spell/construct/slam
/*
*
* These are the spell objects that go into the construct's hands.
*
*/
/*
* Base advanced construct spell types.
*/
/obj/item/weapon/spell/construct //Energy costs are in units of blood, in the event a cultist gets one of these.
name = "unholy energy"
desc = "Your hands appear to be screaming. This is a debug text, you should probably tell a developer!"
icon = 'icons/obj/spells.dmi'
icon_state = "generic"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_spells.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_spells.dmi',
)
throwforce = 0
force = 0
show_examine = FALSE
owner = null
core = null
cast_methods = null // Controls how the spell is casted.
aspect = ASPECT_UNHOLY // Used for combining spells. Pretty much any cult spell is unholy.
toggled = 0 // Mainly used for overlays.
cooldown = 0 // If set, will add a cooldown overlay and adjust click delay. Must be a multiple of 5 for overlays.
cast_sound = null // Sound file played when this is used.
var/last_castcheck = null // The last time this spell was cast.
/obj/item/weapon/spell/construct/New()
//..() //This kills the spell, because super on this calls the default spell's New, which checks for a core. Can't have that.
if(isliving(loc))
owner = loc
if(!owner)
qdel(src)
update_icon()
/obj/item/weapon/spell/construct/adjust_instability(var/amount) //The only drawback to the boons of the geometer is the use of a mortal's blood as fuel. Constructs have already paid that price long ago.
return
/obj/item/weapon/spell/construct/run_checks()
if(owner)
if((iscultist(owner) || istype(owner, /mob/living/simple_animal/construct)) && (world.time >= (last_castcheck + cooldown))) //Are they a cultist or a construct, and has the cooldown time passed?
last_castcheck = world.time
return 1
return 0
/obj/item/weapon/spell/construct/pay_energy(var/amount)
if(owner)
if(istype(owner, /mob/living/simple_animal/construct))
return 1
if(iscultist(owner) && pay_blood(amount))
return 1
return 0
/obj/item/weapon/spell/construct/proc/pay_blood(var/amount) //If, for some reason, this is put into the hands of a cultist, by a talisnam or whatever.
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(!H.should_have_organ(O_HEART))
return 1
if(H.vessel.remove_reagent("blood", amount))
return 1
return 0
/obj/item/weapon/spell/construct/afterattack(atom/target, mob/user, proximity_flag, click_parameters) //Not overriding it caused runtimes, because cooldown checked for core.
if(!run_checks())
return
if(!proximity_flag)
if(cast_methods & CAST_RANGED)
on_ranged_cast(target, user)
else
if(istype(target, /obj/item/weapon/spell))
var/obj/item/weapon/spell/spell = target
if(spell.cast_methods & CAST_COMBINE)
spell.on_combine_cast(src, user)
return
if(cast_methods & CAST_MELEE)
on_melee_cast(target, user)
else if(cast_methods & CAST_RANGED) //Try to use a ranged method if a melee one doesn't exist.
on_ranged_cast(target, user)
if(cooldown)
var/effective_cooldown = round(cooldown, 5)
user.setClickCooldown(effective_cooldown)
flick("cooldown_[effective_cooldown]",src)
/obj/item/weapon/spell/construct/projectile //This makes me angry, but we need the template, and we can't use it because special check overrides on the base.
name = "construct projectile template"
icon_state = "generic"
desc = "This is a generic template that shoots projectiles. If you can read this, the game broke!"
cast_methods = CAST_RANGED
var/obj/item/projectile/spell_projectile = null
var/pre_shot_delay = 0
var/fire_sound = null
var/energy_cost_per_shot = 5
/obj/item/weapon/spell/construct/projectile/on_ranged_cast(atom/hit_atom, mob/living/user)
if(set_up(hit_atom, user))
var/obj/item/projectile/new_projectile = make_projectile(spell_projectile, user)
new_projectile.launch(hit_atom)
log_and_message_admins("has casted [src] at \the [hit_atom].")
if(fire_sound)
playsound(get_turf(src), fire_sound, 75, 1)
return 1
return 0
/obj/item/weapon/spell/construct/projectile/proc/make_projectile(obj/item/projectile/projectile_type, mob/living/user)
var/obj/item/projectile/P = new projectile_type(get_turf(user))
return P
/obj/item/weapon/spell/construct/projectile/proc/set_up(atom/hit_atom, mob/living/user)
if(spell_projectile)
if(pay_energy(energy_cost_per_shot))
if(pre_shot_delay)
var/image/target_image = image(icon = 'icons/obj/spells.dmi', loc = get_turf(hit_atom), icon_state = "target")
user << target_image
user.Stun(pre_shot_delay / 10)
sleep(pre_shot_delay)
qdel(target_image)
if(owner)
return TRUE
return FALSE // We got dropped before the firing occured.
return TRUE // No delay, no need to check.
return FALSE
/obj/item/weapon/spell/construct/spawner
name = "spawner template"
desc = "If you see me, someone messed up."
icon_state = "darkness"
cast_methods = CAST_RANGED
var/obj/effect/spawner_type = null
/obj/item/weapon/spell/construct/spawner/on_ranged_cast(atom/hit_atom, mob/user)
var/turf/T = get_turf(hit_atom)
if(T)
new spawner_type(T)
to_chat(user, "<span class='cult'>You shift \the [src] onto \the [T].</span>")
log_and_message_admins("has casted [src] at [T.x],[T.y],[T.z].")
qdel(src)
//Harvester Laser.
/obj/item/weapon/spell/construct/projectile/inverted_beam
name = "inversion beam"
icon_state = "generic"
desc = "Your manipulators fire searing beams of inverted light."
cast_methods = CAST_RANGED
spell_projectile = /obj/item/projectile/beam/inversion
pre_shot_delay = 0
cooldown = 5
fire_sound = 'sound/weapons/spiderlunge.ogg'
/obj/item/projectile/beam/inversion
name = "inversion beam"
icon_state = "invert"
fire_sound = 'sound/weapons/spiderlunge.ogg'
damage = 15
damage_type = BURN
check_armour = "laser"
armor_penetration = 60
light_range = 2
light_power = -2
light_color = "#FFFFFF"
muzzle_type = /obj/effect/projectile/inversion/muzzle
tracer_type = /obj/effect/projectile/inversion/tracer
impact_type = /obj/effect/projectile/inversion/impact
//Harvester Pain Orb
/obj/item/weapon/spell/construct/spawner/agonizing_sphere
name = "sphere of agony"
desc = "Call forth a portal to a dimension of naught but pain at your target."
spawner_type = /obj/effect/temporary_effect/pulsar/agonizing_sphere
/obj/item/weapon/spell/construct/spawner/agonizing_sphere/on_ranged_cast(atom/hit_atom, mob/user)
if(within_range(hit_atom) && pay_energy(10))
..()
/obj/item/weapon/spell/construct/spawner/agonizing_sphere/on_throw_cast(atom/hit_atom, mob/user)
pay_energy(5)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
L.add_modifier(/datum/modifier/agonize, 10 SECONDS)
/obj/effect/temporary_effect/pulsar/agonizing_sphere
name = "agonizing sphere"
desc = "A portal to some hellish place. Its screams wrack your body with pain.."
icon_state = "red_static_sphere"
time_to_die = null
light_range = 4
light_power = 5
light_color = "#FF0000"
pulses_remaining = 10
/obj/effect/temporary_effect/pulsar/agonizing_sphere/pulse_loop()
while(pulses_remaining)
sleep(1 SECONDS)
spawn()
for(var/mob/living/L in view(4,src))
if(!iscultist(L) && !istype(L, /mob/living/simple_animal/construct))
L.add_modifier(/datum/modifier/agonize, 2 SECONDS)
if(L.isSynthetic())
to_chat(L, "<span class='cult'>Your chassis warps as the [src] pulses!</span>")
L.adjustFireLoss(4)
pulses_remaining--
qdel(src)
//Artificer Heal
/obj/item/weapon/spell/construct/mend_occult
name = "mend acolyte"
desc = "Mend the wounds of a cultist, or construct, over time."
icon_state = "mend_wounds"
cast_methods = CAST_MELEE
aspect = ASPECT_UNHOLY
light_color = "#FF5C5C"
light_power = -2
/obj/item/weapon/spell/construct/mend_occult/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
L.add_modifier(/datum/modifier/mend_occult, 150)
qdel(src)
//Juggernaut + Behemoth Slam
/obj/item/weapon/spell/construct/slam
name = "slam"
desc = "Empower your FIST, to send an opponent flying."
icon_state = "toggled_old"
cast_methods = CAST_MELEE
aspect = ASPECT_UNHOLY
light_color = "#FF5C5C"
light_power = -2
cooldown = 15
/obj/item/weapon/spell/construct/slam/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
var/attack_message = "slams"
if(istype(user, /mob/living/simple_animal))
var/mob/living/simple_animal/S = user
attack_message = pick(S.attacktext)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
L.visible_message("<span class='danger'>\The [user] [attack_message] \the [L], sending them flying!</span>")
playsound(src, "punch", 50, 1)
L.Weaken(2)
L.adjustBruteLoss(rand(30, 50))
var/throwdir = get_dir(src, L)
L.throw_at(get_edge_target_turf(L, throwdir), 3, 1, src)
if(istype(hit_atom, /turf/simulated/wall))
var/turf/simulated/wall/W = hit_atom
user.visible_message("<span class='warning'>\The [user] rears its fist, preparing to hit \the [W]!</span>")
var/windup = cooldown
if(W.reinf_material)
windup = cooldown * 2
if(do_after(user, windup))
W.visible_message("<span class='danger'>\The [user] [attack_message] \the [W], obliterating it!</span>")
W.dismantle_wall(1)
else
user.visible_message("<span class='notice'>\The [user] lowers its fist.</span>")
return
qdel(src)

View File

@@ -14,20 +14,21 @@
return
/obj/item/weapon/melee/cultblade/attack(mob/living/M, mob/living/user, var/target_zone)
if(iscultist(user))
if(iscultist(user) && !istype(user, /mob/living/simple_animal/construct))
return ..()
var/zone = (user.hand ? "l_arm":"r_arm")
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/organ/external/affecting = H.get_organ(zone)
user << "<span class='danger'>An unexplicable force rips through your [affecting.name], tearing the sword from your grasp!</span>"
else
user << "<span class='danger'>An unexplicable force rips through you, tearing the sword from your grasp!</span>"
to_chat(user, "<span class='danger'>An inexplicable force rips through your [affecting.name], tearing the sword from your grasp!</span>")
//random amount of damage between half of the blade's force and the full force of the blade.
user.apply_damage(rand(force/2, force), BRUTE, zone, 0, sharp=1, edge=1)
user.Weaken(5)
else if(!istype(user, /mob/living/simple_animal/construct))
to_chat(user, "<span class='danger'>An inexplicable force rips through you, tearing the sword from your grasp!</span>")
else
to_chat(user, "<span class='critical'>The blade hisses, forcing itself from your manipulators. \The [src] will only allow mortals to wield it against foes, not kin.</span>")
user.drop_from_inventory(src, src.loc)
throw_at(get_edge_target_turf(src, pick(alldirs)), rand(1,3), throw_speed)
@@ -38,10 +39,11 @@
return 1
/obj/item/weapon/melee/cultblade/pickup(mob/living/user as mob)
if(!iscultist(user))
user << "<span class='warning'>An overwhelming feeling of dread comes over you as you pick up the cultist's sword. It would be wise to be rid of this blade quickly.</span>"
if(!iscultist(user) && !istype(user, /mob/living/simple_animal/construct))
to_chat(user, "<span class='warning'>An overwhelming feeling of dread comes over you as you pick up the cultist's sword. It would be wise to be rid of this blade quickly.</span>")
user.make_dizzy(120)
if(istype(user, /mob/living/simple_animal/construct))
to_chat(user, "<span class='warning'>\The [src] hisses, as it is discontent with your acquisition of it. It would be wise to return it to a worthy mortal quickly.</span>")
/obj/item/clothing/head/culthood
name = "cult hood"

View File

@@ -19,6 +19,7 @@
#define ASPECT_EMP "emp" //Unused now.
#define ASPECT_UNSTABLE "unstable" //Heavily RNG-based, causes instability to the victim.
#define ASPECT_CHROMATIC "chromatic" //Used to combine with other spells.
#define ASPECT_UNHOLY "unholy" //Involves the dead, blood, and most things against divine beings.
/obj/item/weapon/spell
name = "glowing particles"

View File

@@ -137,6 +137,18 @@
add_hiddenprint(user)
destroy()
/obj/machinery/camera/attack_generic(mob/user as mob)
if(isanimal(user))
var/mob/living/simple_animal/S = user
set_status(0)
S.do_attack_animation(src)
S.setClickCooldown(user.get_attack_speed())
visible_message("<span class='warning'>\The [user] [pick(S.attacktext)] \the [src]!</span>")
playsound(src.loc, S.attack_sound, 100, 1)
add_hiddenprint(user)
destroy()
..()
/obj/machinery/camera/attackby(obj/item/W as obj, mob/living/user as mob)
update_coverage()
// DECONSTRUCTION

View File

@@ -197,6 +197,27 @@
return
..()
// Proc: attack_generic()
// Parameters: Attacking simple mob, incoming damage.
// Description: Checks the power or integrity of the blast door, if either have failed, chekcs the damage to determine if the creature would be able to open the door by force. Otherwise, super.
/obj/machinery/door/blast/attack_generic(var/mob/user, var/damage)
if(stat & (BROKEN|NOPOWER))
if(damage >= 10)
if(src.density)
visible_message("<span class='danger'>\The [user] starts forcing \the [src] open!</span>")
if(do_after(user, 5 SECONDS, src))
visible_message("<span class='danger'>\The [user] forces \the [src] open!</span>")
force_open(1)
else
visible_message("<span class='danger'>\The [user] starts forcing \the [src] closed!</span>")
if(do_after(user, 2 SECONDS, src))
visible_message("<span class='danger'>\The [user] forces \the [src] closed!</span>")
force_close(1)
else
visible_message("<span class='notice'>\The [user] strains fruitlessly to force \the [src] [density ? "open" : "closed"].</span>")
return
..()
// Proc: open()
// Parameters: None
// Description: Opens the door. Does necessary checks. Automatically closes if autoclose is true

View File

@@ -38,8 +38,11 @@
var/atom/movable/overlay/c_animation = null
/obj/machinery/door/attack_generic(var/mob/user, var/damage)
if(isanimal(user))
var/mob/living/simple_animal/S = user
if(damage >= 10)
visible_message("<span class='danger'>\The [user] smashes into the [src]!</span>")
playsound(src, S.attack_sound, 75, 1)
take_damage(damage)
else
visible_message("<span class='notice'>\The [user] bonks \the [src] harmlessly.</span>")

View File

@@ -216,6 +216,27 @@
return
..()
/obj/machinery/door/firedoor/attack_generic(var/mob/user, var/damage)
if(stat & (BROKEN|NOPOWER))
if(damage >= 10)
var/time_to_force = (2 + (2 * blocked)) * 5
if(src.density)
visible_message("<span class='danger'>\The [user] starts forcing \the [src] open!</span>")
if(do_after(user, time_to_force, src))
visible_message("<span class='danger'>\The [user] forces \the [src] open!</span>")
src.blocked = 0
open(1)
else
time_to_force = (time_to_force / 2)
visible_message("<span class='danger'>\The [user] starts forcing \the [src] closed!</span>")
if(do_after(user, time_to_force, src))
visible_message("<span class='danger'>\The [user] forces \the [src] closed!</span>")
close(1)
else
visible_message("<span class='notice'>\The [user] strains fruitlessly to force \the [src] [density ? "open" : "closed"].</span>")
return
..()
/obj/machinery/door/firedoor/attackby(obj/item/weapon/C as obj, mob/user as mob)
add_fingerprint(user)
if(istype(C, /obj/item/taperoll))

View File

@@ -393,6 +393,18 @@ var/list/turret_icons
attacked = 0
..()
/obj/machinery/porta_turret/attack_generic(mob/user as mob, var/damage)
if(isanimal(user))
var/mob/living/simple_animal/S = user
if(damage >= 10)
var/incoming_damage = round(damage - (damage / 5)) //Turrets are slightly armored, assumedly.
visible_message("<span class='danger'>\The [S] [pick(S.attacktext)] \the [src]!</span>")
take_damage(incoming_damage)
S.do_attack_animation(src)
return 1
visible_message("<span class='notice'>\The [user] bonks \the [src]'s casing!</span>")
return ..()
/obj/machinery/porta_turret/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
//Emagging the turret makes it go bonkers and stun everyone. It also makes

View File

@@ -102,6 +102,11 @@
user << "<span class='danger'>Transfer failed:</span> Existing AI found on remote device. Remove existing AI to install a new one."
return 0
if(!user.IsAdvancedToolUser() && isanimal(user))
var/mob/living/simple_animal/S = user
if(!S.IsHumanoidToolUser(src))
return 0
user.visible_message("\The [user] starts transferring \the [ai] into \the [src]...", "You start transferring \the [ai] into \the [src]...")
ai << "<span class='danger'>\The [user] is transferring you into \the [src]!</span>"

View File

@@ -22,6 +22,11 @@ AI MODULES
var/datum/ai_laws/laws = null
/obj/item/weapon/aiModule/proc/install(var/atom/movable/AM, var/mob/living/user)
if(!user.IsAdvancedToolUser() && isanimal(user))
var/mob/living/simple_animal/S = user
if(!S.IsHumanoidToolUser(src))
return 0
if (istype(AM, /obj/machinery/computer/aiupload))
var/obj/machinery/computer/aiupload/comp = AM
if(comp.stat & NOPOWER)

View File

@@ -29,7 +29,14 @@
return 0
/obj/item/weapon/rcd/proc/can_use(var/mob/user,var/turf/T)
return (user.Adjacent(T) && user.get_active_hand() == src && !user.stat && !user.restrained())
var/usable = 0
if(user.Adjacent(T) && user.get_active_hand() == src && !user.stat && !user.restrained())
usable = 1
if(!user.IsAdvancedToolUser() && istype(user, /mob/living/simple_animal))
var/mob/living/simple_animal/S = user
if(!S.IsHumanoidToolUser(src))
usable = 0
return usable
/obj/item/weapon/rcd/examine()
..()

View File

@@ -199,3 +199,13 @@
/obj/structure/simple_door/resin/New(var/newloc,var/material_name)
..(newloc, "resin")
/obj/structure/simple_door/cult/New(var/newloc,var/material_name)
..(newloc, "cult")
/obj/structure/simple_door/cult/TryToSwitchState(atom/user)
if(isliving(user))
var/mob/living/L = user
if(!iscultist(L) && !istype(L, /mob/living/simple_animal/construct))
return
..()

View File

@@ -57,12 +57,19 @@
source.thermal_conductivity = initial(source.thermal_conductivity)
/turf/simulated/wall/proc/fail_smash(var/mob/user)
user << "<span class='danger'>You smash against the wall!</span>"
to_chat(user, "<span class='danger'>You smash against the wall!</span>")
if(isanimal(user))
var/mob/living/simple_animal/S = user
playsound(src, S.attack_sound, 75, 1)
user.do_attack_animation(src)
take_damage(rand(25,75))
/turf/simulated/wall/proc/success_smash(var/mob/user)
user << "<span class='danger'>You smash through the wall!</span>"
to_chat(user, "<span class='danger'>You smash through the wall!</span>")
user.do_attack_animation(src)
if(isanimal(user))
var/mob/living/simple_animal/S = user
playsound(src, S.attack_sound, 75, 1)
spawn(1)
dismantle_wall(1)

View File

@@ -0,0 +1,146 @@
/*
* Modifiers originating from cult runes, spells, or pylons are kept here.
*/
////////// Self-Enhancing
/datum/modifier/fortify
name = "fortified body"
desc = "You are taking less damage from outside sources."
on_created_text = "<span class='critical'>Your body becomes a mountain to your enemies' storm.</span>"
on_expired_text = "<span class='notice'>Your body softens, returning to its regular durability.</span>"
stacks = MODIFIER_STACK_EXTEND
disable_duration_percent = 0.25 // Disables only last 25% as long.
incoming_damage_percent = 0.5 // 50% incoming damage.
icon_scale_percent = 1.2 // Become a bigger target.
pain_immunity = TRUE
slowdown = 2
evasion = -20
/datum/modifier/ambush
name = "phased"
desc = "You are partially shifted from the material plane."
on_created_text = "<span class='critical'>Your body pulses, before partially dematerializing.</span>"
on_expired_text = "<span class='notice'>Your body rematerializes fully.</span>"
stacks = MODIFIER_STACK_FORBID
incoming_damage_percent = 0.1 // 10% incoming damage. You're not all there.
outgoing_melee_damage_percent = 0 // 0% outgoing damage. Be prepared.
pain_immunity = TRUE
evasion = 50 //Luckily, not being all there means you're actually hard to hit with a gun.
/datum/modifier/ambush/on_applied()
holder.alpha = 30
return
// Override this for special effects when it gets removed.
/datum/modifier/ambush/on_expire()
holder.alpha = 255
return
////////// On-hit
/datum/modifier/deep_wounds
name = "deep wounds"
desc = "Your wounds are mysteriously harder to mend."
on_created_text = "<span class='cult'>Your wounds pain you greatly.</span>"
on_expired_text = "<span class='notice'>Your wounds numb for a moment.</span>"
stacks = MODIFIER_STACK_EXTEND
incoming_healing_percent = 0.66 // 34% less healing.
disable_duration_percent = 1.22 // 22% longer disables.
////////// Auras
/datum/modifier/repair_aura //This aura does not apply modifiers to individuals in the area.
name = "aura of repair (cult)"
desc = "You are emitting a field of strange energy, capable of repairing occult constructs."
on_created_text = "<span class='cult'>You begin emitting an occult repair aura.</span>"
on_expired_text = "<span class='notice'>The occult repair aura fades.</span>"
stacks = MODIFIER_STACK_EXTEND
mob_overlay_state = "cult_aura"
/datum/modifier/repair_aura/tick()
spawn()
for(var/mob/living/simple_animal/construct/T in view(4,holder))
T.adjustBruteLoss(rand(-10,-15))
T.adjustFireLoss(rand(-10,-15))
/datum/modifier/agonize //This modifier is used in an aura spell.
name = "agonize"
desc = "Your body is wracked with pain."
on_created_text = "<span class='cult'>A red lightning quickly covers your body. The pain is horrendous.</span>"
on_expired_text = "<span class='notice'>The lightning fades, and so too does the ongoing pain.</span>"
stacks = MODIFIER_STACK_EXTEND
mob_overlay_state = "red_electricity_constant"
/datum/modifier/agonize/tick()
spawn()
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
H.apply_effect(20, AGONY)
if(prob(10))
to_chat(H, "<span class='warning'>Just make it stop!</span>")
////////// Target Modifier
/datum/modifier/mend_occult
name = "occult mending"
desc = "Your body is mending, though at what cost?"
on_created_text = "<span class='cult'>Something haunting envelops your body as it begins to mend.</span>"
on_expired_text = "<span class='notice'>The cloak of unease dissipates.</span>"
stacks = MODIFIER_STACK_EXTEND
mob_overlay_state = "red_electricity_constant"
/datum/modifier/mend_occult/tick()
spawn()
if(isliving(holder))
var/mob/living/L = holder
if(istype(L, /mob/living/simple_animal/construct))
L.adjustBruteLoss(rand(-5,-10))
L.adjustFireLoss(rand(-5,-10))
else
L.adjustBruteLoss(-2)
L.adjustFireLoss(-2)
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
for(var/obj/item/organ/O in H.internal_organs)
if(O.damage > 0) // Fix internal damage
O.damage = max(O.damage - 2, 0)
if(O.damage <= 5 && O.organ_tag == O_EYES) // Fix eyes
H.sdisabilities &= ~BLIND
for(var/obj/item/organ/external/O in H.organs) // Fix limbs, no matter if they are Man or Machine.
O.heal_damage(rand(1,3), rand(1,3), internal = 1, robo_repair = 1)
for(var/obj/item/organ/E in H.bad_external_organs) // Fix bones
var/obj/item/organ/external/affected = E
if((affected.damage < affected.min_broken_damage * config.organ_health_multiplier) && (affected.status & ORGAN_BROKEN))
affected.status &= ~ORGAN_BROKEN
for(var/datum/wound/W in affected.wounds) // Fix IB
if(istype(W, /datum/wound/internal_bleeding))
affected.wounds -= W
affected.update_damages()
H.restore_blood()
H.apply_effect(15, AGONY)
if(prob(10))
to_chat(H, "<span class='danger'>It feels as though your body is being torn apart!</span>")
L.updatehealth()

View File

@@ -261,6 +261,7 @@ note dizziness decrements automatically in the mob's Life() proc.
// And animate the attack!
animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
update_icon()
return TRUE //Found an item, doing item attack animation.
/mob/proc/spin(spintime, speed)

View File

@@ -1,22 +1,39 @@
/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
@@ -25,11 +42,16 @@
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
@@ -39,6 +61,51 @@
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
@@ -51,6 +118,16 @@
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()
@@ -61,11 +138,15 @@
/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())
adjustBruteLoss(-5)
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
user << "<span class='notice'>\The [src] is undamaged.</span>"
to_chat(user, "<span class='notice'>\The [src] is undamaged.</span>")
return
return ..()
@@ -83,6 +164,8 @@
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///////////////
@@ -91,36 +174,71 @@
/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 = 250
health = 250
maxHealth = 300
health = 300
response_harm = "harmlessly punches"
harm_intent_damage = 0
melee_damage_lower = 30
melee_damage_upper = 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 = 3
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)
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(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))
adjustBruteLoss(P.damage * 0.5)
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)
@@ -145,21 +263,32 @@
/mob/living/simple_animal/construct/wraith
name = "Wraith"
real_name = "Wraith"
desc = "A wicked bladed shell contraption piloted by a bound spirit"
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 = 75
health = 75
maxHealth = 200
health = 200
melee_damage_lower = 25
melee_damage_upper = 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
see_in_dark = 7
attack_sound = 'sound/weapons/rapidslice.ogg'
construct_spells = list(/spell/targeted/ethereal_jaunt/shift)
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/////////////////////////
@@ -168,35 +297,43 @@
/mob/living/simple_animal/construct/builder
name = "Artificer"
real_name = "Artificer"
desc = "A bulbous construct dedicated to building and maintaining The Cult of Nar-Sie's armies"
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 = 50
health = 50
maxHealth = 150
health = 150
response_harm = "viciously beaten"
harm_intent_damage = 5
melee_damage_lower = 5
melee_damage_upper = 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 = 1
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/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"
desc = "The pinnacle of occult technology, Behemoths are the ultimate weapon in the Cult of Nar-Sie's arsenal."
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"
@@ -208,38 +345,84 @@
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
construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser)
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"
desc = "The promised reward of the livings who follow narsie. Obtained by offering their bodies to the geometer of blood"
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 = 25
melee_damage_lower = 20
melee_damage_upper = 25
attack_sharp = 1
attacktext = list("violently stabbed")
speed = -1
friendly = list("caresses")
speed = 0
environment_smash = 1
see_in_dark = 7
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/targeted/harvest,
/spell/aoe_turf/knock/harvester,
/spell/targeted/construct_advanced/inversion_beam,
/spell/targeted/construct_advanced/agonizing_sphere,
/spell/rune_write
)
@@ -250,6 +433,9 @@
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()
@@ -268,71 +454,35 @@
silence_spells(purge)
/mob/living/simple_animal/construct/armoured/Life()
..()
/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)
switch(health)
if(250 to INFINITY) healths.icon_state = "juggernaut_health0"
if(208 to 249) healths.icon_state = "juggernaut_health1"
if(167 to 207) healths.icon_state = "juggernaut_health2"
if(125 to 166) healths.icon_state = "juggernaut_health3"
if(84 to 124) healths.icon_state = "juggernaut_health4"
if(42 to 83) healths.icon_state = "juggernaut_health5"
if(1 to 41) healths.icon_state = "juggernaut_health6"
else healths.icon_state = "juggernaut_health7"
/mob/living/simple_animal/construct/behemoth/Life()
..()
if(healths)
switch(health)
if(750 to INFINITY) healths.icon_state = "juggernaut_health0"
if(625 to 749) healths.icon_state = "juggernaut_health1"
if(500 to 624) healths.icon_state = "juggernaut_health2"
if(375 to 499) healths.icon_state = "juggernaut_health3"
if(250 to 374) healths.icon_state = "juggernaut_health4"
if(125 to 249) healths.icon_state = "juggernaut_health5"
if(1 to 124) healths.icon_state = "juggernaut_health6"
else healths.icon_state = "juggernaut_health7"
/mob/living/simple_animal/construct/builder/Life()
..()
if(healths)
switch(health)
if(50 to INFINITY) healths.icon_state = "artificer_health0"
if(42 to 49) healths.icon_state = "artificer_health1"
if(34 to 41) healths.icon_state = "artificer_health2"
if(26 to 33) healths.icon_state = "artificer_health3"
if(18 to 25) healths.icon_state = "artificer_health4"
if(10 to 17) healths.icon_state = "artificer_health5"
if(1 to 9) healths.icon_state = "artificer_health6"
else healths.icon_state = "artificer_health7"
/mob/living/simple_animal/construct/wraith/Life()
..()
if(healths)
switch(health)
if(75 to INFINITY) healths.icon_state = "wraith_health0"
if(62 to 74) healths.icon_state = "wraith_health1"
if(50 to 61) healths.icon_state = "wraith_health2"
if(37 to 49) healths.icon_state = "wraith_health3"
if(25 to 36) healths.icon_state = "wraith_health4"
if(12 to 24) healths.icon_state = "wraith_health5"
if(1 to 11) healths.icon_state = "wraith_health6"
else healths.icon_state = "wraith_health7"
/mob/living/simple_animal/construct/harvester/Life()
..()
if(healths)
switch(health)
if(150 to INFINITY) healths.icon_state = "harvester_health0"
if(125 to 149) healths.icon_state = "harvester_health1"
if(100 to 124) healths.icon_state = "harvester_health2"
if(75 to 99) healths.icon_state = "harvester_health3"
if(50 to 74) healths.icon_state = "harvester_health4"
if(25 to 49) healths.icon_state = "harvester_health5"
if(1 to 24) healths.icon_state = "harvester_health6"
else healths.icon_state = "harvester_health7"
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

@@ -11,6 +11,7 @@
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////////////////////////////////////////////////////////
@@ -145,9 +146,9 @@
src.icon_state = "soulstone2"
src.name = "Soul Stone: [S.real_name]"
S << "Your soul has been captured! You are now bound to [U.name]'s will, help them suceed in their goals at all costs."
U << "<span class='notice'>Capture successful!</span> : [T.real_name]'s soul has been ripped from their body and stored within the soul stone."
U << "The soulstone has been imprinted with [S.real_name]'s mind, it will no longer react to other souls."
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)
@@ -155,13 +156,13 @@
if(!istype(T))
return;
if (T.stat == DEAD)
U << "<span class='danger'>Capture failed!</span>: The shade has already been banished!"
to_chat(U, "<span class='danger'>Capture failed!</span>: The shade has already been banished!")
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."
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)
U << "<span class='danger'>Capture failed!</span>: The soul stone has already been imprinted with [src.imprinted]'s mind!"
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
@@ -170,14 +171,15 @@
T.health = T.getMaxHealth()
src.icon_state = "soulstone2"
T << "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form"
U << "<span class='notice'>Capture successful!</span> : [T.name]'s has been recaptured and stored within the soul stone."
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)
U << "<span class='danger'>Capture failed!</span>: The soul stone is empty! Go kill someone!"
to_chat(U,"<span class='danger'>Capture failed!</span>: The soul stone is empty! Go kill someone!")
return;
var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer")
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))
@@ -185,8 +187,8 @@
if(iscultist(U))
cult.add_antagonist(Z.mind)
qdel(T)
Z << "<B>You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike.</B>"
Z << "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>"
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")
@@ -195,8 +197,8 @@
if(iscultist(U))
cult.add_antagonist(Z.mind)
qdel(T)
Z << "<B>You are playing a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.</B>"
Z << "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>"
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")
@@ -205,10 +207,31 @@
if(iscultist(U))
cult.add_antagonist(Z.mind)
qdel(T)
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>"
Z << "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>"
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")

View File

@@ -20,6 +20,8 @@
var/show_stat_health = 1 // Does the percentage health show in the stat panel for the mob
var/ai_inactive = 0 // Set to 1 to turn off most AI actions
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,
@@ -139,6 +141,7 @@
var/astar_adjacent_proc = /turf/proc/CardinalTurfsWithAccess // Proc to use when A* pathfinding. Default makes them bound to cardinals.
//Damage resistances
var/shock_resistance = 0 // Siemens modifier, directly subtracted from 1. Value of 0.4 means 0.6 siemens on shocks.
var/resistance = 0 // Damage reduction for all types
var/list/armor = list( // Values for normal getarmor() checks
"melee" = 0,
@@ -785,6 +788,9 @@
return verb
/mob/living/simple_animal/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
@@ -1265,7 +1271,7 @@
// This is the actual act of 'punching'. Override for special behaviour.
/mob/living/simple_animal/proc/DoPunch(var/atom/A)
if(!Adjacent(A)) // They could've moved in the meantime.
if(!Adjacent(A) && !istype(A, /obj/structure/window) && !istype(A, /obj/machinery/door/window)) // They could've moved in the meantime. But a Window probably wouldn't have. This allows player simple-mobs to attack windows.
return FALSE
var/damage_to_do = rand(melee_damage_lower, melee_damage_upper)
@@ -1500,7 +1506,7 @@
//Touches a wire, etc
/mob/living/simple_animal/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null)
shock_damage *= siemens_coeff
shock_damage *= max(siemens_coeff - shock_resistance, 0)
if (shock_damage < 1)
return 0
@@ -1566,11 +1572,11 @@
hud_used.l_hand_hud_object.icon_state = "l_hand_inactive"
hud_used.r_hand_hud_object.icon_state = "r_hand_active"
return
/*
/mob/living/simple_animal/put_in_active_hand(var/obj/item/I)
if(!has_hands || !istype(I))
return
*/
//Puts the item into our active hand if possible. returns 1 on success.
/mob/living/simple_animal/put_in_active_hand(var/obj/item/W)
if(!has_hands)
@@ -1679,6 +1685,23 @@
/mob/living/simple_animal/IsAdvancedToolUser()
return has_hands
/mob/living/simple_animal/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_animal/drop_from_inventory(var/obj/item/W, var/atom/target = null)
. = ..(W, target)
if(!target)
target = src.loc
if(.)
W.forceMove(src.loc)
//Commands, reactions, etc
/mob/living/simple_animal/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
..()

View File

@@ -67,6 +67,9 @@
/mob/living/carbon/human/can_overcome_gravity()
return species && species.can_overcome_gravity(src)
/mob/living/simple_animal/construct/can_overcome_gravity()
return 1 //They care not for standard physics.
/mob/observer/zMove(direction)
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
if(destination)
@@ -97,6 +100,9 @@
/mob/observer/can_ztravel()
return 1
/mob/living/simple_animal/construct/can_ztravel()
return 1
/mob/living/carbon/human/can_ztravel()
if(incapacitated())
return 0
@@ -209,6 +215,9 @@
/mob/living/simple_animal/hostile/carp/can_fall() // So can carp apparently.
return FALSE
/mob/living/simple_animal/construct/can_fall() //As do Constructs.
return FALSE
// Check if this atom prevents things standing on it from falling. Return TRUE to allow the fall.
/obj/proc/CanFallThru(atom/movable/mover as mob|obj, turf/target as turf)
return TRUE

View File

@@ -268,3 +268,24 @@
light_range = 2
light_power = 0.5
light_color = "#8837A3"
//----------------------------
// Inversion / Cult
//----------------------------
/obj/effect/projectile/inversion/tracer
icon_state = "invert"
light_range = 2
light_power = -2
light_color = "#FFFFFF"
/obj/effect/projectile/inversion/muzzle
icon_state = "muzzle_invert"
light_range = 2
light_power = -2
light_color = "#FFFFFF"
/obj/effect/projectile/inversion/impact
icon_state = "impact_invert"
light_range = 2
light_power = -2
light_color = "#FFFFFF"

View File

@@ -141,6 +141,10 @@
return 0
if(!user.IsAdvancedToolUser())
return 0
if(isanimal(user))
var/mob/living/simple_animal/S = user
if(!S.IsHumanoidToolUser(src))
return 0
var/mob/living/M = user
if(dna_lock && attached_lock.stored_dna)

View File

@@ -1,5 +1,9 @@
//////////////////////////////Construct Spells/////////////////////////
/*
* This has been moved to game/gamemodes/cult/construct_spells.dm. This is here for posterity.
*/
/*
/spell/aoe_turf/conjure/construct
name = "Artificer"
desc = "This spell conjures a construct which may be controlled by Shades"
@@ -110,6 +114,44 @@
continue
return
/spell/aoe_turf/conjure/door
name = "Stone Door"
desc = "This spell conjures a massive stone door."
charge_max = 100
spell_flags = CONSTRUCT_CHECK
invocation = "none"
invocation_type = SpI_NONE
range = 0
hud_state = "const_rune"
/spell/aoe_turf/conjure/door/cast(list/targets)
..()
var/turf/spawn_place = pick(targets)
if(spawn_place)
new /obj/structure/simple_door/cult(spawn_place)
return
/spell/aoe_turf/conjure/grille
name = "Arcane Grille"
desc = "This spell conjures an airtight grille."
charge_max = 100
spell_flags = CONSTRUCT_CHECK
invocation = "none"
invocation_type = SpI_NONE
range = 0
hud_state = "const_rune"
/spell/aoe_turf/conjure/grille/cast(list/targets)
..()
var/turf/spawn_place = pick(targets)
if(spawn_place)
new /obj/structure/grille/cult(spawn_place)
return
/spell/aoe_turf/conjure/forcewall/lesser
name = "Shield"
desc = "Allows you to pull up a shield to protect yourself and allies from incoming threats"
@@ -135,3 +177,4 @@
/obj/effect/forcefield/cult/cultify()
return
*/

View File

@@ -22,7 +22,7 @@
door.open()
return
/* Moved to game/gamemodes/cult/construct_spells.dm.
//Construct version
/spell/aoe_turf/knock/harvester
name = "Disintegrate Doors"
@@ -42,3 +42,4 @@
for(var/obj/machinery/door/door in T.contents)
spawn door.cultify()
return
*/

View File

@@ -1,5 +1,8 @@
//////////////////////////////Construct Spells/////////////////////////
/*
* Moved to game/gamemodes/cult/construct_spells.dm. Here for posterity.
*/
/*
proc/findNullRod(var/atom/target)
if(istype(target,/obj/item/weapon/nullrod))
return 1
@@ -8,3 +11,4 @@ proc/findNullRod(var/atom/target)
if(findNullRod(A))
return 1
return 0
*/

View File

@@ -1,3 +1,10 @@
/*
* Here for posterity. Moved to game/gamemodes/cult/construct_spells.dm, though it has been disabled there.
*/
/*
/spell/targeted/harvest
name = "Harvest"
desc = "Back to where I come from, and you're coming with me."
@@ -34,3 +41,4 @@
user << "<span class='sinister'>You warp back to Nar-Sie[prey ? " along with your prey":""].</span>"
else
user << "<span class='danger'>...something's wrong!</span>"//There shouldn't be an instance of Harvesters when Nar-Sie isn't in the world.
*/

View File

@@ -1,3 +1,8 @@
/*
* This has been moved to game/gamemodes/cult/construct_spells.dm. This is here for posterity.
*/
/*
/spell/targeted/ethereal_jaunt/shift
name = "Phase Shift"
desc = "This spell allows you to pass through walls"
@@ -22,3 +27,4 @@
/spell/targeted/ethereal_jaunt/shift/jaunt_steam(var/mobloc)
return
*/

View File

@@ -174,6 +174,21 @@
visible_message("<span class='danger'>\The [user] tears apart \the [src]!</span>")
src.break_to_parts()
/obj/structure/table/attack_generic(mob/user as mob, var/damage)
if(damage >= 10)
if(reinforced && prob(70))
visible_message("<span class='danger'>\The [user] smashes against \the [src]!</span>")
take_damage(damage/2)
user.do_attack_animation(src)
..()
else
visible_message("<span class='danger'>\The [user] tears apart \the [src]!</span>")
src.break_to_parts()
user.do_attack_animation(src)
return 1
visible_message("<span class='notice'>\The [user] scratches at \the [src]!</span>")
return ..()
/obj/structure/table/MouseDrop_T(obj/item/stack/material/what)
if(can_reinforce && isliving(usr) && (!usr.stat) && istype(what) && usr.get_active_hand() == what && Adjacent(usr))
reinforce_table(what, usr)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 KiB

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

@@ -443,6 +443,7 @@
#include "code\game\gamemodes\changeling\powers\silence_sting.dm"
#include "code\game\gamemodes\changeling\powers\transform.dm"
#include "code\game\gamemodes\changeling\powers\visible_camouflage.dm"
#include "code\game\gamemodes\cult\construct_spells.dm"
#include "code\game\gamemodes\cult\cult.dm"
#include "code\game\gamemodes\cult\cult_items.dm"
#include "code\game\gamemodes\cult\cult_structures.dm"
@@ -1686,6 +1687,7 @@
#include "code\modules\mob\_modifiers\modifiers_misc.dm"
#include "code\modules\mob\_modifiers\traits.dm"
#include "code\modules\mob\_modifiers\traits_phobias.dm"
#include "code\modules\mob\_modifiers\unholy.dm"
#include "code\modules\mob\dead\death.dm"
#include "code\modules\mob\dead\observer\login.dm"
#include "code\modules\mob\dead\observer\logout.dm"
@@ -2264,7 +2266,6 @@
#include "code\modules\shuttles\shuttles_web.dm"
#include "code\modules\shuttles\web_datums.dm"
#include "code\modules\spells\artifacts.dm"
#include "code\modules\spells\construct_spells.dm"
#include "code\modules\spells\no_clothes.dm"
#include "code\modules\spells\spell_code.dm"
#include "code\modules\spells\spell_projectile.dm"
@@ -2278,15 +2279,12 @@
#include "code\modules\spells\aoe_turf\smoke.dm"
#include "code\modules\spells\aoe_turf\summons.dm"
#include "code\modules\spells\aoe_turf\conjure\conjure.dm"
#include "code\modules\spells\aoe_turf\conjure\construct.dm"
#include "code\modules\spells\aoe_turf\conjure\forcewall.dm"
#include "code\modules\spells\general\area_teleport.dm"
#include "code\modules\spells\general\rune_write.dm"
#include "code\modules\spells\targeted\ethereal_jaunt.dm"
#include "code\modules\spells\targeted\genetic.dm"
#include "code\modules\spells\targeted\harvest.dm"
#include "code\modules\spells\targeted\mind_transfer.dm"
#include "code\modules\spells\targeted\shift.dm"
#include "code\modules\spells\targeted\subjugate.dm"
#include "code\modules\spells\targeted\targeted.dm"
#include "code\modules\spells\targeted\equip\equip.dm"