diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index bff46717b1..e661baacd7 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -197,6 +197,13 @@ SUBSYSTEM_DEF(shuttle) if(emergency.timeLeft(1) > emergencyCallTime * 0.4) emergency.request(null, set_coefficient = 0.4) +/datum/controller/subsystem/shuttle/proc/block_recall(lockout_timer) + emergencyNoRecall = TRUE + addtimer(CALLBACK(src, .proc/unblock_recall), lockout_timer) + +/datum/controller/subsystem/shuttle/proc/unblock_recall() + emergencyNoRecall = FALSE + /datum/controller/subsystem/shuttle/proc/getShuttle(id) for(var/obj/docking_port/mobile/M in mobile) if(M.id == id) @@ -309,9 +316,7 @@ SUBSYSTEM_DEF(shuttle) return 1 /datum/controller/subsystem/shuttle/proc/canRecall() - if(!emergency || emergency.mode != SHUTTLE_CALL) - return - if(SSticker.mode.name == "meteor") + if(!emergency || emergency.mode != SHUTTLE_CALL || emergencyNoRecall || SSticker.mode.name == "meteor") return var/security_num = seclevel2num(get_security_level()) switch(security_num) diff --git a/code/game/gamemodes/cult/blood_magic.dm b/code/game/gamemodes/cult/blood_magic.dm index 04b56c9f7d..dd66edcfb1 100644 --- a/code/game/gamemodes/cult/blood_magic.dm +++ b/code/game/gamemodes/cult/blood_magic.dm @@ -172,7 +172,6 @@ name = "Twisted Construction" desc = "A sinister spell used to convert:
Plasteel into runed metal
25 metal into a construct shell
Cyborgs directly into constructs
Cyborg shells into construct shells
Airlocks into runed airlocks (harm intent)" button_icon_state = "transmute" - charges = 50 magic_path = "/obj/item/melee/blood_magic/construction" /datum/action/innate/cult/blood_spell/equipment @@ -180,7 +179,6 @@ desc = "A crucial spell that enables you to summon either a ritual dagger or combat gear including armored robes, the nar'sien bola, and an eldritch longsword." button_icon_state = "equip" magic_path = "/obj/item/melee/blood_magic/armor" - charges = 1 /datum/action/innate/cult/blood_spell/equipment/Activate() var/choice = alert(owner,"Choose your equipment type",,"Combat Equipment","Ritual Dagger","Cancel") @@ -271,8 +269,8 @@ qdel(src) /datum/action/innate/cult/blood_spell/veiling - name = "Conceal Runes" - desc = "A multi-function spell that alternates between hiding and revealing nearby runes." + name = "Conceal Presence" + desc = "A multi-function spell that alternates between hiding and revealing nearby cult runes, structures, turf, and airlocks." invocation = "Kla'atu barada nikt'o!" button_icon_state = "gone" charges = 10 @@ -291,6 +289,8 @@ S.conceal() for(var/turf/open/floor/engine/cult/T in range(5,owner)) T.realappearance.alpha = 0 + for(var/obj/machinery/door/airlock/cult/AL in range(5, owner)) + AL.conceal() revealing = TRUE name = "Reveal Runes" button_icon_state = "back" @@ -302,10 +302,12 @@ SEND_SOUND(owner, sound('sound/magic/enter_blood.ogg',0,1,25)) for(var/obj/effect/rune/R in range(7,owner)) //More range in case you weren't standing in exactly the same spot R.reveal() - for(var/obj/structure/destructible/cult/S in range(7,owner)) + for(var/obj/structure/destructible/cult/S in range(6,owner)) S.reveal() - for(var/turf/open/floor/engine/cult/T in range(7,owner)) + for(var/turf/open/floor/engine/cult/T in range(6,owner)) T.realappearance.alpha = initial(T.realappearance.alpha) + for(var/obj/machinery/door/airlock/cult/AL in range(6, owner)) + AL.reveal() revealing = FALSE name = "Conceal Runes" button_icon_state = "gone" @@ -529,13 +531,13 @@ var/turf/T = get_turf(target) if(istype(target, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/candidate = target - if(candidate.use(25)) - uses-=25 + if(candidate.use(50)) + uses-- to_chat(user, "A dark cloud eminates from your hand and swirls around the metal, twisting it into a construct shell!") new /obj/structure/constructshell(T) SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) else - to_chat(user, "You need more metal to produce a construct shell!") + to_chat(user, "You need 50 metal to produce a construct shell!") else if(istype(target, /obj/item/stack/sheet/plasteel)) var/obj/item/stack/sheet/plasteel/candidate = target var/quantity = min(candidate.amount, uses) @@ -563,19 +565,19 @@ if("Artificer") makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder, candidate, user, 0, T) SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) - uses -= 50 + uses-- candidate.mmi = null qdel(candidate) else candidate.color = prev_color else - uses -= 50 + uses-- to_chat(user, "A dark cloud eminates from you hand and swirls around [candidate] - twisting it into a construct shell!") new /obj/structure/constructshell(T) SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) else if(istype(target,/obj/machinery/door/airlock)) target.narsie_act() - uses -= 50 + uses-- user.visible_message("Black ribbons suddenly eminate from [user]'s hand and cling to the airlock - twisting and corrupting it!") SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) else @@ -701,7 +703,7 @@ if(B.bloodiness == 100) //Bonus for "pristine" bloodpools, also to prevent cheese with footprint spam temp += 30 else - temp += max((B.bloodiness**2)/800,0.5) + temp += max((B.bloodiness**2)/800,1) new /obj/effect/temp_visual/cult/turf/floor(get_turf(B)) qdel(B) for(var/obj/effect/decal/cleanable/trail_holder/TH in view(T, 2)) diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index 2874e6bf1b..feb1cfc22a 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -409,6 +409,7 @@ damage_deflection = 10 var/openingoverlaytype = /obj/effect/temp_visual/cult/door var/friendly = FALSE + var/stealthy = FALSE /obj/machinery/door/airlock/cult/Initialize() . = ..() @@ -421,18 +422,36 @@ if(!density) return 1 if(friendly || iscultist(L) || istype(L, /mob/living/simple_animal/shade) || isconstruct(L)) - new openingoverlaytype(loc) + if(!stealthy) + new openingoverlaytype(loc) return 1 else - new /obj/effect/temp_visual/cult/sac(loc) - var/atom/throwtarget - throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src))) - SEND_SOUND(L, sound(pick('sound/hallucinations/turn_around1.ogg','sound/hallucinations/turn_around2.ogg'),0,1,50)) - flash_color(L, flash_color="#960000", flash_time=20) - L.Knockdown(40) - L.throw_at(throwtarget, 5, 1,src) + if(!stealthy) + new /obj/effect/temp_visual/cult/sac(loc) + var/atom/throwtarget + throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src))) + SEND_SOUND(L, sound(pick('sound/hallucinations/turn_around1.ogg','sound/hallucinations/turn_around2.ogg'),0,1,50)) + flash_color(L, flash_color="#960000", flash_time=20) + L.Knockdown(40) + L.throw_at(throwtarget, 5, 1,src) return 0 +/obj/machinery/door/airlock/cult/proc/conceal() + icon = 'icons/obj/doors/airlocks/station/maintenance.dmi' + overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + name = "airlock" + desc = "It opens and closes." + stealthy = TRUE + update_icon() + +/obj/machinery/door/airlock/cult/proc/reveal() + icon = initial(icon) + overlays_file = initial(overlays_file) + name = initial(name) + desc = initial(desc) + stealthy = initial(stealthy) + update_icon() + /obj/machinery/door/airlock/cult/narsie_act() return diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 84a6cc1b9e..66124f8b6d 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -168,7 +168,7 @@ qdel(src) return - if(S.sheettype) + if(S.sheettype && S.sheettype != "runed") var/M = S.sheettype if(state == GIRDER_DISPLACED) if(S.get_amount() < 2) diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm index bedb7dc9bc..68c93fa04c 100644 --- a/code/modules/antagonists/cult/cult_comms.dm +++ b/code/modules/antagonists/cult/cult_comms.dm @@ -80,8 +80,10 @@ return ..() /datum/action/innate/cult/mastervote/Activate() - var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - pollCultists(owner,C.cult_team) + var/choice = alert(owner, "The mantle of leadership is a heavy. Success in this role requires an expert level of communication and experience. Are you sure?",, "Yes", "No") + if(choice == "Yes" && IsAvailable()) + var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + pollCultists(owner,C.cult_team) /proc/pollCultists(var/mob/living/Nominee,datum/team/cult/team) //Cult Master Poll if(world.time < CULT_POLL_WAIT) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 6bf65fa234..e98f89718b 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -503,7 +503,19 @@ if(SSshuttle.emergency.mode == SHUTTLE_CALL) var/cursetime = 1800 var/timer = SSshuttle.emergency.timeLeft(1) + cursetime + var/security_num = seclevel2num(get_security_level()) + var/set_coefficient = 1 + switch(security_num) + if(SEC_LEVEL_GREEN) + set_coefficient = 2 + if(SEC_LEVEL_BLUE) + set_coefficient = 1 + else + set_coefficient = 0.5 + var/surplus = timer - (SSshuttle.emergencyCallTime * set_coefficient) SSshuttle.emergency.setTimer(timer) + if(surplus > 0) + SSshuttle.block_recall(surplus) to_chat(user, "You shatter the orb! A dark essence spirals into the air, then disappears.") playsound(user.loc, 'sound/effects/glassbr1.ogg', 50, 1) qdel(src) @@ -511,18 +523,20 @@ var/global/list/curses if(!curses) curses = list("A fuel technician just slit his own throat and begged for death. The shuttle will be delayed by three minutes.", - "The shuttle's navigation programming was replaced by a file containing two words, IT COMES. The shuttle will be delayed by three minutes.", - "The shuttle's custodian tore out his guts and began painting strange shapes on the floor. The shuttle will be delayed by three minutes.", - "A shuttle engineer began screaming 'DEATH IS NOT THE END' and ripped out wires until an arc flash seared off her flesh. The shuttle will be delayed by three minutes.", - "A shuttle inspector started laughing madly over the radio and then threw herself into an engine turbine. The shuttle will be delayed by three minutes.", - "The shuttle dispatcher was found dead with bloody symbols carved into their flesh. The shuttle will be delayed by three minutes.") + "The shuttle's navigation programming was replaced by a file containing just two words: IT COMES.", + "The shuttle's custodian was found washing the windows with their own blood.", + "A shuttle engineer began screaming 'DEATH IS NOT THE END' and ripped out wires until an arc flash seared off her flesh.", + "A shuttle inspector started laughing madly over the radio and then threw herself into an engine turbine.", + "The shuttle dispatcher was found dead with bloody symbols carved into their flesh.", + "The shuttle's transponder is emitting the encoded message 'FEAR THE OLD BLOOD' in lieu of its assigned identification signal.") var/message = pick_n_take(curses) + message += "
The shuttle will be delayed by three minutes." priority_announce("[message]", "System Failure", 'sound/misc/notice1.ogg') curselimit++ /obj/item/device/cult_shift name = "veil shifter" - desc = "This relic teleports you forward a medium distance." + desc = "This relic instantly teleports you, and anything you're pulling, forward by a moderate distance." icon = 'icons/obj/cult.dmi' icon_state ="shifter" var/uses = 4 diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm index ea8e18d7aa..84cc26d81a 100644 --- a/code/modules/antagonists/cult/cult_structures.dm +++ b/code/modules/antagonists/cult/cult_structures.dm @@ -57,6 +57,7 @@ /obj/structure/destructible/cult/attackby(obj/I, mob/user, params) if(istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user)) anchored = !anchored + density = !density to_chat(user, "You [anchored ? "":"un"]secure \the [src] [anchored ? "to":"from"] the floor.") if(!anchored) icon_state = "[initial(icon_state)]_off" diff --git a/code/modules/antagonists/cult/ritual.dm b/code/modules/antagonists/cult/ritual.dm index 20ac8c88cf..8167a1c0d9 100644 --- a/code/modules/antagonists/cult/ritual.dm +++ b/code/modules/antagonists/cult/ritual.dm @@ -68,6 +68,9 @@ This file contains the cult dagger and rune list code A = get_area(src) if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated() || !check_rune_turf(Turf, user)) return + if(ispath(rune_to_scribe, /obj/effect/rune/summon) && (!is_station_level(Turf.z) || A.map_name == "Space")) + to_chat(user, "The veil is not weak enough here to summon a cultist, you must be on station!") + return if(ispath(rune_to_scribe, /obj/effect/rune/apocalypse)) if((world.time - SSticker.round_start_time) <= 6000) var/wait = 6000 - (world.time - SSticker.round_start_time) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index fc7d6ecc64..8e6ae30d28 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -426,22 +426,19 @@ structure_check() searches for nearby cultist structures required for the invoca else var/area/A = get_area(T) if(A.map_name == "Space") - actual_selected_rune.handle_portal("space") + actual_selected_rune.handle_portal("space", T) target.visible_message("There is a boom of outrushing air as something appears above the rune!", null, "You hear a boom.") else fail_invoke() -/obj/effect/rune/teleport/proc/handle_portal(portal_type) +/obj/effect/rune/teleport/proc/handle_portal(portal_type, turf/origin) var/turf/T = get_turf(src) - if(inner_portal) - qdel(inner_portal) //We need fresh effects/animations - if(outer_portal) - qdel(outer_portal) + close_portal() // To avoid stacking descriptions/animations playsound(T, pick('sound/effects/sparks1.ogg', 'sound/effects/sparks2.ogg', 'sound/effects/sparks3.ogg', 'sound/effects/sparks4.ogg'), 100, TRUE, 14) inner_portal = new /obj/effect/temp_visual/cult/portal(T) if(portal_type == "space") - light_color = RUNE_COLOR_TELEPORT - desc += "
A tear in reality reveals a black void interspersed with dots of light... something recently teleported here from space!" + light_color = color + desc += "
A tear in reality reveals a black void interspersed with dots of light... something recently teleported here from space.
The void feels like it's trying to pull you to the [dir2text(get_dir(T, origin))]!
" else inner_portal.icon_state = "lava" light_color = LIGHT_COLOR_FIRE @@ -452,6 +449,8 @@ structure_check() searches for nearby cultist structures required for the invoca addtimer(CALLBACK(src, .proc/close_portal), 600, TIMER_UNIQUE) /obj/effect/rune/teleport/proc/close_portal() + qdel(inner_portal) + qdel(outer_portal) desc = initial(desc) light_range = 0 update_light() @@ -842,9 +841,13 @@ structure_check() searches for nearby cultist structures required for the invoca var/turf/T = get_turf(src) var/choice = alert(user,"You tear open a connection to the spirit realm...",,"Summon a Cult Ghost","Ascend as a Dark Spirit","Cancel") if(choice == "Summon a Cult Ghost") + var/area/A = get_area(T) + if(A.map_name == "Space" || is_mining_level(T.z)) + to_chat(user, "The veil is not weak enough here to manifest spirits, you must be on station!") + return notify_ghosts("Manifest rune invoked in [get_area(src)].", 'sound/effects/ghost2.ogg', source = src) var/list/ghosts_on_rune = list() - for(var/mob/dead/observer/O in get_turf(src)) + for(var/mob/dead/observer/O in T) if(O.client && !jobban_isbanned(O, ROLE_CULTIST)) ghosts_on_rune += O if(!ghosts_on_rune.len) @@ -853,7 +856,7 @@ structure_check() searches for nearby cultist structures required for the invoca log_game("Manifest rune failed - no nearby ghosts") return list() var/mob/dead/observer/ghost_to_spawn = pick(ghosts_on_rune) - var/mob/living/carbon/human/cult_ghost/new_human = new(get_turf(src)) + var/mob/living/carbon/human/cult_ghost/new_human = new(T) new_human.real_name = ghost_to_spawn.real_name new_human.alpha = 150 //Makes them translucent new_human.equipOutfit(/datum/outfit/ghost_cultist) //give them armor diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 6c6f39ffc1..1c12b48919 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -125,19 +125,19 @@ response_harm = "harmlessly punches" harm_intent_damage = 0 obj_damage = 90 - melee_damage_lower = 30 - melee_damage_upper = 30 + melee_damage_lower = 25 + melee_damage_upper = 25 attacktext = "smashes their armored gauntlet into" speed = 2.5 environment_smash = ENVIRONMENT_SMASH_WALLS attack_sound = 'sound/weapons/punch3.ogg' status_flags = 0 mob_size = MOB_SIZE_LARGE - force_threshold = 11 + force_threshold = 10 construct_spells = list(/obj/effect/proc_holder/spell/targeted/forcewall/cult, /obj/effect/proc_holder/spell/dumbfire/juggernaut) runetype = /datum/action/innate/cult/create_rune/wall - playstyle_string = "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, \ + playstyle_string = "You are a Juggernaut. Though slow, your shell can withstand heavy punishment, \ create shield walls, rip apart enemies and walls alike, and even deflect energy weapons." /mob/living/simple_animal/hostile/construct/armored/hostile //actually hostile, will move around, hit things @@ -146,7 +146,7 @@ /mob/living/simple_animal/hostile/construct/armored/bullet_act(obj/item/projectile/P) if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) - var/reflectchance = 80 - round(P.damage/3) + var/reflectchance = 60 - round(P.damage/3) if(prob(reflectchance)) apply_damage(P.damage * 0.5, P.damage_type) visible_message("The [P.name] is reflected by [src]'s armored shell!", \ @@ -184,8 +184,8 @@ icon_living = "floating" maxHealth = 65 health = 65 - melee_damage_lower = 25 - melee_damage_upper = 25 + melee_damage_lower = 20 + melee_damage_upper = 20 retreat_distance = 2 //AI wraiths will move in and out of combat attacktext = "slashes" attack_sound = 'sound/weapons/bladeslice.ogg' diff --git a/code/modules/spells/spell_types/construct_spells.dm b/code/modules/spells/spell_types/construct_spells.dm index 07e75002bc..64605e0587 100644 --- a/code/modules/spells/spell_types/construct_spells.dm +++ b/code/modules/spells/spell_types/construct_spells.dm @@ -280,9 +280,9 @@ /obj/effect/proc_holder/spell/dumbfire/juggernaut name = "Gauntlet Echo" - desc = "Channels energy into your gauntlet - firing its essence forward in a slow-moving but devastating blow." - proj_icon_state = "cursehand0" - proj_name = "Shadowfist" + desc = "Channels energy into your gauntlet - firing its essence forward in a slow moving, yet devastating, attack." + proj_icon_state = "cultfist" + proj_name = "gauntlet echo" proj_type = "/obj/effect/proc_holder/spell/targeted/inflict_handler/juggernaut" //IMPORTANT use only subtypes of this proj_lifespan = 15 proj_step_delay = 7 diff --git a/icons/mob/actions/actions_cult.dmi b/icons/mob/actions/actions_cult.dmi index 07432d2a27..c2e0467781 100644 Binary files a/icons/mob/actions/actions_cult.dmi and b/icons/mob/actions/actions_cult.dmi differ diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index b2299a75fe..34e6a8134b 100644 Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