mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-12 02:32:10 +00:00
## About The Pull Request I wanted to add the ability to shove people with shields by right-clicking your target, just like how it works barehanded. This also required a solid refactor of disarm code, effectively bringing down the core of it to `mob/living` from `mob/living/carbon` or `mob/living/carbon/human`. This also means you can shove simple mobs inside closets, bins and on tables. Xenos and borgs are pretty much immune to regular disarms, but using a shield will work (borgs and royal xenos are immune to the knockdown). The riot shield armor has been balanced. It now tanks melee attacks pretty well, but will break against bullets in just about 2 to 4 hits depending on the bullet damage. I've always found the lack of sturdiness of the riot shields for what they're supposed to be good for a bit detrimental. Because I've refactored an item flag into a trait, I've had to add a new MOD module that grants protection from shove knockdown and staggering; found pre-installed in the administrative MODsuit, but I've also added it to the black market to make it cooler. You can bash people with the strobe shield on combat mode. ## Why It's Good For The Game Currently, shields are simply items that take a held slot in return of some block chance without being anything special, save for the strobe shield's integrated flash I guess, but are also a botherance as most crumple under the duress of less than half a dozen attacks. Meanwhile swords and other weapons with blok chance just don't care. TL;DR, I want them a bit more remarkable, and flexible as a tool. Of course, this ended up in a larger refactor because the right-click / disarm code was inconsistent. ## Changelog 🆑 add: Shields (and pillows) can be used to shove people around the same way barehanded right-clicking does. Xenos and borgs can actually be moved this way. add: Added a new MODsuit module, the bulwark module, which prevents knockdown and staggering from shoving, and getting pushed away by thrown objects. Inbuilt for the safeguard MODsuit, but one might also it in the black market. refactor: Disarming has been refactored. You can now shove simple critters onto tables and into bins and closets balance: Shields now take their own armor values and the armor penetration of the attack they blocked when damaged. This means shields are a bit sturdier now. balance: Riot shields can tank a lot more damage against melee weapons, but less against bullets. qol: strobe shields can now be used to bash people while combat mode is on. /🆑
100 lines
3.9 KiB
Plaintext
100 lines
3.9 KiB
Plaintext
/// Items with this component will have a chance to get knocked off
|
|
/// (unequipped and sent to the ground) when the wearer is disarmed or knocked down.
|
|
/datum/component/knockoff
|
|
/// Chance to knockoff when a knockoff action occurs.
|
|
var/knockoff_chance = 100
|
|
/// Used in being disarmed.
|
|
/// If set, we will only roll the knockoff chance if the disarmer is targeting one of these zones.
|
|
/// If unset, any disarm act will cause the knock-off chance to be rolled, no matter the zone targeted.
|
|
var/list/target_zones
|
|
/// Bitflag used in equip to determine what slots we need to be in to be knocked off.
|
|
/// If set, we must be equipped in one of the slots to have a chance of our item being knocked off.
|
|
/// If unset / NONE, a disarm or knockdown will have a chance of our item being knocked off regardless of slot, INCLUDING hand slots.
|
|
var/slots_knockoffable = NONE
|
|
|
|
/datum/component/knockoff/Initialize(knockoff_chance = 100, target_zones, slots_knockoffable = NONE)
|
|
if(!isitem(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.knockoff_chance = knockoff_chance
|
|
src.target_zones = target_zones
|
|
src.slots_knockoffable = slots_knockoffable
|
|
|
|
/datum/component/knockoff/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equipped))
|
|
RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_dropped))
|
|
|
|
/datum/component/knockoff/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
|
|
|
|
var/obj/item/item_parent = parent
|
|
if(ismob(item_parent.loc))
|
|
UnregisterSignal(item_parent.loc, list(COMSIG_LIVING_DISARM_HIT, COMSIG_LIVING_STATUS_KNOCKDOWN))
|
|
|
|
/// Signal proc for [COMSIG_LIVING_DISARM_HIT] on the mob who's equipped our parent
|
|
/// Rolls a chance for knockoff whenever we're disarmed
|
|
/datum/component/knockoff/proc/on_equipped_mob_disarm(mob/living/source, mob/living/attacker, zone, obj/item/weapon)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!istype(source))
|
|
return
|
|
|
|
if(target_zones && !(zone in target_zones))
|
|
return
|
|
if(!prob(knockoff_chance))
|
|
return
|
|
|
|
var/obj/item/item_parent = parent
|
|
if(!source.dropItemToGround(item_parent))
|
|
return
|
|
|
|
source.visible_message(
|
|
span_warning("[attacker] knocks off [source]'s [item_parent.name]!"),
|
|
span_userdanger("[attacker] knocks off your [item_parent.name]!"),
|
|
)
|
|
|
|
/// Signal proc for [COMSIG_LIVING_STATUS_KNOCKDOWN] on the mob who's equipped our parent
|
|
/// Rolls a chance for knockoff whenever we're knocked down
|
|
/datum/component/knockoff/proc/on_equipped_mob_knockdown(mob/living/carbon/human/source, amount)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!istype(source))
|
|
return
|
|
|
|
// Healing knockdown or setting knockdown to zero or something? Don't knock off.
|
|
if(amount <= 0)
|
|
return
|
|
if(!prob(knockoff_chance))
|
|
return
|
|
|
|
var/obj/item/item_parent = parent
|
|
if(!source.dropItemToGround(item_parent))
|
|
return
|
|
|
|
source.visible_message(
|
|
span_warning("[source]'s [item_parent.name] get[item_parent.p_s()] knocked off!"),
|
|
span_userdanger("Your [item_parent.name] [item_parent.p_were()] knocked off!"),
|
|
)
|
|
|
|
/// Signal proc for [COMSIG_ITEM_EQUIPPED]
|
|
/// Registers our signals which can cause a knockdown whenever we're equipped correctly
|
|
/datum/component/knockoff/proc/on_equipped(datum/source, mob/living/carbon/human/equipper, slot)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!istype(equipper))
|
|
return
|
|
|
|
if(slots_knockoffable && !(slot & slots_knockoffable))
|
|
UnregisterSignal(equipper, list(COMSIG_LIVING_DISARM_HIT, COMSIG_LIVING_STATUS_KNOCKDOWN))
|
|
return
|
|
|
|
RegisterSignal(equipper, COMSIG_LIVING_DISARM_HIT, PROC_REF(on_equipped_mob_disarm), TRUE)
|
|
RegisterSignal(equipper, COMSIG_LIVING_STATUS_KNOCKDOWN, PROC_REF(on_equipped_mob_knockdown), TRUE)
|
|
|
|
/// Signal proc for [COMSIG_ITEM_DROPPED]
|
|
/// Unregisters our signals which can cause a knockdown when we're unequipped (dropped)
|
|
/datum/component/knockoff/proc/on_dropped(datum/source, mob/living/dropper)
|
|
SIGNAL_HANDLER
|
|
|
|
UnregisterSignal(dropper, list(COMSIG_LIVING_DISARM_HIT, COMSIG_LIVING_STATUS_KNOCKDOWN))
|