From dff70625e7c29616887619dacc0375ddc84f0708 Mon Sep 17 00:00:00 2001 From: ChungusGamer666 <82850673+ChungusGamer666@users.noreply.github.com> Date: Mon, 15 May 2023 01:27:43 -0300 Subject: [PATCH] Bible refactor (#75350) ## About The Pull Request This started as a simple addition where burning a bible would curse you, but then I realized... Bibles aren't even proper books, thus can't be burned! So yeah, since that is not necessary due to how atom_storage works, I reworked that. ## Why It's Good For The Game Because burning bibles and getting cursed for it is funny. ![image](https://github.com/tgstation/tgstation/assets/82850673/2a8489ce-ecd6-45ee-9eb9-168ff820af65) ![image](https://github.com/tgstation/tgstation/assets/82850673/ebe98ad6-2d0d-4d20-9ea1-5d472d6ca465) ## Changelog :cl: add: You can burn bibles now! But heresy has a steep cost... /:cl: --------- Co-authored-by: san7890 --- ...cemoon_underground_abandoned_homestead.dmm | 2 +- _maps/RandomRuins/SpaceRuins/clericden.dmm | 2 +- .../SpaceRuins/dangerous_research.dmm | 2 +- .../SpaceRuins/russian_derelict.dmm | 2 +- _maps/map_files/Birdshot/birdshot.dmm | 6 +- .../map_files/Deltastation/DeltaStation2.dmm | 4 +- .../map_files/IceBoxStation/IceBoxStation.dmm | 12 +- _maps/map_files/MetaStation/MetaStation.dmm | 6 +- _maps/map_files/NorthStar/north_star.dmm | 4 +- .../dormmedupper_attachment_a_3.dmm | 6 +- _maps/map_files/tramstation/tramstation.dmm | 6 +- _maps/shuttles/emergency_cruise.dmm | 2 +- _maps/shuttles/emergency_monastery.dmm | 10 +- _maps/templates/holodeck_chapelcourt.dmm | 4 +- _maps/templates/lazy_templates/ninja_den.dmm | 2 +- code/__DEFINES/achievements.dm | 1 + code/__DEFINES/dcs/signals/signals_object.dm | 2 +- code/__DEFINES/is_helpers.dm | 2 +- code/datums/achievements/misc_achievements.dm | 6 + code/datums/components/crafting/tailoring.dm | 2 +- code/datums/components/omen.dm | 59 ++- code/datums/components/religious_tool.dm | 2 +- code/datums/memory/general_memories.dm | 46 +++ code/datums/quirks/positive_quirks.dm | 2 +- code/game/objects/items/granters/_granters.dm | 2 +- code/game/objects/items/storage/bags.dm | 6 +- code/game/objects/items/storage/book.dm | 293 --------------- code/modules/admin/smites/bad_luck.dm | 5 +- .../heretic/knowledge/general_side.dm | 2 +- .../antagonists/revenant/haunted_item.dm | 2 +- code/modules/asset_cache/assets/bibles.dm | 2 +- .../mission_code/stationCollision.dm | 20 +- code/modules/cargo/packs/general.dm | 2 +- code/modules/clothing/suits/bio.dm | 2 +- code/modules/clothing/suits/costume.dm | 4 +- .../jobs/job_types/chaplain/chaplain.dm | 58 ++- .../job_types/chaplain/chaplain_costumes.dm | 10 +- code/modules/library/bibles.dm | 353 ++++++++++++++++++ code/modules/library/book.dm | 170 +++------ code/modules/library/book_info.dm | 74 ++++ code/modules/library/lib_machines.dm | 2 +- .../lavalandruin_code/elephantgraveyard.dm | 2 +- code/modules/mob/living/carbon/death.dm | 8 +- code/modules/paperwork/paper.dm | 3 + .../uplink/uplink_items/device_tools.dm | 2 +- icons/ui_icons/achievements/achievements.dmi | Bin 213960 -> 217471 bytes tgstation.dme | 3 +- .../Scripts/75350_book_storage_repath.txt | 1 + 48 files changed, 692 insertions(+), 526 deletions(-) delete mode 100644 code/game/objects/items/storage/book.dm create mode 100644 code/modules/library/bibles.dm create mode 100644 code/modules/library/book_info.dm create mode 100644 tools/UpdatePaths/Scripts/75350_book_storage_repath.txt diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_homestead.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_homestead.dmm index f8fd8f41c92ab8..86db7b55fe7ad5 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_homestead.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_homestead.dmm @@ -185,7 +185,7 @@ pixel_x = -3; pixel_y = 3 }, -/obj/item/storage/book/bible{ +/obj/item/book/bible{ pixel_y = 5 }, /obj/item/flashlight/flare/candle{ diff --git a/_maps/RandomRuins/SpaceRuins/clericden.dmm b/_maps/RandomRuins/SpaceRuins/clericden.dmm index 0bf5a3a0579839..ed9b63c7947a2a 100644 --- a/_maps/RandomRuins/SpaceRuins/clericden.dmm +++ b/_maps/RandomRuins/SpaceRuins/clericden.dmm @@ -180,7 +180,7 @@ /turf/open/floor/plating/airless, /area/ruin/space) "Q" = ( -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/effect/decal/cleanable/blood, /turf/open/misc/asteroid/airless, /area/ruin/space) diff --git a/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm b/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm index 1900de44f146f5..b5ff8df5e2967c 100644 --- a/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm +++ b/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm @@ -9,7 +9,7 @@ "ae" = ( /obj/structure/table, /obj/machinery/light/small/directional/west, -/obj/item/storage/book/bible{ +/obj/item/book/bible{ pixel_x = 3 }, /obj/item/book/manual/wiki/cytology{ diff --git a/_maps/RandomRuins/SpaceRuins/russian_derelict.dmm b/_maps/RandomRuins/SpaceRuins/russian_derelict.dmm index f94a92e06b0322..a80bb186c12c95 100644 --- a/_maps/RandomRuins/SpaceRuins/russian_derelict.dmm +++ b/_maps/RandomRuins/SpaceRuins/russian_derelict.dmm @@ -1011,7 +1011,7 @@ /area/ruin/space/ks13/hallway/aft) "oC" = ( /obj/structure/table/wood, -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/directional/east, /obj/structure/cable, diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index c522d0e265e62b..1bfccc919229c8 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -9562,7 +9562,7 @@ /area/station/engineering/atmos) "dSQ" = ( /obj/structure/table/wood, -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/machinery/light/small/directional/east, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/dark/smooth_edge{ @@ -15505,7 +15505,7 @@ /area/station/ai_monitored/turret_protected/aisat/maint) "fZC" = ( /obj/structure/table/wood, -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/dark/smooth_edge, /area/station/maintenance/starboard/greater) @@ -64949,7 +64949,7 @@ /area/station/cargo/office) "wzx" = ( /obj/structure/altar_of_gods, -/obj/item/storage/book/bible, +/obj/item/book/bible, /turf/open/floor/carpet/lone, /area/station/service/chapel/office) "wzK" = ( diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index c850f6f24f5594..8858a325985ecb 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -11355,7 +11355,7 @@ /area/station/maintenance/port/fore) "cKr" = ( /obj/structure/table/wood/fancy, -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/chapel/funeral) @@ -84913,7 +84913,7 @@ /turf/open/floor/iron, /area/station/engineering/atmos/mix) "vkr" = ( -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/structure/altar_of_gods, /turf/open/floor/iron/grimy, /area/station/service/chapel) diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 7b8bbeafbb3ee5..2c12463158a22f 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -7798,7 +7798,7 @@ "cvv" = ( /obj/structure/table/wood, /obj/machinery/airalarm/directional/north, -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/chapel) @@ -19362,7 +19362,7 @@ /turf/open/floor/eighties/red, /area/station/security/prison/safe) "gcP" = ( -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -30671,7 +30671,7 @@ pixel_x = -7; pixel_y = 3 }, -/obj/item/storage/book{ +/obj/item/book{ name = "Tales from the First"; pixel_x = 5; pixel_y = 5 @@ -47616,7 +47616,7 @@ /area/station/security/prison) "peA" = ( /obj/structure/table/wood, -/obj/item/storage/book/bible, +/obj/item/book/bible, /turf/open/floor/iron/dark, /area/station/service/chapel/office) "peV" = ( @@ -54534,7 +54534,7 @@ /area/station/cargo/lobby) "rqR" = ( /obj/structure/table/glass, -/obj/item/storage/book/bible, +/obj/item/book/bible, /turf/open/floor/iron/chapel, /area/station/service/chapel) "rqT" = ( @@ -75984,7 +75984,7 @@ "ygp" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/structure/altar_of_gods, /turf/open/floor/iron/dark, /area/station/service/chapel) diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 67630a5fe5f326..e2d5cdf04d34f4 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -3729,7 +3729,7 @@ desc = "A memorial wall for pinning mementos upon."; name = "memorial board" }, -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/structure/table/wood, /turf/open/floor/carpet, /area/station/service/chapel/funeral) @@ -42991,7 +42991,7 @@ /turf/open/floor/circuit/telecomms/mainframe, /area/station/tcommsat/server) "pwq" = ( -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/structure/altar_of_gods, /turf/open/floor/iron/dark, /area/station/service/chapel) @@ -51281,7 +51281,7 @@ /turf/open/floor/iron, /area/station/security/execution/transfer) "ssi" = ( -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/machinery/light/small/directional/north, /obj/machinery/newscaster/directional/north, /obj/machinery/camera/directional/north{ diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index 074559112abe78..bad1e16ef64133 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -33588,7 +33588,7 @@ "iUE" = ( /obj/structure/altar_of_gods, /obj/effect/turf_decal/siding/white, -/obj/item/storage/book/bible, +/obj/item/book/bible, /turf/open/floor/mineral/silver, /area/station/service/chapel) "iUP" = ( @@ -65637,7 +65637,7 @@ /area/station/service/library) "rdu" = ( /obj/structure/table/bronze, -/obj/item/storage/book/bible, +/obj/item/book/bible, /turf/open/floor/iron, /area/station/service/chapel) "rdx" = ( diff --git a/_maps/map_files/tramstation/maintenance_modules/dormmedupper_attachment_a_3.dmm b/_maps/map_files/tramstation/maintenance_modules/dormmedupper_attachment_a_3.dmm index 0c6ee1868b3f63..e05c8702d05f43 100644 --- a/_maps/map_files/tramstation/maintenance_modules/dormmedupper_attachment_a_3.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/dormmedupper_attachment_a_3.dmm @@ -6,12 +6,12 @@ "h" = ( /obj/structure/rack, /obj/structure/window/spawner/directional/east, -/obj/item/storage/book/bible{ +/obj/item/book/bible{ pixel_x = -4; pixel_y = -4 }, -/obj/item/storage/book/bible, -/obj/item/storage/book/bible{ +/obj/item/book/bible, +/obj/item/book/bible{ pixel_x = 4; pixel_y = 4 }, diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 4b0575a6c9b2c8..fd57d03ad5903d 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -6777,7 +6777,7 @@ /turf/open/floor/plating, /area/station/ai_monitored/turret_protected/aisat/foyer) "aQc" = ( -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/structure/altar_of_gods, /turf/open/floor/iron/dark, /area/station/service/chapel) @@ -42948,7 +42948,7 @@ "ohW" = ( /obj/structure/table/wood, /obj/machinery/light/dim/directional/north, -/obj/item/storage/book/bible, +/obj/item/book/bible, /turf/open/floor/carpet, /area/station/service/chapel/monastery) "ohY" = ( @@ -63100,7 +63100,7 @@ "vrd" = ( /obj/structure/table/wood, /obj/machinery/firealarm/directional/north, -/obj/item/storage/book/bible, +/obj/item/book/bible, /turf/open/floor/iron/chapel{ dir = 9 }, diff --git a/_maps/shuttles/emergency_cruise.dmm b/_maps/shuttles/emergency_cruise.dmm index 98d380a12bc2c7..d488bf896c7a48 100644 --- a/_maps/shuttles/emergency_cruise.dmm +++ b/_maps/shuttles/emergency_cruise.dmm @@ -694,7 +694,7 @@ /area/shuttle/escape) "LM" = ( /obj/structure/table/reinforced, -/obj/item/storage/book/bible/booze{ +/obj/item/book/bible/booze{ pixel_x = -3; pixel_y = 4 }, diff --git a/_maps/shuttles/emergency_monastery.dmm b/_maps/shuttles/emergency_monastery.dmm index d4f75fa0a0d7b7..ad47329ff48df1 100644 --- a/_maps/shuttles/emergency_monastery.dmm +++ b/_maps/shuttles/emergency_monastery.dmm @@ -1612,9 +1612,9 @@ "yr" = ( /obj/structure/closet, /obj/machinery/light/small/directional/south, -/obj/item/storage/book/bible, -/obj/item/storage/book/bible, -/obj/item/storage/book/bible, +/obj/item/book/bible, +/obj/item/book/bible, +/obj/item/book/bible, /turf/open/floor/carpet, /area/shuttle/escape) "yu" = ( @@ -2037,7 +2037,7 @@ /turf/open/misc/asteroid, /area/shuttle/escape) "Dv" = ( -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/structure/cable, /obj/structure/altar_of_gods, /turf/open/floor/carpet, @@ -3211,7 +3211,7 @@ /area/shuttle/escape) "Si" = ( /obj/structure/table/wood/fancy, -/obj/item/storage/book/bible, +/obj/item/book/bible, /turf/open/floor/carpet, /area/shuttle/escape) "Sj" = ( diff --git a/_maps/templates/holodeck_chapelcourt.dmm b/_maps/templates/holodeck_chapelcourt.dmm index 96c39503c3eb1b..6f87e03bc162a2 100644 --- a/_maps/templates/holodeck_chapelcourt.dmm +++ b/_maps/templates/holodeck_chapelcourt.dmm @@ -190,7 +190,7 @@ /area/template_noop) "au" = ( /obj/structure/table/wood/fancy, -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -495,7 +495,7 @@ /area/template_noop) "kv" = ( /obj/structure/table/wood/fancy, -/obj/item/storage/book/bible, +/obj/item/book/bible, /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/holofloor/dark, /area/template_noop) diff --git a/_maps/templates/lazy_templates/ninja_den.dmm b/_maps/templates/lazy_templates/ninja_den.dmm index d7eafeb4cc3d53..14a479d5c496af 100644 --- a/_maps/templates/lazy_templates/ninja_den.dmm +++ b/_maps/templates/lazy_templates/ninja_den.dmm @@ -122,7 +122,7 @@ /area/centcom/central_command_areas/holding) "dj" = ( /obj/structure/table/wood/fancy/royalblack, -/obj/item/storage/book/bible, +/obj/item/book/bible, /turf/open/floor/wood/large, /area/centcom/central_command_areas/holding) "dy" = ( diff --git a/code/__DEFINES/achievements.dm b/code/__DEFINES/achievements.dm index 96f0a7e023f21d..101215774669bb 100644 --- a/code/__DEFINES/achievements.dm +++ b/code/__DEFINES/achievements.dm @@ -45,6 +45,7 @@ #define MEDAL_NARSUPREME "Narsupreme" #define MEDAL_SPRINGLOCK "The Man Inside the Modsuit" #define MEDAL_HEALTHY "Heart Healthy" +#define MEDAL_GODS_WRATH "God's Wrath" //Skill medal hub IDs #define MEDAL_LEGENDARY_MINER "Legendary Miner" diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index b278dfb6e0e487..7a336ec1d4efed 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -171,7 +171,7 @@ ///from [/obj/structure/closet/supplypod/proc/preOpen]: #define COMSIG_SUPPLYPOD_LANDED "supplypodgoboom" -///from /obj/item/storage/book/bible/afterattack(): (mob/user, proximity) +///from /obj/item/book/bible/afterattack(): (mob/user, proximity) #define COMSIG_BIBLE_SMACKED "bible_smacked" ///stops the bible chain from continuing. When all of the effects of the bible smacking have been moved to a signal we can kill this #define COMSIG_END_BIBLE_CHAIN (1<<0) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 258aa884b2eb04..3d08f8d7099238 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -267,7 +267,7 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list( GLOBAL_LIST_INIT(book_types, typecacheof(list( /obj/item/book, /obj/item/spellbook, - /obj/item/storage/book))) +))) // Jobs #define is_job(job_type) (istype(job_type, /datum/job)) diff --git a/code/datums/achievements/misc_achievements.dm b/code/datums/achievements/misc_achievements.dm index 8d9e5e2db3d712..55b5d70cdf9179 100644 --- a/code/datums/achievements/misc_achievements.dm +++ b/code/datums/achievements/misc_achievements.dm @@ -217,3 +217,9 @@ desc = "Don't be such a baby, it's just a heart attack. You've bounced back from worse!" database_id = MEDAL_HEALTHY icon = "picofhealth" + +/datum/award/achievement/misc/gods_wrath + name = "God's Wrath" + desc = "Did you think you could get away with defiling the word of God?" + database_id = MEDAL_GODS_WRATH + icon = "godswrath" diff --git a/code/datums/components/crafting/tailoring.dm b/code/datums/components/crafting/tailoring.dm index 7adc8e99dfa6bf..77b056e8235497 100644 --- a/code/datums/components/crafting/tailoring.dm +++ b/code/datums/components/crafting/tailoring.dm @@ -268,7 +268,7 @@ time = 1 SECONDS tool_paths = list( /obj/item/clothing/suit/hooded/chaplain_hoodie, - /obj/item/storage/book/bible, + /obj/item/book/bible, ) reqs = list(/obj/item/stack/sheet/cloth = 4) category = CAT_CLOTHING diff --git a/code/datums/components/omen.dm b/code/datums/components/omen.dm index 0f30f7e2a34977..46ff3990c2cee0 100644 --- a/code/datums/components/omen.dm +++ b/code/datums/components/omen.dm @@ -17,11 +17,18 @@ /// Base damage from negative events. Cursed take 25% less damage. var/damage_mod = 1 -/datum/component/omen/Initialize(vessel) +/datum/component/omen/Initialize(obj/vessel, permanent, luck_mod, damage_mod) if(!isliving(parent)) return COMPONENT_INCOMPATIBLE - src.vessel = vessel + if(istype(vessel)) + src.vessel = vessel + RegisterSignal(vessel, COMSIG_PARENT_QDELETING, PROC_REF(vessel_qdeleting)) + src.permanent = permanent + if(!isnull(luck_mod)) + src.luck_mod = luck_mod + if(!isnull(damage_mod)) + src.damage_mod = damage_mod /datum/component/omen/Destroy(force) var/mob/living/person = parent @@ -29,6 +36,8 @@ if(vessel) vessel.visible_message(span_warning("[vessel] burns up in a sinister flash, taking an evil energy with it...")) + UnregisterSignal(vessel, COMSIG_PARENT_QDELETING) + vessel.burn() vessel = null return ..() @@ -53,8 +62,8 @@ if(!isliving(our_guy)) return - var/mob/living/living_guy = our_guy + var/mob/living/living_guy = our_guy if(!prob(15 * luck_mod)) return @@ -124,7 +133,10 @@ /datum/component/omen/proc/check_bless(mob/living/our_guy, category) SIGNAL_HANDLER - if (!("blessing" in our_guy.mob_mood.mood_events)) + if(permanent) + return + + if(!("blessing" in our_guy.mob_mood.mood_events)) return qdel(src) @@ -133,6 +145,9 @@ /datum/component/omen/proc/check_death(mob/living/our_guy) SIGNAL_HANDLER + if(permanent) + return + qdel(src) /// Creates a localized explosion that shakes the camera @@ -142,21 +157,18 @@ for(var/mob/witness in view(2, our_guy)) shake_camera(witness, 1 SECONDS, 2) +/// Vessel got deleted, set it to null +/datum/component/omen/proc/vessel_qdeleting(atom/source) + SIGNAL_HANDLER + + UnregisterSignal(vessel, COMSIG_PARENT_QDELETING) + vessel = null + /** * The smite omen. Permanent. */ /datum/component/omen/smite -/datum/component/omen/smite/Initialize(vessel, permanent) - . = ..() - src.permanent = permanent - -/datum/component/omen/smite/check_bless(mob/living/our_guy, category) - if(!permanent) - return ..() - - return - /datum/component/omen/smite/check_death(mob/living/our_guy) if(!permanent) return ..() @@ -198,3 +210,22 @@ player.spawn_gibs() return + +/** + * The bible omen. + * While it lasts, parent gets a cursed aura filter. + */ +/datum/component/omen/bible + +/datum/component/omen/bible/RegisterWithParent() + . = ..() + var/mob/living/living_parent = parent + living_parent.add_filter("omen", 2, list("type" = "drop_shadow", "color" = COLOR_DARK_RED, "alpha" = 0, "size" = 2)) + var/filter = living_parent.get_filter("omen") + animate(filter, alpha = 255, time = 2 SECONDS, loop = -1) + animate(alpha = 0, time = 2 SECONDS) + +/datum/component/omen/bible/UnregisterFromParent() + . = ..() + var/mob/living/living_parent = parent + living_parent.remove_filter("omen") diff --git a/code/datums/components/religious_tool.dm b/code/datums/components/religious_tool.dm index 0aedee328ea31c..f28578c5ce981e 100644 --- a/code/datums/components/religious_tool.dm +++ b/code/datums/components/religious_tool.dm @@ -14,7 +14,7 @@ /// The rite currently being invoked var/datum/religion_rites/performing_rite ///Sets the type for catalyst - var/catalyst_type = /obj/item/storage/book/bible + var/catalyst_type = /obj/item/book/bible ///Enables overide of COMPONENT_NO_AFTERATTACK, not recommended as it means you can potentially cause damage to the item using the catalyst. var/force_catalyst_afterattack = FALSE var/datum/callback/after_sect_select_cb diff --git a/code/datums/memory/general_memories.dm b/code/datums/memory/general_memories.dm index 1326b72fe16683..e3a4a88cd76b0d 100644 --- a/code/datums/memory/general_memories.dm +++ b/code/datums/memory/general_memories.dm @@ -914,3 +914,49 @@ "[protagonist_name]'s mind sets itself on a singular, violent purpose as they're flashed by [antagonist_name]: Kill the heads.", "[antagonist_name] lifts an odd device to [protagonist_name]'s eyes and flashes him, imprinting murderous instructions.", ) + +/// Saw someone play Russian Roulette. +/datum/memory/witnessed_gods_wrath + memory_flags = MEMORY_CHECK_BLINDNESS|MEMORY_SKIP_UNCONSCIOUS + story_value = STORY_VALUE_AMAZING + +/datum/memory/witnessed_gods_wrath/New( + datum/mind/memorizer_mind, + atom/protagonist, + atom/deuteragonist, + atom/antagonist, +) + +/datum/memory/witnessed_gods_wrath/get_names() + return list("[protagonist_name] suffering the wrath of [antagonist_name].") + +/datum/memory/witnessed_gods_wrath/get_starts() + return list( + "[protagonist_name] burns [deuteragonist_name], and [antagonist_name] turns [protagonist_name] into a fine red mist.", + "[antagonist_name] explodes [protagonist_name] into a million pieces for defiling [deuteragonist_name].", + "[protagonist_name] angers [antagonist_name] by defiling [deuteragonist_name], and gets obliterated.", + ) + +/datum/memory/witnessed_gods_wrath/get_moods() + return list("[protagonist_name] [mood_verb] as they get annihilated by [antagonist_name].") + +/datum/memory/witnessed_gods_wrath/get_happy_moods() + return list( + "cackles hysterically", + "laughs maniacally", + "grins widely", + ) + +/datum/memory/witnessed_gods_wrath/get_neutral_moods() + return list( + "appears concerned", + "reconsiders their life decisions", + "has a blank expression", + ) + +/datum/memory/witnessed_gods_wrath/get_sad_moods() + return list( + "appears dejected", + "is filled with regret", + "winces in despair" + ) diff --git a/code/datums/quirks/positive_quirks.dm b/code/datums/quirks/positive_quirks.dm index 70628be04785b3..45168f725ff6cb 100644 --- a/code/datums/quirks/positive_quirks.dm +++ b/code/datums/quirks/positive_quirks.dm @@ -267,7 +267,7 @@ lose_text = span_danger("You lose faith!") medical_record_text = "Patient reports a belief in a higher power." mail_goodies = list( - /obj/item/storage/book/bible/booze, + /obj/item/book/bible/booze, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/bedsheet/chaplain, /obj/item/toy/cards/deck/tarot, diff --git a/code/game/objects/items/granters/_granters.dm b/code/game/objects/items/granters/_granters.dm index 8cb63925f24056..ad9b9a453f05d8 100644 --- a/code/game/objects/items/granters/_granters.dm +++ b/code/game/objects/items/granters/_granters.dm @@ -5,7 +5,7 @@ */ /obj/item/book/granter due_date = 0 - unique = 1 + unique = TRUE /// Flavor messages displayed to mobs reading the granter var/list/remarks = list() /// Controls how long a mob must keep the book in his hand to actually successfully learn diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index ec272c32874d57..88570986e72a9d 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -325,11 +325,7 @@ atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL atom_storage.max_total_storage = 21 atom_storage.max_slots = 7 - atom_storage.set_holdable(list( - /obj/item/book, - /obj/item/spellbook, - /obj/item/storage/book, - )) + atom_storage.set_holdable(list(/obj/item/book, /obj/item/spellbook)) /* * Trays - Agouri diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm deleted file mode 100644 index f558d9552d24e8..00000000000000 --- a/code/game/objects/items/storage/book.dm +++ /dev/null @@ -1,293 +0,0 @@ -/obj/item/storage/book - name = "hollowed book" - desc = "I guess someone didn't like it." - icon = 'icons/obj/library.dmi' - icon_state ="book" - worn_icon_state = "book" - throw_speed = 2 - throw_range = 5 - w_class = WEIGHT_CLASS_NORMAL - resistance_flags = FLAMMABLE - var/title = "book" - -/obj/item/storage/book/Initialize(mapload) - . = ..() - atom_storage.max_slots = 1 - -/obj/item/storage/book/attack_self(mob/user) - balloon_alert(user, "pages cut out!") - -GLOBAL_LIST_INIT(biblenames, list("Bible", "Quran", "Scrapbook", "Burning Bible", "Clown Bible", "Banana Bible", "Creeper Bible", "White Bible", "Holy Light", "The God Delusion", "Tome", "The King in Yellow", "Ithaqua", "Scientology", "Melted Bible", "Necronomicon", "Insulationism", "Guru Granth Sahib", "Kojiki")) -//If you get these two lists not matching in size, there will be runtimes and I will hurt you in ways you couldn't even begin to imagine -// if your bible has no custom itemstate, use one of the existing ones -GLOBAL_LIST_INIT(biblestates, list("bible", "koran", "scrapbook", "burning", "honk1", "honk2", "creeper", "white", "holylight", "atheist", "tome", "kingyellow", "ithaqua", "scientology", "melted", "necronomicon", "insuls", "gurugranthsahib", "kojiki")) -GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "burning", "honk1", "honk2", "creeper", "white", "holylight", "atheist", "tome", "kingyellow", "ithaqua", "scientology", "melted", "necronomicon", "kingyellow", "gurugranthsahib", "kojiki")) - -/obj/item/storage/book/bible - name = "bible" - desc = "Apply to head repeatedly." - icon = 'icons/obj/storage/book.dmi' - icon_state = "bible" - inhand_icon_state = "bible" - worn_icon_state = "bible" - lefthand_file = 'icons/mob/inhands/items/books_lefthand.dmi' - righthand_file = 'icons/mob/inhands/items/books_righthand.dmi' - var/mob/affecting = null - var/deity_name = "Christ" - force_string = "holy" - -/obj/item/storage/book/bible/examine(mob/user) - . = ..() - if(user?.mind?.holy_role) - if(GLOB.chaplain_altars.len) - . += span_notice("[src] has an expansion pack to replace any broken Altar.") - else - . += span_notice("[src] can be unpacked by hitting the floor of a holy area with it.") - -/obj/item/storage/book/bible/Initialize(mapload) - . = ..() - atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL - AddComponent(/datum/component/anti_magic, MAGIC_RESISTANCE_HOLY) - -/obj/item/storage/book/bible/suicide_act(mob/living/user) - user.visible_message(span_suicide("[user] is offering [user.p_them()]self to [deity_name]! It looks like [user.p_theyre()] trying to commit suicide!")) - return BRUTELOSS - -/obj/item/storage/book/bible/attack_self(mob/living/carbon/human/user) - if(GLOB.bible_icon_state) - return FALSE - if(user?.mind?.holy_role != HOLY_ROLE_HIGHPRIEST) - return FALSE - - var/list/skins = list() - for(var/i in 1 to GLOB.biblestates.len) - var/image/bible_image = image(icon = 'icons/obj/storage/book.dmi', icon_state = GLOB.biblestates[i]) - skins += list("[GLOB.biblenames[i]]" = bible_image) - - var/choice = show_radial_menu(user, src, skins, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 40, require_near = TRUE) - if(!choice) - return FALSE - var/bible_index = GLOB.biblenames.Find(choice) - if(!bible_index) - return FALSE - icon_state = GLOB.biblestates[bible_index] - inhand_icon_state = GLOB.bibleitemstates[bible_index] - - switch(icon_state) - if("honk1") - user.dna.add_mutation(/datum/mutation/human/clumsy) - user.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(user), ITEM_SLOT_MASK) - if("honk2") - user.dna.add_mutation(/datum/mutation/human/clumsy) - user.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(user), ITEM_SLOT_MASK) - if("insuls") - var/obj/item/clothing/gloves/color/fyellow/insuls = new - insuls.name = "insuls" - insuls.desc = "A mere copy of the true insuls." - insuls.siemens_coefficient = 0.99999 - user.equip_to_slot(insuls, ITEM_SLOT_GLOVES) - GLOB.bible_icon_state = icon_state - GLOB.bible_inhand_icon_state = inhand_icon_state - SSblackbox.record_feedback("text", "religion_book", 1, "[choice]") - -/** - * Checks if we are allowed to interact with a radial menu - * - * Arguments: - * * user The mob interacting with the menu - */ -/obj/item/storage/book/bible/proc/check_menu(mob/living/carbon/human/user) - if(GLOB.bible_icon_state) - return FALSE - if(!istype(user) || !user.is_holding(src)) - return FALSE - if(user.incapacitated()) - return FALSE - if(user.mind?.holy_role != HOLY_ROLE_HIGHPRIEST) - return FALSE - return TRUE - -/obj/item/storage/book/bible/proc/make_new_altar(atom/bible_smacked, mob/user) - var/new_altar_area = get_turf(bible_smacked) - - balloon_alert(user, "unpacking bible...") - if(!do_after(user, 15 SECONDS, new_altar_area)) - return - new /obj/structure/altar_of_gods(new_altar_area) - qdel(src) - -/obj/item/storage/book/bible/proc/bless(mob/living/L, mob/living/user) - if(GLOB.religious_sect) - return GLOB.religious_sect.sect_bless(L,user) - if(!ishuman(L)) - return - var/mob/living/carbon/human/H = L - for(var/obj/item/bodypart/bodypart as anything in H.bodyparts) - if(!IS_ORGANIC_LIMB(bodypart)) - balloon_alert(user, "can't heal metal!") - return 0 - - var/heal_amt = 10 - var/list/hurt_limbs = H.get_damaged_bodyparts(1, 1, BODYTYPE_ORGANIC) - - if(hurt_limbs.len) - for(var/X in hurt_limbs) - var/obj/item/bodypart/affecting = X - if(affecting.heal_damage(heal_amt, heal_amt, BODYTYPE_ORGANIC)) - H.update_damage_overlays() - H.visible_message(span_notice("[user] heals [H] with the power of [deity_name]!")) - to_chat(H, span_boldnotice("May the power of [deity_name] compel you to be healed!")) - playsound(src.loc, SFX_PUNCH, 25, TRUE, -1) - H.add_mood_event("blessing", /datum/mood_event/blessing) - return TRUE - -/obj/item/storage/book/bible/attack(mob/living/M, mob/living/carbon/human/user, heal_mode = TRUE) - - if (!ISADVANCEDTOOLUSER(user)) - balloon_alert(user, "not dextrous enough!") - return - - if (HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) - to_chat(user, span_danger("[src] slips out of your hand and hits your head.")) - user.take_bodypart_damage(10) - user.Unconscious(40 SECONDS) - return - - if (!user.mind || !user.mind.holy_role) - to_chat(user, span_danger("The book sizzles in your hands.")) - user.take_bodypart_damage(0, 10) - return - - if (!heal_mode) - return ..() - - if (M.stat == DEAD) - M.visible_message(span_danger("[user] smacks [M]'s lifeless corpse with [src].")) - playsound(src.loc, SFX_PUNCH, 25, TRUE, -1) - return - - if(user == M) - balloon_alert(user, "can't heal yourself!") - return - - var/smack = TRUE - - if(prob(60) && bless(M, user)) - smack = FALSE - else if(iscarbon(M)) - var/mob/living/carbon/C = M - if(!istype(C.head, /obj/item/clothing/head/helmet)) - C.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5, 60) - C.balloon_alert(C, "you feel dumber") - - if(smack) - M.visible_message(span_danger("[user] beats [M] over the head with [src]!"), \ - span_userdanger("[user] beats [M] over the head with [src]!")) - playsound(src.loc, SFX_PUNCH, 25, TRUE, -1) - log_combat(user, M, "attacked", src) - -/obj/item/storage/book/bible/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user) - return !istype(storage_holder, /obj/item/storage/book/bible) - -/obj/item/storage/book/bible/afterattack(atom/bible_smacked, mob/user, proximity) - . = ..() - if(!proximity) - return - if(SEND_SIGNAL(bible_smacked, COMSIG_BIBLE_SMACKED, user, proximity) & COMSIG_END_BIBLE_CHAIN) - return . | AFTERATTACK_PROCESSED_ITEM - if(isfloorturf(bible_smacked)) - if(user.mind && (user.mind.holy_role)) - var/area/current_area = get_area(bible_smacked) - if(!GLOB.chaplain_altars.len && istype(current_area, /area/station/service/chapel)) - make_new_altar(bible_smacked, user) - return - for(var/obj/effect/rune/nearby_runes in orange(2,user)) - nearby_runes.invisibility = 0 - bible_smacked.balloon_alert(user, "floor smacked") - - if(user?.mind?.holy_role) - if(bible_smacked.reagents && bible_smacked.reagents.has_reagent(/datum/reagent/water)) // blesses all the water in the holder - . |= AFTERATTACK_PROCESSED_ITEM - bible_smacked.balloon_alert(user, "blessed") - var/water2holy = bible_smacked.reagents.get_reagent_amount(/datum/reagent/water) - bible_smacked.reagents.del_reagent(/datum/reagent/water) - bible_smacked.reagents.add_reagent(/datum/reagent/water/holywater,water2holy) - if(bible_smacked.reagents && bible_smacked.reagents.has_reagent(/datum/reagent/fuel/unholywater)) // yeah yeah, copy pasted code - sue me - . |= AFTERATTACK_PROCESSED_ITEM - bible_smacked.balloon_alert(user, "purified") - var/unholy2clean = bible_smacked.reagents.get_reagent_amount(/datum/reagent/fuel/unholywater) - bible_smacked.reagents.del_reagent(/datum/reagent/fuel/unholywater) - bible_smacked.reagents.add_reagent(/datum/reagent/water/holywater,unholy2clean) - if(istype(bible_smacked, /obj/item/storage/book/bible) && !istype(bible_smacked, /obj/item/storage/book/bible/syndicate)) - . |= AFTERATTACK_PROCESSED_ITEM - bible_smacked.balloon_alert(user, "converted") - var/obj/item/storage/book/bible/B = bible_smacked - B.name = name - B.icon_state = icon_state - B.inhand_icon_state = inhand_icon_state - - if(istype(bible_smacked, /obj/item/cult_bastard) && !IS_CULTIST(user)) - . |= AFTERATTACK_PROCESSED_ITEM - var/obj/item/cult_bastard/sword = bible_smacked - bible_smacked.balloon_alert(user, "exorcising...") - playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,TRUE) - if(do_after(user, 40, target = sword)) - playsound(src,'sound/effects/pray_chaplain.ogg',60,TRUE) - for(var/obj/item/soulstone/SS in sword.contents) - SS.required_role = null - for(var/mob/living/simple_animal/shade/EX in SS) - var/datum/antagonist/cult/cultist = EX.mind.has_antag_datum(/datum/antagonist/cult) - if (cultist) - cultist.silent = TRUE - cultist.on_removal() - - EX.icon_state = "shade_holy" - EX.name = "Purified [EX.name]" - SS.release_shades(user) - qdel(SS) - new /obj/item/nullrod/claymore(get_turf(sword)) - user.visible_message(span_notice("[user] purifies [sword]!")) - qdel(sword) - -/obj/item/storage/book/bible/booze - desc = "To be applied to the head repeatedly." - -/obj/item/storage/book/bible/booze/PopulateContents() - new /obj/item/reagent_containers/cup/glass/bottle/whiskey(src) - -/obj/item/storage/book/bible/syndicate - icon_state ="ebook" - deity_name = "The Syndicate" - throw_speed = 2 - throwforce = 18 - throw_range = 7 - force = 18 - hitsound = 'sound/weapons/sear.ogg' - damtype = BURN - name = "Syndicate Tome" - attack_verb_continuous = list("attacks", "burns", "blesses", "damns", "scorches") - attack_verb_simple = list("attack", "burn", "bless", "damn", "scorch") - item_flags = NO_BLOOD_ON_ITEM - var/uses = 1 - var/ownername - -/obj/item/storage/book/bible/syndicate/attack_self(mob/living/carbon/human/H) - if (uses) - H.mind.holy_role = HOLY_ROLE_PRIEST - uses -= 1 - to_chat(H, span_userdanger("You try to open the book AND IT BITES YOU!")) - playsound(src.loc, 'sound/effects/snap.ogg', 50, TRUE) - H.apply_damage(5, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM), attacking_item = src) - to_chat(H, span_notice("Your name appears on the inside cover, in blood.")) - ownername = H.real_name - -/obj/item/storage/book/bible/syndicate/examine(mob/user) - . = ..() - if(ownername) - . += span_warning("The name [ownername] is written in blood inside the cover.") - -/obj/item/storage/book/bible/syndicate/attack(mob/living/M, mob/living/carbon/human/user, heal_mode = TRUE) - if (!user.combat_mode) - return ..() - else - return ..(M,user,heal_mode = FALSE) diff --git a/code/modules/admin/smites/bad_luck.dm b/code/modules/admin/smites/bad_luck.dm index a5c00aea43d9bd..c9f6a94b93a03e 100644 --- a/code/modules/admin/smites/bad_luck.dm +++ b/code/modules/admin/smites/bad_luck.dm @@ -14,8 +14,11 @@ /datum/smite/bad_luck/effect(client/user, mob/living/target) . = ..() + //if permanent, replace any existing omen + if(permanent) + var/existing_component = target.GetComponent(/datum/component/omen) + qdel(existing_component) target.AddComponent(/datum/component/omen/smite, permanent = permanent) - if(silent) return to_chat(target, span_warning("You get a bad feeling...")) diff --git a/code/modules/antagonists/heretic/knowledge/general_side.dm b/code/modules/antagonists/heretic/knowledge/general_side.dm index b771108e272fee..9c3fbe9d447f36 100644 --- a/code/modules/antagonists/heretic/knowledge/general_side.dm +++ b/code/modules/antagonists/heretic/knowledge/general_side.dm @@ -48,7 +48,7 @@ gain_text = "The occult leaves fragments of knowledge and power anywhere and everywhere. The Codex Cicatrix is one such example. \ Within the leather-bound faces and age old pages, a path into the Mansus is revealed." required_atoms = list( - /obj/item/storage/book/bible = 1, + /obj/item/book/bible = 1, /obj/item/pen/fountain = 1, /obj/item/stack/sheet/animalhide = 1, ) diff --git a/code/modules/antagonists/revenant/haunted_item.dm b/code/modules/antagonists/revenant/haunted_item.dm index a4772912a61f58..7692d8d29f5878 100644 --- a/code/modules/antagonists/revenant/haunted_item.dm +++ b/code/modules/antagonists/revenant/haunted_item.dm @@ -61,7 +61,7 @@ pre_haunt_throwforce = haunted_item.throwforce haunted_item.throwforce = min(haunted_item.throwforce + throw_force_bonus, throw_force_max) - var/static/list/default_dispell_types = list(/obj/item/nullrod, /obj/item/storage/book/bible) + var/static/list/default_dispell_types = list(/obj/item/nullrod, /obj/item/book/bible) src.types_which_dispell_us = types_which_dispell_us || default_dispell_types src.despawn_message = despawn_message diff --git a/code/modules/asset_cache/assets/bibles.dm b/code/modules/asset_cache/assets/bibles.dm index d99a6e26feb9b1..948af216063f84 100644 --- a/code/modules/asset_cache/assets/bibles.dm +++ b/code/modules/asset_cache/assets/bibles.dm @@ -2,7 +2,7 @@ name = "bibles" /datum/asset/spritesheet/bibles/create_spritesheets() - var/obj/item/storage/book/bible/holy_template = /obj/item/storage/book/bible + var/obj/item/book/bible/holy_template = /obj/item/book/bible InsertAll("display", initial(holy_template.icon)) /datum/asset/spritesheet/bibles/ModifyInserted(icon/pre_asset) diff --git a/code/modules/awaymissions/mission_code/stationCollision.dm b/code/modules/awaymissions/mission_code/stationCollision.dm index 414484c6dcf4de..b0f31eaa669853 100644 --- a/code/modules/awaymissions/mission_code/stationCollision.dm +++ b/code/modules/awaymissions/mission_code/stationCollision.dm @@ -23,16 +23,16 @@ name = "Safecode hint spawner" /obj/effect/landmark/sc_bible_spawner/Initialize(mapload) - ..() - var/obj/item/storage/book/bible/B = new /obj/item/storage/book/bible/booze(loc) - B.name = "The Holy book of the Geometer" - B.deity_name = "Narsie" - B.icon_state = "melted" - B.inhand_icon_state = "melted" - B.lefthand_file = 'icons/mob/inhands/items/books_lefthand.dmi' - B.righthand_file = 'icons/mob/inhands/items/books_righthand.dmi' - new /obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_bible(B) - new /obj/item/pen(B) + . = ..() + var/obj/item/book/bible/holy_bible = new /obj/item/book/bible/booze(loc) + holy_bible.name = "The Holy book of the Geometer" + holy_bible.deity_name = "Narsie" + holy_bible.icon_state = "melted" + holy_bible.inhand_icon_state = "melted" + holy_bible.lefthand_file = 'icons/mob/inhands/items/books_lefthand.dmi' + holy_bible.righthand_file = 'icons/mob/inhands/items/books_righthand.dmi' + new /obj/item/paper/fluff/awaymissions/stationcollision/safehint_paper_bible(holy_bible) + new /obj/item/pen(holy_bible) return INITIALIZE_HINT_QDEL /* diff --git a/code/modules/cargo/packs/general.dm b/code/modules/cargo/packs/general.dm index a35d9a920a7b4e..96bb9e42a215f4 100644 --- a/code/modules/cargo/packs/general.dm +++ b/code/modules/cargo/packs/general.dm @@ -209,7 +209,7 @@ cost = CARGO_CRATE_VALUE * 6 // it costs so much because the Space Church needs funding to build a cathedral access_view = ACCESS_CHAPEL_OFFICE contains = list(/obj/item/reagent_containers/cup/glass/bottle/holywater = 2, - /obj/item/storage/book/bible/booze = 2, + /obj/item/book/bible/booze = 2, /obj/item/clothing/suit/hooded/chaplain_hoodie = 2, /obj/item/clothing/under/misc/burial = 2, ) diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index e4b9fe079508a7..ffbef12d1ef7e0 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -132,4 +132,4 @@ /obj/item/clothing/suit/bio_suit/plaguedoctorsuit/Initialize(mapload) . = ..() - allowed += list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/cane) + allowed += list(/obj/item/book/bible, /obj/item/nullrod, /obj/item/cane) diff --git a/code/modules/clothing/suits/costume.dm b/code/modules/clothing/suits/costume.dm index 951ca94cca4a2e..c8faa7e86add23 100644 --- a/code/modules/clothing/suits/costume.dm +++ b/code/modules/clothing/suits/costume.dm @@ -127,7 +127,7 @@ inhand_icon_state = "imperium_monk" body_parts_covered = CHEST|GROIN|LEGS|ARMS flags_inv = HIDESHOES|HIDEJUMPSUIT - allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen) + allowed = list(/obj/item/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen) /obj/item/clothing/suit/costume/chickensuit name = "chicken suit" @@ -484,7 +484,7 @@ worn_icon = 'icons/mob/clothing/suits/costume.dmi' inhand_icon_state = "mysticrobe" body_parts_covered = CHEST|GROIN|LEGS|ARMS - allowed = list(/obj/item/spellbook, /obj/item/storage/book/bible) + allowed = list(/obj/item/spellbook, /obj/item/book/bible) flags_inv = HIDEJUMPSUIT hoodtype = /obj/item/clothing/head/hooded/mysticrobe diff --git a/code/modules/jobs/job_types/chaplain/chaplain.dm b/code/modules/jobs/job_types/chaplain/chaplain.dm index 78befe1b7bd22b..4714bf589d43ad 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain.dm @@ -42,71 +42,69 @@ . = ..() if(!ishuman(spawned)) return - var/mob/living/carbon/human/H = spawned - var/obj/item/storage/book/bible/booze/B = new - + var/mob/living/carbon/human/human_spawned = spawned + var/obj/item/book/bible/booze/holy_bible = new if(GLOB.religion) - if(H.mind) - H.mind.holy_role = HOLY_ROLE_PRIEST - B.deity_name = GLOB.deity - B.name = GLOB.bible_name + if(human_spawned.mind) + human_spawned.mind.holy_role = HOLY_ROLE_PRIEST + holy_bible.deity_name = GLOB.deity + holy_bible.name = GLOB.bible_name // These checks are important as there's no guarantee the "HOLY_ROLE_HIGHPRIEST" chaplain has selected a bible skin. if(GLOB.bible_icon_state) - B.icon_state = GLOB.bible_icon_state + holy_bible.icon_state = GLOB.bible_icon_state if(GLOB.bible_inhand_icon_state) - B.inhand_icon_state = GLOB.bible_inhand_icon_state - to_chat(H, span_boldnotice("There is already an established religion onboard the station. You are an acolyte of [GLOB.deity]. Defer to the Chaplain.")) - H.equip_to_slot_or_del(B, ITEM_SLOT_BACKPACK) + holy_bible.inhand_icon_state = GLOB.bible_inhand_icon_state + to_chat(human_spawned, span_boldnotice("There is already an established religion onboard the station. You are an acolyte of [GLOB.deity]. Defer to the Chaplain.")) + human_spawned.equip_to_slot_or_del(holy_bible, ITEM_SLOT_BACKPACK) var/nrt = GLOB.holy_weapon_type || /obj/item/nullrod - var/obj/item/nullrod/N = new nrt(H) - H.put_in_hands(N) + var/obj/item/nullrod/nullrod = new nrt(human_spawned) + human_spawned.put_in_hands(nullrod) if(GLOB.religious_sect) - GLOB.religious_sect.on_conversion(H) + GLOB.religious_sect.on_conversion(human_spawned) return - if(H.mind) - H.mind.holy_role = HOLY_ROLE_HIGHPRIEST + if(human_spawned.mind) + human_spawned.mind.holy_role = HOLY_ROLE_HIGHPRIEST var/new_religion = player_client?.prefs?.read_preference(/datum/preference/name/religion) || DEFAULT_RELIGION var/new_deity = player_client?.prefs?.read_preference(/datum/preference/name/deity) || DEFAULT_DEITY var/new_bible = player_client?.prefs?.read_preference(/datum/preference/name/bible) || DEFAULT_BIBLE - B.deity_name = new_deity - + holy_bible.deity_name = new_deity switch(lowertext(new_religion)) if("homosexuality", "gay", "penis", "ass", "cock", "cocks") new_bible = pick("Guys Gone Wild","Coming Out of The Closet","War of Cocks") switch(new_bible) if("War of Cocks") - B.deity_name = pick("Dick Powers", "King Cock") + holy_bible.deity_name = pick("Dick Powers", "King Cock") else - B.deity_name = pick("Gay Space Jesus", "Gandalf", "Dumbledore") - H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100) // starts off brain damaged as fuck + holy_bible.deity_name = pick("Gay Space Jesus", "Gandalf", "Dumbledore") + human_spawned.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100) // starts off brain damaged as fuck if("lol", "wtf", "poo", "badmin", "shitmin", "deadmin", "meme", "memes") new_bible = pick("Woody's Got Wood: The Aftermath", "Sweet Bro and Hella Jeff: Expanded Edition","F.A.T.A.L. Rulebook") switch(new_bible) if("Woody's Got Wood: The Aftermath") - B.deity_name = pick("Woody", "Andy", "Cherry Flavored Lube") + holy_bible.deity_name = pick("Woody", "Andy", "Cherry Flavored Lube") if("Sweet Bro and Hella Jeff: Expanded Edition") - B.deity_name = pick("Sweet Bro", "Hella Jeff", "Stairs", "AH") + holy_bible.deity_name = pick("Sweet Bro", "Hella Jeff", "Stairs", "AH") if("F.A.T.A.L. Rulebook") - B.deity_name = "Twenty Ten-Sided Dice" - H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100) // also starts off brain damaged as fuck + holy_bible.deity_name = "Twenty Ten-Sided Dice" + human_spawned.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100) // also starts off brain damaged as fuck if("servicianism", "partying") - B.desc = "Happy, Full, Clean. Live it and give it." + holy_bible.desc = "Happy, Full, Clean. Live it and give it." if("weeaboo","kawaii") new_bible = pick("Fanfiction Compendium","Japanese for Dummies","The Manganomicon","Establishing Your O.T.P") - B.deity_name = "Anime" + holy_bible.deity_name = "Anime" else if(new_bible == DEFAULT_BIBLE) new_bible = DEFAULT_BIBLE_REPLACE(new_bible) - B.name = new_bible + holy_bible.name = new_bible GLOB.religion = new_religion GLOB.bible_name = new_bible - GLOB.deity = B.deity_name + GLOB.deity = holy_bible.deity_name - H.equip_to_slot_or_del(B, ITEM_SLOT_BACKPACK) + human_spawned.equip_to_slot_or_del(holy_bible, ITEM_SLOT_BACKPACK) SSblackbox.record_feedback("text", "religion_name", 1, "[new_religion]", 1) SSblackbox.record_feedback("text", "religion_deity", 1, "[new_deity]", 1) diff --git a/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm b/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm index fe49a435607ff3..9dc8b7ade42a01 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm @@ -1,7 +1,7 @@ //Chaplain Suit Subtypes //If any new staple chaplain items get added, put them in these lists /obj/item/clothing/suit/chaplainsuit - allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) + allowed = list(/obj/item/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) icon = 'icons/obj/clothing/suits/chaplain.dmi' worn_icon = 'icons/mob/clothing/suits/chaplain.dmi' @@ -24,7 +24,7 @@ wound = 20 /obj/item/clothing/suit/hooded/chaplainsuit - allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) + allowed = list(/obj/item/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) //Suits /obj/item/clothing/suit/chaplainsuit/holidaypriest @@ -134,7 +134,7 @@ desc = "It sounds like hissing steam, ticking cogs, gone silent, It looks like a dead machine, trying to tick with life." icon_state = "clockwork_cuirass" inhand_icon_state = null - allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) + allowed = list(/obj/item/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) slowdown = 0 clothing_flags = NONE @@ -164,7 +164,7 @@ desc = "God wills it!" icon_state = "knight_templar" inhand_icon_state = null - allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) + allowed = list(/obj/item/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) slowdown = 0 clothing_flags = NONE @@ -242,7 +242,7 @@ worn_icon = 'icons/mob/clothing/suits/chaplain.dmi' inhand_icon_state = null body_parts_covered = CHEST|GROIN|LEGS|ARMS - allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) + allowed = list(/obj/item/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/cup/glass/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/flashlight/flare/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) hoodtype = /obj/item/clothing/head/hooded/chaplain_hood /obj/item/clothing/head/hooded/chaplain_hood diff --git a/code/modules/library/bibles.dm b/code/modules/library/bibles.dm new file mode 100644 index 00000000000000..830d5c65f194df --- /dev/null +++ b/code/modules/library/bibles.dm @@ -0,0 +1,353 @@ +GLOBAL_LIST_INIT(biblenames, list( + "Bible", + "Quran", + "Scrapbook", + "Burning Bible", + "Clown Bible", + "Banana Bible", + "Creeper Bible", + "White Bible", + "Holy Light", + "The God Delusion", + "Tome", + "The King in Yellow", + "Ithaqua", + "Scientology", + "Melted Bible", + "Necronomicon", + "Insulationism", + "Guru Granth Sahib", + "Kojiki", +)) +//If you get these two lists not matching in size, there will be runtimes and I will hurt you in ways you couldn't even begin to imagine +// if your bible has no custom itemstate, use one of the existing ones +GLOBAL_LIST_INIT(biblestates, list( + "bible", + "koran", + "scrapbook", + "burning", + "honk1", + "honk2", + "creeper", + "white", + "holylight", + "atheist", + "tome", + "kingyellow", + "ithaqua", + "scientology", + "melted", + "necronomicon", + "insuls", + "gurugranthsahib", + "kojiki", +)) +GLOBAL_LIST_INIT(bibleitemstates, list( + "bible", + "koran", + "scrapbook", + "burning", + "honk1", + "honk2", + "creeper", + "white", + "holylight", + "atheist", + "tome", + "kingyellow", + "ithaqua", + "scientology", + "melted", + "necronomicon", + "kingyellow", + "gurugranthsahib", + "kojiki", +)) + +/obj/item/book/bible + name = "bible" + desc = "Apply to head repeatedly." + icon = 'icons/obj/storage/book.dmi' + icon_state = "bible" + worn_icon_state = "bible" + inhand_icon_state = "bible" + lefthand_file = 'icons/mob/inhands/items/books_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items/books_righthand.dmi' + force_string = "holy" + unique = TRUE + /// Deity this bible is related to + var/deity_name = "Space Jesus" + +/obj/item/book/bible/Initialize(mapload) + . = ..() + AddComponent(/datum/component/anti_magic, MAGIC_RESISTANCE_HOLY) + carve_out() + +/obj/item/book/bible/examine(mob/user) + . = ..() + if(deity_name) + . += span_notice("This bible has been approved by [deity_name].") + if(user.mind?.holy_role) + if(GLOB.chaplain_altars.len) + . += span_notice("[src] has an expansion pack to replace any broken Altar.") + else + . += span_notice("[src] can be unpacked by hitting the floor of a holy area with it.") + +/obj/item/book/bible/burn_paper_product_attackby_check(obj/item/attacking_item, mob/living/user, bypass_clumsy) + . = ..() + // no deity to cast a curse upon thee + if(!deity_name) + return + if(. && (resistance_flags & ON_FIRE)) + var/datum/component/omen/existing_omen = user.GetComponent(/datum/component/omen) + //DOUBLE CURSED?! Just straight up gib the guy. + if(existing_omen) + to_chat(user, span_userdanger("[deity_name] SMITE thee!")) + add_memory_in_range(user, 7, /datum/memory/witnessed_gods_wrath, protagonist = user, deuteragonist = src, antagonist = deity_name) + user.client?.give_award(/datum/award/achievement/misc/gods_wrath, user) + user.gib() + else + to_chat(user, span_userdanger("[deity_name] cast a curse upon thee!")) + user.AddComponent(/datum/component/omen/bible) + +/obj/item/book/bible/carve_out(obj/item/carving_item, mob/living/user) + . = ..() + atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL + +/obj/item/book/bible/suicide_act(mob/living/user) + user.visible_message(span_suicide("[user] is offering [user.p_them()]self to [deity_name]! It looks like [user.p_theyre()] trying to commit suicide!")) + return BRUTELOSS + +/obj/item/book/bible/attack_self(mob/living/carbon/human/user) + if(GLOB.bible_icon_state) + return FALSE + if(user?.mind?.holy_role != HOLY_ROLE_HIGHPRIEST) + return FALSE + + var/list/skins = list() + for(var/i in 1 to GLOB.biblestates.len) + var/image/bible_image = image(icon = 'icons/obj/storage/book.dmi', icon_state = GLOB.biblestates[i]) + skins += list("[GLOB.biblenames[i]]" = bible_image) + + var/choice = show_radial_menu(user, src, skins, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 40, require_near = TRUE) + if(!choice) + return FALSE + var/bible_index = GLOB.biblenames.Find(choice) + if(!bible_index) + return FALSE + icon_state = GLOB.biblestates[bible_index] + inhand_icon_state = GLOB.bibleitemstates[bible_index] + + switch(icon_state) + if("honk1") + user.dna.add_mutation(/datum/mutation/human/clumsy) + user.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(user), ITEM_SLOT_MASK) + if("honk2") + user.dna.add_mutation(/datum/mutation/human/clumsy) + user.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(user), ITEM_SLOT_MASK) + if("insuls") + var/obj/item/clothing/gloves/color/fyellow/insuls = new + insuls.name = "insuls" + insuls.desc = "A mere copy of the true insuls." + insuls.siemens_coefficient = 0.99999 + user.equip_to_slot(insuls, ITEM_SLOT_GLOVES) + GLOB.bible_icon_state = icon_state + GLOB.bible_inhand_icon_state = inhand_icon_state + SSblackbox.record_feedback("text", "religion_book", 1, "[choice]") + +/** + * Checks if we are allowed to interact with a radial menu + * + * Arguments: + * * user The mob interacting with the menu + */ +/obj/item/book/bible/proc/check_menu(mob/living/carbon/human/user) + if(GLOB.bible_icon_state) + return FALSE + if(!istype(user) || !user.is_holding(src)) + return FALSE + if(user.incapacitated()) + return FALSE + if(user.mind?.holy_role != HOLY_ROLE_HIGHPRIEST) + return FALSE + return TRUE + +/obj/item/book/bible/proc/make_new_altar(atom/bible_smacked, mob/user) + var/new_altar_area = get_turf(bible_smacked) + + balloon_alert(user, "unpacking bible...") + if(!do_after(user, 15 SECONDS, new_altar_area)) + return + new /obj/structure/altar_of_gods(new_altar_area) + qdel(src) + +/obj/item/book/bible/proc/bless(mob/living/blessed, mob/living/user) + if(GLOB.religious_sect) + return GLOB.religious_sect.sect_bless(blessed,user) + if(!ishuman(blessed)) + return + var/mob/living/carbon/human/built_in_his_image = blessed + for(var/obj/item/bodypart/bodypart as anything in built_in_his_image.bodyparts) + if(!IS_ORGANIC_LIMB(bodypart)) + balloon_alert(user, "can't heal metal!") + return FALSE + + var/heal_amt = 10 + var/list/hurt_limbs = built_in_his_image.get_damaged_bodyparts(1, 1, BODYTYPE_ORGANIC) + if(length(hurt_limbs)) + for(var/obj/item/bodypart/affecting as anything in hurt_limbs) + if(affecting.heal_damage(heal_amt, heal_amt, BODYTYPE_ORGANIC)) + built_in_his_image.update_damage_overlays() + built_in_his_image.visible_message(span_notice("[user] heals [built_in_his_image] with the power of [deity_name]!")) + to_chat(built_in_his_image, span_boldnotice("May the power of [deity_name] compel you to be healed!")) + playsound(built_in_his_image, SFX_PUNCH, 25, TRUE, -1) + built_in_his_image.add_mood_event("blessing", /datum/mood_event/blessing) + return TRUE + +/obj/item/book/bible/attack(mob/living/target_mob, mob/living/carbon/human/user, params, heal_mode = TRUE) + if(!ISADVANCEDTOOLUSER(user)) + balloon_alert(user, "not dextrous enough!") + return + + if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) + to_chat(user, span_danger("[src] slips out of your hand and hits your head.")) + user.take_bodypart_damage(10) + user.Unconscious(40 SECONDS) + return + + if(!user.mind?.holy_role) + to_chat(user, span_danger("The book sizzles in your hands.")) + user.take_bodypart_damage(burn = 10) + return + + if(!heal_mode) + return ..() + + if(target_mob.stat == DEAD) + target_mob.visible_message(span_danger("[user] smacks [target_mob]'s lifeless corpse with [src].")) + playsound(target_mob, SFX_PUNCH, 25, TRUE, -1) + return + + if(user == target_mob) + balloon_alert(user, "can't heal yourself!") + return + + var/smack = TRUE + if(prob(60) && bless(target_mob, user)) + smack = FALSE + else if(iscarbon(target_mob)) + var/mob/living/carbon/carbon_target = target_mob + if(!istype(carbon_target.head, /obj/item/clothing/head/helmet)) + carbon_target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5, 60) + carbon_target.balloon_alert(carbon_target, "you feel dumber!") + if(smack) + target_mob.visible_message(span_danger("[user] beats [target_mob] over the head with [src]!"), \ + span_userdanger("[user] beats [target_mob] over the head with [src]!")) + playsound(target_mob, SFX_PUNCH, 25, TRUE, -1) + log_combat(user, target_mob, "attacked", src) + +/obj/item/book/bible/afterattack(atom/bible_smacked, mob/user, proximity_flag, click_parameters) + . = ..() + if(!proximity_flag) + return + if(SEND_SIGNAL(bible_smacked, COMSIG_BIBLE_SMACKED, user, proximity_flag, click_parameters) & COMSIG_END_BIBLE_CHAIN) + return . | AFTERATTACK_PROCESSED_ITEM + if(isfloorturf(bible_smacked)) + if(user.mind?.holy_role) + var/area/current_area = get_area(bible_smacked) + if(!GLOB.chaplain_altars.len && istype(current_area, /area/station/service/chapel)) + make_new_altar(bible_smacked, user) + return + for(var/obj/effect/rune/nearby_runes in range(2, user)) + nearby_runes.invisibility = 0 + bible_smacked.balloon_alert(user, "floor smacked!") + + if(user.mind?.holy_role) + if(bible_smacked.reagents && bible_smacked.reagents.has_reagent(/datum/reagent/water)) // blesses all the water in the holder + . |= AFTERATTACK_PROCESSED_ITEM + bible_smacked.balloon_alert(user, "blessed") + var/water2holy = bible_smacked.reagents.get_reagent_amount(/datum/reagent/water) + bible_smacked.reagents.del_reagent(/datum/reagent/water) + bible_smacked.reagents.add_reagent(/datum/reagent/water/holywater,water2holy) + if(bible_smacked.reagents && bible_smacked.reagents.has_reagent(/datum/reagent/fuel/unholywater)) // yeah yeah, copy pasted code - sue me + . |= AFTERATTACK_PROCESSED_ITEM + bible_smacked.balloon_alert(user, "purified") + var/unholy2holy = bible_smacked.reagents.get_reagent_amount(/datum/reagent/fuel/unholywater) + bible_smacked.reagents.del_reagent(/datum/reagent/fuel/unholywater) + bible_smacked.reagents.add_reagent(/datum/reagent/water/holywater,unholy2holy) + if(istype(bible_smacked, /obj/item/book/bible) && !istype(bible_smacked, /obj/item/book/bible/syndicate)) + . |= AFTERATTACK_PROCESSED_ITEM + bible_smacked.balloon_alert(user, "converted") + var/obj/item/book/bible/other_bible = bible_smacked + other_bible.name = name + other_bible.icon_state = icon_state + other_bible.inhand_icon_state = inhand_icon_state + other_bible.deity_name = deity_name + + if(istype(bible_smacked, /obj/item/cult_bastard) && !IS_CULTIST(user)) + . |= AFTERATTACK_PROCESSED_ITEM + var/obj/item/cult_bastard/sword = bible_smacked + bible_smacked.balloon_alert(user, "exorcising...") + playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,TRUE) + if(do_after(user, 4 SECONDS, target = sword)) + playsound(src,'sound/effects/pray_chaplain.ogg',60,TRUE) + for(var/obj/item/soulstone/stone in sword.contents) + stone.required_role = null + for(var/mob/living/simple_animal/shade/shade in stone) + var/datum/antagonist/cult/cultist = shade.mind.has_antag_datum(/datum/antagonist/cult) + if(cultist) + cultist.silent = TRUE + cultist.on_removal() + shade.icon_state = "shade_holy" + shade.name = "Purified [shade.name]" + stone.release_shades(user) + qdel(stone) + new /obj/item/nullrod/claymore(get_turf(sword)) + user.visible_message(span_notice("[user] exorcises [sword]!")) + qdel(sword) + +/obj/item/book/bible/booze + desc = "To be applied to the head repeatedly." + +/obj/item/book/bible/booze/Initialize(mapload) + . = ..() + new /obj/item/reagent_containers/cup/glass/bottle/whiskey(src) + +/obj/item/book/bible/syndicate + name = "Syndicate Tome" + desc = "A very ominous tome resembling a bible." + icon_state ="ebook" + item_flags = NO_BLOOD_ON_ITEM + throw_speed = 2 + throw_range = 7 + throwforce = 18 + force = 18 + hitsound = 'sound/weapons/sear.ogg' + damtype = BURN + attack_verb_continuous = list("attacks", "burns", "blesses", "damns", "scorches", "curses", "smites") + attack_verb_simple = list("attack", "burn", "bless", "damn", "scorch", "curses", "smites") + deity_name = "The Syndicate" + var/uses = 1 + var/owner_name + +/obj/item/book/bible/syndicate/attack_self(mob/living/carbon/human/user, modifiers) + if(!uses || !istype(user)) + return + user.mind.holy_role = HOLY_ROLE_PRIEST + uses -= 1 + to_chat(user, span_userdanger("You try to open the book AND IT BITES YOU!")) + playsound(src.loc, 'sound/effects/snap.ogg', 50, TRUE) + var/active_hand_zone = (!(user.active_hand_index % RIGHT_HANDS) ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM) + user.apply_damage(5, BRUTE, active_hand_zone, attacking_item = src) + to_chat(user, span_notice("Your name appears on the inside cover, in blood.")) + owner_name = user.real_name + +/obj/item/book/bible/syndicate/examine(mob/user) + . = ..() + if(owner_name) + . += span_warning("The name [owner_name] is written in blood inside the cover.") + +/obj/item/book/bible/syndicate/attack(mob/living/target_mob, mob/living/carbon/human/user, params, heal_mode = TRUE) + if(!user.combat_mode) + return ..() + return ..(target_mob, user, heal_mode = FALSE) diff --git a/code/modules/library/book.dm b/code/modules/library/book.dm index 42578728554182..268a2cfb10f601 100644 --- a/code/modules/library/book.dm +++ b/code/modules/library/book.dm @@ -1,84 +1,9 @@ -//Some information about how html sanitization is handled -//All book info datums should store sanitized data. This cannot be worked around -//All inputs and outputs from the round (DB calls) need to use sanitized data -//All tgui menus should get unsanitized data, since jsx handles that on its own -//Everything else should use sanitized data. Yes including names, it's an xss vuln because of how chat works -///A datum which contains all the metadata of a book -/datum/book_info - ///The title of the book - var/title - ///The "author" of the book - var/author - ///The info inside the book - var/content - -/datum/book_info/New(_title, _author, _content) - title = _title - author = _author - content = _content - -/datum/book_info/proc/set_title(_title, trusted = FALSE) //Trusted should only be used for books read from the db, or in cases that we can be sure the info has already been sanitized - if(trusted) - title = _title - return - title = reject_bad_text(trim(html_encode(_title), 30)) - -/datum/book_info/proc/get_title(default="N/A") //Loads in an html decoded version of the title. Only use this for tgui menus, absolutely nothing else. - return html_decode(title) || "N/A" - -/datum/book_info/proc/set_author(_author, trusted = FALSE) - if(trusted) - author = _author - return - author = trim(html_encode(_author), MAX_NAME_LEN) - -/datum/book_info/proc/get_author(default="N/A") - return html_decode(author) || "N/A" - -/datum/book_info/proc/set_content(_content, trusted = FALSE) - if(trusted) - content = _content - return - content = trim(html_encode(_content), MAX_PAPER_LENGTH) - -/datum/book_info/proc/set_content_using_paper(obj/item/paper/paper) - // Just the paper's raw data. - var/raw_content = "" - for(var/datum/paper_input/text_input as anything in paper.raw_text_inputs) - raw_content += text_input.to_raw_html() - - content = trim(html_encode(raw_content), MAX_PAPER_LENGTH) - -/datum/book_info/proc/get_content(default="N/A") - return html_decode(content) || "N/A" - -///Returns a copy of the book_info datum -/datum/book_info/proc/return_copy() - var/datum/book_info/copycat = new(title, author, content) - return copycat - -///Modify an existing book_info datum to match your data -/datum/book_info/proc/copy_into(datum/book_info/copycat) - copycat.set_title(title, trusted = TRUE) - copycat.set_author(author, trusted = TRUE) - copycat.set_content(content, trusted = TRUE) - return copycat - -/datum/book_info/proc/compare(datum/book_info/cmp_with) - if(author != cmp_with.author) - return FALSE - if(title != cmp_with.title) - return FALSE - if(content != cmp_with.content) - return FALSE - return TRUE - /obj/item/book name = "book" + desc = "Crack it open, inhale the musk of its pages, and learn something new." icon = 'icons/obj/library.dmi' icon_state ="book" worn_icon_state = "book" - desc = "Crack it open, inhale the musk of its pages, and learn something new." throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_NORMAL //upped to three because books are, y'know, pretty big. (and you could hide them inside eachother recursively forever) @@ -87,22 +12,25 @@ resistance_flags = FLAMMABLE drop_sound = 'sound/items/handling/book_drop.ogg' pickup_sound = 'sound/items/handling/book_pickup.ogg' - ///Game time in 1/10th seconds + /// Maximum icon state number + var/maximum_book_state = 8 + /// Game time in 1/10th seconds var/due_date = 0 - ///false - Normal book, true - Should not be treated as normal book, unable to be copied, unable to be modified + /// false - Normal book, true - Should not be treated as normal book, unable to be copied, unable to be modified var/unique = FALSE + /// whether or not we have been carved out + var/carved = FALSE + /// Specific window size for the book, i.e: "1920x1080", Size x Width var/window_size = null - ///The initial title, for use in var editing and such + /// The initial title, for use in var editing and such var/starting_title - ///The initial author, for use in var editing and such + /// The initial author, for use in var editing and such var/starting_author - ///The initial bit of content, for use in var editing and such + /// The initial bit of content, for use in var editing and such var/starting_content - ///The packet of information that describes this book + /// The packet of information that describes this book var/datum/book_info/book_data - ///Maximum icon state number - var/maximum_book_state = 8 /obj/item/book/Initialize(mapload) . = ..() @@ -110,6 +38,11 @@ AddElement(/datum/element/falling_hazard, damage = 5, wound_bonus = 0, hardhat_safety = TRUE, crushes = FALSE, impact_sound = drop_sound) +/obj/item/book/examine(mob/user) + . = ..() + if(carved) + . += span_notice("[src] has been hollowed out.") + /obj/item/book/ui_static_data(mob/user) var/list/data = list() data["author"] = book_data.get_author() @@ -118,8 +51,11 @@ return data /obj/item/book/ui_interact(mob/living/user, datum/tgui/ui) + if(carved) + balloon_alert(user, "book is carved out!") + return if(!length(book_data.get_content())) - balloon_alert(user, "this book is blank!") + balloon_alert(user, "book is blank!") return if(istype(user) && !isnull(user.mind)) @@ -134,10 +70,6 @@ ui = new(user, src, "MarkdownViewer", name) ui.open() -/// Generates a random icon state for the book -/obj/item/book/proc/gen_random_icon_state() - icon_state = "book[rand(1, maximum_book_state)]" - /obj/item/book/attack_self(mob/user) if(user.is_blind()) to_chat(user, span_warning("You are blind and can't read anything!")) @@ -149,7 +81,7 @@ user.visible_message(span_notice("[user] opens a book titled \"[book_data.title]\" and begins reading intently.")) ui_interact(user) -/obj/item/book/attackby(obj/item/attacking_item, mob/user, params) +/obj/item/book/attackby(obj/item/attacking_item, mob/living/user, params) if(burn_paper_product_attackby_check(attacking_item, user)) return @@ -162,6 +94,9 @@ if(unique) to_chat(user, span_warning("These pages don't seem to take the ink well! Looks like you can't modify it.")) return + if(carved) + to_chat(user, span_warning("The book has been carved out! There is nothing to be vandalized.")) + return var/choice = tgui_input_list(usr, "What would you like to change?", "Book Alteration", list("Title", "Contents", "Author", "Cancel")) if(isnull(choice)) @@ -197,15 +132,12 @@ to_chat(user, span_warning("The name is invalid.")) return book_data.set_author(html_decode(author)) //Setting this encodes, don't want to double up - else - return - else if(istype(attacking_item, /obj/item/barcodescanner)) var/obj/item/barcodescanner/scanner = attacking_item var/obj/machinery/computer/libraryconsole/bookmanagement/computer = scanner.computer_ref?.resolve() if(!computer) to_chat(user, span_alert("[scanner]'s screen flashes: 'No associated computer found!'")) - return ..() + return scanner.book_data = book_data.return_copy() switch(scanner.mode) @@ -231,23 +163,35 @@ computer.inventory[ref(our_copy)] = our_copy computer.inventory_update() to_chat(user, span_notice("[scanner]'s screen flashes: 'Book stored in buffer. Title added to general inventory.'")) - - else if(((attacking_item.sharpness & SHARP_EDGED) || (attacking_item.tool_behaviour == TOOL_KNIFE) || (attacking_item.tool_behaviour == TOOL_WIRECUTTER)) && !(flags_1 & HOLOGRAM_1)) - to_chat(user, span_notice("You begin to carve out [book_data.title]...")) - if(do_after(user, 30, target = src)) - to_chat(user, span_notice("You carve out the pages from [book_data.title]! You didn't want to read it anyway.")) - var/obj/item/storage/book/carved_out = new - carved_out.name = src.name - carved_out.title = book_data.title - carved_out.icon_state = src.icon_state - if(user.is_holding(src)) - qdel(src) - user.put_in_hands(carved_out) - return - else - carved_out.forceMove(drop_location()) - qdel(src) - return + else if(try_carve(attacking_item, user, params)) return - else - return ..() + return ..() + +/// Generates a random icon state for the book +/obj/item/book/proc/gen_random_icon_state() + icon_state = "book[rand(1, maximum_book_state)]" + +/// Called when user attempts to carve the book with an item +/obj/item/book/proc/try_carve(obj/item/carving_item, mob/living/user, params) + if(carved) + return FALSE + if(!user.combat_mode) + return FALSE + if(!((carving_item.sharpness & SHARP_EDGED) && (carving_item.tool_behaviour != TOOL_KNIFE) && (carving_item.tool_behaviour != TOOL_WIRECUTTER))) + return FALSE + //i hate balloon alerts i hate them so god damn much + balloon_alert(user, "carving out...") + if(!do_after(user, 3 SECONDS, target = src)) + balloon_alert(user, "interrupted!") + return FALSE + carve_out(carving_item, user) + return TRUE + +/// Called when the book gets carved successfully +/obj/item/book/proc/carve_out(obj/item/carving_item, mob/living/user) + if(user) + balloon_alert(user, "carved out") + playsound(src, 'sound/effects/cloth_rip.ogg', vol = 75, vary = TRUE) + carved = TRUE + create_storage(max_slots = 1) + return TRUE diff --git a/code/modules/library/book_info.dm b/code/modules/library/book_info.dm new file mode 100644 index 00000000000000..8663069644d74f --- /dev/null +++ b/code/modules/library/book_info.dm @@ -0,0 +1,74 @@ +//Some information about how html sanitization is handled +//All book info datums should store sanitized data. This cannot be worked around +//All inputs and outputs from the round (DB calls) need to use sanitized data +//All tgui menus should get unsanitized data, since jsx handles that on its own +//Everything else should use sanitized data. Yes including names, it's an xss vuln because of how chat works +///A datum which contains all the metadata of a book +/datum/book_info + ///The title of the book + var/title + ///The "author" of the book + var/author + ///The info inside the book + var/content + +/datum/book_info/New(_title, _author, _content) + title = _title + author = _author + content = _content + +/datum/book_info/proc/set_title(_title, trusted = FALSE) //Trusted should only be used for books read from the db, or in cases that we can be sure the info has already been sanitized + if(trusted) + title = _title + return + title = reject_bad_text(trim(html_encode(_title), 30)) + +/datum/book_info/proc/get_title(default="N/A") //Loads in an html decoded version of the title. Only use this for tgui menus, absolutely nothing else. + return html_decode(title) || "N/A" + +/datum/book_info/proc/set_author(_author, trusted = FALSE) + if(trusted) + author = _author + return + author = trim(html_encode(_author), MAX_NAME_LEN) + +/datum/book_info/proc/get_author(default="N/A") + return html_decode(author) || "N/A" + +/datum/book_info/proc/set_content(_content, trusted = FALSE) + if(trusted) + content = _content + return + content = trim(html_encode(_content), MAX_PAPER_LENGTH) + +/datum/book_info/proc/set_content_using_paper(obj/item/paper/paper) + // Just the paper's raw data. + var/raw_content = "" + for(var/datum/paper_input/text_input as anything in paper.raw_text_inputs) + raw_content += text_input.to_raw_html() + + content = trim(html_encode(raw_content), MAX_PAPER_LENGTH) + +/datum/book_info/proc/get_content(default="N/A") + return html_decode(content) || "N/A" + +///Returns a copy of the book_info datum +/datum/book_info/proc/return_copy() + var/datum/book_info/copycat = new(title, author, content) + return copycat + +///Modify an existing book_info datum to match your data +/datum/book_info/proc/copy_into(datum/book_info/copycat) + copycat.set_title(title, trusted = TRUE) + copycat.set_author(author, trusted = TRUE) + copycat.set_content(content, trusted = TRUE) + return copycat + +/datum/book_info/proc/compare(datum/book_info/cmp_with) + if(author != cmp_with.author) + return FALSE + if(title != cmp_with.title) + return FALSE + if(content != cmp_with.content) + return FALSE + return TRUE diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index c24fba1709cf82..337b72a4c9da45 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -648,7 +648,7 @@ return TRUE /obj/machinery/computer/libraryconsole/bookmanagement/proc/print_bible() - var/obj/item/storage/book/bible/holy_book = new(loc) + var/obj/item/book/bible/holy_book = new(loc) if(!GLOB.bible_icon_state || !GLOB.bible_inhand_icon_state) return holy_book.icon_state = GLOB.bible_icon_state diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm index fc52a488b87f4b..3591a33deadb2e 100644 --- a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm +++ b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm @@ -178,7 +178,7 @@ new /obj/item/coin/silver(src) new /obj/item/shovel/spade(src) if(4) - new /obj/item/storage/book/bible/booze(src) + new /obj/item/book/bible/booze(src) if(5) new /obj/item/clothing/neck/stethoscope(src) new /obj/item/scalpel(src) diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 2ba3cf01e9872f..c3282967e64c44 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -41,9 +41,9 @@ var/atom/Tsec = drop_location() if(!no_bodyparts) if(no_organs)//so the organs don't get transfered inside the bodyparts we'll drop. - for(var/X in organs) - if(no_brain || !istype(X, /obj/item/organ/internal/brain)) - qdel(X) + for(var/organ in organs) + if(no_brain || !istype(organ, /obj/item/organ/internal/brain)) + qdel(organ) else //we're going to drop all bodyparts except chest, so the only organs that needs spilling are those inside it. for(var/obj/item/organ/organ as anything in organs) if(no_brain && istype(organ, /obj/item/organ/internal/brain)) @@ -71,6 +71,8 @@ for(var/obj/item/bodypart/part as anything in bodyparts) if(skip_head && part.body_zone == BODY_ZONE_HEAD) continue + else if(part.body_zone == BODY_ZONE_CHEST) + continue part.drop_limb() part.throw_at(get_edge_target_turf(src, pick(GLOB.alldirs)), rand(1,3), 5) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index d5503c422f1d1b..4916dc37c8cb45 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -355,6 +355,9 @@ //can't be put on fire! if((resistance_flags & FIRE_PROOF) || !(resistance_flags & FLAMMABLE)) return FALSE + //already on fire! + if(resistance_flags & ON_FIRE) + return FALSE var/ignition_message = attacking_item.ignition_effect(src, user) if(!ignition_message) return FALSE diff --git a/code/modules/uplink/uplink_items/device_tools.dm b/code/modules/uplink/uplink_items/device_tools.dm index b5012ab4f885ef..8e993aec4ee757 100644 --- a/code/modules/uplink/uplink_items/device_tools.dm +++ b/code/modules/uplink/uplink_items/device_tools.dm @@ -37,7 +37,7 @@ the seemingly magical books of a certain cult. Though lacking the esoteric abilities \ of the originals, these inferior copies are still quite useful, being able to provide \ both weal and woe on the battlefield, even if they do occasionally bite off a finger." - item = /obj/item/storage/book/bible/syndicate + item = /obj/item/book/bible/syndicate cost = 5 /datum/uplink_item/device_tools/tram_remote diff --git a/icons/ui_icons/achievements/achievements.dmi b/icons/ui_icons/achievements/achievements.dmi index 29a85c0b3d27f5fc6c6eef25396a8fd9c4aaecad..a20e0fbecff3df46e6176c6923a63307cbe5d228 100644 GIT binary patch delta 25378 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 a{X3+NTzu!7sHf}@@FORsELkdH;QxQ9{$oi1 delta 21839 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