From 1a32fe06c9f4ae291a085db01b043e4a3ec1df27 Mon Sep 17 00:00:00 2001 From: Geeves Date: Sat, 8 Feb 2020 14:17:32 +0200 Subject: [PATCH] Cult Revamp (#8075) --- aurorastation.dme | 41 +- code/game/antagonist/antagonist_helpers.dm | 17 +- code/game/antagonist/station/cultist.dm | 11 +- code/game/gamemodes/cult/cult.dm | 4 +- code/game/gamemodes/cult/cult_items.dm | 131 -- code/game/gamemodes/cult/hell_universe.dm | 7 +- code/game/gamemodes/cult/items/armor.dm | 41 + code/game/gamemodes/cult/items/clothes.dm | 36 + code/game/gamemodes/cult/items/sword.dm | 57 + code/game/gamemodes/cult/items/talisman.dm | 35 + code/game/gamemodes/cult/items/tome.dm | 200 +++ code/game/gamemodes/cult/ritual.dm | 594 --------- code/game/gamemodes/cult/runes.dm | 1144 ----------------- code/game/gamemodes/cult/runes/armor.dm | 53 + .../game/gamemodes/cult/runes/blind_others.dm | 46 + code/game/gamemodes/cult/runes/blood_boil.dm | 26 + code/game/gamemodes/cult/runes/blood_drain.dm | 40 + code/game/gamemodes/cult/runes/communicate.dm | 23 + code/game/gamemodes/cult/runes/conversion.dm | 86 ++ .../gamemodes/cult/runes/create_talisman.dm | 36 + .../gamemodes/cult/runes/deafen_others.dm | 44 + code/game/gamemodes/cult/runes/emp.dm | 24 + .../game/gamemodes/cult/runes/free_cultist.dm | 61 + code/game/gamemodes/cult/runes/ghost_mode.dm | 19 + code/game/gamemodes/cult/runes/hide_runes.dm | 23 + .../gamemodes/cult/runes/manifest_ghost.dm | 54 + code/game/gamemodes/cult/runes/raise_dead.dm | 84 ++ .../game/gamemodes/cult/runes/reveal_runes.dm | 48 + code/game/gamemodes/cult/runes/rune.dm | 98 ++ code/game/gamemodes/cult/runes/sacrifice.dm | 83 ++ .../gamemodes/cult/runes/see_invisible.dm | 17 + code/game/gamemodes/cult/runes/stun.dm | 34 + .../gamemodes/cult/runes/summon_cultist.dm | 39 + .../gamemodes/cult/runes/summon_narsie.dm | 30 + code/game/gamemodes/cult/runes/summon_tome.dm | 14 + code/game/gamemodes/cult/runes/teleport.dm | 56 + code/game/gamemodes/cult/runes/wall.dm | 9 + code/game/gamemodes/cult/structures/altar.dm | 44 + code/game/gamemodes/cult/structures/desk.dm | 12 + code/game/gamemodes/cult/structures/forge.dm | 10 + .../game/gamemodes/cult/structures/gateway.dm | 51 + .../pylon.dm} | 126 +- .../gamemodes/cult/structures/structure.dm | 8 + code/game/gamemodes/cult/talisman.dm | 118 -- code/game/magic/Uristrunes.dm | 128 -- .../objects/items/weapons/chaplain_items.dm | 5 +- code/game/turfs/turf.dm | 2 +- code/modules/admin/admin_verbs.dm | 3 - .../modules/mob/abstract/observer/observer.dm | 9 +- .../living/carbon/human/species/species.dm | 6 +- code/modules/mob/living/silicon/ai/login.dm | 2 - code/modules/spells/general/rune_write.dm | 215 +--- html/changelogs/geeves-cultstuff.yml | 24 + icons/obj/cult.dmi | Bin 37324 -> 37322 bytes icons/obj/rune.dmi | Bin 4141 -> 8764 bytes 55 files changed, 1668 insertions(+), 2460 deletions(-) delete mode 100644 code/game/gamemodes/cult/cult_items.dm create mode 100644 code/game/gamemodes/cult/items/armor.dm create mode 100644 code/game/gamemodes/cult/items/clothes.dm create mode 100644 code/game/gamemodes/cult/items/sword.dm create mode 100644 code/game/gamemodes/cult/items/talisman.dm create mode 100644 code/game/gamemodes/cult/items/tome.dm delete mode 100644 code/game/gamemodes/cult/ritual.dm delete mode 100644 code/game/gamemodes/cult/runes.dm create mode 100644 code/game/gamemodes/cult/runes/armor.dm create mode 100644 code/game/gamemodes/cult/runes/blind_others.dm create mode 100644 code/game/gamemodes/cult/runes/blood_boil.dm create mode 100644 code/game/gamemodes/cult/runes/blood_drain.dm create mode 100644 code/game/gamemodes/cult/runes/communicate.dm create mode 100644 code/game/gamemodes/cult/runes/conversion.dm create mode 100644 code/game/gamemodes/cult/runes/create_talisman.dm create mode 100644 code/game/gamemodes/cult/runes/deafen_others.dm create mode 100644 code/game/gamemodes/cult/runes/emp.dm create mode 100644 code/game/gamemodes/cult/runes/free_cultist.dm create mode 100644 code/game/gamemodes/cult/runes/ghost_mode.dm create mode 100644 code/game/gamemodes/cult/runes/hide_runes.dm create mode 100644 code/game/gamemodes/cult/runes/manifest_ghost.dm create mode 100644 code/game/gamemodes/cult/runes/raise_dead.dm create mode 100644 code/game/gamemodes/cult/runes/reveal_runes.dm create mode 100644 code/game/gamemodes/cult/runes/rune.dm create mode 100644 code/game/gamemodes/cult/runes/sacrifice.dm create mode 100644 code/game/gamemodes/cult/runes/see_invisible.dm create mode 100644 code/game/gamemodes/cult/runes/stun.dm create mode 100644 code/game/gamemodes/cult/runes/summon_cultist.dm create mode 100644 code/game/gamemodes/cult/runes/summon_narsie.dm create mode 100644 code/game/gamemodes/cult/runes/summon_tome.dm create mode 100644 code/game/gamemodes/cult/runes/teleport.dm create mode 100644 code/game/gamemodes/cult/runes/wall.dm create mode 100644 code/game/gamemodes/cult/structures/altar.dm create mode 100644 code/game/gamemodes/cult/structures/desk.dm create mode 100644 code/game/gamemodes/cult/structures/forge.dm create mode 100644 code/game/gamemodes/cult/structures/gateway.dm rename code/game/gamemodes/cult/{cult_structures.dm => structures/pylon.dm} (81%) create mode 100644 code/game/gamemodes/cult/structures/structure.dm delete mode 100644 code/game/gamemodes/cult/talisman.dm delete mode 100644 code/game/magic/Uristrunes.dm create mode 100644 html/changelogs/geeves-cultstuff.yml diff --git a/aurorastation.dme b/aurorastation.dme index 03d835bbfc5..8247eb13a14 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -455,16 +455,46 @@ #include "code\game\gamemodes\changeling\implements\powers\stings.dm" #include "code\game\gamemodes\changeling\implements\powers\suck.dm" #include "code\game\gamemodes\cult\cult.dm" -#include "code\game\gamemodes\cult\cult_items.dm" -#include "code\game\gamemodes\cult\cult_structures.dm" #include "code\game\gamemodes\cult\hell_universe.dm" #include "code\game\gamemodes\cult\narsie.dm" -#include "code\game\gamemodes\cult\ritual.dm" -#include "code\game\gamemodes\cult\runes.dm" -#include "code\game\gamemodes\cult\talisman.dm" #include "code\game\gamemodes\cult\cultify\mob.dm" #include "code\game\gamemodes\cult\cultify\obj.dm" #include "code\game\gamemodes\cult\cultify\turf.dm" +#include "code\game\gamemodes\cult\items\armor.dm" +#include "code\game\gamemodes\cult\items\clothes.dm" +#include "code\game\gamemodes\cult\items\sword.dm" +#include "code\game\gamemodes\cult\items\talisman.dm" +#include "code\game\gamemodes\cult\items\tome.dm" +#include "code\game\gamemodes\cult\runes\armor.dm" +#include "code\game\gamemodes\cult\runes\blind_others.dm" +#include "code\game\gamemodes\cult\runes\blood_boil.dm" +#include "code\game\gamemodes\cult\runes\blood_drain.dm" +#include "code\game\gamemodes\cult\runes\communicate.dm" +#include "code\game\gamemodes\cult\runes\conversion.dm" +#include "code\game\gamemodes\cult\runes\create_talisman.dm" +#include "code\game\gamemodes\cult\runes\deafen_others.dm" +#include "code\game\gamemodes\cult\runes\emp.dm" +#include "code\game\gamemodes\cult\runes\free_cultist.dm" +#include "code\game\gamemodes\cult\runes\ghost_mode.dm" +#include "code\game\gamemodes\cult\runes\hide_runes.dm" +#include "code\game\gamemodes\cult\runes\manifest_ghost.dm" +#include "code\game\gamemodes\cult\runes\raise_dead.dm" +#include "code\game\gamemodes\cult\runes\reveal_runes.dm" +#include "code\game\gamemodes\cult\runes\rune.dm" +#include "code\game\gamemodes\cult\runes\sacrifice.dm" +#include "code\game\gamemodes\cult\runes\see_invisible.dm" +#include "code\game\gamemodes\cult\runes\stun.dm" +#include "code\game\gamemodes\cult\runes\summon_cultist.dm" +#include "code\game\gamemodes\cult\runes\summon_narsie.dm" +#include "code\game\gamemodes\cult\runes\summon_tome.dm" +#include "code\game\gamemodes\cult\runes\teleport.dm" +#include "code\game\gamemodes\cult\runes\wall.dm" +#include "code\game\gamemodes\cult\structures\altar.dm" +#include "code\game\gamemodes\cult\structures\desk.dm" +#include "code\game\gamemodes\cult\structures\forge.dm" +#include "code\game\gamemodes\cult\structures\gateway.dm" +#include "code\game\gamemodes\cult\structures\pylon.dm" +#include "code\game\gamemodes\cult\structures\structure.dm" #include "code\game\gamemodes\endgame\endgame.dm" #include "code\game\gamemodes\endgame\supermatter_cascade\blob.dm" #include "code\game\gamemodes\endgame\supermatter_cascade\portal.dm" @@ -701,7 +731,6 @@ #include "code\game\machinery\telecomms\telecomunications.dm" #include "code\game\machinery\telecomms\telemonitor.dm" #include "code\game\machinery\telecomms\traffic_control.dm" -#include "code\game\magic\Uristrunes.dm" #include "code\game\modifiers\modifiers.dm" #include "code\game\modifiers\modifiers_chem.dm" #include "code\game\objects\buckling.dm" diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm index b876de0d738..fd3c4ba5c6e 100644 --- a/code/game/antagonist/antagonist_helpers.dm +++ b/code/game/antagonist/antagonist_helpers.dm @@ -1,18 +1,19 @@ /datum/antagonist/proc/can_become_antag(var/datum/mind/player, var/ignore_role) - if (!player.current) - return 0 + if(!player.current) + return FALSE if(jobban_isbanned(player.current, bantype)) - return 0 - if(required_age && required_age > player.current.client.player_age) return FALSE if(!ignore_role) + if(establish_db_connection(dbcon)) //no database, no age restriction + if(required_age && required_age > player.current.client.player_age) + return FALSE if(player.assigned_role in restricted_jobs) - return 0 + return FALSE if(config.protect_roles_from_antagonist && (player.assigned_role in protected_jobs)) - return 0 + return FALSE if(player.current.client.prefs && player.current.client.prefs.species in restricted_species) - return 0 - return 1 + return FALSE + return TRUE /datum/antagonist/proc/antags_are_dead() for(var/datum/mind/antag in current_antagonists) diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm index c704b06b3d0..5b4cd377e1d 100644 --- a/code/game/antagonist/station/cultist.dm +++ b/code/game/antagonist/station/cultist.dm @@ -38,7 +38,6 @@ var/datum/antagonist/cultist/cult var/allow_narsie = 1 var/datum/mind/sacrifice_target - var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide") var/list/sacrificed = list() var/list/harvested = list() @@ -67,7 +66,7 @@ var/datum/antagonist/cultist/cult if(!..()) return 0 - var/obj/item/paper/talisman/supply/T = new(get_turf(player)) + var/obj/item/book/tome/T = new(get_turf(player)) var/list/slots = list ( "backpack" = slot_in_backpack, "left pocket" = slot_l_store, @@ -102,8 +101,8 @@ var/datum/antagonist/cultist/cult /datum/antagonist/cultist/can_become_antag(var/datum/mind/player, ignore_role = 1) if(!..()) - return 0 + return FALSE for(var/obj/item/implant/loyalty/L in player.current) - if(L && (L.imp_in == player.current)) - return 0 - return 1 + if(L?.imp_in == player.current) + return FALSE + return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index fca728d49a7..13a65618ecd 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -5,5 +5,5 @@ config_tag = "cult" required_players = 9 required_enemies = 4 - end_on_antag_death = 1 - antag_tags = list(MODE_CULTIST) + end_on_antag_death = FALSE + antag_tags = list(MODE_CULTIST) \ No newline at end of file diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm deleted file mode 100644 index aad97a2538e..00000000000 --- a/code/game/gamemodes/cult/cult_items.dm +++ /dev/null @@ -1,131 +0,0 @@ -/obj/item/melee/cultblade - name = "eldritch blade" - desc = "A sword humming with unholy energy. It glows with a dim red light." - icon_state = "cultblade" - item_state = "cultblade" - icon = 'icons/obj/weapons.dmi' - w_class = 4 - force = 30 - throwforce = 10 - edge = 1 - sharp = 1 - hitsound = 'sound/weapons/bladeslice.ogg' - - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - can_embed = 0 //can't get stuck anymore, because blood magic - -/obj/item/melee/cultblade/cultify() - return - -/obj/item/melee/cultblade/attack(mob/living/M, mob/living/user, var/target_zone) - if(iscultist(user)) - return ..() - - var/zone = (user.hand ? BP_L_ARM:BP_R_ARM) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - var/obj/item/organ/external/affecting = H.get_organ(zone) - to_chat(user, "An unexplicable force rips through your [affecting.name], tearing the sword from your grasp!") - else - to_chat(user, "An unexplicable force rips through you, tearing the sword from your grasp!") - - //random amount of damage between half of the blade's force and the full force of the blade. - user.apply_damage(rand(force/2, force), BRUTE, zone, 0, sharp=1, edge=1) - user.Weaken(5) - - user.drop_from_inventory(src) - throw_at(get_edge_target_turf(src, pick(alldirs)), rand(1,3), throw_speed) - - var/spooky = pick('sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg', 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/wail.ogg') - playsound(loc, spooky, 50, 1) - - return 1 - -/obj/item/melee/cultblade/pickup(mob/living/user as mob) - ..() - if(!iscultist(user)) - to_chat(user, "An overwhelming feeling of dread comes over you as you pick up \the [src]. It would be wise to be rid of this blade quickly.") - user.make_dizzy(120) - -/obj/item/melee/cultblade/attackby(var/obj/item/I, var/mob/user) - ..() - if(istype(I, /obj/item/nullrod)) - to_chat(user, "You cleanse \the [src] of taint, restoring the blade to its original state.") - var/obj/item/material/sword/blade = new(get_turf(src)) - blade.force = 15 - qdel(src) - -/obj/item/clothing/head/culthood - name = "ragged hood" - icon_state = "culthood" - desc = "A torn, dust-caked hood." - flags_inv = HIDEFACE|HIDEEARS|HIDEEYES - body_parts_covered = HEAD|EYES - armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0) - cold_protection = HEAD - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0 - -/obj/item/clothing/head/culthood/cultify() - return - -/obj/item/clothing/head/culthood/magus - name = "magus helm" - icon_state = "magus" - desc = "A helm worn by the followers of Nar-Sie." - flags_inv = HIDEFACE | BLOCKHAIR - body_parts_covered = HEAD|FACE|EYES - -/obj/item/clothing/head/culthood/alt - icon_state = "cult_hoodalt" - -/obj/item/clothing/suit/cultrobes - name = "ragged robes" - desc = "A ragged, dusty set of robes." - icon_state = "cultrobes" - item_state = "cultrobes" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/book/tome,/obj/item/melee/cultblade) - armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0) - flags_inv = HIDEJUMPSUIT - siemens_coefficient = 0 - -/obj/item/clothing/suit/cultrobes/cultify() - return - -/obj/item/clothing/suit/cultrobes/alt - icon_state = "cultrobesalt" - item_state = "cultrobesalt" - -/obj/item/clothing/suit/cultrobes/magusred - name = "magus robes" - desc = "A set of armored robes worn by the followers of Nar-Sie." - icon_state = "magusred" - item_state = "magusred" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - flags_inv = HIDEGLOVES|HIDEJUMPSUIT - -/obj/item/clothing/head/helmet/space/cult - name = "eldritch helmet" - desc = "A bulky helmet, bristling with spikes. It looks space proof." - icon_state = "cult_helmet" - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - siemens_coefficient = 0 - -/obj/item/clothing/head/helmet/space/cult/cultify() - return - -/obj/item/clothing/suit/space/cult - name = "eldritch armour" - icon_state = "cult_armour" - item_state = "cult_armour" - desc = "A bulky suit of armour, bristling with spikes. It looks space proof." - w_class = 3 - allowed = list(/obj/item/book/tome,/obj/item/melee/cultblade,/obj/item/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit) - slowdown = 1 - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - siemens_coefficient = 0 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS - -/obj/item/clothing/suit/space/cult/cultify() - return diff --git a/code/game/gamemodes/cult/hell_universe.dm b/code/game/gamemodes/cult/hell_universe.dm index 1f6eda7e2e8..2bff07e1403 100644 --- a/code/game/gamemodes/cult/hell_universe.dm +++ b/code/game/gamemodes/cult/hell_universe.dm @@ -17,11 +17,6 @@ In short: /datum/universal_state/hell/OnShuttleCall(var/mob/user) return 1 - /* - if(user) - to_chat(user, "All you hear on the frequency is static and panicked screaming. There will be no shuttle call today.") - return 0 - */ /datum/universal_state/hell/DecayTurf(var/turf/T) if(!T.holy) @@ -53,7 +48,7 @@ In short: KillMobs() OverlayAndAmbientSet() - runedec += 9000 //basically removing the rune cap + rune_boost += 9001 //basically removing the rune cap /datum/universal_state/hell/proc/AreaSet() for(var/area/A in all_areas) diff --git a/code/game/gamemodes/cult/items/armor.dm b/code/game/gamemodes/cult/items/armor.dm new file mode 100644 index 00000000000..a9d043757b2 --- /dev/null +++ b/code/game/gamemodes/cult/items/armor.dm @@ -0,0 +1,41 @@ +/obj/item/clothing/head/culthood/magus + name = "magus helm" + icon_state = "magus" + desc = "A helm worn by the followers of Nar-Sie." + flags_inv = HIDEFACE | BLOCKHAIR + body_parts_covered = HEAD|FACE|EYES + +/obj/item/clothing/suit/cultrobes/magusred + name = "magus robes" + desc = "A set of armored robes worn by the followers of Nar-Sie." + icon_state = "magusred" + item_state = "magusred" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS + flags_inv = HIDEGLOVES|HIDEJUMPSUIT + +/obj/item/clothing/head/helmet/space/cult + name = "eldritch helmet" + desc = "A bulky helmet, bristling with spikes. It looks space proof." + icon_state = "cult_helmet" + armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 30, bio = 30, rad = 30) + siemens_coefficient = 0 + light_overlay = "helmet_light_dual_red" + light_color = "FF6D6D" + +/obj/item/clothing/head/helmet/space/cult/cultify() + return + +/obj/item/clothing/suit/space/cult + name = "eldritch armour" + icon_state = "cult_armour" + item_state = "cult_armour" + desc = "A bulky suit of armour, bristling with spikes. It looks space proof." + w_class = 3 + allowed = list(/obj/item/book/tome, /obj/item/melee/cultblade, /obj/item/tank, /obj/item/device/suit_cooling_unit) + slowdown = 1 + armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 30, bio = 30, rad = 30) + siemens_coefficient = 0 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS + +/obj/item/clothing/suit/space/cult/cultify() + return \ No newline at end of file diff --git a/code/game/gamemodes/cult/items/clothes.dm b/code/game/gamemodes/cult/items/clothes.dm new file mode 100644 index 00000000000..41cb45c2f4d --- /dev/null +++ b/code/game/gamemodes/cult/items/clothes.dm @@ -0,0 +1,36 @@ +/obj/item/clothing/head/culthood + name = "ragged hood" + icon_state = "culthood" + desc = "A torn, dust-caked hood." + flags_inv = HIDEFACE|HIDEEARS|HIDEEYES + body_parts_covered = HEAD|EYES + armor = list(melee = 50, bullet = 30, laser = 50, energy = 20, bomb = 25, bio = 10, rad = 0) + cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0 + +/obj/item/clothing/head/culthood/cultify() + new /obj/item/clothing/head/helmet/space/cult(get_turf(src)) + ..() + +/obj/item/clothing/head/culthood/alt + icon_state = "cult_hoodalt" + +/obj/item/clothing/suit/cultrobes + name = "ragged robes" + desc = "A ragged, dusty set of robes." + icon_state = "cultrobes" + item_state = "cultrobes" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/book/tome, /obj/item/melee/cultblade) + armor = list(melee = 50, bullet = 30, laser = 50, energy = 20, bomb = 25, bio = 10, rad = 0) + flags_inv = HIDEJUMPSUIT + siemens_coefficient = 0 + +/obj/item/clothing/suit/cultrobes/cultify() + new /obj/item/clothing/suit/space/cult(get_turf(src)) + ..() + +/obj/item/clothing/suit/cultrobes/alt + icon_state = "cultrobesalt" + item_state = "cultrobesalt" \ No newline at end of file diff --git a/code/game/gamemodes/cult/items/sword.dm b/code/game/gamemodes/cult/items/sword.dm new file mode 100644 index 00000000000..579e20ee098 --- /dev/null +++ b/code/game/gamemodes/cult/items/sword.dm @@ -0,0 +1,57 @@ +/obj/item/melee/cultblade + name = "eldritch blade" + desc = "A sword humming with unholy energy. It glows with a dim red light." + icon_state = "cultblade" + item_state = "cultblade" + icon = 'icons/obj/weapons.dmi' + w_class = 4 + force = 30 + throwforce = 10 + slot_flags = SLOT_BELT + edge = TRUE + sharp = TRUE + hitsound = 'sound/weapons/bladeslice.ogg' + + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + can_embed = FALSE //can't get stuck anymore, because blood magic + +/obj/item/melee/cultblade/cultify() + return + +/obj/item/melee/cultblade/attack(mob/living/M, mob/living/user, var/target_zone) + if(iscultist(user)) + return ..() + + var/zone = (user.hand ? BP_L_ARM:BP_R_ARM) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + var/obj/item/organ/external/affecting = H.get_organ(zone) + to_chat(user, span("cult", "An unexplicable force rips through your [affecting.name], tearing the sword from your grasp!")) + else + to_chat(user, span("cult", "An unexplicable force rips through you, tearing the sword from your grasp!")) + + //random amount of damage between half of the blade's force and the full force of the blade. + user.apply_damage(rand(force/2, force), BRUTE, zone, 0, sharp=1, edge=1) + user.Weaken(5) + + user.drop_from_inventory(src) + throw_at(get_edge_target_turf(src, pick(alldirs)), rand(1,3), throw_speed) + + var/spooky = pick('sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg', 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/wail.ogg') + playsound(loc, spooky, 50, 1) + + return TRUE + +/obj/item/melee/cultblade/pickup(mob/living/user) + ..() + if(!iscultist(user)) + to_chat(user, span("cult", "An overwhelming feeling of dread comes over you as you pick up \the [src]. It would be wise to be rid of this blade quickly.")) + user.make_dizzy(120) + +/obj/item/melee/cultblade/attackby(obj/item/I, mob/user) + ..() + if(istype(I, /obj/item/nullrod)) + to_chat(user, span("notice", "You cleanse \the [src] of taint, restoring the blade to its original state.")) + var/obj/item/material/sword/blade = new(get_turf(src)) + blade.force = 15 + qdel(src) \ No newline at end of file diff --git a/code/game/gamemodes/cult/items/talisman.dm b/code/game/gamemodes/cult/items/talisman.dm new file mode 100644 index 00000000000..bc1a056acb5 --- /dev/null +++ b/code/game/gamemodes/cult/items/talisman.dm @@ -0,0 +1,35 @@ +/obj/item/paper/talisman + icon_state = "paper_talisman" + var/datum/callback/imbued_rune + var/network // Which network the teleport talisman is on + var/uses = 1 + var/rune + info = "


" + +/obj/item/paper/talisman/Initialize() + . = ..() + name = "bloodied paper" + color = "FF6D6D" + +/obj/item/paper/talisman/examine(mob/user) + ..() + if(iscultist(user) && rune) + to_chat(user, "The spell inscription reads: [rune].") + +/obj/item/paper/talisman/attack_self(mob/living/user) + if(iscultist(user)) + if(imbued_rune) + if(imbued_rune.Invoke(user, src)) + user.take_organ_damage(5, 0) + use() + return + else + to_chat(user, span("cult", "This talisman has not been imbued with power!")) + else + to_chat(user, span("cult", "You see strange symbols on the paper. Are they supposed to mean something?")) + return + +/obj/item/paper/talisman/proc/use() + uses-- + if(uses <= 0) + qdel(src) \ No newline at end of file diff --git a/code/game/gamemodes/cult/items/tome.dm b/code/game/gamemodes/cult/items/tome.dm new file mode 100644 index 00000000000..cbe36daf237 --- /dev/null +++ b/code/game/gamemodes/cult/items/tome.dm @@ -0,0 +1,200 @@ +/obj/item/book/tome + name = "arcane tome" + icon = 'icons/obj/library.dmi' + icon_state = "tome" + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + unique = TRUE + slot_flags = SLOT_BELT + var/tomedat = "" + + tomedat = {" + + + + +

The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood.

+ + The book is written in an unknown dialect, there are lots of pictures of various complex geometric shapes. You find some notes in Tau Ceti Basic that give you basic understanding of the many runes written in the book.
+ Below is the summary of the runes.
+ +

Rune Descriptions

+

Teleport self

+ Basically, when you have two runes with the same destination, invoking one will teleport you to the other one. If there are more than 2 runes, you will be teleported to a random one. You can imbue this rune into a talisman, giving you a great escape mechanism.
+

Teleport other

+ Teleport other allows for teleportation for any movable object to another rune with the same third word. You need 3 cultists chanting the invocation for this rune to work.
+

Summon new tome

+ Invoking this rune summons a new arcane tome. +

Convert a person

+ This rune opens target's mind to the realm of Nar-Sie, which usually results in this person joining the cult. However, some people (mostly the ones who possess high authority) have strong enough will to stay true to their old ideals.
+

Summon Nar-Sie

+ The ultimate rune. It summons the Avatar of Nar-Sie himself, tearing a huge hole in reality and consuming everything around it. Summoning it is the final goal of any cult.
+

Disable Technology

+ Invoking this rune creates a strong electromagnetic pulse in a small radius, making it basically analogous to an EMP grenade. You can imbue this rune into a talisman, making it a decent defensive item.
+

Drain Blood

+ This rune instantly heals you of some brute damage at the expense of a person placed on top of the rune. Whenever you invoke a drain rune, ALL drain runes on the station are activated, draining blood from anyone located on top of those runes. This includes yourself, though the blood you drain from yourself just comes back to you. This might help you identify this rune when studying words. One drain gives up to 25HP per each victim, but you can repeat it if you need more. Draining only works on living people, so you might need to recharge your "Battery" once its empty. Drinking too much blood at once might cause blood hunger.
+

Raise Dead

+ This rune allows for the resurrection of any dead person. You will need a dead human body and a living human sacrifice. Make 2 raise dead runes. Put a living, awake human on top of one, and a dead body on the other one. When you invoke the rune, the life force of the living human will be transferred into the dead body, allowing a ghost standing on top of the dead body to enter it, instantly and fully healing it. Use other runes to ensure there is a ghost ready to be resurrected.
+

Hide runes

+ This rune makes all nearby runes completely invisible. They are still there and will work if activated somehow, but you cannot invoke them directly if you do not see them.
+

Reveal runes

+ This rune is made to reverse the process of hiding a rune. It reveals all hidden runes in a rather large area around it. +

Leave your body

+ This rune gently rips your soul out of your body, leaving it intact. You can observe the surroundings as a ghost as well as communicate with other ghosts. Your body takes damage while you are there, so ensure your journey is not too long, or you might never come back.
+

Manifest a ghost

+ Unlike the Raise Dead rune, this rune does not require any special preparations or vessels. Instead of using full lifeforce of a sacrifice, it will drain YOUR lifeforce. Stand on the rune and invoke it. If there's a ghost standing over the rune, it will materialise, and will live as long as you don't move off the rune or die. You can put a paper with a name on the rune to make the new body look like that person.
+

Imbue a talisman

+ This rune allows you to imbue the magic of some runes into paper talismans. Create an imbue rune, then an appropriate rune beside it. Put an empty piece of paper on the imbue rune and invoke it. You will now have a one-use talisman with the power of the target rune. Using a talisman drains some health, so be careful with it. You can imbue a talisman with power of the following runes: summon tome, reveal, conceal, teleport, disable technology, communicate, deafen, blind and stun.
+

Sacrifice

+ Sacrifice rune allows you to sacrifice a living thing or a body to the Geometer of Blood. Monkeys and dead humans are the most basic sacrifices, they might or might not be enough to gain His favor. A living human is what a real sacrifice should be, however, you will need 3 people chanting the invocation to sacrifice a living person. +

Create a wall

+ Invoking this rune solidifies the air above it, creating an an invisible wall. To remove the wall, simply invoke the rune again. +

Summon cultist

+ This rune allows you to summon a fellow cultist to your location. The target cultist must be unhandcuffed and not buckled to anything. You also need to have 3 people chanting at the rune to successfully invoke it. Invoking it takes heavy strain on the bodies of all chanting cultists.
+

Free a cultist

+ This rune unhandcuffs and unbuckles any cultist of your choice, no matter where he is. You need to have 3 people invoking the rune for it to work. Invoking it takes heavy strain on the bodies of all chanting cultists.
+

Deafen

+ This rune temporarily deafens all non-cultists around you.
+

Blind

+ This rune temporarily blinds all non-cultists around you. Very robust. Use together with the deafen rune to leave your enemies completely helpless.
+

Blood boil

+ This rune boils the blood all non-cultists in visible range. The damage is enough to instantly critically hurt any person. You need 3 cultists invoking the rune for it to work. This rune is unreliable and may cause unpredicted effect when invoked. It also drains significant amount of your health when successfully invoked.
+

Communicate

+ Invoking this rune allows you to relay a message to all cultists on the station and nearby space objects. +

Stun

+ When invoked directly as a rune, it releases some dark energy, briefly stunning everyone around. When imbued into a talisman, you can force some dark energy into a person, causing their eyes to flash, and their words to falter, keeping them quiet. However, the effect wears off rather fast.
+

Equip Armor

+ When this rune is invoked, either from a rune or a talisman, it will equip the user with the armor of the followers of Nar-Sie. To use this rune to its fullest extent, make sure you are not wearing any form of headgear, armor, gloves or shoes, and make sure you are not holding anything in your hands.
+

See Invisible

+ When invoked when standing on it, this rune allows the user to see the world beyond as long as he does not move.
+ + + "} + +/obj/item/book/tome/attack(mob/living/M, mob/living/user) + if(isobserver(M)) + var/mob/abstract/observer/D = M + D.manifest(user) + attack_admins(D, user) + return + + if(!istype(M)) + return + + if(!iscultist(user)) + return ..() + + if(iscultist(M)) + return + + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + M.take_organ_damage(0, rand(5,20)) //really lucky - 5 hits for a crit + visible_message(span("warning", "\The [user] beats \the [M] with \the [src]!")) + to_chat(M, span("danger", "You feel searing heat inside!")) + attack_admins(M, user) + +/obj/item/book/tome/proc/attack_admins(var/mob/living/M, var/mob/living/user) + M.attack_log += text("\[[time_stamp()]\] Has had the [name] used on them by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used [name] on [M.name] ([M.ckey])") + msg_admin_attack("[key_name_admin(user)] used [name] on [M.name] ([M.ckey]) (JMP)",ckey=key_name(user),ckey_target=key_name(M)) + + +/obj/item/book/tome/attack_self(mob/living/user) + if(use_check_and_message(user)) + return + + if(iscultist(user)) + if(!istype(user.loc, /turf)) + to_chat(user, span("warning", "You do not have enough space to write a proper rune.")) + return + + var/turf/T = get_turf(user) + + if(T.is_hole || T.is_space()) + to_chat(user, span("warning", "You are unable to write a rune here.")) + return + + // This counts how many runes exist in the game, for some sort of arbitrary rune limit. I trust the old devs had their reasons. - Geeves + if(length(rune_list) >= 25 + rune_boost + cult.current_antagonists.len) + to_chat(user, span("warning", "The cloth of reality can't take that much of a strain. Remove some runes first!")) + return + else + switch(alert("What shall you do with the tome?", "Tome of Nar'sie", "Read it", "Scribe a rune", "Cancel")) + if("Cancel") + return + if("Read it") + if(use_check_and_message(user)) + return + user << browse("[tomedat]", "window=Arcane Tome") + return + + //only check if they want to scribe a rune, so they can still read if standing on a rune + if(locate(/obj/effect/rune) in user.loc) + to_chat(user, span("warning", "There is already a rune in this location.")) + return + + if(use_check_and_message(user)) + return + + var/chosen_rune + var/network + chosen_rune = input("Choose a rune to scribe.") in rune_types + if(!chosen_rune) + return + if(chosen_rune == "None") + to_chat(user, span("notice", "You decide against scribing a rune, perhaps you should take this time to study your notes.")) + return + if(chosen_rune == "Teleport") + network = input(user, "Choose a teleportation network for the rune to connect to.", "Teleportation Rune") in teleport_network + + if(use_check_and_message(user)) + return + + user.visible_message(span("warning", "\The [user] slices open a finger and begins to chant and paint symbols on the floor."), span("notice", "You slice open one of your fingers and begin drawing a rune on the floor whilst softly chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world.")) + user.take_overall_damage((rand(9)+1)/10) // 0.1 to 1.0 damage + + if(do_after(user, 50)) + var/area/A = get_area(user) + if(use_check_and_message(user)) + return + + //prevents using multiple dialogs to layer runes. + if(locate(/obj/effect/rune) in user.loc) //This is check is done twice. once when choosing to scribe a rune, once here + to_chat(user, span("warning", "There is already a rune in this location.")) + return + + log_and_message_admins("created \an [chosen_rune] rune at \the [A.name] - [user.loc.x]-[user.loc.y]-[user.loc.z].") //only message if it's actually made + + var/mob/living/carbon/human/H = user + var/rune_path = rune_types[chosen_rune] + var/obj/effect/rune/R = new rune_path(get_turf(user)) + to_chat(user, span("notice", "You finish drawing the arcane markings of the Geometer.")) + R.blood_DNA = list() + R.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type + if(network) + R.network = network + R.cult_description = chosen_rune + if(ishuman(user)) + var/mob/living/carbon/human/scribe = user + R.color = scribe.species.blood_color + return + else + to_chat(user, span("cult", "The book seems full of illegible scribbles.")) + return + +/obj/item/book/tome/examine(mob/user) + ..(user) + if(!iscultist(user) || !isobserver(user)) + desc = "An old, dusty tome with frayed edges and a sinister looking cover." + else + desc = "The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood. Contains the details of every ritual his followers could think of. Most of these are useless, though." + +/obj/item/book/tome/cultify() + return \ No newline at end of file diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm deleted file mode 100644 index 07b18f0dc47..00000000000 --- a/code/game/gamemodes/cult/ritual.dm +++ /dev/null @@ -1,594 +0,0 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -var/cultwords = list() -var/runedec = 0 -var/global/list/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide") -var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri") - -/client/proc/check_words() // -- Urist - set category = "Special Verbs" - set name = "Check Rune Words" - set desc = "Check the rune-word meaning" - if(!cultwords["travel"]) - runerandom() - for (var/word in engwords) - to_chat(usr, "[cultwords[word]] is [word]") - -/proc/runerandom() //randomizes word meaning - var/list/runewords=rnwords - for (var/word in engwords) - cultwords[word] = pick(runewords) - runewords-=cultwords[word] - -/obj/effect/rune - desc = "A strange collection of symbols drawn in blood." - anchored = 1 - icon = 'icons/obj/rune.dmi' - icon_state = "1" - var/visibility = 0 - unacidable = 1 - layer = AO_LAYER - - - var/word1 - var/word2 - var/word3 - var/image/blood_image - var/list/converting = list() - -// Places these combos are mentioned: this file - twice in the rune code, once in imbued tome, once in tome's HTML runes.dm - in the imbue rune code. If you change a combination - dont forget to change it everywhere. - -// travel self [word] - Teleport to random [rune with word destination matching] -// travel other [word] - Portal to rune with word destination matching - kinda doesnt work. At least the icon. No idea why. -// see blood Hell - Create a new tome -// join blood self - Incorporate person over the rune into the group -// Hell join self - Summon TERROR -// destroy see technology - EMP rune -// travel blood self - Drain blood -// see Hell join - See invisible -// blood join Hell - Raise dead - -// hide see blood - Hide nearby runes -// blood see hide - Reveal nearby runes - The point of this rune is that its reversed obscure rune. So you always know the words to reveal the rune once oyu have obscured it. - -// Hell travel self - Leave your body and ghost around -// blood see travel - Manifest a ghost into a mortal body -// Hell tech join - Imbue a rune into a talisman -// Hell blood join - Sacrifice rune -// destroy travel self - Wall rune -// join other self - Summon cultist rune -// travel technology other - Freeing rune // other blood travel was freedom join other - -// hide other see - Deafening rune // was destroy see hear -// destroy see other - Blinding rune -// destroy see blood - BLOOD BOIL - -// self other technology - Communication rune //was other hear blood -// join hide technology - stun rune. Rune color: bright pink. - -/obj/effect/rune/Initialize() - . = ..() - blood_image = image(loc = src) - blood_image.override = 1 - for(var/mob/living/silicon/ai/AI in player_list) - if(AI.client) - AI.client.images += blood_image - rune_list += src - -/obj/effect/rune/Destroy() - for(var/mob/living/silicon/ai/AI in player_list) - if(AI.client) - AI.client.images -= blood_image - qdel(blood_image) - blood_image = null - rune_list -= src - return ..() - -/obj/effect/rune/examine(mob/user) - ..() - if(iscultist(user)) - to_chat(user, "This spell circle reads: [word1] [word2] [word3].") - -/obj/effect/rune/attackby(I as obj, user as mob) - if(istype(I, /obj/item/book/tome) && iscultist(user)) - to_chat(user, "You retrace your steps, carefully undoing the lines of the rune.") - qdel(src) - return - else if(istype(I, /obj/item/nullrod)) - to_chat(user, "You disrupt the vile magic with the deadening field of \the [I]!") - qdel(src) - return - return - - -/obj/effect/rune/attack_hand(var/mob/living/user) - if(!iscultist(user)) - to_chat(user, "You can't mouth the arcane scratchings without fumbling over them.") - return - if(istype(user.wear_mask, /obj/item/clothing/mask/muzzle)) - to_chat(user, "You are unable to speak the words of the rune.") - return - if(!word1 || !word2 || !word3 || prob(user.getBrainLoss())) - return fizzle(user) - //if(!src.visibility) - //src.visibility=1 - if(word1 == cultwords["travel"] && word2 == cultwords["self"]) - return teleport(user,src.word3) - if(word1 == cultwords["see"] && word2 == cultwords["blood"] && word3 == cultwords["hell"]) - return tomesummon(user) - if(word1 == cultwords["hell"] && word2 == cultwords["destroy"] && word3 == cultwords["other"]) - return armor(user) - if(word1 == cultwords["join"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) - return convert(user) - if(word1 == cultwords["hell"] && word2 == cultwords["join"] && word3 == cultwords["self"]) - return tearreality(user) - if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["technology"]) - return emp(user, src.loc,3) - if(word1 == cultwords["travel"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) - return drain(user) - if(word1 == cultwords["see"] && word2 == cultwords["hell"] && word3 == cultwords["join"]) - return seer(user) - if(word1 == cultwords["blood"] && word2 == cultwords["join"] && word3 == cultwords["hell"]) - return raise(user) - if(word1 == cultwords["hide"] && word2 == cultwords["see"] && word3 == cultwords["blood"]) - return obscure(user, 4) - if(word1 == cultwords["hell"] && word2 == cultwords["travel"] && word3 == cultwords["self"]) - return ajourney(user) - if(word1 == cultwords["blood"] && word2 == cultwords["see"] && word3 == cultwords["travel"]) - return manifest(user) - if(word1 == cultwords["hell"] && word2 == cultwords["technology"] && word3 == cultwords["join"]) - return talisman(user) - if(word1 == cultwords["hell"] && word2 == cultwords["blood"] && word3 == cultwords["join"]) - return sacrifice(user) - if(word1 == cultwords["blood"] && word2 == cultwords["see"] && word3 == cultwords["hide"]) - return revealrunes(user, src) - if(word1 == cultwords["destroy"] && word2 == cultwords["travel"] && word3 == cultwords["self"]) - return wall(user) - if(word1 == cultwords["travel"] && word2 == cultwords["technology"] && word3 == cultwords["other"]) - return freedom(user) - if(word1 == cultwords["join"] && word2 == cultwords["other"] && word3 == cultwords["self"]) - return cultsummon(user) - if(word1 == cultwords["hide"] && word2 == cultwords["other"] && word3 == cultwords["see"]) - return deafen(user) - if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["other"]) - return blind(user) - if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["blood"]) - return bloodboil(user) - if(word1 == cultwords["self"] && word2 == cultwords["other"] && word3 == cultwords["technology"]) - return communicate(user) - if(word1 == cultwords["travel"] && word2 == cultwords["other"]) - return itemport(user, src.word3) - if(word1 == cultwords["join"] && word2 == cultwords["hide"] && word3 == cultwords["technology"]) - return runestun(user) - else - return fizzle(user) - - -/obj/effect/rune/proc/fizzle(var/mob/living/user) - if(istype(src,/obj/effect/rune)) - user.say(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.", "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) - else - user.whisper(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.", "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) - for (var/mob/V in viewers(src)) - V.show_message("The markings pulse with a small burst of light, then fall dark.", 3, "You hear a faint fizzle.", 2) - return - -/obj/effect/rune/proc/check_icon() - icon = get_uristrune_cult(word1, word2, word3) - -/obj/item/book/tome - name = "arcane tome" - icon = 'icons/obj/library.dmi' - icon_state ="tome" - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - unique = 1 - var/tomedat = "" - var/list/words = list("ire" = "ire", "ego" = "ego", "nahlizet" = "nahlizet", "certum" = "certum", "veri" = "veri", "jatkaa" = "jatkaa", "balaq" = "balaq", "mgar" = "mgar", "karazet" = "karazet", "geeri" = "geeri") - - tomedat = {" - - - - -

