Adds Necropolis curses for cursed items in Necropolis ruins (#28992)
* Adds Necropolis curses for cursed items in Necropolis ruins * Adds sounds credit @FuryMcFlurry * stat tweak * these are painful enough * a bit stronger * i kind of wish there was a version of get_ranged_target_turf() that worked off of angle.... but there isn't * smart coder 2000 * bossed around
@@ -73,6 +73,7 @@
|
||||
#define UI_DAMAGE_LAYER 18.2
|
||||
#define BLIND_LAYER 18.3
|
||||
#define CRIT_LAYER 18.4
|
||||
#define CURSE_LAYER 18.5
|
||||
|
||||
#define HUD_PLANE 19
|
||||
#define HUD_LAYER 19
|
||||
|
||||
@@ -51,6 +51,12 @@
|
||||
#define DEVIL_BODYPART "devil"
|
||||
/*see __DEFINES/inventory.dm for bodypart bitflag defines*/
|
||||
|
||||
//Health hud screws for carbon mobs
|
||||
#define SCREWYHUD_NONE 0
|
||||
#define SCREWYHUD_CRIT 1
|
||||
#define SCREWYHUD_DEAD 2
|
||||
#define SCREWYHUD_HEALTHY 3
|
||||
|
||||
//Nutrition levels for humans
|
||||
#define NUTRITION_LEVEL_FAT 600
|
||||
#define NUTRITION_LEVEL_FULL 550
|
||||
|
||||
@@ -54,6 +54,12 @@
|
||||
|
||||
#define STATUS_EFFECT_SAWBLEED /datum/status_effect/saw_bleed //if the bleed builds up enough, takes a ton of damage
|
||||
|
||||
#define STATUS_EFFECT_NECROPOLIS_CURSE /datum/status_effect/necropolis_curse
|
||||
#define CURSE_BLINDING 1 //makes the edges of the target's screen obscured
|
||||
#define CURSE_SPAWNING 2 //spawns creatures that attack the target only
|
||||
#define CURSE_WASTING 4 //causes gradual damage
|
||||
#define CURSE_GRASPING 8 //hands reach out from the sides of the screen, doing damage and stunning if they hit the target
|
||||
|
||||
/////////////
|
||||
// NEUTRAL //
|
||||
/////////////
|
||||
|
||||
@@ -100,6 +100,11 @@
|
||||
layer = BLIND_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/obj/screen/fullscreen/curse
|
||||
icon_state = "curse"
|
||||
layer = CURSE_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/obj/screen/fullscreen/impaired
|
||||
icon_state = "impairedoverlay"
|
||||
|
||||
@@ -163,4 +168,4 @@
|
||||
plane = LIGHTING_PLANE
|
||||
layer = LIGHTING_LAYER
|
||||
blend_mode = BLEND_ADD
|
||||
show_when_dead = TRUE
|
||||
show_when_dead = TRUE
|
||||
|
||||
@@ -341,3 +341,96 @@
|
||||
owner.adjustBruteLoss(bleed_damage)
|
||||
else
|
||||
new /obj/effect/temp_visual/bleed(get_turf(owner))
|
||||
|
||||
/mob/living/proc/apply_necropolis_curse(set_curse)
|
||||
var/datum/status_effect/necropolis_curse/C = has_status_effect(STATUS_EFFECT_NECROPOLIS_CURSE)
|
||||
if(!set_curse)
|
||||
set_curse = pick(CURSE_BLINDING, CURSE_SPAWNING, CURSE_WASTING, CURSE_GRASPING)
|
||||
if(QDELETED(C))
|
||||
apply_status_effect(STATUS_EFFECT_NECROPOLIS_CURSE, set_curse)
|
||||
else
|
||||
C.apply_curse(set_curse)
|
||||
C.duration += 3000 //additional curses add 5 minutes
|
||||
|
||||
/datum/status_effect/necropolis_curse
|
||||
id = "necrocurse"
|
||||
duration = 6000 //you're cursed for 10 minutes have fun
|
||||
tick_interval = 50
|
||||
alert_type = null
|
||||
var/curse_flags = NONE
|
||||
var/effect_last_activation = 0
|
||||
var/effect_cooldown = 100
|
||||
var/obj/effect/temp_visual/curse/wasting_effect = new
|
||||
|
||||
/datum/status_effect/necropolis_curse/on_creation(mob/living/new_owner, set_curse)
|
||||
. = ..()
|
||||
if(.)
|
||||
apply_curse(set_curse)
|
||||
|
||||
/datum/status_effect/necropolis_curse/Destroy()
|
||||
if(!QDELETED(wasting_effect))
|
||||
qdel(wasting_effect)
|
||||
wasting_effect = null
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/necropolis_curse/on_remove()
|
||||
remove_curse(curse_flags)
|
||||
|
||||
/datum/status_effect/necropolis_curse/proc/apply_curse(set_curse)
|
||||
curse_flags |= set_curse
|
||||
if(curse_flags & CURSE_BLINDING)
|
||||
owner.overlay_fullscreen("curse", /obj/screen/fullscreen/curse, 1)
|
||||
|
||||
/datum/status_effect/necropolis_curse/proc/remove_curse(remove_curse)
|
||||
if(remove_curse & CURSE_BLINDING)
|
||||
owner.clear_fullscreen("curse", 50)
|
||||
curse_flags &= ~remove_curse
|
||||
|
||||
/datum/status_effect/necropolis_curse/tick()
|
||||
if(owner.stat == DEAD)
|
||||
return
|
||||
if(curse_flags & CURSE_WASTING)
|
||||
wasting_effect.forceMove(owner.loc)
|
||||
wasting_effect.setDir(owner.dir)
|
||||
wasting_effect.transform = owner.transform //if the owner has been stunned the overlay should inherit that position
|
||||
wasting_effect.alpha = 255
|
||||
animate(wasting_effect, alpha = 0, time = 32)
|
||||
playsound(owner, 'sound/effects/curse5.ogg', 20, 1, -1)
|
||||
owner.adjustFireLoss(0.75)
|
||||
if(effect_last_activation <= world.time)
|
||||
effect_last_activation = world.time + effect_cooldown
|
||||
if(curse_flags & CURSE_SPAWNING)
|
||||
var/turf/spawn_turf
|
||||
var/sanity = 10
|
||||
while(!spawn_turf && sanity)
|
||||
spawn_turf = locate(owner.x + pick(rand(10, 15), rand(-10, -15)), owner.y + pick(rand(10, 15), rand(-10, -15)), owner.z)
|
||||
sanity--
|
||||
if(spawn_turf)
|
||||
var/mob/living/simple_animal/hostile/asteroid/curseblob/C = new (spawn_turf)
|
||||
C.set_target = owner
|
||||
C.GiveTarget()
|
||||
if(curse_flags & CURSE_GRASPING)
|
||||
var/grab_dir = turn(owner.dir, pick(-90, 90, 180, 180)) //grab them from a random direction other than the one faced, favoring grabbing from behind
|
||||
var/turf/spawn_turf = get_ranged_target_turf(owner, grab_dir, 5)
|
||||
if(spawn_turf)
|
||||
grasp(spawn_turf)
|
||||
|
||||
/datum/status_effect/necropolis_curse/proc/grasp(turf/spawn_turf)
|
||||
set waitfor = FALSE
|
||||
new/obj/effect/temp_visual/dir_setting/curse/grasp_portal(spawn_turf, owner.dir)
|
||||
playsound(spawn_turf, 'sound/effects/curse2.ogg', 80, 1, -1)
|
||||
var/turf/ownerloc = get_turf(owner)
|
||||
var/obj/item/projectile/curse_hand/C = new (spawn_turf)
|
||||
C.current = spawn_turf
|
||||
C.starting = spawn_turf
|
||||
C.yo = ownerloc.y - spawn_turf.y
|
||||
C.xo = ownerloc.x - spawn_turf.x
|
||||
C.original = owner
|
||||
C.fire()
|
||||
|
||||
/obj/effect/temp_visual/curse
|
||||
icon_state = "curse"
|
||||
|
||||
/obj/effect/temp_visual/curse/Initialize()
|
||||
. = ..()
|
||||
deltimer(timerid)
|
||||
|
||||
@@ -109,6 +109,41 @@
|
||||
icon_state = "tailsweep"
|
||||
duration = 4
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/curse
|
||||
icon_state = "curse"
|
||||
duration = 32
|
||||
var/fades = TRUE
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/curse/Initialize(mapload, set_dir)
|
||||
. = ..()
|
||||
if(fades)
|
||||
animate(src, alpha = 0, time = 32)
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/curse/blob
|
||||
icon_state = "curseblob"
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/curse/grasp_portal
|
||||
icon = 'icons/effects/64x64.dmi'
|
||||
layer = LARGE_MOB_LAYER
|
||||
pixel_y = -16
|
||||
pixel_x = -16
|
||||
duration = 32
|
||||
fades = FALSE
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/curse/grasp_portal/fading
|
||||
duration = 32
|
||||
fades = TRUE
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/curse/hand
|
||||
icon_state = "cursehand"
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/curse/hand/Initialize(mapload, set_dir, handedness)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/projectile/curse_hand/update_icon()
|
||||
icon_state = "[icon_state][handedness]"
|
||||
|
||||
/obj/effect/temp_visual/wizard
|
||||
name = "water"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
|
||||
@@ -11,11 +11,6 @@ Gunshots/explosions/opening doors/less rare audio (done)
|
||||
|
||||
*/
|
||||
|
||||
#define SCREWYHUD_NONE 0
|
||||
#define SCREWYHUD_CRIT 1
|
||||
#define SCREWYHUD_DEAD 2
|
||||
#define SCREWYHUD_HEALTHY 3
|
||||
|
||||
/mob/living/carbon
|
||||
var/image/halimage
|
||||
var/image/halbody
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob
|
||||
name = "curse mass"
|
||||
desc = "A mass of purple... smoke?"
|
||||
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
|
||||
icon_state = "curseblob"
|
||||
icon_living = "curseblob"
|
||||
icon_aggro = "curseblob"
|
||||
move_to_delay = 5
|
||||
vision_range = 20
|
||||
aggro_vision_range = 20
|
||||
idle_vision_range = 20
|
||||
maxHealth = 40 //easy to kill, but oh, will you be seeing a lot of them.
|
||||
health = 40
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 10
|
||||
melee_damage_type = BURN
|
||||
attacktext = "slashes"
|
||||
attack_sound = 'sound/effects/curseattack.ogg'
|
||||
throw_message = "passes through the smokey body of"
|
||||
obj_damage = 0
|
||||
environment_smash = ENVIRONMENT_SMASH_NONE
|
||||
sentience_type = SENTIENCE_BOSS
|
||||
layer = LARGE_MOB_LAYER
|
||||
var/doing_move_loop = FALSE
|
||||
var/mob/living/set_target
|
||||
var/timerid
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/Initialize(mapload)
|
||||
. = ..()
|
||||
timerid = QDEL_IN(src, 600)
|
||||
playsound(src, 'sound/effects/curse1.ogg', 100, 1, -1)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/Destroy()
|
||||
new /obj/effect/temp_visual/dir_setting/curse/blob(loc, dir)
|
||||
doing_move_loop = FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/Goto(move_target, delay, minimum_distance)
|
||||
move_loop(target, delay)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/proc/move_loop(move_target, delay)
|
||||
set waitfor = FALSE
|
||||
if(doing_move_loop)
|
||||
return
|
||||
doing_move_loop = TRUE
|
||||
if(check_for_target())
|
||||
return
|
||||
while(!QDELETED(src) && doing_move_loop && isturf(loc) && !check_for_target())
|
||||
var/step_turf = get_step(src, get_dir(src, set_target))
|
||||
if(step_turf != get_turf(set_target))
|
||||
forceMove(step_turf)
|
||||
sleep(delay)
|
||||
doing_move_loop = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/proc/check_for_target()
|
||||
if(QDELETED(set_target) || set_target.stat != CONSCIOUS || z != set_target.z)
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/GiveTarget(new_target)
|
||||
if(check_for_target())
|
||||
return
|
||||
new_target = set_target
|
||||
. = ..()
|
||||
Goto(target, move_to_delay)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/LoseTarget() //we can't lose our target!
|
||||
if(check_for_target())
|
||||
return
|
||||
|
||||
//if it's not our target, we ignore it
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/CanPass(atom/movable/mover, turf/target, height = 0)
|
||||
if(mover == set_target)
|
||||
return FALSE
|
||||
if(istype(mover, /obj/item/projectile))
|
||||
var/obj/item/projectile/P = mover
|
||||
if(P.firer == set_target)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
#define IGNORE_PROC_IF_NOT_TARGET(X) /mob/living/simple_animal/hostile/asteroid/curseblob/##X(AM) { if (AM == set_target) return ..(); }
|
||||
|
||||
IGNORE_PROC_IF_NOT_TARGET(attack_hand)
|
||||
|
||||
IGNORE_PROC_IF_NOT_TARGET(attack_hulk)
|
||||
|
||||
IGNORE_PROC_IF_NOT_TARGET(attack_paw)
|
||||
|
||||
IGNORE_PROC_IF_NOT_TARGET(attack_alien)
|
||||
|
||||
IGNORE_PROC_IF_NOT_TARGET(attack_larva)
|
||||
|
||||
IGNORE_PROC_IF_NOT_TARGET(attack_animal)
|
||||
|
||||
IGNORE_PROC_IF_NOT_TARGET(attack_slime)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/bullet_act(obj/item/projectile/Proj)
|
||||
if(Proj.firer != set_target)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/attacked_by(obj/item/I, mob/living/L)
|
||||
if(L != set_target)
|
||||
return
|
||||
return ..()
|
||||
|
||||
#undef IGNORE_PROC_IF_NOT_TARGET
|
||||
@@ -161,6 +161,8 @@
|
||||
var/turf/target_turf = get_turf(A)
|
||||
|
||||
if(!prehit(A))
|
||||
if(forcedodge)
|
||||
loc = target_turf
|
||||
return FALSE
|
||||
var/permutation = A.bullet_act(src, def_zone) // searches for return value, could be deleted after run so check A isn't null
|
||||
if(permutation == -1 || forcedodge)// the bullet passes through a dense object!
|
||||
@@ -264,7 +266,7 @@
|
||||
old_pixel_x = pixel_x_offset
|
||||
old_pixel_y = pixel_y_offset
|
||||
|
||||
if(original && (original.layer>=2.75) || ismob(original))
|
||||
if(original && (original.layer >= PROJECTILE_HIT_THRESHHOLD_LAYER) || ismob(original))
|
||||
if(loc == get_turf(original))
|
||||
if(!(original in permutated))
|
||||
Bump(original, 1)
|
||||
@@ -279,7 +281,7 @@
|
||||
if((!( current ) || loc == current))
|
||||
current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z)
|
||||
step_towards(src, current)
|
||||
if(original && (original.layer>=2.75) || ismob(original))
|
||||
if(original && (original.layer >= PROJECTILE_HIT_THRESHHOLD_LAYER) || ismob(original))
|
||||
if(loc == get_turf(original))
|
||||
if(!(original in permutated))
|
||||
Bump(original, 1)
|
||||
|
||||
@@ -334,3 +334,57 @@
|
||||
for(var/turf/Z in range(T,power))
|
||||
new /obj/effect/temp_visual/gravpush(Z)
|
||||
|
||||
/obj/effect/ebeam/curse_arm
|
||||
name = "curse arm"
|
||||
layer = LARGE_MOB_LAYER
|
||||
|
||||
/obj/item/projectile/curse_hand
|
||||
name = "curse hand"
|
||||
icon_state = "cursehand"
|
||||
hitsound = 'sound/effects/curse4.ogg'
|
||||
layer = LARGE_MOB_LAYER
|
||||
damage_type = BURN
|
||||
damage = 10
|
||||
knockdown = 20
|
||||
speed = 2
|
||||
range = 16
|
||||
forcedodge = TRUE
|
||||
var/datum/beam/arm
|
||||
var/handedness = 0
|
||||
|
||||
/obj/item/projectile/curse_hand/Initialize(mapload)
|
||||
. = ..()
|
||||
handedness = prob(50)
|
||||
update_icon()
|
||||
|
||||
/obj/item/projectile/curse_hand/update_icon()
|
||||
icon_state = "[icon_state][handedness]"
|
||||
|
||||
/obj/item/projectile/curse_hand/fire(setAngle)
|
||||
if(starting)
|
||||
arm = starting.Beam(src, icon_state = "curse[handedness]", time = INFINITY, maxdistance = INFINITY, beam_type=/obj/effect/ebeam/curse_arm)
|
||||
..()
|
||||
|
||||
/obj/item/projectile/curse_hand/prehit(atom/target)
|
||||
if(target == original)
|
||||
forcedodge = FALSE
|
||||
else if(!isturf(target))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/projectile/curse_hand/Destroy()
|
||||
if(arm)
|
||||
arm.End()
|
||||
arm = null
|
||||
if(forcedodge)
|
||||
playsound(src, 'sound/effects/curse3.ogg', 25, 1, -1)
|
||||
var/turf/T = get_step(src, dir)
|
||||
new/obj/effect/temp_visual/dir_setting/curse/hand(T, dir, handedness)
|
||||
for(var/obj/effect/temp_visual/dir_setting/curse/grasp_portal/G in starting)
|
||||
qdel(G)
|
||||
new /obj/effect/temp_visual/dir_setting/curse/grasp_portal/fading(starting, dir)
|
||||
var/datum/beam/D = starting.Beam(T, icon_state = "curse[handedness]", time = 32, maxdistance = INFINITY, beam_type=/obj/effect/ebeam/curse_arm, beam_sleep_time = 1)
|
||||
for(var/b in D.elements)
|
||||
var/obj/effect/ebeam/B = b
|
||||
animate(B, alpha = 0, time = 32)
|
||||
return ..()
|
||||
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 393 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 501 KiB After Width: | Height: | Size: 867 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 4.0 MiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 112 KiB |
BIN
sound/effects/curse1.ogg
Normal file
BIN
sound/effects/curse2.ogg
Normal file
BIN
sound/effects/curse3.ogg
Normal file
BIN
sound/effects/curse4.ogg
Normal file
BIN
sound/effects/curse5.ogg
Normal file
BIN
sound/effects/curse6.ogg
Normal file
BIN
sound/effects/curseattack.ogg
Normal file
@@ -1735,6 +1735,7 @@
|
||||
#include "code\modules\mob\living\simple_animal\hostile\megafauna\megafauna.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\megafauna\swarmer.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\basilisk.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\curse_blob.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\goldgrub.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\goliath.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\gutlunch.dm"
|
||||
|
||||