Adds Shadow demons (#19732)

* reshuffle

* shared base type

* moves this to the base type

* the monster

* event

* FUCK

* better sprites

* refactors bloodcrawl, more nice sprites

* review stuff

* Apply suggestions from code review

Co-authored-by: Sirryan2002 <80364400+Sirryan2002@users.noreply.github.com>

* heart of darkness

* pre TM tweaks

* ARGH

* hopefully fixes double hits

* tweaks

* derp

* tweaks

* TEMP RUNTIME REMOVE LATER

* fixes

* runtime fixes

* cig runtime fix

* review + another runtime fix

* re adds sprite

* removes runtime

* oop I forgor

* DRUNK CODING

* SPRITES

Co-authored-by: Sirryan2002 <80364400+Sirryan2002@users.noreply.github.com>
This commit is contained in:
Charlie
2022-12-29 17:26:37 +00:00
committed by GitHub
parent 7be765d5ef
commit 8ef4aa727e
48 changed files with 563 additions and 312 deletions
@@ -165,7 +165,7 @@
var/veil_msg = "<span class='warning'>You sense a dark presence lurking \
just beyond the veil...</span>"
var/objective_verb = "Kill"
var/mob/living/demon_type = /mob/living/simple_animal/slaughter
var/mob/living/demon_type = /mob/living/simple_animal/demon/slaughter
/obj/item/antag_spawner/slaughter_demon/attack_self(mob/user)
if(level_blocks_magic(user.z)) //this is to make sure the wizard does NOT summon a demon from the Den..
@@ -179,7 +179,7 @@
to_chat(user, "<span class='notice'>You break the seal on the bottle, calling upon the dire spirits of the underworld...</span>")
var/type = "slaughter"
if(demon_type == /mob/living/simple_animal/slaughter/laughter)
if(demon_type == /mob/living/simple_animal/demon/slaughter/laughter)
type = "laughter"
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a [type] demon summoned by [user.real_name]?", ROLE_DEMON, TRUE, 10 SECONDS, source = demon_type)
@@ -196,9 +196,8 @@
/obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, type = "", mob/user)
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
var/mob/living/simple_animal/slaughter/S = new demon_type(holder)
var/mob/living/simple_animal/demon/slaughter/S = new demon_type(holder)
S.vialspawned = TRUE
S.holder = holder
S.key = C.key
S.mind.assigned_role = S.name
S.mind.special_role = S.name
@@ -226,7 +225,7 @@
veil_msg = "<span class='warning'>You sense an adorable presence \
lurking just beyond the veil...</span>"
objective_verb = "Hug and tickle"
demon_type = /mob/living/simple_animal/slaughter/laughter
demon_type = /mob/living/simple_animal/demon/slaughter/laughter
///////////MORPH
+2 -2
View File
@@ -44,10 +44,10 @@
/obj/item/clothing/head/hardhat/proc/turn_off(mob/user)
set_light(0)
/obj/item/clothing/head/hardhat/extinguish_light(mob/living/user)
/obj/item/clothing/head/hardhat/extinguish_light(force = FALSE)
if(on)
on = FALSE
turn_off(user)
turn_off()
update_icon(UPDATE_ICON_STATE)
visible_message("<span class='danger'>[src]'s light fades and turns off.</span>")
+1 -1
View File
@@ -68,7 +68,7 @@
var/datum/action/A = X
A.UpdateButtonIcon()
/obj/item/clothing/head/helmet/space/hardsuit/extinguish_light()
/obj/item/clothing/head/helmet/space/hardsuit/extinguish_light(force = FALSE)
if(on)
toggle_light()
visible_message("<span class='danger'>[src]'s light fades and turns off.</span>")
@@ -82,7 +82,7 @@
set_light(brightness_on)
/obj/item/clothing/head/helmet/space/plasmaman/extinguish_light()
/obj/item/clothing/head/helmet/space/plasmaman/extinguish_light(force = FALSE)
if(on)
toggle_light()
+1
View File
@@ -197,6 +197,7 @@ GLOBAL_LIST_EMPTY(event_last_fired)
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Traders", /datum/event/traders, 85, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Terror Spiders", /datum/event/spider_terror, 20, list(ASSIGNMENT_SECURITY = 4), TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Slaughter Demon", /datum/event/spawn_slaughter, 10, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Shadow Demon", /datum/event/spawn_slaughter/shadow, 50, is_one_shot = TRUE)
//new /datum/event_meta(EVENT_LEVEL_MAJOR, "Floor Cluwne", /datum/event/spawn_floor_cluwne, 15, is_one_shot = TRUE)
)
+32 -16
View File
@@ -1,9 +1,9 @@
/datum/event/spawn_slaughter
var/key_of_slaughter
var/demon = /mob/living/simple_animal/slaughter/lesser
var/mob/living/simple_animal/demon/demon = /mob/living/simple_animal/demon/slaughter/lesser
/datum/event/spawn_slaughter/proc/get_slaughter()
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a slaughter demon?", ROLE_DEMON, TRUE, source = /mob/living/simple_animal/slaughter)
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a [initial(demon.name)]?", ROLE_DEMON, TRUE, source = demon)
if(!length(candidates))
kill()
return
@@ -17,25 +17,41 @@
var/datum/mind/player_mind = new /datum/mind(key_of_slaughter)
player_mind.active = TRUE
var/list/spawn_locs = list()
var/turf/spawn_loc = get_spawn_loc(player_mind.current)
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(spawn_loc)
var/mob/living/simple_animal/demon/S = new demon(holder)
player_mind.transfer_to(S)
player_mind.assigned_role = "Demon"
player_mind.special_role = SPECIAL_ROLE_DEMON
message_admins("[key_name_admin(S)] has been made into a [S.name] by an event.")
log_game("[key_name_admin(S)] was spawned as a [S.name] by an event.")
/datum/event/spawn_slaughter/proc/get_spawn_loc(mob/player)
RETURN_TYPE(/turf)
var/list/spawn_centers = list()
for(var/obj/effect/landmark/spawner/rev/L in GLOB.landmarks_list)
spawn_locs += get_turf(L)
if(!spawn_locs) //If we can't find a good place, just spawn the revenant at the player's location
spawn_locs += get_turf(player_mind.current)
if(!spawn_locs) //If we can't find THAT, then give up
spawn_centers += get_turf(L)
if(!spawn_centers) //If we can't find a good place, just spawn the revenant at the player's location
spawn_centers += get_turf(player)
if(!spawn_centers) //If we can't find THAT, then give up
kill()
return
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(pick(spawn_locs))
var/mob/living/simple_animal/slaughter/S = new demon(holder)
S.holder = holder
player_mind.transfer_to(S)
player_mind.assigned_role = "Slaughter Demon"
player_mind.special_role = SPECIAL_ROLE_SLAUGHTER_DEMON
message_admins("[key_name_admin(S)] has been made into a Slaughter Demon by an event.")
log_game("[key_name_admin(S)] was spawned as a Slaughter Demon by an event.")
return pick(spawn_centers)
/datum/event/spawn_slaughter/start()
INVOKE_ASYNC(src, PROC_REF(get_slaughter))
/datum/event/spawn_slaughter/greater
demon = /mob/living/simple_animal/slaughter
demon = /mob/living/simple_animal/demon/slaughter
/datum/event/spawn_slaughter/shadow
demon = /mob/living/simple_animal/demon/shadow
/datum/event/spawn_slaughter/shadow/get_spawn_loc()
var/turf/spawn_center = ..()
for(var/turf/T in range(50, spawn_center))
if(T.get_lumcount()) // if the turf is not pitch black
continue
return T // return the first turf that is dark nearby.
kill()
@@ -115,7 +115,7 @@
if(old_stat != stat)
update_icon(UPDATE_OVERLAYS)
/obj/machinery/smartfridge/extinguish_light()
/obj/machinery/smartfridge/extinguish_light(force = FALSE)
set_light(0)
underlays.Cut()
+6
View File
@@ -206,3 +206,9 @@
add_attack_logs(user, target, "[what_done] ([reagent_str] | [genes_str])")
/obj/item/reagent_containers/food/snacks/grown/extinguish_light(force = FALSE)
if(!force)
return
if(seed.get_gene(/datum/plant_gene/trait/glow/shadow))
return
set_light(0)
@@ -61,3 +61,10 @@
if(seed)
for(var/datum/plant_gene/trait/T in seed.genes)
T.on_throw_impact(src, hit_atom)
/obj/item/grown/extinguish_light(force = FALSE)
if(!force)
return
if(seed.get_gene(/datum/plant_gene/trait/glow/shadow))
return
set_light(0)
+1 -1
View File
@@ -54,7 +54,7 @@
else
light = new/datum/light_source(src, .)
/atom/proc/extinguish_light()
/atom/proc/extinguish_light(force = FALSE)
return
// If we have opacity, make sure to tell (potentially) affected light sources.
+2 -2
View File
@@ -134,9 +134,9 @@
var/list/antag_serialized = serialized.Copy()
antag_serialized["antag"] = "Xenomorph"
antagonists += list(antag_serialized)
else if(isslaughterdemon(M))
else if(isdemon(M))
var/list/antag_serialized = serialized.Copy()
antag_serialized["antag"] = "Slaughter Demon"
antag_serialized["antag"] = "Demon"
antagonists += list(antag_serialized)
else
if(length(orbiters) >= 0.2 * length_of_ghosts) // If a bunch of people are orbiting an object, like the nuke disk.
@@ -1966,7 +1966,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
to_chat(src, "<span class='whisper'>[pick(GLOB.boo_phrases)]</span>")
return TRUE
/mob/living/carbon/human/extinguish_light()
/mob/living/carbon/human/extinguish_light(force = FALSE)
// Parent function handles stuff the human may be holding
..()
+2 -2
View File
@@ -1092,10 +1092,10 @@
/mob/living/proc/fakefire()
return
/mob/living/extinguish_light()
/mob/living/extinguish_light(force = FALSE)
for(var/atom/A in src)
if(A.light_range > 0)
A.extinguish_light()
A.extinguish_light(force)
/mob/living/vv_edit_var(var_name, var_value)
switch(var_name)
@@ -42,8 +42,6 @@
var/mob_biotypes = MOB_ORGANIC
var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature..
var/holder = null //The holder for blood crawling
var/ventcrawler = 0 //0 No vent crawling, 1 vent crawling in the nude, 2 vent crawling always
var/list/icon/pipes_shown = list()
var/last_played_vent
+1 -1
View File
@@ -515,7 +515,7 @@
CRASH("pAI without card")
loc = card
/mob/living/silicon/pai/extinguish_light()
/mob/living/silicon/pai/extinguish_light(force = FALSE)
flashlight_on = FALSE
set_light(0)
card.set_light(0)
@@ -1473,7 +1473,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
overlays += "[base_icon]-shield"
/mob/living/silicon/robot/extinguish_light()
/mob/living/silicon/robot/extinguish_light(force = FALSE)
update_headlamp(1, 150)
/mob/living/silicon/robot/rejuvenate()
+1 -1
View File
@@ -390,7 +390,7 @@ GLOBAL_LIST_EMPTY(PDAs)
if(current_app)
current_app.program_process()
/obj/item/pda/extinguish_light()
/obj/item/pda/extinguish_light(force = FALSE)
var/datum/data/pda/utility/flashlight/FL = find_program(/datum/data/pda/utility/flashlight)
if(FL && FL.fon)
FL.start()
+1 -1
View File
@@ -941,7 +941,7 @@
limb.droplimb(0, DROPLIMB_BURN)
return FIRELOSS
/obj/machinery/light/extinguish_light()
/obj/machinery/light/extinguish_light(force = FALSE)
on = FALSE
extinguished = TRUE
emergency_mode = FALSE
+5 -8
View File
@@ -368,14 +368,11 @@
if(!gun_light)
return
var/mob/living/carbon/human/user = usr
if(!isturf(user.loc))
to_chat(user, "<span class='warning'>You cannot turn the light on while in this [user.loc]!</span>")
gun_light.on = !gun_light.on
to_chat(user, "<span class='notice'>You toggle the gun light [gun_light.on ? "on":"off"].</span>")
playsound(user, 'sound/weapons/empty.ogg', 100, 1)
var/mob/living/carbon/human/user = usr
if(user)
to_chat(user, "<span class='notice'>You toggle the gun light [gun_light.on ? "on":"off"].</span>")
playsound(src, 'sound/weapons/empty.ogg', 100, 1)
update_gun_light(user)
/obj/item/gun/proc/update_gun_light(mob/user = null)
@@ -401,7 +398,7 @@
knife_overlay = null
return TRUE
/obj/item/gun/extinguish_light()
/obj/item/gun/extinguish_light(force = FALSE)
if(gun_light?.on)
toggle_gunlight()
visible_message("<span class='danger'>[src]'s light fades and turns off.</span>")