The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood.

- - The book is written in an unknown dialect, there are lots of pictures of various complex geometric shapes. You find some notes in english that give you basic understanding of the many runes written in the book. The notes give you an understanding what the words for the runes should be. However, you do not know how to write all these words in this dialect.
- Below is the summary of the runes.
- -

Contents

-

- Teleport self: Travel Self (word)
- Teleport other: Travel Other (word)
- Summon new tome: See Blood Hell
- Convert a person: Join Blood Self
- Summon Nar-Sie: Hell Join Self
- Disable technology: Destroy See Technology
- Drain blood: Travel Blood Self
- Raise dead: Blood Join Hell
- Hide runes: Hide See Blood
- Reveal hidden runes: Blood See Hide
- Leave your body: Hell travel self
- Ghost Manifest: Blood See Travel
- Imbue a talisman: Hell Technology Join
- Sacrifice: Hell Blood Join
- Create a wall: Destroy Travel Self
- Summon cultist: Join Other Self
- Free a cultist: Travel technology other
- Deafen: Hide Other See
- Blind: Destroy See Other
- Blood Boil: Destroy See Blood
- Communicate: Self Other Technology
- Stun: Join Hide Technology
- Summon Cultist Armor: Hell Destroy Other
- See Invisible: See Hell Join
-

-

Rune Descriptions

-

Teleport self

- Teleport rune is a special rune, as it only needs two words, with the third word being destination. Basically, when you have two runes with the same destination, invoking one will teleport you to the other one. If there are more than 2 runes, you will be teleported to a random one. Runes with different third words will create separate networks. You can imbue this rune into a talisman, giving you a great escape mechanism.
-

Teleport other

- Teleport other allows for teleportation for any movable object to another rune with the same third word. You need 3 cultists chanting the invocation for this rune to work.
-

Summon new tome

- Invoking this rune summons a new arcane tome. -

Convert a person

- This rune opens target's mind to the realm of Nar-Sie, which usually results in this person joining the cult. However, some people (mostly the ones who possess high authority) have strong enough will to stay true to their old ideals.
-

Summon Nar-Sie

- The ultimate rune. It summons the Avatar of Nar-Sie himself, tearing a huge hole in reality and consuming everything around it. Summoning it is the final goal of any cult.
-

Disable Technology

- Invoking this rune creates a strong electromagnetic pulse in a small radius, making it basically analogous to an EMP grenade. You can imbue this rune into a talisman, making it a decent defensive item.
-

Drain Blood

- This rune instantly heals you of some brute damage at the expense of a person placed on top of the rune. Whenever you invoke a drain rune, ALL drain runes on the station are activated, draining blood from anyone located on top of those runes. This includes yourself, though the blood you drain from yourself just comes back to you. This might help you identify this rune when studying words. One drain gives up to 25HP per each victim, but you can repeat it if you need more. Draining only works on living people, so you might need to recharge your "Battery" once its empty. Drinking too much blood at once might cause blood hunger.
-

Raise Dead

- This rune allows for the resurrection of any dead person. You will need a dead human body and a living human sacrifice. Make 2 raise dead runes. Put a living, awake human on top of one, and a dead body on the other one. When you invoke the rune, the life force of the living human will be transferred into the dead body, allowing a ghost standing on top of the dead body to enter it, instantly and fully healing it. Use other runes to ensure there is a ghost ready to be resurrected.
-

Hide runes

- This rune makes all nearby runes completely invisible. They are still there and will work if activated somehow, but you cannot invoke them directly if you do not see them.
-

Reveal runes

- This rune is made to reverse the process of hiding a rune. It reveals all hidden runes in a rather large area around it. -

Leave your body

- This rune gently rips your soul out of your body, leaving it intact. You can observe the surroundings as a ghost as well as communicate with other ghosts. Your body takes damage while you are there, so ensure your journey is not too long, or you might never come back.
-

