A lot more Cult fixes (#15161)

* Some fixes

1: ERT members can no longer be given as an assassinate/sacrifice antag objective.
2. Cultists attempting to teleport to a deleted rune will no longer be teleported into nullspace.
3. Re-ordered the cult Blood Rites spell code because it was bugging me. (sorry qwerty)

* Cult stuff

1: Cultists can no longer be chosen as a sacrifice target
2: Rune drawing is limited to one at a time (No spamming on one tile)
3: Removed some unneccesary `/improper`s from area names, for the cult Summoning locations
4: Changed a couple of colours to use defines

* QDELETED()

* Eye colour fix

* Reorganisation, Objectives, and Gender

The majority of the changes here are just reordering the procs, but there's a few fixes too:

1. Roundstart cultists now get given the 'servecult' objective.
2. Deconverting someone now removes their 'servecult' objective, so they won't be notified about target changes.
3. Stopped summoned ghosts from experiencing a spontaneous gender change.

* Screwdriver fix

* Prayer bead stripping

* Some more construct fixes

1: Fixed *all* holy constructs getting the 'Summon soulstone' ability
2: Fixed Wraiths getting their blue light reset to red after jaunting
3: Added a 'holy' variable to constructs, and made the holyification its own proc.

* qdeleted

* Construct Converting

Apparently you can convert holy constructs. Who knew!

* Another two weeks

Moved all the construct icon states to their own file, and fixed Nar'Sie constructs not getting a glowing effect.

* Grab fix

Fixed upgrading a grab having the ability to potentially transport the victim across dimensions.

* Not actually a cult fix but eh

Fixes: Runtime in outfit.dm, 114: bad number
And updates the cult corpse from legion spawns

* Teleport spell effect

Fixed the teleport effect for the spell being attached to the wrong mob.

* Small cleanup

* Eye colour cloning fix

* Veil Shifter

Fixed:
Runtime in cult_items.dm,355: pick() from empty list
Veil shifters not retaining any grabs after teleporting.

* Adjacent
This commit is contained in:
SabreML
2021-05-16 11:33:07 +01:00
committed by GitHub
parent 2c63bd9581
commit 3d6e072464
22 changed files with 251 additions and 204 deletions
+2
View File
@@ -111,6 +111,8 @@
for(var/path in backpack_contents)
var/number = backpack_contents[path]
if(!number)
number = 1
for(var/i in 1 to number)
H.equip_or_collect(new path(H), slot_in_backpack)
+8 -3
View File
@@ -49,7 +49,7 @@
/obj/effect/proc_holder/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"
desc = "This spell reaches into Redspace, summoning one of the legendary fragments across time and space"
action_icon_state = "summonsoulstone"
action_background_icon_state = "bg_cult"
school = "conjuration"
@@ -68,7 +68,7 @@
/obj/effect/proc_holder/spell/aoe_turf/conjure/pylon
name = "Cult Pylon"
desc = "This spell conjures a fragile crystal from Nar'Sie's realm. Makes for a convenient light source."
desc = "This spell conjures a fragile crystal from Redspace. Makes for a convenient light source."
action_icon_state = "pylon"
action_background_icon_state = "bg_cult"
school = "conjuration"
@@ -118,7 +118,12 @@
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/do_jaunt(mob/living/target)
target.set_light(0)
..()
target.set_light(2, 3, l_color = SSticker.cultdat ? SSticker.cultdat.construct_glow : LIGHT_COLOR_BLOOD_MAGIC)
if(isconstruct(target))
var/mob/living/simple_animal/hostile/construct/C = target
if(C.holy)
C.set_light(3, 5, LIGHT_COLOR_DARK_BLUE)
else
C.set_light(2, 3, l_color = SSticker.cultdat ? SSticker.cultdat.construct_glow : LIGHT_COLOR_BLOOD_MAGIC)
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/jaunt_steam(mobloc)
return
+30 -30
View File
@@ -1108,7 +1108,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/engine/equipmentstorage
name = "\improper Engineering Equipment Storage"
name = "Engineering Equipment Storage"
icon_state = "storage"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
@@ -1260,7 +1260,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/medical/biostorage
name = "\improper Medical Storage"
name = "Medical Storage"
icon_state = "medbaysecstorage"
/area/medical/reception
@@ -1285,19 +1285,19 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "patientsward"
/area/medical/patient_a
name = "\improper Isolation A"
name = "Isolation A"
icon_state = "medbayisoa"
/area/medical/patient_b
name = "\improper Isolation B"
name = "Isolation B"
icon_state = "medbayisob"
/area/medical/patient_c
name = "\improper Isolation C"
name = "Isolation C"
icon_state = "medbayisoc"
/area/medical/iso_access
name = "\improper Isolation Access"
name = "Isolation Access"
icon_state = "medbayisoaccess"
/area/medical/cmo
@@ -1305,15 +1305,15 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "CMO"
/area/medical/cmostore
name = "\improper Medical Secondary Storage"
name = "Medical Secondary Storage"
icon_state = "medbaysecstorage"
/area/medical/robotics
name = "\improper Robotics"
name = "Robotics"
icon_state = "medresearch"
/area/medical/research
name = "\improper Medical Research"
name = "Medical Research"
icon_state = "medresearch"
/area/medical/research_shuttle_dock
@@ -1321,7 +1321,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "medresearch"
/area/medical/virology
name = "\improper Virology"
name = "Virology"
icon_state = "virology"
/area/medical/virology/lab
@@ -1336,7 +1336,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/medical/chemistry
name = "\improper Chemistry"
name = "Chemistry"
icon_state = "chem"
/area/medical/surgery
@@ -1344,19 +1344,19 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "surgery"
/area/medical/surgery1
name = "\improper Surgery 1"
name = "Surgery 1"
icon_state = "surgery1"
/area/medical/surgery2
name = "\improper Surgery 2"
name = "Surgery 2"
icon_state = "surgery2"
/area/medical/surgeryobs
name = "\improper Surgery Observation"
name = "Surgery Observation"
icon_state = "surgery"
/area/medical/cryo
name = "\improper Cryogenics"
name = "Cryogenics"
icon_state = "cryo"
/area/medical/exam_room
@@ -1376,7 +1376,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "exam_room"
/area/medical/paramedic
name = "\improper Paramedic"
name = "Paramedic"
icon_state = "medbay"
//Security
@@ -1441,22 +1441,22 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "brig"
/area/security/execution
name = "\improper Execution"
name = "Execution"
icon_state = "execution"
can_get_auto_cryod = FALSE
/area/security/processing
name = "\improper Prisoner Processing"
name = "Prisoner Processing"
icon_state = "prisonerprocessing"
can_get_auto_cryod = FALSE
/area/security/interrogation
name = "\improper Interrogation"
name = "Interrogation"
icon_state = "interrogation"
can_get_auto_cryod = FALSE
/area/security/seceqstorage
name = "\improper Security Equipment Storage"
name = "Security Equipment Storage"
icon_state = "securityequipmentstorage"
/area/security/interrogationhallway
@@ -1469,7 +1469,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
sound_environment = SOUND_AREA_LARGE_ENCLOSED
/area/security/interrogationobs
name = "\improper Interrogation Observation"
name = "Interrogation Observation"
icon_state = "security"
can_get_auto_cryod = FALSE
@@ -1530,11 +1530,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "nuke_storage"
/area/security/customs
name = "\improper Customs"
name = "Customs"
icon_state = "checkpoint1"
/area/security/customs2
name = "\improper Customs"
name = "Customs"
icon_state = "security"
/area/security/checkpoint
@@ -1601,7 +1601,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "mining"
/area/quartermaster/miningstorage
name = "\improper Mining Storage"
name = "Mining Storage"
icon_state = "green"
/area/quartermaster/mechbay
@@ -1614,7 +1614,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/hydroponics
name = "\improper Hydroponics"
name = "Hydroponics"
icon_state = "hydro"
sound_environment = SOUND_AREA_STANDARD_STATION
@@ -1629,7 +1629,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
sound_environment = SOUND_AREA_STANDARD_STATION
/area/toxins/lab
name = "\improper Research and Development"
name = "Research and Development"
icon_state = "toxlab"
/area/toxins/hallway
@@ -1650,7 +1650,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
xenobiology_compatible = TRUE
/area/toxins/xenobiology/xenoflora_storage
name = "\improper Xenoflora Storage"
name = "Xenoflora Storage"
icon_state = "toxlab"
/area/toxins/xenobiology/xenoflora
@@ -1658,7 +1658,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "toxlab"
/area/toxins/storage
name = "\improper Toxins Storage"
name = "Toxins Storage"
icon_state = "toxstorage"
/area/toxins/test_area
@@ -1671,7 +1671,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "toxmix"
/area/toxins/launch
name = "Toxins Launch Room"
name = "\improper Toxins Launch Room"
icon_state = "toxlaunch"
/area/toxins/misc_lab
@@ -1739,7 +1739,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "auxstorage"
/area/storage/office
name = "\improper Office Supplies"
name = "Office Supplies"
icon_state = "office_supplies"
// ENGIE OUTPOST
+48 -43
View File
@@ -249,7 +249,7 @@
/datum/action/innate/cult/blood_spell/horror/Destroy()
var/obj/effect/proc_holder/horror/destroy = PH
. = ..()
if(destroy && !QDELETED(destroy))
if(!QDELETED(destroy))
QDEL_NULL(destroy)
/datum/action/innate/cult/blood_spell/horror/Activate()
@@ -264,7 +264,7 @@
/obj/effect/proc_holder/horror/Destroy()
var/datum/action/innate/cult/blood_spell/AA = attached_action
. = ..()
if(AA && !QDELETED(AA))
if(!QDELETED(AA))
QDEL_NULL(AA)
/obj/effect/proc_holder/horror/proc/toggle(mob/user)
@@ -464,9 +464,15 @@
var/list/potential_runes = list()
var/list/teleportnames = list()
var/list/duplicaterunecount = list()
var/atom/movable/teleportee
if(!iscultist(target) || !proximity)
to_chat(user, "<span class='warning'>You can only teleport adjacent cultists with this spell!</span>")
return
if(user != target) // So that the teleport effect shows on the correct mob
teleportee = target
else
teleportee = user
for(var/R in GLOB.teleport_runes)
var/obj/effect/rune/teleport/T = R
var/resultkey = T.listkey
@@ -487,16 +493,15 @@
log_game("Teleport spell failed - user in away mission")
return
var/mob/living/L = target
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
if(!src || QDELETED(src) || !user || user.l_hand != src && user.r_hand != src || user.incapacitated() || !actual_selected_rune)
if(QDELETED(src) || !user || user.l_hand != src && user.r_hand != src || user.incapacitated() || !actual_selected_rune)
return
uses--
var/turf/origin = get_turf(user)
var/turf/origin = get_turf(teleportee)
var/turf/destination = get_turf(actual_selected_rune)
INVOKE_ASYNC(actual_selected_rune, /obj/effect/rune/.proc/teleport_effect, user, origin, destination)
INVOKE_ASYNC(actual_selected_rune, /obj/effect/rune/.proc/teleport_effect, teleportee, origin, destination)
if(is_mining_level(user.z) && !is_mining_level(destination.z)) //No effect if you stay on lavaland
actual_selected_rune.handle_portal("lava")
@@ -510,7 +515,7 @@
target.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [target] disappears in a flash of red light!</span>", \
"<span class='cultitalic'>You suddenly find yourself somewhere else!</span>")
destination.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
L.forceMove(destination)
teleportee.forceMove(destination)
return ..()
//Shackles
@@ -658,7 +663,7 @@
/obj/item/melee/blood_magic/empower/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
if(proximity_flag)
//Shielded suit
// Shielded suit
if(istype(target, /obj/item/clothing/suit/hooded/cultrobes/cult_shield))
var/obj/item/clothing/suit/hooded/cultrobes/cult_shield/C = target
if(C.current_charges < 3)
@@ -672,7 +677,7 @@
to_chat(user, "<span class='warning'>[target] is already at full charge!</span>")
return
//Plasteel to runed metal
// Veil Shifter
else if(istype(target, /obj/item/cult_shift))
var/obj/item/cult_shift/S = target
if(S.uses < 4)
@@ -846,39 +851,6 @@
var/list/options = list("Blood Orb (50)", "Blood Recharge (75)", "Blood Spear (150)", "Blood Bolt Barrage (300)")
var/choice = input(user, "Choose a greater blood rite...", "Greater Blood Rites") as null|anything in options
switch(choice)
if("Blood Spear (150)")
if(uses < BLOOD_SPEAR_COST)
to_chat(user, "<span class='warning'>You need [BLOOD_SPEAR_COST] charges to perform this rite.</span>")
else
uses -= BLOOD_SPEAR_COST
var/turf/T = get_turf(user)
qdel(src)
var/datum/action/innate/cult/spear/S = new(user)
var/obj/item/twohanded/cult_spear/rite = new(T)
S.Grant(user, rite)
rite.spear_act = S
if(user.put_in_hands(rite))
to_chat(user, "<span class='cult'>A [rite.name] appears in your hand!</span>")
else
user.visible_message("<span class='warning'>A [rite.name] appears at [user]'s feet!</span>", \
"<span class='cult'>A [rite.name] materializes at your feet.</span>")
if("Blood Bolt Barrage (300)")
if(uses < BLOOD_BARRAGE_COST)
to_chat(user, "<span class='cultitalic'>You need [BLOOD_BARRAGE_COST] charges to perform this rite.</span>")
else
var/obj/rite = new /obj/item/gun/projectile/shotgun/boltaction/enchanted/arcane_barrage/blood()
uses -= BLOOD_BARRAGE_COST
qdel(src)
user.swap_hand()
user.drop_item()
if(user.put_in_hands(rite))
to_chat(user, "<span class='cult'>Both of your hands glow with power!</span>")
else
to_chat(user, "<span class='warning'>You need a free hand for this rite!</span>")
uses += BLOOD_BARRAGE_COST // Refund the charges
qdel(rite)
if("Blood Orb (50)")
if(uses < BLOOD_ORB_COST)
to_chat(user, "<span class='warning'>You need [BLOOD_ORB_COST] charges to perform this rite.</span>")
@@ -898,7 +870,7 @@
if(user.put_in_hands(rite))
to_chat(user, "<span class='cult'>A [rite.name] appears in your hand!</span>")
else
user.visible_message("<span class='warning'>A [rite.name] appears at [user]'s feet!</span>", \
user.visible_message("<span class='warning'>A [rite.name] appears at [user]'s feet!</span>",
"<span class='cult'>A [rite.name] materializes at your feet.</span>")
if("Blood Recharge (75)")
@@ -914,3 +886,36 @@
to_chat(user, "<span class='warning'>You need a free hand for this rite!</span>")
uses += BLOOD_RECHARGE_COST // Refund the charges
qdel(rite)
if("Blood Spear (150)")
if(uses < BLOOD_SPEAR_COST)
to_chat(user, "<span class='warning'>You need [BLOOD_SPEAR_COST] charges to perform this rite.</span>")
else
uses -= BLOOD_SPEAR_COST
var/turf/T = get_turf(user)
qdel(src)
var/datum/action/innate/cult/spear/S = new(user)
var/obj/item/twohanded/cult_spear/rite = new(T)
S.Grant(user, rite)
rite.spear_act = S
if(user.put_in_hands(rite))
to_chat(user, "<span class='cult'>A [rite.name] appears in your hand!</span>")
else
user.visible_message("<span class='warning'>A [rite.name] appears at [user]'s feet!</span>",
"<span class='cult'>A [rite.name] materializes at your feet.</span>")
if("Blood Bolt Barrage (300)")
if(uses < BLOOD_BARRAGE_COST)
to_chat(user, "<span class='cultitalic'>You need [BLOOD_BARRAGE_COST] charges to perform this rite.</span>")
else
var/obj/rite = new /obj/item/gun/projectile/shotgun/boltaction/enchanted/arcane_barrage/blood()
uses -= BLOOD_BARRAGE_COST
qdel(src)
user.swap_hand()
user.drop_item()
if(user.put_in_hands(rite))
to_chat(user, "<span class='cult'>Both of your hands glow with power!</span>")
else
to_chat(user, "<span class='warning'>You need a free hand for this rite!</span>")
uses += BLOOD_BARRAGE_COST // Refund the charges
qdel(rite)
+80 -67
View File
@@ -85,6 +85,9 @@ GLOBAL_LIST_EMPTY(all_cults)
to_chat(cult_mind.current, CULT_GREETING)
equip_cultist(cult_mind.current)
cult_mind.current.faction |= "cult"
var/datum/objective/servecult/obj = new
obj.owner = cult_mind
cult_mind.objectives += obj
if(cult_mind.assigned_role == "Clown")
to_chat(cult_mind.current, "<span class='cultitalic'>A dark power has allowed you to overcome your clownish nature, letting you wield weapons without harming yourself.</span>")
@@ -100,50 +103,6 @@ GLOBAL_LIST_EMPTY(all_cults)
addtimer(CALLBACK(src, .proc/cult_threshold_check), 2 MINUTES) // Check again in 2 minutes for latejoiners
..()
/**
* Decides at the start of the round how many conversions are needed to rise/ascend.
*
* The number is decided by (Percentage * (Players - Cultists)), so for example at 110 players it would be 11 conversions for rise. (0.1 * (110 - 4))
* These values change based on population because 20 cultists are MUCH more powerful if there's only 50 players, compared to 120.
*
* Below 100 players, [CULT_RISEN_LOW] and [CULT_ASCENDANT_LOW] are used.
* Above 100 players, [CULT_RISEN_HIGH] and [CULT_ASCENDANT_HIGH] are used.
*/
/datum/game_mode/proc/cult_threshold_check()
var/players = length(GLOB.player_list)
var/cultists = get_cultists() // Don't count the starting cultists towards the number of needed conversions
if(players >= CULT_POPULATION_THRESHOLD)
// Highpop
ascend_percent = CULT_ASCENDANT_HIGH
rise_number = round(CULT_RISEN_HIGH * (players - cultists))
ascend_number = round(CULT_ASCENDANT_HIGH * (players - cultists))
else
// Lowpop
ascend_percent = CULT_ASCENDANT_LOW
rise_number = round(CULT_RISEN_LOW * (players - cultists))
ascend_number = round(CULT_ASCENDANT_LOW * (players - cultists))
/**
* Returns the current number of cultists and constructs.
*
* Returns the number of cultists and constructs in a list ([1] = Cultists, [2] = Constructs), or as one combined number.
*
* * separate - Should the number be returned in two separate values (Humans and Constructs) or as one?
*/
/datum/game_mode/proc/get_cultists(separate = FALSE)
var/cultists = 0
var/constructs = 0
for(var/I in cult)
var/datum/mind/M = I
if(ishuman(M.current) && !M.current.has_status_effect(STATUS_EFFECT_SUMMONEDGHOST))
cultists++
else if(isconstruct(M.current))
constructs++
if(separate)
return list(cultists, constructs)
else
return cultists + constructs
/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/H, metal = TRUE)
if(!istype(H))
return
@@ -209,6 +168,81 @@ GLOBAL_LIST_EMPTY(all_cults)
cult_objs.study(cult_mind.current)
return TRUE
/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = TRUE, remove_gear = FALSE)
if(!(cult_mind in cult)) // Not actually a cultist in the first place
return
var/mob/cultist = cult_mind.current
cult -= cult_mind
cultist.faction -= "cult"
cult_mind.special_role = null
for(var/datum/objective/servecult/S in cult_mind.objectives)
cult_mind.objectives -= S
qdel(S)
for(var/datum/action/innate/cult/C in cultist.actions)
qdel(C)
update_cult_icons_removed(cult_mind)
if(ishuman(cultist))
var/mob/living/carbon/human/H = cultist
REMOVE_TRAIT(H, CULT_EYES, null)
H.change_eye_color(H.original_eye_color, FALSE)
H.update_eyes()
H.remove_overlay(HALO_LAYER)
H.update_body()
if(remove_gear) // No flagellants robe for non-cultists
for(var/I in H.contents)
if(is_type_in_list(I, CULT_CLOTHING))
H.unEquip(I)
check_cult_size()
if(show_message)
cultist.visible_message("<span class='cult'>[cultist] looks like [cultist.p_they()] just reverted to [cultist.p_their()] old faith!</span>",
"<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of [SSticker.cultdat ? SSticker.cultdat.entity_title1 : "Nar'Sie"] and the memories of your time as their servant with it.</span>")
/**
* Decides at the start of the round how many conversions are needed to rise/ascend.
*
* The number is decided by (Percentage * (Players - Cultists)), so for example at 110 players it would be 11 conversions for rise. (0.1 * (110 - 4))
* These values change based on population because 20 cultists are MUCH more powerful if there's only 50 players, compared to 120.
*
* Below 100 players, [CULT_RISEN_LOW] and [CULT_ASCENDANT_LOW] are used.
* Above 100 players, [CULT_RISEN_HIGH] and [CULT_ASCENDANT_HIGH] are used.
*/
/datum/game_mode/proc/cult_threshold_check()
var/players = length(GLOB.player_list)
var/cultists = get_cultists() // Don't count the starting cultists towards the number of needed conversions
if(players >= CULT_POPULATION_THRESHOLD)
// Highpop
ascend_percent = CULT_ASCENDANT_HIGH
rise_number = round(CULT_RISEN_HIGH * (players - cultists))
ascend_number = round(CULT_ASCENDANT_HIGH * (players - cultists))
else
// Lowpop
ascend_percent = CULT_ASCENDANT_LOW
rise_number = round(CULT_RISEN_LOW * (players - cultists))
ascend_number = round(CULT_ASCENDANT_LOW * (players - cultists))
/**
* Returns the current number of cultists and constructs.
*
* Returns the number of cultists and constructs in a list ([1] = Cultists, [2] = Constructs), or as one combined number.
*
* * separate - Should the number be returned as a list with two separate values (Humans and Constructs) or as one number.
*/
/datum/game_mode/proc/get_cultists(separate = FALSE)
var/cultists = 0
var/constructs = 0
for(var/I in cult)
var/datum/mind/M = I
if(ishuman(M.current) && !M.current.has_status_effect(STATUS_EFFECT_SUMMONEDGHOST))
cultists++
else if(isconstruct(M.current))
constructs++
if(separate)
return list(cultists, constructs)
else
return cultists + constructs
/datum/game_mode/proc/check_cult_size()
if(cult_ascendant)
@@ -238,6 +272,8 @@ GLOBAL_LIST_EMPTY(all_cults)
/datum/game_mode/proc/rise(cultist)
if(ishuman(cultist) && iscultist(cultist))
var/mob/living/carbon/human/H = cultist
if(!H.original_eye_color)
H.original_eye_color = H.get_eye_color()
H.change_eye_color(BLOODCULT_EYE, FALSE)
H.update_eyes()
ADD_TRAIT(H, CULT_EYES, CULT_TRAIT)
@@ -249,29 +285,6 @@ GLOBAL_LIST_EMPTY(all_cults)
new /obj/effect/temp_visual/cult/sparks(get_turf(H), H.dir)
H.update_halo_layer()
/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = TRUE)
if(cult_mind in cult)
var/mob/cultist = cult_mind.current
cult -= cult_mind
cultist.faction -= "cult"
cult_mind.special_role = null
for(var/datum/action/innate/cult/C in cultist.actions)
qdel(C)
update_cult_icons_removed(cult_mind)
if(ishuman(cultist))
var/mob/living/carbon/human/H = cultist
REMOVE_TRAIT(H, CULT_EYES, null)
H.change_eye_color(H.original_eye_color, FALSE)
H.update_eyes()
H.remove_overlay(HALO_LAYER)
H.update_body()
check_cult_size()
if(show_message)
cultist.visible_message("<span class='cult'>[cultist] looks like [cultist.p_they()] just reverted to [cultist.p_their()] old faith!</span>",
"<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of [SSticker.cultdat ? SSticker.cultdat.entity_title1 : "Nar'Sie"] and the memories of your time as their servant with it.</span>")
/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind)
var/datum/atom_hud/antag/culthud = GLOB.huds[ANTAG_HUD_CULT]
if(cult_mind.current)
+12 -16
View File
@@ -316,7 +316,8 @@
var/mob/living/carbon/C = user
if(C.pulling)
var/atom/movable/pulled = C.pulling
pulled.forceMove(T)
var/turf/turf_behind = get_turf(get_step(T, turn(C.dir, 180)))
pulled.forceMove(turf_behind)
. = pulled
/obj/item/cult_shift/attack_self(mob/user)
@@ -324,7 +325,7 @@
to_chat(user, "<span class='warning'>[src] is dull and unmoving in your hands.</span>")
return
if(!iscultist(user))
user.unEquip(src, 1)
user.unEquip(src, TRUE)
step(src, pick(GLOB.alldirs))
to_chat(user, "<span class='warning'>[src] flickers out of your hands, too eager to move!</span>")
return
@@ -332,36 +333,31 @@
var/outer_tele_radius = 9
var/mob/living/carbon/C = user
var/turf/mobloc = get_turf(C)
var/list/turfs = new/list()
for(var/turf/T in range(user, outer_tele_radius))
var/list/turfs = list()
for(var/turf/T in orange(user, outer_tele_radius))
if(!is_teleport_allowed(T.z))
break
if(get_dir(C, T) != C.dir)
if(get_dir(C, T) != C.dir) // This seems like a very bad way to do this
continue
if(T == mobloc)
continue
if(istype(T, /turf/space))
if(isspaceturf(T))
continue
if(T.x > world.maxx-outer_tele_radius || T.x < outer_tele_radius)
continue //putting them at the edge is dumb
if(T.y > world.maxy-outer_tele_radius || T.y < outer_tele_radius)
continue
turfs += T
if(turfs)
if(length(turfs))
uses--
var/turf/mobloc = get_turf(C)
var/turf/destination = pick(turfs)
if(uses <= 0)
icon_state ="shifter_drained"
playsound(mobloc, "sparks", 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
icon_state = "shifter_drained"
playsound(src, "sparks", 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
new /obj/effect/temp_visual/dir_setting/cult/phase/out(mobloc, C.dir)
var/atom/movable/pulled = handle_teleport_grab(destination, C)
handle_teleport_grab(destination, C)
C.forceMove(destination)
if(pulled)
C.start_pulling(pulled) //forcemove resets pulls, so we need to re-pull
new /obj/effect/temp_visual/dir_setting/cult/phase(destination, C.dir)
playsound(destination, 'sound/effects/phasein.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
+2 -2
View File
@@ -133,13 +133,13 @@
for(var/mob/living/carbon/human/H in GLOB.player_list)
if(is_admin_level(H.z)) //We can't sacrifice people that are on the centcom z-level
continue
if(H.mind && !is_convertable_to_cult(H.mind) && (H.stat != DEAD) && (H.mind.offstation_role != TRUE))
if(H.mind && !iscultist(H) && !is_convertable_to_cult(H.mind) && (H.stat != DEAD) && !H.mind.offstation_role)
target_candidates += H.mind
if(!length(target_candidates)) //There are no living unconvertables on the station. Looking for a Sacrifice Target among the ordinary crewmembers
for(var/mob/living/carbon/human/H in GLOB.player_list)
if(is_admin_level(H.z)) //We can't sacrifice people that are on the centcom z-level
continue
if(H.mind && !iscultist(H) && (H.stat != DEAD) && (H.mind.offstation_role != TRUE))
if(H.mind && !iscultist(H) && (H.stat != DEAD) && !H.mind.offstation_role) // Same checks, but add them even if they could be converted
target_candidates += H.mind
if(length(target_candidates))
target = pick(target_candidates)
+9 -3
View File
@@ -84,6 +84,10 @@
/obj/item/melee/cultblade/dagger/proc/can_scribe(mob/living/user)
if(!src || !user || loc != user || user.incapacitated())
return FALSE
if(drawing_rune)
to_chat(user, "<span class='warning'>You're already drawing a rune!</span>")
return FALSE
var/turf/T = get_turf(user)
if(isspaceturf(T))
return FALSE
@@ -135,12 +139,12 @@
to_chat(user, "<span class='cultitalic'>The veil is not weak enough here to summon a cultist, you must be on station!</span>")
return
var/old_color = user.color // we'll temporarily redden the user for better feedback to fellow cultists. Store this to revert them back.
var/old_color = user.color // we'll temporarily redden the user for better feedback to fellow cultists. Store this to revert them back.
if(narsie_rune)
if(!narsie_rune_check(user, A))
return // don't do shit
var/list/summon_areas = gamemode.cult_objs.obj_summon.summon_spots
if(!(A in summon_areas)) // Check again to make sure they didn't move
if(!(A in summon_areas)) // Check again to make sure they didn't move
to_chat(user, "<span class='cultlarge'>The ritual can only begin where the veil is weak - in [english_list(summon_areas)]!</span>")
return
GLOB.command_announcement.Announce("Figments from an eldritch god are being summoned into the [A.map_name] from an unknown dimension. Disrupt the ritual at all costs, before the station is destroyed! Space law and SOP are suspended. The entire crew must kill cultists on sight.", "Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg')
@@ -148,7 +152,7 @@
var/turf/T = I
var/obj/machinery/shield/cult/narsie/N = new(T)
shields |= N
user.color = "red"
user.color = COLOR_RED
// Draw the rune
var/mob/living/carbon/human/H = user
@@ -161,12 +165,14 @@
user.visible_message(others_message,
"<span class='cultitalic'>You slice open your body and begin drawing a sigil of [SSticker.cultdat.entity_title3].</span>")
drawing_rune = TRUE // Only one at a time
var/scribe_successful = do_after(user, initial(rune.scribe_delay) * scribe_multiplier, target = runeturf)
for(var/V in shields) // Only used for the 'Tear Veil' rune
var/obj/machinery/shield/S = V
if(S && !QDELETED(S))
qdel(S)
user.color = old_color
drawing_rune = FALSE
if(!scribe_successful)
return
+8 -3
View File
@@ -263,6 +263,8 @@ structure_check() searches for nearby cultist structures required for the invoca
var/turf/T = get_turf(src)
for(var/mob/living/M in T)
if(!iscultist(M) || (M.mind && is_sacrifice_target(M.mind)))
if(isconstruct(M)) // No offering constructs please
continue
offer_targets += M
// Offering a head/brain
@@ -418,6 +420,8 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/teleport/Destroy()
GLOB.teleport_runes -= src
QDEL_NULL(inner_portal)
QDEL_NULL(outer_portal)
return ..()
/obj/effect/rune/teleport/invoke(list/invokers)
@@ -452,7 +456,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
if(!src || !Adjacent(user) || QDELETED(src) || user.incapacitated() || !actual_selected_rune)
if(QDELETED(src) || QDELETED(actual_selected_rune) ||!Adjacent(user) || user.incapacitated())
fail_invoke()
return
@@ -685,7 +689,7 @@ structure_check() searches for nearby cultist structures required for the invoca
cultists[M.current.real_name] = M.current
var/input = input(user, "Who do you wish to call to [src]?", "Acolytes") as null|anything in cultists
var/mob/living/cultist_to_summon = cultists[input]
if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated())
if(QDELETED(src) || !Adjacent(user) || user.incapacitated())
return
if(!cultist_to_summon)
log_game("Summon Cultist rune failed - no target")
@@ -882,6 +886,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/mob/living/carbon/human/new_human = new(T)
new_human.real_name = ghost_to_spawn.real_name
new_human.key = ghost_to_spawn.key
new_human.gender = ghost_to_spawn.gender
new_human.alpha = 150 //Makes them translucent
new_human.equipOutfit(/datum/outfit/ghost_cultist) //give them armor
new_human.apply_status_effect(STATUS_EFFECT_SUMMONEDGHOST) //ghosts can't summon more ghosts, also lets you see actual ghosts
@@ -999,7 +1004,7 @@ structure_check() searches for nearby cultist structures required for the invoca
//BEGIN THE SUMMONING
gamemode.cult_objs.succesful_summon()
used = TRUE
color = rgb(255, 0, 0)
color = COLOR_RED
..()
SEND_SOUND(world, sound('sound/effects/dimensional_rend.ogg'))
to_chat(world, "<span class='cultitalic'><b>The veil... <span class='big'>is...</span> <span class='reallybig'>TORN!!!--</span></b></span>")
+4 -6
View File
@@ -339,13 +339,11 @@
if(shade.mind)
shade.mind.transfer_to(src)
if(SS.purified)
set_light(3, 5, LIGHT_COLOR_DARK_BLUE)
name = "Holy [name]"
real_name = "Holy [real_name]"
make_holy()
// Replace regular soulstone summoning with purified soulstones
RemoveSpell(/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone)
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone/holy)
if(is_type_in_list(/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone, mob_spell_list))
RemoveSpell(/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone)
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone/holy)
else if(iscultist(src)) // Re-grant cult actions, lost in the transfer
var/datum/action/innate/cult/comm/CC = new
@@ -532,6 +532,9 @@
L.throw_at(throwtarget, 5, 1,src)
return FALSE
/obj/machinery/door/airlock/cult/screwdriver_act(mob/user, obj/item/I)
return
/obj/machinery/door/airlock/cult/cult_conceal()
icon = stealth_icon
overlays_file = stealth_overlays
@@ -83,7 +83,7 @@
/obj/effect/temp_visual/dir_setting/wraith
name = "blood"
icon = 'icons/mob/mob.dmi'
icon = 'icons/mob/cult.dmi'
icon_state = "phase_shift2"
duration = 12
@@ -471,7 +471,7 @@
if(target.mind)
if(iscultist(target))
SSticker.mode.remove_cultist(target.mind) // This proc will handle message generation.
SSticker.mode.remove_cultist(target.mind, TRUE, TRUE) // This proc will handle message generation.
praying = FALSE
return
@@ -202,7 +202,7 @@
H.ha_style = "None"
update_head_accessory()
/mob/living/carbon/human/proc/change_eye_color(colour = "#000000", update_dna = 1)
/mob/living/carbon/human/proc/change_eye_color(colour = "#000000", update_dna = TRUE)
// Update the main DNA datum, then sync the change across the organs
var/obj/item/organ/internal/eyes/eyes_organ = get_int_organ(/obj/item/organ/internal/eyes)
if(eyes_organ)
@@ -215,10 +215,16 @@
if(update_dna)
update_dna()
sync_organ_dna(assimilate=0)
sync_organ_dna(assimilate = FALSE)
update_eyes()
update_body()
return 1
return TRUE
/mob/living/carbon/human/proc/get_eye_color()
var/obj/item/organ/internal/eyes/E = get_int_organ(/obj/item/organ/internal/eyes)
if(E)
return E.eye_color
return FALSE
/mob/living/carbon/human/proc/change_hair_color(colour = "#000000", secondary)
var/obj/item/organ/external/head/H = get_organ("head")
+1 -1
View File
@@ -973,7 +973,7 @@
M.LAssailant = usr
/mob/living/proc/check_pull()
if(pulling && !(pulling in orange(1)))
if(pulling && !pulling.Adjacent(src))
stop_pulling()
/mob/living/proc/update_z(new_z) // 1+ to register, null to unregister
@@ -4,9 +4,10 @@
mob_biotypes = NONE
speak_emote = list("hisses")
emote_hear = list("wails","screeches")
response_help = "thinks better of touching"
response_help = "thinks better of touching"
response_disarm = "flails at"
response_harm = "punches"
response_harm = "punches"
icon = 'icons/mob/cult.dmi'
icon_dead = "shade_dead"
speed = 0
a_intent = INTENT_HARM
@@ -26,6 +27,9 @@
deathmessage = "collapses in a shattered heap."
var/construct_type = "shade"
var/list/construct_spells = list()
/// Is this a holy/purified construct?
var/holy = FALSE
/// Message to send to the construct when they are created, containing information about their role.
var/playstyle_string = "<b>You are a generic construct! Your job is to not exist, and you should probably adminhelp this.</b>"
/mob/living/simple_animal/hostile/construct/New()
@@ -98,7 +102,6 @@
name = "Juggernaut"
real_name = "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
@@ -149,7 +152,6 @@
name = "Wraith"
real_name = "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
@@ -174,7 +176,6 @@
name = "Artificer"
real_name = "Artificer"
desc = "A bulbous construct dedicated to building and maintaining Cult armies."
icon = 'icons/mob/mob.dmi'
icon_state = "artificer"
icon_living = "artificer"
maxHealth = 50
@@ -254,7 +255,6 @@
name = "Behemoth"
real_name = "Behemoth"
desc = "The pinnacle of occult technology, Behemoths are the ultimate weapon in the Cult's arsenal."
icon = 'icons/mob/mob.dmi'
icon_state = "behemoth"
icon_living = "behemoth"
maxHealth = 750
@@ -288,7 +288,6 @@
name = "Harvester"
real_name = "Harvester"
desc = "A harbinger of enlightenment. It'll be all over soon."
icon = 'icons/mob/mob.dmi'
icon_state = "harvester"
icon_living = "harvester"
maxHealth = 60
@@ -316,6 +315,17 @@
AIStatus = AI_ON
environment_smash = 1 //only token destruction, don't smash the cult wall NO STOP
/mob/living/simple_animal/hostile/construct/proc/make_holy()
if(holy) // Already holy-fied
return
holy = TRUE
set_light(3, 5, LIGHT_COLOR_DARK_BLUE)
name = "Holy [name]"
real_name = "Holy [real_name]"
faction.Remove("cult")
///ui stuff
/mob/living/simple_animal/hostile/construct/armoured/update_health_hud()
@@ -419,11 +419,13 @@
back = /obj/item/tank/internals/oxygen
mask = /obj/item/clothing/mask/breath
if("Cultist")
uniform = /obj/item/clothing/under/roman
suit = /obj/item/clothing/suit/hooded/cultrobes
suit_store = /obj/item/tome
r_pocket = /obj/item/restraints/legcuffs/bola/cult
uniform = /obj/item/clothing/under/color/black
back = /obj/item/storage/backpack/cultpack
suit = /obj/item/clothing/suit/hooded/cultrobes/alt
if(prob(40))
suit_store = /obj/item/melee/cultblade
l_pocket = /obj/item/melee/cultblade/dagger
glasses = /obj/item/clothing/glasses/hud/health/night
backpack_contents = list(/obj/item/reagent_containers/food/drinks/bottle/unholywater = 1, /obj/item/cult_shift = 1, /obj/item/flashlight/flare = 1, /obj/item/stack/sheet/runed_metal = 15)
if(prob(60))
r_pocket = /obj/item/reagent_containers/food/drinks/bottle/unholywater
backpack_contents = list(/obj/item/tome = 1, /obj/item/restraints/legcuffs/bola/cult = 1, /obj/item/stack/sheet/runed_metal = 15)
. = ..()
@@ -2,7 +2,7 @@
name = "Shade"
real_name = "Shade"
desc = "A bound spirit"
icon = 'icons/mob/mob.dmi'
icon = 'icons/mob/cult.dmi'
icon_state = "shade"
icon_living = "shade"
icon_dead = "shade_dead"
@@ -34,6 +34,10 @@
deathmessage = "lets out a contented sigh as their form unwinds."
var/holy = FALSE
/mob/living/simple_animal/shade/cult/Initialize(mapload)
. = ..()
icon_state = SSticker.cultdat?.shade_icon_state
/mob/living/simple_animal/shade/death(gibbed)
. = ..()
SSticker.mode.remove_cultist(mind, FALSE)
@@ -48,11 +52,6 @@
/mob/living/simple_animal/shade/Process_Spacemove()
return TRUE
/mob/living/simple_animal/shade/cult/Initialize(mapload)
. = ..()
icon_state = SSticker.cultdat?.shade_icon_state
/mob/living/simple_animal/shade/holy
holy = TRUE
icon_state = "shade_angelic"
+2
View File
@@ -193,6 +193,8 @@
/obj/item/grab/proc/adjust_position()
if(affecting.buckled)
return
if(!assailant.Adjacent(affecting)) // To prevent teleportation via grab
return
if(affecting.lying && state != GRAB_KILL)
animate(affecting, pixel_x = 0, pixel_y = 0, 5, 1, LINEAR_EASING)
return //KJK
@@ -265,16 +265,11 @@
M.SetConfused(0)
return
if(iscultist(M))
SSticker.mode.remove_cultist(M.mind)
SSticker.mode.remove_cultist(M.mind, TRUE, TRUE)
holder.remove_reagent(id, volume) // maybe this is a little too perfect and a max() cap on the statuses would be better??
M.SetJitter(0)
M.SetStuttering(0)
M.SetConfused(0)
if(ishuman(M)) // Unequip all cult clothing
var/mob/living/carbon/human/H = M
for(var/I in H.contents)
if(is_type_in_list(I, CULT_CLOTHING))
H.unEquip(I)
return
if(ishuman(M) && M.mind && M.mind.vampire && !M.mind.vampire.get_ability(/datum/vampire_passive/full) && prob(80))
var/mob/living/carbon/V = M