[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
🆑
add: Expanded the RPG loot wizard event by giving various different
items their own statistic boost.
/🆑

---------

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>
This commit is contained in:
SkyratBot
2023-08-01 02:02:03 +02:00
committed by GitHub
parent 62ab5e77f4
commit 72b1a979ff
53 changed files with 681 additions and 54 deletions
@@ -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)
@@ -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
+2
View File
@@ -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
+1
View File
@@ -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`
@@ -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)
+24 -27
View File
@@ -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 = "<span class='danger'>"
effect_description = span_bold("mottled black glow")
location.visible_message("[span][originalName] is covered by a [effect_description] and then transforms into [parent]!</span>")
location.visible_message("[span]The [originalName] is covered by a [effect_description] and then transforms into [parent]!</span>")
@@ -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
+70 -7
View File
@@ -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)
+20
View File
@@ -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)
+5 -2
View File
@@ -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)
+17
View File
@@ -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))
+19
View File
@@ -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()
+60
View File
@@ -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)
+2 -1
View File
@@ -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))
+41 -1
View File
@@ -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)
+9
View File
@@ -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)
. = ..()
+12
View File
@@ -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)
@@ -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.
*
@@ -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
. = ..()
@@ -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(!.)
@@ -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(!.)
@@ -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(!.)
@@ -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)
@@ -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(!.)
+10 -1
View File
@@ -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
+9
View File
@@ -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
+8
View File
@@ -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)))
+23 -1
View File
@@ -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))
+3
View File
@@ -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
/**
@@ -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)
. = ..()
+1 -1
View File
@@ -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)
@@ -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
@@ -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, \
+1 -1
View File
@@ -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!"))
+8
View File
@@ -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 ..()
+8
View File
@@ -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)
@@ -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
+14
View File
@@ -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 ..()
+14
View File
@@ -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."
+23 -10
View File
@@ -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
+1
View File
@@ -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
+10
View File
@@ -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.
@@ -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
@@ -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)
. = ..()
@@ -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)
+11
View File
@@ -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)
@@ -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)
@@ -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))
@@ -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)
@@ -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)
@@ -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)
@@ -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)
+2
View File
@@ -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"