Manifest a ghost

- Unlike the Raise Dead rune, this rune does not require any special preparations or vessels. Instead of using full lifeforce of a sacrifice, it will drain YOUR lifeforce. Stand on the rune and invoke it. If there's a ghost standing over the rune, it will materialise, and will live as long as you don't move off the rune or die. You can put a paper with a name on the rune to make the new body look like that person.
-

Imbue a talisman

- This rune allows you to imbue the magic of some runes into paper talismans. Create an imbue rune, then an appropriate rune beside it. Put an empty piece of paper on the imbue rune and invoke it. You will now have a one-use talisman with the power of the target rune. Using a talisman drains some health, so be careful with it. You can imbue a talisman with power of the following runes: summon tome, reveal, conceal, teleport, disable technology, communicate, deafen, blind and stun.
-

Sacrifice

- Sacrifice rune allows you to sacrifice a living thing or a body to the Geometer of Blood. Monkeys and dead humans are the most basic sacrifices, they might or might not be enough to gain His favor. A living human is what a real sacrifice should be, however, you will need 3 people chanting the invocation to sacrifice a living person. -

Create a wall

- Invoking this rune solidifies the air above it, creating an an invisible wall. To remove the wall, simply invoke the rune again. -

Summon cultist

- This rune allows you to summon a fellow cultist to your location. The target cultist must be unhandcuffed and not buckled to anything. You also need to have 3 people chanting at the rune to successfully invoke it. Invoking it takes heavy strain on the bodies of all chanting cultists.
-

Free a cultist

- This rune unhandcuffs and unbuckles any cultist of your choice, no matter where he is. You need to have 3 people invoking the rune for it to work. Invoking it takes heavy strain on the bodies of all chanting cultists.
-

Deafen

- This rune temporarily deafens all non-cultists around you.
-

Blind

- This rune temporarily blinds all non-cultists around you. Very robust. Use together with the deafen rune to leave your enemies completely helpless.
-

Blood boil

- This rune boils the blood all non-cultists in visible range. The damage is enough to instantly critically hurt any person. You need 3 cultists invoking the rune for it to work. This rune is unreliable and may cause unpredicted effect when invoked. It also drains significant amount of your health when successfully invoked.
-

Communicate

- Invoking this rune allows you to relay a message to all cultists on the station and nearby space objects. -

Stun

- When invoked directly as a rune, it releases some dark energy, briefly stunning everyone around. When imbued into a talisman, you can force some dark energy into a person, causing their eyes to flash, and their words to falter, keeping them quiet. However, the effect wears off rather fast.
-

Equip Armor

- When this rune is invoked, either from a rune or a talisman, it will equip the user with the armor of the followers of Nar-Sie. To use this rune to its fullest extent, make sure you are not wearing any form of headgear, armor, gloves or shoes, and make sure you are not holding anything in your hands.
-

See Invisible

