mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-26 22:50:26 +01:00
[MIRROR] Bible refactor [MDB IGNORE] (#21190)
* Bible refactor * Delete book.dm * updatepaths * you're meaning to tell me i have to edit CODE?? --------- Co-authored-by: ChungusGamer666 <82850673+ChungusGamer666@users.noreply.github.com> Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com> Co-authored-by: Jolly-66 <70232195+Jolly-66@users.noreply.github.com>
This commit is contained in:
co-authored by
ChungusGamer666
Tom
Jolly-66
parent
71e0d530d3
commit
d3f2386664
@@ -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] <b>SMITE</b> 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)
|
||||
+57
-113
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user