diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 0b2a3e06d4..4bb27d56d6 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -82,6 +82,7 @@ // /mob/living/carbon/human signals #define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target) #define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker) +#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted) #define CALTROP_BYPASS_SHOES 1 #define CALTROP_IGNORE_WALKERS 2 diff --git a/code/datums/components/knockoff.dm b/code/datums/components/knockoff.dm new file mode 100644 index 0000000000..35d1e5423e --- /dev/null +++ b/code/datums/components/knockoff.dm @@ -0,0 +1,53 @@ +//Items with these will have a chance to get knocked off when disarming +/datum/component/knockoff + var/knockoff_chance = 100 //Chance to knockoff + var/list/target_zones //Aiming for these zones will cause the knockoff, null means all zones allowed + var/list/slots_knockoffable //Can be only knocked off from these slots, null means all slots allowed + var/datum/component/redirect/disarm_redirect + +/datum/component/knockoff/Initialize(knockoff_chance,zone_override,slots_knockoffable) + if(!isitem(parent)) + . = COMPONENT_INCOMPATIBLE + CRASH("Knockoff component misuse") + RegisterSignal(COMSIG_ITEM_EQUIPPED,.proc/OnEquipped) + RegisterSignal(COMSIG_ITEM_DROPPED,.proc/OnDropped) + + src.knockoff_chance = knockoff_chance + + if(zone_override) + target_zones = zone_override + + if(slots_knockoffable) + src.slots_knockoffable = slots_knockoffable + +/datum/component/knockoff/proc/Knockoff(mob/living/attacker,zone) + var/obj/item/I = parent + var/mob/living/carbon/human/wearer = I.loc + if(!istype(wearer)) + return + if(target_zones && !(zone in target_zones)) + return + if(!prob(knockoff_chance)) + return + if(!wearer.dropItemToGround(I)) + return + + wearer.visible_message("[attacker] knocks off [wearer]'s [I.name]!","[attacker] knocks off your [I.name]!") + +/datum/component/knockoff/proc/OnEquipped(mob/living/carbon/human/H,slot) + if(!istype(H)) + return + if(slots_knockoffable && !(slot in slots_knockoffable)) + if(disarm_redirect) + QDEL_NULL(disarm_redirect) + return + if(!disarm_redirect) + disarm_redirect = H.AddComponent(/datum/component/redirect,list(COMSIG_HUMAN_DISARM_HIT),CALLBACK(src,.proc/Knockoff)) + +/datum/component/knockoff/proc/OnDropped(mob/living/M) + if(disarm_redirect) + QDEL_NULL(disarm_redirect) + +/datum/component/knockoff/Destroy() + QDEL_NULL(disarm_redirect) + . = ..() \ No newline at end of file diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index d4e5240642..823a91cead 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -406,6 +406,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) if(DROPDEL_1 & flags_1) qdel(src) in_inventory = FALSE + SendSignal(COMSIG_ITEM_DROPPED,user) // called just as an item is picked up (loc is not yet changed) /obj/item/proc/pickup(mob/user) @@ -436,6 +437,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/datum/action/A = X if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot. A.Grant(user) + SendSignal(COMSIG_ITEM_EQUIPPED,user,slot) in_inventory = TRUE //sometimes we only want to grant the item's action if it's equipped in a specific slot. diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 9c7c34510c..fd414b8d9a 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -129,6 +129,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM reagents.add_reagent_list(list_reagents) if(starts_lit) light() + AddComponent(/datum/component/knockoff,90,list("mouth"),list(slot_wear_mask))//90% to knock off when wearing a mask /obj/item/clothing/mask/cigarette/Destroy() STOP_PROCESSING(SSobj, src) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 0b02a2c711..a3ebf5ab2f 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1366,8 +1366,6 @@ GLOBAL_LIST_EMPTY(roundstart_races) else if(target.lying) target.forcesay(GLOB.hit_appends) - - /datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) var/aim_for_mouth = user.zone_selected == "mouth" var/target_on_help_and_unarmed = target.a_intent == INTENT_HELP && !target.get_active_held_item() @@ -1387,10 +1385,12 @@ GLOBAL_LIST_EMPTY(roundstart_races) return 1 else user.do_attack_animation(target, ATTACK_EFFECT_DISARM) - + if(target.w_uniform) target.w_uniform.add_fingerprint(user) - var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected)) + var/randomized_zone = ran_zone(user.zone_selected) + target.SendSignal(COMSIG_HUMAN_DISARM_HIT, user, user.zone_selected) + var/obj/item/bodypart/affecting = target.get_bodypart(randomized_zone) var/randn = rand(1, 100) if(randn <= 25) playsound(target, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) diff --git a/tgstation.dme b/tgstation.dme index 2852a1d295..7f9f4707e1 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -344,6 +344,7 @@ #include "code\datums\components\caltrop.dm" #include "code\datums\components\chasm.dm" #include "code\datums\components\decal.dm" +#include "code\datums\components\knockoff.dm" #include "code\datums\components\infective.dm" #include "code\datums\components\jousting.dm" #include "code\datums\components\material_container.dm"