- When invoked when standing on it, this rune allows the user to see the world beyond as long as he does not move.
- - - "} - - -/obj/item/book/tome/Initialize() - . = ..() - if(!cultwords["travel"]) - runerandom() - for(var/V in cultwords) - words[cultwords[V]] = V - - - -/obj/item/book/tome/attack(mob/living/M as mob, mob/living/user as mob) - - M.attack_log += text("\[[time_stamp()]\] Has had the [name] used on them by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used [name] on [M.name] ([M.ckey])") - msg_admin_attack("[key_name_admin(user)] used [name] on [M.name] ([M.ckey]) (JMP)",ckey=key_name(user),ckey_target=key_name(M)) - - if(isobserver(M)) - var/mob/abstract/observer/D = M - D.manifest(user) - return - - if(!istype(M)) - return - - if(!iscultist(user)) - return ..() - - if(iscultist(M)) - return - - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - M.take_organ_damage(0,rand(5,20)) //really lucky - 5 hits for a crit - for(var/mob/O in viewers(M, null)) - O.show_message("\The [user] beats \the [M] with \the [src]!", 1) - to_chat(M, "You feel searing heat inside!") - - -/obj/item/book/tome/attack_self(mob/living/user as mob) - - if(!user.canmove || user.stat || user.restrained()) - return - - if(!cultwords["travel"]) - runerandom() - - if(iscultist(user)) - var/C = 0 - for(var/obj/effect/rune/N in rune_list) - C++ - - if (!istype(user.loc,/turf)) - to_chat(user, "You do not have enough space to write a proper rune.") - return - - var/turf/T = get_turf(user) - - if (T.is_hole || T.is_space()) - to_chat(user, "You are unable to write a rune here.") - return - - if (C>=26 + runedec + cult.current_antagonists.len) //including the useless rune at the secret room, shouldn't count against the limit of 25 runes - Urist - alert("The cloth of reality can't take that much of a strain. Remove some runes first!") - return - - else - switch(alert("You open the tome",,"Read it","Scribe a rune", "Cancel")) - if("Cancel") - return - if("Read it") - if(user.get_active_hand() != src) - return - user << browse("[tomedat]", "window=Arcane Tome") - return - //only check if they want to scribe a rune, so they can still read if standing on a rune - if(locate(/obj/effect/rune) in user.loc) - to_chat(user, "There is already a rune in this location.") - return - - if(isipc(user)) - to_chat(user, "You cannot draw runes, as you have no blood.") - return - - if(user.get_active_hand() != src) - return - - var/list/static/dictionary = list ( - "convert" = list("join","blood","self"), - "wall" = list("destroy","travel","self"), - "blood boil" = list("destroy","see","blood"), - "blood drain" = list("travel","blood","self"), - "raise dead" = list("blood","join","hell"), - "summon narsie" = list("hell","join","self"), - "communicate" = list("self","other","technology"), - "emp" = list("destroy","see","technology"), - "manifest" = list("blood","see","travel"), - "summon tome" = list("see","blood","hell"), - "see invisible" = list("see","hell","join"), - "hide" = list("hide","see","blood"), - "reveal" = list("blood","see","hide"), - "astral journey" = list("hell","travel","self"), - "imbue" = list("hell","technology","join"), - "sacrifice" = list("hell","blood","join"), - "summon cultist" = list("join","other","self"), - "free cultist" = list("travel","technology","other"), - "deafen" = list("hide","other","see"), - "blind" = list("destroy","see","other"), - "stun" = list("join","hide","technology"), - "armor" = list("hell","destroy","other"), - "teleport" = list("travel","self"), - "teleport other" = list("travel","other") - ) - - var/list/english = list() - - var/list/scribewords = list("none") - - for (var/entry in words) - if (words[entry] != entry) - english += list(words[entry] = entry) - - for (var/entry in dictionary) - scribewords += entry - - var/chosen_rune = null - var/list/required = null - if(user) - chosen_rune = input ("Choose a rune to scribe.") in scribewords - if (!chosen_rune) - return - if (chosen_rune == "none") - to_chat(user, "You decide against scribing a rune, perhaps you should take this time to study your notes.") - return - required = dictionary[chosen_rune].Copy() - if(chosen_rune == "teleport" || chosen_rune == "teleport other") - required += input ("Choose a destination word") in english - - if(user.get_active_hand() != src) - return - - for (var/mob/V in viewers(src)) - V.show_message("\The [user] slices open a finger and begins to chant and paint symbols on the floor.", 3, "You hear chanting.", 2) - to_chat(user, "You slice open one of your fingers and begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world.") - user.take_overall_damage((rand(9)+1)/10) // 0.1 to 1.0 damage - if(do_after(user, 50)) - var/area/A = get_area(user) - - if(user.get_active_hand() != src) - return - - //prevents using multiple dialogs to layer runes. - if(locate(/obj/effect/rune) in user.loc) //This is check is done twice. once when choosing to scribe a rune, once here - to_chat(user, "There is already a rune in this location.") - return - - log_and_message_admins("created \an [chosen_rune] rune at \the [A.name] - [user.loc.x]-[user.loc.y]-[user.loc.z].") //only message if it's actually made - - var/mob/living/carbon/human/H = user - var/obj/effect/rune/R = new /obj/effect/rune(user.loc) - to_chat(user, "You finish drawing the arcane markings of the Geometer.") - R.word1 = english[required[1]] - R.word2 = english[required[2]] - R.word3 = english[required[3]] - R.check_icon() - R.blood_DNA = list() - R.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type - return - else - to_chat(user, "The book seems full of illegible scribbles.") - return - -/obj/item/book/tome/examine(mob/user) - ..(user) - if(!iscultist(user)) - desc = "An old, dusty tome with frayed edges and a sinister looking cover." - else - desc = "The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood. Contains the details of every ritual his followers could think of. Most of these are useless, though." - -/obj/item/book/tome/cultify() - return - -/obj/item/book/tome/imbued //admin tome, spawns working runes without waiting - w_class = 2.0 - var/cultistsonly = 1 - attack_self(mob/user as mob) - if(src.cultistsonly && !iscultist(user)) - return - if(!cultwords["travel"]) - runerandom() - if(user) - var/r - if (!istype(user.loc,/turf)) - to_chat(user, "You do not have enough space to write a proper rune.") - var/list/runes = list("teleport", "itemport", "tome", "armor", "convert", "tear in reality", "emp", "drain", "seer", "raise", "obscure", "reveal", "astral journey", "manifest", "imbue talisman", "sacrifice", "wall", "freedom", "cultsummon", "deafen", "blind", "bloodboil", "communicate", "stun") - r = input("Choose a rune to scribe", "Rune Scribing") in runes //not cancellable. - - var/obj/effect/rune/R = new /obj/effect/rune(user.loc) - if(istype(user, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - R.blood_DNA = list() - R.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type - var/area/A = get_area(user) - log_and_message_admins("created \an [r] rune at \the [A.name] - [user.loc.x]-[user.loc.y]-[user.loc.z].") - switch(r) - if("teleport") - var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") - var/beacon - if(user) - beacon = input("Select the last rune", "Rune Scribing") in words - R.word1=cultwords["travel"] - R.word2=cultwords["self"] - R.word3=beacon - if("itemport") - var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") - var/beacon - if(user) - beacon = input("Select the last rune", "Rune Scribing") in words - R.word1=cultwords["travel"] - R.word2=cultwords["other"] - R.word3=beacon - if("tome") - R.word1=cultwords["see"] - R.word2=cultwords["blood"] - R.word3=cultwords["hell"] - if("armor") - R.word1=cultwords["hell"] - R.word2=cultwords["destroy"] - R.word3=cultwords["other"] - if("convert") - R.word1=cultwords["join"] - R.word2=cultwords["blood"] - R.word3=cultwords["self"] - if("tear in reality") - R.word1=cultwords["hell"] - R.word2=cultwords["join"] - R.word3=cultwords["self"] - if("emp") - R.word1=cultwords["destroy"] - R.word2=cultwords["see"] - R.word3=cultwords["technology"] - if("drain") - R.word1=cultwords["travel"] - R.word2=cultwords["blood"] - R.word3=cultwords["self"] - if("seer") - R.word1=cultwords["see"] - R.word2=cultwords["hell"] - R.word3=cultwords["join"] - if("raise") - R.word1=cultwords["blood"] - R.word2=cultwords["join"] - R.word3=cultwords["hell"] - if("obscure") - R.word1=cultwords["hide"] - R.word2=cultwords["see"] - R.word3=cultwords["blood"] - if("astral journey") - R.word1=cultwords["hell"] - R.word2=cultwords["travel"] - R.word3=cultwords["self"] - if("manifest") - R.word1=cultwords["blood"] - R.word2=cultwords["see"] - R.word3=cultwords["travel"] - if("imbue talisman") - R.word1=cultwords["hell"] - R.word2=cultwords["technology"] - R.word3=cultwords["join"] - if("sacrifice") - R.word1=cultwords["hell"] - R.word2=cultwords["blood"] - R.word3=cultwords["join"] - if("reveal") - R.word1=cultwords["blood"] - R.word2=cultwords["see"] - R.word3=cultwords["hide"] - if("wall") - R.word1=cultwords["destroy"] - R.word2=cultwords["travel"] - R.word3=cultwords["self"] - if("freedom") - R.word1=cultwords["travel"] - R.word2=cultwords["technology"] - R.word3=cultwords["other"] - if("cultsummon") - R.word1=cultwords["join"] - R.word2=cultwords["other"] - R.word3=cultwords["self"] - if("deafen") - R.word1=cultwords["hide"] - R.word2=cultwords["other"] - R.word3=cultwords["see"] - if("blind") - R.word1=cultwords["destroy"] - R.word2=cultwords["see"] - R.word3=cultwords["other"] - if("bloodboil") - R.word1=cultwords["destroy"] - R.word2=cultwords["see"] - R.word3=cultwords["blood"] - if("communicate") - R.word1=cultwords["self"] - R.word2=cultwords["other"] - R.word3=cultwords["technology"] - if("stun") - R.word1=cultwords["join"] - R.word2=cultwords["hide"] - R.word3=cultwords["technology"] - R.forceMove(user.loc) - R.check_icon() diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm deleted file mode 100644 index af165b609fa..00000000000 --- a/code/game/gamemodes/cult/runes.dm +++ /dev/null @@ -1,1144 +0,0 @@ -var/list/sacrificed = list() - -/obj/effect/rune/cultify() - return - -/obj/effect/rune -/* - * Use as a general guideline for this and related files: - * * ... - when something non-trivial or an error happens, so something similar to "Sparks come out of the machine!" - * * ... - when something that is fit for 'warning' happens but there is some damage or pain as well. - * * ... - when there is a private message to the cultists. This guideline is very arbitrary but there has to be some consistency! - */ - - -/////////////////////////////////////////FIRST RUNE -/obj/effect/rune/proc/teleport(var/mob/living/user, var/key) - var/allrunesloc[] - allrunesloc = new/list() - var/index = 0 -// var/tempnum = 0 - for(var/obj/effect/rune/R in rune_list) - if(R == src) - continue - if(R.word1 == cultwords["travel"] && R.word2 == cultwords["self"] && R.word3 == key && isStationLevel(R.z)) - index++ - allrunesloc.len = index - allrunesloc[index] = R.loc - if(index >= 5) - to_chat(user, "You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric.") - if (istype(user, /mob/living)) - user.take_overall_damage(5, 0) - qdel(src) - - var/turf/T = get_turf(user) - if(isNotStationLevel(T.z)) - to_chat(user, "You are too far from the station, Nar'sie is unable to reach you here.") - return fizzle(user) - - if(allrunesloc && index != 0) - if(istype(src,/obj/effect/rune)) - user.say("Sas[pick("'","`")]so c'arta forbici!")//Only you can stop auto-muting - else - user.whisper("Sas[pick("'","`")]so c'arta forbici!") - user.visible_message("[user] disappears in a flash of red light!", \ - "You feel as your body gets dragged through the dimension of Nar-Sie!", \ - "You hear a sickening crunch and sloshing of viscera.") - user.forceMove(allrunesloc[rand(1,index)]) - return - if(istype(src,/obj/effect/rune)) - return fizzle(user) //Use friggin manuals, Dorf, your list was of zero length. - else - call(/obj/effect/rune/proc/fizzle)(user) - return - - -/obj/effect/rune/proc/itemport(var/mob/living/user, var/key) -// var/allrunesloc[] -// allrunesloc = new/list() -// var/index = 0 -// var/tempnum = 0 - var/culcount = 0 - var/runecount = 0 - var/obj/effect/rune/IP = null - for(var/obj/effect/rune/R in rune_list) - if(R == src) - continue - if(R.word1 == cultwords["travel"] && R.word2 == cultwords["other"] && R.word3 == key) - IP = R - runecount++ - if(runecount >= 2) - to_chat(user, "You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric.") - if (istype(user, /mob/living)) - user.take_overall_damage(5, 0) - qdel(src) - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - culcount++ - if(culcount>=3) - user.say("Sas[pick("'","`")]so c'arta forbici tarem!") - user.visible_message("You feel air moving from the rune - like as it was swapped with somewhere else.", \ - "You feel air moving from the rune - like as it was swapped with somewhere else.", \ - "You smell ozone.") - for(var/obj/O in src.loc) - if(!O.anchored) - O.forceMove(IP.loc) - for(var/mob/M in src.loc) - M.forceMove(IP.loc) - return - - return fizzle(user) - - -/////////////////////////////////////////SECOND RUNE - -/obj/effect/rune/proc/tomesummon(var/mob/living/user) - if(istype(src,/obj/effect/rune)) - user.say("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!") - else - user.whisper("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!") - user.visible_message("Rune disappears with a flash of red light, and in its place now a book lies.", \ - "You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a book.", \ - "You hear a pop and smell ozone.") - if(istype(src,/obj/effect/rune)) - new /obj/item/book/tome(src.loc) - else - new /obj/item/book/tome(user.loc) - qdel(src) - return - - - -/////////////////////////////////////////THIRD RUNE - -/obj/effect/rune/proc/convert(var/mob/living/user) - var/mob/attacker = user - var/mob/living/carbon/target = null - for(var/mob/living/carbon/M in src.loc) - if(!iscultist(M) && M.stat < DEAD && !(M in converting)) - target = M - break - - if(!target) //didn't find any new targets - if(!converting.len) - fizzle(user) - else - to_chat(user, "You sense that the power of the dark one is already working away at them.") - return - - user.say("Mah[pick("'","`")]weyh pleggh at e'ntrath!") - - converting |= target - var/list/waiting_for_input = list(target = 0) //need to box this up in order to be able to reset it again from inside spawn, apparently - var/initial_message = 0 - while(target in converting) - if(target.loc != src.loc || target.stat == DEAD) - converting -= target - if(target.getFireLoss() < 100) - target.hallucination = min(target.hallucination, 500) - return 0 - - target.take_overall_damage(0, rand(5, 20)) // You dirty resister cannot handle the damage to your mind. Easily. - even cultists who accept right away should experience some effects - // Resist messages go! - if(initial_message) //don't do this stuff right away, only if they resist or hesitate. - admin_attack_log(attacker, target, "Used a convert rune", "Was subjected to a convert rune", "used a convert rune on") - switch(target.getFireLoss()) - if(0 to 25) - to_chat(target, "Your blood boils as you force yourself to resist the corruption invading every corner of your mind.") - target.take_overall_damage(0, 3) - if(25 to 45) - to_chat(target, "Your blood boils and your body burns as the corruption further forces itself into your body and mind.") - target.take_overall_damage(0, 5) - if(45 to 75) - to_chat(target, "You begin to hallucinate images of a dark and incomprehensible being and your entire body feels like its engulfed in flame as your mental defenses crumble.") - target.apply_effect(rand(1,10), STUTTER) - target.take_overall_damage(0, 10) - if(75 to 100) - to_chat(target, "Your mind turns to ash as the burning flames engulf your very soul and images of an unspeakable horror begin to bombard the last remnants of mental resistance.") - //broken mind - 5000 may seem like a lot I wanted the effect to really stand out for maxiumum losing-your-mind-spooky - //hallucination is reduced when the step off as well, provided they haven't hit the last stage... - target.hallucination += 5000 - target.apply_effect(10, STUTTER) - target.adjustBrainLoss(1, 55) - if(100 to INFINITY) - to_chat(target, "Your entire broken soul and being is engulfed in corruption and flames as your mind shatters away into nothing.") - target.hallucination += 5000 - target.apply_effect(15, STUTTER) - target.adjustBrainLoss(rand(1,5), 55) - - initial_message = 1 - if (!target.can_feel_pain()) - target.visible_message("The markings below [target] glow a bloody red.") - else - target.visible_message("[target] writhes in pain as the markings below \him glow a bloody red.", "AAAAAAHHHH!", "You hear an anguished scream.") - - if(!waiting_for_input[target]) //so we don't spam them with dialogs if they hesitate - waiting_for_input[target] = 1 - - if(!cult.can_become_antag(target.mind) || jobban_isbanned(target, "cultist"))//putting jobban check here because is_convertable uses mind as argument - //waiting_for_input ensures this is only shown once, so they basically auto-resist from here on out. They still need to find a way to get off the freaking rune if they don't want to burn to death, though. - to_chat(target, "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 in the festering wound left behind something sinister takes root.") - to_chat(target, "And you were able to force it out of your mind. Though the memory of that dark, horrible vision will surely haunt you for decades to come.") - - else spawn() - var/choice = alert(target,"Do you want to join the cult?","Submit to Nar'Sie","Resist","Submit") - waiting_for_input[target] = 0 - if(choice == "Submit") //choosing 'Resist' does nothing of course. - cult.add_antagonist(target.mind) - converting -= target - target.hallucination = 0 //sudden clarity - sound_to(target, 'sound/effects/bloodcult.ogg') - sleep(100) //proc once every 10 seconds - return 1 - -/////////////////////////////////////////FOURTH RUNE - -/obj/effect/rune/proc/tearreality(var/mob/living/user) - if(!cult.allow_narsie) - return fizzle(user) - - var/turf/T = get_turf(src) - if(isNotStationLevel(T.z)) - to_chat(user, "You are too far from the station, Nar'sie can not be summoned here.") - return fizzle(user) - - var/list/cultists = new() - for(var/mob/M in range(1,src)) - if(iscultist(M) && !M.stat) - M.say("Tok-lyr rqa'nap g[pick("'","`")]lt-ulotf!") - if(istype(M, /mob/living/carbon/human/apparition)) - continue - cultists.Add(M) - if(cultists.len >= 9) - log_and_message_admins_many(cultists, "summoned Nar-sie.") - new /obj/singularity/narsie/large(src.loc) - - // Can't summon a singular entity twice. - cult.allow_narsie = 0 - return - else - return fizzle(user) - -/////////////////////////////////////////FIFTH RUNE - -/obj/effect/rune/proc/emp(var/mob/living/user, var/U, var/range_red) //range_red - var which determines by which number to reduce the default emp range, U is the source loc, needed because of talisman emps which are held in hand at the moment of using and that apparently messes things up -- Urist - log_and_message_admins("activated an EMP rune.") - if(istype(src,/obj/effect/rune)) - user.say("Ta'gh fara[pick("'","`")]qha fel d'amar det!") - else - user.whisper("Ta'gh fara[pick("'","`")]qha fel d'amar det!") - playsound(U, 'sound/magic/Disable_Tech.ogg', 25, 1) - var/turf/T = get_turf(U) - var/rune = src // detaching the proc - in theory - - var/list/ex = list(user) // exclude caster - for(var/mob/M in range(range_red, T)) - if(iscultist(M)) - ex += M - else - continue - empulse(T, range_red - 2, range_red, exclude = ex) - qdel(rune) - return - -/////////////////////////////////////////SIXTH RUNE - -/obj/effect/rune/proc/drain(var/mob/living/user) - var/drain = 0 - for(var/obj/effect/rune/R in rune_list) - if(R.word1==cultwords["travel"] && R.word2==cultwords["blood"] && R.word3==cultwords["self"]) - for(var/mob/living/carbon/D in R.loc) - if(D.stat!=2) - admin_attack_log(user, D, "Used a blood drain rune.", "Was victim of a blood drain rune.", "used a blood drain rune on") - var/bdrain = rand(1,25) - to_chat(D, "You feel weakened.") - D.take_overall_damage(bdrain, 0) - drain += bdrain - if(!drain) - return fizzle(user) - user.say ("Yu[pick("'","`")]gular faras desdae. Havas mithum javara. Umathar uf'kal thenar!") - user.visible_message("Blood flows from the rune into [user]!", \ - "The blood starts flowing from the rune and into your frail mortal body. You feel... empowered.", \ - "You hear a liquid flowing.") - playsound(user, 'sound/magic/enter_blood.ogg', 100, 1) - - if(user.bhunger) - user.bhunger = max(user.bhunger-2*drain,0) - if(drain>=50) - user.visible_message("[user]'s eyes give off eerie red glow!", \ - "...but it wasn't nearly enough. You crave, crave for more. The hunger consumes you from within.", \ - "You hear a heartbeat.") - user.bhunger += drain - src = user - spawn() - for (,user.bhunger>0,user.bhunger--) - sleep(50) - user.take_overall_damage(3, 0) - return - user.heal_organ_damage(drain%5, 0) - drain-=drain%5 - for (,drain>0,drain-=5) - sleep(2) - user.heal_organ_damage(5, 0) - return - - - -/////////////////////////////////////////SEVENTH RUNE - -/obj/effect/rune/proc/seer(var/mob/living/user) - if(user.loc==src.loc) - if(user.seer==1) - user.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium viortia.") - to_chat(user, "The world beyond fades from your vision.") - user.see_invisible = SEE_INVISIBLE_LIVING - user.seer = 0 - else if(user.see_invisible!=SEE_INVISIBLE_LIVING) - to_chat(user, "The world beyond flashes your eyes but disappears quickly, as if something is disrupting your vision.") - user.see_invisible = SEE_INVISIBLE_CULT - user.seer = 0 - else - user.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium vivira. Itonis al'ra matum!") - to_chat(user, "The world beyond opens to your eyes.") - user.see_invisible = SEE_INVISIBLE_CULT - user.seer = 1 - return - return fizzle(user) - -/////////////////////////////////////////EIGHTH RUNE - -/obj/effect/rune/proc/raise(var/mob/living/user) - var/mob/living/carbon/human/corpse_to_raise - var/mob/living/carbon/human/body_to_sacrifice - - var/is_sacrifice_target = 0 - for(var/mob/living/carbon/human/M in src.loc) - if(M.stat == DEAD) - if(cult && M.mind == cult.sacrifice_target) - is_sacrifice_target = 1 - else - corpse_to_raise = M - if(M.key) - M.ghostize(1) //kick them out of their body - break - if(!corpse_to_raise) - if(is_sacrifice_target) - to_chat(user, "The Geometer of blood wants this mortal for himself.") - return fizzle(user) - - - is_sacrifice_target = 0 - find_sacrifice: - for(var/obj/effect/rune/R in rune_list) - if(R.word1==cultwords["blood"] && R.word2==cultwords["join"] && R.word3==cultwords["hell"]) - for(var/mob/living/carbon/human/N in R.loc) - if(cult && N.mind && N.mind == cult.sacrifice_target) - is_sacrifice_target = 1 - else - if(N.stat!= DEAD) - body_to_sacrifice = N - break find_sacrifice - - if(!body_to_sacrifice) - if (is_sacrifice_target) - to_chat(user, "The Geometer of Blood wants that corpse for himself.") - else - to_chat(user, "The sacrifical corpse is not dead. You must free it from this world of illusions before it may be used.") - return fizzle(user) - - var/mob/abstract/observer/ghost - for(var/mob/abstract/observer/O in loc) - if(!O.client) continue - if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue - ghost = O - break - - if(!ghost) - to_chat(user, "You require a restless spirit which clings to this world. Beckon their prescence with the sacred chants of Nar-Sie.") - return fizzle(user) - - corpse_to_raise.revive() - - corpse_to_raise.key = ghost.key //the corpse will keep its old mind! but a new player takes ownership of it (they are essentially possessed) - //This means, should that player leave the body, the original may re-enter - user.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!") - corpse_to_raise.visible_message("[corpse_to_raise]'s eyes glow with a faint red as he stands up, slowly starting to breathe again.", \ - "Life... I'm alive again...", \ - "You hear a faint, slightly familiar whisper.") - body_to_sacrifice.visible_message("[body_to_sacrifice] is torn apart, a black smoke swiftly dissipating from \his remains!", \ - "You feel as your blood boils, tearing you apart.", \ - "You hear a thousand voices, all crying in pain.") - body_to_sacrifice.gib() - -// if(ticker.mode.name == "cult") -// ticker.mode:add_cultist(corpse_to_raise.mind) -// else -// ticker.mode.cult |= corpse_to_raise.mind - - to_chat(corpse_to_raise, "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 in the festering wound left behind something sinister takes root.") - to_chat(corpse_to_raise, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") - return - - - - - -/////////////////////////////////////////NINETH RUNE - -/obj/effect/rune/proc/obscure(var/mob/living/user, var/rad) - var/S=0 - for(var/obj/effect/rune/R in orange(rad,src)) - if(R!=src) - R.invisibility=INVISIBILITY_OBSERVER - S=1 - if(S) - if(istype(src,/obj/effect/rune)) - user.say("Kla[pick("'","`")]atu barada nikt'o!") - for (var/mob/V in viewers(src)) - V.show_message("The rune turns into gray dust, veiling the surrounding runes.", 3) - qdel(src) - else - user.whisper("Kla[pick("'","`")]atu barada nikt'o!") - to_chat(user, "Your talisman turns into gray dust, veiling the surrounding runes.") - for (var/mob/V in orange(1,src)) - if(V!=user) - V.show_message("Dust emanates from [user]'s hands for a moment.", 3) - - return - if(istype(src,/obj/effect/rune)) - return fizzle(user) - else - call(/obj/effect/rune/proc/fizzle)(user) - return - -/////////////////////////////////////////TENTH RUNE - -/obj/effect/rune/proc/ajourney(var/mob/living/user) //some bits copypastaed from admin tools - Urist - if(user.loc==src.loc) - var/mob/living/carbon/human/L = user - user.say("Fwe[pick("'","`")]sh mah erl nyag r'ya!") - user.visible_message("[user]'s eyes glow blue as \he freezes in place, absolutely motionless.", \ - "The shadow that is your spirit separates itself from your body. You are now in the realm beyond. While this is a great sight, being here strains your mind and body. Hurry...", \ - "You hear only complete silence for a moment.") - announce_ghost_joinleave(user.ghostize(1), 1, "You feel that they had to use some [pick("dark", "black", "blood", "forgotten", "forbidden")] magic to [pick("invade","disturb","disrupt","infest","taint","spoil","blight")] this place!") - L.ajourn = 1 - while(L) - if(L.key) - L.ajourn=0 - return - else - L.take_organ_damage(10, 0) - sleep(100) - return fizzle(user) - - - - -/////////////////////////////////////////ELEVENTH RUNE - -/obj/effect/rune/proc/manifest(var/mob/living/user) - var/obj/effect/rune/this_rune = src - if(user.loc!=this_rune.loc) - return this_rune.fizzle(user) - var/mob/abstract/observer/ghost - for(var/mob/abstract/observer/O in this_rune.loc) - if(!O.client) continue - if(!O.MayRespawn()) continue - if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue - ghost = O - break - if(!ghost) - return this_rune.fizzle(user) - if(jobban_isbanned(ghost, "cultist")) - return this_rune.fizzle(user) - - user.say("Gal'h'rfikk harfrandid mud[pick("'","`")]gib!") - var/mob/living/carbon/human/apparition/D = new(this_rune.loc) - user.visible_message("A shape forms in the center of the rune. A shape of... a man.", \ - "A shape forms in the center of the rune. A shape of... a man.", \ - "You hear liquid flowing.") - - var/chose_name = 0 - for(var/obj/item/paper/P in this_rune.loc) - if(P.info) - D.real_name = copytext(P.info, findtext(P.info,">")+1, findtext(P.info,"<",2) ) - chose_name = 1 - break - D.universal_speak = 1 - D.underwear = null - D.key = ghost.key - cult.add_antagonist(D.mind) - playsound(loc, 'sound/magic/exit_blood.ogg', 100, 1) - - if(!chose_name) - D.real_name = pick("Anguished", "Blasphemous", "Corrupt", "Cruel", "Depraved", "Despicable", "Disturbed", "Exacerbated", "Foul", "Hateful", "Inexorable", "Implacable", "Impure", "Malevolent", "Malignant", "Malicious", "Pained", "Profane", "Profligate", "Relentless", "Resentful", "Restless", "Spiteful", "Tormented", "Unclean", "Unforgiving", "Vengeful", "Vindictive", "Wicked", "Wronged") - D.real_name += " " - D.real_name += pick("Apparition", "Aptrgangr", "Dis", "Draugr", "Dybbuk", "Eidolon", "Fetch", "Fylgja", "Ghast", "Ghost", "Gjenganger", "Haint", "Phantom", "Phantasm", "Poltergeist", "Revenant", "Shade", "Shadow", "Soul", "Spectre", "Spirit", "Spook", "Visitant", "Wraith") - - log_and_message_admins("used a manifest rune.") - - while(this_rune && user && user.stat==CONSCIOUS && user.client && user.loc==this_rune.loc) - user.take_organ_damage(1, 0) - sleep(30) - if(D) - D.visible_message("[D] slowly dissipates into dust and bones.", \ - "You feel pain, as bonds formed between your soul and this homunculus break.", \ - "You hear faint rustle.") - D.dust() - return - - - -/////////////////////////////////////////TWELFTH RUNE - -/obj/effect/rune/proc/talisman(var/mob/living/user)//only hide, emp, teleport, deafen, blind and tome runes can be imbued atm - var/obj/item/paper/newtalisman - var/unsuitable_newtalisman = 0 - for(var/obj/item/paper/P in src.loc) - if(!P.info) - newtalisman = P - break - else - unsuitable_newtalisman = 1 - if (!newtalisman) - if (unsuitable_newtalisman) - to_chat(user, "The blank is tainted. It is unsuitable.") - return fizzle(user) - - var/obj/effect/rune/imbued_from - var/obj/item/paper/talisman/T - for(var/obj/effect/rune/R in orange(1,src)) - if(R==src) - continue - if(R.word1==cultwords["travel"] && R.word2==cultwords["self"]) //teleport - T = new(src.loc) - T.imbue = "[R.word3]" - T.info = "[R.word3]" - imbued_from = R - break - if(R.word1==cultwords["see"] && R.word2==cultwords["blood"] && R.word3==cultwords["hell"]) //tome - T = new(src.loc) - T.imbue = "newtome" - imbued_from = R - break - if(R.word1==cultwords["destroy"] && R.word2==cultwords["see"] && R.word3==cultwords["technology"]) //emp - T = new(src.loc) - T.imbue = "emp" - imbued_from = R - break - if(R.word1==cultwords["hide"] && R.word2==cultwords["see"] && R.word3==cultwords["blood"]) //conceal - T = new(src.loc) - T.imbue = "conceal" - imbued_from = R - break - if(R.word1==cultwords["hell"] && R.word2==cultwords["destroy"] && R.word3==cultwords["other"]) //armor - T = new(src.loc) - T.imbue = "armor" - imbued_from = R - break - if(R.word1==cultwords["blood"] && R.word2==cultwords["see"] && R.word3==cultwords["hide"]) //reveal - T = new(src.loc) - T.imbue = "revealrunes" - imbued_from = R - break - if(R.word1==cultwords["hide"] && R.word2==cultwords["other"] && R.word3==cultwords["see"]) //deafen - T = new(src.loc) - T.imbue = "deafen" - imbued_from = R - break - if(R.word1==cultwords["destroy"] && R.word2==cultwords["see"] && R.word3==cultwords["other"]) //blind - T = new(src.loc) - T.imbue = "blind" - imbued_from = R - break - if(R.word1==cultwords["self"] && R.word2==cultwords["other"] && R.word3==cultwords["technology"]) //communicat - T = new(src.loc) - T.imbue = "communicate" - imbued_from = R - break - if(R.word1==cultwords["join"] && R.word2==cultwords["hide"] && R.word3==cultwords["technology"]) //communicat - T = new(src.loc) - T.imbue = "runestun" - imbued_from = R - break - if (imbued_from) - for (var/mob/V in viewers(src)) - V.show_message("The runes turn into dust, which then forms into an arcane image on the paper.", 3) - user.say("H'drak v[pick("'","`")]loso, mir'kanas verbot!") - qdel(imbued_from) - qdel(newtalisman) - else - return fizzle(user) - -/////////////////////////////////////////THIRTEENTH RUNE - -/obj/effect/rune/proc/mend(var/mob/living/user) - src = null - user.say("Uhrast ka'hfa heldsagen ver[pick("'","`")]lot!") - user.take_overall_damage(200, 0) - runedec+=10 - user.visible_message("\The [user] keels over dead, \his blood glowing blue as it escapes \his body and dissipates into thin air.", \ - "In the last moment of your humble life, you feel an immense pain as fabric of reality mends... with your blood.", \ - "You hear faint rustle.") - for(,user.stat==2) - sleep(600) - if (!user) - return - runedec-=10 - return - - -/////////////////////////////////////////FOURTEETH RUNE - -// returns 0 if the rune is not used. returns 1 if the rune is used. -/obj/effect/rune/proc/communicate(var/mob/living/user) - . = 1 // Default output is 1. If the rune is deleted it will return 1 - var/input = input(user, "Please choose a message to tell to the other acolytes.", "Voice of Blood", "")//sanitize() below, say() and whisper() have their own - if(!input) - if (istype(src)) - fizzle(user) - return 0 - else - return 0 - - if(istype(src,/obj/effect/rune)) - user.say("O bidai nabora se[pick("'","`")]sma!") - user.say("[input]") - else - user.whisper("O bidai nabora se[pick("'","`")]sma!") - user.whisper("[input]") - - input = sanitize(input) - log_and_message_admins("used a communicate rune to say '[input]'") - for(var/datum/mind/H in cult.current_antagonists) - if (H.current) - to_chat(H.current, "[input]") - qdel(src) - return 1 - -/////////////////////////////////////////FIFTEENTH RUNE - -/obj/effect/rune/proc/sacrifice(var/mob/living/user) - var/list/mob/living/carbon/human/cultsinrange = list() - var/list/mob/living/carbon/human/victims = list() - for(var/mob/living/carbon/human/V in src.loc)//Checks for non-cultist humans to sacrifice - if(ishuman(V)) - if(!(iscultist(V))) - victims += V//Checks for cult status and mob type - for(var/obj/item/I in src.loc)//Checks for MMIs/brains/Intellicards - if(istype(I,/obj/item/organ/internal/brain)) - var/obj/item/organ/internal/brain/B = I - victims += B.brainmob - else if(istype(I,/obj/item/device/mmi)) - var/obj/item/device/mmi/B = I - victims += B.brainmob - else if(istype(I,/obj/item/aicard)) - for(var/mob/living/silicon/ai/A in I) - victims += A - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - cultsinrange += C - C.say("Barhah hra zar[pick("'","`")]garis!") - - for(var/mob/H in victims) - - var/worth = 0 - if(istype(H,/mob/living/carbon/human)) - var/mob/living/carbon/human/lamb = H - if(lamb.species.rarity_value > 3) - worth = 1 - - if (SSticker.mode.name == "Cult") - if(H.mind == cult.sacrifice_target) - if(cultsinrange.len >= 3) - sacrificed += H.mind - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - to_chat(user, "The Geometer of Blood accepts this sacrifice, your objective is now complete.") - else - to_chat(user, "Your target's earthly bonds are too strong. You need more cultists to succeed in this ritual.") - else - if(cultsinrange.len >= 3) - if(H.stat != DEAD) - if(prob(80) || worth) - to_chat(user, "The Geometer of Blood accepts this [worth ? "exotic " : ""]sacrifice.") - else - to_chat(user, "The Geometer of Blood accepts this sacrifice.") - to_chat(user, "However, this soul was not enough to gain His favor.") - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - else - if(prob(40) || worth) - to_chat(user, "The Geometer of Blood accepts this [worth ? "exotic " : ""]sacrifice.") - else - to_chat(user, "The Geometer of Blood accepts this sacrifice.") - to_chat(user, "However, a mere dead body is not enough to satisfy Him.") - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - else - if(H.stat != DEAD) - to_chat(user, "The victim is still alive, you will need more cultists chanting for the sacrifice to succeed.") - else - if(prob(40)) - - to_chat(user, "The Geometer of Blood accepts this sacrifice.") - else - to_chat(user, "The Geometer of Blood accepts this sacrifice.") - to_chat(user, "However, a mere dead body is not enough to satisfy Him.") - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - else - if(cultsinrange.len >= 3) - if(H.stat != DEAD) - if(prob(80)) - to_chat(user, "The Geometer of Blood accepts this sacrifice.") - else - to_chat(user, "The Geometer of Blood accepts this sacrifice.") - to_chat(user, "However, this soul was not enough to gain His favor.") - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - else - if(prob(40)) - to_chat(user, "The Geometer of Blood accepts this sacrifice.") - else - to_chat(user, "The Geometer of Blood accepts this sacrifice.") - to_chat(user, "However, a mere dead body is not enough to satisfy Him.") - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - else - if(H.stat != DEAD) - to_chat(user, "The victim is still alive, you will need more cultists chanting for the sacrifice to succeed.") - else - if(prob(40)) - to_chat(user, "The Geometer of Blood accepts this sacrifice.") - else - to_chat(user, "The Geometer of Blood accepts this sacrifice.") - to_chat(user, "However, a mere dead body is not enough to satisfy Him.") - if(isrobot(H)) - H.dust()//To prevent the MMI from remaining - else - H.gib() - -/////////////////////////////////////////SIXTEENTH RUNE - -/obj/effect/rune/proc/revealrunes(var/mob/living/user, var/obj/W as obj) - var/go=0 - var/rad - var/S=0 - if(istype(W,/obj/effect/rune)) - rad = 6 - go = 1 - if (istype(W,/obj/item/paper/talisman)) - rad = 4 - go = 1 - if (istype(W,/obj/item/nullrod)) - rad = 2 - go = 1 - if(go) - for(var/obj/effect/rune/R in orange(rad,src)) - if(R!=src) - R:visibility=15 - S=1 - if(S) - if(istype(W,/obj/item/nullrod)) - visible_message(span("warning", "Arcane markings suddenly glow from underneath a thin layer of dust!")) - return - if(istype(W,/obj/effect/rune)) - user.say("Nikt[pick("'","`")]o barada kla'atu!") - for (var/mob/V in viewers(src)) - V.show_message("The rune turns into red dust, reveaing the surrounding runes.", 3) - qdel(src) - return - if(istype(W,/obj/item/paper/talisman)) - user.whisper("Nikt[pick("'","`")]o barada kla'atu!") - to_chat(user, "Your talisman turns into red dust, revealing the surrounding runes.") - for (var/mob/V in orange(1,user.loc)) - if(V!=user) - V.show_message("Red dust emanates from [user]'s hands for a moment.", 3) - return - return - if(istype(W,/obj/effect/rune)) - return fizzle(user) - if(istype(W,/obj/item/paper/talisman)) - call(/obj/effect/rune/proc/fizzle)(user) - return - -/////////////////////////////////////////SEVENTEENTH RUNE - -/obj/effect/rune/proc/wall(var/mob/living/user) - user.say("Khari[pick("'","`")]d! Eske'te tannin!") - src.density = !src.density - user.take_organ_damage(2, 0) - if(src.density) - to_chat(user, "Your blood flows into the rune, and you feel that the very space over the rune thickens.") - else - to_chat(user, "Your blood flows into the rune, and you feel as the rune releases its grasp on space.") - return - -/////////////////////////////////////////EIGHTTEENTH RUNE - -/obj/effect/rune/proc/freedom(var/mob/living/user) - var/list/mob/living/carbon/cultists = new - for(var/datum/mind/H in cult.current_antagonists) - if (istype(H.current,/mob/living/carbon)) - cultists+=H.current - var/list/mob/living/carbon/users = new - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - users+=C - var/dam = round(15 / users.len) - if(users.len>=3) - var/mob/living/carbon/cultist = input("Choose the one who you want to free", "Followers of Geometer") as null|anything in (cultists - users) - if(!cultist) - return fizzle(user) - if (cultist == user) //just to be sure. - return - if(!(cultist.buckled || \ - cultist.handcuffed || \ - istype(cultist.wear_mask, /obj/item/clothing/mask/muzzle) || \ - (istype(cultist.loc, /obj/structure/closet)&&cultist.loc:welded) || \ - (istype(cultist.loc, /obj/structure/closet/secure_closet)&&cultist.loc:locked) || \ - (istype(cultist.loc, /obj/machinery/dna_scannernew)&&cultist.loc:locked) \ - )) - to_chat(user, "The [cultist] is already free.") - return - cultist.buckled = null - if (cultist.handcuffed) - cultist.drop_from_inventory(cultist.handcuffed) - if (cultist.legcuffed) - cultist.drop_from_inventory(cultist.legcuffed) - if (istype(cultist.wear_mask, /obj/item/clothing/mask/muzzle)) - cultist.drop_from_inventory(cultist.wear_mask) - if(istype(cultist.loc, /obj/structure/closet)&&cultist.loc:welded) - cultist.loc:welded = 0 - if(istype(cultist.loc, /obj/structure/closet/secure_closet)&&cultist.loc:locked) - cultist.loc:locked = 0 - if(istype(cultist.loc, /obj/machinery/dna_scannernew)&&cultist.loc:locked) - cultist.loc:locked = 0 - for(var/mob/living/carbon/C in users) - user.take_overall_damage(dam, 0) - C.say("Khari[pick("'","`")]d! Gual'te nikka!") - qdel(src) - return fizzle(user) - -/////////////////////////////////////////NINETEENTH RUNE - -/obj/effect/rune/proc/cultsummon(var/mob/living/user) - var/list/mob/living/carbon/cultists = new - for(var/datum/mind/H in cult.current_antagonists) - if (istype(H.current,/mob/living/carbon)) - cultists+=H.current - var/list/mob/living/carbon/users = new - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - users += C - if(users.len>=3) - var/mob/living/carbon/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - user) - if(!cultist) - return fizzle(user) - if (cultist == user) //just to be sure. - return - if(cultist.buckled || cultist.handcuffed || (!isturf(cultist.loc) && !istype(cultist.loc, /obj/structure/closet))) - to_chat(user, "You cannot summon \the [cultist], for \his shackles of blood are strong.") - return fizzle(user) - cultist.forceMove(src.loc) - cultist.lying = 1 - cultist.regenerate_icons() - - var/dam = round(25 / (users.len/2)) //More people around the rune less damage everyone takes. Minimum is 3 cultists - - for(var/mob/living/carbon/human/C in users) - if(iscultist(C) && !C.stat) - C.say("N'ath reth sh'yro eth d[pick("'","`")]rekkathnor!") - C.take_overall_damage(dam, 0) - if(users.len <= 4) // You did the minimum, this is going to hurt more and we're going to stun you. - C.apply_effect(rand(3,6), STUN) - C.apply_effect(1, WEAKEN) - user.visible_message("Rune disappears with a flash of red light, and in its place now a body lies.", \ - "You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a body.", \ - "You hear a pop and smell ozone.") - qdel(src) - return fizzle(user) - -/////////////////////////////////////////TWENTIETH RUNES - -/obj/effect/rune/proc/deafen(var/mob/living/user) - if(istype(src,/obj/effect/rune)) - var/list/affected = new() - for(var/mob/living/carbon/C in range(7,src)) - if (iscultist(C)) - continue - var/obj/item/nullrod/N = locate() in C - if(N) - continue - C.ear_deaf += 50 - C.show_message("The world around you suddenly becomes quiet.", 3) - affected += C - if(prob(1)) - C.sdisabilities |= DEAF - if(affected.len) - user.say("Sti[pick("'","`")] kaliedir!") - to_chat(user, "The world becomes quiet as the deafening rune dissipates into fine dust.") - admin_attacker_log_many_victims(user, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on") - qdel(src) - else - return fizzle(user) - else - var/list/affected = new() - for(var/mob/living/carbon/C in range(7,user)) - if (iscultist(C)) - continue - var/obj/item/nullrod/N = locate() in C - if(N) - continue - C.ear_deaf += 30 - //talismans is weaker. - C.show_message("The world around you suddenly becomes quiet.", 3) - affected += C - if(affected.len) - user.whisper("Sti[pick("'","`")] kaliedir!") - to_chat(user, "Your talisman turns into gray dust, deafening everyone around.") - admin_attacker_log_many_victims(user, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on") - for (var/mob/V in orange(1,src)) - if(!(iscultist(V))) - V.show_message("Dust flows from [user]'s hands for a moment, and the world suddenly becomes quiet..", 3) - return - -/obj/effect/rune/proc/blind(var/mob/living/user) - if(istype(src,/obj/effect/rune)) - var/list/affected = new() - for(var/mob/living/carbon/C in viewers(src)) - if (iscultist(C)) - continue - var/obj/item/nullrod/N = locate() in C - if(N) - continue - C.eye_blurry += 50 - C.eye_blind += 20 - if(prob(5)) - C.disabilities |= NEARSIGHTED - if(prob(10)) - C.sdisabilities |= BLIND - C.show_message("Suddenly you see a red flash that blinds you.", 3) - affected += C - if(affected.len) - user.say("Sti[pick("'","`")] kaliesin!") - to_chat(user, "The rune flashes, blinding those who not follow the Nar-Sie, and dissipates into fine dust.") - admin_attacker_log_many_victims(user, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on") - qdel(src) - else - return fizzle(user) - else - var/list/affected = new() - for(var/mob/living/carbon/C in view(2,user)) - if (iscultist(C)) - continue - var/obj/item/nullrod/N = locate() in C - if(N) - continue - C.eye_blurry += 30 - C.eye_blind += 10 - //talismans is weaker. - affected += C - C.show_message("You feel a sharp pain in your eyes, and the world disappears into darkness..", 3) - if(affected.len) - user.whisper("Sti[pick("'","`")] kaliesin!") - to_chat(user, "Your talisman turns into gray dust, blinding those who not follow the Nar-Sie.") - admin_attacker_log_many_victims(user, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on") - return - - -/obj/effect/rune/proc/bloodboil(var/mob/living/user) //cultists need at least one DANGEROUS rune. Even if they're all stealthy. -/* - var/list/mob/living/carbon/cultists = new - for(var/datum/mind/H in ticker.mode.cult) - if (istype(H.current,/mob/living/carbon)) - cultists+=H.current -*/ - var/list/cultists = new //also, wording for it is old wording for obscure rune, which is now hide-see-blood. - var/list/victims = new -// var/list/cultboil = list(cultists-user) //and for this words are destroy-see-blood. - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - cultists+=C - if(cultists.len>=3) - for(var/mob/living/carbon/M in viewers(user)) - if(iscultist(M)) - continue - var/obj/item/nullrod/N = locate() in M - if(N) - continue - M.take_overall_damage(51,51) - to_chat(M, "Your blood boils!") - victims += M - if(prob(5)) - spawn(5) - M.gib() - for(var/obj/effect/rune/R in view(src)) - if(prob(10)) - explosion(R.loc, -1, 0, 1, 5) - for(var/mob/living/carbon/human/C in orange(1,src)) - if(iscultist(C) && !C.stat) - C.say("Dedo ol[pick("'","`")]btoh!") - C.take_overall_damage(15, 0) - admin_attacker_log_many_victims(user, victims, "Used a blood boil rune.", "Was the victim of a blood boil rune.", "used a blood boil rune on") - log_and_message_admins_many(cultists - user, "assisted activating a blood boil rune.") - qdel(src) - else - return fizzle(user) - return - -// WIP rune, I'll wait for Rastaf0 to add limited blood. - -/obj/effect/rune/proc/burningblood(var/mob/living/user) - var/culcount = 0 - for(var/mob/living/carbon/C in orange(1,src)) - if(iscultist(C) && !C.stat) - culcount++ - if(culcount >= 5) - for(var/obj/effect/rune/R in rune_list) - if(R.blood_DNA == src.blood_DNA) - for(var/mob/living/M in orange(2,R)) - M.take_overall_damage(0,15) - if (R.invisibility>M.see_invisible) - to_chat(M, "Aargh it burns!") - else - to_chat(M, "Rune suddenly ignites, burning you!") - var/turf/T = get_turf(R) - T.hotspot_expose(700,125) - for(var/obj/effect/decal/cleanable/blood/B in world) - if(B.blood_DNA == src.blood_DNA) - for(var/mob/living/M in orange(1,B)) - M.take_overall_damage(0,5) - to_chat(M, "Blood suddenly ignites, burning you!") - var/turf/T = get_turf(B) - T.hotspot_expose(700,125) - qdel(B) - qdel(src) - -////////// Rune 24 (counting burningblood, which kinda doesnt work yet.) - -/obj/effect/rune/proc/runestun(var/mob/living/user, var/mob/living/T as mob) - if(istype(src,/obj/effect/rune)) ///When invoked as rune, flash and briefly stun everyone around. - user.say("Fuu ma[pick("'","`")]jin!") - for(var/mob/living/L in viewers(src)) - if(iscultist(L)) - continue - if(iscarbon(L)) - var/mob/living/carbon/C = L - flick("e_flash", C.flash) - if(C.stuttering < 1 && (!(HULK in C.mutations))) - C.stuttering = 1 - C.Weaken(3) - C.Stun(3) - C.silent += 15 - C.show_message("The rune explodes in a bright flash.", 3) - admin_attack_log(user, C, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on") - - else if(issilicon(L)) - var/mob/living/silicon/S = L - S.Weaken(5) - flick("e_flash", S.flash) - S.silent += 15 - S.show_message("BZZZT... The rune has exploded in a bright flash.", 3) - admin_attack_log(user, S, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on") - qdel(src) - else ///When invoked as talisman, flash and mute the target mob. - user.say("Dream sign ''Evil sealing talisman'[pick("'","`")]!") - var/obj/item/nullrod/N = locate() in T - if(N) - for(var/mob/O in viewers(T, null)) - O.show_message(text("[] invokes a talisman at [], but they are unaffected!", user, T), 1) - else - for(var/mob/O in viewers(T, null)) - O.show_message(text("[] invokes a talisman at []", user, T), 1) - - if(issilicon(T)) - flick("e_flash", T.flash) - T.silent += 15 - admin_attack_log(user, T, "Used a stun talisman.", "Was victim of a stun talisman.", "used a stun talisman on") - else if(iscarbon(T)) - var/mob/living/carbon/C = T - flick("e_flash", C.flash) - if(!(HULK in C.mutations)) - C.silent += 15 - admin_attack_log(user, C, "Used a stun talisman.", "Was victim of a stun talisman.", "used a stun talisman on") - return - -/////////////////////////////////////////TWENTY-FIFTH RUNE - -/obj/effect/rune/proc/armor(var/mob/living/user) - if(istype(src,/obj/effect/rune)) - user.say("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!") - else - user.whisper("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!") - user.visible_message("The rune disappears with a flash of red light, and a set of armor appears on [user]...", \ - "You are blinded by the flash of red light! After you're able to see again, you see that you are now wearing a set of armor.") - - if(istype(user, /mob/living/simple_animal/construct)) - var/mob/living/simple_animal/construct/C = user - var/construct_class - if(narsie_cometh) - construct_class = alert(C, "Please choose which type of construct you wish to become.",,"Juggernaut","Wraith","Harvester") - else - construct_class = alert(C, "Please choose which type of construct you wish to become.",,"Juggernaut","Wraith","Artificer") - switch(construct_class) - if("Juggernaut") - var/mob/living/simple_animal/construct/armoured/Z = new /mob/living/simple_animal/construct/armoured (get_turf(C.loc)) - Z.key = C.key - if(iscultist(C)) - cult.add_antagonist(Z.mind) - C.death() - to_chat(Z, "You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike.") - to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") - Z.cancel_camera() - if("Wraith") - var/mob/living/simple_animal/construct/wraith/Z = new /mob/living/simple_animal/construct/wraith (get_turf(C.loc)) - Z.key = C.key - if(iscultist(C)) - cult.add_antagonist(Z.mind) - C.death() - to_chat(Z, "You are playing a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.") - to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") - Z.cancel_camera() - if("Artificer") - var/mob/living/simple_animal/construct/builder/Z = new /mob/living/simple_animal/construct/builder (get_turf(C.loc)) - Z.key = C.key - if(iscultist(C)) - cult.add_antagonist(Z.mind) - C.death() - to_chat(Z, "You are playing an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, repair allied constructs (by clicking on them), and even create new constructs") - to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") - Z.cancel_camera() - if("Harvester") - var/mob/living/simple_animal/construct/builder/Z = new /mob/living/simple_animal/construct/harvester (get_turf(C.loc)) - Z.key = C.key - if(iscultist(C)) - cult.add_antagonist(Z.mind) - C.death() - to_chat(Z, "You are playing a Harvester. You are gifted with the ability to open doors with your mind, to draw runes at will, and to teleport back to Nar'Sie. Seek out all non-believers and bring them to the Geometer.") - to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") - Z.cancel_camera() - else - user.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head) - user.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit) - user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult(user), slot_shoes) - user.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), slot_back) - //the above update their overlay icons cache but do not call update_icons() - //the below calls update_icons() at the end, which will update overlay icons by using the (now updated) cache - user.put_in_hands(new /obj/item/melee/cultblade(user)) //put in hands or on floor - - qdel(src) - return diff --git a/code/game/gamemodes/cult/runes/armor.dm b/code/game/gamemodes/cult/runes/armor.dm new file mode 100644 index 00000000000..41ec46d337c --- /dev/null +++ b/code/game/gamemodes/cult/runes/armor.dm @@ -0,0 +1,53 @@ +/obj/effect/rune/armor + can_talisman = TRUE + +/obj/effect/rune/armor/do_rune_action(mob/living/user, obj/O = src) + if(istype(O, /obj/effect/rune)) + user.say("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!") + else + user.whisper("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!") + user.visible_message(span("warning", "The rune disappears with a flash of red light, and a set of armor appears on [user]..."), span("cult", "You are blinded by the flash of red light! You feel the armor of the Dark One form around you.")) + + if(istype(user, /mob/living/simple_animal/construct)) + var/mob/living/simple_animal/construct/C = user + var/construct_class + if(narsie_cometh) + construct_class = alert(C, "Please choose which type of construct you wish to become.", "Construct Selection", "Juggernaut", "Wraith", "Harvester") + else + construct_class = alert(C, "Please choose which type of construct you wish to become.", "Construct Selection", "Juggernaut", "Wraith", "Artificer") + + var/list/static/construct_types = list("Juggernaut" = /mob/living/simple_animal/construct/armoured, + "Wraith" = /mob/living/simple_animal/construct/wraith, + "Artificer" = /mob/living/simple_animal/construct/builder, + "Harvester" = /mob/living/simple_animal/construct/harvester) + + var/construct_path = construct_types[construct_class] + var/mob/living/simple_animal/construct/Z = new construct_path(get_turf(C)) + Z.key = C.key + if(iscultist(C)) + cult.add_antagonist(Z.mind) + C.death() + construct_msg(Z, construct_class) + Z.cancel_camera() + + else if(ishuman(user)) + user.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head) + user.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit) + user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult(user), slot_shoes) + user.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), slot_back) + user.put_in_hands(new /obj/item/melee/cultblade(user)) + + qdel(O) + return TRUE + +/obj/effect/rune/armor/proc/construct_msg(mob/construct, var/type) + switch(type) + if("Juggernaut") + to_chat(construct, span("cult", "You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike.")) + if("Wraith") + to_chat(construct, span("cult", "You are playing a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.")) + if("Artificer") + to_chat(construct, span("cult", "You are playing an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, repair allied constructs (by clicking on them), and even create new constructs")) + if("Harvester") + to_chat(construct, span("cult", "You are playing a Harvester. You are gifted with the ability to open doors with your mind, to draw runes at will, and to teleport back to Nar'Sie. Seek out all non-believers and bring them to the Geometer.")) + to_chat(construct, span("cult", "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.")) diff --git a/code/game/gamemodes/cult/runes/blind_others.dm b/code/game/gamemodes/cult/runes/blind_others.dm new file mode 100644 index 00000000000..ec6c7d6f402 --- /dev/null +++ b/code/game/gamemodes/cult/runes/blind_others.dm @@ -0,0 +1,46 @@ +/obj/effect/rune/blind + can_talisman = TRUE + +/obj/effect/rune/blind/do_rune_action(mob/living/user, obj/O = src) + if(istype(O, /obj/effect/rune)) + var/list/affected = list() + for(var/mob/living/carbon/C in viewers(get_turf(O))) + if(iscultist(C)) + continue + var/obj/item/nullrod/N = locate() in C + if(N) + continue + C.eye_blurry += 50 + C.eye_blind += 20 + if(prob(5)) + C.disabilities |= NEARSIGHTED + if(prob(10)) + C.sdisabilities |= BLIND + to_chat(C, span("danger", "Suddenly you see a red flash that blinds you!")) + affected += C + if(length(affected)) + user.say("Sti[pick("'","`")] kaliesin!") + to_chat(user, span("warning", "The rune flashes, blinding those who not follow the Nar-Sie, and dissipates into fine dust.")) + admin_attacker_log_many_victims(user, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on") + qdel(O) + return TRUE + else + return fizzle(user) + else + var/list/affected = list() + for(var/mob/living/carbon/C in view(2,user)) + if(iscultist(C)) + continue + var/obj/item/nullrod/N = locate() in C + if(N) + continue + C.eye_blurry += 30 + C.eye_blind += 10 + //talismans is weaker. + affected += C + to_chat(C, span("warning", "You feel a sharp pain in your eyes, and the world disappears into darkness..")) + if(length(affected)) + user.whisper("Sti[pick("'","`")] kaliesin!") + to_chat(user, span("warning", "Your talisman turns into gray dust, blinding those who not follow the Nar-Sie.")) + admin_attacker_log_many_victims(user, affected, "Used a blindness talisman.", "Was victim of a blindness talisman.", "used a blindness talisman on") + return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/blood_boil.dm b/code/game/gamemodes/cult/runes/blood_boil.dm new file mode 100644 index 00000000000..8c648308d87 --- /dev/null +++ b/code/game/gamemodes/cult/runes/blood_boil.dm @@ -0,0 +1,26 @@ +/obj/effect/rune/blood_boil/do_rune_action(mob/living/user) //cultists need at least one DANGEROUS rune. Even if they're all stealthy. + var/list/cultists = list() + var/list/victims = list() + for(var/mob/living/carbon/C in orange(1, src)) + if(iscultist(C) && !C.stat) + cultists += C + if(length(cultists) >= 3) + for(var/mob/living/carbon/M in viewers(user)) + if(iscultist(M)) + continue + var/obj/item/nullrod/N = locate() in M + if(N) + continue + M.take_overall_damage(50, 50) + to_chat(M, span("danger", "Your blood boils!")) + victims += M + for(var/mob/living/carbon/human/C in orange(1, src)) + if(iscultist(C) && !C.stat) + C.say("Dedo ol[pick("'","`")]btoh!") + C.take_overall_damage(15, 0) + admin_attacker_log_many_victims(user, victims, "Used a blood boil rune.", "Was the victim of a blood boil rune.", "used a blood boil rune on") + log_and_message_admins_many(cultists - user, "assisted activating a blood boil rune.") + qdel(src) + return TRUE + else + return fizzle(user) \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/blood_drain.dm b/code/game/gamemodes/cult/runes/blood_drain.dm new file mode 100644 index 00000000000..434c752dc67 --- /dev/null +++ b/code/game/gamemodes/cult/runes/blood_drain.dm @@ -0,0 +1,40 @@ +/obj/effect/rune/blood_drain + can_talisman = TRUE + +/obj/effect/rune/blood_drain/do_rune_action(mob/living/user) + var/drain + for(var/obj/effect/rune/blood_drain/R in rune_list) + for(var/mob/living/carbon/D in get_turf(R)) + if(D.stat != DEAD) + admin_attack_log(user, D, "Used a blood drain rune.", "Was victim of a blood drain rune.", "used a blood drain rune on") + var/bdrain = rand(1, 25) + to_chat(D, span("warning", "You feel weakened.")) + D.take_overall_damage(bdrain, 0) + drain += bdrain + if(!drain) + return fizzle(user) + user.say("Yu[pick("'","`")]gular faras desdae. Havas mithum javara. Umathar uf'kal thenar!") + user.visible_message("Blood flows from the rune into [user]!", \ + "The blood starts flowing from the rune and into your frail body. You feel... empowered.", \ + "You hear a liquid flowing.") + playsound(user, 'sound/magic/enter_blood.ogg', 100, 1) + + if(user.bhunger) + user.bhunger = max(user.bhunger-2*drain,0) + if(drain >= 50) + user.visible_message("[user]'s eyes give off an eerie red glow!", \ + "...but it wasn't nearly enough. You crave, crave for more. The hunger consumes you from within.", \ + "You hear a heartbeat.") + user.bhunger += drain + while(user.bhunger) + user.bhunger-- + sleep(50) + user.take_overall_damage(3, 0) + return + user.heal_organ_damage(drain%5, 0) + drain-=drain%5 + while(drain) + drain -= 5 + sleep(2) + user.heal_organ_damage(5, 0) + return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/communicate.dm b/code/game/gamemodes/cult/runes/communicate.dm new file mode 100644 index 00000000000..2843255fbd7 --- /dev/null +++ b/code/game/gamemodes/cult/runes/communicate.dm @@ -0,0 +1,23 @@ +// returns FALSE if the rune is not used. returns TRUE if the rune is used. +/obj/effect/rune/communicate/do_rune_action(mob/living/user) + . = TRUE // Default output is TRUE. If the rune is deleted it will return TRUE + var/input = input(user, "Please choose a message to tell to the other acolytes.", "Voice of Blood", "")//sanitize() below, say() and whisper() have their own + if(!input) + if(istype(src)) + fizzle(user) + return FALSE + + if(istype(src, /obj/effect/rune)) + user.say("O bidai nabora se[pick("'","`")]sma!") + user.say("[input]") + else + user.whisper("O bidai nabora se[pick("'","`")]sma!") + user.whisper("[input]") + + input = sanitize(input) + log_and_message_admins("used a communicate rune to say '[input]'") + for(var/datum/mind/H in cult.current_antagonists) + if(H.current) + to_chat(H.current, span("cult", "Cult Broadcast: \"[input]\"")) + qdel(src) + return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/conversion.dm b/code/game/gamemodes/cult/runes/conversion.dm new file mode 100644 index 00000000000..6f0cbc84125 --- /dev/null +++ b/code/game/gamemodes/cult/runes/conversion.dm @@ -0,0 +1,86 @@ +/obj/effect/rune/convert/do_rune_action(mob/living/user) + var/mob/living/attacker = user + var/mob/living/carbon/target = null + for(var/mob/living/carbon/M in src.loc) + if(!iscultist(M) && M.stat < DEAD && !(M in converting)) + target = M + break + + if(!target) //didn't find any new targets + if(!converting.len) + fizzle(user) + else + to_chat(user, span("cult", "You sense that the power of the dark one is already working away at them.")) + return + + user.say("Mah[pick("'","`")]weyh pleggh at e'ntrath!") + + converting |= target + var/list/waiting_for_input = list(target = 0) //need to box this up in order to be able to reset it again from inside spawn, apparently + var/initial_message = 0 + while(target in converting) + if(target.loc != src.loc || target.stat == DEAD) + converting -= target + if(target.getFireLoss() < 100) + target.hallucination = min(target.hallucination, 500) + return FALSE + + target.take_overall_damage(0, rand(5, 20)) // You dirty resister cannot handle the damage to your mind. Easily. - even cultists who accept right away should experience some effects + // Resist messages go! + if(initial_message) //don't do this stuff right away, only if they resist or hesitate. + admin_attack_log(attacker, target, "Used a convert rune", "Was subjected to a convert rune", "used a convert rune on") + switch(target.getFireLoss()) + if(0 to 25) + to_chat(target, span("cult", "Your blood boils as you force yourself to resist the corruption invading every corner of your mind.")) + target.take_overall_damage(0, 3) + if(25 to 45) + to_chat(target, span("cult", "Your blood boils and your body burns as the corruption further forces itself into your body and mind.")) + target.take_overall_damage(0, 5) + if(45 to 75) + to_chat(target, span("cult", "You begin to hallucinate images of a dark and incomprehensible being and your entire body feels like its engulfed in flame as your mental defenses crumble.")) + target.apply_effect(rand(1, 10), STUTTER) + target.take_overall_damage(0, 10) + if(75 to 100) + to_chat(target, span("cult", "Your mind turns to ash as the burning flames engulf your very soul and images of an unspeakable horror begin to bombard the last remnants of mental resistance.")) + //broken mind - 5000 may seem like a lot I wanted the effect to really stand out for maxiumum losing-your-mind-spooky + //hallucination is reduced when the step off as well, provided they haven't hit the last stage... + target.hallucination += 5000 + target.apply_effect(10, STUTTER) + target.adjustBrainLoss(1) + if(100 to INFINITY) + to_chat(target, span("cult", "Your entire broken soul and being is engulfed in corruption and flames as your mind shatters away into nothing.")) + target.hallucination += 5000 + target.apply_effect(15, STUTTER) + target.adjustBrainLoss(rand(1, 5)) + + initial_message = TRUE + if(!target.can_feel_pain()) + target.visible_message(span("warning", "The markings below [target] glow a bloody red.")) + else + target.visible_message(span("warning", "[target] writhes in pain as the markings below \him glow a bloody red."), span("danger", "AAAAAAHHHH!")) + + if(!waiting_for_input[target]) //so we don't spam them with dialogs if they hesitate + waiting_for_input[target] = TRUE + + if(!cult.can_become_antag(target.mind) || jobban_isbanned(target, "cultist"))//putting jobban check here because is_convertable uses mind as argument + //waiting_for_input ensures this is only shown once, so they basically auto-resist from here on out. They still need to find a way to get off the freaking rune if they don't want to burn to death, though. + to_chat(target, span("cult", "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 in the festering wound left behind, something sinister takes root.")) + to_chat(target, span("cult", "And you were able to force it out of your mind. Though the memory of that dark, horrible vision will surely haunt you for decades to come.")) + var/has_implant // we don't want people with loy implants to just get gibbed + for(var/obj/item/implant/loyalty/L in target) + if(L?.imp_in == target) + has_implant = TRUE + if(!has_implant) + to_chat(target, span("cult", "..or will it?")) + target.gib() // people who can't be cultists get gibbed to preserve cult anonymity + else + var/choice = alert(target,"Do you want to join the cult?", "Submit to Nar'Sie", "Resist", "Submit") + waiting_for_input[target] = FALSE + if(choice == "Submit") //choosing 'Resist' does nothing of course. + cult.add_antagonist(target.mind) + converting -= target + target.hallucination = 0 //sudden clarity + target.setBrainLoss(0) // nar'sie heals you + sound_to(target, 'sound/effects/bloodcult.ogg') + sleep(100) //proc once every 10 seconds + return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/create_talisman.dm b/code/game/gamemodes/cult/runes/create_talisman.dm new file mode 100644 index 00000000000..2ff8e794026 --- /dev/null +++ b/code/game/gamemodes/cult/runes/create_talisman.dm @@ -0,0 +1,36 @@ +//only hide, emp, teleport, deafen, blind and tome runes can be imbued atm +/obj/effect/rune/create_talisman/do_rune_action(mob/living/user) + var/obj/item/paper/new_talisman + var/cant_talisman + + for(var/obj/item/paper/P in get_turf(src)) + if(!P.info) + new_talisman = P + break + else + cant_talisman = TRUE + if(!new_talisman) + if(cant_talisman) + to_chat(user, span("cult", "The paper is tainted. It is unsuitable.")) + return fizzle(user) + + var/obj/effect/rune/imbued_from + for(var/obj/effect/rune/R in orange(1, src)) + if(R == src) + continue + if(!R.can_talisman) + continue + var/obj/item/paper/talisman/T = new /obj/item/paper/talisman(get_turf(src)) + T.imbued_rune = CALLBACK(R, /obj/effect/rune/.proc/do_rune_action) + T.rune = R.cult_description + imbued_from = R + if(R.network) + T.network = R.network + break + if(imbued_from) + visible_message(span("warning", "The runes turn into dust, which then forms into an arcane image on the paper.")) + user.say("H'drak v[pick("'","`")]loso, mir'kanas verbot!") + qdel(imbued_from) + qdel(new_talisman) + else + return fizzle(user) \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/deafen_others.dm b/code/game/gamemodes/cult/runes/deafen_others.dm new file mode 100644 index 00000000000..17624f73c11 --- /dev/null +++ b/code/game/gamemodes/cult/runes/deafen_others.dm @@ -0,0 +1,44 @@ +/obj/effect/rune/deafen + can_talisman = TRUE + +/obj/effect/rune/deafen/do_rune_action(mob/living/user, obj/O = src) + if(istype(O, /obj/effect/rune)) + var/list/affected = list() + for(var/mob/living/carbon/C in range(7, get_turf(O))) + if(iscultist(C)) + continue + var/obj/item/nullrod/N = locate() in C + if(N) + continue + C.ear_deaf += 50 + to_chat(C, span("warning", "The world around you suddenly becomes quiet.")) + affected += C + if(prob(1)) + C.sdisabilities |= DEAF + if(affected.len) + user.say("Sti[pick("'","`")] kaliedir!") + to_chat(user, span("cult", "The world becomes quiet as the deafening rune dissipates into fine dust.")) + admin_attacker_log_many_victims(user, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on") + qdel(O) + else + return fizzle(user) + else + var/list/affected = list() + for(var/mob/living/carbon/C in range(7, user)) + if(iscultist(C)) + continue + var/obj/item/nullrod/N = locate() in C + if(N) + continue + C.ear_deaf += 30 + //talismans is weaker. + to_chat(C, span("warning", "The world around you suddenly becomes quiet.")) + affected += C + if(affected.len) + user.whisper("Sti[pick("'","`")] kaliedir!") + to_chat(user, span("warning", "Your talisman turns into gray dust, deafening everyone around.")) + admin_attacker_log_many_victims(user, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on") + for(var/mob/V in orange(1, get_turf(O))) + if(!iscultist(V)) + to_chat(V, span("warning", "Dust flows from [user]'s hands for a moment, and the world suddenly becomes quiet..")) + return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/emp.dm b/code/game/gamemodes/cult/runes/emp.dm new file mode 100644 index 00000000000..39c58c77607 --- /dev/null +++ b/code/game/gamemodes/cult/runes/emp.dm @@ -0,0 +1,24 @@ +/obj/effect/rune/emp + can_talisman = TRUE + +/obj/effect/rune/emp/do_rune_action(mob/living/user, obj/O = src) + var/radius = 4 + if(istype(O, /obj/effect/rune)) + user.say("Ta'gh fara[pick("'","`")]qha fel d'amar det!") + log_and_message_admins("activated an EMP rune.") + else + user.whisper("Ta'gh fara[pick("'","`")]qha fel d'amar det!") + radius = 2 + log_and_message_admins("activated an EMP talisman.") + var/turf/T = get_turf(O) + playsound(T, 'sound/magic/Disable_Tech.ogg', 25, 1) + + var/list/ex = list(user) // exclude caster + for(var/mob/M in range(radius, T)) + if(iscultist(M)) + ex += M + else + continue + empulse(T, 1, radius, exclude = ex) + qdel(O) + return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/free_cultist.dm b/code/game/gamemodes/cult/runes/free_cultist.dm new file mode 100644 index 00000000000..0bbc635196b --- /dev/null +++ b/code/game/gamemodes/cult/runes/free_cultist.dm @@ -0,0 +1,61 @@ +/obj/effect/rune/freedom/do_rune_action(mob/living/user) + var/list/mob/living/carbon/human/cultists = list() + for(var/datum/mind/H in cult.current_antagonists) + if(istype(H.current,/mob/living/carbon/human)) + cultists += H.current + + var/list/mob/living/carbon/users = list() + for(var/mob/living/carbon/C in orange(1, src)) + if(iscultist(C) && !C.stat) + users += C + + if(users.len >= 3) + var/mob/living/carbon/human/cultist = input("Choose a cultist you wish to free.", "Followers of Geometer") as null|anything in (cultists - users) + if(!cultist) + return fizzle(user) + if(cultist == user) //just to be sure. + return + + var/cultist_free = TRUE + if(cultist.buckled) + cultist_free = FALSE + cultist.buckled = null + if(cultist.handcuffed) + cultist_free = FALSE + cultist.drop_from_inventory(cultist.handcuffed) + if(cultist.legcuffed) + cultist_free = FALSE + cultist.drop_from_inventory(cultist.legcuffed) + if(istype(cultist.wear_mask, /obj/item/clothing/mask/muzzle)) + cultist_free = FALSE + cultist.drop_from_inventory(cultist.wear_mask) + if(istype(cultist.wear_suit, /obj/item/clothing/suit/straight_jacket)) + cultist_free = FALSE + cultist.drop_from_inventory(cultist.wear_suit) + if(istype(cultist.loc, /obj/structure/closet)) + var/obj/structure/closet/C = cultist.loc + if(C.welded) + cultist_free = FALSE + C.welded = FALSE + if(istype(cultist.loc, /obj/structure/closet/secure_closet)) + var/obj/structure/closet/secure_closet/C = cultist.loc + if(C.locked) + cultist_free = FALSE + C.locked = FALSE + for(var/obj/machinery/door/airlock/door in range(2, get_turf(cultist))) + if(door.locked) + cultist_free = FALSE + door.unlock() + door.open() + + if(!cultist_free) + to_chat(cultist, span("cult", "Your fellow cultists have freed you!")) + + for(var/mob/living/carbon/C in users) + if(cultist_free) + to_chat(C, span("cult", "\The [cultist] is already free.")) + else + C.say("Khari[pick("'","`")]d! Gual'te nikka!") + qdel(src) + else if(istype(src, /obj/effect/rune)) + return fizzle(user) \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/ghost_mode.dm b/code/game/gamemodes/cult/runes/ghost_mode.dm new file mode 100644 index 00000000000..eb908d3eead --- /dev/null +++ b/code/game/gamemodes/cult/runes/ghost_mode.dm @@ -0,0 +1,19 @@ +/obj/effect/rune/ethereal/do_rune_action(mob/living/user) //some bits copypastaed from admin tools - Urist + if(get_turf(user) == get_turf(src)) + var/mob/living/carbon/human/L = user + user.say("Fwe[pick("'","`")]sh mah erl nyag r'ya!") + user.visible_message("[user]'s eyes glow blue as \he freezes in place, absolutely motionless.", \ + "The shadow that is your spirit separates itself from your body. You are now in the realm beyond. While this is a great sight, being here strains your mind and body. Hurry...", \ + "You hear only complete silence for a moment.") + announce_ghost_joinleave(user.ghostize(TRUE), 1, "You feel that they had to use some [pick("dark", "black", "blood", "forgotten", "forbidden")] magic to [pick("invade","disturb","disrupt","infest","taint","spoil","blight")] this place!") + L.ajourn = TRUE + while(L) + if(L.key) + L.ajourn = FALSE + return + else + L.take_organ_damage(10, 0) + sleep(100) + else + to_chat(user, span("warning", "You must be standing on the rune!")) + return fizzle(user) \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/hide_runes.dm b/code/game/gamemodes/cult/runes/hide_runes.dm new file mode 100644 index 00000000000..97a67c14358 --- /dev/null +++ b/code/game/gamemodes/cult/runes/hide_runes.dm @@ -0,0 +1,23 @@ +/obj/effect/rune/hiderunes + can_talisman = TRUE + +/obj/effect/rune/hiderunes/do_rune_action(mob/living/user, obj/O = src) + var/rune_found + for(var/obj/effect/rune/R in orange(4, get_turf(O))) + if(R != O) + R.invisibility=INVISIBILITY_OBSERVER + rune_found = TRUE + if(rune_found) + if(istype(O,/obj/effect/rune)) + user.say("Kla[pick("'","`")]atu barada nikt'o!") + for(var/mob/V in viewers(get_turf(O))) + to_chat(V, span("warning", "The rune turns into gray dust, veiling the surrounding runes.")) + qdel(O) + else + user.whisper("Kla[pick("'","`")]atu barada nikt'o!") + to_chat(user, span("warning", "Your talisman turns into gray dust, veiling the surrounding runes.")) + for(var/mob/V in orange(1, get_turf(O))) + if(V == user) + continue + to_chat(V, span("warning", "Dust emanates from [user]'s hands for a moment.")) + return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/manifest_ghost.dm b/code/game/gamemodes/cult/runes/manifest_ghost.dm new file mode 100644 index 00000000000..919c34e4a95 --- /dev/null +++ b/code/game/gamemodes/cult/runes/manifest_ghost.dm @@ -0,0 +1,54 @@ +/obj/effect/rune/manifest/do_rune_action(mob/living/user) + if(!iscarbon(user)) + to_chat(user, span("warning", "Your primitive form cannot use this rune!")) + if(get_turf(user) != get_turf(src)) + return fizzle(user) + + var/mob/abstract/observer/ghost + for(var/mob/abstract/observer/O in get_turf(src)) + if(!O.client) + continue + if(O.mind?.current?.stat != DEAD) + continue + if(jobban_isbanned(O, "cultist")) + continue + ghost = O + break + if(!ghost) + return fizzle(user) + + user.say("Gal'h'rfikk harfrandid mud[pick("'","`")]gib!") + var/mob/living/carbon/human/apparition/D = new(get_turf(src)) + user.visible_message("A shape forms in the center of the rune. A shape of... a man.", \ + "A shape forms in the center of the rune. A shape of... a man.", \ + "You hear liquid flowing.") + + var/chose_name = FALSE + for(var/obj/item/paper/P in get_turf(src)) + if(P.info) + D.real_name = copytext(P.info, findtext(P.info,">")+1, findtext(P.info,"<",2) ) + chose_name = TRUE + break + D.universal_speak = TRUE + D.underwear = null + D.key = ghost.key + cult.add_antagonist(D.mind) + playsound(loc, 'sound/magic/exit_blood.ogg', 100, 1) + + if(!chose_name) + D.real_name = pick("Anguished", "Blasphemous", "Corrupt", "Cruel", "Depraved", "Despicable", "Disturbed", "Exacerbated", "Foul", "Hateful", "Inexorable", "Implacable", "Impure", "Malevolent", "Malignant", "Malicious", "Pained", "Profane", "Profligate", "Relentless", "Resentful", "Restless", "Spiteful", "Tormented", "Unclean", "Unforgiving", "Vengeful", "Vindictive", "Wicked", "Wronged") + D.real_name += " " + D.real_name += pick("Apparition", "Aptrgangr", "Dis", "Draugr", "Dybbuk", "Eidolon", "Fetch", "Fylgja", "Ghast", "Ghost", "Gjenganger", "Haint", "Phantom", "Phantasm", "Poltergeist", "Revenant", "Shade", "Shadow", "Soul", "Spectre", "Spirit", "Spook", "Visitant", "Wraith") + + log_and_message_admins("used a manifest rune.") + + // The cultist doesn't have to stand on the rune, but they will continually take damage for as long as they have a summoned ghost + while(src && user?.stat == CONSCIOUS && user.client) + user.take_organ_damage(1, 0) + sleep(30) + if(D) + D.visible_message("[D] slowly dissipates into dust and bones.", \ + "You feel pain, as bonds formed between your soul and this homunculus break.", \ + "You hear a faint rustling.") + D.dust() + return diff --git a/code/game/gamemodes/cult/runes/raise_dead.dm b/code/game/gamemodes/cult/runes/raise_dead.dm new file mode 100644 index 00000000000..0cce47fd19c --- /dev/null +++ b/code/game/gamemodes/cult/runes/raise_dead.dm @@ -0,0 +1,84 @@ +/obj/effect/rune/raise_dead/do_rune_action(mob/living/user) + var/mob/living/carbon/human/corpse_to_raise + var/mob/living/carbon/human/body_to_maim + + var/is_sacrifice_target + for(var/mob/living/carbon/human/M in get_turf(src)) + if(M.stat == DEAD) + if(M.mind == cult?.sacrifice_target) + is_sacrifice_target = TRUE + else + corpse_to_raise = M + if(M.key) + M.ghostize(TRUE) + break + if(!corpse_to_raise) + if(is_sacrifice_target) + to_chat(user, span("warning", "The Geometer of blood wants this mortal for himself.")) + return fizzle(user) + + is_sacrifice_target = FALSE + for(var/obj/effect/rune/raise_dead/R in rune_list) + var/found_sacrifice = FALSE + for(var/mob/living/carbon/human/N in get_turf(R)) + if(N?.mind == cult?.sacrifice_target) + is_sacrifice_target = TRUE + else + if(N.stat != DEAD) + body_to_maim = N + found_sacrifice = TRUE + break + if(found_sacrifice) + break + + if(!body_to_maim) + if(is_sacrifice_target) + to_chat(user, span("cult", "The Geometer of Blood wants that corpse for himself.")) + else + to_chat(user, span("warning", "The sacrifical corpse is not dead. You must free it from this world of illusions before it may be used.")) + return fizzle(user) + + var/mob/abstract/observer/ghost + for(var/mob/abstract/observer/O in get_turf(src)) + if(!O.client) + continue + if(O.mind?.current?.stat != DEAD) + continue + if(jobban_isbanned(O, "cultist")) + continue + ghost = O + break + + if(!ghost) + to_chat(user, span("warning", "You require a restless spirit which clings to this world. Beckon their prescence with the sacred chants of Nar-Sie.")) + var/area/A = get_area(src) + for(var/mob/M in dead_mob_list) + to_chat(M, "[ghost_follow_link(user, M)] A cultist is attempting to revive a body in [A.name]!") + return fizzle(user) + + corpse_to_raise.revive() + + corpse_to_raise.key = ghost.key //the corpse will keep its old mind! but a new player takes ownership of it (they are essentially possessed) + //This means, should that player leave the body, the original may re-enter + user.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!") + corpse_to_raise.visible_message("[corpse_to_raise]'s eyes glow with a faint red as \he stands up, slowly starting to breathe again.", \ + "Life... I'm alive again...", \ + "You hear a faint, slightly familiar whisper.") + body_to_maim.visible_message("[body_to_maim] is torn apart, a black smoke swiftly dissipating from \his wounds!", \ + "You feel as your blood boils, tearing you apart.", \ + "You hear a thousand voices, all crying in pain.") + + var/list/obj/item/organ/external/possible_limbs = list() + var/limbs_to_drop = round(rand(1, 3)) + for(var/obj/item/organ/external/E in body_to_maim.organs) + if(E.vital) + continue + possible_limbs += E + + for(var/i = 1; i < limbs_to_drop + 1; i++) + var/obj/item/organ/external/limb = pick(possible_limbs) + limb.droplimb(FALSE, DROPLIMB_BURN) + + to_chat(corpse_to_raise, span("cult", "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 in the festering wound left behind something sinister takes root.")) + to_chat(corpse_to_raise, span("cult", "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring it back.")) + return \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/reveal_runes.dm b/code/game/gamemodes/cult/runes/reveal_runes.dm new file mode 100644 index 00000000000..d405908e9f4 --- /dev/null +++ b/code/game/gamemodes/cult/runes/reveal_runes.dm @@ -0,0 +1,48 @@ +/obj/effect/rune/revealrunes + can_talisman = TRUE + +/obj/effect/rune/revealrunes/do_rune_action(mob/living/user, obj/O = src) + var/reveal = FALSE + var/rad + var/did_reveal + if(istype(O, /obj/effect/rune)) + rad = 6 + reveal = TRUE + if(istype(O, /obj/item/paper/talisman)) + rad = 4 + reveal = TRUE + if(istype(O, /obj/item/nullrod)) + rad = 2 + reveal = TRUE + if(reveal) + for(var/obj/effect/rune/R in orange(rad, src)) + if(R == src) + continue + R.visible = 15 + did_reveal = TRUE + if(did_reveal) + if(istype(O, /obj/item/nullrod)) + visible_message(span("warning", "Arcane markings suddenly glow from underneath a thin layer of dust!")) + return + if(istype(O, /obj/effect/rune)) + user.say("Nikt[pick("'","`")]o barada kla'atu!") + for(var/mob/V in viewers(src)) + to_chat(V, span("warning", "The rune turns into red dust, reveaing the surrounding runes.")) + qdel(src) + return TRUE + if(istype(O, /obj/item/paper/talisman)) + user.whisper("Nikt[pick("'","`")]o barada kla'atu!") + to_chat(user, span("warning", "Your talisman turns into red dust, revealing the surrounding runes.")) + for(var/mob/V in orange(1, user.loc)) + if(V == user) + continue + to_chat(V, span("warning", "Red dust emanates from [user]'s hands for a moment.")) + qdel(src) + return + return TRUE + if(istype(O, /obj/effect/rune)) + return fizzle(user) + if(istype(O, /obj/item/paper/talisman)) + var/datum/callback/cb = CALLBACK(src, /obj/effect/rune/.proc/fizzle) + cb.Invoke(user) + return \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/rune.dm b/code/game/gamemodes/cult/runes/rune.dm new file mode 100644 index 00000000000..7aa73206340 --- /dev/null +++ b/code/game/gamemodes/cult/runes/rune.dm @@ -0,0 +1,98 @@ +var/global/rune_boost = 0 // How many extra runes the cult can lay down + +var/global/list/static/rune_types = list( + "Armor" = /obj/effect/rune/armor, + "Summon Tome" = /obj/effect/rune/summon_tome, + "Become Ethereal" = /obj/effect/rune/ethereal, + "Manifest Ghost" = /obj/effect/rune/manifest, + "Raise Dead" = /obj/effect/rune/raise_dead, + "Rune Wall" = /obj/effect/rune/wall, + "Blind" = /obj/effect/rune/blind, + "Blood Boil" = /obj/effect/rune/blood_boil, + "Blood Drain" = /obj/effect/rune/blood_drain, + "Communicate" = /obj/effect/rune/communicate, + "Convert" = /obj/effect/rune/convert, + "Create Talisman" = /obj/effect/rune/create_talisman, + "Deafen Others" = /obj/effect/rune/deafen, + "EMP" = /obj/effect/rune/emp, + "Free Cultist" = /obj/effect/rune/freedom, + "Hide Runes" = /obj/effect/rune/hiderunes, + "Reveal Runes" = /obj/effect/rune/revealrunes, + "Teleport" = /obj/effect/rune/teleport, + "Sacrifice" = /obj/effect/rune/sacrifice, + "See Invisible" = /obj/effect/rune/see_invisible, + "Stun" = /obj/effect/rune/stun, + "Summon Cultist" = /obj/effect/rune/summon_cultist, + "Summon Nar'sie" = /obj/effect/rune/summon_narsie, + "None" = /obj/effect/rune + ) + +/obj/effect/rune + desc = "A strange collection of symbols drawn in blood." + anchored = 1 + icon = 'icons/obj/rune.dmi' + icon_state = "1" + var/visible = FALSE + unacidable = TRUE + layer = AO_LAYER + + var/can_talisman = FALSE // some runes just don't work with talisman stuff + var/cult_description // what does the cult see the rune as? + + var/network // For teleportation runes. Can connect to other runes in the network. + var/list/converting = list() + +/obj/effect/rune/Initialize() + . = ..() + rune_list += src + name = "graffiti" + icon_state = pick("1", "2", "3", "4", "5", "6") + +/obj/effect/rune/Destroy() + rune_list -= src + return ..() + +/obj/effect/rune/examine(mob/user) + ..(user) + if(iscultist(user) || isobserver(user)) + desc = "A powerful rune drawn with blood magic gifted by Nar'sie Himself." + if(cult_description) + to_chat(user, "This spell circle reads: [cult_description].") + else + desc = "A strange collection of symbols drawn in blood." + +/obj/effect/rune/attackby(obj/I, mob/user) + if(istype(I, /obj/item/book/tome) && iscultist(user)) + to_chat(user, span("notice", "You retrace your steps, carefully undoing the lines of the rune.")) + qdel(src) + return + else if(istype(I, /obj/item/nullrod)) + to_chat(user, span("notice", "You disrupt the vile magic with the deadening field of \the [I]!")) + qdel(src) + return + return + +/obj/effect/rune/attack_hand(mob/living/user) + if(!iscultist(user)) + to_chat(user, span("notice", "You can't mouth the arcane scratchings without fumbling over them.")) + return + if(istype(user.wear_mask, /obj/item/clothing/mask/muzzle)) + to_chat(user, span("warning", "You are unable to speak the words of the rune.")) + return + return do_rune_action(user) + +// Runes should override this +/obj/effect/rune/proc/do_rune_action(var/mob/living/user, var/obj/O = src) + return + +/obj/effect/rune/proc/fizzle(var/mob/living/user) + if(istype(src,/obj/effect/rune)) + user.say(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.", "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) + else + user.whisper(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.", "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) + for(var/mob/V in viewers(src)) + to_chat(V, span("warning", "The markings pulse with a small burst of light, then fall dark.")) + return + +/obj/effect/rune/cultify() + return \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/sacrifice.dm b/code/game/gamemodes/cult/runes/sacrifice.dm new file mode 100644 index 00000000000..97c38c374f8 --- /dev/null +++ b/code/game/gamemodes/cult/runes/sacrifice.dm @@ -0,0 +1,83 @@ +/obj/effect/rune/sacrifice/do_rune_action(mob/living/user) + var/list/mob/living/carbon/human/cultists_in_range = list() + var/list/mob/living/carbon/human/victims = list() + + for(var/mob/living/carbon/human/V in get_turf(src)) // Checks for non-cultist humans to sacrifice + if(ishuman(V) && !iscultist(V)) + victims += V // Checks for cult status and mob type + + for(var/obj/item/I in get_turf(src)) // Checks for MMIs/brains/Intellicards + if(istype(I,/obj/item/organ/internal/brain)) + var/obj/item/organ/internal/brain/B = I + victims += B.brainmob + + else if(istype(I,/obj/item/device/mmi)) + var/obj/item/device/mmi/B = I + victims += B.brainmob + + else if(istype(I,/obj/item/aicard)) + for(var/mob/living/silicon/ai/A in I) + victims += A + + for(var/mob/living/carbon/C in orange(1, src)) + if(iscultist(C) && !C.stat) + cultists_in_range += C + C.say("Barhah hra zar[pick("'","`")]garis!") + + for(var/mob/H in victims) + var/worthy = FALSE + if(istype(H,/mob/living/carbon/human)) + var/mob/living/carbon/human/lamb = H + if(lamb.species.rarity_value > 3) + worthy = TRUE + + var/output + if(SSticker.mode.name == "Cult") + if(H.mind == cult.sacrifice_target) + if(cultists_in_range.len >= 3) + cult.sacrificed += H.mind + if(isrobot(H)) + H.dust() // To prevent the MMI from remaining + else + H.gib() + output = span("cult", "The Geometer of Blood accepts this sacrifice, your objective is now complete.") + else + output = span("cult", "Your target's earthly bonds are too strong. You need more cultists to succeed in this ritual.") + else + do_sacrifice(cultists_in_range, H, H.stat, 80, worthy) + else + fizzle(user) + + if(output) + for(var/mob/C in cultists_in_range) + to_chat(C, output) + +/obj/effect/rune/sacrifice/proc/do_sacrifice(var/list/mob/cultists, var/mob/victim, var/victim_status, var/probability, var/worthy) + var/victim_dead + if(victim_status == DEAD) + victim_dead = TRUE + + var/enough_cultists + if(length(cultists) >= 3) + enough_cultists = TRUE + + if(victim_dead && enough_cultists) // dead sacrifices are half as likely to satisfy nar'sie + probability *= 0.5 + + var/victim_sacrifice = TRUE // Checks whether we're gonna sacrifice the victim or not + for(var/mob/C in cultists) + if(!victim_dead && enough_cultists) + if(prob(probability) || worthy) + to_chat(C, span("cult", "The Geometer of Blood accepts this sacrifice.")) + else + to_chat(C, span("cult", "The Geometer of Blood accepts this sacrifice.")) + to_chat(C, span("warning", "However, this soul was not enough to gain His favor.")) + else if(!victim_dead && !enough_cultists) + to_chat(C, span("warning", "The victim is still alive, you will need more cultists chanting for the sacrifice to succeed.")) + victim_sacrifice = FALSE + + if(victim_sacrifice) + if(isrobot(victim)) + victim.dust() // To prevent the MMI from remaining + else + victim.gib() \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/see_invisible.dm b/code/game/gamemodes/cult/runes/see_invisible.dm new file mode 100644 index 00000000000..f11bc68bbc7 --- /dev/null +++ b/code/game/gamemodes/cult/runes/see_invisible.dm @@ -0,0 +1,17 @@ +/obj/effect/rune/see_invisible/do_rune_action(mob/living/user) + if(user.seer == TRUE) + user.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium viortia.") + to_chat(user, span("warning", "The world beyond fades from your vision.")) + user.see_invisible = SEE_INVISIBLE_LIVING + user.seer = FALSE + else if(user.see_invisible!=SEE_INVISIBLE_LIVING) + to_chat(user, span("warning", "The world beyond flashes your eyes but disappears quickly, as if something is disrupting your vision.")) + user.see_invisible = SEE_INVISIBLE_CULT + user.seer = FALSE + else + user.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium vivira. Itonis al'ra matum!") + to_chat(user, span("warning", "The world beyond opens to your eyes.")) + user.see_invisible = SEE_INVISIBLE_CULT + user.seer = TRUE + return + return fizzle(user) \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/stun.dm b/code/game/gamemodes/cult/runes/stun.dm new file mode 100644 index 00000000000..2b8b5168ba4 --- /dev/null +++ b/code/game/gamemodes/cult/runes/stun.dm @@ -0,0 +1,34 @@ +/obj/effect/rune/stun + can_talisman = TRUE + +/obj/effect/rune/stun/do_rune_action(mob/living/user, obj/O = src) + user.say("Fuu ma[pick("'","`")]jin!") + + var/radius = 5 + var/is_rune = TRUE + if(!istype(O, /obj/effect/rune)) + radius = 2 + is_rune = FALSE + + for(var/mob/living/L in range(radius, O)) + if(iscultist(L)) + continue + if(iscarbon(L)) + var/mob/living/carbon/C = L + flick("e_flash", C.flash) + if(C.stuttering < 1 && !HULK in C.mutations) + C.stuttering = 1 + if(is_rune) + C.Weaken(3) + C.Stun(3) + C.silent += 15 + to_chat(C, span("danger", "The rune explodes in a bright flash!")) + admin_attack_log(user, C, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on") + else if(issilicon(L)) + var/mob/living/silicon/S = L + S.Weaken(5) + flick("e_flash", S.flash) + S.silent += 15 + to_chat(S, span("danger", "BZZZT... The rune has exploded in a bright flash!")) + admin_attack_log(user, S, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on") + qdel(O) \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/summon_cultist.dm b/code/game/gamemodes/cult/runes/summon_cultist.dm new file mode 100644 index 00000000000..ea7f9908c50 --- /dev/null +++ b/code/game/gamemodes/cult/runes/summon_cultist.dm @@ -0,0 +1,39 @@ +/obj/effect/rune/summon_cultist/do_rune_action(mob/living/user) + var/list/mob/living/carbon/cultists = list() + for(var/datum/mind/H in cult.current_antagonists) + if(istype(H.current, /mob/living/carbon)) + cultists += H.current + + var/list/mob/living/carbon/users = list() + for(var/mob/living/carbon/C in orange(1, src)) + if(iscultist(C) && !C.stat) + users += C + + if(users.len >= 3) + var/mob/living/carbon/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - user) + if(!cultist) + return fizzle(user) + if(cultist == user) //just to be sure. + return + if(cultist.buckled || cultist.handcuffed || (!isturf(cultist.loc) && !istype(cultist.loc, /obj/structure/closet))) + for(var/mob/C in users) + to_chat(C, span("warning", "You cannot summon \the [cultist], for \his shackles of blood are strong.")) + return fizzle(user) + cultist.forceMove(get_turf(src)) + cultist.lying = TRUE + cultist.regenerate_icons() + + var/dam = round(25 / (users.len/2)) //More people around the rune less damage everyone takes. Minimum is 3 cultists + + for(var/mob/living/carbon/human/C in users) + if(iscultist(C) && !C.stat) + C.say("N'ath reth sh'yro eth d[pick("'","`")]rekkathnor!") + C.take_overall_damage(dam, 0) + if(users.len <= 4) // You did the minimum, this is going to hurt more and we're going to stun you. + C.apply_effect(rand(3,6), STUN) + C.apply_effect(1, WEAKEN) + user.visible_message("The rune disappears with a flash of red light, and in its place now a body lies.", \ + "You are blinded by a flash of red light! After you're able to see again, you see that now instead of the rune there's a body.", \ + "You hear a pop and smell ozone.") + qdel(src) + return fizzle(user) \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/summon_narsie.dm b/code/game/gamemodes/cult/runes/summon_narsie.dm new file mode 100644 index 00000000000..8bbe042318f --- /dev/null +++ b/code/game/gamemodes/cult/runes/summon_narsie.dm @@ -0,0 +1,30 @@ +/obj/effect/rune/summon_narsie/do_rune_action(mob/living/user) + if(!cult.allow_narsie) + return fizzle(user) + + var/turf/T = get_turf(src) + if(isNotStationLevel(T.z)) + to_chat(user, span("warning", "You are too far from the station, Nar'sie can not be summoned here.")) + return fizzle(user) + + var/list/cultists = list() + for(var/mob/M in range(1, src)) + if(istype(M, /mob/living/carbon/human/apparition)) + to_chat(M, span("warning", "Apparitions cannot partake in the summoning of the Great Dark One! Clear the area and defend the cultists!")) + continue + if(iscultist(M) && !M.stat) + M.say("Tok-lyr rqa'nap g[pick("'","`")]lt-ulotf!") + cultists += M + if(cultists.len >= 9) + log_and_message_admins_many(cultists, "summoned Nar-sie.") + new /obj/singularity/narsie/large(src.loc) + + // Can't summon a singular entity twice. + cult.allow_narsie = FALSE + return + else + for(var/mob/M in cultists) + if(!iscultist(M)) + continue + to_chat(M, span("warning", "Not enough cultists are around to summon the Great Dark One!")) + return fizzle(user) \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/summon_tome.dm b/code/game/gamemodes/cult/runes/summon_tome.dm new file mode 100644 index 00000000000..14763bd3326 --- /dev/null +++ b/code/game/gamemodes/cult/runes/summon_tome.dm @@ -0,0 +1,14 @@ +/obj/effect/rune/summon_tome + can_talisman = TRUE + +/obj/effect/rune/summon_tome/do_rune_action(mob/living/user, obj/O = src) + if(istype(O, /obj/effect/rune)) + user.say("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!") + else + user.whisper("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!") + user.visible_message("Rune disappears with a flash of red light, and in its place now a book lies.", \ + "You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a book.", \ + "You hear a pop and smell ozone.") + new /obj/item/book/tome(get_turf(O)) + qdel(O) + return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/teleport.dm b/code/game/gamemodes/cult/runes/teleport.dm new file mode 100644 index 00000000000..61730119847 --- /dev/null +++ b/code/game/gamemodes/cult/runes/teleport.dm @@ -0,0 +1,56 @@ +var/global/list/teleport_runes = list() +var/global/list/static/teleport_network = list("Vernuth", "Koglan", "Irgros", "Akon") + +/obj/effect/rune/teleport + can_talisman = TRUE + +/obj/effect/rune/teleport/Initialize() + . = ..() + addtimer(CALLBACK(src, .proc/random_network), 10) // if this rune somehow spawned without a network, we assign a random one + +/obj/effect/rune/teleport/examine(mob/user) + ..() + if(iscultist(user) && network) + to_chat(user, "This rune's network tag reads: [network].") + +/obj/effect/rune/teleport/proc/random_network() + if(!network) // check if it hasn't been assigned yet + network = pick(teleport_network) + +/obj/effect/rune/teleport/do_rune_action(mob/living/user) + var/turf/T = get_turf(user) + if(isNotStationLevel(T.z)) + to_chat(user, span("warning", "You are too far from the station, Nar'sie is unable to reach you here.")) + return fizzle(user) + + var/list/obj/effect/rune/teleport/possible_runes = list() + for(var/obj/effect/rune/R in teleport_runes) + if(R == src) + continue + if(R.network != src.network) + continue + possible_runes += R + + if(length(possible_runes)) + if(istype(src,/obj/effect/rune)) + user.say("Sas[pick("'","`")]so c'arta forbici!")//Only you can stop auto-muting + else + user.whisper("Sas[pick("'","`")]so c'arta forbici!") + user.visible_message("[user] disappears in a flash of red light!", \ + "You feel as your body gets dragged through the dimension of Nar-Sie!", \ + "You hear a sickening crunch and sloshing of viscera.") + user.forceMove(get_turf(pick(possible_runes))) + return TRUE + if(istype(src, /obj/effect/rune)) + return fizzle(user) //Use friggin manuals, Dorf, your list was of zero length. + else + call(/obj/effect/rune/proc/fizzle)(user) + return + +/obj/effect/rune/teleport/Initialize() + . = ..() + teleport_runes += src + +/obj/effect/rune/teleport/Destroy() + teleport_runes -= src + . = ..() \ No newline at end of file diff --git a/code/game/gamemodes/cult/runes/wall.dm b/code/game/gamemodes/cult/runes/wall.dm new file mode 100644 index 00000000000..20702dd62e1 --- /dev/null +++ b/code/game/gamemodes/cult/runes/wall.dm @@ -0,0 +1,9 @@ +/obj/effect/rune/wall/do_rune_action(mob/living/user) + user.say("Khari[pick("'","`")]d! Eske'te tannin!") + src.density = !src.density + user.take_organ_damage(2, 0) + if(src.density) + to_chat(user, span("cult", "Your blood flows into the rune, and you feel that the very space over the rune thickens.")) + else + to_chat(user, span("cult", "Your blood flows into the rune, and you feel as the rune releases its grasp on space.")) + return \ No newline at end of file diff --git a/code/game/gamemodes/cult/structures/altar.dm b/code/game/gamemodes/cult/structures/altar.dm new file mode 100644 index 00000000000..d65bb7c7b78 --- /dev/null +++ b/code/game/gamemodes/cult/structures/altar.dm @@ -0,0 +1,44 @@ +/obj/structure/cult/talisman + name = "daemon altar" + desc = "A bloodstained altar. Looking at it makes you feel slightly terrified." + description_antag = "If you are a cultist, you could click on this altar to pray to Nar'Sie, who will in turn heal some of your ailments." + icon_state = "talismanaltar" + var/last_use = 0 + +/obj/structure/cult/talisman/attack_hand(mob/user) + . = ..() + if(iscultist(user) && ishuman(user)) + if(last_use <= world.time) + last_use = world.time + 1200 // Cooldown of two minutes + var/mob/living/carbon/human/H = user + H.heal_overall_damage(20, 20) + to_chat(H, span("cult", "You begin your prayer to Nar'Sie, your wounds slowly closing up...")) + for(var/obj/item/organ/external/O in H.organs) + if(O.status & ORGAN_ARTERY_CUT) + to_chat(H, span("warning", "Severed artery found in [O.name], repairing...")) + if(do_after(user, 20)) + O.status &= ~ORGAN_ARTERY_CUT + if(O.status & ORGAN_TENDON_CUT) + to_chat(H, span("warning", "Severed tendon found in [O.name], repairing...")) + if(do_after(user, 20)) + O.status &= ~ORGAN_TENDON_CUT + if(O.status & ORGAN_BROKEN) + to_chat(H, span("warning", "Broken bone found in [O.name], repairing...")) + if(do_after(user, 20)) + O.status &= ~ORGAN_BROKEN + O.update_damages() + + var/virus_found + for(var/datum/disease/D in H.viruses) + virus_found = TRUE + D.cure() + for(var/ID in H.virus2) + var/datum/disease2/disease/V = H.virus2[ID] + virus_found = TRUE + V.cure(src) + if(virus_found) + to_chat(H, span("warning", "Virus found, curing...")) + else + to_chat(user, span("warning", "This altar isn't ready to be prayed at yet.")) + else + to_chat(user, span("warning", "The altar lightly zaps you.")) \ No newline at end of file diff --git a/code/game/gamemodes/cult/structures/desk.dm b/code/game/gamemodes/cult/structures/desk.dm new file mode 100644 index 00000000000..4edf3a8823d --- /dev/null +++ b/code/game/gamemodes/cult/structures/desk.dm @@ -0,0 +1,12 @@ +/obj/structure/cult/tome + name = "arcanaeum desk" + desc = "A desk covered in arcane manuscripts and tomes in unknown languages. Looking at the text makes your skin crawl." + description_antag = "A desk covered with the scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood. Most of them are beyond your current comprehension. If you are a cultist, you could click on this desk with any non-unique book to turn it into a tome." + icon_state = "tomealtar" + +/obj/structure/cult/tome/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/book) && iscultist(user)) + var/obj/item/book/B = W + if(!B.unique) + B.cultify() + to_chat(user, span("cult", "You pass the book over the desk. The contents within fade away and get replaced by the writings of Nar'Sie.")) \ No newline at end of file diff --git a/code/game/gamemodes/cult/structures/forge.dm b/code/game/gamemodes/cult/structures/forge.dm new file mode 100644 index 00000000000..aaae3bfe3c6 --- /dev/null +++ b/code/game/gamemodes/cult/structures/forge.dm @@ -0,0 +1,10 @@ +/obj/structure/cult/forge + name = "daemon forge" + desc = "A mysterious forge. The noxious heat emanating from it makes your skin crawl." + description_antag = "A forge used in crafting the unholy weapons used by the armies of Nar-Sie. This is a powerful forge. If you are a cultist, you can click on this with an item in-hand to cultify it. Some items may burn in the process, but some can be forged into better variants." + icon_state = "forge" + +/obj/structure/cult/forge/attackby(obj/item/W, mob/user) + if(iscultist(user)) + W.cultify() + to_chat(user, span("cult", "You put \the [W] into \the [src]. What remains, remains.")) \ No newline at end of file diff --git a/code/game/gamemodes/cult/structures/gateway.dm b/code/game/gamemodes/cult/structures/gateway.dm new file mode 100644 index 00000000000..d1142ab4494 --- /dev/null +++ b/code/game/gamemodes/cult/structures/gateway.dm @@ -0,0 +1,51 @@ +/obj/effect/gateway + name = "gateway" + desc = "You're pretty sure that abyss is staring back." + icon = 'icons/obj/cult.dmi' + icon_state = "hole" + density = TRUE + unacidable = TRUE + anchored = 1.0 + var/spawnable = null + +/obj/effect/gateway/CollidedWith(mob/M) + return + +/obj/effect/gateway/Crossed(AM as mob|obj) + return + +/obj/effect/gateway/active + light_range=5 + light_color="#ff0000" + spawnable=list( + /mob/living/simple_animal/hostile/scarybat, + /mob/living/simple_animal/hostile/creature, + /mob/living/simple_animal/hostile/faithless + ) + +/obj/effect/gateway/active/cult + light_range=5 + light_color="#ff0000" + spawnable=list( + /mob/living/simple_animal/hostile/scarybat/cult, + /mob/living/simple_animal/hostile/creature/cult, + /mob/living/simple_animal/hostile/faithless/cult + ) + appearance_flags = NO_CLIENT_COLOR + +/obj/effect/gateway/active/cult/cultify() + return + +/obj/effect/gateway/active/New() + addtimer(CALLBACK(src, .proc/do_spawn), rand(30, 60) SECONDS) + +/obj/effect/gateway/active/proc/do_spawn() + var/thing = pick(spawnable) + new thing(src.loc) + qdel(src) + +/obj/effect/gateway/attackby(var/obj/item/I, var/mob/user) + ..() + if(istype(I, /obj/item/nullrod)) + to_chat(user, "You touch \the [src] with \the [I], closing the path to the otherworld.") + qdel(src) \ No newline at end of file diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/structures/pylon.dm similarity index 81% rename from code/game/gamemodes/cult/cult_structures.dm rename to code/game/gamemodes/cult/structures/pylon.dm index 65a7f4db563..1cab8a5f518 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/structures/pylon.dm @@ -1,58 +1,7 @@ -/obj/structure/cult - density = 1 - anchored = 1 - icon = 'icons/obj/cult.dmi' - appearance_flags = NO_CLIENT_COLOR - -/obj/structure/cult/cultify() - return - -/obj/structure/cult/talisman - name = "altar" - desc = "A bloodstained altar dedicated to Nar-Sie" - icon_state = "talismanaltar" - - -/obj/structure/cult/forge - name = "daemon forge" - desc = "A forge used in crafting the unholy weapons used by the armies of Nar-Sie" - icon_state = "forge" - -/* - Cult pylons can be used as arcane defensive turrets. - - First of all they must be empowered with a sacrifice. Any small organic creature that can be picked up is valid - Hit the pylon with the creature - while still alive - to present it as a sacrifice, and then end its life to complete the process. - - Once empowered, pylons will fire rapid, weak magical beams at non cult mobs. - - As crystals, pylons are immune to energy weaponry. More than immune, they will absorb lasers and become - supercharged for some time, boosting their damage. Pylons can only be harmed by ballistics and physical weapons - Building reinforced windows around them is highly recommended. - - Pylons are fairly fragile and will quickly break under direct hits. - A damaged pylon will self repair, if it contains a soul. - - - Pylons are largely intended as a stalling, early warning, fire support and area denial system. They are unlikely to actually - kill anyone alone but they can keep pesky civilians away for long enough to learn runes and prepare rituals. - - If you can get ahold of a laser rifle to supercharge them, they can even give security some pause - - Recommended tools for combatting pylons: - Heavy melee (fireaxe, baseball bat, etc) - Sniper rifles - Exosuits - Explosives - Ablative armour - Smoke grenades - Close the damn firelocks so they can't see you -*/ - /obj/structure/cult/pylon name = "pylon" - desc = "A floating crystal that hums with an unearthly energy" - description_antag = "A pylon can be upgraded into a magical defensive turret that shoots anyone opposing the cult\ + desc = "A floating crystal that hums with an unearthly energy." + description_antag = "A pylon can be upgraded into a magical defensive turret that shoots anyone opposing the cult\
Upgrading a pylon requires a sacrifice. Bring it a small organic creature, like a monkey or rat. Use the creature on the pylon, or drag and drop to present it.\
Once the sacrifice is accepted, kill it to complete the process. This will gib its body and make a very visible mess. After this point the pylon is fixed to the floor and cant be moved\
The pylon will fire weak beams that are harmless to the cult. In addition it can be upgraded even more by shooting it with a laser, which will give it a limited number of extra-power shots." @@ -571,73 +520,4 @@ anchored = 0 else anchored = 0 - set_light(0) - - - -//============================================ -/obj/structure/cult/tome - name = "desk" - desc = "A desk covered in arcane manuscripts and tomes in unknown languages. Looking at the text makes your skin crawl" - icon_state = "tomealtar" - -/obj/effect/gateway - name = "gateway" - desc = "You're pretty sure that abyss is staring back" - icon = 'icons/obj/cult.dmi' - icon_state = "hole" - density = 1 - unacidable = 1 - anchored = 1.0 - var/spawnable = null - -/obj/effect/gateway/CollidedWith(mob/M) - return - -/obj/effect/gateway/Crossed(AM as mob|obj) - return - -/obj/effect/gateway/active - light_range=5 - light_color="#ff0000" - spawnable=list( - /mob/living/simple_animal/hostile/scarybat, - /mob/living/simple_animal/hostile/creature, - /mob/living/simple_animal/hostile/faithless - ) - -/obj/effect/gateway/active/cult - light_range=5 - light_color="#ff0000" - spawnable=list( - /mob/living/simple_animal/hostile/scarybat/cult, - /mob/living/simple_animal/hostile/creature/cult, - /mob/living/simple_animal/hostile/faithless/cult - ) - appearance_flags = NO_CLIENT_COLOR - -/obj/effect/gateway/active/cult/cultify() - return - -/obj/effect/gateway/active/New() - addtimer(CALLBACK(src, .proc/do_spawn), rand(30, 60) SECONDS) - -/obj/effect/gateway/active/proc/do_spawn() - var/thing = pick(spawnable) - new thing(src.loc) - qdel(src) - -/obj/effect/gateway/attackby(var/obj/item/I, var/mob/user) - ..() - if(istype(I, /obj/item/nullrod)) - to_chat(user, "You touch \the [src] with \the [I], closing the path to the otherworld.") - qdel(src) - -/obj/effect/testtrans - icon = 'icons/obj/cult.dmi' - icon_state = "tt" - -/obj/effect/testtrans/New() - ..() - spawn(10) - qdel(src) + set_light(0) \ No newline at end of file diff --git a/code/game/gamemodes/cult/structures/structure.dm b/code/game/gamemodes/cult/structures/structure.dm new file mode 100644 index 00000000000..1622a609b48 --- /dev/null +++ b/code/game/gamemodes/cult/structures/structure.dm @@ -0,0 +1,8 @@ +/obj/structure/cult + density = TRUE + anchored = TRUE + icon = 'icons/obj/cult.dmi' + appearance_flags = NO_CLIENT_COLOR + +/obj/structure/cult/cultify() + return \ No newline at end of file diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm deleted file mode 100644 index bcfc234fcaa..00000000000 --- a/code/game/gamemodes/cult/talisman.dm +++ /dev/null @@ -1,118 +0,0 @@ -/obj/item/paper/talisman - icon_state = "paper_talisman" - var/imbue = null - var/uses = 0 - info = "


