From 8149f52777521e751ee9a6f8a790495f0a520ea5 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Mon, 18 Dec 2017 18:55:09 -0800 Subject: [PATCH] Adds jousting (#33531) --- code/__DEFINES/components.dm | 3 +- code/datums/components/jousting.dm | 81 ++++++++++++++++++++++++++++ code/game/objects/items.dm | 3 +- code/game/objects/items/twohanded.dm | 4 ++ tgstation.dme | 1 + 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 code/datums/components/jousting.dm diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 87c226b839..0b2a3e06d4 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -61,6 +61,8 @@ #define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user) #define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob) #define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob) +#define COMSIG_ITEM_EQUIPPED "item_equip" //from base of obj/item/equipped(): (/mob/equipper, slot) +#define COMSIG_ITEM_DROPPED "item_drop" //from base of obj/item/dropped(): (/mob/dropper) // /obj/item/clothing signals #define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): () @@ -77,7 +79,6 @@ #define COMSIG_MACHINE_PROCESS "machine_process" //from machinery subsystem fire(): () #define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): () - // /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) diff --git a/code/datums/components/jousting.dm b/code/datums/components/jousting.dm new file mode 100644 index 0000000000..68621e60ec --- /dev/null +++ b/code/datums/components/jousting.dm @@ -0,0 +1,81 @@ +/datum/component/jousting + var/current_direction = NONE + var/max_tile_charge = 5 + var/min_tile_charge = 2 //tiles before this code gets into effect. + var/current_tile_charge = 0 + var/movement_reset_tolerance = 2 //deciseconds + var/unmounted_damage_boost_per_tile = 0 + var/unmounted_knockdown_chance_per_tile = 0 + var/unmounted_knockdown_time = 0 + var/mounted_damage_boost_per_tile = 2 + var/mounted_knockdown_chance_per_tile = 20 + var/mounted_knockdown_time = 20 + var/requires_mob_riding = TRUE //whether this only works if the attacker is riding a mob, rather than anything they can buckle to. + var/requires_mount = TRUE //kinda defeats the point of jousting if you're not mounted but whatever. + var/mob/current_holder + var/datum/component/redirect/listener + var/current_timerid + +/datum/component/jousting/Initialize() + if(!isitem(parent)) + . = COMPONENT_INCOMPATIBLE + stack_trace("Warning: Jousting component incorrectly applied to invalid parent type [parent.type]") + RegisterSignal(COMSIG_ITEM_EQUIPPED, .proc/on_equip) + RegisterSignal(COMSIG_ITEM_DROPPED, .proc/on_drop) + RegisterSignal(COMSIG_ITEM_ATTACK, .proc/on_attack) + +/datum/component/jousting/Destroy() + QDEL_NULL(listener) + return ..() + +/datum/component/jousting/proc/on_equip(mob/user, slot) + QDEL_NULL(listener) + current_holder = user + listener = new(user, COMSIG_MOVABLE_MOVED, CALLBACK(src, .proc/mob_move)) + +/datum/component/jousting/proc/on_drop(mob/user) + QDEL_NULL(listener) + current_holder = null + current_direction = NONE + current_tile_charge = 0 + +/datum/component/jousting/proc/on_attack(mob/living/target, mob/user) + if(user != current_holder) + return + var/current = current_tile_charge + var/obj/item/I = parent + var/target_buckled = target.buckled ? TRUE : FALSE //we don't need the reference of what they're buckled to, just whether they are. + if((requires_mount && ((requires_mob_riding && !ismob(user.buckled)) || (!user.buckled))) || !current_direction || (current_tile_charge < min_tile_charge)) + return + var/turf/target_turf = get_step(user, current_direction) + if(target in range(1, target_turf)) + var/knockdown_chance = (target_buckled? mounted_knockdown_chance_per_tile : unmounted_knockdown_chance_per_tile) * current + var/knockdown_time = (target_buckled? mounted_knockdown_time : unmounted_knockdown_time) + var/damage = (target_buckled? mounted_damage_boost_per_tile : unmounted_damage_boost_per_tile) * current + var/sharp = I.is_sharp() + var/msg + if(damage) + msg += "[user] [sharp? "impales" : "slams into"] [target] [sharp? "on" : "with"] their [parent]" + target.apply_damage(damage, BRUTE, user.zone_selected, 0) + if(prob(knockdown_chance)) + msg += " and knocks [target] [target_buckled? "off of [target.buckled]" : "down"]" + if(target_buckled) + target.buckled.unbuckle_mob(target) + target.Knockdown(knockdown_time) + if(length(msg)) + user.visible_message("[msg]!") + +/datum/component/jousting/proc/mob_move(newloc, dir) + if(!current_holder || (requires_mount && ((requires_mob_riding && !ismob(current_holder.buckled)) || (!current_holder.buckled)))) + return + if(dir != current_direction) + current_tile_charge = 0 + current_direction = dir + if(current_tile_charge < max_tile_charge) + current_tile_charge++ + if(current_timerid) + deltimer(current_timerid) + current_timerid = addtimer(CALLBACK(src, .proc/reset_charge), movement_reset_tolerance, TIMER_STOPPABLE) + +/datum/component/jousting/proc/reset_charge() + current_tile_charge = 0 diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index a74b246282..d4e5240642 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -286,7 +286,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) if(!user.put_in_active_hand(src)) dropped(user) - /obj/item/attack_paw(mob/user) if(!user) return @@ -400,6 +399,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) return ITALICS | REDUCE_RANGE /obj/item/proc/dropped(mob/user) + SendSignal(COMSIG_ITEM_DROPPED, user) for(var/X in actions) var/datum/action/A = X A.Remove(user) @@ -431,6 +431,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) // for items that can be placed in multiple slots // note this isn't called during the initial dressing of a player /obj/item/proc/equipped(mob/user, slot) + SendSignal(COMSIG_ITEM_EQUIPPED, user, slot) for(var/X in actions) var/datum/action/A = X if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot. diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index c11d41eaa8..58758668c3 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -429,6 +429,10 @@ var/obj/item/grenade/explosive = null var/war_cry = "AAAAARGH!!!" +/obj/item/twohanded/spear/Initialize() + . = ..() + AddComponent(/datum/component/jousting) + /obj/item/twohanded/spear/examine(mob/user) ..() if(explosive) diff --git a/tgstation.dme b/tgstation.dme index 737f7e8274..01dbb29b04 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -345,6 +345,7 @@ #include "code\datums\components\chasm.dm" #include "code\datums\components\decal.dm" #include "code\datums\components\infective.dm" +#include "code\datums\components\jousting.dm" #include "code\datums\components\material_container.dm" #include "code\datums\components\ntnet_interface.dm" #include "code\datums\components\paintable.dm"