forked from tgstation/tgstation
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replaces the rpg loot datum with a component and makes some suffixes …
…have real effects (tgstation#44044) * Replaces the rpg loot datum with a component * Makes bane accept species types And cleans up some other code
- Loading branch information
1 parent
ec4a7dd
commit 66cab55
Showing
12 changed files
with
418 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#define AFFIX_PREFIX (1 << 0) | ||
#define AFFIX_SUFFIX (1 << 1) | ||
|
||
#define AFFIX_GOOD (1 << 0) | ||
#define AFFIX_EVIL (1 << 1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/datum/component/bane | ||
dupe_mode = COMPONENT_DUPE_ALLOWED | ||
|
||
var/mobtype | ||
var/speciestype | ||
var/damage_multiplier | ||
|
||
/datum/component/bane/Initialize(mobtype, damage_multiplier=1) | ||
if(!isitem(parent)) | ||
return COMPONENT_INCOMPATIBLE | ||
|
||
if(ispath(mobtype, /mob/living)) | ||
src.mobtype = mobtype | ||
else if(ispath(mobtype, /datum/species)) | ||
speciestype = mobtype | ||
else | ||
return COMPONENT_INCOMPATIBLE | ||
|
||
src.damage_multiplier = damage_multiplier | ||
|
||
/datum/component/bane/RegisterWithParent() | ||
if(speciestype) | ||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/speciesCheck) | ||
else | ||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/mobCheck) | ||
|
||
/datum/component/bane/UnregisterFromParent() | ||
UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK) | ||
|
||
/datum/component/bane/proc/speciesCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) | ||
if(!is_species(target, speciestype)) | ||
return | ||
activate(source, target, user) | ||
|
||
/datum/component/bane/proc/mobCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) | ||
if(!istype(target, mobtype)) | ||
return | ||
activate(source, target, user) | ||
|
||
/datum/component/bane/proc/activate(obj/item/source, mob/living/target, mob/attacker) | ||
if(attacker.a_intent != INTENT_HARM) | ||
return | ||
|
||
var/extra_damage = max(0, source.force * damage_multiplier) | ||
target.apply_damage(extra_damage, source.damtype, attacker.zone_selected) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/datum/component/fantasy | ||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS | ||
|
||
var/quality | ||
|
||
var/canFail | ||
var/announce | ||
|
||
var/originalName | ||
var/list/affixes | ||
var/list/appliedComponents | ||
|
||
var/static/list/affixListing | ||
|
||
/datum/component/fantasy/Initialize(quality, list/affixes = list(), canFail=FALSE, announce=FALSE) | ||
if(!isitem(parent)) | ||
return COMPONENT_INCOMPATIBLE | ||
|
||
src.quality = quality || randomQuality() | ||
src.canFail = canFail | ||
src.announce = announce | ||
|
||
src.affixes = affixes | ||
appliedComponents = list() | ||
randomAffixes() | ||
|
||
/datum/component/fantasy/Destroy() | ||
unmodify() | ||
affixes = null | ||
return ..() | ||
|
||
/datum/component/fantasy/RegisterWithParent() | ||
var/obj/item/master = parent | ||
originalName = master.name | ||
modify() | ||
|
||
/datum/component/fantasy/UnregisterFromParent() | ||
unmodify() | ||
|
||
/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, list/arguments) | ||
unmodify() | ||
if(newComp) | ||
quality += newComp.quality | ||
canFail = newComp.canFail | ||
announce = newComp.announce | ||
else | ||
arguments.len = 5 // This is done to replicate what happens when an arglist smaller than the necessary arguments is given | ||
quality += arguments[1] | ||
canFail = arguments[4] || canFail | ||
announce = arguments[5] || announce | ||
modify() | ||
|
||
/datum/component/fantasy/proc/randomQuality() | ||
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 | ||
|
||
/datum/component/fantasy/proc/randomAffixes(force) | ||
if(!affixListing) | ||
affixListing = list() | ||
for(var/T in subtypesof(/datum/fantasy_affix)) | ||
var/datum/fantasy_affix/affix = new T | ||
affixListing[affix] = affix.weight | ||
|
||
var/usedSlots = NONE | ||
for(var/i in affixes) | ||
var/datum/fantasy_affix/affix = i | ||
usedSlots |= affix.placement | ||
|
||
var/alignment | ||
if(quality >= 0) | ||
alignment |= AFFIX_GOOD | ||
if(quality <= 0) | ||
alignment |= AFFIX_EVIL | ||
|
||
for(var/i in 1 to max(1, abs(quality))) // We want at least 1 affix applied | ||
var/datum/fantasy_affix/affix = pickweight(affixListing) | ||
if(affix.placement & usedSlots) | ||
continue | ||
if(!(affix.alignment & alignment)) | ||
continue | ||
affixes += affix | ||
usedSlots |= affix.placement | ||
|
||
/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.armor = master.armor.modifyAllRatings(quality) | ||
|
||
var/newName = originalName | ||
for(var/i in affixes) | ||
var/datum/fantasy_affix/affix = i | ||
newName = affix.apply(src, newName) | ||
|
||
if(quality != 0) | ||
newName = "[newName] [quality > 0 ? "+" : ""][quality]" | ||
|
||
if(canFail && prob((quality - 9)*10)) | ||
var/turf/place = get_turf(parent) | ||
place.visible_message("<span class='danger'>[parent] <span class='inathneq_large'>violently glows blue</span> for a while, then evaporates.</span>") | ||
master.burn() | ||
return | ||
else if(announce) | ||
announce() | ||
|
||
master.name = newName | ||
|
||
/datum/component/fantasy/proc/unmodify() | ||
var/obj/item/master = parent | ||
|
||
for(var/i in affixes) | ||
var/datum/fantasy_affix/affix = i | ||
affix.remove(src) | ||
for(var/i in appliedComponents) | ||
qdel(i) | ||
|
||
master.force = max(0, master.force - quality) | ||
master.throwforce = max(0, master.throwforce - quality) | ||
master.armor = master.armor.modifyAllRatings(-quality) | ||
|
||
master.name = originalName | ||
|
||
/datum/component/fantasy/proc/announce() | ||
var/turf/location = get_turf(parent) | ||
var/span | ||
var/effect_description | ||
if(quality >= 0) | ||
span = "<span class='notice'>" | ||
effect_description = "<span class='heavy_brass'>shimmering golden glow</span>" | ||
else | ||
span = "<span class='danger'>" | ||
effect_description = "<span class='umbra_emphasis'>mottled black glow</span>" | ||
|
||
location.visible_message("[span][originalName] is covered by a [effect_description] and then transforms into [parent]!</span>") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/datum/fantasy_affix | ||
var/placement // A bitflag of "slots" this affix takes up, for example pre/suffix | ||
var/alignment | ||
var/weight = 10 | ||
|
||
/datum/fantasy_affix/proc/apply(datum/component/fantasy/comp, newName) | ||
return newName | ||
|
||
/datum/fantasy_affix/proc/remove(datum/component/fantasy/comp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/datum/fantasy_affix/cosmetic_prefixes | ||
placement = AFFIX_PREFIX | ||
alignment = AFFIX_GOOD | AFFIX_EVIL | ||
|
||
var/list/goodPrefixes | ||
var/list/badPrefixes | ||
|
||
/datum/fantasy_affix/cosmetic_prefixes/New() | ||
goodPrefixes = list( | ||
"greater", | ||
"major", | ||
"blessed", | ||
"superior", | ||
"empowered", | ||
"honed", | ||
"true", | ||
"glorious", | ||
"robust", | ||
) | ||
badPrefixes = list( | ||
"lesser", | ||
"minor", | ||
"blighted", | ||
"inferior", | ||
"enfeebled", | ||
"rusted", | ||
"unsteady", | ||
"tragic", | ||
"gimped", | ||
"cursed", | ||
) | ||
|
||
weight = (length(goodPrefixes) + length(badPrefixes)) * 10 | ||
|
||
/datum/fantasy_affix/cosmetic_prefixes/apply(datum/component/fantasy/comp, newName) | ||
if(comp.quality > 0 || (comp.quality == 0 && prob(50))) | ||
return "[pick(goodPrefixes)] [newName]" | ||
else | ||
return "[pick(badPrefixes)] [newName]" | ||
|
||
/datum/fantasy_affix/tactical | ||
placement = AFFIX_PREFIX | ||
alignment = AFFIX_GOOD | ||
weight = 1 // Very powerful, no one should have such power | ||
|
||
/datum/fantasy_affix/tactical/apply(datum/component/fantasy/comp, newName) | ||
var/obj/item/master = comp.parent | ||
comp.appliedComponents += master.AddComponent(/datum/component/tactical) | ||
return "tactical [newName]" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/datum/fantasy_affix/cosmetic_suffixes | ||
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))) | ||
return "[newName] of [pick(goodSuffixes)]" | ||
else | ||
return "[newName] of [pick(badSuffixes)]" | ||
|
||
//////////// Good suffixes | ||
/datum/fantasy_affix/bane | ||
placement = AFFIX_SUFFIX | ||
alignment = AFFIX_GOOD | ||
weight = 20 | ||
|
||
/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 = typecacheof(list( | ||
/mob/living/simple_animal, | ||
/mob/living/carbon, | ||
/datum/species, | ||
)) | ||
// Some particular types to disallow if they're too broad/abstract | ||
possible_mobtypes -= list( | ||
/mob/living/simple_animal/hostile, | ||
) | ||
// Some types to remove them and their subtypes | ||
possible_mobtypes -= typecacheof(list( | ||
/mob/living/carbon/human/species, | ||
)) | ||
|
||
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 | ||
comp.appliedComponents += master.AddComponent(/datum/component/bane, picked_mobtype) | ||
return "[newName] of [initial(picked_mobtype.name)] slaying" | ||
|
||
/datum/fantasy_affix/strength | ||
placement = AFFIX_SUFFIX | ||
alignment = AFFIX_GOOD | ||
|
||
/datum/fantasy_affix/strength/apply(datum/component/fantasy/comp, newName) | ||
. = ..() | ||
var/obj/item/master = comp.parent | ||
comp.appliedComponents += master.AddComponent(/datum/component/knockback, CEILING(comp.quality/2, 1)) | ||
return "[newName] of strength" | ||
|
||
//////////// Bad suffixes | ||
|
||
/datum/fantasy_affix/fool | ||
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/bikehorn) | ||
return "[newName] of the fool" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/datum/component/knockback | ||
var/throw_distance | ||
|
||
/datum/component/knockback/Initialize(throw_distance=1) | ||
if(!isitem(parent)) | ||
return COMPONENT_INCOMPATIBLE | ||
|
||
src.throw_distance = throw_distance | ||
|
||
/datum/component/knockback/RegisterWithParent() | ||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/afterattack_react) | ||
|
||
/datum/component/knockback/UnregisterFromParent() | ||
UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK) | ||
|
||
/datum/component/knockback/proc/afterattack_react(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) | ||
if(!ismovableatom(target) || !proximity_flag) | ||
return | ||
var/obj/item/master = parent | ||
var/atom/movable/throwee = target | ||
var/atom/throw_target = get_edge_target_turf(throwee, get_dir(master, throwee)) | ||
throwee.safe_throw_at(throw_target, throw_distance, 1, user) |
Oops, something went wrong.