" - -/obj/item/paper/talisman/attack_self(mob/living/user as mob) - if(iscultist(user)) - var/delete = 1 - // who the hell thought this was a good idea :( - switch(imbue) - if("newtome") - call(/obj/effect/rune/proc/tomesummon)(user) - if("armor") - call(/obj/effect/rune/proc/armor)(user) - if("emp") - call(/obj/effect/rune/proc/emp)(user, user.loc,3) - if("conceal") - call(/obj/effect/rune/proc/obscure)(user, 2) - if("revealrunes") - call(/obj/effect/rune/proc/revealrunes)(user, src) - if("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") - call(/obj/effect/rune/proc/teleport)(user, imbue) - if("communicate") - //If the user cancels the talisman this var will be set to 0 - delete = call(/obj/effect/rune/proc/communicate)(user) - if("deafen") - call(/obj/effect/rune/proc/deafen)(user) - if("blind") - call(/obj/effect/rune/proc/blind)(user) - if("runestun") - to_chat(user, "To use this talisman, attack your target directly.") - return - if("supply") - supply() - user.take_organ_damage(5, 0) - if(src && src.imbue!="supply" && src.imbue!="runestun") - if(delete) - qdel(src) - return - else - to_chat(user, "You see strange symbols on the paper. Are they supposed to mean something?") - return - - -/obj/item/paper/talisman/attack(mob/living/carbon/T as mob, mob/living/user as mob) - if(iscultist(user)) - if(imbue == "runestun") - user.take_organ_damage(5, 0) - call(/obj/effect/rune/proc/runestun)(user, T) - qdel(src) - else - ..() ///If its some other talisman, use the generic attack code, is this supposed to work this way? - else - ..() - - -/obj/item/paper/talisman/proc/supply(var/key) - if (!src.uses) - qdel(src) - return - - var/dat = "There are [src.uses] bloody runes on the parchment.
" - dat += "Please choose the chant to be imbued into the fabric of reality.
" - dat += "
" - dat += "N'ath reth sh'yro eth d'raggathnor! - Allows you to summon a new arcane tome.
" - dat += "Sas'so c'arta forbici! - Allows you to move to a rune with the same last word.
" - dat += "Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range.
" - dat += "Kla'atu barada nikt'o! - Allows you to conceal the runes you placed on the floor.
" - dat += "O bidai nabora se'sma! - Allows you to coordinate with others of your cult.
" - dat += "Fuu ma'jin - Allows you to silence and flash a person by attacking them with the talisman.
" - dat += "Sa tatha najin - Allows you to summon armoured robes and an unholy blade
" - dat += "Kal om neth - Summons a soul stone
" - dat += "Da A'ig Osk - Summons a construct shell for use with captured souls. It is too large to carry on your person.
" - usr << browse(dat, "window=id_com;size=350x200") - return - - -/obj/item/paper/talisman/Topic(href, href_list) - if(!src) return - if (usr.stat || usr.restrained() || !in_range(src, usr)) return - - if (href_list["rune"]) - switch(href_list["rune"]) - if("newtome") - var/obj/item/paper/talisman/T = new /obj/item/paper/talisman(get_turf(usr)) - T.imbue = "newtome" - if("teleport") - var/obj/item/paper/talisman/T = new /obj/item/paper/talisman(get_turf(usr)) - T.imbue = "[pick("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri", "orkan", "allaq")]" - T.info = "[T.imbue]" - if("emp") - var/obj/item/paper/talisman/T = new /obj/item/paper/talisman(get_turf(usr)) - T.imbue = "emp" - if("conceal") - var/obj/item/paper/talisman/T = new /obj/item/paper/talisman(get_turf(usr)) - T.imbue = "conceal" - if("communicate") - var/obj/item/paper/talisman/T = new /obj/item/paper/talisman(get_turf(usr)) - T.imbue = "communicate" - if("runestun") - var/obj/item/paper/talisman/T = new /obj/item/paper/talisman(get_turf(usr)) - T.imbue = "runestun" - if("armor") - var/obj/item/paper/talisman/T = new /obj/item/paper/talisman(get_turf(usr)) - T.imbue = "armor" - if("soulstone") - new /obj/item/device/soulstone(get_turf(usr)) - if("construct") - new /obj/structure/constructshell/cult(get_turf(usr)) - src.uses-- - supply() - return - - -/obj/item/paper/talisman/supply - imbue = "supply" - uses = 5 diff --git a/code/game/magic/Uristrunes.dm b/code/game/magic/Uristrunes.dm deleted file mode 100644 index 79238be00f5..00000000000 --- a/code/game/magic/Uristrunes.dm +++ /dev/null @@ -1,128 +0,0 @@ - -var/list/word_to_uristrune_table = null - -/proc/word_to_uristrune_bit(word) - if(word_to_uristrune_table == null) - word_to_uristrune_table = list() - - var/bit = 1 - var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "mgar", "balaq", "karazet", "geeri") - - while(length(words)) - var/w = pick(words) - - word_to_uristrune_table[w] = bit - - words -= w - bit <<= 1 - - return word_to_uristrune_table[word] - - - -/proc/get_uristrune_cult(word1, word2, word3) - var/animated - - if((word1 == cultwords["travel"] && word2 == cultwords["self"]) \ - || (word1 == cultwords["join"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) \ - || (word1 == cultwords["hell"] && word2 == cultwords["join"] && word3 == cultwords["self"]) \ - || (word1 == cultwords["see"] && word2 == cultwords["blood"] && word3 == cultwords["hell"]) \ - || (word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["technology"]) \ - || (word1 == cultwords["travel"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) \ - || (word1 == cultwords["see"] && word2 == cultwords["hell"] && word3 == cultwords["join"]) \ - || (word1 == cultwords["blood"] && word2 == cultwords["join"] && word3 == cultwords["hell"]) \ - || (word1 == cultwords["hide"] && word2 == cultwords["see"] && word3 == cultwords["blood"]) \ - || (word1 == cultwords["hell"] && word2 == cultwords["travel"] && word3 == cultwords["self"]) \ - || (word1 == cultwords["blood"] && word2 == cultwords["see"] && word3 == cultwords["travel"]) \ - || (word1 == cultwords["hell"] && word2 == cultwords["technology"] && word3 == cultwords["join"]) \ - || (word1 == cultwords["hell"] && word2 == cultwords["blood"] && word3 == cultwords["join"]) \ - || (word1 == cultwords["blood"] && word2 == cultwords["see"] && word3 == cultwords["hide"]) \ - || (word1 == cultwords["destroy"] && word2 == cultwords["travel"] && word3 == cultwords["self"]) \ - || (word1 == cultwords["travel"] && word2 == cultwords["technology"] && word3 == cultwords["other"]) \ - || (word1 == cultwords["join"] && word2 == cultwords["other"] && word3 == cultwords["self"]) \ - || (word1 == cultwords["hide"] && word2 == cultwords["other"] && word3 == cultwords["see"]) \ - || (word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["other"]) \ - || (word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["blood"]) \ - || (word1 == cultwords["self"] && word2 == cultwords["other"] && word3 == cultwords["technology"]) \ - || (word1 == cultwords["travel"] && word2 == cultwords["other"]) \ - || (word1 == cultwords["join"] && word2 == cultwords["hide"] && word3 == cultwords["technology"]) ) - animated = 1 - else - animated = 0 - - var/bits = word_to_uristrune_bit(word1) \ - | word_to_uristrune_bit(word2) \ - | word_to_uristrune_bit(word3) - - return get_uristrune(bits, animated) - -/proc/get_uristrune(symbol_bits, animated = 0) - var/lookup = "[symbol_bits]-[animated]" - - var/icon/result = SSicon_cache.uristrunes[lookup] - if (result) - return result - - var/icon/I = icon('icons/effects/uristrunes.dmi', "blank") - - for(var/i = 0, i < 10, i++) - if(BITTEST(symbol_bits, i)) - I.Blend(icon('icons/effects/uristrunes.dmi', "rune-[1 << i]"), ICON_OVERLAY) - - I.SwapColor(rgb(0, 0, 0, 100), rgb(100, 0, 0, 200)) - 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) - - 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) - - SSicon_cache.uristrunes[lookup] = result - - return result diff --git a/code/game/objects/items/weapons/chaplain_items.dm b/code/game/objects/items/weapons/chaplain_items.dm index 9e6b13ed4ab..cc3d66cce1f 100644 --- a/code/game/objects/items/weapons/chaplain_items.dm +++ b/code/game/objects/items/weapons/chaplain_items.dm @@ -125,11 +125,12 @@ /obj/item/nullrod/afterattack(atom/A, mob/user as mob, proximity) if(!proximity) return - if (istype(A, /turf/simulated/floor) && (cooldown + 5 SECONDS < world.time)) + if(istype(A, /turf/simulated/floor) && (cooldown + 5 SECONDS < world.time)) cooldown = world.time user.visible_message(span("notice", "[user] loudly taps their [src.name] against the floor.")) playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) - call(/obj/effect/rune/proc/revealrunes)(src) + var/datum/callback/cb = CALLBACK(src, /obj/effect/rune/revealrunes/.proc/do_rune_action) + cb.Invoke(user, src) return /obj/item/reagent_containers/spray/aspergillum diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index ee7dc8efc6d..d775e2b7b13 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -322,7 +322,7 @@ var/const/enterloopsanity = 100 if(istype(O,/obj/effect/rune)) var/obj/effect/rune/R = O // Only show message for visible runes - if (R.visibility) + if(R.visible) to_chat(user, span("warning", "No matter how well you wash, the bloody symbols remain!")) else if( !(last_clean && world.time < last_clean + 100) ) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 53e3828ff26..9d639b815a4 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -43,7 +43,6 @@ var/list/admin_verbs_admin = list( /client/proc/cmd_admin_direct_narrate, //send text directly to a player with no padding. Useful for narratives and fluff-text, /client/proc/cmd_admin_world_narrate, //sends text to all players with no padding, /client/proc/cmd_admin_create_centcom_report, - /client/proc/check_words, //displays cult-words, /client/proc/check_ai_laws, //shows AI and borg laws, /client/proc/rename_silicon, //properly renames silicons, /client/proc/manage_silicon_laws, // Allows viewing and editing silicon laws. , @@ -264,7 +263,6 @@ var/list/admin_verbs_hideable = list( /client/proc/admin_cancel_shuttle, /client/proc/cmd_admin_direct_narrate, /client/proc/cmd_admin_world_narrate, - /client/proc/check_words, /client/proc/play_local_sound, /client/proc/play_sound, /client/proc/play_server_sound, @@ -335,7 +333,6 @@ var/list/admin_verbs_mod = list( /datum/admins/proc/paralyze_mob, /client/proc/toggleattacklogs, /client/proc/cmd_admin_check_contents, - /client/proc/check_words, /*displays cult-words*/ /client/proc/check_ai_laws, /*shows AI and borg laws*/ /client/proc/aooc, /client/proc/print_logout_report diff --git a/code/modules/mob/abstract/observer/observer.dm b/code/modules/mob/abstract/observer/observer.dm index 9bef02870c2..204ecba4651 100644 --- a/code/modules/mob/abstract/observer/observer.dm +++ b/code/modules/mob/abstract/observer/observer.dm @@ -281,12 +281,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return if(mind.current.ajourn && mind.current.stat != DEAD) //check if the corpse is astral-journeying (it's client ghosted using a cultist rune). var/found_rune - for(var/obj/effect/rune/R in mind.current.loc) //whilst corpse is alive, we can only reenter the body if it's on the rune - if(R && R.word1 == cultwords["hell"] && R.word2 == cultwords["travel"] && R.word3 == cultwords["self"]) // Found an astral journey rune. - found_rune = 1 - break + for(var/obj/effect/rune/ethereal/R in get_turf(mind.current)) //whilst corpse is alive, we can only reenter the body if it's on the rune + found_rune = TRUE + break if(!found_rune) - to_chat(usr, "The astral cord that ties your body and your spirit has been severed. You are likely to wander the realm beyond until your body is finally dead and thus reunited with you.") + to_chat(usr, span("cult", "The astral cord that ties your body and your spirit has been severed. You are likely to wander the realm beyond until your body is finally dead and thus reunited with you.")) return stop_following() mind.current.ajourn=0 diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 3b416cb5582..6dc6f21988c 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -458,10 +458,8 @@ if(!H.druggy) H.see_in_dark = (H.sight == (SEE_TURFS|SEE_MOBS|SEE_OBJS)) ? 8 : min(darksight + H.equipment_darkness_modifier, 8) - if(H.seer) - var/obj/effect/rune/R = locate() in H.loc - if(R && R.word1 == cultwords["see"] && R.word2 == cultwords["hell"] && R.word3 == cultwords["join"]) - H.see_invisible = SEE_INVISIBLE_CULT + if(H.seer && locate(/obj/effect/rune/see_invisible) in get_turf(H)) + H.see_invisible = SEE_INVISIBLE_CULT if(H.see_invisible != SEE_INVISIBLE_CULT && H.equipment_see_invis) H.see_invisible = min(H.see_invisible, H.equipment_see_invis) diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm index 39cbe718b58..4304b1db552 100644 --- a/code/modules/mob/living/silicon/ai/login.dm +++ b/code/modules/mob/living/silicon/ai/login.dm @@ -1,7 +1,5 @@ /mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up ¬_¬ ~Carn ..() - for(var/obj/effect/rune/rune in rune_list) - client.images += rune.blood_image regenerate_icons() flash = new /obj/screen() flash.icon_state = "blank" diff --git a/code/modules/spells/general/rune_write.dm b/code/modules/spells/general/rune_write.dm index f85cdc70357..5d40b8708ba 100644 --- a/code/modules/spells/general/rune_write.dm +++ b/code/modules/spells/general/rune_write.dm @@ -17,182 +17,43 @@ return list(user) /spell/rune_write/cast(null, mob/user = usr) - if(!cultwords["travel"]) - runerandom() - var/list/runes = list("Teleport", "Teleport Other", "Spawn a Tome", "Change Construct Type", "Convert", "EMP", "Drain Blood", "See Invisible", "Resurrect", "Hide Runes", "Reveal Runes", "Astral Journey", "Manifest a Ghost", "Imbue Talisman", "Sacrifice", "Wall", "Free Cultist", "Summon Cultist", "Deafen", "Blind", "BloodBoil", "Communicate", "Stun") - var/r = input(user, "Choose a rune to scribe", "Rune Scribing") in runes //not cancellable. - if(locate(/obj/effect/rune) in user.loc) - to_chat(user, "There is already a rune in this location.") + if(!isturf(user.loc)) + to_chat(user, span("warning", "You do not have enough space to write a proper rune.")) + + var/rune = input(user, "Choose a rune to scribe", "Rune Scribing") in rune_types //not cancellable. + if(locate(/obj/effect/rune) in get_turf(user)) + to_chat(user, span("warning", "There is already a rune in this location.")) return - var/obj/effect/rune/R = new /obj/effect/rune(user.loc) - if(istype(user.loc,/turf)) - var/area/A = get_area(user) - log_and_message_admins("created \an [r] rune at \the [A.name] - [user.loc.x]-[user.loc.y]-[user.loc.z].", user) - switch(r) - if("Teleport") - if(cast_check(1)) - var/beacon - if(user) - beacon = input(user, "Select the last rune", "Rune Scribing") in rnwords - R.word1=cultwords["travel"] - R.word2=cultwords["self"] - R.word3=beacon - R.check_icon() - if("Teleport Other") - if(cast_check(1)) - var/beacon - if(user) - beacon = input(user, "Select the last rune", "Rune Scribing") in rnwords - R.word1=cultwords["travel"] - R.word2=cultwords["other"] - R.word3=beacon - R.check_icon() - if("Spawn a Tome") - if(cast_check(1)) - R.word1=cultwords["see"] - R.word2=cultwords["blood"] - R.word3=cultwords["hell"] - R.check_icon() - if("Change Construct Type") - if(cast_check(1)) - R.word1=cultwords["hell"] - R.word2=cultwords["destroy"] - R.word3=cultwords["other"] - R.check_icon() - if("Convert") - if(cast_check(1)) - R.word1=cultwords["join"] - R.word2=cultwords["blood"] - R.word3=cultwords["self"] - R.check_icon() - if("EMP") - if(cast_check(1)) - R.word1=cultwords["destroy"] - R.word2=cultwords["see"] - R.word3=cultwords["technology"] - R.check_icon() - if("Drain Blood") - if(cast_check(1)) - R.word1=cultwords["travel"] - R.word2=cultwords["blood"] - R.word3=cultwords["self"] - R.check_icon() - if("See Invisible") - if(cast_check(1)) - R.word1=cultwords["see"] - R.word2=cultwords["hell"] - R.word3=cultwords["join"] - R.check_icon() - if("Resurrect") - if(cast_check(1)) - R.word1=cultwords["blood"] - R.word2=cultwords["join"] - R.word3=cultwords["hell"] - R.check_icon() - if("Hide Runes") - if(cast_check(1)) - R.word1=cultwords["hide"] - R.word2=cultwords["see"] - R.word3=cultwords["blood"] - R.check_icon() - if("Astral Journey") - if(cast_check(1)) - R.word1=cultwords["hell"] - R.word2=cultwords["travel"] - R.word3=cultwords["self"] - R.check_icon() - if("Manifest a Ghost") - if(cast_check(1)) - R.word1=cultwords["blood"] - R.word2=cultwords["see"] - R.word3=cultwords["travel"] - R.check_icon() - if("Imbue Talisman") - if(cast_check(1)) - R.word1=cultwords["hell"] - R.word2=cultwords["technology"] - R.word3=cultwords["join"] - R.check_icon() - if("Sacrifice") - if(cast_check(1)) - R.word1=cultwords["hell"] - R.word2=cultwords["blood"] - R.word3=cultwords["join"] - R.check_icon() - if("Reveal Runes") - if(cast_check(1)) - R.word1=cultwords["blood"] - R.word2=cultwords["see"] - R.word3=cultwords["hide"] - R.check_icon() - if("Wall") - if(cast_check(1)) - R.word1=cultwords["destroy"] - R.word2=cultwords["travel"] - R.word3=cultwords["self"] - R.check_icon() - if("Freedom") - if(cast_check(1)) - R.word1=cultwords["travel"] - R.word2=cultwords["technology"] - R.word3=cultwords["other"] - R.check_icon() - if("Cultsummon") - if(cast_check(1)) - R.word1=cultwords["join"] - R.word2=cultwords["other"] - R.word3=cultwords["self"] - R.check_icon() - if("Deafen") - if(cast_check(1)) - R.word1=cultwords["hide"] - R.word2=cultwords["other"] - R.word3=cultwords["see"] - R.check_icon() - if("Blind") - if(cast_check(1)) - R.word1=cultwords["destroy"] - R.word2=cultwords["see"] - R.word3=cultwords["other"] - R.check_icon() - if("BloodBoil") - if(cast_check(1)) - R.word1=cultwords["destroy"] - R.word2=cultwords["see"] - R.word3=cultwords["blood"] - R.check_icon() - if("Communicate") - if(cast_check(1)) - R.word1=cultwords["self"] - R.word2=cultwords["other"] - R.word3=cultwords["technology"] - R.check_icon() - if("Stun") - if(cast_check(1)) - R.word1=cultwords["join"] - R.word2=cultwords["hide"] - R.word3=cultwords["technology"] - R.check_icon() - for(var/obj/O in range(1,user)) - O.cultify() - for(var/turf/T in range(1,user)) - var/atom/movable/overlay/animation = new /atom/movable/overlay(T) - animation.name = "conjure" - animation.density = 0 - animation.anchored = 1 - animation.icon = 'icons/effects/effects.dmi' - animation.layer = 3 - animation.master = T - if(istype(T,/turf/simulated/wall)) - animation.icon_state = "cultwall" - flick("cultwall",animation) - else - animation.icon_state = "cultfloor" - flick("cultfloor",animation) - spawn(10) - qdel(animation) - T.cultify() - else - to_chat(user, "You do not have enough space to write a proper rune.") - return + var/rune_path = rune_types[rune] + var/obj/effect/rune/R = new rune_path(get_turf(user)) + + var/network + if(istype(R, /obj/effect/rune/teleport)) + network = input(user, "Choose a teleportation network for the rune to connect to.", "Teleport Rune") in teleport_network + if(network) + R.network = network + R.cult_description = rune + R.color = "#A10808" + + var/area/A = get_area(R) + log_and_message_admins("created \an [rune] rune at \the [A.name] - [user.loc.x]-[user.loc.y]-[user.loc.z].", user) + + for(var/obj/O in range(1,user)) + O.cultify() + for(var/turf/T in range(1,user)) + var/atom/movable/overlay/animation = new /atom/movable/overlay(T) + animation.name = "conjure" + animation.density = 0 + animation.anchored = 1 + animation.icon = 'icons/effects/effects.dmi' + animation.layer = 3 + animation.master = T + if(istype(T,/turf/simulated/wall)) + animation.icon_state = "cultwall" + flick("cultwall", animation) + else + animation.icon_state = "cultfloor" + flick("cultfloor", animation) + QDEL_IN(animation, 10) + T.cultify() diff --git a/html/changelogs/geeves-cultstuff.yml b/html/changelogs/geeves-cultstuff.yml new file mode 100644 index 00000000000..456f8e662c4 --- /dev/null +++ b/html/changelogs/geeves-cultstuff.yml @@ -0,0 +1,24 @@ +author: Geeves + +delete-after: True + +changes: + - bugfix: "Fixed some cult item descriptions not having a full stop" + - rscdel: "The final remnants of the cultwords code has been ripped out." + - tweak: "Cult blades and tomes now fit on the belt slot." + - tweak: "Talismans now display what their copied runes are when examined." + - tweak: "The tome has been simplified and shortened. Should be easier for new people to use now." + - rscdel: "Blood boil can no longer randomly gib people." + - tweak: "The freedom rune now handles cultist saving a bit better. Should be more useful now. Alerts the rescued cultist that their cult is doing things to help." + - tweak: "You no longer have to stay on the rune to keep your manifested ghost alive, but you'll still take continual damage until it's dispelled." + - tweak: "Raising the dead no longer needs you to kill someone on a rune, but it will cause them to lose some limbs." + - tweak: "The stun talisman now affects non-cultists in a two tile radius around you." + - tweak: "Teleport runes now have four distinct teleport networks you can choose from. They will connect and beam to eachother." + - tweak: "Teleport runes now display which network they're connected to when examined." + - tweak: "Trying to summon a ghostly apparition now announces the effort to deadchat and gives them a follow link to jump to it." + - rscadd: "The freedom rune can now open bolted airlocks." + - tweak: "Cultist clothes now get turned into eldritch voidsuits when cultified. Find out how to do so." + - tweak: "The daemon forge can now be used to cultify objects." + - rscadd: "IPCs can now scribe runes, and do more rune based stuff in general." + - rscadd: "Runes now take the colour of the blood of the person who drew them. Remember to be stealthy." + - rscadd: "Cult structures (altars, forges and desks) have now been given some use. Examine them as an antag to find out their secrets." \ No newline at end of file diff --git a/icons/obj/cult.dmi b/icons/obj/cult.dmi index eb632925865a94e14af248fe8ff105961b8106c0..7cc87661a641182af2e086c28979c6301504bec3 100644 GIT binary patch delta 228 zcmVIFI8N2y1QbrE#Unpv=#s()Yvf7b(eAoLren{-Me{Fy4qy e4zs=f1-gdqzJX@f>JQpWw@+9OiG;Hk0kx37#%;L( delta 230 zcmVX9WNf7OgS8N2y1QbrE#Ul>}gCI%-ivf7b_UA*lu zbP~Mxy@#}g=lx52gyzud8*vV41P6}~JFVV>mmVC{l~z54u9wdx3krdQ&1H&d+-T(k zXK-M(Ix`NG!GW!`@)U6b2bEc!nR8Cu(K@G|G1gdPXOmzIdB72)AQwt3Q`BjoAC%>o zKE*<{r#p|ibDpkIy1<@(Z+Dqu8s9J%l9o`OvS54-zEo>@`P!_`cbr_AN&exLU%+%D gKJ{4q>tCQ-*dH5c4z2zG&#JdcL4%oyvlRigkXRdS`Tzg` diff --git a/icons/obj/rune.dmi b/icons/obj/rune.dmi index deb6869347ba4f37d2391a5f6961bf7f92d7ca4a..d7b1a5d90135ed1c3d9f1a0b5b80f2875a74dc5d 100644 GIT binary patch literal 8764 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 literal 4141 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