Datumizes Cult. (#24379)

* cult 1

* massive data refactor

* progress

* More crap

* IM SCARED IT COMPILES

* oops

* more fixes

* good comment

* hell yeah, team control

* lol

* blamo

* blam

* More stuff

* team refactor

* epic merge fail

* src not _src_

* more

* progress

* cult

* more stuff

* water

* goodbye __IMPLIED_TYPE__

* time to undraft

* FUCK FUCK FUCK

* okay this is better

* goodbye todos

* fix

* order of operations

* last fix? maybe

* yeah

* oops

* okay this should be ALL the fixes

* wow

* hell yeah

* wow

* fixes duplicate teams + adds more team safeties

* how the fuck did this happen

* admin objective improvements

* wah more bullshit

* guh

* fuuuuck

* fucking hell

* fixes
This commit is contained in:
Contrabang
2024-03-16 20:36:55 +00:00
committed by GitHub
parent 0c25bf4a21
commit 2ec55dbfbb
69 changed files with 1328 additions and 1137 deletions
+7 -4
View File
@@ -10,7 +10,7 @@
#define RUNE_COLOR_EMP "#4D94FF"
#define RUNE_COLOR_SUMMON "#00FF00"
#define is_sacrifice_target(A) SSticker.mode?.cult_objs.is_sac_target(A)
#define IS_SACRIFICE_TARGET(A) SSticker?.mode?.cult_team?.is_sac_target(A)
// Blood magic
/// Maximum number of spells with an empowering rune
@@ -42,9 +42,6 @@
#define DEFAULT_TOOLTIP "6:-29,5:-2"
// Text
#define CULT_GREETING "<span class='cultlarge'>You catch a glimpse of the Realm of [SSticker.cultdat.entity_name], [SSticker.cultdat.entity_title3]. \
You now see how flimsy the world is, you see that it should be open to the knowledge of [SSticker.cultdat.entity_name].</span>"
#define CULT_CURSES list("A fuel technician just slit his own throat and begged for death.", \
"The shuttle's navigation programming was replaced by a file containing two words, IT COMES.", \
"The shuttle's custodian tore out his guts and began painting strange shapes on the floor.", \
@@ -66,3 +63,9 @@
#define NARSIE_NEEDS_SUMMONING 2
#define NARSIE_HAS_RISEN 3
#define NARSIE_HAS_FALLEN -1
/// Safely accesses SSticker.cult_data, returns the default if cult data is not set up yet. Allows for both variable and proc call access.
#define GET_CULT_DATA(var_or_proc, default) (SSticker.cult_data ? SSticker.cult_data.var_or_proc : default)
/// Checks that the given element is living an has a cult antag datum
#define IS_CULTIST(mob) (isliving(mob) && mob?:mind?:has_antag_datum(/datum/antagonist/cultist)) // for someone TODO, move all antag checks over to TG's `IS_TRAITOR` defines. Also remove `isliving()` from this call someday
+1 -1
View File
@@ -952,7 +952,7 @@
#define COMSIG_AIRLOCK_CLOSE "airlock_close"
// /datum/objective signals
///from datum/objective/proc/find_target()
///from datum/objective/proc/find_target(list/target_blacklist)
#define COMSIG_OBJECTIVE_TARGET_FOUND "objective_target_found"
///from datum/objective/is_invalid_target()
#define COMSIG_OBJECTIVE_CHECK_VALID_TARGET "objective_check_valid_target"
+13 -11
View File
@@ -1,15 +1,17 @@
//objective defines
#define TARGET_INVALID_IS_OWNER 1
#define TARGET_INVALID_NOT_HUMAN 2
#define TARGET_INVALID_DEAD 3
#define TARGET_INVALID_NOCKEY 4
#define TARGET_INVALID_UNREACHABLE 5
#define TARGET_INVALID_GOLEM 6
#define TARGET_INVALID_EVENT 7
#define TARGET_INVALID_IS_TARGET 8
#define TARGET_INVALID_BLACKLISTED 9
#define TARGET_INVALID_CHANGELING 10
#define TARGET_INVALID_NOTHEAD 11
#define TARGET_INVALID_IS_OWNER 1
#define TARGET_INVALID_NOT_HUMAN 2
#define TARGET_INVALID_DEAD 3
#define TARGET_INVALID_NOCKEY 4
#define TARGET_INVALID_UNREACHABLE 5
#define TARGET_INVALID_GOLEM 6
#define TARGET_INVALID_EVENT 7
#define TARGET_INVALID_IS_TARGET 8
#define TARGET_INVALID_BLACKLISTED 9
#define TARGET_INVALID_CHANGELING 10
#define TARGET_INVALID_NOTHEAD 11
#define TARGET_INVALID_CULTIST 12
#define TARGET_INVALID_CULT_CONVERTABLE 13
//gamemode istype helpers
#define GAMEMODE_IS_CULT (SSticker && istype(SSticker.mode, /datum/game_mode/cult))
+4
View File
@@ -690,3 +690,7 @@ do { \
#define RETURN_POINT_VECTOR(ATOM, ANGLE, SPEED) (new /datum/point_precise/vector(ATOM, null, null, null, null, ANGLE, SPEED))
#define RETURN_POINT_VECTOR_INCREMENT(ATOM, ANGLE, SPEED, AMT) (new /datum/point_precise/vector(ATOM, null, null, null, null, ANGLE, SPEED, AMT))
#define TEAM_ADMIN_ADD_OBJ_SUCCESS (1<<0)
#define TEAM_ADMIN_ADD_OBJ_CANCEL_LOG (1<<1)
#define TEAM_ADMIN_ADD_OBJ_PURPOSEFUL_CANCEL (1<<2)
+4 -3
View File
@@ -37,8 +37,8 @@ SUBSYSTEM_DEF(ticker)
var/Bible_name
/// Name of the bible deity
var/Bible_deity_name
/// Cult data. Here instead of cult for adminbus purposes
var/datum/cult_info/cultdat = null
/// Cult static info, used for things like sprites. Someone should refactor the sprites out of it someday and just use SEPERATE ICONS DEPNDING ON THE TYPE OF CULT... like a sane person
var/datum/cult_info/cult_data
/// If set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders
var/random_players = FALSE
/// Did we broadcast the tip of the round yet?
@@ -159,7 +159,8 @@ SUBSYSTEM_DEF(ticker)
reboot_helper("Round ended.", "proper completion")
/datum/controller/subsystem/ticker/proc/setup()
cultdat = setupcult()
var/random_cult = pick(typesof(/datum/cult_info))
cult_data = new random_cult()
score = new()
// Create and announce mode
+18 -26
View File
@@ -167,13 +167,6 @@
var/mob/living/carbon/human/H = new_character
if(H.mind in SSticker.mode.syndicates)
SSticker.mode.update_synd_icons_added()
if(H.mind in SSticker.mode.cult)
SSticker.mode.update_cult_icons_added(H.mind) // Adds the cult antag hud
SSticker.mode.add_cult_actions(H.mind) // And all the actions
if(SSticker.mode.cult_risen)
SSticker.mode.rise(H)
if(SSticker.mode.cult_ascendant)
SSticker.mode.ascend(H)
/datum/mind/proc/store_memory(new_text)
memory += "[new_text]<br>"
@@ -339,7 +332,7 @@
/datum/mind/proc/memory_edit_cult(mob/living/carbon/human/H)
. = _memory_edit_header("cult")
if(src in SSticker.mode.cult)
if(has_antag_datum(/datum/antagonist/cultist))
. += "<a href='?src=[UID()];cult=clear'>no</a>|<b><font color='red'>CULTIST</font></b>"
. += "<br>Give <a href='?src=[UID()];cult=dagger'>dagger</a>|<a href='?src=[UID()];cult=runedmetal'>runedmetal</a>."
else
@@ -818,8 +811,7 @@
to_chat(H, "<span class='userdanger'>You somehow have become the recipient of a mindshield transplant, and it just activated!</span>")
var/datum/antagonist/rev/has_rev = has_antag_datum(/datum/antagonist/rev)
if(has_rev)
has_rev.silent = TRUE // we have some custom text, lets make the removal silent
remove_antag_datum(/datum/antagonist/rev)
remove_antag_datum(/datum/antagonist/rev, silent_removal = TRUE) // we have some custom text, lets make the removal silent
to_chat(H, "<span class='userdanger'>The nanobots in the mindshield implant remove all thoughts about being a revolutionary. Get back to work!</span>")
else if(href_list["revolution"])
@@ -911,27 +903,25 @@
else if(href_list["cult"])
switch(href_list["cult"])
if("clear")
if(src in SSticker.mode.cult)
SSticker.mode.remove_cultist(src)
special_role = null
if(has_antag_datum(/datum/antagonist/cultist))
remove_antag_datum(/datum/antagonist/cultist)
log_admin("[key_name(usr)] has de-culted [key_name(current)]")
message_admins("[key_name_admin(usr)] has de-culted [key_name_admin(current)]")
if("cultist")
if(!(src in SSticker.mode.cult))
to_chat(current, CULT_GREETING)
SSticker.mode.add_cultist(src)
to_chat(current, "<span class='cultitalic'>Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [SSticker.cultdat.entity_title2] above all else. Bring It back.</span>")
log_and_message_admins("[key_name(usr)] has culted [key_name(current)]")
if(!has_antag_datum(/datum/antagonist/cultist))
add_antag_datum(/datum/antagonist/cultist)
to_chat(current, "<span class='cultitalic'>Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [GET_CULT_DATA(entity_title2, "your god")] above all else. Bring It back.</span>")
log_and_message_admins("has culted [key_name(current)]")
if("dagger")
var/mob/living/carbon/human/H = current
if(!SSticker.mode.cult_give_item(/obj/item/melee/cultblade/dagger, H))
var/datum/antagonist/cultist/cultist = has_antag_datum(/datum/antagonist/cultist)
if(!cultist.cult_give_item(/obj/item/melee/cultblade/dagger))
to_chat(usr, "<span class='warning'>Spawning dagger failed!</span>")
log_and_message_admins("[key_name(usr)] has equipped [key_name(current)] with a cult dagger")
log_and_message_admins("has equipped [key_name(current)] with a cult dagger")
if("runedmetal")
var/mob/living/carbon/human/H = current
if(!SSticker.mode.cult_give_item(/obj/item/stack/sheet/runed_metal/ten, H))
var/datum/antagonist/cultist/cultist = has_antag_datum(/datum/antagonist/cultist)
if(!cultist.cult_give_item(/obj/item/stack/sheet/runed_metal/ten))
to_chat(usr, "<span class='warning'>Spawning runed metal failed!</span>")
log_and_message_admins("[key_name(usr)] has equipped [key_name(current)] with 10 runed metal sheets")
log_and_message_admins("has equipped [key_name(current)] with 10 runed metal sheets")
else if(href_list["wizard"])
@@ -1536,9 +1526,11 @@
* Arguments:
* * datum_type - an antag datum typepath
*/
/datum/mind/proc/remove_antag_datum(datum_type, check_subtypes = TRUE)
/datum/mind/proc/remove_antag_datum(datum_type, check_subtypes = TRUE, silent_removal = FALSE)
var/datum/antagonist/A = has_antag_datum(datum_type, check_subtypes)
qdel(A)
if(A)
A.silent |= silent_removal
qdel(A)
/**
* Removes all antag datums from the src mind.
+1 -1
View File
@@ -127,7 +127,7 @@
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)
C.set_light(2, 3, l_color = GET_CULT_DATA(construct_glow, LIGHT_COLOR_BLOOD_MAGIC))
/obj/effect/proc_holder/spell/ethereal_jaunt/shift/jaunt_steam(mobloc)
return
+10 -11
View File
@@ -136,7 +136,7 @@
..()
/datum/action/innate/cult/blood_spell/IsAvailable()
if(!iscultist(owner) || owner.incapacitated() || !charges)
if(!IS_CULTIST(owner) || owner.incapacitated() || !charges)
return FALSE
return ..()
@@ -229,8 +229,7 @@
button_icon_state = "cult_dagger"
/datum/action/innate/cult/blood_spell/dagger/New()
if(SSticker.mode)
button_icon_state = SSticker.cultdat.dagger_icon
button_icon_state = GET_CULT_DATA(dagger_icon, "cult_dagger")
..()
/datum/action/innate/cult/blood_spell/dagger/Activate()
@@ -298,7 +297,7 @@
/obj/effect/proc_holder/horror/InterceptClickOn(mob/living/user, params, atom/target)
if(..())
return
if(ranged_ability_user.incapacitated() || !iscultist(user))
if(ranged_ability_user.incapacitated() || !IS_CULTIST(user))
user.ranged_ability.remove_ranged_ability(user)
return
if(user.holy_check())
@@ -307,7 +306,7 @@
if(!isturf(T))
return FALSE
if(target in view(7, ranged_ability_user))
if(!ishuman(target) || iscultist(target))
if(!ishuman(target) || IS_CULTIST(target))
return
var/mob/living/carbon/human/H = target
H.Hallucinate(120 SECONDS)
@@ -336,7 +335,7 @@
owner.visible_message("<span class='warning'>Thin grey dust falls from [owner]'s hand!</span>", \
"<span class='cultitalic'>You invoke the veiling spell, hiding nearby runes and cult structures.</span>")
charges--
if(!SSticker.mode.cult_risen || !SSticker.mode.cult_ascendant)
if(!SSticker.mode.cult_team.cult_risen || !SSticker.mode.cult_team.cult_ascendant)
playsound(owner, 'sound/magic/smoke.ogg', 25, TRUE, SOUND_RANGE_SET(4)) // If Cult is risen/ascendant.
else
playsound(owner, 'sound/magic/smoke.ogg', 25, TRUE, SOUND_RANGE_SET(1)) // If Cult is unpowered.
@@ -352,7 +351,7 @@
"<span class='cultitalic'>You invoke the counterspell, revealing nearby runes and cult structures.</span>")
charges--
owner.whisper(invocation)
if(!SSticker.mode.cult_risen || !SSticker.mode.cult_ascendant)
if(!SSticker.mode.cult_team.cult_risen || !SSticker.mode.cult_team.cult_ascendant)
playsound(owner, 'sound/misc/enter_blood.ogg', 25, TRUE, SOUND_RANGE_SET(7)) // If Cult is risen/ascendant.
else
playsound(owner, 'sound/magic/smoke.ogg', 25, TRUE, SOUND_RANGE_SET(1)) // If Cult is unpowered.
@@ -429,7 +428,7 @@
afterattack(user, user, TRUE)
/obj/item/melee/blood_magic/attack(mob/living/M, mob/living/carbon/user)
if(!iscarbon(user) || !iscultist(user))
if(!iscarbon(user) || !IS_CULTIST(user))
uses = 0
qdel(src)
return
@@ -462,7 +461,7 @@
if(!isliving(target) || !proximity)
return
var/mob/living/L = target
if(iscultist(target))
if(IS_CULTIST(target))
return
if(user.holy_check())
return
@@ -511,7 +510,7 @@
var/list/teleportnames = list()
var/list/duplicaterunecount = list()
var/atom/movable/teleportee
if(!iscultist(target) || !proximity)
if(!IS_CULTIST(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
@@ -875,7 +874,7 @@
if(!proximity)
return ..()
if(ishuman(target))
if(iscultist(target))
if(IS_CULTIST(target))
heal_cultist(user, target)
target.clean_blood()
else
+8 -12
View File
@@ -5,7 +5,7 @@
buttontooltipstyle = "cult"
/datum/action/innate/cult/IsAvailable()
if(!iscultist(owner))
if(!IS_CULTIST(owner))
return FALSE
return ..()
@@ -55,7 +55,7 @@
living_message = "<span class='cult[(large ? "large" : "speech")]'>[title]: [message]</span>"
for(var/mob/M in GLOB.player_list)
if(iscultist(M))
if(IS_CULTIST(M))
to_chat(M, living_message)
else if((M in GLOB.dead_mob_list) && !isnewplayer(M))
to_chat(M, "<span class='cult[(large ? "large" : "speech")]'>[title] ([ghost_follow_link(user, ghost=M)]): [message]</span>")
@@ -78,7 +78,7 @@
living_message = "<span class='cultlarge'>[title]: [message]</span>"
for(var/mob/M in GLOB.player_list)
if(iscultist(M))
if(IS_CULTIST(M))
to_chat(M, living_message)
else if((M in GLOB.dead_mob_list) && !isnewplayer(M))
to_chat(M, "<span class='cultlarge'>[title] ([ghost_follow_link(user, ghost=M)]): [message]</span>")
@@ -92,20 +92,17 @@
check_flags = AB_CHECK_CONSCIOUS
/datum/action/innate/cult/check_progress/New()
if(SSticker.mode)
button_icon_state = SSticker.cultdat.tome_icon
button_icon_state = GET_CULT_DATA(tome_icon, "tome")
..()
/datum/action/innate/cult/check_progress/IsAvailable()
if(iscultist(owner) || isobserver(owner))
return TRUE
return FALSE
return IS_CULTIST(owner) || isobserver(owner)
/datum/action/innate/cult/check_progress/Activate()
if(!IsAvailable())
return
if(SSticker && SSticker.mode)
SSticker.mode.cult_objs.study(usr, TRUE)
if(SSticker?.mode?.cult_team)
SSticker.mode.cult_team.study_objectives(usr, TRUE)
else
to_chat(usr, "<span class='cultitalic'>You fail to study the Veil. (This should never happen, adminhelp and/or yell at a coder)</span>")
@@ -117,8 +114,7 @@
button_icon_state = "blood_dagger"
/datum/action/innate/cult/use_dagger/Grant()
if(SSticker.mode)
button_icon_state = SSticker.cultdat.dagger_icon
button_icon_state = GET_CULT_DATA(dagger_icon, "blood_dagger")
..()
/datum/action/innate/cult/use_dagger/override_location()
-3
View File
@@ -74,9 +74,6 @@
var/airlock_unruned_icon_file = 'icons/obj/doors/airlocks/cult/unruned/cult.dmi'
var/airlock_unruned_overlays_file = 'icons/obj/doors/airlocks/cult/unruned/cult-overlays.dmi'
/// Are cultist mirror shields active yet?
var/mirror_shields_active = FALSE
/datum/cult_info/fire
name = "Cult of Kha'Rin"
+20 -22
View File
@@ -7,8 +7,7 @@
w_class = WEIGHT_CLASS_SMALL
/obj/item/tome/New()
if(SSticker.mode)
icon_state = SSticker.cultdat.tome_icon
icon_state = GET_CULT_DATA(tome_icon, "tome")
..()
/obj/item/melee/cultblade
@@ -26,9 +25,8 @@
sprite_sheets_inhand = list("Skrell" = 'icons/mob/clothing/species/skrell/held.dmi') // To stop skrell stabbing themselves in the head
/obj/item/melee/cultblade/New()
if(SSticker.mode)
icon_state = SSticker.cultdat.sword_icon
item_state = SSticker.cultdat.sword_icon
icon_state = GET_CULT_DATA(sword_icon, "blood_blade")
item_state = GET_CULT_DATA(sword_icon, "blood_blade")
..()
/obj/item/melee/cultblade/examine(mob/user)
@@ -36,7 +34,7 @@
. += "<span class='notice'>This blade is a powerful weapon, capable of severing limbs easily. Nonbelievers are unable to use this weapon. Striking a nonbeliever after downing them with your cult magic will stun them completely.</span>"
/obj/item/melee/cultblade/attack(mob/living/target, mob/living/carbon/human/user)
if(!iscultist(user))
if(!IS_CULTIST(user))
user.Weaken(10 SECONDS)
user.unEquip(src, 1)
user.visible_message("<span class='warning'>A powerful force shoves [user] away from [target]!</span>",
@@ -47,7 +45,7 @@
else
user.adjustBruteLoss(rand(force/2, force))
return
if(!iscultist(target))
if(!IS_CULTIST(target))
var/datum/status_effect/cult_stun_mark/S = target.has_status_effect(STATUS_EFFECT_CULT_STUN)
if(S)
S.trigger()
@@ -55,7 +53,7 @@
/obj/item/melee/cultblade/pickup(mob/living/user)
. = ..()
if(!iscultist(user))
if(!IS_CULTIST(user))
to_chat(user, "<span class='cultlarge'>\"I wouldn't advise that.\"</span>")
to_chat(user, "<span class='warning'>An overwhelming sense of nausea overpowers you!</span>")
user.Confused(20 SECONDS)
@@ -74,13 +72,13 @@
knockdown_duration = 2 SECONDS
/obj/item/restraints/legcuffs/bola/cult/throw_at(atom/target, range, speed, mob/thrower, spin, diagonals_first, datum/callback/callback)
if(thrower && !iscultist(thrower)) // A couple of objs actually proc throw_at, so we need to make sure that yes, we got tossed by a person before trying to send a message
if(thrower && !IS_CULTIST(thrower)) // A couple of objs actually proc throw_at, so we need to make sure that yes, we got tossed by a person before trying to send a message
thrower.visible_message("<span class='danger'>The bola glows, and boomarangs back at [thrower]!</span>")
throw_impact(thrower)
. = ..()
/obj/item/restraints/legcuffs/bola/cult/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(iscultist(hit_atom))
if(IS_CULTIST(hit_atom))
hit_atom.visible_message("<span class='warning'>[src] bounces off of [hit_atom], as if repelled by an unseen force!</span>")
return
. = ..()
@@ -164,7 +162,7 @@
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/equipped(mob/living/user, slot)
..()
if(!iscultist(user)) // Todo: Make this only happen when actually equipped to the correct slot. (For all cult items)
if(!IS_CULTIST(user)) // Todo: Make this only happen when actually equipped to the correct slot. (For all cult items)
to_chat(user, "<span class='cultlarge'>\"I wouldn't advise that.\"</span>")
to_chat(user, "<span class='warning'>An overwhelming sense of nausea overpowers you!</span>")
user.unEquip(src, 1)
@@ -201,7 +199,7 @@
/obj/item/clothing/suit/hooded/cultrobes/flagellant_robe/equipped(mob/living/user, slot)
..()
if(!iscultist(user))
if(!IS_CULTIST(user))
to_chat(user, "<span class='cultlarge'>\"I wouldn't advise that.\"</span>")
to_chat(user, "<span class='warning'>An overwhelming sense of nausea overpowers you!</span>")
user.unEquip(src, 1)
@@ -268,7 +266,7 @@
/obj/item/clothing/glasses/hud/health/night/cultblind/equipped(mob/living/user, slot)
..()
if(!iscultist(user))
if(!IS_CULTIST(user))
to_chat(user, "<span class='cultlarge'>\"You want to be blind, do you?\"</span>")
user.unEquip(src, 1)
user.Confused(60 SECONDS)
@@ -283,7 +281,7 @@
var/global/curselimit = 0
/obj/item/shuttle_curse/attack_self(mob/living/user)
if(!iscultist(user))
if(!IS_CULTIST(user))
user.unEquip(src, 1)
user.Weaken(10 SECONDS)
to_chat(user, "<span class='warning'>A powerful force shoves you away from [src]!</span>")
@@ -334,7 +332,7 @@
if(!uses || !iscarbon(user))
to_chat(user, "<span class='warning'>[src] is dull and unmoving in your hands.</span>")
return
if(!iscultist(user))
if(!IS_CULTIST(user))
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>")
@@ -461,11 +459,11 @@
*/
/obj/item/shield/mirror/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
// Incase they get one by some magic
if(!SSticker.cultdat.mirror_shields_active)
if(!SSticker.mode.cult_team.mirror_shields_active)
to_chat(owner, "<span class='warning'>This shield is powerless! You must perform the required sacrifice to empower it!</span>")
return
if(iscultist(owner) && !owner.holy_check()) // Cultist holding the shield
if(IS_CULTIST(owner) && !owner.holy_check()) // Cultist holding the shield
// Hit by a projectile
if(istype(hitby, /obj/item/projectile))
@@ -533,7 +531,7 @@
illusions++
else if(isliving(loc))
var/mob/living/holder = loc
if(iscultist(holder))
if(IS_CULTIST(holder))
to_chat(holder, "<span class='cultitalic'>The shield's illusions are back at full strength!</span>")
else
to_chat(holder, "<span class='warning'>[src] vibrates slightly, and starts glowing.")
@@ -584,7 +582,7 @@
var/turf/T = get_turf(hit_atom)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
if(iscultist(L))
if(IS_CULTIST(L))
playsound(src, 'sound/weapons/throwtap.ogg', 50)
if(!L.restrained() && L.put_in_active_hand(src))
L.visible_message("<span class='warning'>[L] catches [src] out of the air!</span>")
@@ -688,7 +686,7 @@
hitsound = 'sound/effects/splat.ogg'
/obj/item/projectile/magic/arcane_barrage/blood/prehit(atom/target)
if(iscultist(target))
if(IS_CULTIST(target))
damage = 0
nodamage = TRUE
if(ishuman(target))
@@ -720,7 +718,7 @@
/obj/item/portal_amulet/afterattack(atom/O, mob/user, proximity)
. = ..()
if(!iscultist(user))
if(!IS_CULTIST(user))
if(!iscarbon(user))
return
var/mob/living/carbon/M = user
@@ -799,7 +797,7 @@
exit = new /obj/effect/cult_portal_exit(target)
/obj/effect/portal/cult/attackby(obj/I, mob/user, params)
if(istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user) || istype(I, /obj/item/nullrod) && HAS_MIND_TRAIT(user, TRAIT_HOLY))
if(istype(I, /obj/item/melee/cultblade/dagger) && IS_CULTIST(user) || istype(I, /obj/item/nullrod) && HAS_MIND_TRAIT(user, TRAIT_HOLY))
to_chat(user, "<span class='notice'>You close the portal with your [I].</span>")
playsound(src, 'sound/magic/magic_missile.ogg', 100, TRUE)
qdel(src)
+14 -362
View File
@@ -1,49 +1,10 @@
/datum/game_mode
/// A list of all minds currently in the cult
var/list/datum/mind/cult = list()
var/datum/cult_objectives/cult_objs = new
/// Does the cult have glowing eyes
var/cult_risen = FALSE
/// Does the cult have halos
var/cult_ascendant = FALSE
/// How many crew need to be converted to rise
var/rise_number
/// How many crew need to be converted to ascend
var/ascend_number
/// Used for the CentComm announcement at ascension
var/ascend_percent
var/datum/team/cult/cult_team
/proc/iscultist(mob/living/M)
return istype(M) && M.mind && SSticker && SSticker.mode && (M.mind in SSticker.mode.cult)
/proc/is_convertable_to_cult(datum/mind/mind)
if(!mind)
return FALSE
if(!mind.current)
return FALSE
if(is_sacrifice_target(mind))
return FALSE
if(iscultist(mind.current))
return TRUE //If they're already in the cult, assume they are convertable
if(HAS_MIND_TRAIT(mind.current, TRAIT_HOLY))
return FALSE
if(ishuman(mind.current))
var/mob/living/carbon/human/H = mind.current
if(ismindshielded(H)) //mindshield protects against conversions unless removed
return FALSE
if(mind.offstation_role)
return FALSE
if(issilicon(mind.current))
return FALSE //can't convert machines, that's ratvar's thing
if(isguardian(mind.current))
var/mob/living/simple_animal/hostile/guardian/G = mind.current
if(iscultist(G.summoner))
return TRUE //can't convert it unless the owner is converted
if(isgolem(mind.current))
return FALSE
if(isanimal(mind.current))
return FALSE
return TRUE
/datum/game_mode/proc/get_cult_team()
if(!cult_team)
new /datum/team/cult() // assignment happens in create_team()
return cult_team
/datum/game_mode/cult
name = "cult"
@@ -54,6 +15,8 @@
required_enemies = 3
recommended_enemies = 4
var/list/pre_cult = list()
var/const/min_cultists_to_start = 3
var/const/max_cultists_to_start = 4
@@ -71,335 +34,24 @@
break
var/datum/mind/cultist = pick(cultists_possible)
cultists_possible -= cultist
cult += cultist
pre_cult += cultist
cultist.restricted_roles = restricted_jobs
cultist.special_role = SPECIAL_ROLE_CULTIST
return (length(cult) > 0)
return length(pre_cult)
/datum/game_mode/cult/post_setup()
modePlayer += cult
cult_objs.setup()
for(var/datum/mind/cult_mind in cult)
SEND_SOUND(cult_mind.current, sound('sound/ambience/antag/bloodcult.ogg'))
to_chat(cult_mind.current, CULT_GREETING)
equip_cultist(cult_mind.current)
cult_mind.current.faction |= "cult"
cult_mind.add_mind_objective(/datum/objective/servecult)
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>")
cult_mind.current.dna.SetSEState(GLOB.clumsyblock, FALSE)
singlemutcheck(cult_mind.current, GLOB.clumsyblock, MUTCHK_FORCED)
var/datum/action/innate/toggle_clumsy/A = new
A.Grant(cult_mind.current)
update_cult_icons_added(cult_mind)
cult_objs.study(cult_mind.current)
to_chat(cult_mind.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Cultist)</span>")
cult_threshold_check()
addtimer(CALLBACK(src, PROC_REF(cult_threshold_check)), 2 MINUTES) // Check again in 2 minutes for latejoiners
new /datum/team/cult(pre_cult)
..()
/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/H, metal = TRUE)
if(!istype(H))
return
. += cult_give_item(/obj/item/melee/cultblade/dagger, H)
if(metal)
. += cult_give_item(/obj/item/stack/sheet/runed_metal/ten, H)
to_chat(H, "<span class='cult'>These will help you start the cult on this station. Use them well, and remember - you are not the only one.</span>")
/datum/game_mode/proc/cult_give_item(obj/item/item_path, mob/living/carbon/human/H)
var/list/slots = list(
"backpack" = SLOT_HUD_IN_BACKPACK,
"left pocket" = SLOT_HUD_LEFT_STORE,
"right pocket" = SLOT_HUD_RIGHT_STORE)
var/T = new item_path(H)
var/item_name = initial(item_path.name)
var/where = H.equip_in_one_of_slots(T, slots)
if(!where)
to_chat(H, "<span class='userdanger'>Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).</span>")
return FALSE
else
to_chat(H, "<span class='danger'>You have a [item_name] in your [where].</span>")
return TRUE
/datum/game_mode/proc/add_cultist(datum/mind/cult_mind)
if(!istype(cult_mind))
return FALSE
if(!ascend_percent) // If the rise/ascend thresholds haven't been set (non-cult rounds)
cult_objs.setup()
cult_threshold_check()
if(!(cult_mind in cult))
cult += cult_mind
cult_mind.current.faction |= "cult"
cult_mind.special_role = SPECIAL_ROLE_CULTIST
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>")
cult_mind.current.dna.SetSEState(GLOB.clumsyblock, FALSE)
singlemutcheck(cult_mind.current, GLOB.clumsyblock, MUTCHK_FORCED)
var/datum/action/innate/toggle_clumsy/A = new
A.Grant(cult_mind.current)
SEND_SOUND(cult_mind.current, sound('sound/ambience/antag/bloodcult.ogg'))
cult_mind.current.create_attack_log("<span class='danger'>Has been converted to the cult!</span>")
cult_mind.current.create_log(CONVERSION_LOG, "Converted to the cult")
if(jobban_isbanned(cult_mind.current, ROLE_CULTIST) || jobban_isbanned(cult_mind.current, ROLE_SYNDICATE))
replace_jobbanned_player(cult_mind.current, ROLE_CULTIST)
if(!cult_objs.cult_status && ishuman(cult_mind.current))
cult_objs.setup()
update_cult_icons_added(cult_mind)
add_cult_actions(cult_mind)
cult_mind.add_mind_objective(/datum/objective/servecult)
if(cult_risen)
rise(cult_mind.current)
if(cult_ascendant)
ascend(cult_mind.current)
check_cult_size()
cult_objs.study(cult_mind.current)
to_chat(cult_mind.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Cultist)</span>")
RegisterSignal(cult_mind.current, COMSIG_MOB_STATCHANGE, PROC_REF(cultist_stat_change))
RegisterSignal(cult_mind.current, COMSIG_PARENT_QDELETING, PROC_REF(remove_cultist))
return TRUE
/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = TRUE, remove_gear = FALSE, mob/target_mob)
if(!(cult_mind in cult)) // Not actually a cultist in the first place
return
var/mob/cultist = target_mob
if(!cultist)
cultist = cult_mind.current
cult -= cult_mind
cultist.faction -= "cult"
cult_mind.special_role = null
cult_mind.objective_holder.clear(/datum/objective/servecult)
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)
if(cult_mind.assigned_role == "Clown")
to_chat(H, "<span class='sans'>You are free of the dark power suppressing your clownish nature. You are clumsy again! Honk!</span>")
H.dna.SetSEState(GLOB.clumsyblock, TRUE)
singlemutcheck(H, GLOB.clumsyblock, MUTCHK_FORCED)
for(var/datum/action/innate/toggle_clumsy/A in H.actions)
A.Remove(H)
cult_mind.current.create_log(CONVERSION_LOG, "Deconverted from the cult")
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>")
UnregisterSignal(cult_mind.current, COMSIG_MOB_STATCHANGE)
UnregisterSignal(cult_mind.current, COMSIG_PARENT_QDELETING)
/datum/game_mode/proc/add_cult_immunity(mob/living/target)
ADD_TRAIT(target, TRAIT_CULT_IMMUNITY, CULT_TRAIT)
addtimer(CALLBACK(src, PROC_REF(remove_cult_immunity), target), 1 MINUTES)
/datum/game_mode/proc/remove_cult_immunity(mob/living/target)
REMOVE_TRAIT(target, TRAIT_CULT_IMMUNITY, CULT_TRAIT)
/**
* 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/list/living_players = get_living_players(exclude_nonhuman = TRUE, exclude_offstation = TRUE)
var/players = length(living_players)
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/datum/mind/M as anything in cult)
if(QDELETED(M) || M.current?.stat == DEAD)
continue
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)
return cultists + constructs
/datum/game_mode/proc/cultist_stat_change(mob/target_cultist, new_stat, old_stat)
SIGNAL_HANDLER // COMSIG_MOB_STATCHANGE from cultists
if(new_stat == old_stat) // huh, how? whatever, we ignore it
return
if(new_stat != DEAD && old_stat != DEAD)
return // switching between alive and unconcious
// switching between dead and alive/unconcious
check_cult_size()
/datum/game_mode/proc/check_cult_size()
var/cult_players = get_cultists()
if(cult_ascendant)
// The cult only falls if below 1/2 of the rising, usually pretty low. e.g. 5% on highpop, 10% on lowpop
if(cult_players < (rise_number / 2))
cult_fall()
return
if((cult_players >= rise_number) && !cult_risen)
cult_rise()
return
if(cult_players >= ascend_number)
cult_ascend()
/datum/game_mode/proc/cult_rise()
cult_risen = TRUE
for(var/datum/mind/M in cult)
if(!ishuman(M.current))
continue
SEND_SOUND(M.current, sound('sound/hallucinations/i_see_you2.ogg'))
to_chat(M.current, "<span class='cultlarge'>The veil weakens as your cult grows, your eyes begin to glow...</span>")
addtimer(CALLBACK(src, PROC_REF(rise), M.current), 20 SECONDS)
/datum/game_mode/proc/cult_ascend()
cult_ascendant = TRUE
for(var/datum/mind/M in cult)
if(!ishuman(M.current))
continue
SEND_SOUND(M.current, sound('sound/hallucinations/im_here1.ogg'))
to_chat(M.current, "<span class='cultlarge'>Your cult is ascendant and the red harvest approaches - you cannot hide your true nature for much longer!</span>")
addtimer(CALLBACK(src, PROC_REF(ascend), M.current), 20 SECONDS)
GLOB.major_announcement.Announce("Picking up extradimensional activity related to the Cult of [SSticker.cultdat ? SSticker.cultdat.entity_name : "Nar'Sie"] from your station. Data suggests that about [ascend_percent * 100]% of the station has been converted. Security staff are authorized to use lethal force freely against cultists. Non-security staff should be prepared to defend themselves and their work areas from hostile cultists. Self defense permits non-security staff to use lethal force as a last resort, but non-security staff should be defending their work areas, not hunting down cultists. Dead crewmembers must be revived and deconverted once the situation is under control.", "Central Command Higher Dimensional Affairs", 'sound/AI/commandreport.ogg')
/datum/game_mode/proc/cult_fall()
cult_ascendant = FALSE
for(var/datum/mind/M in cult)
if(!ishuman(M.current))
continue
SEND_SOUND(M.current, sound('sound/hallucinations/wail.ogg'))
to_chat(M.current, "<span class='cultlarge'>The veil repairs itself, your power grows weaker...</span>")
addtimer(CALLBACK(src, PROC_REF(descend), M.current), 20 SECONDS)
GLOB.major_announcement.Announce("Paranormal activity has returned to minimal levels. \
Security staff should minimize lethal force against cultists, using non-lethals where possible. \
All dead cultists should be taken to medbay or robotics for immediate revival and deconversion. \
Non-security staff may defend themselves, but should prioritize leaving any areas with cultists and reporting the cultists to security. \
Self defense permits non-security staff to use lethal force as a last resort. Hunting down cultists may make you liable for a manslaughter charge. \
Any access granted in response to the paranormal threat should be reset. \
Any and all security gear that was handed out should be returned. Finally, all weapons (including improvised) should be removed from the crew.",
"Central Command Higher Dimensional Affairs", 'sound/AI/commandreport.ogg')
/datum/game_mode/proc/rise(cultist)
if(!ishuman(cultist) || !iscultist(cultist))
return
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)
H.update_body()
/datum/game_mode/proc/ascend(cultist)
if(!ishuman(cultist) || !iscultist(cultist))
return
var/mob/living/carbon/human/H = cultist
new /obj/effect/temp_visual/cult/sparks(get_turf(H), H.dir)
H.update_halo_layer()
/datum/game_mode/proc/descend(cultist)
if(!ishuman(cultist) || !iscultist(cultist))
return
var/mob/living/carbon/human/H = cultist
new /obj/effect/temp_visual/cult/sparks(get_turf(H), H.dir)
H.update_halo_layer()
to_chat(cultist, "<span class='userdanger'>The halo above your head shatters!</span>")
playsound(cultist, "shatter", 50, TRUE)
/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)
culthud.join_hud(cult_mind.current)
set_antag_hud(cult_mind.current, "hudcultist")
/datum/game_mode/proc/update_cult_icons_removed(datum/mind/cult_mind)
var/datum/atom_hud/antag/culthud = GLOB.huds[ANTAG_HUD_CULT]
if(cult_mind.current)
culthud.leave_hud(cult_mind.current)
set_antag_hud(cult_mind.current, null)
/datum/game_mode/proc/add_cult_actions(datum/mind/cult_mind)
if(cult_mind.current)
var/datum/action/innate/cult/comm/C = new
var/datum/action/innate/cult/check_progress/D = new
C.Grant(cult_mind.current)
D.Grant(cult_mind.current)
if(ishuman(cult_mind.current))
var/datum/action/innate/cult/blood_magic/magic = new
magic.Grant(cult_mind.current)
var/datum/action/innate/cult/use_dagger/dagger = new
dagger.Grant(cult_mind.current)
cult_mind.current.update_action_buttons(TRUE)
/datum/game_mode/cult/declare_completion()
if(cult_objs.cult_status == NARSIE_HAS_RISEN)
if(cult_team.sacrifices_required == NARSIE_HAS_RISEN)
SSticker.mode_result = "cult win - cult win"
to_chat(world, "<span class='danger'> <FONT size = 3>The cult wins! It has succeeded in summoning [SSticker.cultdat.entity_name]!</FONT></span>")
else if(cult_objs.cult_status == NARSIE_HAS_FALLEN)
to_chat(world, "<span class='danger'> <FONT size = 3>The cult wins! It has succeeded in summoning [GET_CULT_DATA(entity_name, "their god")]!</FONT></span>")
else if(cult_team.sacrifices_required == NARSIE_HAS_FALLEN)
SSticker.mode_result = "cult draw - narsie died, nobody wins"
to_chat(world, "<span class='danger'> <FONT size = 3>Nobody wins! [SSticker.cultdat.entity_name] was summoned, but banished!</FONT></span>")
to_chat(world, "<span class='danger'> <FONT size = 3>Nobody wins! [GET_CULT_DATA(entity_name, "the cult god")] was summoned, but banished!</FONT></span>")
else
SSticker.mode_result = "cult loss - staff stopped the cult"
to_chat(world, "<span class='warning'> <FONT size = 3>The staff managed to stop the cult!</FONT></span>")
var/list/endtext = list()
endtext += "<br><b>The cultists' objectives were:</b>"
for(var/datum/objective/obj in cult_objs.presummon_objs)
endtext += "<br>[obj.explanation_text] - "
if(!obj.check_completion())
endtext += "<font color='red'>Fail.</font>"
else
endtext += "<font color='green'><B>Success!</B></font>"
if(cult_objs.cult_status >= NARSIE_NEEDS_SUMMONING)
endtext += "<br>[cult_objs.obj_summon.explanation_text] - "
if(!cult_objs.obj_summon.check_completion())
endtext+= "<font color='red'>Fail.</font>"
else
endtext += "<font color='green'><B>Success!</B></font>"
to_chat(world, endtext.Join(""))
..()
+40 -136
View File
@@ -1,123 +1,4 @@
/// Replace with team antag datum objectives from tg once ported
/datum/cult_objectives
var/cult_status = NARSIE_IS_ASLEEP
var/list/presummon_objs = list()
var/datum/objective/eldergod/obj_summon = new
var/sacrifices_done = 0
var/sacrifices_required = 2
/datum/cult_objectives/proc/setup()
if(cult_status != NARSIE_IS_ASLEEP)
return FALSE
cult_status = NARSIE_DEMANDS_SACRIFICE
var/datum/objective/sacrifice/obj_sac = new
if(obj_sac.find_target())
presummon_objs.Add(obj_sac)
else
ready_to_summon()
/datum/cult_objectives/proc/study(mob/living/M, display_members = FALSE) //Called by cultists/cult constructs checking their objectives
if(!M)
return FALSE
switch(cult_status)
if(NARSIE_IS_ASLEEP)
to_chat(M, "<span class='cult'>[SSticker.cultdat ? SSticker.cultdat.entity_name : "The Dark One"] is asleep.</span>")
if(NARSIE_DEMANDS_SACRIFICE)
if(!length(presummon_objs))
to_chat(M, "<span class='danger'>Error: No objectives in sacrifice list. Something went wrong. Oof.</span>")
else
var/datum/objective/sacrifice/current_obj = presummon_objs[length(presummon_objs)] //get the last obj in the list, ie the current one
to_chat(M, "<span class='cult'>The Veil needs to be weakened before we are able to summon [SSticker.cultdat ? SSticker.cultdat.entity_title1 : "The Dark One"].</span>")
to_chat(M, "<span class='cult'>Current goal: [current_obj.explanation_text]</span>")
if(NARSIE_NEEDS_SUMMONING)
to_chat(M, "<span class='cult'>The Veil is weak! We can summon [SSticker.cultdat ? SSticker.cultdat.entity_title3 : "The Dark One"]!</span>")
to_chat(M, "<span class='cult'>Current goal: [obj_summon.explanation_text]</span>")
if(NARSIE_HAS_RISEN)
to_chat(M, "<span class='cultlarge'>\"I am here.\"</span>")
to_chat(M, "<span class='cult'>Current goal:</span> <span class='cultlarge'>\"Feed me.\"</span>")
if(NARSIE_HAS_FALLEN)
to_chat(M, "<span class='cultlarge'>[SSticker.cultdat ? SSticker.cultdat.entity_name : "The Dark One"] has been banished!</span>")
to_chat(M, "<span class='cult'>Current goal: Slaughter the unbelievers!</span>")
else
to_chat(M, "<span class='danger'>Error: Cult objective status currently unknown. Something went wrong. Oof.</span>")
if(display_members)
var/list/cult = SSticker.mode.get_cultists(TRUE)
var/total_cult = cult[1] + cult[2]
var/rise = SSticker.mode.rise_number - total_cult
var/ascend = SSticker.mode.ascend_number - total_cult
var/overview = "<span class='cultitalic'><br><b>Current cult members: [total_cult]"
if(!SSticker.mode.cult_ascendant)
if(rise > 0)
overview += " | Conversions until Rise: [rise]"
else if(ascend > 0)
overview += " | Conversions until Ascension: [ascend]"
to_chat(M, "[overview]</b></span>")
if(cult[2]) // If there are any constructs, separate them out
to_chat(M, "<span class='cultitalic'><b>Cultists:</b> [cult[1]]")
to_chat(M, "<span class='cultitalic'><b>Constructs:</b> [cult[2]]")
/datum/cult_objectives/proc/current_sac_objective() //Return the current sacrifice objective datum, if any
if(cult_status == NARSIE_DEMANDS_SACRIFICE && length(presummon_objs))
var/datum/objective/sacrifice/current_obj = presummon_objs[length(presummon_objs)]
return current_obj
return FALSE
/datum/cult_objectives/proc/is_sac_target(datum/mind/mind)
if(cult_status != NARSIE_DEMANDS_SACRIFICE || !length(presummon_objs))
return FALSE
var/datum/objective/sacrifice/current_obj = presummon_objs[length(presummon_objs)]
if(current_obj.target == mind)
return TRUE
return FALSE
/datum/cult_objectives/proc/find_new_sacrifice_target(datum/mind/mind)
var/datum/objective/sacrifice/current_obj = presummon_objs[length(presummon_objs)]
if(current_obj.find_target())
for(var/datum/mind/cult_mind in SSticker.mode.cult)
if(cult_mind && cult_mind.current)
to_chat(cult_mind.current, "<span class='danger'>[SSticker.cultdat.entity_name]</span> murmurs, <span class='cultlarge'>Our goal is beyond your reach. Sacrifice [current_obj.target] instead...</span>")
return TRUE
return FALSE
/datum/cult_objectives/proc/succesful_sacrifice()
var/datum/objective/sacrifice/current_obj = presummon_objs[length(presummon_objs)]
current_obj.sacced = TRUE
sacrifices_done++
if(sacrifices_done >= sacrifices_required)
ready_to_summon()
else
var/datum/objective/sacrifice/obj_sac = new
if(obj_sac.find_target())
presummon_objs += obj_sac
for(var/datum/mind/cult_mind in SSticker.mode.cult)
if(cult_mind && cult_mind.current)
to_chat(cult_mind.current, "<span class='cult'>You and your acolytes have made progress, but there is more to do still before [SSticker.cultdat ? SSticker.cultdat.entity_title1 : "The Dark One"] can be summoned!</span>")
to_chat(cult_mind.current, "<span class='cult'>Current goal: [obj_sac.explanation_text]</span>")
else
ready_to_summon()
/datum/cult_objectives/proc/ready_to_summon()
cult_status = NARSIE_NEEDS_SUMMONING
for(var/datum/mind/cult_mind in SSticker.mode.cult)
if(cult_mind && cult_mind.current)
to_chat(cult_mind.current, "<span class='cult'>You and your acolytes have succeeded in preparing the station for the ultimate ritual!</span>")
to_chat(cult_mind.current, "<span class='cult'>Current goal: [obj_summon.explanation_text]</span>")
/datum/cult_objectives/proc/succesful_summon()
cult_status = NARSIE_HAS_RISEN
obj_summon.summoned = TRUE
/datum/cult_objectives/proc/narsie_death()
cult_status = NARSIE_HAS_FALLEN
obj_summon.killed = TRUE
//Objectives
// Objectives
/// Given to cultists on conversion/roundstart
/datum/objective/servecult
explanation_text = "Assist your fellow cultists and Tear the Veil! (Use the Study Veil action to check your progress.)"
@@ -131,26 +12,49 @@
/datum/objective/sacrifice/check_completion()
return sacced || completed
/datum/objective/sacrifice/find_target()
var/list/target_candidates = list()
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
/datum/objective/sacrifice/find_target(list/target_blacklist)
. = ..()
if(target && !(target in target_blacklist)) // check the blacklist, it wont update otherwise
return
//There are no living unconvertables on the station. Looking for a Sacrifice Target among the convertable minds
var/list/possible_targets = list()
for(var/datum/mind/possible_target in SSticker.minds)
if(possible_target in target_blacklist)
continue
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) // Same checks, but add them even if they could be converted
target_candidates += H.mind
if(length(target_candidates))
target = pick(target_candidates)
explanation_text = "Sacrifice [target], the [target.assigned_role] via invoking an Offer rune with [target.p_their()] body or brain on it and three acolytes around it."
var/mind_result = is_invalid_target(possible_target)
if(mind_result && mind_result != TARGET_INVALID_CULT_CONVERTABLE)
continue
possible_targets += possible_target
if(length(possible_targets))
target = pick(possible_targets)
update_explanation_text()
return TRUE
message_admins("Cult Sacrifice: Could not find unconvertible or convertible target. Nar'Sie summoning unlocked!")
return FALSE
/datum/objective/sacrifice/is_invalid_target(datum/mind/possible_target)
. = ..()
if(.)
return
if(possible_target.has_antag_datum(/datum/antagonist/cultist))
return TARGET_INVALID_CULTIST
if(!SSticker.mode.cult_team)
stack_trace("/datum/objective/sacrifice/is_invalid_target was called without there being an assigned cult team")
return
if(SSticker.mode.cult_team.is_convertable_to_cult(possible_target))
return TARGET_INVALID_CULT_CONVERTABLE
/datum/objective/sacrifice/update_explanation_text()
if(target?.current)
explanation_text = "Sacrifice [target], the [target.assigned_role] via invoking an Offer rune with [target.p_their()] body or brain on it and three acolytes around it."
else
// Code will reach here as part of find_target, but people should never be able to READ it.
explanation_text = "If you're reading this, something went very wrong. Contact an admin."
/datum/objective/eldergod
needs_target = FALSE
@@ -183,7 +87,7 @@
if(valid_spot)
summon_spots += summon
sanity++
explanation_text = "Summon [SSticker.cultdat ? SSticker.cultdat.entity_name : "your god"] by invoking the rune 'Tear Veil' with 9 cultists, constructs, or summoned ghosts on it.\
explanation_text = "Summon [GET_CULT_DATA(entity_name, "your god")] by invoking the rune 'Tear Veil' with 9 cultists, constructs, or summoned ghosts on it.\
\nThe summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin."
+11 -11
View File
@@ -48,25 +48,25 @@
/obj/structure/cult/functional/examine(mob/user)
. = ..()
if(iscultist(user) && cooldowntime > world.time)
if(IS_CULTIST(user) && cooldowntime > world.time)
. += "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [get_ETA()].</span>"
. += "<span class='notice'>[src] is [anchored ? "":"not "]secured to the floor.</span>"
/obj/structure/cult/functional/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user))
if(istype(I, /obj/item/melee/cultblade/dagger) && IS_CULTIST(user))
if(user.holy_check())
return
anchored = !anchored
to_chat(user, "<span class='notice'>You [anchored ? "":"un"]secure [src] [anchored ? "to":"from"] the floor.</span>")
if(!anchored)
icon_state = SSticker.cultdat?.get_icon("[initial(icon_state)]_off")
icon_state = GET_CULT_DATA(get_icon("[initial(icon_state)]_off"), "[initial(icon_state)]_off")
else
icon_state = SSticker.cultdat?.get_icon("[initial(icon_state)]")
icon_state = GET_CULT_DATA(get_icon(initial(icon_state)), initial(icon_state))
return
return ..()
/obj/structure/cult/functional/attack_hand(mob/living/user)
if(!iscultist(user))
if(!IS_CULTIST(user))
to_chat(user, "[heathen_message]")
return
if(invisibility)
@@ -150,7 +150,7 @@
/obj/structure/cult/functional/altar/Initialize(mapload)
. = ..()
icon_state = SSticker.cultdat?.altar_icon_state
icon_state = GET_CULT_DATA(altar_icon_state, "altar")
cooldowntime = world.time + CULT_STRUCTURE_COOLDOWN
/obj/structure/cult/functional/forge
@@ -170,7 +170,7 @@
/obj/structure/cult/functional/forge/get_choosable_items()
. = ..()
if(SSticker.cultdat.mirror_shields_active)
if(SSticker.mode.cult_team.mirror_shields_active)
// Both lines here are needed. If you do it without, youll get issues.
. += "Mirror Shield"
.["Mirror Shield"] = /obj/item/shield/mirror
@@ -178,7 +178,7 @@
/obj/structure/cult/functional/forge/Initialize(mapload)
. = ..()
icon_state = SSticker.cultdat?.forge_icon_state
icon_state = GET_CULT_DATA(forge_icon_state, "forge")
/obj/structure/cult/functional/forge/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/grab))
@@ -236,7 +236,7 @@ GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list(
/obj/structure/cult/functional/pylon/Initialize(mapload)
. = ..()
START_PROCESSING(SSobj, src)
icon_state = SSticker.cultdat?.pylon_icon_state
icon_state = GET_CULT_DATA(pylon_icon_state, "pylon")
/obj/structure/cult/functional/pylon/attack_hand(mob/living/user)//override as it should not create anything
return
@@ -260,7 +260,7 @@ GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list(
if(last_heal <= world.time)
last_heal = world.time + heal_delay
for(var/mob/living/L in range(5, src))
if(iscultist(L) || iswizard(L) || isshade(L) || isconstruct(L))
if(IS_CULTIST(L) || iswizard(L) || isshade(L) || isconstruct(L))
if(L.health != L.maxHealth)
new /obj/effect/temp_visual/heal(get_turf(src), COLOR_HEALING_GREEN)
@@ -322,7 +322,7 @@ GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list(
/obj/structure/cult/functional/archives/Initialize(mapload)
. = ..()
icon_state = SSticker.cultdat?.archives_icon_state
icon_state = GET_CULT_DATA(archives_icon_state, "archives")
/obj/effect/gateway
name = "gateway"
+16 -17
View File
@@ -22,19 +22,18 @@
/obj/item/melee/cultblade/dagger/New()
..()
if(SSticker.mode)
icon_state = SSticker.cultdat.dagger_icon
item_state = SSticker.cultdat.dagger_icon
icon_state = GET_CULT_DATA(dagger_icon, "blood_dagger")
item_state = GET_CULT_DATA(dagger_icon, "blood_dagger")
/obj/item/melee/cultblade/dagger/examine(mob/user)
. = ..()
if(iscultist(user) || user.stat == DEAD)
. += "<span class='cult'>A dagger gifted by [SSticker.cultdat.entity_title3]. Allows the scribing of runes and access to the knowledge archives of the cult of [SSticker.cultdat.entity_name].</span>"
if(IS_CULTIST(user) || user.stat == DEAD)
. += "<span class='cult'>A dagger gifted by [GET_CULT_DATA(entity_title3, "your god")]. Allows the scribing of runes and access to the knowledge archives of the cult of [GET_CULT_DATA(entity_name, "your god")].</span>"
. += "<span class='cultitalic'>Striking another cultist with it will purge holy water from them.</span>"
. += "<span class='cultitalic'>Striking a noncultist will tear their flesh, additionally, if you recently downed them with cult magic it will stun them completely.</span>"
/obj/item/melee/cultblade/dagger/attack(mob/living/M, mob/living/user)
if(iscultist(M))
if(IS_CULTIST(M))
if(M.reagents && M.reagents.has_reagent("holywater")) //allows cultists to be rescued from the clutches of ordained religion
if(M == user) // Targeting yourself
to_chat(user, "<span class='warning'>You can't remove holy water from yourself!</span>")
@@ -51,7 +50,7 @@
. = ..()
/obj/item/melee/cultblade/dagger/attack_self(mob/user)
if(!iscultist(user))
if(!IS_CULTIST(user))
to_chat(user, "<span class='warning'>[src] is covered in unintelligible shapes and markings.</span>")
return
scribe_rune(user)
@@ -59,26 +58,26 @@
/obj/item/melee/cultblade/dagger/proc/narsie_rune_check(mob/living/user, area/A)
var/datum/game_mode/gamemode = SSticker.mode
if(gamemode.cult_objs.cult_status < NARSIE_NEEDS_SUMMONING)
to_chat(user, "<span class='cultitalic'><b>[SSticker.cultdat.entity_name]</b> is not ready to be summoned yet!</span>")
if(gamemode.cult_team.cult_status < NARSIE_NEEDS_SUMMONING)
to_chat(user, "<span class='cultitalic'><b>[GET_CULT_DATA(entity_name, "Your god")]</b> is not ready to be summoned yet!</span>")
return FALSE
if(gamemode.cult_objs.cult_status == NARSIE_HAS_RISEN)
if(gamemode.cult_team.cult_status == NARSIE_HAS_RISEN)
to_chat(user, "<span class='cultlarge'>\"I am already here. There is no need to try to summon me now.\"</span>")
return FALSE
var/list/summon_areas = gamemode.cult_objs.obj_summon.summon_spots
var/list/summon_areas = gamemode.cult_team.obj_summon.summon_spots
if(!(A in summon_areas))
to_chat(user, "<span class='cultlarge'>[SSticker.cultdat.entity_name] can only be summoned where the veil is weak - in [english_list(summon_areas)]!</span>")
to_chat(user, "<span class='cultlarge'>[GET_CULT_DATA(entity_name, "Your god")] can only be summoned where the veil is weak - in [english_list(summon_areas)]!</span>")
return FALSE
var/confirm_final = tgui_alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence AND your location!",
"Are you prepared for the final battle?", list("My life for [SSticker.cultdat.entity_name]!", "No"))
"Are you prepared for the final battle?", list("My life for [GET_CULT_DATA(entity_name, "the cult")]!", "No"))
if(user)
if(confirm_final == "No" || confirm_final == null)
to_chat(user, "<span class='cultitalic'><b>You decide to prepare further before scribing the rune.</b></span>")
return FALSE
else
if(locate(/obj/effect/rune) in range(1, user))
to_chat(user, "<span class='cultlarge'>You need a space cleared of runes before you can summon [SSticker.cultdat.entity_title1]!</span>")
to_chat(user, "<span class='cultlarge'>You need a space cleared of runes before you can summon [GET_CULT_DATA(entity_title1, "your god")]!</span>")
return FALSE
else
return TRUE
@@ -150,7 +149,7 @@
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
var/list/summon_areas = gamemode.cult_team.obj_summon.summon_spots
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
@@ -170,7 +169,7 @@
else
others_message = "<span class='biggerdanger'>[user] cuts [user.p_their()] body and begins writing something particularly ominous in [user.p_their()] own blood!</span>"
user.visible_message(others_message,
"<span class='cultitalic'>You slice open your body and begin drawing a sigil of [SSticker.cultdat.entity_title3].</span>")
"<span class='cultitalic'>You slice open your body and begin drawing a sigil of [GET_CULT_DATA(entity_title3, "your god")].</span>")
drawing_rune = TRUE // Only one at a time
var/scribe_successful = do_after(user, initial(rune.scribe_delay) * scribe_multiplier, target = runeturf)
@@ -184,7 +183,7 @@
return
user.visible_message("<span class='warning'>[user] creates a strange circle in [user.p_their()] own blood.</span>",
"<span class='cultitalic'>You finish drawing the arcane markings of [SSticker.cultdat.entity_title3].</span>")
"<span class='cultitalic'>You finish drawing the arcane markings of [GET_CULT_DATA(entity_title3, "your god")].</span>")
var/obj/effect/rune/R = new rune(runeturf, keyword)
if(narsie_rune)
+73 -88
View File
@@ -68,7 +68,7 @@ To draw a rune, use a ritual dagger.
/obj/effect/rune/examine(mob/user)
. = ..()
if(iscultist(user) || user.stat == DEAD) //If they're a cultist or a ghost, tell them the effects
if(IS_CULTIST(user) || isobserver(user)) //If they're a cultist or a ghost, tell them the effects
. += "<b>Name:</b> [cultist_name]"
. += "<b>Effects:</b> [capitalize(cultist_desc)]"
. += "<b>Required Acolytes:</b> [req_cultists]"
@@ -76,7 +76,7 @@ To draw a rune, use a ritual dagger.
. += "<b>Keyword:</b> <span class='cultitalic'>[keyword]</span>"
/obj/effect/rune/attackby(obj/I, mob/user, params)
if(istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user))
if(istype(I, /obj/item/melee/cultblade/dagger) && IS_CULTIST(user))
// Telerunes with portals open
if(istype(src, /obj/effect/rune/teleport))
var/obj/effect/rune/teleport/T = src // Can't erase telerunes if they have a portal open
@@ -92,7 +92,7 @@ To draw a rune, use a ritual dagger.
qdel(src)
return
if(istype(I, /obj/item/nullrod))
if(iscultist(user))//cultist..what are doing..cultist..staph...
if(IS_CULTIST(user))//cultist..what are doing..cultist..staph...
user.drop_item()
user.visible_message("<span class='warning'>[I] suddenly glows with a white light, forcing [user] to drop it in pain!</span>", \
"<span class='danger'>[I] suddenly glows with a white light that sears your hand, forcing you to drop it!</span>") // TODO: Make this actually burn your hand
@@ -104,7 +104,7 @@ To draw a rune, use a ritual dagger.
/obj/effect/rune/attack_hand(mob/living/user)
user.Move_Pulled(src) // So that you can still drag things onto runes
if(!iscultist(user))
if(!IS_CULTIST(user))
to_chat(user, "<span class='warning'>You aren't able to understand the words of [src].</span>")
return
var/list/invokers = can_invoke(user)
@@ -115,7 +115,7 @@ To draw a rune, use a ritual dagger.
/obj/effect/rune/attack_animal(mob/living/simple_animal/M)
if(isshade(M) || isconstruct(M))
if(construct_invoke || !iscultist(M)) //if you're not a cult construct we want the normal fail message
if(construct_invoke || !IS_CULTIST(M)) //if you're not a cult construct we want the normal fail message
attack_hand(M)
else
to_chat(M, "<span class='warning'>You are unable to invoke the rune!</span>")
@@ -164,7 +164,7 @@ structure_check() searches for nearby cultist structures required for the invoca
// Get anyone nearby
if(req_cultists > 1 || allow_excess_invokers)
for(var/mob/living/L in range(1, src))
if(iscultist(L))
if(IS_CULTIST(L))
if(L == user)
continue
if(L.stat)
@@ -202,7 +202,7 @@ structure_check() searches for nearby cultist structures required for the invoca
L.apply_damage(invoke_damage, BRUTE)
to_chat(L, "<span class='cultitalic'>[src] saps your strength!</span>")
do_invoke_glow()
SSblackbox.record_feedback("nested tally", "runes_invoked", 1, list("[initial(cultist_name)]", "[length(SSticker.mode.cult)]")) // the name of the rune, and the number of cultists in the cult when it was invoked
SSblackbox.record_feedback("nested tally", "runes_invoked", 1, list("[initial(cultist_name)]", "[length(SSticker.mode.cult_team.members)]")) // the name of the rune, and the number of cultists in the cult when it was invoked
if(ghost_invokers)
SSblackbox.record_feedback("nested tally", "runes_invoked_with_ghost", 1, list("[initial(cultist_name)]", "[ghost_invokers]")) //the name of the rune and the number of ghosts used to invoke it.
@@ -214,7 +214,7 @@ structure_check() searches for nearby cultist structures required for the invoca
* * location - Location to teleport from
* * target - Location to teleport to
*/
/obj/effect/rune/proc/teleport_effect(mob/living/user, turf/location, target)
/obj/effect/rune/proc/teleport_effect(mob/living/user, turf/location, turf/target)
new /obj/effect/temp_visual/dir_setting/cult/phase/out(location, user.dir)
new /obj/effect/temp_visual/dir_setting/cult/phase(target, user.dir)
// So that the mob only appears after the effect is finished
@@ -236,15 +236,6 @@ structure_check() searches for nearby cultist structures required for the invoca
animate(src, color = rgb(255, 0, 0), time = 0)
animate(src, color = rune_blood_color, time = 5)
/obj/effect/rune/proc/check_icon()
if(!SSticker.mode)//work around for maps with runes and cultdat is not loaded all the way
var/bits = make_bit_triplet()
icon = get_rune(bits)
else
icon = get_rune_cult(invocation)
//Malformed Rune: This forms if a rune is not drawn correctly. Invoking it does nothing but hurt the user.
/obj/effect/rune/malformed
cultist_name = "Malformed"
@@ -256,7 +247,7 @@ structure_check() searches for nearby cultist structures required for the invoca
..()
for(var/M in invokers)
var/mob/living/L = M
to_chat(L, "<span class='cultitalic'><b>You feel your life force draining. [SSticker.cultdat.entity_title3] is displeased.</b></span>")
to_chat(L, "<span class='cultitalic'><b>You feel your life force draining. [GET_CULT_DATA(entity_title3, "Your god")] is displeased.</b></span>")
qdel(src)
/mob/proc/null_rod_check() //The null rod, if equipped, will protect the holder from the effects of most runes
@@ -282,7 +273,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/list/offer_targets = list()
var/turf/T = get_turf(src)
for(var/mob/living/M in T)
if(!iscultist(M) || (M.mind && is_sacrifice_target(M.mind)))
if(!IS_CULTIST(M) || (M.mind && IS_SACRIFICE_TARGET(M.mind)))
if(isconstruct(M)) // No offering constructs please
continue
offer_targets += M
@@ -300,7 +291,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/obj/item/organ/internal/brain/brain = O
b_mob = brain.brainmob
if(b_mob && b_mob.mind && (!iscultist(b_mob) || is_sacrifice_target(b_mob.mind)))
if(b_mob && b_mob.mind && (!IS_CULTIST(b_mob) || IS_SACRIFICE_TARGET(b_mob.mind)))
offer_targets += b_mob
if(!length(offer_targets))
@@ -318,7 +309,7 @@ structure_check() searches for nearby cultist structures required for the invoca
rune_in_use = FALSE
return
if(L.stat != DEAD && is_convertable_to_cult(L.mind))
if(L.stat != DEAD && SSticker.mode.cult_team.is_convertable_to_cult(L.mind))
..()
do_convert(L, invokers)
else
@@ -333,50 +324,49 @@ structure_check() searches for nearby cultist structures required for the invoca
for(var/I in invokers)
to_chat(I, "<span class='warning'>You need at least two invokers to convert!</span>")
return
else
convertee.visible_message("<span class='warning'>[convertee] writhes in pain as the markings below them glow a bloody red!</span>", \
"<span class='cultlarge'><i>AAAAAAAAAAAAAA-</i></span>")
SSticker.mode.add_cultist(convertee.mind)
convertee.mind.special_role = "Cultist"
to_chat(convertee, "<span class='cultitalic'><b>Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
convertee.visible_message("<span class='warning'>[convertee] writhes in pain as the markings below them glow a bloody red!</span>", \
"<span class='cultlarge'><i>AAAAAAAAAAAAAA-</i></span>")
convertee.mind.add_antag_datum(/datum/antagonist/cultist)
to_chat(convertee, "<span class='cultitalic'><b>Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
and something evil takes root.</b></span>")
to_chat(convertee, "<span class='cultitalic'><b>Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve [SSticker.cultdat.entity_title3] above all else. Bring it back.\
to_chat(convertee, "<span class='cultitalic'><b>Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve [GET_CULT_DATA(entity_title3, "your god")] above all else. Bring it back.\
</b></span>")
if(ishuman(convertee))
var/mob/living/carbon/human/H = convertee
var/brutedamage = convertee.getBruteLoss()
var/burndamage = convertee.getFireLoss()
if(brutedamage || burndamage) // If the convertee is injured
// Heal 90% of all damage, including robotic limbs
H.adjustBruteLoss(-(brutedamage * 0.9), robotic = TRUE)
H.adjustFireLoss(-(burndamage * 0.9), robotic = TRUE)
if(ismachineperson(H))
H.visible_message("<span class='warning'>A dark force repairs [convertee]!</span>",
"<span class='cultitalic'>Your damage has been repaired. Now spread the blood to others.</span>")
else
H.visible_message("<span class='warning'>[convertee]'s wounds heal and close!</span>",
"<span class='cultitalic'>Your wounds have been healed. Now spread the blood to others.</span>")
for(var/obj/item/organ/external/E in H.bodyparts)
E.mend_fracture()
E.fix_internal_bleeding()
E.fix_burn_wound()
for(var/datum/disease/critical/crit in H.viruses) // cure all crit conditions
crit.cure()
H.uncuff()
H.Silence(6 SECONDS) //Prevent "HALP MAINT CULT" before you realise you're converted
var/obj/item/melee/cultblade/dagger/D = new(get_turf(src))
if(H.equip_to_slot_if_possible(D, SLOT_HUD_IN_BACKPACK, FALSE, TRUE))
to_chat(H, "<span class='cultlarge'>You have a dagger in your backpack. Use it to do [SSticker.cultdat.entity_title1]'s bidding.</span>")
if(ishuman(convertee))
var/mob/living/carbon/human/H = convertee
var/brutedamage = convertee.getBruteLoss()
var/burndamage = convertee.getFireLoss()
if(brutedamage || burndamage) // If the convertee is injured
// Heal 90% of all damage, including robotic limbs
H.adjustBruteLoss(-(brutedamage * 0.9), robotic = TRUE)
H.adjustFireLoss(-(burndamage * 0.9), robotic = TRUE)
if(ismachineperson(H))
H.visible_message("<span class='warning'>A dark force repairs [convertee]!</span>",
"<span class='cultitalic'>Your damage has been repaired. Now spread the blood to others.</span>")
else
to_chat(H, "<span class='cultlarge'>There is a dagger on the floor. Use it to do [SSticker.cultdat.entity_title1]'s bidding.</span>")
H.visible_message("<span class='warning'>[convertee]'s wounds heal and close!</span>",
"<span class='cultitalic'>Your wounds have been healed. Now spread the blood to others.</span>")
for(var/obj/item/organ/external/E in H.bodyparts)
E.mend_fracture()
E.fix_internal_bleeding()
E.fix_burn_wound()
for(var/datum/disease/critical/crit in H.viruses) // cure all crit conditions
crit.cure()
H.uncuff()
H.Silence(6 SECONDS) //Prevent "HALP MAINT CULT" before you realise you're converted
var/obj/item/melee/cultblade/dagger/D = new(get_turf(src))
if(H.equip_to_slot_if_possible(D, SLOT_HUD_IN_BACKPACK, FALSE, TRUE))
to_chat(H, "<span class='cultlarge'>You have a dagger in your backpack. Use it to do [GET_CULT_DATA(entity_title1, "your god")]'s bidding.</span>")
else
to_chat(H, "<span class='cultlarge'>There is a dagger on the floor. Use it to do [GET_CULT_DATA(entity_title1, "your god")]'s bidding.</span>")
/obj/effect/rune/convert/proc/do_sacrifice(mob/living/offering, list/invokers)
var/mob/living/user = invokers[1] //the first invoker is always the user
if(offering.stat != DEAD || (offering.mind && is_sacrifice_target(offering.mind))) //Requires three people to sacrifice living targets/sacrifice objective
if(offering.stat != DEAD || (offering.mind && IS_SACRIFICE_TARGET(offering.mind))) //Requires three people to sacrifice living targets/sacrifice objective
if(length(invokers) < 3)
for(var/M in invokers)
to_chat(M, "<span class='cultitalic'>[offering] is too greatly linked to the world! You need three acolytes!</span>")
@@ -386,7 +376,6 @@ structure_check() searches for nearby cultist structures required for the invoca
var/sacrifice_fulfilled
var/worthless = FALSE
var/datum/game_mode/gamemode = SSticker.mode
if(isliving(offering) && !isbrain(offering))
var/mob/living/L = offering
@@ -398,7 +387,7 @@ structure_check() searches for nearby cultist structures required for the invoca
if(offering.mind)
GLOB.sacrificed += offering.mind
if(is_sacrifice_target(offering.mind))
if(IS_SACRIFICE_TARGET(offering.mind))
sacrifice_fulfilled = TRUE
else
GLOB.sacrificed += offering
@@ -407,9 +396,9 @@ structure_check() searches for nearby cultist structures required for the invoca
for(var/M in invokers)
if(sacrifice_fulfilled)
to_chat(M, "<span class='cultlarge'>\"Yes! This is the one I desire! You have done well.\"</span>")
if(!SSticker.cultdat.mirror_shields_active) // Only show once
if(!SSticker.mode.cult_team.mirror_shields_active) // Only show once
to_chat(M, "<span class='cultitalic'>You are now able to construct mirror shields inside the daemon forge.</span>")
SSticker.cultdat.mirror_shields_active = TRUE
SSticker.mode.cult_team.mirror_shields_active = TRUE
else
if(ishuman(offering) && offering.mind?.offstation_role && offering.mind.special_role != SPECIAL_ROLE_ERT) //If you try it on a ghost role, you get nothing
to_chat(M, "<span class='cultlarge'>\"This soul is of no use to either of us.\"</span>")
@@ -435,7 +424,7 @@ structure_check() searches for nearby cultist structures required for the invoca
offering.gib()
playsound(offering, 'sound/magic/disintegrate.ogg', 100, TRUE, SOUND_RANGE_SET(10))
if(sacrifice_fulfilled)
gamemode.cult_objs.succesful_sacrifice()
SSticker.mode.cult_team.successful_sacrifice()
return TRUE
/obj/effect/rune/teleport
@@ -592,7 +581,7 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/raise_dead/examine(mob/user)
. = ..()
if(iscultist(user) || user.stat == DEAD)
if(IS_CULTIST(user) || user.stat == DEAD)
. += "<b>Sacrifices unrewarded:</b><span class='cultitalic'> [length(GLOB.sacrificed) - sacrifices_used]</span>"
. += "<b>Sacrifice cost per ressurection:</b><span class='cultitalic> [SOULS_TO_REVIVE]</span>"
@@ -625,7 +614,7 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
return
for(var/mob/living/M in T.contents)
if(!iscultist(M))
if(!IS_CULTIST(M))
continue
potential_revive_mobs |= M
if(!length(potential_revive_mobs))
@@ -704,7 +693,7 @@ structure_check() searches for nearby cultist structures required for the invoca
..()
rune_in_use = FALSE
for(var/mob/living/M in range(0, src))
if(iscultist(M) && M.stat == DEAD)
if(IS_CULTIST(M) && M.stat == DEAD)
M.visible_message("<span class='warning'>[M] twitches.</span>")
//Rite of the Corporeal Shield: When invoked, becomes solid and cannot be passed. Invoke again to undo.
@@ -753,7 +742,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/mob/living/user = invokers[1]
var/list/cultists = list()
for(var/datum/mind/M in SSticker.mode.cult)
for(var/datum/mind/M in SSticker.mode.cult_team.members)
if(!(M.current in invokers) && M.current && M.current.stat != DEAD)
cultists[M.current.real_name] = M.current
var/input = tgui_input_list(user, "Who do you wish to call to [src]?", "Acolytes", cultists)
@@ -774,8 +763,8 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
log_game("Summon Cultist rune failed - target restrained")
return
if(!iscultist(cultist_to_summon))
to_chat(user, "<span class='cultitalic'>[cultist_to_summon] is not a follower of the [SSticker.cultdat.entity_title3]!</span>")
if(!IS_CULTIST(cultist_to_summon))
to_chat(user, "<span class='cultitalic'>[cultist_to_summon] is not a follower of [GET_CULT_DATA(entity_title3, "our god")]!</span>")
fail_invoke()
log_game("Summon Cultist rune failed - target was deconverted")
return
@@ -788,7 +777,7 @@ structure_check() searches for nearby cultist structures required for the invoca
cultist_to_summon.visible_message("<span class='warning'>[cultist_to_summon] suddenly disappears in a flash of red light!</span>", \
"<span class='cultitalic'><b>Overwhelming vertigo consumes you as you are hurled through the air!</b></span>")
..()
INVOKE_ASYNC(src, PROC_REF(teleport_effect), cultist_to_summon, get_turf(cultist_to_summon), src)
INVOKE_ASYNC(src, PROC_REF(teleport_effect), cultist_to_summon, get_turf(cultist_to_summon), get_turf(src))
visible_message("<span class='warning'>[src] begins to bubble and rises into the form of [cultist_to_summon]!</span>")
cultist_to_summon.forceMove(get_turf(src))
qdel(src)
@@ -822,7 +811,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/turf/T = get_turf(src)
var/list/targets = list()
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume && !ismachineperson(L))
if(!IS_CULTIST(L) && L.blood_volume && !ismachineperson(L))
var/atom/I = L.null_rod_check()
if(I)
if(isitem(I))
@@ -860,7 +849,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/multiplier = iteration / 2 // Iteration 1 = 0.5, Iteration 2 = 1, etc.
set_light(6, 1 * iteration, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume && !ismachineperson(L))
if(!IS_CULTIST(L) && L.blood_volume && !ismachineperson(L))
if(L.null_rod_check())
continue
L.take_overall_damage(0, tick_damage * multiplier)
@@ -876,7 +865,7 @@ structure_check() searches for nearby cultist structures required for the invoca
return FALSE
var/list/cultists = list()
for(var/mob/living/M in range(1, src)) // Get all cultists currently in range
if(iscultist(M) && !M.incapacitated())
if(IS_CULTIST(M) && !M.incapacitated())
cultists += M
if(length(cultists) < req_cultists) // Stop the rune there's not enough invokers
@@ -896,9 +885,9 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/manifest/examine(mob/user)
. = ..()
if(iscultist(user) || user.stat == DEAD)
if(IS_CULTIST(user) || user.stat == DEAD)
. += "<b>Amount of ghosts summoned:</b><span class='cultitalic'> [ghosts]</span>"
. += "<b>Maximum amount of ghosts:</b><span class='cultitalic'> [clamp(default_ghost_limit - SSticker.mode.cult_objs.sacrifices_done, minimum_ghost_limit, default_ghost_limit)]</span>"
. += "<b>Maximum amount of ghosts:</b><span class='cultitalic'> [clamp(default_ghost_limit - SSticker.mode.cult_team.sacrifices_done, minimum_ghost_limit, default_ghost_limit)]</span>"
. += "Lowers to a minimum of [minimum_ghost_limit] for each objective accomplished."
/obj/effect/rune/manifest/invoke(list/invokers)
@@ -928,7 +917,7 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
log_game("Manifest rune failed - not enough health")
return list()
if(ghosts >= clamp(default_ghost_limit - SSticker.mode.cult_objs.sacrifices_done, minimum_ghost_limit, default_ghost_limit))
if(ghosts >= clamp(default_ghost_limit - SSticker.mode.cult_team.sacrifices_done, minimum_ghost_limit, default_ghost_limit))
to_chat(user, "<span class='cultitalic'>You are sustaining too many ghosts to summon more!</span>")
fail_invoke()
log_game("Manifest rune failed - too many summoned ghosts")
@@ -945,7 +934,7 @@ structure_check() searches for nearby cultist structures required for the invoca
for(var/mob/dead/observer/O in T)
if(!O.client)
continue
if(iscultist(O) || jobban_isbanned(O, ROLE_CULTIST))
if(IS_CULTIST(O) || jobban_isbanned(O, ROLE_CULTIST))
continue
if(!HAS_TRAIT(O, TRAIT_RESPAWNABLE) || QDELETED(src) || QDELETED(O))
continue
@@ -974,8 +963,8 @@ structure_check() searches for nearby cultist structures required for the invoca
"<span class='cultitalic'>Your blood begins flowing into [src]. You must remain in place and conscious to maintain the forms of those summoned. This will hurt you slowly but surely...</span>")
var/obj/machinery/shield/cult/weak/shield = new(T)
SSticker.mode.add_cultist(new_human.mind, 0)
to_chat(new_human, "<span class='cultlarge'>You are a servant of the [SSticker.cultdat.entity_title3]. You have been made semi-corporeal by the cult of [SSticker.cultdat.entity_name], and you are to serve them at all costs.</span>")
new_human.mind.add_antag_datum(/datum/antagonist/cultist)
to_chat(new_human, "<span class='cultlarge'>You are a servant of [GET_CULT_DATA(entity_title3, "the cult")]. You have been made semi-corporeal by the cult of [GET_CULT_DATA(entity_name, "your god")], and you are to serve them at all costs.</span>")
while(!QDELETED(src) && !QDELETED(user) && !QDELETED(new_human) && (user in T))
if(new_human.InCritical())
@@ -999,7 +988,7 @@ structure_check() searches for nearby cultist structures required for the invoca
"<span class='cultlarge'>Your link to the world fades. Your form breaks apart.</span>")
for(var/obj/item/I in new_human.get_all_slots())
new_human.unEquip(I)
SSticker.mode.remove_cultist(new_human.mind, FALSE)
new_human.mind.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE)
new_human.dust()
/obj/effect/rune/manifest/proc/ghostify(mob/living/user, turf/T)
@@ -1054,11 +1043,8 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/narsie/New()
..()
cultist_name = "Summon [SSticker.cultdat ? SSticker.cultdat.entity_name : "your god"]"
cultist_desc = "tears apart dimensional barriers, calling forth [SSticker.cultdat ? SSticker.cultdat.entity_title3 : "your god"]."
/obj/effect/rune/narsie/check_icon()
return
cultist_name = "Summon [GET_CULT_DATA(entity_name, "your god")]"
cultist_desc = "tears apart dimensional barriers, calling forth [GET_CULT_DATA(entity_title3, "your god")]."
/obj/effect/rune/narsie/cult_conceal() //can't hide this, and you wouldn't want to
return
@@ -1070,19 +1056,18 @@ structure_check() searches for nearby cultist structures required for the invoca
if(used)
return
var/mob/living/user = invokers[1]
var/datum/game_mode/gamemode = SSticker.mode
if(!is_station_level(user.z))
message_admins("[key_name_admin(user)] tried to summon an eldritch horror off station")
log_game("Summon Nar'Sie rune failed - off station Z level")
return
if(gamemode.cult_objs.cult_status == NARSIE_HAS_RISEN)
if(SSticker.mode.cult_team.cult_status == NARSIE_HAS_RISEN)
for(var/M in invokers)
to_chat(M, "<span class='cultlarge'>\"I am already here. There is no need to try to summon me now.\"</span>")
log_game("Summon god rune failed - already summoned")
return
//BEGIN THE SUMMONING
gamemode.cult_objs.succesful_summon()
SSticker.mode.cult_team.successful_summon()
used = TRUE
color = COLOR_RED
..()
@@ -1098,7 +1083,7 @@ structure_check() searches for nearby cultist structures required for the invoca
new /obj/singularity/narsie/large(T) //Causes Nar'Sie to spawn even if the rune has been removed
/obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal.
if((istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user)))
if((istype(I, /obj/item/melee/cultblade/dagger) && IS_CULTIST(user)))
log_game("Summon Narsie rune erased by [key_name(user)] with a cult dagger")
message_admins("[key_name_admin(user)] erased a Narsie rune with a cult dagger")
if(istype(I, /obj/item/nullrod)) //Begone foul magiks. You cannot hinder me.
-1
View File
@@ -20,7 +20,6 @@
var/probability = 0
var/station_was_nuked = FALSE //see nuclearbomb.dm and malfunction.dm
var/explosion_in_progress = FALSE //sit back and relax
var/list/datum/mind/modePlayer = new
var/list/restricted_jobs = list() // Jobs it doesn't make sense to be. I.E chaplain or AI cultist
var/list/secondary_restricted_jobs = list() // Same as above, but for secondary antagonists
var/list/protected_jobs = list() // Jobs that can't be traitors
@@ -117,7 +117,7 @@
return new /datum/spell_targeting/alive_mob_list
/obj/effect/proc_holder/spell/sense_victims/valid_target(mob/living/target, user)
return target.stat == CONSCIOUS && target.key && !iscultist(target) // Only conscious, non cultist players
return target.stat == CONSCIOUS && target.key && !IS_CULTIST(target) // Only conscious, non cultist players
/obj/effect/proc_holder/spell/sense_victims/cast(list/targets, mob/user)
var/mob/living/victim = targets[1]
@@ -152,7 +152,7 @@
S.mind.assigned_role = "Harbinger of the Slaughter"
S.mind.special_role = "Harbinger of the Slaughter"
to_chat(S, playstyle_string)
SSticker.mode.add_cultist(S.mind)
S.mind.add_antag_datum(/datum/antagonist/cultist)
var/obj/effect/proc_holder/spell/sense_victims/SV = new
AddSpell(SV)
+5 -29
View File
@@ -1,6 +1,3 @@
// then call SSticker.mode.add_revolutionary(_THE_PLAYERS_MIND_)
// nothing else needs to be done, as that proc will check if they are a valid target.
// Just make sure the converter is a head before you call it!
// To remove a rev (from brainwashing or w/e), call SSticker.mode.remove_revolutionary(_THE_PLAYERS_MIND_),
// this will also check they're not a head, so it can just be called freely
@@ -41,7 +38,7 @@
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
restricted_jobs |= protected_jobs
for(var/i = 1 to REVOLUTION_MAX_HEADREVS)
for(var/i in 1 to REVOLUTION_MAX_HEADREVS)
if(!length(possible_revolutionaries))
break
var/datum/mind/new_headrev = pick_n_take(possible_revolutionaries)
@@ -56,14 +53,13 @@
/datum/game_mode/revolution/post_setup()
rev_team = new /datum/team/revolution()
get_rev_team()
for(var/i in 1 to rev_team.need_another_headrev(1)) // yes this is a ONE, not a true
if(!length(pre_revolutionaries))
break
var/datum/mind/new_headrev = pick_n_take(pre_revolutionaries)
new_headrev.add_antag_datum(/datum/antagonist/rev/head)
rev_team.add_member(new_headrev)
..()
@@ -81,7 +77,7 @@
/datum/game_mode/proc/get_rev_team()
if(!rev_team)
rev_team = new /datum/team/revolution()
new /datum/team/revolution() // assignment happens in create_team()
return rev_team
//////////////////////////////////////
@@ -109,25 +105,6 @@
return TRUE
return ..()
///////////////////////////////////////////////////
//Deals with converting players to the revolution//
///////////////////////////////////////////////////
/datum/game_mode/proc/add_revolutionary(datum/mind/rev_mind)
var/mob/living/carbon/human/conversion_target = rev_mind.current
if(rev_mind.assigned_role in GLOB.command_positions)
return FALSE
if(ismindshielded(conversion_target))
return FALSE
if(rev_mind.has_antag_datum(/datum/antagonist/rev))
return FALSE
if(!conversion_target)
return FALSE
rev_team.add_member(rev_mind)
conversion_target.Silence(10 SECONDS)
conversion_target.Stun(10 SECONDS)
return TRUE
//////////////////////////////////////////////////////////////////////////////
//Deals with players being converted from the revolution (Not a rev anymore)// // Modified to handle borged MMIs. Accepts another var if the target is being borged at the time -- Polymorph.
//////////////////////////////////////////////////////////////////////////////
@@ -136,9 +113,8 @@
var/remove_head = (beingborged && rev_mind.has_antag_datum(/datum/antagonist/rev/head))
if(rev_mind.has_antag_datum(/datum/antagonist/rev, FALSE) || remove_head)
var/datum/antagonist/rev = rev_mind.has_antag_datum(/datum/antagonist/rev)
rev.silent = TRUE // We have some custom text, lets make the removal silent
rev_team.remove_member(rev_mind)
// We have some custom text, lets make the removal silent
rev_mind.remove_antag_datum(/datum/antagonist/rev, silent_removal = TRUE)
if(beingborged)
revolutionary.visible_message(
-14
View File
@@ -130,17 +130,3 @@
GLOB.assigned_mutation_blocks[block] = mutation
//testing("DNA2: [numsToAssign.len] blocks are unused: [english_list(numsToAssign)]")
/proc/setupcult()
var/static/datum/cult_info/picked_cult // Only needs to get picked once
if(picked_cult)
return picked_cult
var/random_cult = pick(typesof(/datum/cult_info))
picked_cult = new random_cult()
if(!picked_cult)
stack_trace("Cult datum creation failed")
//todo:add adminonly datum var, check for said var here...
return picked_cult
+25 -28
View File
@@ -35,10 +35,10 @@
held_body = null
/obj/item/soulstone/proc/can_use(mob/living/user)
if(iscultist(user) && purified && !iswizard(user))
if(IS_CULTIST(user) && purified && !iswizard(user))
return FALSE
if(iscultist(user) || iswizard(user) || (HAS_MIND_TRAIT(user, TRAIT_HOLY) && purified) || usability)
if(IS_CULTIST(user) || iswizard(user) || (HAS_MIND_TRAIT(user, TRAIT_HOLY) && purified) || usability)
return TRUE
return FALSE
@@ -66,7 +66,7 @@
/obj/item/soulstone/pickup(mob/living/user)
. = ..()
if(iscultist(user) && purified && !iswizard(user))
if(IS_CULTIST(user) && purified && !iswizard(user))
to_chat(user, "<span class='danger'>[src] reeks of holy magic. You will need to cleanse it with a ritual dagger before anything can be done with it.</span>")
return
if(HAS_MIND_TRAIT(user, TRAIT_HOLY))
@@ -120,7 +120,7 @@
to_chat(user, "<span class='warning'>A mysterious force prevents you from trapping this being's soul.</span>")
return ..()
if(iscultist(user) && iscultist(M))
if(IS_CULTIST(user) && IS_CULTIST(M))
to_chat(user, "<span class='cultlarge'>\"Come now, do not capture your fellow's soul.\"</span>")
return ..()
@@ -178,7 +178,7 @@
return
/obj/item/soulstone/attackby(obj/item/O, mob/user)
if(istype(O, /obj/item/storage/bible) && !iscultist(user) && HAS_MIND_TRAIT(user, TRAIT_HOLY))
if(istype(O, /obj/item/storage/bible) && !IS_CULTIST(user) && HAS_MIND_TRAIT(user, TRAIT_HOLY))
if(purified)
return
to_chat(user, "<span class='notice'>You begin to exorcise [src].</span>")
@@ -193,9 +193,9 @@
for(var/mob/M in contents)
if(M.mind)
icon_state = "purified_soulstone2"
if(iscultist(M))
SSticker.mode.remove_cultist(M.mind, FALSE)
to_chat(M, "<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of [SSticker.cultdat ? SSticker.cultdat.entity_title1 : "Nar'Sie"] \
if(IS_CULTIST(M))
M.mind.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE)
to_chat(M, "<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of [GET_CULT_DATA(entity_title1, "Nar'Sie")] \
and the memories of your time as their servant with it.</span>")
to_chat(M, "<span class='danger'>Assist [user], your saviour, and get vengeance on those who enslaved you!</span>")
else
@@ -206,7 +206,7 @@
EX.icon_state = "shade_angelic"
user.visible_message("<span class='notice'>[user] purifies [src]!</span>", "<span class='notice'>You purify [src]!</span>")
else if(istype(O, /obj/item/melee/cultblade/dagger) && iscultist(user))
else if(istype(O, /obj/item/melee/cultblade/dagger) && IS_CULTIST(user))
if(!purified)
return
to_chat(user, "<span class='notice'>You begin to cleanse [src] of holy magic.</span>")
@@ -220,11 +220,11 @@
for(var/mob/M in contents)
if(M.mind)
icon_state = "soulstone2"
SSticker.mode.add_cultist(M.mind)
M.mind.add_antag_datum(/datum/antagonist/cultist)
to_chat(M, "<span class='cult'>Your shard has been cleansed of holy magic, and you are now bound to the cult's will. Obey them and assist in their goals.</span>")
for(var/mob/living/simple_animal/shade/EX in src)
EX.holy = FALSE
EX.icon_state = SSticker.cultdat?.shade_icon_state
EX.icon_state = GET_CULT_DATA(shade_icon_state, "shade")
to_chat(user, "<span class='notice'>You have cleansed [src] of holy magic.</span>")
else
..()
@@ -254,7 +254,7 @@
B.brainmob.key = S.key
S.cancel_camera()
held_body.forceMove(get_turf(src))
SSticker.mode.add_cult_immunity(held_body)
SSticker.mode?.cult_team?.add_cult_immunity(held_body)
remove_held_body()
new /obj/effect/temp_visual/cult/sparks(get_turf(src))
playsound(src, 'sound/effects/pylon_shatter.ogg', 40, TRUE)
@@ -269,7 +269,7 @@
else
icon_state = "soulstone"
name = initial(name)
if(iscultist(A))
if(IS_CULTIST(A))
to_chat(A, "<span class='userdanger'>You have been released from your prison, but you are still bound to the cult's will. Help them succeed in their goals at all costs.</span>")
else
to_chat(A, "<span class='userdanger'>You have been released from your prison, but you are still bound to your [purified ? "saviour" : "creator"]'s will.</span>")
@@ -288,7 +288,7 @@
/obj/structure/constructshell/examine(mob/user)
. = ..()
if(in_range(user, src) && (iscultist(user) || iswizard(user) || user.stat == DEAD))
if(in_range(user, src) && (IS_CULTIST(user) || iswizard(user) || user.stat == DEAD))
. += "<span class='cult'>A construct shell, used to house bound souls from a soulstone.</span>"
. += "<span class='cult'>Placing a soulstone with a soul into this shell allows you to produce your choice of the following:</span>"
. += "<span class='cultitalic'>An <b>Artificer</b>, which can produce <b>more shells and soulstones</b>, as well as fortifications.</span>"
@@ -349,7 +349,7 @@
return
if(T.stat == DEAD)
to_chat(user, "<span class='danger'>Capture failed!</span> The shade has already been banished!")
if((iscultist(T) && purified) || (T.holy && !purified))
if((IS_CULTIST(T) && purified) || (T.holy && !purified))
to_chat(user, "<span class='danger'>Capture failed!</span> The shade recoils away from [src]!")
else
if(locate(/mob/living/simple_animal/shade) in contents)
@@ -370,9 +370,9 @@
"Wraith" = /mob/living/simple_animal/hostile/construct/wraith,
"Artificer" = /mob/living/simple_animal/hostile/construct/builder)
/// Custom construct icons for different cults
var/list/construct_icons = list("Juggernaut" = image(icon = 'icons/mob/cult.dmi', icon_state = SSticker.cultdat.get_icon("juggernaut")),
"Wraith" = image(icon = 'icons/mob/cult.dmi', icon_state = SSticker.cultdat.get_icon("wraith")),
"Artificer" = image(icon = 'icons/mob/cult.dmi', icon_state = SSticker.cultdat.get_icon("builder")))
var/list/construct_icons = list("Juggernaut" = image(icon = 'icons/mob/cult.dmi', icon_state = GET_CULT_DATA(get_icon("juggernaut"), "behemoth")),
"Wraith" = image(icon = 'icons/mob/cult.dmi', icon_state = GET_CULT_DATA(get_icon("wraith"), "floating")),
"Artificer" = image(icon = 'icons/mob/cult.dmi', icon_state = GET_CULT_DATA(get_icon("builder"), "artificer")))
if(shade)
var/construct_choice = show_radial_menu(user, shell, construct_icons, custom_check = CALLBACK(src, PROC_REF(radial_check), user), require_near = TRUE)
@@ -404,12 +404,12 @@
RemoveSpell(/obj/effect/proc_holder/spell/aoe/conjure/build/soulstone)
AddSpell(new /obj/effect/proc_holder/spell/aoe/conjure/build/soulstone/holy)
else if(iscultist(src)) // Re-grant cult actions, lost in the transfer
else if(mind.has_antag_datum(/datum/antagonist/cultist)) // Re-grant cult actions, lost in the transfer
var/datum/action/innate/cult/comm/CC = new
var/datum/action/innate/cult/check_progress/D = new
CC.Grant(src)
D.Grant(src)
SSticker.mode.cult_objs.study(src) // Display objectives again
SSticker.mode.cult_team.study_objectives(src) // Display objectives again
to_chat(src, "<span class='userdanger'>You are still bound to serve the cult, follow their orders and help them complete their goals at all costs.</span>")
else
to_chat(src, "<span class='userdanger'>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</span>")
@@ -429,10 +429,9 @@
new /obj/effect/particle_effect/smoke/sleeping(target.loc)
C.faction |= "\ref[user]"
C.key = target.key
if(user && iscultist(user) || cult_override)
SSticker.mode.add_cultist(C.mind)
SSticker.mode.update_cult_icons_added(C.mind)
if(user && iscultist(user))
if(user && IS_CULTIST(user) || cult_override)
C.mind.add_antag_datum(/datum/antagonist/cultist)
if(user && IS_CULTIST(user))
to_chat(C, "<B>You are still bound to serve the cult, follow their orders and help them complete their goals at all costs.</B>")
else
to_chat(C, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>")
@@ -454,10 +453,8 @@
if(iswizard(user))
SSticker.mode.update_wiz_icons_added(S.mind)
S.mind.special_role = SPECIAL_ROLE_WIZARD_APPRENTICE
if(iscultist(user))
SSticker.mode.add_cultist(S.mind)
S.mind.special_role = SPECIAL_ROLE_CULTIST
S.mind.store_memory("<b>Serve the cult's will.</b>")
if(IS_CULTIST(user))
S.mind.add_antag_datum(/datum/antagonist/cultist)
to_chat(S, "<span class='userdanger'>Your soul has been captured! You are now bound to the cult's will. Help them succeed in their goals at all costs.</span>")
else
S.mind.store_memory("<b>Serve [user.real_name], your creator.</b>")
-1
View File
@@ -28,7 +28,6 @@
var/datum/mind/wizard = pick(possible_wizards)
wizards += wizard
modePlayer += wizard
wizard.assigned_role = SPECIAL_ROLE_WIZARD //So they aren't chosen for other jobs.
wizard.special_role = SPECIAL_ROLE_WIZARD
wizard.set_original_mob(wizard.current)
+1 -1
View File
@@ -174,7 +174,7 @@
GLOB.empty_playable_ai_cores += D
else
if(brain.brainmob.mind)
SSticker.mode.remove_cultist(brain.brainmob.mind, 1)
brain.brainmob.mind.remove_antag_datum(/datum/antagonist/cultist)
SSticker.mode.remove_revolutionary(brain.brainmob.mind, 1)
var/mob/living/silicon/ai/A = new /mob/living/silicon/ai(loc, laws, brain)
+2 -3
View File
@@ -354,9 +354,8 @@
I.forceMove(loc)
// Find a new sacrifice target if needed, if unable allow summoning
if(is_sacrifice_target(occupant.mind))
if(!SSticker.mode.cult_objs.find_new_sacrifice_target())
SSticker.mode.cult_objs.ready_to_summon()
if(IS_SACRIFICE_TARGET(occupant.mind))
SSticker.mode.cult_team.find_new_sacrifice_target()
//Update any existing objectives involving this mob.
if(occupant.mind)
+8 -8
View File
@@ -505,18 +505,18 @@
/obj/machinery/door/airlock/cult/Initialize()
. = ..()
icon = SSticker.cultdat?.airlock_runed_icon_file
overlays_file = SSticker.cultdat?.airlock_runed_overlays_file
icon = GET_CULT_DATA(airlock_runed_icon_file, initial(icon))
overlays_file = GET_CULT_DATA(airlock_runed_overlays_file, initial(overlays_file))
update_icon()
new openingoverlaytype(loc)
/obj/machinery/door/airlock/cult/canAIControl(mob/user)
return (iscultist(user) && !isAllPowerLoss())
return (IS_CULTIST(user) && !isAllPowerLoss())
/obj/machinery/door/airlock/cult/allowed(mob/living/L)
if(!density)
return TRUE
if(friendly || iscultist(L) || isshade(L)|| isconstruct(L))
if(friendly || IS_CULTIST(L) || isshade(L) || isconstruct(L))
if(!stealthy)
new openingoverlaytype(loc)
return TRUE
@@ -545,8 +545,8 @@
update_icon()
/obj/machinery/door/airlock/cult/cult_reveal()
icon = SSticker.cultdat?.airlock_runed_icon_file
overlays_file = SSticker.cultdat?.airlock_runed_overlays_file
icon = GET_CULT_DATA(airlock_runed_icon_file, initial(icon))
overlays_file = GET_CULT_DATA(airlock_runed_overlays_file, initial(overlays_file))
opacity = initial(opacity)
glass = initial(glass)
airlock_material = initial(airlock_material)
@@ -583,8 +583,8 @@
/obj/machinery/door/airlock/cult/unruned/Initialize()
. = ..()
icon = SSticker.cultdat?.airlock_unruned_icon_file
overlays_file = SSticker.cultdat?.airlock_unruned_overlays_file
icon = GET_CULT_DATA(airlock_unruned_icon_file, initial(icon))
overlays_file = GET_CULT_DATA(airlock_unruned_overlays_file, initial(overlays_file))
update_icon()
/obj/machinery/door/airlock/cult/unruned/friendly
+1 -1
View File
@@ -97,7 +97,7 @@
parent_rune.attack_hand(user)
/obj/machinery/shield/cult/barrier/attack_animal(mob/living/simple_animal/user)
if(iscultist(user))
if(IS_CULTIST(user))
parent_rune.attack_animal(user)
else
..()
-95
View File
@@ -1,95 +0,0 @@
/proc/get_rune_cult(word)
var/animated
if(word && !(SSticker.cultdat.theme == "fire" || SSticker.cultdat.theme == "death"))
animated = 1
else
animated = 0
var/bits = make_bit_triplet()
return get_rune(bits, animated)
GLOBAL_LIST_EMPTY(cult_rune_cache)
GLOBAL_VAR_INIT(cult_rune_style, "rune") // Style of run the cult is using (fire, death, regular, etc)
/proc/get_rune(symbol_bits, animated = 0)
var/lookup = "[symbol_bits]-[animated]"
if(!SSticker.mode)//work around for maps with runes and cultdat is not loaded all the way
GLOB.cult_rune_style = "rune"
else if(SSticker.cultdat.theme == "fire")
GLOB.cult_rune_style = "fire-rune"
else if(SSticker.cultdat.theme == "death")
GLOB.cult_rune_style = "death-rune"
if(lookup in GLOB.cult_rune_cache)
return GLOB.cult_rune_cache[lookup]
var/icon/I = icon('icons/effects/uristrunes.dmi', "[GLOB.cult_rune_style]-179")
for(var/i = 0, i < 10, i++)
if(symbol_bits & (1 << i))
I.Blend(icon('icons/effects/uristrunes.dmi', "[GLOB.cult_rune_style]-[1 << i]"), ICON_OVERLAY)
I.SwapColor(rgb(0, 0, 0, 100), rgb(100, 0, 0, 200))//TO DO COMMENT:NEED TO ADJUST FOR DIFFRNET CULTS
I.SwapColor(rgb(0, 0, 0, 50), rgb(150, 0, 0, 200))
for(var/x = 1, x <= 32, x++)
for(var/y = 1, y <= 32, y++)
var/p = I.GetPixel(x, y)
if(p == null)
var/n = I.GetPixel(x, y + 1)
var/s = I.GetPixel(x, y - 1)
var/e = I.GetPixel(x + 1, y)
var/w = I.GetPixel(x - 1, y)
if(n == "#000000" || s == "#000000" || e == "#000000" || w == "#000000")
I.DrawBox(rgb(200, 0, 0, 200), x, y)
else
var/ne = I.GetPixel(x + 1, y + 1)
var/se = I.GetPixel(x + 1, y - 1)
var/nw = I.GetPixel(x - 1, y + 1)
var/sw = I.GetPixel(x - 1, y - 1)
if(ne == "#000000" || se == "#000000" || nw == "#000000" || sw == "#000000")
I.DrawBox(rgb(200, 0, 0, 100), x, y)
var/icon/result = icon(I, "")
result.Insert(I, "", frame = 1, delay = 10)
if(animated == 1)
var/icon/I2 = icon(I, "")
I2.MapColors(rgb(0xff,0x0c,0,0), rgb(0,0,0,0), rgb(0,0,0,0), rgb(0,0,0,0xff))
I2.SetIntensity(1.04)
var/icon/I3 = icon(I, "")
I3.MapColors(rgb(0xff,0x18,0,0), rgb(0,0,0,0), rgb(0,0,0,0), rgb(0,0,0,0xff))
I3.SetIntensity(1.08)
var/icon/I4 = icon(I, "")
I4.MapColors(rgb(0xff,0x24,0,0), rgb(0,0,0,0), rgb(0,0,0,0), rgb(0,0,0,0xff))
I4.SetIntensity(1.12)
var/icon/I5 = icon(I, "")
I5.MapColors(rgb(0xff,0x30,0,0), rgb(0,0,0,0), rgb(0,0,0,0), rgb(0,0,0,0xff))
I5.SetIntensity(1.16)
result.Insert(I2, "", frame = 2, delay = 4)
result.Insert(I3, "", frame = 3, delay = 3)
result.Insert(I4, "", frame = 4, delay = 2)
result.Insert(I5, "", frame = 5, delay = 6)
result.Insert(I4, "", frame = 6, delay = 2)
result.Insert(I3, "", frame = 7, delay = 2)
result.Insert(I2, "", frame = 8, delay = 2)
GLOB.cult_rune_cache[lookup] = result
return result
@@ -80,14 +80,14 @@
/obj/effect/temp_visual/dir_setting/wraith/Initialize(mapload)
. = ..()
icon_state = SSticker.cultdat?.wraith_jaunt_in_animation
icon_state = GET_CULT_DATA(wraith_jaunt_in_animation, initial(icon_state))
/obj/effect/temp_visual/dir_setting/wraith/out
icon_state = "phase_shift"
/obj/effect/temp_visual/dir_setting/wraith/out/Initialize(mapload)
. = ..()
icon_state = SSticker.cultdat?.wraith_jaunt_out_animation
icon_state = GET_CULT_DATA(wraith_jaunt_out_animation, initial(icon_state))
/obj/effect/temp_visual/dir_setting/tailsweep
icon_state = "tailsweep"
+1 -1
View File
@@ -31,7 +31,7 @@
for(var/mob/M in range(heavy_range, epicenter))
SEND_SOUND(M, emp_sound)
for(var/atom/T in range(light_range, epicenter))
if(cause == "cult" && iscultist(T))
if(cause == "cult" && IS_CULTIST(T))
continue
var/distance = get_dist(epicenter, T)
var/will_affect = FALSE
+17 -1
View File
@@ -180,11 +180,27 @@
return
if(M.stat != CONSCIOUS)
to_chat(user, "<span class='warning'>They must be conscious before you can convert [M.p_them()]!</span>")
else if(SSticker.mode.add_revolutionary(M.mind))
else if(add_revolutionary(M.mind))
times_used-- //Flashes less likely to burn out for headrevs when used for conversion
else
to_chat(user, "<span class='warning'>This mind seems resistant to [src]!</span>")
/obj/item/flash/proc/add_revolutionary(datum/mind/converting_mind)
var/mob/living/carbon/human/conversion_target = converting_mind.current
if(converting_mind.assigned_role in GLOB.command_positions)
return FALSE
if(!istype(conversion_target))
return FALSE
if(ismindshielded(conversion_target))
return FALSE
if(converting_mind.has_antag_datum(/datum/antagonist/rev))
return FALSE
converting_mind.add_antag_datum(/datum/antagonist/rev)
conversion_target.Silence(10 SECONDS)
conversion_target.Stun(10 SECONDS)
return TRUE
/obj/item/flash/cyborg
origin_tech = null
@@ -493,11 +493,11 @@ GLOBAL_LIST_INIT(cult_recipes, list (
/obj/item/stack/sheet/runed_metal/New()
. = ..()
icon_state = SSticker.cultdat?.runed_metal_icon_state
item_state = SSticker.cultdat?.runed_metal_item_state
icon_state = GET_CULT_DATA(runed_metal_icon_state, initial(icon_state))
item_state = GET_CULT_DATA(runed_metal_item_state, initial(item_state))
/obj/item/stack/sheet/runed_metal/attack_self(mob/living/user)
if(!iscultist(user))
if(!IS_CULTIST(user))
to_chat(user, "<span class='warning'>Only one with forbidden knowledge could hope to work this metal...</span>")
return
if(usr.holy_check())
@@ -19,7 +19,7 @@
if(target.mind)
if(target.mind.has_antag_datum(/datum/antagonist/rev))
SSticker.mode.remove_revolutionary(target.mind)
if(target.mind in SSticker.mode.cult)
if(IS_CULTIST(target))
to_chat(target, "<span class='warning'>You feel the corporate tendrils of Nanotrasen try to invade your mind!</span>")
return TRUE
@@ -561,8 +561,10 @@
var/mob/living/carbon/human/target = M
if(target.mind)
if(iscultist(target))
SSticker.mode.remove_cultist(target.mind, TRUE, TRUE) // This proc will handle message generation.
if(IS_CULTIST(target))
var/datum/antagonist/cultist/cultist = IS_CULTIST(target)
cultist.remove_gear_on_removal = TRUE
target.mind.remove_antag_datum(/datum/antagonist/cultist)
praying = FALSE
return
var/datum/antagonist/vampire/V = M.mind?.has_antag_datum(/datum/antagonist/vampire)
@@ -156,7 +156,7 @@
/obj/item/melee/spellblade/examine(mob/user)
. = ..()
if(enchant && (iswizard(user) || iscultist(user))) // only wizards and cultists understand runes
if(enchant && (iswizard(user) || IS_CULTIST(user))) // only wizards and cultists understand runes
. += "The runes along the side read; [enchant.desc]."
@@ -170,8 +170,8 @@
/obj/structure/door_assembly/door_assembly_cult/Initialize(mapload)
. = ..()
icon = SSticker.cultdat?.airlock_runed_icon_file
overlays_file = SSticker.cultdat?.airlock_runed_overlays_file
icon = GET_CULT_DATA(airlock_runed_icon_file, initial(icon))
overlays_file = GET_CULT_DATA(airlock_runed_overlays_file, initial(overlays_file))
update_icon()
/obj/structure/door_assembly/door_assembly_cult/unruned
@@ -182,8 +182,8 @@
/obj/structure/door_assembly/door_assembly_cult/unruned/Initialize(mapload)
. = ..()
icon = SSticker.cultdat?.airlock_unruned_icon_file
overlays_file = SSticker.cultdat?.airlock_unruned_overlays_file
icon = GET_CULT_DATA(airlock_unruned_icon_file, initial(icon))
overlays_file = GET_CULT_DATA(airlock_unruned_overlays_file, initial(overlays_file))
update_icon()
/obj/structure/door_assembly/door_assembly_centcom
+2 -2
View File
@@ -454,11 +454,11 @@
/obj/structure/girder/cult/Initialize(mapload)
. = ..()
icon_state = SSticker.cultdat?.cult_girder_icon_state
icon_state = GET_CULT_DATA(cult_girder_icon_state, initial(icon_state))
/obj/structure/girder/cult/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
if(istype(W, /obj/item/melee/cultblade/dagger) && iscultist(user)) //Cultists can demolish cult girders instantly with their dagger
if(istype(W, /obj/item/melee/cultblade/dagger) && IS_CULTIST(user)) //Cultists can demolish cult girders instantly with their dagger
user.visible_message("<span class='warning'>[user] strikes [src] with [W]!</span>", "<span class='notice'>You demolish [src].</span>")
refundMetal(metalUsed)
qdel(src)
+1 -2
View File
@@ -235,8 +235,7 @@
/turf/simulated/floor/engine/cult/Initialize(mapload)
. = ..()
if(SSticker.mode)//only do this if the round is going..otherwise..fucking asteroid..
icon_state = SSticker.cultdat.cult_floor_icon_state
icon_state = GET_CULT_DATA(cult_floor_icon_state, initial(icon_state))
/turf/simulated/floor/engine/cult/Entered(atom/A, atom/OL, ignoreRest)
. = ..()
+1 -1
View File
@@ -15,7 +15,7 @@
. = ..()
if(SSticker.mode)//game hasn't started officially don't do shit..
new /obj/effect/temp_visual/cult/turf(src)
icon_state = SSticker.cultdat.cult_wall_icon_state
icon_state = GET_CULT_DATA(cult_wall_icon_state, initial(icon_state))
/turf/simulated/wall/cult/bullet_act(obj/item/projectile/Proj)
. = ..()
+3
View File
@@ -23,6 +23,9 @@ GLOBAL_PROTECT(href_token)
/// Our currently linked marked datum
var/datum/marked_datum
/// Our index into GLOB.antagonist_teams, so that admins can have pretty tabs in the Check Teams menu.
var/team_switch_tab_index = 1
/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey)
if(IsAdminAdvancedProcCall())
to_chat(usr, "<span class='boldannounceooc'>Admin rank creation blocked: Advanced ProcCall detected.</span>")
+26 -1
View File
@@ -643,7 +643,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
antag_list += "Head Rev"
if(M.mind.has_antag_datum(/datum/antagonist/rev, FALSE))
antag_list += "Revolutionary"
if(M.mind in SSticker.mode.cult)
if(IS_CULTIST(M))
antag_list += "Cultist"
if(M.mind in SSticker.mode.syndicates)
antag_list += "Nuclear Operative"
@@ -989,4 +989,29 @@ GLOBAL_VAR_INIT(gamma_ship_location, 1) // 0 = station , 1 = space
result[1]++
return result
/**
* Allows admins to safely pick from SSticker.minds for objectives
* - caller, mob to ask for results
* - blacklist, optional list of targets that are not available
* - default_target, the target to show in the list as default
*/
/proc/get_admin_objective_targets(mob/caller, list/blacklist, mob/default_target)
if(!islist(blacklist))
blacklist = list(blacklist)
var/list/possible_targets = list()
for(var/datum/mind/possible_target in SSticker.minds)
if(!(possible_target in blacklist) && ishuman(possible_target.current))
possible_targets += possible_target.current // Allows for admins to pick off station roles
if(!length(possible_targets))
to_chat(caller, "<span class='warning'>No possible target found.</span>")
return
possible_targets = sortAtom(possible_targets)
var/mob/new_target = input(caller, "Select target:", "Objective target", default_target) as null|anything in possible_targets
if(!QDELETED(new_target))
return new_target.mind
#undef PLAYER_NOTES_ENTRIES_PER_PAGE
+3 -28
View File
@@ -429,34 +429,9 @@
/*if(ticker.mode.ninjas.len)
dat += check_role_table("Ninjas", ticker.mode.ninjas)*/
if(SSticker.mode.cult.len)
var/datum/game_mode/gamemode = SSticker.mode
var/datum/objective/current_sac_obj = gamemode.cult_objs.current_sac_objective()
dat += check_role_table("Cultists", SSticker.mode.cult)
if(current_sac_obj)
dat += "<br>Current cult objective: <br>[current_sac_obj.explanation_text]"
else if(gamemode.cult_objs.cult_status == NARSIE_NEEDS_SUMMONING)
dat += "<br>Current cult objective: Summon [SSticker.cultdat ? SSticker.cultdat.entity_name : "Nar'Sie"]"
else if(gamemode.cult_objs.cult_status == NARSIE_HAS_RISEN)
dat += "<br>Current cult objective: Feed [SSticker.cultdat ? SSticker.cultdat.entity_name : "Nar'Sie"]"
else if(gamemode.cult_objs.cult_status == NARSIE_HAS_FALLEN)
dat += "<br>Current cult objective: Kill all non-cultists"
else
dat += "<br>Current cult objective: None! (This is most likely a bug, or var editing gone wrong.)"
dat += "<br>Sacrifice objectives completed: [gamemode.cult_objs.sacrifices_done]"
dat += "<br>Sacrifice objectives needed for summoning: [gamemode.cult_objs.sacrifices_required]"
dat += "<br>Summoning locations: [english_list(gamemode.cult_objs.obj_summon.summon_spots)]"
dat += "<br><a href='?src=[UID()];cult_mindspeak=[UID()]'>Cult Mindspeak</a>"
if(gamemode.cult_objs.cult_status == NARSIE_DEMANDS_SACRIFICE)
dat += "<br><a href='?src=[UID()];cult_adjustsacnumber=[UID()]'>Modify amount of sacrifices required</a>"
dat += "<br><a href='?src=[UID()];cult_newtarget=[UID()]'>Reroll sacrifice target</a>"
else
dat += "<br>Modify amount of sacrifices required (Summon available!)</a>"
dat += "<br>Reroll sacrifice target (Summon available!)</a>"
dat += "<br><a href='?src=[UID()];cult_newsummonlocations=[UID()]'>Reroll summoning locations</a>"
dat += "<br><a href='?src=[UID()];cult_unlocknarsie=[UID()]'>Unlock Nar'Sie summoning</a>"
if(SSticker.mode.cult_team)
dat += check_role_table("Cultists", SSticker.mode.cult_team.members)
dat += "<a href='?src=[UID()];check_teams=1'>View Cult Team & Controls</a><br>"
if(SSticker.mode.traitors.len)
dat += check_role_table("Traitors", SSticker.mode.traitors)
+22 -63
View File
@@ -1616,12 +1616,30 @@
else if(href_list["team_command"])
if(!check_rights(R_ADMIN))
return
if(href_list["team_command"] == "reload") // reload the panel
check_teams()
return
var/datum/team/team
if(href_list["team_command"] == "new_custom_team") // this needs to be handled before all the other stuff, as the team doesn't exist yet
message_admins("[key_name_admin(usr)] created a new custom team.")
log_admin("[key_name(usr)] created a new custom team.")
team = new()
team.admin_rename_team(usr)
var/list/possible_teams = list()
for(var/datum/team/team_path as anything in typesof(/datum/team))
possible_teams[initial(team_path.name)] = team_path
var/chosen_team_name = input("Select a team type: (Creating a duplicate of a non-generic team may produce runtimes!)", "Team Type") as null|anything in possible_teams
if(!chosen_team_name)
return
var/chosen_team_path = possible_teams[chosen_team_name]
team = new chosen_team_path()
log_and_message_admins("created a new team '[team]' ([chosen_team_path]).")
if(chosen_team_path == /datum/team)
team.admin_rename_team(usr) // this has to come after, because the admin log could be delayed indefinitely.
check_teams()
return
if(href_list["team_command"] == "switch_team_tab")
team_switch_tab_index = clamp(text2num(href_list["team_index"]), 1, length(GLOB.antagonist_teams))
check_teams()
return
@@ -1692,65 +1710,6 @@
else
SStickets.convert_to_other_ticket(indexNum)
else if(href_list["cult_mindspeak"])
var/input = stripped_input(usr, "Communicate to all the cultists with the voice of [SSticker.cultdat.entity_name]", "Voice of [SSticker.cultdat.entity_name]")
if(!input)
return
for(var/datum/mind/H in SSticker.mode.cult)
if(H.current)
to_chat(H.current, "<span class='cult'>[SSticker.cultdat.entity_name] murmurs,</span> <span class='cultlarge'>\"[input]\"</span>")
for(var/mob/dead/observer/O in GLOB.player_list)
to_chat(O, "<span class='cult'>[SSticker.cultdat.entity_name] murmurs,</span> <span class='cultlarge'>\"[input]\"</span>")
message_admins("Admin [key_name_admin(usr)] has talked with the Voice of [SSticker.cultdat.entity_name].")
log_admin("[key_name(usr)] Voice of [SSticker.cultdat.entity_name]: [input]")
else if(href_list["cult_adjustsacnumber"])
var/amount = input("Adjust the amount of sacrifices required before summoning Nar'Sie", "Sacrifice Adjustment", 2) as null | num
if(amount > 0)
var/datum/game_mode/gamemode = SSticker.mode
var/old = gamemode.cult_objs.sacrifices_required
gamemode.cult_objs.sacrifices_required = amount
message_admins("Admin [key_name_admin(usr)] has modified the amount of cult sacrifices required before summoning from [old] to [amount]")
log_admin("Admin [key_name_admin(usr)] has modified the amount of cult sacrifices required before summoning from [old] to [amount]")
else if(href_list["cult_newtarget"])
if(alert(usr, "Reroll the cult's sacrifice target?", "Cult Debug", "Yes", "No") != "Yes")
return
var/datum/game_mode/gamemode = SSticker.mode
if(!gamemode.cult_objs.find_new_sacrifice_target())
gamemode.cult_objs.ready_to_summon()
message_admins("Admin [key_name_admin(usr)] has rerolled the Cult's sacrifice target.")
log_admin("Admin [key_name_admin(usr)] has rerolled the Cult's sacrifice target.")
else if(href_list["cult_newsummonlocations"])
if(alert(usr, "Reroll the cult's summoning locations?", "Cult Debug", "Yes", "No") != "Yes")
return
var/datum/game_mode/gamemode = SSticker.mode
gamemode.cult_objs.obj_summon.find_summon_locations(TRUE)
if(gamemode.cult_objs.cult_status == NARSIE_NEEDS_SUMMONING) //Only update cultists if they are already have the summon goal since they arent aware of summon spots till then
for(var/datum/mind/cult_mind in gamemode.cult)
if(cult_mind && cult_mind.current)
to_chat(cult_mind.current, "<span class='cult'>The veil has shifted! Our summoning will need to take place elsewhere.</span>")
to_chat(cult_mind.current, "<span class='cult'>Current goal : [gamemode.cult_objs.obj_summon.explanation_text]</span>")
message_admins("Admin [key_name_admin(usr)] has rerolled the Cult's sacrifice target.")
log_admin("Admin [key_name_admin(usr)] has rerolled the Cult's sacrifice target.")
else if(href_list["cult_unlocknarsie"])
if(alert(usr, "Unlock the ability to summon Nar'Sie?", "Cult Debug", "Yes", "No") != "Yes")
return
var/datum/game_mode/gamemode = SSticker.mode
gamemode.cult_objs.ready_to_summon()
message_admins("Admin [key_name_admin(usr)] has unlocked the Cult's ability to summon Nar'Sie.")
log_admin("Admin [key_name_admin(usr)] has unlocked the Cult's ability to summon Nar'Sie.")
else if(href_list["adminplayerobservecoodjump"])
var/client/C = usr.client
if(!isobserver(usr))
+11 -11
View File
@@ -162,7 +162,7 @@
var/list/mob/living/carbon/human/candidates = list()
var/mob/living/carbon/human/H = null
var/antnum = input(owner, "How many cultists do you want to create? Enter 0 to cancel.", "Amount:", 0) as num
if(!antnum || antnum <= 0) // 5 because cultist can really screw balance over if spawned in high amount.
if(!antnum || antnum <= 0)
return
log_admin("[key_name(owner)] tried making a Cult with One-Click-Antag")
message_admins("[key_name_admin(owner)] tried making a Cult with One-Click-Antag")
@@ -171,17 +171,17 @@
if(CandCheck(ROLE_CULTIST, applicant, temp))
candidates += applicant
if(length(candidates))
var/numCultists = min(length(candidates), antnum)
if(!length(candidates))
return FALSE
for(var/I in 1 to numCultists)
H = pick(candidates)
to_chat(H, CULT_GREETING)
SSticker.mode.add_cultist(H.mind)
SSticker.mode.equip_cultist(H)
candidates.Remove(H)
return TRUE
return FALSE
for(var/I in 1 to antnum)
if(!length(candidates))
return
H = pick_n_take(candidates)
var/datum/antagonist/cultist/cultist = H.mind.add_antag_datum(/datum/antagonist/cultist)
cultist.equip_roundstart_cultist(H)
return TRUE
//Abductors
/datum/admins/proc/makeAbductorTeam()
+2 -2
View File
@@ -23,11 +23,11 @@
cross = image('icons/obj/storage.dmi',"kingyellow")
font_color = "blue"
prayer_type = "CHAPLAIN PRAYER"
else if(iscultist(usr))
else if(IS_CULTIST(usr))
cross = image('icons/obj/storage.dmi',"tome")
font_color = "red"
prayer_type = "CULTIST PRAYER"
deity = SSticker.cultdat.entity_name
deity = GET_CULT_DATA(entity_name, "Cult God")
log_say("(PRAYER) [msg]", usr)
msg = "<span class='notice'>[bicon(cross)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""][mind && HAS_MIND_TRAIT(usr, TRAIT_HOLY) ? " (blessings: [mind.num_blessed])" : ""]:</font> [key_name(src, 1)] ([ADMIN_QUE(src,"?")]) ([ADMIN_PP(src,"PP")]) ([ADMIN_VV(src,"VV")]) ([ADMIN_TP(src,"TP")]) ([ADMIN_SM(src,"SM")]) ([admin_jump_link(src)]) ([ADMIN_SC(src,"SC")]) (<A HREF='?_src_=holder;Bless=[UID()]'>BLESS</A>) (<A HREF='?_src_=holder;Smite=[UID()]'>SMITE</A>):</b> [msg]</span>"
@@ -1,5 +1,7 @@
GLOBAL_LIST_EMPTY(antagonists)
#define SUCCESSFUL_DETACH "dont touch this string numbnuts"
/datum/antagonist
/// The name of the antagonist.
var/name = "Antagonist"
@@ -33,6 +35,8 @@ GLOBAL_LIST_EMPTY(antagonists)
var/clown_gain_text = "You are no longer clumsy."
/// If the owner is a clown, this text will be displayed to them when they lose this datum.
var/clown_removal_text = "You are clumsy again."
/// The spawn class to use for gain/removal clown text
var/clown_text_span_class = "boldnotice"
/// The url page name for this antagonist, appended to the end of the wiki url in the form of: [GLOB.configuration.url.wiki_url]/index.php/[wiki_page_name]
var/wiki_page_name
@@ -56,8 +60,8 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/Destroy(force, ...)
qdel(objective_holder)
GLOB.antagonists -= src
if(!QDELETED(owner))
detach_from_owner()
if(!QDELETED(owner) && detach_from_owner() != SUCCESSFUL_DETACH)
stack_trace("[src] ([type]) failed to detach from owner! This is very bad!")
return ..()
@@ -79,6 +83,7 @@ GLOBAL_LIST_EMPTY(antagonists)
LAZYREMOVE(owner.antag_datums, src)
restore_last_hud_and_role()
owner = null
return SUCCESSFUL_DETACH
/**
* Adds the owner to their respective gamemode's list. For example `SSticker.mode.traitors |= owner`.
@@ -408,3 +413,5 @@ GLOBAL_LIST_EMPTY(antagonists)
/// This is the custom blurb message used on login for an antagonist.
/datum/antagonist/proc/custom_blurb()
return FALSE
#undef SUCCESSFUL_DETACH
+152 -38
View File
@@ -1,6 +1,6 @@
GLOBAL_LIST_EMPTY(antagonist_teams)
#define DEFAULT_TEAM_NAME "Generic Team Name"
#define DEFAULT_TEAM_NAME "Generic/Custom Team"
/**
* # Antagonist Team
@@ -11,7 +11,7 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
/// The name of the team.
var/name = DEFAULT_TEAM_NAME
/// A list of [minds][/datum/mind] who belong to this team.
var/list/datum/mind/members
var/list/datum/mind/members = list()
/// A list of objectives which all team members share.
var/datum/objective_holder/objective_holder
/// Type of antag datum members of this team have. Also given to new members added by admins.
@@ -21,40 +21,87 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
/datum/team/New(list/starting_members)
..()
members = list()
if(!can_create_team())
QDEL_IN(src, 0 SECONDS) // Give us time to crash so we can get the full call stack
CRASH("[src] ([type]) is not allowed to be created, this may be a duplicate team. Deleting...")
// Assign the team before member assignment to prevent duplicate teams
assign_team()
if(!create_team(starting_members))
CRASH("[src] ([type]) somehow failed to create a team!")
/datum/team/proc/create_team(list/starting_members)
PROTECTED_PROC(TRUE)
objective_holder = new(src)
if(starting_members && !islist(starting_members))
starting_members = list(starting_members)
for(var/datum/mind/M as anything in starting_members)
add_member(M)
GLOB.antagonist_teams += src
return TRUE
/datum/team/Destroy(force = FALSE, ...)
for(var/datum/mind/member as anything in members)
remove_member(member)
clear_team_reference() // Team reference must come AFTER removing all members, otherwise antag datums will not get removed
qdel(objective_holder)
members.Cut()
GLOB.antagonist_teams -= src
return ..()
/datum/team/proc/can_create_team()
return TRUE
/datum/team/proc/assign_team()
return
/datum/team/proc/clear_team_reference()
return
/**
* Adds `new_member` to this team.
*
* Generally this should ONLY be called by `add_antag_datum()` to ensure proper order of operations.
* This is an interface proc, to prevent handle_removing_member from being called multiple times.
* It is better if this is only called from `add_antag_datum()`, but it is not required.
*/
/datum/team/proc/add_member(datum/mind/new_member)
SHOULD_CALL_PARENT(TRUE)
var/datum/antagonist/antag = get_antag_datum_from_member(new_member) // make sure they have the antag datum
/datum/team/proc/add_member(datum/mind/new_member, force = FALSE)
SHOULD_NOT_OVERRIDE(TRUE)
if(!force && (new_member in members))
return FALSE
members |= new_member
handle_adding_member(new_member)
return TRUE
/**
* An internal proc to allow teams to handle custom parts of adding a member.
* This should ONLY be called by `add_member()` to ensure proper order of operations.
*/
/datum/team/proc/handle_adding_member(datum/mind/new_member)
PROTECTED_PROC(TRUE)
SHOULD_CALL_PARENT(TRUE)
var/datum/antagonist/antag = get_antag_datum_from_member(new_member) // make sure they have the antag datum
if(!antag) // this team has no antag role, we'll add it directly to their mind team
LAZYDISTINCTADD(new_member.teams, src)
/**
* Removes `member` from this team.
* This is an interface proc, to prevent handle_removing_member from being called multiple times.
*/
/datum/team/proc/remove_member(datum/mind/member)
SHOULD_CALL_PARENT(TRUE)
/datum/team/proc/remove_member(datum/mind/member, force = FALSE)
SHOULD_NOT_OVERRIDE(TRUE)
if(!force && !(member in members))
return FALSE
members -= member
handle_removing_member(member)
return TRUE
/**
* An internal proc for teams to remove a member.
*/
/datum/team/proc/handle_removing_member(datum/mind/member, force = FALSE)
PROTECTED_PROC(TRUE)
SHOULD_CALL_PARENT(TRUE)
LAZYREMOVE(member.teams, src)
var/datum/antagonist/antag = get_antag_datum_from_member(member)
if(!QDELETED(antag))
@@ -70,13 +117,17 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
continue
valid_minds[H.real_name] = H.mind
if(!length(valid_minds))
to_chat(user, "<span class='warning'>No suitable humanoid targets found!</span>")
return
var/name = input(user, "Choose a player to add to this team", "Add Team Member") as null|anything in valid_minds
if(!name)
to_chat(user, "<span class='warning'>No suitable humanoid targets found!</span>")
return
var/datum/mind/new_member = valid_minds[name]
add_member(new_member)
add_member(new_member, TRUE)
log_admin("[key_name(usr)] added [key_name(new_member)] to the team '[src]'.")
message_admins("[key_name_admin(usr)] added [key_name(new_member)] to the team '[src]'.")
/**
* Adds a team objective to each member's matching antag datum.
@@ -178,21 +229,61 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
message_admins("Team Message: [key_name(user)] -> '[name]' team. Message: [message]")
log_admin("Team Message: [key_name(user)] -> '[name]' team. Message: [message]")
#define SEPERATOR "---"
/**
* Allows admins to add a team objective.
* Minimize overriding this proc please.
*/
/datum/team/proc/admin_add_objective(mob/user)
var/selected = input("Select an objective type:", "Objective Type") as null|anything in GLOB.admin_objective_list
if(!selected)
SHOULD_CALL_PARENT(TRUE)
// available_objectives is assoc, `objective name` = `objective_path`
var/list/available_objectives = get_admin_priority_objectives()
if(length(available_objectives))
available_objectives[SEPERATOR] = "Whatever, we never read this"
available_objectives += GLOB.admin_objective_list
var/selected = input("Select an objective type:", "Objective Type") as null|anything in available_objectives
if(!selected || selected == SEPERATOR)
return
var/objective_type = GLOB.admin_objective_list[selected]
var/objective_type = available_objectives[selected]
var/return_value = handle_adding_admin_objective(user, objective_type)
if(istype(return_value, /datum/objective)) // handle_adding_admin_objective can return TRUE if its handled
add_team_objective(return_value)
else
if(return_value & TEAM_ADMIN_ADD_OBJ_PURPOSEFUL_CANCEL)
return
if(!(return_value & TEAM_ADMIN_ADD_OBJ_SUCCESS))
to_chat(user, "<span class='warning'>[src] team failed to properly handle your selected objective, if you believe this was an error, tell a coder.</span>")
return
if(return_value & TEAM_ADMIN_ADD_OBJ_CANCEL_LOG) // Logs are being handled elsewhere
return
message_admins("[key_name_admin(user)] added objective [objective_type] to the team '[name]'.")
log_admin("[key_name(user)] added objective [objective_type] to the team '[name]'.")
#undef SEPERATOR
/**
* Overridable logic for handling how the adding of objectives works works
* Can return an objective datum, or a boolean.
* Returns a boolean if its already added to the team objectives in a custom way
*/
/datum/team/proc/handle_adding_admin_objective(mob/user, objective_type)
PROTECTED_PROC(TRUE)
var/datum/objective/O = new objective_type(team_to_join = src)
O.find_target(get_target_excludes()) // Blacklist any team members from being the target.
add_team_objective(O)
return O
message_admins("[key_name_admin(user)] added objective [O.type] to the team '[name]'.")
log_admin("[key_name(user)] added objective [O.type] to the team '[name]'.")
/**
* Returns an associated list of priority objectives for admins to add to the team, this is like
* Must return in the form `objective name` = `objective_path`.
*/
/datum/team/proc/get_admin_priority_objectives()
return list()
/**
* Allows admins to announce objectives to all team members.
@@ -239,7 +330,7 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
/datum/team/proc/admin_remove_member(mob/user, datum/mind/M)
message_admins("[key_name_admin(user)] removed [key_name_admin(M)] from the team '[name]'.")
log_admin("[key_name(user)] removed [key_name(M)] from the team '[name]'.")
remove_member(M)
remove_member(M, TRUE)
// Used for running team specific admin commands.
/datum/team/Topic(href, href_list)
@@ -251,8 +342,35 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
if(href_list["command"] == admin_command)
var/datum/callback/C = commands[admin_command]
C.Invoke(usr)
usr.client.holder.check_teams()
return
/datum/team/proc/get_admin_html()
var/list/content = list()
content += "<h3>[name] - [type]</h3>"
content += "<a href='?_src_=holder;team_command=rename_team;team=[UID()]'>Rename Team</a>"
content += "<a href='?_src_=holder;team_command=delete_team;team=[UID()]'>Delete Team</a>"
content += "<a href='?_src_=holder;team_command=communicate;team=[UID()]'>OOC Message Team</a>"
content += ADMIN_VV(src, "View Variables")
for(var/command in get_admin_commands())
// src is UID() so it points to `/datum/team/Topic` instead of `/datum/admins/Topic`.
content += "<a href='?src=[UID()];command=[command]'>[command]</a>"
content += "<br><br>Objectives:<br><ol>"
for(var/datum/objective/O as anything in objective_holder.get_objectives())
if(!istype(O))
stack_trace("Non-objective found in [type]'s objective_holder.get_objectives()")
continue
content += "<li>[O.explanation_text] - <a href='?_src_=holder;team_command=remove_objective;team=[UID()];objective=[O.UID()]'>Remove</a></li>"
content += "</ol><a href='?_src_=holder;team_command=add_objective;team=[UID()]'>Add Objective</a><br>"
if(objective_holder.has_objectives())
content += "</ol><a href='?_src_=holder;team_command=announce_objectives;team=[UID()]'>Announce Objectives to All Members</a><br><br>"
content += "Members: <br><ol>"
for(var/datum/mind/M as anything in members)
content += "<li>[M.name] - <a href='?_src_=holder;team_command=view_member;team=[UID()];member=[M.UID()]'>Show Player Panel</a>"
content += "<a href='?_src_=holder;team_command=remove_member;team=[UID()];member=[M.UID()]'>Remove Member</a></li>"
content += "</ol><a href='?_src_=holder;team_command=admin_add_member;team=[UID()]'>Add Member</a>"
return content
/**
* A list of team-specific admin commands for this team. Should be in the form of `"command" = CALLBACK(x, PROC_REF(some_proc))`.
*/
@@ -279,26 +397,22 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
if(!length(GLOB.antagonist_teams))
content += "There are currently no antag teams.<br/>"
content += "<a href='?_src_=holder;team_command=new_custom_team;'>Create new Team</a>"
for(var/datum/team/T as anything in GLOB.antagonist_teams) // with multiple teams, this is going to get messy. It should probably be turned into a tabs-like system
content += "<h3>[T.name] - [T.type]</h3>"
content += "<a href='?_src_=holder;team_command=rename_team;team=[T.UID()]'>Rename Team</a>"
content += "<a href='?_src_=holder;team_command=delete_team;team=[T.UID()]'>Delete Team</a>"
content += "<a href='?_src_=holder;team_command=communicate;team=[T.UID()]'>Message Team</a>"
content += ADMIN_VV(T, "View Variables")
for(var/command in T.get_admin_commands())
// _src_ is T.UID() so it points to `/datum/team/Topic` instead of `/datum/admins/Topic`.
content += "<a href='?_src_=[T.UID()];command=[command]'>[command]</a>"
content += "<br><br>Objectives:<br><ol>"
for(var/datum/objective/O as anything in T.objective_holder.get_objectives())
content += "<li>[O.explanation_text] - <a href='?_src_=holder;team_command=remove_objective;team=[T.UID()];objective=[O.UID()]'>Remove</a></li>"
content += "</ol><a href='?_src_=holder;team_command=add_objective;team=[T.UID()]'>Add Objective</a><br>"
if(T.objective_holder.has_objectives())
content += "</ol><a href='?_src_=holder;team_command=announce_objectives;team=[T.UID()]'>Announce Objectives to All Members</a><br><br>"
content += "Members: <br><ol>"
for(var/datum/mind/M as anything in T.members)
content += "<li>[M.name] - <a href='?_src_=holder;team_command=view_member;team=[T.UID()];member=[M.UID()]'>Show Player Panel</a>"
content += "<a href='?_src_=holder;team_command=remove_member;team=[T.UID()];member=[M.UID()]'>Remove Member</a></li>"
content += "</ol><a href='?_src_=holder;team_command=admin_add_member;team=[T.UID()]'>Add Member</a><hr>"
content += "<a href='?_src_=holder;team_command=reload;'>Reload Menu</a><br>"
if(length(GLOB.antagonist_teams) > 1)
var/index = 1
for(var/datum/team/T as anything in GLOB.antagonist_teams)
content += "<a href='?_src_=holder;team_command=switch_team_tab;team_index=[index]'>[T.name]</a>"
index++
else
team_switch_tab_index = 1
if(length(GLOB.antagonist_teams))
content += "<hr>"
team_switch_tab_index = clamp(team_switch_tab_index, 1, length(GLOB.antagonist_teams))
var/datum/team/T = GLOB.antagonist_teams[team_switch_tab_index]
if(istype(T))
var/list/stringy_list = T.get_admin_html()
content += stringy_list.Join()
return content.Join()
#undef DEFAULT_TEAM_NAME
@@ -0,0 +1,142 @@
/datum/antagonist/cultist
name = "Cultist"
job_rank = ROLE_CULTIST
special_role = SPECIAL_ROLE_CULTIST
give_objectives = FALSE
antag_hud_name = "hudcultist"
antag_hud_type = ANTAG_HUD_CULT
clown_gain_text = "A dark power has allowed you to overcome your clownish nature, letting you wield weapons without harming yourself."
clown_removal_text = "You are free of the dark power suppressing your clownish nature. You are clumsy again! Honk!"
clown_text_span_class = "cultitalic"
wiki_page_name = "Cultist"
var/remove_gear_on_removal = FALSE
/datum/antagonist/cultist/on_gain()
create_team() // make sure theres a global cult team
..()
owner.current.faction |= "cult"
add_cult_actions()
SEND_SOUND(owner.current, sound('sound/ambience/antag/bloodcult.ogg'))
owner.current.create_log(CONVERSION_LOG, "Converted to the cult")
owner.current.create_attack_log("<span class='danger'>Has been converted to the cult!</span>")
var/datum/team/cult/cult = get_team()
ASSERT(cult)
if(cult.cult_risen)
rise()
if(cult.cult_ascendant)
ascend()
cult.study_objectives(owner.current)
/datum/antagonist/cultist/detach_from_owner()
if(!owner.current)
return ..()
owner.current.faction -= "cult"
owner.current.create_log(CONVERSION_LOG, "Deconverted from the cult") // yes, this is its own log, instead of the default MISC_LOG
for(var/datum/action/innate/cult/C in owner.current.actions)
qdel(C)
if(!ishuman(owner.current))
return ..()
var/mob/living/carbon/human/H = owner.current
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_on_removal)
for(var/I in H.contents)
if(is_type_in_list(I, CULT_CLOTHING))
H.unEquip(I)
return ..()
/datum/antagonist/cultist/greet()
return "<span class='cultlarge'>You catch a glimpse of the Realm of [GET_CULT_DATA(entity_name, "this is a bug at this point")], [GET_CULT_DATA(entity_title3, "I dont know what else to write")]. \
You now see how flimsy the world is, you see that it should be open to the knowledge of [GET_CULT_DATA(entity_name, "making a bug report")].</span>"
/datum/antagonist/cultist/farewell()
if(owner && owner.current)
owner.current.visible_message("<span class='cult'>[owner.current] looks like [owner.current.p_they()] just reverted to [owner.current.p_their()] old faith!</span>",
"<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of [GET_CULT_DATA(entity_title1, "Nar'Sie")] and the memories of your time as their servant with it.</span>")
/datum/antagonist/cultist/create_team(team)
return SSticker.mode.get_cult_team()
/datum/antagonist/cultist/get_team()
return SSticker.mode.cult_team
/datum/antagonist/cultist/on_body_transfer(old_body, new_body)
var/datum/team/cult/cult = get_team()
cult.cult_body_transfer(old_body, new_body)
add_cult_actions()
/datum/antagonist/cultist/proc/rise()
if(!ishuman(owner.current))
return
var/mob/living/carbon/human/H = owner.current
if(!H.original_eye_color)
H.original_eye_color = H.get_eye_color()
H.change_eye_color(BLOODCULT_EYE, FALSE)
ADD_TRAIT(H, CULT_EYES, CULT_TRAIT)
H.update_eyes()
H.update_body()
/datum/antagonist/cultist/proc/ascend()
if(!ishuman(owner.current))
return
var/mob/living/carbon/human/H = owner.current
new /obj/effect/temp_visual/cult/sparks(get_turf(H), H.dir)
H.update_halo_layer()
/datum/antagonist/cultist/proc/descend()
if(!ishuman(owner.current))
return
var/mob/living/carbon/human/H = owner.current
new /obj/effect/temp_visual/cult/sparks(get_turf(H), H.dir)
H.update_halo_layer()
to_chat(H, "<span class='userdanger'>The halo above your head shatters!</span>")
playsound(H, "shatter", 50, TRUE)
/datum/antagonist/cultist/proc/add_cult_actions()
if(!owner.current)
return
var/datum/action/innate/cult/comm/communicate_spell = new
var/datum/action/innate/cult/check_progress/progress_report = new
communicate_spell.Grant(owner.current)
progress_report.Grant(owner.current)
if(ishuman(owner.current))
var/datum/action/innate/cult/blood_magic/magic = new
var/datum/action/innate/cult/use_dagger/dagger = new
magic.Grant(owner.current)
dagger.Grant(owner.current)
owner.current.update_action_buttons(TRUE)
/datum/antagonist/cultist/proc/equip_roundstart_cultist()
if(!ishuman(owner.current))
return FALSE
. |= cult_give_item(/obj/item/melee/cultblade/dagger)
. |= cult_give_item(/obj/item/stack/sheet/runed_metal/ten)
to_chat(owner.current, "<span class='cult'>These will help you start the cult on this station. Use them well, and remember - you are not the only one.</span>")
/datum/antagonist/cultist/proc/cult_give_item(obj/item/item_path)
if(!ishuman(owner.current))
return
var/mob/living/carbon/human/H = owner.current
var/list/slots = list(
"backpack" = SLOT_HUD_IN_BACKPACK,
"left pocket" = SLOT_HUD_LEFT_STORE,
"right pocket" = SLOT_HUD_RIGHT_STORE
)
var/where = H.equip_in_one_of_slots(new item_path(H), slots)
if(where)
to_chat(H, "<span class='danger'>You have \a [initial(item_path.name)] in your [where].</span>")
if(H.s_active) // Update whatever inventory they have open
H.s_active.orient2hud(H)
H.s_active.show_to(H)
return TRUE
to_chat(H, "<span class='userdanger'>Unfortunately, you weren't able to get \a [initial(item_path.name)]. This is very bad and you should adminhelp immediately (press F1).</span>")
return FALSE
+569
View File
@@ -0,0 +1,569 @@
/datum/team/cult
name = "Cult"
antag_datum_type = /datum/antagonist/cultist
/// Does the cult have glowing eyes
var/cult_risen = FALSE
/// Does the cult have halos
var/cult_ascendant = FALSE
/// How many crew need to be converted to rise
var/rise_number
/// How many crew need to be converted to ascend
var/ascend_number
/// Used for the CentComm announcement at ascension
var/ascend_percent
/// Variable used for tracking the progress of the cult's sacrifices & god summonings
var/cult_status = NARSIE_IS_ASLEEP
/// God summon objective added when ready_to_summon() is called
var/datum/objective/eldergod/obj_summon
var/sacrifices_done = 0
var/sacrifices_required = 2
/// Are cultist mirror shields active yet?
var/mirror_shields_active = FALSE
// Disables the station-wide announcements, unused except for admin editing.
var/no_announcements = FALSE
/datum/team/cult/create_team(list/starting_members)
cult_threshold_check() // Set this ALWAYS before any check_cult_size check, or
. = ..()
objective_holder.add_objective(/datum/objective/servecult)
addtimer(CALLBACK(src, PROC_REF(cult_threshold_check)), 2 MINUTES) // Check again in 2 minutes for latejoiners
cult_status = NARSIE_DEMANDS_SACRIFICE
create_next_sacrifice()
for(var/datum/mind/M as anything in starting_members)
var/datum/antagonist/cultist/cultist = M.has_antag_datum(/datum/antagonist/cultist)
cultist.equip_roundstart_cultist()
/datum/team/cult/can_create_team()
return isnull(SSticker.mode.cult_team)
/datum/team/cult/assign_team()
SSticker.mode.cult_team = src
/datum/team/cult/clear_team_reference()
if(SSticker.mode.cult_team == src)
SSticker.mode.cult_team = null
else
CRASH("[src] ([type]) attempted to clear a team reference that wasn't itself!")
/datum/team/cult/handle_adding_member(datum/mind/new_member)
. = ..()
check_cult_size()
RegisterSignal(new_member.current, COMSIG_MOB_STATCHANGE, PROC_REF(cultist_stat_change))
RegisterSignal(new_member.current, COMSIG_PARENT_QDELETING, PROC_REF(cultist_deleting))
/datum/team/cult/handle_removing_member(datum/mind/member)
. = ..()
UnregisterSignal(member.current, COMSIG_MOB_STATCHANGE)
UnregisterSignal(member.current, COMSIG_PARENT_QDELETING)
check_cult_size()
/datum/team/cult/on_round_end()
var/list/endtext = list()
endtext += "<br><b>The cultists' objectives were:</b>"
for(var/datum/objective/obj in objective_holder.get_objectives())
endtext += "<br>[obj.explanation_text] - "
if(!obj.check_completion())
endtext += "<font color='red'>Fail.</font>"
else
endtext += "<font color='green'><B>Success!</B></font>"
to_chat(world, endtext.Join(""))
/datum/team/cult/proc/add_cult_immunity(mob/living/target)
ADD_TRAIT(target, TRAIT_CULT_IMMUNITY, CULT_TRAIT)
addtimer(CALLBACK(src, PROC_REF(remove_cult_immunity), target), 1 MINUTES)
/datum/team/cult/proc/remove_cult_immunity(mob/living/target)
REMOVE_TRAIT(target, TRAIT_CULT_IMMUNITY, CULT_TRAIT)
/**
* Makes sure that the signal stays on the correct body when a cultist changes bodies
*/
/datum/team/cult/proc/cult_body_transfer(old_body, new_body)
UnregisterSignal(old_body, COMSIG_MOB_STATCHANGE)
UnregisterSignal(old_body, COMSIG_PARENT_QDELETING)
RegisterSignal(new_body, COMSIG_MOB_STATCHANGE, PROC_REF(cultist_stat_change))
RegisterSignal(new_body, COMSIG_PARENT_QDELETING, PROC_REF(cultist_deleting))
/**
* 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/team/cult/proc/get_cultists(separate = FALSE)
var/cultists = 0
var/constructs = 0
var/list/minds_to_remove = list()
for(var/datum/mind/M as anything in members)
if(isnull(M))
stack_trace("Found a null mind in /datum/team/cult's members. Removing...")
minds_to_remove |= M // I don't really want to remove them while iterating, as I'm not sure how byond would handle that while iterating over members
continue
if(isnull(M.current))
stack_trace("Found a mind with no body in /datum/team/cult's members. Removing...")
minds_to_remove |= M // I don't really want to remove them while iterating, as I'm not sure how byond would handle that while iterating over members
continue
if(QDELETED(M) || M.current.stat == DEAD)
continue
if(ishuman(M.current) && !M.current.has_status_effect(STATUS_EFFECT_SUMMONEDGHOST))
cultists++
else if(isconstruct(M.current))
constructs++
if(length(minds_to_remove))
for(var/datum/mind/M as anything in minds_to_remove)
remove_member(M)
if(separate)
return list(cultists, constructs)
return cultists + constructs
/datum/team/cult/proc/cultist_stat_change(mob/target_cultist, new_stat, old_stat)
SIGNAL_HANDLER
if(new_stat == old_stat) // huh, how? whatever, we ignore it
return
if(new_stat != DEAD && old_stat != DEAD)
return // switching between alive and unconcious
// switching between dead and alive/unconcious
INVOKE_ASYNC(src, PROC_REF(check_cult_size))
/datum/team/cult/proc/cultist_deleting(mob/deleting_cultist)
SIGNAL_HANDLER
INVOKE_ASYNC(src, PROC_REF(remove_member), deleting_cultist.mind)
/datum/team/cult/proc/check_cult_size()
if(!ascend_percent)
stack_trace("[src]'s check_cult_size was called before cult_threshold_check, which leads to weird logic! This should be fixed ASAP.")
cult_threshold_check()
var/cult_players = get_cultists()
if(cult_ascendant)
// The cult only falls if below 1/2 of the rising, usually pretty low. e.g. 5% on highpop, 10% on lowpop
if(cult_players < (rise_number / 2))
cult_fall()
return
if((cult_players >= rise_number) && !cult_risen)
cult_rise()
return
if(cult_players >= ascend_number)
cult_ascend()
/datum/team/cult/proc/cult_rise()
cult_risen = TRUE
for(var/datum/mind/M in members)
if(!ishuman(M.current))
continue
SEND_SOUND(M.current, sound('sound/hallucinations/i_see_you2.ogg'))
to_chat(M.current, "<span class='cultlarge'>The veil weakens as your cult grows, your eyes begin to glow...</span>")
addtimer(CALLBACK(src, PROC_REF(all_members_timer), TYPE_PROC_REF(/datum/antagonist/cultist, rise)), 20 SECONDS)
/datum/team/cult/proc/cult_ascend()
cult_ascendant = TRUE
for(var/datum/mind/M in members)
if(!ishuman(M.current))
continue
SEND_SOUND(M.current, sound('sound/hallucinations/im_here1.ogg'))
to_chat(M.current, "<span class='cultlarge'>Your cult is ascendant and the red harvest approaches - you cannot hide your true nature for much longer!</span>")
addtimer(CALLBACK(src, PROC_REF(all_members_timer), TYPE_PROC_REF(/datum/antagonist/cultist, ascend)), 20 SECONDS)
if(!no_announcements)
GLOB.major_announcement.Announce("Picking up extradimensional activity related to the Cult of [GET_CULT_DATA(entity_name, "Nar'Sie")] from your station. Data suggests that about [ascend_percent * 100]% of the station has been converted. Security staff are authorized to use lethal force freely against cultists. Non-security staff should be prepared to defend themselves and their work areas from hostile cultists. Self defense permits non-security staff to use lethal force as a last resort, but non-security staff should be defending their work areas, not hunting down cultists. Dead crewmembers must be revived and deconverted once the situation is under control.", "Central Command Higher Dimensional Affairs", 'sound/AI/commandreport.ogg')
/datum/team/cult/proc/cult_fall()
cult_ascendant = FALSE
for(var/datum/mind/M in members)
if(!ishuman(M.current))
continue
SEND_SOUND(M.current, sound('sound/hallucinations/wail.ogg'))
to_chat(M.current, "<span class='cultlarge'>The veil repairs itself, your power grows weaker...</span>")
addtimer(CALLBACK(src, PROC_REF(all_members_timer), TYPE_PROC_REF(/datum/antagonist/cultist, descend)), 20 SECONDS)
if(!no_announcements)
GLOB.major_announcement.Announce("Paranormal activity has returned to minimal levels. \
Security staff should minimize lethal force against cultists, using non-lethals where possible. \
All dead cultists should be taken to medbay or robotics for immediate revival and deconversion. \
Non-security staff may defend themselves, but should prioritize leaving any areas with cultists and reporting the cultists to security. \
Self defense permits non-security staff to use lethal force as a last resort. Hunting down cultists may make you liable for a manslaughter charge. \
Any access granted in response to the paranormal threat should be reset. \
Any and all security gear that was handed out should be returned. Finally, all weapons (including improvised) should be removed from the crew.",
"Central Command Higher Dimensional Affairs", 'sound/AI/commandreport.ogg')
/**
* This is a magic fuckin proc that takes a proc_ref, and calls it on all the human cultists.
* Created so that we don't make 1000 timers, and I'm too lazy to make a proc for all of these.
* Used in callbacks for some *magic bullshit*.
*/
/datum/team/cult/proc/all_members_timer(proc_ref_to_call)
for(var/datum/mind/M in members)
if(!ishuman(M.current))
continue
var/datum/antagonist/cultist/cultist = M.has_antag_datum(/datum/antagonist/cultist)
if(cultist)
call(cultist, proc_ref_to_call)() // yes this is a type proc ref passed by a callback, i know its deranged
/datum/team/cult/proc/is_convertable_to_cult(datum/mind/mind)
if(!mind)
return FALSE
if(!mind.current)
return FALSE
if(IS_SACRIFICE_TARGET(mind))
return FALSE
if(mind.has_antag_datum(/datum/antagonist/cultist))
return TRUE //If they're already in the cult, assume they are convertable
if(HAS_MIND_TRAIT(mind.current, TRAIT_HOLY))
return FALSE
if(ishuman(mind.current))
var/mob/living/carbon/human/H = mind.current
if(ismindshielded(H)) //mindshield protects against conversions unless removed
return FALSE
if(mind.offstation_role)
return FALSE
if(issilicon(mind.current))
return FALSE //can't convert machines, that's ratvar's thing
if(isguardian(mind.current))
var/mob/living/simple_animal/hostile/guardian/G = mind.current
if(IS_CULTIST(G.summoner))
return TRUE //can't convert it unless the owner is converted
if(isgolem(mind.current))
return FALSE
if(isanimal(mind.current))
return FALSE
return TRUE
/**
* 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/team/cult/proc/cult_threshold_check()
var/list/living_players = get_living_players(exclude_nonhuman = TRUE, exclude_offstation = TRUE)
var/players = length(living_players)
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))
/datum/team/cult/proc/speak_to_all_alive_cultists(...)
var/message_to_sent = args.Join("<br>")
for(var/datum/mind/cult_mind in members)
if(cult_mind?.current)
to_chat(cult_mind.current, message_to_sent)
/datum/team/cult/get_admin_priority_objectives()
. = list()
.["Sacrifice"] = /datum/objective/sacrifice
.["Summon God"] = /datum/objective/eldergod
/datum/team/cult/handle_adding_admin_objective(mob/user, objective_type)
if(objective_type == /datum/objective/sacrifice)
if(obj_summon)
if(confirm_remove_eldergod_obj(user))
return TEAM_ADMIN_ADD_OBJ_SUCCESS
if(current_sac_objective())
var/alert_result = alert(user, "There is already a current sacrifice, reroll the cult's sacrifice target?", "Cult Debug", "Reroll", "Add new sacrifice", "Cancel")
if(alert_result == "Reroll")
admin_reroll_sac_target(user)
return TEAM_ADMIN_ADD_OBJ_SUCCESS | TEAM_ADMIN_ADD_OBJ_CANCEL_LOG
else if(alert_result == "Add new sacrifice")
return ..()
else
return TEAM_ADMIN_ADD_OBJ_PURPOSEFUL_CANCEL
return ..()
else if(objective_type == /datum/objective/eldergod)
if(confirm_add_eldergod_obj())
return TEAM_ADMIN_ADD_OBJ_SUCCESS
return TEAM_ADMIN_ADD_OBJ_PURPOSEFUL_CANCEL
return ..()
/datum/team/cult/admin_remove_objective(mob/user, datum/objective/O)
if(istype(O, /datum/objective/eldergod))
confirm_remove_eldergod_obj(user)
return
. = ..()
/datum/team/cult/proc/confirm_add_eldergod_obj(admin_caller, alert_text = "Unlock the ability to summon Nar'Sie?")
if(alert(admin_caller, alert_text, "Cult Debug", "Yes", "No") != "Yes")
return FALSE
ready_to_summon()
message_admins("Admin [key_name_admin(admin_caller)] has unlocked the Cult's ability to summon Nar'Sie.")
log_admin("Admin [key_name_admin(admin_caller)] has unlocked the Cult's ability to summon Nar'Sie.")
return TRUE
/datum/team/cult/proc/confirm_remove_eldergod_obj(admin_caller)
if(alert(admin_caller, "Revert to pre-summon stage of Cult?", "Cult Debug", "Yes", "No") != "Yes")
return FALSE
sacrifices_required = max(sacrifices_done + 1, sacrifices_required) // make sure we're at least one above the required amount
objective_holder.remove_objective(obj_summon) // qdel's the objective too
obj_summon = null
current_sac_objective() // Create an objective only if needed
cult_status = NARSIE_DEMANDS_SACRIFICE
message_admins("Admin [key_name_admin(admin_caller)] has removed the Cult's ability to summon Nar'Sie.")
log_admin("Admin [key_name_admin(admin_caller)] has removed the Cult's ability to summon Nar'Sie.")
return TRUE
/datum/team/cult/proc/study_objectives(mob/living/M, display_members = FALSE) //Called by cultists/cult constructs checking their objectives
if(!M)
return FALSE
switch(cult_status)
if(NARSIE_IS_ASLEEP)
to_chat(M, "<span class='cult'>[GET_CULT_DATA(entity_name, "The Dark One")] is asleep. This is probably a bug.</span>")
if(NARSIE_DEMANDS_SACRIFICE)
var/list/all_objectives = objective_holder.get_objectives()
if(!length(all_objectives))
to_chat(M, "<span class='danger'>Error: No objectives. Something went wrong, adminhelp with F1.</span>")
else
var/datum/objective/sacrifice/current_obj = all_objectives[length(all_objectives)] //get the last obj in the list, ie the current one
to_chat(M, "<span class='cult'>The Veil needs to be weakened before we are able to summon [GET_CULT_DATA(entity_title1, "The Dark One")].</span>")
to_chat(M, "<span class='cult'>Current goal: [current_obj.explanation_text]</span>")
if(NARSIE_NEEDS_SUMMONING)
to_chat(M, "<span class='cult'>The Veil is weak! We can summon [GET_CULT_DATA(entity_title3, "The Dark One")]!</span>")
to_chat(M, "<span class='cult'>Current goal: [obj_summon.explanation_text]</span>")
if(NARSIE_HAS_RISEN)
to_chat(M, "<span class='cultlarge'>\"I am here.\"</span>")
to_chat(M, "<span class='cult'>Current goal:</span> <span class='cultlarge'>\"Feed me.\"</span>")
if(NARSIE_HAS_FALLEN)
to_chat(M, "<span class='cultlarge'>[GET_CULT_DATA(entity_name, "The Dark One")] has been banished!</span>")
to_chat(M, "<span class='cult'>Current goal: Slaughter the unbelievers!</span>")
else
to_chat(M, "<span class='danger'>Error: Cult objective status currently unknown. Something went wrong, adminhelp with F1.</span>")
if(!display_members)
return
var/list/cult = get_cultists(separate = TRUE)
var/total_cult = cult[1] + cult[2]
var/overview = "<span class='cultitalic'><br><b>Current cult members: [total_cult]"
if(!cult_ascendant)
var/rise = rise_number - total_cult
var/ascend = ascend_number - total_cult
if(rise > 0)
overview += " | Conversions until Rise: [rise]"
else if(ascend > 0)
overview += " | Conversions until Ascension: [ascend]"
to_chat(M, "[overview]</b></span>")
if(cult[2]) // If there are any constructs, separate them out
to_chat(M, "<span class='cultitalic'><b>Cultists:</b> [cult[1]]")
to_chat(M, "<span class='cultitalic'><b>Constructs:</b> [cult[2]]")
/datum/team/cult/proc/create_next_sacrifice()
var/datum/objective/sacrifice/obj_sac = objective_holder.add_objective(/datum/objective/sacrifice)
if(!obj_sac.target)
objective_holder.remove_objective(obj_sac)
ready_to_summon()
return
return obj_sac
/// Return the current sacrifice objective datum, if any
/datum/team/cult/proc/current_sac_objective()
var/list/presummon_objs = objective_holder.get_objectives()
if(cult_status == NARSIE_DEMANDS_SACRIFICE && length(presummon_objs))
var/datum/objective/sacrifice/current_obj = presummon_objs[length(presummon_objs)]
if(current_obj.sacced)
return create_next_sacrifice()
if(istype(current_obj))
return current_obj
/datum/team/cult/proc/is_sac_target(datum/mind/mind)
var/datum/objective/sacrifice/current_obj = current_sac_objective()
return istype(current_obj) && current_obj.target == mind
/datum/team/cult/proc/find_new_sacrifice_target()
var/datum/objective/sacrifice/current_obj = current_sac_objective()
if(!current_obj)
return FALSE
if(!current_obj.find_target(list(current_obj.target)))
objective_holder.remove_objective(current_obj)
ready_to_summon()
return FALSE
speak_to_all_alive_cultists("<span class='danger'>[GET_CULT_DATA(entity_name, "Your god")]</span> murmurs, <span class='cultlarge'>Our goal is beyond your reach. Sacrifice [current_obj.target] instead...</span>")
return TRUE
/datum/team/cult/proc/successful_sacrifice()
var/datum/objective/sacrifice/current_obj = current_sac_objective()
if(!istype(current_obj))
return
current_obj.sacced = TRUE
sacrifices_done++
if(sacrifices_done >= sacrifices_required)
ready_to_summon()
return
var/datum/objective/sacrifice/obj_sac = create_next_sacrifice()
if(!obj_sac)
return
speak_to_all_alive_cultists(
"<span class='cult'>You and your acolytes have made progress, but there is more to do still before [GET_CULT_DATA(entity_title1, "The Dark One")] can be summoned!</span>",
"<span class='cult'>Current goal: [obj_sac.explanation_text]</span>"
)
/datum/team/cult/proc/ready_to_summon()
if(!obj_summon)
obj_summon = objective_holder.add_objective(/datum/objective/eldergod)
cult_status = NARSIE_NEEDS_SUMMONING
speak_to_all_alive_cultists(
"<span class='cult'>You and your acolytes have succeeded in preparing the station for the ultimate ritual!</span>",
"<span class='cult'>Current goal: [obj_summon.explanation_text]</span>"
)
/datum/team/cult/proc/successful_summon()
cult_status = NARSIE_HAS_RISEN
obj_summon.summoned = TRUE
/datum/team/cult/proc/narsie_death()
cult_status = NARSIE_HAS_FALLEN
obj_summon.killed = TRUE
speak_to_all_alive_cultists(
"<span class='cultlarge'>RETRIBUTION!</span>",
"<span class='cult'>Current goal: Slaughter the heretics!</span>"
)
/datum/team/cult/proc/get_cult_status_as_string()
var/list/define_to_string = list(
"[NARSIE_IS_ASLEEP]" = "NARSIE_IS_ASLEEP",
"[NARSIE_DEMANDS_SACRIFICE]" = "NARSIE_DEMANDS_SACRIFICE",
"[NARSIE_NEEDS_SUMMONING]" = "NARSIE_NEEDS_SUMMONING",
"[NARSIE_HAS_RISEN]" = "NARSIE_HAS_RISEN",
"[NARSIE_HAS_FALLEN]" = "NARSIE_HAS_FALLEN",
)
return define_to_string["[cult_status]"]
/**
* ADMIN STUFF DOWN YONDER
*/
/datum/team/cult/get_admin_commands()
return list(
"Cult Mindspeak" = CALLBACK(src, PROC_REF(cult_mindspeak))
)
/datum/team/cult/proc/cult_mindspeak(admin_caller)
var/input = stripped_input(admin_caller, "Communicate to all the cultists with the voice of [GET_CULT_DATA(entity_name, "a cult god")]", "Voice of [GET_CULT_DATA(entity_name, "Cult God")]")
if(!input)
return
speak_to_all_alive_cultists("<span class='cult'>[GET_CULT_DATA(entity_name, "Your god")] murmurs,</span> <span class='cultlarge'>\"[input]\"</span>")
for(var/mob/dead/observer/O in GLOB.player_list)
to_chat(O, "<span class='cult'>[GET_CULT_DATA(entity_name, "Your god")] murmurs,</span> <span class='cultlarge'>\"[input]\"</span>")
message_admins("Admin [key_name_admin(admin_caller)] has talked with the Voice of [GET_CULT_DATA(entity_name, "Cult God")].")
log_admin("[key_name(admin_caller)] Voice of [GET_CULT_DATA(entity_name, "Cult God")]: [input]")
/datum/team/cult/proc/admin_reroll_sac_target(mob/user)
var/datum/objective/sacrifice/current_obj = current_sac_objective()
var/choice = alert(usr, "How would you like to reroll the cult sacrifice?", "Pick objective", "Pick target", "Random reroll", "Cancel")
if(choice == "Pick target")
var/new_target = get_admin_objective_targets(user, get_target_excludes(), current_obj.target.current)
if(new_target)
current_obj.target = new_target
current_obj.update_explanation_text()
else if(choice == "Random reroll")
find_new_sacrifice_target()
else
return
message_admins("Admin [key_name_admin(user)] has rerolled the Cult's sacrifice target.")
log_admin("Admin [key_name_admin(user)] has rerolled the Cult's sacrifice target.")
user.client.holder.check_teams()
/datum/team/cult/Topic(href, href_list)
. = ..()
if(!check_rights(R_ADMIN))
return
// manually cramming some shit in here, because it only conditonally pops up
switch(href_list["cult_command"])
if("cult_adjustsacnumber")
var/amount = input("Adjust the amount of sacrifices required before summoning Nar'Sie", "Sacrifice Adjustment", 2) as null | num
if(amount > 0)
var/old = sacrifices_required
sacrifices_required = amount
message_admins("Admin [key_name_admin(usr)] has modified the amount of cult sacrifices required before summoning from [old] to [amount]")
log_admin("Admin [key_name_admin(usr)] has modified the amount of cult sacrifices required before summoning from [old] to [amount]")
if(sacrifices_done >= sacrifices_required)
confirm_add_eldergod_obj(usr, "Would you also like to unlock the summoning of Nar'sie?")
usr.client.holder.check_teams()
if("cult_newtarget")
if(alert(usr, "Reroll the cult's sacrifice target?", "Cult Debug", "Yes", "No") != "Yes")
return
admin_reroll_sac_target(usr)
if("cult_newsummonlocations")
if(!obj_summon)
to_chat(usr, "<span class='danger'>The cult has NO summon objective yet.</span>")
return
if(alert(usr, "Reroll the cult's summoning locations?", "Cult Debug", "Yes", "No") != "Yes")
return
obj_summon.find_summon_locations(TRUE)
if(cult_status == NARSIE_NEEDS_SUMMONING) //Only update cultists if they are already have the summon goal since they arent aware of summon spots till then
speak_to_all_alive_cultists(
"<span class='cult'>The veil has shifted! Our summoning will need to take place elsewhere.</span>",
"<span class='cult'>Current goal: [obj_summon.explanation_text]</span>"
)
message_admins("Admin [key_name_admin(usr)] has rerolled the Cult's sacrifice target.")
log_admin("Admin [key_name_admin(usr)] has rerolled the Cult's sacrifice target.")
usr.client.holder.check_teams()
/datum/team/cult/get_admin_html()
var/list/content = ..()
content += "<br><br>Cult Controls:<br>"
content += "<br>Cult Status: [get_cult_status_as_string()]"
content += "<br>Sacrifices completed: [sacrifices_done]"
content += "<br>Sacrifice required for summoning: [sacrifices_required]<br>"
if(obj_summon)
content += "<br>Summoning locations: [english_list(obj_summon.summon_spots)]"
content += "<br><a href='?src=[UID()];cult_command=cult_newsummonlocations'>Reroll summoning locations</a>"
else
content += "<br>Summoning locations: None, Cult has not yet reached the summoning stage."
content += "<br>"
if(cult_status == NARSIE_DEMANDS_SACRIFICE)
content += "<br><a href='?src=[UID()];cult_command=cult_adjustsacnumber'>Modify amount of sacrifices required</a>"
content += "<br><a href='?src=[UID()];cult_command=cult_newtarget'>Reroll sacrifice target</a>"
else
content += "<br>Cannot modify amount of sacrifices required (Summon available!)"
content += "<br>Cannot reroll sacrifice target (Summon available!)"
return content
@@ -57,8 +57,7 @@
/datum/antagonist/rev/head/proc/demote()
var/datum/mind/old_owner = owner
silent = TRUE
owner.remove_antag_datum(/datum/antagonist/rev/head)
owner.remove_antag_datum(/datum/antagonist/rev/head, silent_removal = TRUE)
var/datum/antagonist/rev/demoted = new()
demoted.silent = TRUE
@@ -38,7 +38,7 @@
return SSticker.mode.get_rev_team()
/datum/antagonist/rev/get_team()
return SSticker.mode.get_rev_team()
return SSticker.mode.rev_team
/datum/antagonist/rev/give_objectives()
var/datum/team/revolution/revolting = get_team()
@@ -46,8 +46,7 @@
/datum/antagonist/rev/proc/promote()
var/datum/mind/old_owner = owner
silent = TRUE
owner.remove_antag_datum(/datum/antagonist/rev, FALSE)
owner.remove_antag_datum(/datum/antagonist/rev, FALSE, silent_removal = TRUE)
var/datum/antagonist/rev/head/new_revhead = new()
new_revhead.silent = TRUE
@@ -4,27 +4,30 @@
var/max_headrevs = REVOLUTION_MAX_HEADREVS // adminbus is possible
var/have_we_won = FALSE
/datum/team/revolution/New()
..()
/datum/team/revolution/create_team()
. = ..()
update_team_objectives()
SSshuttle.registerHostileEnvironment(src)
/datum/team/revolution/Destroy(force, ...)
SSticker.mode.rev_team = null
SSshuttle.clearHostileEnvironment(src)
return ..()
/datum/team/revolution/can_create_team()
return isnull(SSticker.mode.rev_team)
/datum/team/revolution/assign_team()
SSticker.mode.rev_team = src
/datum/team/revolution/clear_team_reference()
if(SSticker.mode.rev_team == src)
SSticker.mode.rev_team = null
else
CRASH("[src] ([type]) attempted to clear a team reference that wasn't itself!")
/datum/team/revolution/get_target_excludes()
return ..() + get_targetted_head_minds()
/datum/team/revolution/remove_member(datum/mind/member)
. = ..()
var/datum/antagonist/rev/revolting = member.has_antag_datum(/datum/antagonist/rev) // maybe this should be get_antag_datum_from_member(member)
if(!QDELETED(revolting))
member.remove_antag_datum(/datum/antagonist/rev)
/datum/team/revolution/admin_add_objective(mob/user)
sanitize_objectives()
. = ..()
@@ -32,6 +35,10 @@
message_admins("[key_name_admin(user)] added a mutiny objective to the team '[name]', and no target was found, removing.")
log_admin("[key_name_admin(user)] added a mutiny objective to the team '[name]', and no target was found, removing.")
/datum/team/revolution/get_admin_priority_objectives()
. = list()
.["Mutiny"] = /datum/objective/mutiny
/datum/team/revolution/on_round_end()
return // for now... show nothing. Add this in when revs is added to midround/dynamic. Not showing it currently because its dependent on rev gamemode
-1
View File
@@ -111,7 +111,6 @@
if(SSticker && SSticker.mode)
other_antags += list(
"Blob" = (mind.special_role == SPECIAL_ROLE_BLOB),
"Cultist" = (mind in SSticker.mode.cult),
"Wizard" = (mind in SSticker.mode.wizards),
"Wizard's Apprentice" = (mind in SSticker.mode.apprentices),
"Nuclear Operative" = (mind in SSticker.mode.syndicates),
@@ -31,10 +31,10 @@
return "<span class='warning'>[p_they(TRUE)] [p_have()] [hand_blood_color != "#030303" ? "blood-stained":"oil-stained"] hands!</span>\n"
if("eyes")
if(HAS_TRAIT(src, SCRYING))
if(iscultist(src) && HAS_TRAIT(src, CULT_EYES))
if(IS_CULTIST(src) && HAS_TRAIT(src, CULT_EYES))
return "<span class='boldwarning'>[p_their(TRUE)] glowing red eyes are glazed over!</span>\n"
return "<span class='boldwarning'>[p_their(TRUE)] eyes are glazed over.</span>\n"
if(iscultist(src) && HAS_TRAIT(src, CULT_EYES))
if(IS_CULTIST(src) && HAS_TRAIT(src, CULT_EYES))
return "<span class='boldwarning'>[p_their(TRUE)] eyes are glowing an unnatural red!</span>\n"
return msg
@@ -1676,7 +1676,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
rad_act(current_size * 3)
/mob/living/carbon/human/narsie_act()
if(iswizard(src) && iscultist(src)) //Wizard cultists are immune to narsie because it would prematurely end the wiz round that's about to end by the automated shuttle call anyway
if(iswizard(src) && IS_CULTIST(src)) //Wizard cultists are immune to narsie because it would prematurely end the wiz round that's about to end by the automated shuttle call anyway
return
..()
@@ -1343,7 +1343,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
/mob/living/carbon/human/proc/update_halo_layer()
remove_overlay(HALO_LAYER)
if(iscultist(src) && SSticker.mode.cult_ascendant)
if(IS_CULTIST(src) && SSticker.mode.cult_team.cult_ascendant)
var/istate = pick("halo1", "halo2", "halo3", "halo4", "halo5", "halo6")
var/mutable_appearance/new_halo_overlay = mutable_appearance('icons/effects/32x64.dmi', istate, -HALO_LAYER)
overlays_standing[HALO_LAYER] = new_halo_overlay
-5
View File
@@ -482,11 +482,6 @@
C.reagents.clear_reagents()
QDEL_LIST_CONTENTS(C.reagents.addiction_list)
C.reagents.addiction_threshold_accumulated.Cut()
if(iscultist(src))
if(SSticker.mode.cult_risen)
SSticker.mode.rise(src)
if(SSticker.mode.cult_ascendant)
SSticker.mode.ascend(src)
QDEL_LIST_CONTENTS(C.processing_patches)
@@ -39,8 +39,6 @@ GLOBAL_DATUM_INIT(paiController, /datum/paiController, new) // Global handler fo
card.setPersonality(pai)
card.looking_for_personality = 0
SSticker.mode.update_cult_icons_removed(card.pai.mind)
pai_candidates -= candidate
usr << browse(null, "window=findPai")
return
@@ -2,7 +2,7 @@
SetSleeping(0)
if(mind && SSticker && SSticker.mode)
SSticker.mode.remove_revolutionary(mind, 1)
SSticker.mode.remove_cultist(mind, 1)
mind.remove_antag_datum(/datum/antagonist/cultist)
SSticker.mode.remove_wizard(mind)
mind.remove_antag_datum(/datum/antagonist/changeling)
mind.remove_antag_datum(/datum/antagonist/vampire)
@@ -36,30 +36,26 @@
/mob/living/simple_animal/hostile/construct/Initialize(mapload)
. = ..()
if(!SSticker.mode)//work around for maps with runes and cultdat is not loaded all the way
name = "[construct_type] ([rand(1, 1000)])"
real_name = construct_type
icon_living = construct_type
icon_state = construct_type
else
name = "[SSticker.cultdat.get_name(construct_type)] ([rand(1, 1000)])"
real_name = SSticker.cultdat.get_name(construct_type)
icon_living = SSticker.cultdat.get_icon(construct_type)
icon_state = SSticker.cultdat.get_icon(construct_type)
name = "[GET_CULT_DATA(get_name(construct_type), construct_type)] ([rand(1, 1000)])"
real_name = GET_CULT_DATA(get_name(construct_type), construct_type)
icon_living = GET_CULT_DATA(get_icon(construct_type), construct_type)
icon_state = GET_CULT_DATA(get_icon(construct_type), construct_type)
for(var/spell in construct_spells)
AddSpell(new spell(null))
set_light(2, 3, l_color = SSticker.cultdat ? SSticker.cultdat.construct_glow : LIGHT_COLOR_BLOOD_MAGIC)
set_light(2, 3, l_color = GET_CULT_DATA(construct_glow, LIGHT_COLOR_BLOOD_MAGIC))
/mob/living/simple_animal/hostile/construct/Destroy()
mind?.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE)
remove_held_body()
return ..()
/mob/living/simple_animal/hostile/construct/death(gibbed)
mind?.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE)
if(held_body) // Null check for empty bodies
held_body.forceMove(get_turf(src))
SSticker.mode.add_cult_immunity(held_body)
SSticker.mode?.cult_team?.add_cult_immunity(held_body)
if(ismob(held_body)) // Check if the held_body is a mob
held_body.key = key
else if(istype(held_body, /obj/item/organ/internal/brain)) // Check if the held_body is a brain
@@ -72,10 +68,6 @@
playsound(src, 'sound/effects/pylon_shatter.ogg', 40, TRUE)
return ..()
/mob/living/simple_animal/hostile/construct/Destroy()
SSticker.mode.remove_cultist(show_message = FALSE, target_mob = src)
return ..()
/mob/living/simple_animal/hostile/construct/proc/add_held_body(atom/movable/body)
held_body = body
RegisterSignal(body, COMSIG_PARENT_QDELETING, PROC_REF(remove_held_body))
@@ -373,7 +373,7 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/hit_up_narsi()
SetRecoveryTime(20)
visible_message("<span class='colossus'><b>[pick("[SSticker.cultdat.entity_name], I call on YOU for one of MY favours you owe me!", "[SSticker.cultdat.entity_title1], I call on you for some support...", "Let us see how you like the minions of [SSticker.cultdat.entity_title2]!", "Oh, [SSticker.cultdat.entity_title3] join me in RENDING THIS WHELP APART!")]</b></span>")
visible_message("<span class='colossus'><b>[pick("[GET_CULT_DATA(entity_name, "Nar'sie")], I call on YOU for one of MY favours you owe me!", "[GET_CULT_DATA(entity_title1, "Nar'sie")], I call on you for some support...", "Let us see how you like the minions of [GET_CULT_DATA(entity_title2, "Nar'sie")]!", "Oh, [GET_CULT_DATA(entity_title3, "Nar'sie")] join me in RENDING THIS WHELP APART!")]</b></span>")
var/list/turfs = list()
var/constructs = 0
for(var/turf/T in view(6, target))
@@ -284,7 +284,7 @@
continue
if(T.z != usr.z) //No crossing zlvls
continue
if(istype(i, /obj/item/shield/mirror) && !iscultist(usr)) //No teleporting to cult bases
if(istype(i, /obj/item/shield/mirror) && !IS_CULTIST(usr)) //No teleporting to cult bases
continue
if(istype(i, /obj/structure/mirror))
var/obj/structure/mirror/B = i
@@ -34,12 +34,8 @@
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/Destroy()
SSticker.mode.remove_cultist(show_message = FALSE, target_mob = src)
mind?.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE)
return ..()
/mob/living/simple_animal/shade/attackby(obj/item/O, mob/user) //Marker -Agouri
@@ -56,6 +52,12 @@
holy = TRUE
icon_state = "shade_angelic"
/mob/living/simple_animal/shade/cult
/mob/living/simple_animal/shade/cult/Initialize(mapload)
. = ..()
icon_state = GET_CULT_DATA(shade_icon_state, initial(icon_state))
/mob/living/simple_animal/shade/sword
faction = list("neutral")
a_intent = INTENT_HARM // scuffed sword mechanics bad
+2 -3
View File
@@ -1486,12 +1486,11 @@ GLOBAL_LIST_INIT(holy_areas, typecacheof(list(
return FALSE
//Allows cult to bypass holy areas once they summon
var/datum/game_mode/gamemode = SSticker.mode
if(iscultist(src) && gamemode.cult_objs.cult_status == NARSIE_HAS_RISEN)
if(mind.has_antag_datum(/datum/antagonist/cultist) && SSticker.mode.cult_team.cult_status == NARSIE_HAS_RISEN)
return FALSE
//Execption for Holy Constructs
if(isconstruct(src) && !iscultist(src))
if(isconstruct(src) && !mind.has_antag_datum(/datum/antagonist/cultist))
return FALSE
to_chat(src, "<span class='warning'>Your powers are useless on this holy ground.</span>")
@@ -28,8 +28,8 @@
/obj/singularity/narsie/large/Initialize(mapload, starting_energy)
. = ..()
icon_state = SSticker.cultdat?.entity_icon_state
name = SSticker.cultdat?.entity_name
icon_state = GET_CULT_DATA(entity_icon_state, initial(icon_state))
name = GET_CULT_DATA(entity_name, initial(name))
var/sound/cry = sound(pick('sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg'))
@@ -40,9 +40,7 @@
to_chat(player, "<font size='15' color='red'><b> [uppertext(name)] HAS RISEN</b></font>")
SEND_SOUND(player, cry)
var/datum/game_mode/gamemode = SSticker.mode
if(gamemode)
gamemode.cult_objs.succesful_summon()
SSticker.mode?.cult_team?.successful_summon()
var/area/A = get_area(src)
if(A)
@@ -59,13 +57,7 @@
/obj/singularity/narsie/large/Destroy()
to_chat(world, "<font size='15' color='red'><b> [uppertext(name)] HAS FALLEN</b></font>")
SEND_SOUND(world, sound('sound/hallucinations/wail.ogg'))
var/datum/game_mode/gamemode = SSticker.mode
if(gamemode)
gamemode.cult_objs.narsie_death()
for(var/datum/mind/cult_mind in SSticker.mode.cult)
if(cult_mind && cult_mind.current)
to_chat(cult_mind.current, "<span class='cultlarge'>RETRIBUTION!</span>")
to_chat(cult_mind.current, "<span class='cult'>Current goal: Slaughter the heretics!</span>")
SSticker.mode?.cult_team?.narsie_death()
..()
/obj/singularity/narsie/large/attack_ghost(mob/dead/observer/user as mob)
@@ -102,7 +94,7 @@
/obj/singularity/narsie/mezzer()
for(var/mob/living/carbon/M in oviewers(8, src))
if(M.stat == CONSCIOUS)
if(!iscultist(M))
if(!IS_CULTIST(M))
to_chat(M, "<span class='warning'>You feel your sanity crumble away in an instant as you gaze upon [src.name]...</span>")
M.Stun(6 SECONDS)
@@ -129,7 +121,7 @@
if(pos.z != src.z)
continue
if(iscultist(food))
if(IS_CULTIST(food))
cultists += food
else
noncultists += food
@@ -160,12 +152,12 @@
return
if(!target)
return
to_chat(target, "<span class='cultlarge'>[uppertext(SSticker.cultdat.entity_name)] HAS LOST INTEREST IN YOU</span>")
to_chat(target, "<span class='cultlarge'>[uppertext(GET_CULT_DATA(entity_name, name))] HAS LOST INTEREST IN YOU</span>")
target = food
if(ishuman(target))
to_chat(target, "<span class ='cultlarge'>[uppertext(SSticker.cultdat.entity_name)] HUNGERS FOR YOUR SOUL</span>")
to_chat(target, "<span class ='cultlarge'>[uppertext(GET_CULT_DATA(entity_name, name))] HUNGERS FOR YOUR SOUL</span>")
else
to_chat(target, "<span class ='cultlarge'>[uppertext(SSticker.cultdat.entity_name)] HAS CHOSEN YOU TO LEAD HER TO HER NEXT MEAL</span>")
to_chat(target, "<span class ='cultlarge'>[uppertext(GET_CULT_DATA(entity_name, name))] HAS CHOSEN YOU TO LEAD HER TO HER NEXT MEAL</span>")
//Wizard narsie
/obj/singularity/narsie/wizard
@@ -182,7 +174,7 @@
icon = 'icons/obj/narsie_spawn_anim.dmi'
dir = SOUTH
move_self = FALSE
flick(SSticker.cultdat?.entity_spawn_animation, src)
flick(GET_CULT_DATA(entity_spawn_animation, "narsie_spawn_anim"), src)
sleep(11)
move_self = TRUE
icon = initial(icon)
@@ -314,10 +314,10 @@
set_light(10)
if(istype(A, /obj/singularity/narsie))
if(current_size == STAGE_SIX)
visible_message("<span class='userdanger'>[SSticker.cultdat?.entity_name] is consumed by [src]!</span>")
visible_message("<span class='userdanger'>[GET_CULT_DATA(entity_name, A.name)] is consumed by [src]!</span>")
qdel(A)
else
visible_message("<span class='userdanger'>[SSticker.cultdat?.entity_name] strikes down [src]!</span>")
visible_message("<span class='userdanger'>[GET_CULT_DATA(entity_name, A.name)] strikes down [src]!</span>")
investigate_log("has been destroyed by Nar'Sie","singulo")
qdel(src)
@@ -260,7 +260,7 @@
if(current_cycle >= 30) // 12 units, 60 seconds @ metabolism 0.4 units & tick rate 2.0 sec
M.AdjustStuttering(8 SECONDS, bound_lower = 0, bound_upper = 40 SECONDS)
M.Dizzy(10 SECONDS)
if(iscultist(M))
if(IS_CULTIST(M))
for(var/datum/action/innate/cult/blood_magic/BM in M.actions)
for(var/datum/action/innate/cult/blood_spell/BS in BM.spells)
to_chat(M, "<span class='cultlarge'>Your blood rites falter as holy water scours your body!</span>")
@@ -278,14 +278,18 @@
M.AdjustConfused(6 SECONDS)
if(isvampirethrall(M))
M.mind.remove_antag_datum(/datum/antagonist/mindslave/thrall)
holder.remove_reagent(id, volume)
M.visible_message("<span class='biggerdanger'>[M] recoils, their skin flushes with colour, regaining their sense of control!</span>")
M.SetJitter(0)
M.SetStuttering(0)
M.SetConfused(0)
return
if(iscultist(M))
SSticker.mode.remove_cultist(M.mind, TRUE, TRUE)
if(IS_CULTIST(M))
var/datum/antagonist/cultist/cultist = IS_CULTIST(M)
cultist.remove_gear_on_removal = TRUE
M.mind.remove_antag_datum(/datum/antagonist/cultist)
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)
@@ -374,7 +378,7 @@
/datum/reagent/fuel/unholywater/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
if(iscultist(M))
if(IS_CULTIST(M))
M.AdjustDrowsy(-10 SECONDS)
M.AdjustParalysis(-2 SECONDS)
M.AdjustStunned(-4 SECONDS)
+2 -2
View File
@@ -150,7 +150,7 @@ GLOBAL_DATUM_INIT(multispin_words, /regex, regex("like a record baby"))
/obj/item/organ/internal/vocal_cords/colossus/handle_speech(message)
spans = "colossus yell" //reset spans, just in case someone gets deculted or the cords change owner
if(iscultist(owner))
if(IS_CULTIST(owner))
spans += "narsiesmall"
return "<span class=\"[spans]\">[uppertext(message)]</span>"
@@ -186,7 +186,7 @@ GLOBAL_DATUM_INIT(multispin_words, /regex, regex("like a record baby"))
power_multiplier *= 0.5
//Cultists are closer to their gods and are more powerful, but they'll give themselves away
if(iscultist(owner))
if(IS_CULTIST(owner))
power_multiplier *= 2
//It's magic, they are a wizard.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

+2 -1
View File
@@ -885,7 +885,6 @@
#include "code\game\machinery\vendors\tilt_crits.dm"
#include "code\game\machinery\vendors\vending.dm"
#include "code\game\machinery\vendors\wardrobe_vendors.dm"
#include "code\game\magic\Uristrunes.dm"
#include "code\game\mecha\mech_bay.dm"
#include "code\game\mecha\mech_fabricator.dm"
#include "code\game\mecha\mecha.dm"
@@ -1434,6 +1433,8 @@
#include "code\modules\antagonists\changeling\powers\swap_form.dm"
#include "code\modules\antagonists\changeling\powers\tiny_prick.dm"
#include "code\modules\antagonists\changeling\powers\transform.dm"
#include "code\modules\antagonists\cult\datum_cultist.dm"
#include "code\modules\antagonists\cult\team_cult.dm"
#include "code\modules\antagonists\revolutionary\datum_headrev.dm"
#include "code\modules\antagonists\revolutionary\datum_revolutionary.dm"
#include "code\modules\antagonists\revolutionary\team_revolution.dm"