From 72b1a979ffbb4505b4e36e29f76323b010c84973 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Tue, 1 Aug 2023 02:02:03 +0200 Subject: [PATCH] [MIRROR] Improves the RPG loot wizard event. [MDB IGNORE] (#22800) * Improves the RPG loot wizard event. (#77218) ## About The Pull Request As the title says. Adds a bunch more stat changes to various different items and a somewhat simple way of modifying them whilst minimizing side-effects as much as possible. Added a new negative curse of polymorph suffix that can randomly polymorph you once you pick up the item. Curse of hunger items won't start on items that are not on a turf. Curse of polymorph will only activate when equipped. Bodyparts, two-handed melees, bags, guns and grenades, to name a few, have a bunch of type-specific stat changes depending on their quality. Some items won't gain fantasy suffixes during the RPG loot event, like stacks, chairs and paper, to make gamifying the stats a bit harder. I'm sure there'll still be other ways to game the event, but it's not that big of a deal since these are the easiest ways to game it. High level items also have a cool unusual effect aura ## Why It's Good For The Game Makes the RPG item event cooler. Right now, it's a bit lame since everything only gains force value and wound bonus on attack. This makes the statistic increases more type-based and make it interesting to use It's okay for some items to be powerful since this is a wizard event and a very impactful one too. By making the curse of hunger items not spawn on people, it'll also make it a less painful event too. ## Changelog :cl: add: Expanded the RPG loot wizard event by giving various different items their own statistic boost. /:cl: --------- Co-authored-by: Watermelon914 <3052169-Watermelon914@ users.noreply.gitlab.com> * Improves the RPG loot wizard event. --------- Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com> Co-authored-by: Watermelon914 <3052169-Watermelon914@ users.noreply.gitlab.com> --- code/__DEFINES/dcs/signals/signals_global.dm | 2 + code/__DEFINES/dcs/signals/signals_object.dm | 9 +++ code/__DEFINES/obj_flags.dm | 2 + code/controllers/subsystem/atoms.dm | 1 + code/datums/components/curse_of_polymorph.dm | 36 +++++++++ code/datums/components/fantasy/_fantasy.dm | 51 ++++++------ code/datums/components/fantasy/prefixes.dm | 1 - code/datums/components/fantasy/suffixes.dm | 77 +++++++++++++++++-- code/datums/components/slippery.dm | 20 +++++ code/datums/components/soul_stealer.dm | 7 +- code/datums/components/transforming.dm | 17 ++++ code/datums/components/twohanded.dm | 19 +++++ code/datums/components/unusual_effect.dm | 60 +++++++++++++++ code/datums/storage/storage.dm | 3 +- code/game/objects/items.dm | 42 +++++++++- code/game/objects/items/cards_ids.dm | 9 +++ code/game/objects/items/chainsaw.dm | 12 +++ code/game/objects/items/grenades/_grenade.dm | 23 ++++++ .../objects/items/grenades/chem_grenade.dm | 6 ++ .../objects/items/grenades/clusterbuster.dm | 8 ++ code/game/objects/items/grenades/flashbang.dm | 6 ++ code/game/objects/items/grenades/hypno.dm | 6 ++ code/game/objects/items/grenades/plastic.dm | 13 ++++ .../objects/items/grenades/spawnergrenade.dm | 6 ++ code/game/objects/items/handcuffs.dm | 11 ++- code/game/objects/items/melee/baton.dm | 9 +++ code/game/objects/items/mop.dm | 8 ++ code/game/objects/items/stacks/medical.dm | 24 +++++- code/game/objects/items/stacks/stack.dm | 3 + code/game/objects/items/storage/storage.dm | 22 ++++++ code/game/objects/items/trash.dm | 2 +- .../objects/structures/beds_chairs/chair.dm | 1 + .../antagonists/cult/cult_bastard_sword.dm | 2 +- code/modules/capture_the_flag/ctf_game.dm | 2 +- code/modules/clothing/clothing.dm | 8 ++ code/modules/clothing/gloves/_gloves.dm | 8 ++ code/modules/clothing/gloves/insulated.dm | 9 +++ code/modules/clothing/shoes/_shoes.dm | 14 ++++ code/modules/clothing/suits/armor.dm | 14 ++++ code/modules/events/wizard/rpgloot.dm | 33 +++++--- code/modules/paperwork/paper.dm | 1 + code/modules/projectiles/gun.dm | 10 +++ .../projectiles/guns/energy/beam_rifle.dm | 12 +++ .../guns/energy/kinetic_accelerator.dm | 8 ++ .../projectiles/guns/energy/recharge.dm | 8 ++ code/modules/projectiles/guns/magic.dm | 11 +++ .../projectiles/guns/special/chem_gun.dm | 11 +++ .../guns/special/grenade_launcher.dm | 8 ++ .../projectiles/guns/special/syringe_gun.dm | 8 ++ code/modules/reagents/reagent_containers.dm | 12 +++ code/modules/surgery/bodyparts/_bodyparts.dm | 17 ++++ .../unit_tests/modify_fantasy_variable.dm | 21 +++++ tgstation.dme | 2 + 53 files changed, 681 insertions(+), 54 deletions(-) create mode 100644 code/datums/components/curse_of_polymorph.dm create mode 100644 code/datums/components/unusual_effect.dm create mode 100644 code/modules/unit_tests/modify_fantasy_variable.dm diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm index 6b00f3bde89..4be04166d47 100644 --- a/code/__DEFINES/dcs/signals/signals_global.dm +++ b/code/__DEFINES/dcs/signals/signals_global.dm @@ -51,6 +51,8 @@ #define LINKED_UP (1<<0) /// an obj/item is created! (obj/item/created_item) #define COMSIG_GLOB_NEW_ITEM "!new_item" +/// called post /obj/item initialize (obj/item/created_item) +#define COMSIG_GLOB_ATOM_AFTER_POST_INIT "!atom_after_post_init" /// an obj/machinery is created! (obj/machinery/created_machine) #define COMSIG_GLOB_NEW_MACHINE "!new_machine" /// a client (re)connected, after all /client/New() checks have passed : (client/connected_client) diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 420147f0c1e..eff3b3b7f0c 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -133,6 +133,11 @@ ///from base of obj/item/on_outfit_equip(): (mob/equipper, visuals_only, slot) #define COMSIG_ITEM_EQUIPPED_AS_OUTFIT "item_equip_as_outfit" +///from base of obj/item/apply_fantasy_bonuses(): (bonus) +#define COMSIG_ITEM_APPLY_FANTASY_BONUSES "item_apply_fantasy_bonuses" +///from base of obj/item/remove_fantasy_bonuses(): (bonus) +#define COMSIG_ITEM_REMOVE_FANTASY_BONUSES "item_remove_fantasy_bonuses" + /// Sebt from obj/item/ui_action_click(): (mob/user, datum/action) #define COMSIG_ITEM_UI_ACTION_CLICK "item_action_click" /// Return to prevent the default behavior (attack_selfing) from ocurring. @@ -183,6 +188,10 @@ ///from [/obj/structure/closet/supplypod/proc/preOpen]: #define COMSIG_SUPPLYPOD_LANDED "supplypodgoboom" +/// from [/obj/item/stack/proc/can_merge]: (obj/item/stack/merge_with, in_hand) +#define COMSIG_STACK_CAN_MERGE "stack_can_merge" + #define CANCEL_STACK_MERGE (1<<0) + ///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 diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index 27384cd5f9d..be0da9a61ff 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -42,6 +42,8 @@ #define ITEM_HAS_CONTEXTUAL_SCREENTIPS (1 << 19) /// No blood overlay is allowed to appear on this item, and it cannot gain blood DNA forensics #define NO_BLOOD_ON_ITEM (1 << 20) +/// Whether this item should skip the /datum/component/fantasy applied on spawn on the RPG event. Used on things like stacks +#define SKIP_FANTASY_ON_SPAWN (1<<21) // Flags for the clothing_flags var on /obj/item/clothing diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index 9d639a703d9..933542746be 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -155,6 +155,7 @@ SUBSYSTEM_DEF(atoms) BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT else SEND_SIGNAL(A, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ATOM_AFTER_POST_INIT, A) var/atom/location = A.loc if(location) /// Sends a signal that the new atom `src`, has been created at `loc` diff --git a/code/datums/components/curse_of_polymorph.dm b/code/datums/components/curse_of_polymorph.dm new file mode 100644 index 00000000000..bbfb6c842e3 --- /dev/null +++ b/code/datums/components/curse_of_polymorph.dm @@ -0,0 +1,36 @@ +/** + * curse of polymorph component; + * + * Used as a rpgloot suffix and wizard spell! + */ +/datum/component/curse_of_polymorph + var/polymorph_type + +/datum/component/curse_of_polymorph/Initialize(polymorph_type) + . = ..() + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + src.polymorph_type = polymorph_type + +/datum/component/curse_of_polymorph/RegisterWithParent() + . = ..() + var/obj/item/cursed_item = parent + RegisterSignal(cursed_item, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip)) + +/datum/component/curse_of_polymorph/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, list( + COMSIG_ITEM_EQUIPPED, + )) + +///signal called from equipping parent +/datum/component/curse_of_polymorph/proc/on_equip(datum/source, mob/living/equipper, slot) + SIGNAL_HANDLER + var/obj/item/polymorpher_item = parent + // Items with no slot flags curse on pickup (because hand slot) + if(polymorpher_item.slot_flags && !(polymorpher_item.slot_flags & slot)) + return + ASYNC + equipper.dropItemToGround(polymorpher_item, TRUE) + equipper.wabbajack(polymorph_type) + diff --git a/code/datums/components/fantasy/_fantasy.dm b/code/datums/components/fantasy/_fantasy.dm index 164d97aefd4..31f969e6193 100644 --- a/code/datums/components/fantasy/_fantasy.dm +++ b/code/datums/components/fantasy/_fantasy.dm @@ -17,16 +17,18 @@ if(!isitem(parent)) return COMPONENT_INCOMPATIBLE - src.quality = quality || randomQuality() + src.quality = quality + if(isnull(src.quality)) + src.quality = random_quality() src.canFail = canFail src.announce = announce src.affixes = affixes appliedComponents = list() if(affixes && affixes.len) - setAffixes() + set_affixes() else - randomAffixes() + random_affixes() /datum/component/fantasy/Destroy() unmodify() @@ -37,6 +39,11 @@ var/obj/item/master = parent originalName = master.name modify() + RegisterSignal(parent, COMSIG_STACK_CAN_MERGE, PROC_REF(try_merge_stack)) + +/datum/component/fantasy/proc/try_merge_stack(obj/item/stack/to_merge, in_hand) + SIGNAL_HANDLER + return CANCEL_STACK_MERGE /datum/component/fantasy/UnregisterFromParent() unmodify() @@ -53,14 +60,20 @@ src.announce = announce || src.announce modify() -/datum/component/fantasy/proc/randomQuality() +/datum/component/fantasy/proc/random_quality() var/quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0) if(prob(50)) quality = -quality return quality ///proc on creation for random affixes -/datum/component/fantasy/proc/randomAffixes(force) +/datum/component/fantasy/proc/random_affixes(force) + var/alignment + if(quality >= 0) + alignment |= AFFIX_GOOD + if(quality <= 0) + alignment |= AFFIX_EVIL + if(!affixListing) affixListing = list() for(var/T in subtypesof(/datum/fantasy_affix)) @@ -72,12 +85,6 @@ return affixes = list() - var/alignment - if(quality >= 0) - alignment |= AFFIX_GOOD - if(quality <= 0) - alignment |= AFFIX_EVIL - var/usedSlots = NONE for(var/i in 1 to max(1, abs(quality))) // We want at least 1 affix applied var/datum/fantasy_affix/affix = pick_weight(affixListing) @@ -91,7 +98,7 @@ usedSlots |= affix.placement ///proc on creation for specific affixes given to the fantasy component -/datum/component/fantasy/proc/setAffixes(force) +/datum/component/fantasy/proc/set_affixes(force) var/usedSlots = NONE for(var/datum/fantasy_affix/affix in affixes) // We want at least 1 affix applied if((affix.placement & usedSlots) || (!affix.validate(parent))) @@ -101,12 +108,7 @@ /datum/component/fantasy/proc/modify() var/obj/item/master = parent - - master.force = max(0, master.force + quality) - master.throwforce = max(0, master.throwforce + quality) - master.set_armor(master.get_armor().generate_new_with_modifiers(list(ARMOR_ALL = quality))) - master.wound_bonus += quality - master.bare_wound_bonus += quality + master.apply_fantasy_bonuses(quality) var/newName = originalName for(var/i in affixes) @@ -121,10 +123,10 @@ place.visible_message(span_danger("[parent] [span_blue("violently glows blue")] for a while, then evaporates.")) master.burn() return - else if(announce) - announce() master.name = newName + if(announce) + announce() /datum/component/fantasy/proc/unmodify() var/obj/item/master = parent @@ -133,12 +135,7 @@ var/datum/fantasy_affix/affix = i affix.remove(src) QDEL_LIST(appliedComponents) - - master.force = max(0, master.force - quality) - master.throwforce = max(0, master.throwforce - quality) - master.set_armor(master.get_armor().generate_new_with_modifiers(list(ARMOR_ALL = -quality))) - master.wound_bonus -= quality - master.bare_wound_bonus -= quality + master.remove_fantasy_bonuses(quality) master.name = originalName @@ -153,4 +150,4 @@ span = "" effect_description = span_bold("mottled black glow") - location.visible_message("[span][originalName] is covered by a [effect_description] and then transforms into [parent]!") + location.visible_message("[span]The [originalName] is covered by a [effect_description] and then transforms into [parent]!") diff --git a/code/datums/components/fantasy/prefixes.dm b/code/datums/components/fantasy/prefixes.dm index 8ac9aa0cef8..cd80a114313 100644 --- a/code/datums/components/fantasy/prefixes.dm +++ b/code/datums/components/fantasy/prefixes.dm @@ -145,7 +145,6 @@ var/obj/item/master = comp.parent master.RemoveElement(/datum/element/venomous) - /datum/fantasy_affix/soul_stealer name = "soul-stealing" placement = AFFIX_PREFIX diff --git a/code/datums/components/fantasy/suffixes.dm b/code/datums/components/fantasy/suffixes.dm index 4e38d61b0d1..c8809efae49 100644 --- a/code/datums/components/fantasy/suffixes.dm +++ b/code/datums/components/fantasy/suffixes.dm @@ -42,9 +42,16 @@ /datum/fantasy_affix/cosmetic_suffixes/apply(datum/component/fantasy/comp, newName) if(comp.quality > 0 || (comp.quality == 0 && prob(50))) - return "[newName] of [pick(goodSuffixes)]" + . = "[newName] of [pick(goodSuffixes)]" + if(comp.quality >= 10) + START_PROCESSING(SSprocessing, src) + if(comp.quality >= 15) + comp.parent.AddComponent(/datum/component/unusual_effect, color = "#FFEA0030", include_particles = TRUE) + else + comp.parent.AddComponent(/datum/component/unusual_effect, color = "#FFBF0030") else - return "[newName] of [pick(badSuffixes)]" + . = "[newName] of [pick(badSuffixes)]" + return . //////////// Good suffixes /datum/fantasy_affix/bane @@ -189,11 +196,13 @@ name = "curse of hunger" placement = AFFIX_SUFFIX alignment = AFFIX_EVIL + weight = 5 /datum/fantasy_affix/curse_of_hunger/validate(obj/item/attached) - //curse of hunger that attaches onto food has the ability to eat itself. it's hilarious. - if(!IS_EDIBLE(attached)) - return TRUE + // Curse of hunger can be really unbearable to deal with, + // so it should not start on someone or in a bag. + if(!isturf(attached.loc)) + return FALSE return TRUE /datum/fantasy_affix/curse_of_hunger/apply(datum/component/fantasy/comp, newName) @@ -201,10 +210,64 @@ var/obj/item/master = comp.parent var/filter_color = "#8a0c0ca1" //clarified args var/new_name = pick(", eternally hungry", " of the glutton", " cursed with hunger", ", consumer of all", " of the feast") - master.AddElement(/datum/element/curse_announcement, "[master] is cursed with the curse of hunger!", filter_color, new_name, comp) + master.AddElement(/datum/element/curse_announcement, "[master] is cursed with the curse of hunger!", filter_color, "", comp) comp.appliedComponents += master.AddComponent(/datum/component/curse_of_hunger) - return newName //no spoilers! + return "[newName][new_name]" /datum/fantasy_affix/curse_of_hunger/remove(datum/component/fantasy/comp) var/obj/item/master = comp.parent master.RemoveElement(/datum/element/curse_announcement) //just in case + +/datum/fantasy_affix/curse_of_polymorph + name = "curse of polymorph" + placement = AFFIX_SUFFIX + alignment = AFFIX_EVIL + +/datum/fantasy_affix/curse_of_polymorph/validate(obj/item/attached) + // Don't start on someone so that it doesn't immediately polymorph them. + if(ismob(attached.loc)) + return FALSE + if(!isclothing(attached)) + return FALSE + return TRUE + +/datum/fantasy_affix/curse_of_polymorph/apply(datum/component/fantasy/comp, newName) + . = ..() + var/obj/item/master = comp.parent + var/filter_color = "#800080a1" //clarified args + var/new_name = pick(", transforming", " of the polymorph", " cursed with polymorphing", ", changer of all", " of changing") + var/static/list/possible_results = list( + WABBAJACK_MONKEY, + WABBAJACK_ROBOT, + WABBAJACK_SLIME, + WABBAJACK_XENO, + WABBAJACK_HUMAN, + WABBAJACK_ANIMAL, + ) + master.AddElement(/datum/element/curse_announcement, "[master] is cursed with the curse of polymorph!", filter_color, "", comp) + comp.appliedComponents += master.AddComponent(/datum/component/curse_of_polymorph, pick(possible_results)) + return "[newName][new_name]" + +/datum/fantasy_affix/curse_of_polymorph/remove(datum/component/fantasy/comp) + var/obj/item/master = comp.parent + master.RemoveElement(/datum/element/curse_announcement) //just in case + +/datum/fantasy_affix/speed + name = "of speed" + placement = AFFIX_SUFFIX + alignment = AFFIX_GOOD + +/datum/fantasy_affix/speed/validate(obj/item/attached) + if(!istype(attached, /obj/item/clothing/shoes)) + return FALSE + return TRUE + +/datum/fantasy_affix/speed/apply(datum/component/fantasy/comp, newName) + . = ..() + var/obj/item/master = comp.parent + master.slowdown = min(-comp.quality / 5, master.slowdown) + return "[newName] of speed" + +/datum/fantasy_affix/speed/remove(datum/component/fantasy/comp) + var/obj/item/master = comp.parent + master.slowdown = initial(master.slowdown) diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm index 5f1dd18bdfd..7288ae0e275 100644 --- a/code/datums/components/slippery.dm +++ b/code/datums/components/slippery.dm @@ -53,9 +53,29 @@ if(isitem(parent)) RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip)) RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop)) + RegisterSignal(parent, COMSIG_ITEM_APPLY_FANTASY_BONUSES, PROC_REF(apply_fantasy_bonuses)) + RegisterSignal(parent, COMSIG_ITEM_REMOVE_FANTASY_BONUSES, PROC_REF(remove_fantasy_bonuses)) else RegisterSignal(parent, COMSIG_ATOM_ENTERED, PROC_REF(Slip)) +/datum/component/slippery/proc/apply_fantasy_bonuses(obj/item/source, bonus) + SIGNAL_HANDLER + knockdown_time = source.modify_fantasy_variable("knockdown_time", knockdown_time, bonus) + if(bonus >= 5) + paralyze_time = source.modify_fantasy_variable("paralyze_time", paralyze_time, bonus) + LAZYSET(source.fantasy_modifications, "lube_flags", lube_flags) + lube_flags |= SLIDE + if(bonus >= 10) + lube_flags |= GALOSHES_DONT_HELP|SLIP_WHEN_CRAWLING + +/datum/component/slippery/proc/remove_fantasy_bonuses(obj/item/source, bonus) + SIGNAL_HANDLER + knockdown_time = source.reset_fantasy_variable("knockdown_time", knockdown_time) + paralyze_time = source.reset_fantasy_variable("paralyze_time", paralyze_time) + var/previous_lube_flags = LAZYACCESS(source.fantasy_modifications, "lube_flags") + if(!isnull(previous_lube_flags)) + lube_flags = previous_lube_flags + /datum/component/slippery/proc/add_connect_loc_behalf_to_parent() if(ismovable(parent)) AddComponent(/datum/component/connect_loc_behalf, parent, default_connections) diff --git a/code/datums/components/soul_stealer.dm b/code/datums/components/soul_stealer.dm index 5b3c39a59da..a69265421bb 100644 --- a/code/datums/components/soul_stealer.dm +++ b/code/datums/components/soul_stealer.dm @@ -5,13 +5,16 @@ * Used in the cult bastard sword! */ /datum/component/soul_stealer + var/obj/item/soulstone/soulstone_type /// List of soulstones captured by this item. var/list/obj/item/soulstone/soulstones = list() -/datum/component/soul_stealer/Initialize() +/datum/component/soul_stealer/Initialize(soulstone_type = /obj/item/soulstone/anybody/purified) if(!isitem(parent)) return COMPONENT_INCOMPATIBLE + src.soulstone_type = soulstone_type + /datum/component/soul_stealer/Destroy() QDEL_LIST(soulstones) // We own these, so we'll also just get rid of them. Any souls inside will die, this is fine. return ..() @@ -60,7 +63,7 @@ /datum/component/soul_stealer/proc/try_capture(mob/living/carbon/human/victim, mob/living/captor) if(victim.stat == CONSCIOUS) return - var/obj/item/soulstone/soulstone = new(parent) + var/obj/item/soulstone/soulstone = new soulstone_type(parent) soulstone.attack(victim, captor) if(!length(soulstone.contents)) // failed qdel(soulstone) diff --git a/code/datums/components/transforming.dm b/code/datums/components/transforming.dm index d704ca2098d..3c3fec196c2 100644 --- a/code/datums/components/transforming.dm +++ b/code/datums/components/transforming.dm @@ -89,6 +89,23 @@ RegisterSignal(parent, COMSIG_ITEM_SHARPEN_ACT, PROC_REF(on_sharpen)) RegisterSignal(parent, COMSIG_DETECTIVE_SCANNED, PROC_REF(on_scan)) + RegisterSignal(parent, COMSIG_ITEM_APPLY_FANTASY_BONUSES, PROC_REF(apply_fantasy_bonuses)) + RegisterSignal(parent, COMSIG_ITEM_REMOVE_FANTASY_BONUSES, PROC_REF(remove_fantasy_bonuses)) + +/datum/component/transforming/proc/apply_fantasy_bonuses(obj/item/source, bonus) + SIGNAL_HANDLER + active = FALSE + set_inactive(source) + force_on = source.modify_fantasy_variable("force_on", force_on, bonus) + throwforce_on = source.modify_fantasy_variable("throwforce_on", throwforce_on, bonus) + +/datum/component/transforming/proc/remove_fantasy_bonuses(obj/item/source, bonus) + SIGNAL_HANDLER + active = FALSE + set_inactive(source) + force_on = source.reset_fantasy_variable("force_on", force_on) + throwforce_on = source.reset_fantasy_variable("throwforce_on", throwforce_on) + /datum/component/transforming/UnregisterFromParent() UnregisterSignal(parent, list(COMSIG_ITEM_ATTACK_SELF, COMSIG_ITEM_SHARPEN_ACT, COMSIG_DETECTIVE_SCANNED)) diff --git a/code/datums/components/twohanded.dm b/code/datums/components/twohanded.dm index bb28c4eeb02..9b51d6830e5 100644 --- a/code/datums/components/twohanded.dm +++ b/code/datums/components/twohanded.dm @@ -92,6 +92,25 @@ RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON, PROC_REF(on_update_icon)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) RegisterSignal(parent, COMSIG_ITEM_SHARPEN_ACT, PROC_REF(on_sharpen)) + RegisterSignal(parent, COMSIG_ITEM_APPLY_FANTASY_BONUSES, PROC_REF(apply_fantasy_bonuses)) + RegisterSignal(parent, COMSIG_ITEM_REMOVE_FANTASY_BONUSES, PROC_REF(remove_fantasy_bonuses)) + +/datum/component/two_handed/proc/apply_fantasy_bonuses(obj/item/source, bonus) + SIGNAL_HANDLER + force_wielded = source.modify_fantasy_variable("force_wielded", force_wielded, bonus) + force_unwielded = source.modify_fantasy_variable("force_unwielded", force_unwielded, bonus) + if(wielded && ismob(source.loc)) + unwield(source.loc) + if(force_multiplier) + force_multiplier = source.modify_fantasy_variable("force_multiplier", force_multiplier, bonus/10, minimum = 1) + +/datum/component/two_handed/proc/remove_fantasy_bonuses(obj/item/source, bonus) + SIGNAL_HANDLER + force_wielded = source.reset_fantasy_variable("force_wielded", force_wielded) + force_unwielded = source.reset_fantasy_variable("force_unwielded", force_unwielded) + if(wielded && ismob(source.loc)) + unwield(source.loc) + force_multiplier = source.reset_fantasy_variable("force_multiplier", force_multiplier) // Remove all siginals registered to the parent item /datum/component/two_handed/UnregisterFromParent() diff --git a/code/datums/components/unusual_effect.dm b/code/datums/components/unusual_effect.dm new file mode 100644 index 00000000000..eb67b953799 --- /dev/null +++ b/code/datums/components/unusual_effect.dm @@ -0,0 +1,60 @@ + +/particles/unusual_effect + icon = 'icons/effects/particles/pollen.dmi' + icon_state = "pollen" + width = 100 + height = 100 + count = 1000 + spawning = 4 + lifespan = 0.7 SECONDS + fade = 1 SECONDS + grow = -0.01 + velocity = list(0, 0) + position = generator(GEN_CIRCLE, 0, 16, NORMAL_RAND) + drift = generator(GEN_VECTOR, list(0, -0.2), list(0, 0.2)) + gravity = list(0, 0.95) + scale = generator(GEN_VECTOR, list(0.3, 0.3), list(1,1), NORMAL_RAND) + rotation = 30 + spin = generator(GEN_NUM, -20, 20) + +/// Creates a cool looking effect on the movable. +/// In the future, this could be expanded to have more interesting particles and effects. +/datum/component/unusual_effect + dupe_mode = COMPONENT_DUPE_HIGHLANDER + + var/obj/effect/abstract/particle_holder/special_effects + + var/color + + COOLDOWN_DECLARE(glow_cooldown) + +/datum/component/unusual_effect/Initialize(color, include_particles = FALSE) + var/atom/movable/parent_movable = parent + if (!istype(parent_movable)) + return COMPONENT_INCOMPATIBLE + + src.color = color + parent_movable.add_filter("unusual_effect", 2, list("type" = "outline", "color" = color, "size" = 2)) + if(include_particles) + special_effects = new(parent_movable, /particles/unusual_effect) + START_PROCESSING(SSobj, src) + +/datum/component/unusual_effect/Destroy(force, silent) + var/atom/movable/parent_movable = parent + if (istype(parent_movable)) + parent_movable.remove_filter("unusual_effect") + STOP_PROCESSING(SSobj, src) + return ..() + +/datum/component/unusual_effect/process(seconds_per_tick) + var/atom/movable/parent_movable = parent + var/filter = parent_movable.get_filter("unusual_effect") + if (!filter) + parent_movable.add_filter("unusual_effect", 2, list("type" = "outline", "color" = color, "size" = 2)) + return + if(!COOLDOWN_FINISHED(src, glow_cooldown)) + return + + animate(filter, alpha = 110, time = 1.5 SECONDS, loop = -1) + animate(alpha = 40, time = 2.5 SECONDS) + COOLDOWN_START(src, glow_cooldown, 4 SECONDS) diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index a9f73840f14..a61a8725a30 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -343,7 +343,8 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) return FALSE if(locked > force) - user.balloon_alert(user, "closed!") + if(user && messages) + user.balloon_alert(user, "closed!") return FALSE if((to_insert == resolve_parent) || (to_insert == real_location)) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 681c4b7b077..767f215cbf6 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -223,8 +223,10 @@ var/uses_advanced_reskins = FALSE // SKYRAT EDIT ADDITION END -/obj/item/Initialize(mapload) + /// A lazylist used for applying fantasy values, contains the actual modification applied to a variable. + var/list/fantasy_modifications +/obj/item/Initialize(mapload) if(attack_verb_continuous) attack_verb_continuous = string_list(attack_verb_continuous) if(attack_verb_simple) @@ -1651,3 +1653,41 @@ /obj/item/update_atom_colour() . = ..() update_slot_icon() + +/// Modifies the fantasy variable +/obj/item/proc/modify_fantasy_variable(variable_key, value, bonus, minimum = 0) + if(LAZYACCESS(fantasy_modifications, variable_key) != null) + stack_trace("modify_fantasy_variable was called twice for the same key '[variable_key]' on type '[type]' before reset_fantasy_variable could be called!") + var/intended_target = value + bonus + value = max(minimum, intended_target) + + var/difference = intended_target - value + var/modified_amount = bonus - difference + LAZYSET(fantasy_modifications, variable_key, modified_amount) + return value + +/// Returns the original fantasy variable value +/obj/item/proc/reset_fantasy_variable(variable_key, current_value) + var/modification = LAZYACCESS(fantasy_modifications, variable_key) + LAZYREMOVE(fantasy_modifications, variable_key) + if(!modification) + return current_value + return current_value - modification + +/obj/item/proc/apply_fantasy_bonuses(bonus) + SHOULD_CALL_PARENT(TRUE) + SEND_SIGNAL(src, COMSIG_ITEM_APPLY_FANTASY_BONUSES, bonus) + force = modify_fantasy_variable("force", force, bonus) + throwforce = modify_fantasy_variable("throwforce", throwforce, bonus) + wound_bonus = modify_fantasy_variable("wound_bonus", wound_bonus, bonus) + bare_wound_bonus = modify_fantasy_variable("bare_wound_bonus", bare_wound_bonus, bonus) + toolspeed = modify_fantasy_variable("toolspeed", toolspeed, -bonus/10, minimum = 0.1) + +/obj/item/proc/remove_fantasy_bonuses(bonus) + SHOULD_CALL_PARENT(TRUE) + force = reset_fantasy_variable("force", force) + throwforce = reset_fantasy_variable("throwforce", throwforce) + wound_bonus = reset_fantasy_variable("wound_bonus", wound_bonus) + bare_wound_bonus = reset_fantasy_variable("bare_wound_bonus", bare_wound_bonus) + toolspeed = reset_fantasy_variable("toolspeed", toolspeed) + SEND_SIGNAL(src, COMSIG_ITEM_REMOVE_FANTASY_BONUSES, bonus) diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index a471046ca9c..e21109b5aeb 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -112,6 +112,15 @@ fire = 100 acid = 100 +/obj/item/card/id/apply_fantasy_bonuses(bonus) + . = ..() + if(bonus >= 15) + add_access(SSid_access.get_region_access_list(list(REGION_ALL_GLOBAL)), mode = FORCE_ADD_ALL) + else if(bonus >= 10) + add_access(SSid_access.get_region_access_list(list(REGION_ALL_STATION)), mode = FORCE_ADD_ALL) + else if(bonus <= -10) + clear_access() + /obj/item/card/id/Initialize(mapload) . = ..() diff --git a/code/game/objects/items/chainsaw.dm b/code/game/objects/items/chainsaw.dm index 20e3df19a14..e26f9aa2e99 100644 --- a/code/game/objects/items/chainsaw.dm +++ b/code/game/objects/items/chainsaw.dm @@ -27,6 +27,18 @@ ///The looping sound for our chainsaw when running var/datum/looping_sound/chainsaw/chainsaw_loop +/obj/item/chainsaw/apply_fantasy_bonuses(bonus) + . = ..() + force_on = modify_fantasy_variable("force_on", force_on, bonus) + if(on) + force = force_on + +/obj/item/chainsaw/remove_fantasy_bonuses(bonus) + force_on = reset_fantasy_variable("force_on", force_on) + if(on) + force = force_on + return ..() + /obj/item/chainsaw/Initialize(mapload) . = ..() chainsaw_loop = new(src) diff --git a/code/game/objects/items/grenades/_grenade.dm b/code/game/objects/items/grenades/_grenade.dm index fd25df13967..9fde5723f45 100644 --- a/code/game/objects/items/grenades/_grenade.dm +++ b/code/game/objects/items/grenades/_grenade.dm @@ -66,6 +66,29 @@ if(!QDELETED(src)) qdel(src) +/obj/item/grenade/apply_fantasy_bonuses(bonus) + . = ..() + apply_grenade_fantasy_bonuses(bonus) + +/obj/item/grenade/remove_fantasy_bonuses(bonus) + remove_grenade_fantasy_bonuses(bonus) + return ..() + +/obj/item/grenade/proc/apply_grenade_fantasy_bonuses(quality) + if(ex_dev == 0 && ex_heavy == 0 && ex_light == 0 && ex_flame == 0) + return + var/devIncrease = round(quality / 10) + var/heavyIncrease = round(quality / 5) + var/lightIncrease = round(quality / 2) + ex_dev = modify_fantasy_variable("ex_dev", ex_dev, devIncrease, 0) + ex_heavy = modify_fantasy_variable("ex_heavy", ex_heavy, heavyIncrease, 0) + ex_light = modify_fantasy_variable("ex_light", ex_light, lightIncrease, 0) + +/obj/item/grenade/proc/remove_grenade_fantasy_bonuses(quality) + ex_dev = reset_fantasy_variable("ex_dev", ex_dev) + ex_heavy = reset_fantasy_variable("ex_heavy", ex_heavy) + ex_light = reset_fantasy_variable("ex_light", ex_light) + /** * Checks for various ways to botch priming a grenade. * diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index 5eccf08d06e..49304446c0b 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -40,6 +40,12 @@ QDEL_LIST(beakers) return ..() +/obj/item/grenade/chem_grenade/apply_grenade_fantasy_bonuses(quality) + threatscale = modify_fantasy_variable("threatscale", threatscale, quality/10) + +/obj/item/grenade/chem_grenade/remove_grenade_fantasy_bonuses(quality) + threatscale = reset_fantasy_variable("threatscale", threatscale) + /obj/item/grenade/chem_grenade/examine(mob/user) display_timer = (stage == GRENADE_READY) //show/hide the timer based on assembly state . = ..() diff --git a/code/game/objects/items/grenades/clusterbuster.dm b/code/game/objects/items/grenades/clusterbuster.dm index a12c302c188..e4862919c1c 100644 --- a/code/game/objects/items/grenades/clusterbuster.dm +++ b/code/game/objects/items/grenades/clusterbuster.dm @@ -18,6 +18,14 @@ var/max_spawned = 8 var/segment_chance = 35 +/obj/item/grenade/clusterbuster/apply_grenade_fantasy_bonuses(quality) + min_spawned = modify_fantasy_variable("min_spawned", min_spawned, round(quality/2)) + max_spawned = modify_fantasy_variable("max_spawned", max_spawned, round(quality/2)) + +/obj/item/grenade/clusterbuster/remove_grenade_fantasy_bonuses(quality) + min_spawned = reset_fantasy_variable("min_spawned", min_spawned) + max_spawned = reset_fantasy_variable("max_spawned", max_spawned) + /obj/item/grenade/clusterbuster/detonate(mob/living/lanced_by) . = ..() if(!.) diff --git a/code/game/objects/items/grenades/flashbang.dm b/code/game/objects/items/grenades/flashbang.dm index 2b4899baa54..c66e6b396e4 100644 --- a/code/game/objects/items/grenades/flashbang.dm +++ b/code/game/objects/items/grenades/flashbang.dm @@ -6,6 +6,12 @@ righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' var/flashbang_range = 7 //how many tiles away the mob will be stunned. +/obj/item/grenade/flashbang/apply_grenade_fantasy_bonuses(quality) + flashbang_range = modify_fantasy_variable("flashbang_range", flashbang_range, quality) + +/obj/item/grenade/flashbang/remove_grenade_fantasy_bonuses(quality) + flashbang_range = reset_fantasy_variable("flashbang_range", flashbang_range) + /obj/item/grenade/flashbang/detonate(mob/living/lanced_by) . = ..() if(!.) diff --git a/code/game/objects/items/grenades/hypno.dm b/code/game/objects/items/grenades/hypno.dm index 035533d4731..0d7601df204 100644 --- a/code/game/objects/items/grenades/hypno.dm +++ b/code/game/objects/items/grenades/hypno.dm @@ -7,6 +7,12 @@ righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' var/flashbang_range = 7 +/obj/item/grenade/hypnotic/apply_grenade_fantasy_bonuses(quality) + flashbang_range = modify_fantasy_variable("flashbang_range", flashbang_range, quality) + +/obj/item/grenade/hypnotic/remove_grenade_fantasy_bonuses(quality) + flashbang_range = reset_fantasy_variable("flashbang_range", flashbang_range) + /obj/item/grenade/hypnotic/detonate(mob/living/lanced_by) . = ..() if(!.) diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm index b9f84691367..5902298032c 100644 --- a/code/game/objects/items/grenades/plastic.dm +++ b/code/game/objects/items/grenades/plastic.dm @@ -23,6 +23,19 @@ /// Maximum timer for c4 charges var/maximum_timer = 60000 +/obj/item/grenade/c4/apply_grenade_fantasy_bonuses(quality) + var/devIncrease = round(quality / 10) + var/heavyIncrease = round(quality / 5) + var/lightIncrease = round(quality / 2) + boom_sizes[1] = modify_fantasy_variable("devIncrease", boom_sizes[1], devIncrease) + boom_sizes[2] = modify_fantasy_variable("heavyIncrease", boom_sizes[2], heavyIncrease) + boom_sizes[3] = modify_fantasy_variable("lightIncrease", boom_sizes[3], lightIncrease) + +/obj/item/grenade/c4/remove_grenade_fantasy_bonuses(quality) + boom_sizes[1] = reset_fantasy_variable("devIncrease", boom_sizes[1]) + boom_sizes[2] = reset_fantasy_variable("heavyIncrease", boom_sizes[2]) + boom_sizes[3] = reset_fantasy_variable("lightIncrease", boom_sizes[3]) + /obj/item/grenade/c4/Initialize(mapload) . = ..() AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) diff --git a/code/game/objects/items/grenades/spawnergrenade.dm b/code/game/objects/items/grenades/spawnergrenade.dm index 3e8c81054f1..860812021e2 100644 --- a/code/game/objects/items/grenades/spawnergrenade.dm +++ b/code/game/objects/items/grenades/spawnergrenade.dm @@ -7,6 +7,12 @@ var/spawner_type = null // must be an object path var/deliveryamt = 1 // amount of type to deliver +/obj/item/grenade/spawnergrenade/apply_grenade_fantasy_bonuses(quality) + deliveryamt = modify_fantasy_variable("deliveryamt", deliveryamt, quality) + +/obj/item/grenade/spawnergrenade/remove_grenade_fantasy_bonuses(quality) + deliveryamt = reset_fantasy_variable("deliveryamt", deliveryamt) + /obj/item/grenade/spawnergrenade/detonate(mob/living/lanced_by) // Prime now just handles the two loops that query for people in lockers and people who can see it. . = ..() if(!.) diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 87e8d06db41..0266180a96d 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -46,6 +46,7 @@ throw_range = 5 custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 5) breakouttime = 1 MINUTES + var/handcuff_time = 3 SECONDS armor_type = /datum/armor/restraints_handcuffs custom_price = PAYCHECK_COMMAND * 0.35 ///Sound that plays when starting to put handcuffs on someone @@ -55,6 +56,14 @@ /// How strong the cuffs are. Weak cuffs can be broken with wirecutters or boxcutters. var/restraint_strength = HANDCUFFS_TYPE_STRONG +/obj/item/restraints/handcuffs/apply_fantasy_bonuses(bonus) + . = ..() + handcuff_time = modify_fantasy_variable("handcuff_time", handcuff_time, -bonus * 2, minimum = 0.3 SECONDS) + +/obj/item/restraints/handcuffs/remove_fantasy_bonuses(bonus) + handcuff_time = reset_fantasy_variable("handcuff_time", handcuff_time) + return ..() + /datum/armor/restraints_handcuffs fire = 50 acid = 50 @@ -78,7 +87,7 @@ to_chat(C, span_userdanger("As you feel someone grab your wrists, [src] start digging into your skin!")) playsound(loc, cuffsound, 30, TRUE, -2) log_combat(user, C, "attempted to handcuff") - if(do_after(user, 3 SECONDS, C, timed_action_flags = IGNORE_SLOWDOWNS) && C.canBeHandcuffed()) + if(do_after(user, handcuff_time, C, timed_action_flags = IGNORE_SLOWDOWNS) && C.canBeHandcuffed()) if(iscyborg(user)) apply_cuffs(C, user, TRUE) else diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm index ed842159d20..8a8635d879a 100644 --- a/code/game/objects/items/melee/baton.dm +++ b/code/game/objects/items/melee/baton.dm @@ -95,6 +95,15 @@ if(BATON_ATTACKING) finalize_baton_attack(target, user, modifiers) +/obj/item/melee/baton/apply_fantasy_bonuses(bonus) + . = ..() + stamina_damage = modify_fantasy_variable("stamina_damage", stamina_damage, bonus * 4) + + +/obj/item/melee/baton/remove_fantasy_bonuses(bonus) + stamina_damage = reset_fantasy_variable("stamina_damage", stamina_damage) + return ..() + /obj/item/melee/baton/add_item_context(datum/source, list/context, atom/target, mob/living/user) if (isturf(target)) return NONE diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm index 1599e8974b0..8a59c8c8326 100644 --- a/code/game/objects/items/mop.dm +++ b/code/game/objects/items/mop.dm @@ -25,6 +25,14 @@ /obj/structure/mop_bucket, )) +/obj/item/mop/apply_fantasy_bonuses(bonus) + . = ..() + mopspeed = modify_fantasy_variable("mopspeed", mopspeed, -bonus) + +/obj/item/mop/remove_fantasy_bonuses(bonus) + mopspeed = reset_fantasy_variable("mopspeed", mopspeed) + return ..() + /obj/item/mop/Initialize(mapload) . = ..() AddComponent(/datum/component/cleaner, mopspeed, pre_clean_callback=CALLBACK(src, PROC_REF(should_clean)), on_cleaned_callback=CALLBACK(src, PROC_REF(apply_reagents))) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index bd6deadbbb5..5113559cfd8 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -12,7 +12,7 @@ resistance_flags = FLAMMABLE max_integrity = 40 novariants = FALSE - item_flags = NOBLUDGEON + item_flags = NOBLUDGEON|SKIP_FANTASY_ON_SPAWN cost = 250 source = /datum/robot_energy_storage/medical merge_type = /obj/item/stack/medical @@ -37,6 +37,28 @@ . = ..() try_heal(patient, user) +/obj/item/stack/medical/apply_fantasy_bonuses(bonus) + . = ..() + if(heal_brute) + heal_brute = modify_fantasy_variable("heal_brute", heal_brute, bonus) + if(heal_burn) + heal_burn = modify_fantasy_variable("heal_burn", heal_burn, bonus) + if(stop_bleeding) + stop_bleeding = modify_fantasy_variable("stop_bleeding", stop_bleeding, bonus/10) + if(sanitization) + sanitization = modify_fantasy_variable("sanitization", sanitization, bonus/10) + if(flesh_regeneration) + flesh_regeneration = modify_fantasy_variable("flesh_regeneration", flesh_regeneration, bonus/10) + +/obj/item/stack/medical/remove_fantasy_bonuses(bonus) + heal_brute = reset_fantasy_variable("heal_brute", heal_brute) + heal_burn = reset_fantasy_variable("heal_burn", heal_burn) + stop_bleeding = reset_fantasy_variable("stop_bleeding", stop_bleeding) + sanitization = reset_fantasy_variable("sanitization", sanitization) + flesh_regeneration = reset_fantasy_variable("flesh_regeneration", flesh_regeneration) + return ..() + + /// In which we print the message that we're starting to heal someone, then we try healing them. Does the do_after whether or not it can actually succeed on a targeted mob /obj/item/stack/medical/proc/try_heal(mob/living/patient, mob/user, silent = FALSE) if(!patient.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE)) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 09096e1d656..3b72a282f22 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -20,6 +20,7 @@ gender = PLURAL material_modifier = 0.05 //5%, so that a 50 sheet stack has the effect of 5k materials instead of 100k. max_integrity = 100 + item_flags = SKIP_FANTASY_ON_SPAWN /// A list to all recipies this stack item can create. var/list/datum/stack_recipe/recipes /// What's the name of just 1 of this stack. You have a stack of leather, but one piece of leather @@ -579,6 +580,8 @@ var/obj/machinery/machine = loc if(!(src in machine.component_parts) || !(check in machine.component_parts)) return FALSE + if(SEND_SIGNAL(src, COMSIG_STACK_CAN_MERGE, check, inhand) & CANCEL_STACK_MERGE) + return FALSE return TRUE /** diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm index 0571d647cfd..8063778f413 100644 --- a/code/game/objects/items/storage/storage.dm +++ b/code/game/objects/items/storage/storage.dm @@ -10,6 +10,28 @@ /// What storage type to use for this item var/datum/storage/storage_type = /datum/storage +/obj/item/storage/apply_fantasy_bonuses(bonus) + . = ..() + atom_storage.max_slots = modify_fantasy_variable("max_slots", atom_storage.max_slots, round(bonus/2)) + atom_storage.max_total_storage = modify_fantasy_variable("max_total_storage", atom_storage.max_total_storage, round(bonus/2)) + LAZYSET(fantasy_modifications, "max_specific_storage", atom_storage.max_specific_storage) + if(bonus >= 15) + atom_storage.max_specific_storage = max(WEIGHT_CLASS_HUGE, atom_storage.max_specific_storage) + else if(bonus >= 10) + atom_storage.max_specific_storage = max(WEIGHT_CLASS_BULKY, atom_storage.max_specific_storage) + else if(bonus <= -10) + atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL + else if(bonus <= -15) + atom_storage.max_specific_storage = WEIGHT_CLASS_TINY + +/obj/item/storage/remove_fantasy_bonuses(bonus) + atom_storage.max_slots = reset_fantasy_variable("max_slots", atom_storage.max_slots) + atom_storage.max_total_storage = reset_fantasy_variable("max_total_storage", atom_storage.max_total_storage) + var/previous_max_storage = LAZYACCESS(fantasy_modifications, "max_specific_storage") + if(previous_max_storage) + atom_storage.max_specific_storage = previous_max_storage + return ..() + /obj/item/storage/Initialize(mapload) . = ..() diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm index 2f608eac844..7ce67bb360f 100644 --- a/code/game/objects/items/trash.dm +++ b/code/game/objects/items/trash.dm @@ -6,7 +6,7 @@ desc = "This is rubbish." w_class = WEIGHT_CLASS_TINY resistance_flags = FLAMMABLE - item_flags = NOBLUDGEON + item_flags = NOBLUDGEON|SKIP_FANTASY_ON_SPAWN /obj/item/trash/Initialize(mapload) var/turf/T = get_turf(src) diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index 89f8399ff21..b9c80fd7f6c 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -330,6 +330,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) hitsound = 'sound/items/trayhit1.ogg' hit_reaction_chance = 50 custom_materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT) + item_flags = SKIP_FANTASY_ON_SPAWN var/break_chance = 5 //Likely hood of smashing the chair. var/obj/structure/chair/origin_type = /obj/structure/chair diff --git a/code/modules/antagonists/cult/cult_bastard_sword.dm b/code/modules/antagonists/cult/cult_bastard_sword.dm index 29bbc15c32f..a30ffb1f5ee 100644 --- a/code/modules/antagonists/cult/cult_bastard_sword.dm +++ b/code/modules/antagonists/cult/cult_bastard_sword.dm @@ -33,7 +33,7 @@ set_light(4) AddComponent(/datum/component/butchering, 50, 80) AddComponent(/datum/component/two_handed, require_twohands = TRUE) - AddComponent(/datum/component/soul_stealer) + AddComponent(/datum/component/soul_stealer, soulstone_type = /obj/item/soulstone) AddComponent( \ /datum/component/spin2win, \ spin_cooldown_time = 25 SECONDS, \ diff --git a/code/modules/capture_the_flag/ctf_game.dm b/code/modules/capture_the_flag/ctf_game.dm index fc8cc0ceb15..3e8a3a6fd44 100644 --- a/code/modules/capture_the_flag/ctf_game.dm +++ b/code/modules/capture_the_flag/ctf_game.dm @@ -263,7 +263,7 @@ /obj/item/ctf_flag/attackby(obj/item/item, mob/user, params) if(!istype(item, /obj/item/ctf_flag)) return ..() - + var/obj/item/ctf_flag/flag = item if(flag.team != team) to_chat(user, span_userdanger("Take \the [initial(flag.name)] to your team's controller!")) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index ebb747022cc..ef1769bf029 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -534,3 +534,11 @@ BLIND // can't see anything to_chat(L, span_warning("The damaged threads on your [src.name] chafe!")) #undef MOTH_EATING_CLOTHING_DAMAGE + +/obj/item/clothing/apply_fantasy_bonuses(bonus) + . = ..() + set_armor(get_armor().generate_new_with_modifiers(list(ARMOR_ALL = bonus))) + +/obj/item/clothing/remove_fantasy_bonuses(bonus) + set_armor(get_armor().generate_new_with_modifiers(list(ARMOR_ALL = -bonus))) + return ..() diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index ff01d0ca1de..3f5503ca0ee 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -21,6 +21,14 @@ /// Used for handling bloody gloves leaving behind bloodstains on objects. Will be decremented whenever a bloodstain is left behind, and be incremented when the gloves become bloody. var/transfer_blood = 0 +/obj/item/clothing/gloves/apply_fantasy_bonuses(bonus) + . = ..() + siemens_coefficient = modify_fantasy_variable("siemens_coefficient", siemens_coefficient, -bonus / 10) + +/obj/item/clothing/gloves/remove_fantasy_bonuses(bonus) + siemens_coefficient = reset_fantasy_variable("siemens_coefficient", siemens_coefficient) + return ..() + /obj/item/clothing/gloves/wash(clean_types) . = ..() if((clean_types & CLEAN_TYPE_BLOOD) && transfer_blood > 0) diff --git a/code/modules/clothing/gloves/insulated.dm b/code/modules/clothing/gloves/insulated.dm index ffd4b98c0bc..99a1ed04355 100644 --- a/code/modules/clothing/gloves/insulated.dm +++ b/code/modules/clothing/gloves/insulated.dm @@ -15,6 +15,15 @@ cut_type = /obj/item/clothing/gloves/cut clothing_traits = list(TRAIT_CHUNKYFINGERS) +/obj/item/clothing/gloves/color/yellow/apply_fantasy_bonuses(bonus) + . = ..() + if(bonus >= 10) + detach_clothing_traits(TRAIT_CHUNKYFINGERS) + +/obj/item/clothing/gloves/color/yellow/remove_fantasy_bonuses(bonus) + attach_clothing_traits(TRAIT_CHUNKYFINGERS) + return ..() + /datum/armor/color_yellow bio = 50 diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index 13e9399718b..aa88961e3c4 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -292,3 +292,17 @@ // SKYRAT EDIT END to_chat(user, span_notice("You [tied ? "untie" : "tie"] the laces on [src].")) adjust_laces(tied ? SHOES_UNTIED : SHOES_TIED, user) + +/obj/item/clothing/shoes/apply_fantasy_bonuses(bonus) + . = ..() + slowdown = modify_fantasy_variable("slowdown", slowdown, -bonus * 0.1, 0) + if(ismob(loc)) + var/mob/wearer = loc + wearer.update_equipment_speed_mods() + +/obj/item/clothing/shoes/remove_fantasy_bonuses(bonus) + slowdown = reset_fantasy_variable("slowdown", slowdown) + if(ismob(loc)) + var/mob/wearer = loc + wearer.update_equipment_speed_mods() + return ..() diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index af0f22904d4..e2af151e49d 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -29,6 +29,20 @@ if(!allowed) allowed = GLOB.security_vest_allowed +/obj/item/clothing/suit/armor/apply_fantasy_bonuses(bonus) + . = ..() + slowdown = modify_fantasy_variable("slowdown", slowdown, -bonus * 0.1, 0) + if(ismob(loc)) + var/mob/wearer = loc + wearer.update_equipment_speed_mods() + +/obj/item/clothing/suit/armor/remove_fantasy_bonuses(bonus) + slowdown = reset_fantasy_variable("slowdown", slowdown) + if(ismob(loc)) + var/mob/wearer = loc + wearer.update_equipment_speed_mods() + return ..() + /obj/item/clothing/suit/armor/vest name = "armor vest" desc = "A slim Type I armored vest that provides decent protection against most types of damage." diff --git a/code/modules/events/wizard/rpgloot.dm b/code/modules/events/wizard/rpgloot.dm index e31f970fea8..443cc2ddea5 100644 --- a/code/modules/events/wizard/rpgloot.dm +++ b/code/modules/events/wizard/rpgloot.dm @@ -23,21 +23,28 @@ var/can_backfire = TRUE var/uses = 1 -/obj/item/upgradescroll/afterattack(obj/item/target, mob/user, proximity) +/obj/item/upgradescroll/apply_fantasy_bonuses(bonus) . = ..() - if(!proximity || !istype(target)) + if(bonus >= 15) + can_backfire = FALSE + upgrade_amount = modify_fantasy_variable("upgrade_amount", upgrade_amount, round(bonus / 4), minimum = 1) + +/obj/item/upgradescroll/remove_fantasy_bonuses(bonus) + upgrade_amount = reset_fantasy_variable("upgrade_amount", upgrade_amount) + can_backfire = TRUE + return ..() + + +/obj/item/upgradescroll/pre_attack(obj/item/target, mob/living/user) + . = ..() + if(. || !istype(target) || !user.combat_mode) return - - . |= AFTERATTACK_PROCESSED_ITEM - target.AddComponent(/datum/component/fantasy, upgrade_amount, null, null, can_backfire, TRUE) - uses -= 1 if(!uses) visible_message(span_warning("[src] vanishes, its magic completely consumed from the fortification.")) qdel(src) - - return . + return TRUE /obj/item/upgradescroll/unlimited name = "unlimited foolproof item fortification scroll" @@ -66,13 +73,16 @@ GLOBAL_DATUM(rpgloot_controller, /datum/rpgloot_controller) /datum/rpgloot_controller/New() . = ..() //second operation takes MUCH longer, so lets set up signals first. - RegisterSignal(SSdcs, COMSIG_GLOB_NEW_ITEM, PROC_REF(on_new_item_in_existence)) + RegisterSignal(SSdcs, COMSIG_GLOB_ATOM_AFTER_POST_INIT, PROC_REF(on_new_item_in_existence)) handle_current_items() ///signal sent by a new item being created. /datum/rpgloot_controller/proc/on_new_item_in_existence(datum/source, obj/item/created_item) SIGNAL_HANDLER - + if(!istype(created_item)) + return + if(created_item.item_flags & SKIP_FANTASY_ON_SPAWN) + return created_item.AddComponent(/datum/component/fantasy) /** @@ -91,6 +101,9 @@ GLOBAL_DATUM(rpgloot_controller, /datum/rpgloot_controller) fantasy_item.AddComponent(/datum/component/fantasy) + if(isnull(fantasy_item.loc)) + continue + if(istype(fantasy_item, /obj/item/storage)) var/obj/item/storage/storage_item = fantasy_item var/datum/storage/storage_component = storage_item.atom_storage diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index cc513076a96..82517f72494 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -29,6 +29,7 @@ pickup_sound = 'sound/items/handling/paper_pickup.ogg' grind_results = list(/datum/reagent/cellulose = 3) color = COLOR_WHITE + item_flags = SKIP_FANTASY_ON_SPAWN /// Lazylist of raw, unsanitised, unparsed text inputs that have been made to the paper. var/list/datum/paper_input/raw_text_inputs diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index fae2c411c3c..61e9b0bac49 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -92,6 +92,16 @@ QDEL_NULL(suppressed) return ..() +/obj/item/gun/apply_fantasy_bonuses(bonus) + . = ..() + fire_delay = modify_fantasy_variable("fire_delay", fire_delay, -bonus, 0) + projectile_damage_multiplier = modify_fantasy_variable("projectile_damage_multiplier", projectile_damage_multiplier, bonus/10, 0.1) + +/obj/item/gun/remove_fantasy_bonuses(bonus) + fire_delay = reset_fantasy_variable("fire_delay", fire_delay) + projectile_damage_multiplier = reset_fantasy_variable("projectile_damage_multiplier", projectile_damage_multiplier) + return ..() + /// Handles adding [the seclite mount component][/datum/component/seclite_attachable] to the gun. /// If the gun shouldn't have a seclight mount, override this with a return. /// Or, if a child of a gun with a seclite mount has slightly different behavior or icons, extend this. diff --git a/code/modules/projectiles/guns/energy/beam_rifle.dm b/code/modules/projectiles/guns/energy/beam_rifle.dm index b91484f3d67..702da95f701 100644 --- a/code/modules/projectiles/guns/energy/beam_rifle.dm +++ b/code/modules/projectiles/guns/energy/beam_rifle.dm @@ -74,6 +74,18 @@ var/mob/listeningTo +/obj/item/gun/energy/beam_rifle/apply_fantasy_bonuses(bonus) + . = ..() + delay = modify_fantasy_variable("delay", delay, -bonus * 2) + aiming_time = modify_fantasy_variable("aiming_time", aiming_time, -bonus * 2) + recoil = modify_fantasy_variable("aiming_time", aiming_time, round(-bonus / 2)) + +/obj/item/gun/energy/beam_rifle/remove_fantasy_bonuses(bonus) + delay = reset_fantasy_variable("delay", delay) + aiming_time = reset_fantasy_variable("aiming_time", aiming_time) + recoil = reset_fantasy_variable("recoil", recoil) + return ..() + /obj/item/gun/energy/beam_rifle/debug delay = 0 cell_type = /obj/item/stock_parts/cell/infinite diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 488b4f7ccee..bbb31e1c4c2 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -16,6 +16,14 @@ var/list/modkits = list() gun_flags = NOT_A_REAL_GUN +/obj/item/gun/energy/recharge/kinetic_accelerator/apply_fantasy_bonuses(bonus) + . = ..() + max_mod_capacity = modify_fantasy_variable("max_mod_capacity", max_mod_capacity, bonus * 10) + +/obj/item/gun/energy/recharge/kinetic_accelerator/remove_fantasy_bonuses(bonus) + max_mod_capacity = reset_fantasy_variable("max_mod_capacity", max_mod_capacity) + return ..() + /obj/item/gun/energy/recharge/kinetic_accelerator/Initialize(mapload) . = ..() diff --git a/code/modules/projectiles/guns/energy/recharge.dm b/code/modules/projectiles/guns/energy/recharge.dm index ae67135ea26..6644accd8a5 100644 --- a/code/modules/projectiles/guns/energy/recharge.dm +++ b/code/modules/projectiles/guns/energy/recharge.dm @@ -18,6 +18,14 @@ /// Do we recharge slower with more of our type? var/unique_frequency = FALSE +/obj/item/gun/energy/recharge/apply_fantasy_bonuses(bonus) + . = ..() + recharge_time = modify_fantasy_variable("recharge_time", recharge_time, -bonus, minimum = 0.2 SECONDS) + +/obj/item/gun/energy/recharge/remove_fantasy_bonuses(bonus) + recharge_time = reset_fantasy_variable("recharge_time", recharge_time) + return ..() + /obj/item/gun/energy/recharge/Initialize(mapload) . = ..() if(!holds_charge) diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm index 762e95544c5..94c1e7502a8 100644 --- a/code/modules/projectiles/guns/magic.dm +++ b/code/modules/projectiles/guns/magic.dm @@ -29,6 +29,17 @@ . = ..() RegisterSignal(src, COMSIG_ITEM_MAGICALLY_CHARGED, PROC_REF(on_magic_charge)) +/obj/item/gun/magic/apply_fantasy_bonuses(bonus) + . = ..() + recharge_rate = modify_fantasy_variable("recharge_rate", recharge_rate, -bonus, minimum = 1) + max_charges = modify_fantasy_variable("max_charges", max_charges, bonus) + charges = modify_fantasy_variable("charges", charges, bonus) + +/obj/item/gun/magic/remove_fantasy_bonuses(bonus) + recharge_rate = reset_fantasy_variable("recharge_rate", recharge_rate) + max_charges = reset_fantasy_variable("max_charges", max_charges) + charges = reset_fantasy_variable("charges", charges) + return ..() /obj/item/gun/magic/fire_sounds() var/frequency_to_use = sin((90/max_charges) * charges) diff --git a/code/modules/projectiles/guns/special/chem_gun.dm b/code/modules/projectiles/guns/special/chem_gun.dm index c902c8b19b6..b085a20026e 100644 --- a/code/modules/projectiles/guns/special/chem_gun.dm +++ b/code/modules/projectiles/guns/special/chem_gun.dm @@ -17,6 +17,17 @@ var/max_syringes = 4 var/last_synth = 0 +/obj/item/gun/chem/apply_fantasy_bonuses(bonus) + . = ..() + max_syringes = modify_fantasy_variable("max_syringes", max_syringes, bonus, minimum = 1) + time_per_syringe = modify_fantasy_variable("time_per_syringe", time_per_syringe, -bonus * 10) + +/obj/item/gun/chem/remove_fantasy_bonuses(bonus) + max_syringes = reset_fantasy_variable("max_syringes", max_syringes) + time_per_syringe = reset_fantasy_variable("time_per_syringe", time_per_syringe) + return ..() + + /obj/item/gun/chem/Initialize(mapload) . = ..() chambered = new /obj/item/ammo_casing/chemgun(src) diff --git a/code/modules/projectiles/guns/special/grenade_launcher.dm b/code/modules/projectiles/guns/special/grenade_launcher.dm index c23e1615053..e5ce8c51316 100644 --- a/code/modules/projectiles/guns/special/grenade_launcher.dm +++ b/code/modules/projectiles/guns/special/grenade_launcher.dm @@ -16,6 +16,14 @@ . = ..() . += "[grenades.len] / [max_grenades] grenades loaded." +/obj/item/gun/grenadelauncher/apply_fantasy_bonuses(bonus) + . = ..() + max_grenades = modify_fantasy_variable("max_syringes", max_grenades, bonus, minimum = 1) + +/obj/item/gun/grenadelauncher/remove_fantasy_bonuses(bonus) + max_grenades = reset_fantasy_variable("max_syringes", max_grenades) + return ..() + /obj/item/gun/grenadelauncher/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/grenade/c4)) diff --git a/code/modules/projectiles/guns/special/syringe_gun.dm b/code/modules/projectiles/guns/special/syringe_gun.dm index fdee3d450c7..aa6f0aec572 100644 --- a/code/modules/projectiles/guns/special/syringe_gun.dm +++ b/code/modules/projectiles/guns/special/syringe_gun.dm @@ -30,6 +30,14 @@ chambered = new /obj/item/ammo_casing/syringegun(src) recharge_newshot() +/obj/item/gun/syringe/apply_fantasy_bonuses(bonus) + . = ..() + max_syringes = modify_fantasy_variable("max_syringes", max_syringes, bonus, minimum = 1) + +/obj/item/gun/syringe/remove_fantasy_bonuses(bonus) + max_syringes = reset_fantasy_variable("max_syringes", max_syringes) + return ..() + /obj/item/gun/syringe/handle_atom_del(atom/A) . = ..() if(A in syringes) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 131bad01510..acefe102256 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -38,6 +38,18 @@ /// The icon file to take fill icon appearances from var/fill_icon = 'icons/obj/medical/reagent_fillings.dmi' +/obj/item/reagent_containers/apply_fantasy_bonuses(bonus) + . = ..() + if(reagents) + reagents.maximum_volume = modify_fantasy_variable("maximum_volume", reagents.maximum_volume, bonus * 10, minimum = 5) + volume = modify_fantasy_variable("maximum_volume_beaker", volume, bonus * 10, minimum = 5) + +/obj/item/reagent_containers/remove_fantasy_bonuses(bonus) + if(reagents) + reagents.maximum_volume = reset_fantasy_variable("maximum_volume", reagents.maximum_volume) + volume = reset_fantasy_variable("maximum_volume_beaker", volume) + return ..() + /obj/item/reagent_containers/Initialize(mapload, vol) . = ..() if(isnum(vol) && vol > 0) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index be805f8a092..746f7921997 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -200,6 +200,23 @@ /// List of the above datums which have actually been instantiated, managed automatically var/list/feature_offsets = list() +/obj/item/bodypart/apply_fantasy_bonuses(bonus) + . = ..() + unarmed_damage_low = modify_fantasy_variable("unarmed_damage_low", unarmed_damage_low, bonus, minimum = 1) + unarmed_damage_high = modify_fantasy_variable("unarmed_damage_high", unarmed_damage_high, bonus, minimum = 1) + brute_modifier = modify_fantasy_variable("brute_modifier", brute_modifier, bonus * 0.02, minimum = 0.7) + burn_modifier = modify_fantasy_variable("burn_modifier", burn_modifier, bonus * 0.02, minimum = 0.7) + wound_resistance = modify_fantasy_variable("wound_resistance", wound_resistance, bonus) + +/obj/item/bodypart/remove_fantasy_bonuses(bonus) + unarmed_damage_low = reset_fantasy_variable("unarmed_damage_low", unarmed_damage_low) + unarmed_damage_high = reset_fantasy_variable("unarmed_damage_high", unarmed_damage_high) + brute_modifier = reset_fantasy_variable("brute_modifier", brute_modifier) + burn_modifier = reset_fantasy_variable("burn_modifier", burn_modifier) + wound_resistance = reset_fantasy_variable("wound_resistance", wound_resistance) + return ..() + + /obj/item/bodypart/Initialize(mapload) . = ..() if(can_be_disabled) diff --git a/code/modules/unit_tests/modify_fantasy_variable.dm b/code/modules/unit_tests/modify_fantasy_variable.dm new file mode 100644 index 00000000000..d78c1d1dac7 --- /dev/null +++ b/code/modules/unit_tests/modify_fantasy_variable.dm @@ -0,0 +1,21 @@ +// Unit test to make sure that there are no duplicate keys when modify_fantasy_variable is called when applying fantasy bonuses. +// Also to make sure the fantasy_modifications list is null when fantasy bonuses are removed. +/datum/unit_test/modify_fantasy_variable/Run() + + for(var/obj/item/path as anything in subtypesof(/obj/item)) + var/obj/item/object = allocate(path) + // Try positive + object.apply_fantasy_bonuses(bonus = 5) + object.remove_fantasy_bonuses(bonus = 5) + TEST_ASSERT_NULL(object.fantasy_modifications) + // Then negative + object.apply_fantasy_bonuses(bonus = -5) + object.remove_fantasy_bonuses(bonus = -5) + TEST_ASSERT_NULL(object.fantasy_modifications) + // Now try the extremes of each + object.apply_fantasy_bonuses(bonus = 500) + object.remove_fantasy_bonuses(bonus = 500) + TEST_ASSERT_NULL(object.fantasy_modifications) + object.apply_fantasy_bonuses(bonus = -500) + object.remove_fantasy_bonuses(bonus = -500) + TEST_ASSERT_NULL(object.fantasy_modifications) diff --git a/tgstation.dme b/tgstation.dme index aaa1760c12d..73f66c498ea 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1010,6 +1010,7 @@ #include "code\datums\components\creamed.dm" #include "code\datums\components\cult_ritual_item.dm" #include "code\datums\components\curse_of_hunger.dm" +#include "code\datums\components\curse_of_polymorph.dm" #include "code\datums\components\customizable_reagent_holder.dm" #include "code\datums\components\damage_aura.dm" #include "code\datums\components\deadchat_control.dm" @@ -1156,6 +1157,7 @@ #include "code\datums\components\udder.dm" #include "code\datums\components\unbreakable.dm" #include "code\datums\components\unobserved_actor.dm" +#include "code\datums\components\unusual_effect.dm" #include "code\datums\components\uplink.dm" #include "code\datums\components\usb_port.dm" #include "code\datums\components\vacuum.dm"