mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-14 03:32:00 +00:00
## About The Pull Request  New sprites for the DRAGnet, coming alongside some functionaltiy changes. DRAGnets are now bulky, and do not fit in backpacks. They also cannot be dual-wielded. DRAGnet no longer have the trap snare functionality. You know, the infamous bola bullet. DRAGnets now have two functions; The first function is straight up a scatter disabler blast that does a total of 55 stamina damage point blank (it's like, 5 less than what it did before). The second function is a single bolt that, when it hits a living mob, dealing 30 damage and staggering it briefly slowing it down. It also places down a wide net of transportation fields around the target, much like the net functionality does on live (but that's attached to the scatter function, not the single bolt)  ### Misc Changes DRAGnets now cost more form cargo, at 3600 credits. (This barely matters for departmental orders) ## Why It's Good For The Game The sprite is ancient. Like nearing two decades old ancient. I believe the INTENTION was this thing  It didn't really work out that way.  Either way, the new sprite is cool and more unique in my opinion. Fitting its status as an energy weapon. As for balance changes; I've wanted to do this for a very long time but put it off a lot. I think this is about the most moderate approach I have. It otherwise functions pretty much as expected, maintaining the cool niche functionality while exorcising the problem bits; one-handed energy shotgun bit, and the bola shot bit. I think I've spent at least the last...four or so years hammering on about the horror that is this gun for balance? And even when it was seeing more widespread use from people who recognized how bullshit it really was, I didn't really want to get rid of the bit I actually quite liked, which was the teleportation field. I'm happy with this version. ## Changelog 🆑 NecromancerAnne (Code, Mild Sprite Edits) Michiyamenotehifunana (Sprites) image: Replaces the decrepit DRAGnet sprite with something newer and more interesting. balance: Completely reworks the DRAGnet. They are now bulky energy guns. balance: Snare is now a single shot bolt that deals 30 stamina force, staggers the target and lays out a net of teleportation fields that can transport anyone standing on them for too long to a DRAGnet beacon. balance: Net has been replaced with a scattershot disabler round. /🆑
309 lines
10 KiB
Plaintext
309 lines
10 KiB
Plaintext
/datum/fantasy_affix/cosmetic_suffixes
|
|
name = "purely cosmetic suffix"
|
|
placement = AFFIX_SUFFIX
|
|
alignment = AFFIX_GOOD | AFFIX_EVIL
|
|
|
|
var/list/goodSuffixes
|
|
var/list/badSuffixes
|
|
|
|
/datum/fantasy_affix/cosmetic_suffixes/New()
|
|
goodSuffixes = list(
|
|
"dexterity",
|
|
"constitution",
|
|
"intelligence",
|
|
"wisdom",
|
|
"charisma",
|
|
"the forest",
|
|
"the hills",
|
|
"the plains",
|
|
"the sea",
|
|
"the sun",
|
|
"the moon",
|
|
"the void",
|
|
"the world",
|
|
"many secrets",
|
|
"many tales",
|
|
"many colors",
|
|
"rending",
|
|
"sundering",
|
|
"the night",
|
|
"the day",
|
|
)
|
|
badSuffixes = list(
|
|
"draining",
|
|
"burden",
|
|
"discomfort",
|
|
"awkwardness",
|
|
"poor hygiene",
|
|
"timidity",
|
|
)
|
|
|
|
weight = (length(goodSuffixes) + length(badSuffixes)) * 10
|
|
|
|
/datum/fantasy_affix/cosmetic_suffixes/apply(datum/component/fantasy/comp, newName)
|
|
if(comp.quality > 0 || (comp.quality == 0 && prob(50)))
|
|
. = "[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
|
|
. = "[newName] of [pick(badSuffixes)]"
|
|
return .
|
|
|
|
//////////// Good suffixes
|
|
/datum/fantasy_affix/bane
|
|
name = "of <mobtype> slaying (random species, carbon or simple animal)"
|
|
placement = AFFIX_SUFFIX
|
|
alignment = AFFIX_GOOD
|
|
var/list/target_types_by_comp = list()
|
|
|
|
/datum/fantasy_affix/bane/apply(datum/component/fantasy/comp, newName)
|
|
. = ..()
|
|
// This is set up to be easy to add to these lists as I expect it will need modifications
|
|
var/static/list/possible_mobtypes
|
|
if(!possible_mobtypes)
|
|
// The base list of allowed mob/species types
|
|
possible_mobtypes = zebra_typecacheof(list(
|
|
/mob/living/simple_animal = TRUE,
|
|
/mob/living/carbon = TRUE,
|
|
/datum/species = TRUE,
|
|
// Some types to remove them and their subtypes
|
|
/mob/living/carbon/human/species = FALSE,
|
|
))
|
|
// Some particular types to disallow if they're too broad/abstract
|
|
// Not in the above typecache generator because it includes subtypes and this doesn't.
|
|
possible_mobtypes -= list(
|
|
/mob/living/simple_animal/hostile,
|
|
)
|
|
|
|
var/mob/picked_mobtype = pick(possible_mobtypes)
|
|
// This works even with the species picks since we're only accessing the name
|
|
|
|
var/obj/item/master = comp.parent
|
|
master.AddElement(/datum/element/bane, target_type = picked_mobtype)
|
|
target_types_by_comp[comp] = picked_mobtype
|
|
return "[newName] of [initial(picked_mobtype.name)] slaying"
|
|
|
|
/datum/fantasy_affix/bane/remove(datum/component/fantasy/comp)
|
|
var/picked_mobtype = target_types_by_comp[comp]
|
|
var/obj/item/master = comp.parent
|
|
master.RemoveElement(/datum/element/bane, picked_mobtype)
|
|
target_types_by_comp -= comp
|
|
|
|
/datum/fantasy_affix/summoning
|
|
name = "of <mobtype> summoning (dangerous, can pick all but megafauna tier stuff)"
|
|
placement = AFFIX_SUFFIX
|
|
alignment = AFFIX_GOOD
|
|
weight = 5
|
|
|
|
/datum/fantasy_affix/summoning/apply(datum/component/fantasy/comp, newName)
|
|
. = ..()
|
|
// This is set up to be easy to add to these lists as I expect it will need modifications
|
|
var/static/list/possible_mobtypes
|
|
if(isnull(possible_mobtypes))
|
|
possible_mobtypes = list()
|
|
var/list/mob_subtype_whitelist = list(
|
|
/mob/living/basic,
|
|
/mob/living/carbon,
|
|
/mob/living/simple_animal,
|
|
)
|
|
for(var/type in mob_subtype_whitelist)
|
|
possible_mobtypes += subtypesof(type)
|
|
|
|
var/list/mob_subtype_blacklist = list(
|
|
/mob/living/simple_animal/hostile/asteroid/elite,
|
|
/mob/living/simple_animal/hostile/megafauna,
|
|
)
|
|
for(var/type in mob_subtype_blacklist)
|
|
possible_mobtypes -= subtypesof(type)
|
|
|
|
possible_mobtypes -= GLOB.abstract_mob_types
|
|
|
|
var/mob/picked_mobtype = pick(possible_mobtypes)
|
|
var/obj/item/master = comp.parent
|
|
var/max_mobs = max(CEILING(comp.quality / 2, 1), 1)
|
|
var/spawn_delay = 30 SECONDS - (3 SECONDS * comp.quality)
|
|
comp.appliedComponents += master.AddComponent(\
|
|
/datum/component/summoning,\
|
|
mob_types = list(picked_mobtype),\
|
|
max_mobs = max_mobs,\
|
|
spawn_delay = spawn_delay,\
|
|
)
|
|
return "[newName] of [initial(picked_mobtype.name)] summoning"
|
|
|
|
/datum/fantasy_affix/shrapnel
|
|
name = "shrapnel"
|
|
placement = AFFIX_SUFFIX
|
|
alignment = AFFIX_GOOD
|
|
|
|
/datum/fantasy_affix/shrapnel/validate(obj/item/attached)
|
|
if(isgun(attached))
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/datum/fantasy_affix/shrapnel/apply(datum/component/fantasy/comp, newName)
|
|
. = ..()
|
|
// higher means more likely
|
|
var/list/weighted_projectile_types = list(/obj/projectile/meteor = 1,
|
|
/obj/projectile/energy/nuclear_particle = 1,
|
|
/obj/projectile/beam/pulse = 1,
|
|
/obj/projectile/bullet/honker = 15,
|
|
/obj/projectile/temp = 15,
|
|
/obj/projectile/ion = 15,
|
|
/obj/projectile/magic/door = 15,
|
|
/obj/projectile/magic/locker = 15,
|
|
/obj/projectile/magic/fetch = 15,
|
|
/obj/projectile/beam/emitter = 15,
|
|
/obj/projectile/magic/flying = 15,
|
|
/obj/projectile/bullet/incendiary/c9mm = 15,
|
|
/obj/projectile/temp/hot = 15,
|
|
/obj/projectile/beam/disabler = 15)
|
|
|
|
var/obj/projectile/picked_projectiletype = pick_weight(weighted_projectile_types)
|
|
|
|
var/obj/item/master = comp.parent
|
|
comp.appliedComponents += master.AddComponent(/datum/component/mirv, picked_projectiletype)
|
|
return "[newName] of [initial(picked_projectiletype.name)] shrapnel"
|
|
|
|
/datum/fantasy_affix/strength
|
|
name = "of strength (knockback)"
|
|
placement = AFFIX_SUFFIX
|
|
alignment = AFFIX_GOOD
|
|
|
|
/datum/fantasy_affix/strength/apply(datum/component/fantasy/comp, newName)
|
|
. = ..()
|
|
var/obj/item/master = comp.parent
|
|
master.AddElement(/datum/element/knockback, CEILING(comp.quality/2, 1), FLOOR(comp.quality/10, 1))
|
|
return "[newName] of strength"
|
|
|
|
/datum/fantasy_affix/strength/remove(datum/component/fantasy/comp)
|
|
var/obj/item/master = comp.parent
|
|
master.RemoveElement(/datum/element/knockback, CEILING(comp.quality/2, 1), FLOOR(comp.quality/10, 1))
|
|
|
|
//////////// Bad suffixes
|
|
|
|
/datum/fantasy_affix/fool
|
|
name = "of the fool (honking)"
|
|
placement = AFFIX_SUFFIX
|
|
alignment = AFFIX_EVIL
|
|
|
|
/datum/fantasy_affix/fool/apply(datum/component/fantasy/comp, newName)
|
|
. = ..()
|
|
var/obj/item/master = comp.parent
|
|
comp.appliedComponents += master.AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg' = 1), 50, falloff_exponent = 20)
|
|
return "[newName] of the fool"
|
|
|
|
/datum/fantasy_affix/curse_of_hunger
|
|
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 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)
|
|
. = ..()
|
|
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, "", comp)
|
|
comp.appliedComponents += master.AddComponent(/datum/component/curse_of_hunger)
|
|
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)
|
|
|
|
/datum/fantasy_affix/doot
|
|
name = "of dooting"
|
|
placement = AFFIX_SUFFIX
|
|
alignment = AFFIX_GOOD
|
|
weight = 1
|
|
|
|
/datum/fantasy_affix/doot/apply(datum/component/fantasy/comp, newName)
|
|
. = ..()
|
|
comp.parent.AddElement(/datum/element/spooky, too_spooky = comp.quality > 17, stam_damage_mult = comp.quality * 0.15)
|
|
return "[newName] of [pick("dooting", "spooks", "rattling", "the bones")]"
|
|
|
|
/datum/fantasy_affix/doot/remove(datum/component/fantasy/comp)
|
|
comp.parent.RemoveElement(/datum/element/spooky, too_spooky = comp.quality > 17, stam_damage_mult = comp.quality * 0.15)
|
|
|
|
// On hitting a mob their click cd is slowed marginally
|
|
/datum/fantasy_affix/windseeker
|
|
name = "of the Windseeker"
|
|
placement = AFFIX_SUFFIX
|
|
alignment = AFFIX_GOOD
|
|
weight = 3
|
|
|
|
/datum/fantasy_affix/windseeker/apply(datum/component/fantasy/comp, newName)
|
|
comp.parent.AddElement(/datum/element/slow_target_click_cd_attack, get_cd_penalty(comp))
|
|
return "[newName] of the Windseeker"
|
|
|
|
/datum/fantasy_affix/windseeker/remove(datum/component/fantasy/comp)
|
|
comp.parent.RemoveElement(/datum/element/slow_target_click_cd_attack, get_cd_penalty(comp))
|
|
|
|
/datum/fantasy_affix/windseeker/proc/get_cd_penalty(datum/component/fantasy/comp)
|
|
return min(round(sqrt(comp.quality) * 0.1, 0.1), 0.4) // this gives you a small number, like 0.2 seconds
|