diff --git a/code/__DEFINES/~darkpack/dcs/signals_mob/signals_mob_living.dm b/code/__DEFINES/~darkpack/dcs/signals_mob/signals_mob_living.dm index 3a96936550da..6facf61e8255 100644 --- a/code/__DEFINES/~darkpack/dcs/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/~darkpack/dcs/signals_mob/signals_mob_living.dm @@ -1,3 +1,6 @@ +///from base of /mob/living/proc/melee_swing() +#define COMSIG_LIVING_MELEE_SWING "mob_melee_swing" + #define COMSIG_LIVING_JUMP_PREP_TOGGLE "living_jump_prep_toggle" //from base of living/set_pull_offset(): (mob/living/pull_target, grab_state) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index b81f8ed1b206..8a7a8bb10d88 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -176,8 +176,13 @@ else if(LAZYACCESS(modifiers, RIGHT_CLICK)) ranged_secondary_attack(A, modifiers) + /* // DARKPACK EDIT REMOVAL - COMBAT else RangedAttack(A, modifiers) + */ + // DARKPACK EDIT ADD START - COMBAT + RangedAttack(A, modifiers) + // DARKPACK EDIT ADD END /// Is the atom obscured by a PREVENT_CLICK_UNDER_1 object above it /atom/proc/IsObscured() diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index 73542be9b0c4..08ca58518321 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -181,7 +181,13 @@ /mob/living/carbon/get_attacking_limb(atom/target, datum/martial_art/attacker_style) var/obj/item/organ/brain/brain = get_organ_slot(ORGAN_SLOT_BRAIN) - var/obj/item/bodypart/attacking_bodypart = attacker_style?.get_attacking_limb(src, target) || brain?.get_attacking_limb(target) || get_active_hand() + // DARKPACK EDIT CHANGE START - COMBAT + var/obj/item/bodypart/attacking_bodypart + if(ishuman(target)) + attacking_bodypart = attacker_style?.get_attacking_limb(src, target) || brain?.get_attacking_limb(target) || get_active_hand() + else + attacking_bodypart = get_active_hand() + // DARKPACK EDIT CHANGE END if(attacking_bodypart.unarmed_attack_effect == ATTACK_EFFECT_BITE) if(is_mouth_covered(ITEM_SLOT_MASK)) diff --git a/config/darkpack_config.txt b/config/darkpack_config.txt index bd565bc978fd..ba88ad8fcbca 100644 --- a/config/darkpack_config.txt +++ b/config/darkpack_config.txt @@ -54,3 +54,7 @@ LOG_STATS ## Bool for if roleplay only merits/quirks are enabled ROLEPLAY_ONLY_MERITS 1 + +## Configs for the type of attack we use when we click at a ranged distance. Only one can be enabled at a time. +#DIRECTIONAL_COMBAT +#SWING_COMBAT diff --git a/modular_darkpack/master_files/code/modules/mob/living/carbon/human/initialize.dm b/modular_darkpack/master_files/code/modules/mob/living/carbon/human/initialize.dm index 0ac4a2ff2f89..c176a5f1d004 100644 --- a/modular_darkpack/master_files/code/modules/mob/living/carbon/human/initialize.dm +++ b/modular_darkpack/master_files/code/modules/mob/living/carbon/human/initialize.dm @@ -4,4 +4,8 @@ //Initializes Jumping on the player AddComponent(/datum/component/jumper) AddComponent(/datum/component/violation_observer, violation_aoe) + if(CONFIG_GET(flag/swing_combat)) + AddElement(/datum/element/swing_attack) + else if(CONFIG_GET(flag/directional_combat)) + AddElement(/datum/element/directional_attack) update_visible_name() diff --git a/modular_darkpack/modules/combat/code/combat_config.dm b/modular_darkpack/modules/combat/code/combat_config.dm new file mode 100644 index 000000000000..2fa2a24db3ff --- /dev/null +++ b/modular_darkpack/modules/combat/code/combat_config.dm @@ -0,0 +1,9 @@ +/datum/config_entry/flag/directional_combat + +/datum/config_entry/flag/swing_combat + + +/datum/preference/toggle/ranged_click_to_melee + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + savefile_key = "ranged_click_to_melee" + savefile_identifier = PREFERENCE_PLAYER diff --git a/modular_darkpack/modules/combat/code/directional_attack.dm b/modular_darkpack/modules/combat/code/directional_attack.dm new file mode 100644 index 000000000000..c2c7f0f2555c --- /dev/null +++ b/modular_darkpack/modules/combat/code/directional_attack.dm @@ -0,0 +1,49 @@ +/*! + * This element allows the mob its attached to the ability to click an adjacent mob by clicking a distant atom + * that is in the general direction relative to the parent. + */ +/datum/element/directional_attack/Attach(datum/target) + . = ..() + if(!isliving(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_MOB_ATTACK_RANGED, PROC_REF(on_ranged_attack)) + +/datum/element/directional_attack/Detach(datum/source, ...) + . = ..() + UnregisterSignal(source, COMSIG_MOB_ATTACK_RANGED) + +/** + * This proc handles clicks on tiles that aren't adjacent to the source mob + * In addition to clicking the distant tile, it checks the tile in the direction and clicks the mob in the tile if there is one + * Arguments: + * * source - The mob clicking + * * clicked_atom - The atom being clicked (should be a distant one) + * * click_params - Miscellaneous click parameters, passed from Click itself + */ +/datum/element/directional_attack/proc/on_ranged_attack(mob/living/source, atom/clicked_atom, click_params) + SIGNAL_HANDLER + + if(!source.combat_mode) + return + + if(!source?.client?.prefs?.read_preference(/datum/preference/toggle/ranged_click_to_melee)) + return + + if(QDELETED(clicked_atom)) + return + + var/turf/turf_to_check = get_step(source, angle2dir(get_angle(source, clicked_atom))) + if(!turf_to_check || !source.Adjacent(turf_to_check)) + return + + var/mob/living/target_mob + for(target_mob in turf_to_check) + if(target_mob == source) + continue + if(!target_mob || target_mob.stat == DEAD) + continue + //This is here to undo the +1 the click on the distant turf adds so we can click the mob near us + source.next_click = world.time - 1 + INVOKE_ASYNC(source, TYPE_PROC_REF(/mob, ClickOn), target_mob, list2params(click_params)) + return diff --git a/modular_darkpack/modules/combat/code/swing.dm b/modular_darkpack/modules/combat/code/swing.dm new file mode 100644 index 000000000000..6e0a4bc94619 --- /dev/null +++ b/modular_darkpack/modules/combat/code/swing.dm @@ -0,0 +1,119 @@ +/mob/living/proc/melee_swing(visual_effect, atom/swung_item) + playsound(loc, 'modular_darkpack/modules/combat/sounds/swing.ogg', 50, TRUE) + var/atom/hit_target + var/turf/center_turf = get_step(src, dir) + var/turf/left_turf = get_step(center_turf, turn(dir, -90)) + var/turf/right_turf = get_step(center_turf, turn(dir, 90)) + + for(var/turf/swung_turf in list(center_turf, left_turf, right_turf)) + var/mob/living/living_on_turf = locate() in swung_turf + if(!living_on_turf) + continue + if(living_on_turf.stat == DEAD) + continue + hit_target = living_on_turf + break + /* // More likely then not, not acctually what your trying to click on. Revisit + if(!hit_target) + for(var/obj/swung_object in center_turf) + if(swung_object.obj_flags & CAN_BE_HIT) + hit_target = swung_object + break + */ + + if(!visual_effect) + visual_effect = get_swing_visual(hit_target, swung_item) + new visual_effect(get_turf(src), dir) + + // Originally this was in front of searching for turfs but SURELY you would want this after you get a target. Right? + SEND_SIGNAL(src, COMSIG_LIVING_MELEE_SWING, hit_target, center_turf, left_turf, right_turf) + + if(hit_target) + // changeNext_move(CLICK_CD_MELEE) + return hit_target + else + changeNext_move(CLICK_CD_RANGE) // Whiff punish (to avoid people spam clicking and the visuals looking dumb) + +/mob/living/proc/get_swing_visual(atom/target, atom/swung_item) + return /obj/effect/temp_visual/dir_setting/swing_effect + +// unarmed_attack_effect = ATTACK_EFFECT_CLAW + + +/mob/living/carbon/get_swing_visual(atom/target, atom/swung_item) + . = ..() + + if(!swung_item) + var/obj/item/bodypart/attacking_bodypart = get_attacking_limb(target) + if(attacking_bodypart?.unarmed_attack_effect == ATTACK_EFFECT_CLAW) + return /obj/effect/temp_visual/dir_setting/claw_effect + + +/obj/item/proc/can_swing() + // Technicly meant for no flavor text but is semi widly used as a "noncombat" weapon check + if(!(item_flags & NOBLUDGEON)) + return TRUE + +/obj/item/gun/can_swing() + return FALSE + + +/obj/effect/temp_visual/dir_setting/swing_effect + icon = 'modular_darkpack/modules/combat/icons/swing.dmi' + icon_state = "swing1" + pixel_w = -32 + pixel_z = -32 + duration = 0.3 SECONDS + +/obj/effect/temp_visual/dir_setting/claw_effect + icon = 'modular_darkpack/modules/combat/icons/swing.dmi' + icon_state = "claw1" + pixel_w = -32 + pixel_z = -32 + duration = 0.3 SECONDS + + +/*! + * This element allows the mob its attached to the ability to click an adjacent mob by clicking a distant atom + * that is in the general direction relative to the parent. + */ +/datum/element/swing_attack/Attach(datum/target) + . = ..() + if(!isliving(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_MOB_ATTACK_RANGED, PROC_REF(on_ranged_attack)) + +/datum/element/swing_attack/Detach(datum/source, ...) + . = ..() + UnregisterSignal(source, COMSIG_MOB_ATTACK_RANGED) + +/** + * This proc handles clicks on tiles that aren't adjacent to the source mob + * In addition to clicking the distant tile, it checks the tile in the direction and clicks the mob in the tile if there is one + * Arguments: + * * source - The mob clicking + * * clicked_atom - The atom being clicked (should be a distant one) + * * click_params - Miscellaneous click parameters, passed from Click itself + */ +/datum/element/swing_attack/proc/on_ranged_attack(mob/living/source, atom/clicked_atom, click_params) + SIGNAL_HANDLER + + if(!source.combat_mode) + return + + if(!source?.client?.prefs?.read_preference(/datum/preference/toggle/ranged_click_to_melee)) + return + + if(QDELETED(clicked_atom)) + return + + var/obj/item/held_item = source.get_active_held_item() + if(held_item && !held_item.can_swing()) + return + + var/atom/swing_result = source.melee_swing(swung_item = held_item) + if(swing_result?.IsReachableBy(source, held_item ? held_item.reach : 1)) + //This is here to undo the +1 the click on the distant turf adds so we can click the mob near us + source.next_click = world.time - 1 + INVOKE_ASYNC(source, TYPE_PROC_REF(/mob, ClickOn), swing_result, list2params(click_params)) diff --git a/modular_darkpack/modules/combat/icons/swing.dmi b/modular_darkpack/modules/combat/icons/swing.dmi new file mode 100644 index 000000000000..fabcdd2c54d1 Binary files /dev/null and b/modular_darkpack/modules/combat/icons/swing.dmi differ diff --git a/modular_darkpack/modules/deprecated/sounds/swing.ogg b/modular_darkpack/modules/combat/sounds/swing.ogg similarity index 100% rename from modular_darkpack/modules/deprecated/sounds/swing.ogg rename to modular_darkpack/modules/combat/sounds/swing.ogg diff --git a/tgstation.dme b/tgstation.dme index 7c0a3128bd57..c571b10bdf44 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -7145,6 +7145,9 @@ #include "modular_darkpack\modules\clothes\code\neck.dm" #include "modular_darkpack\modules\clothes\code\suit.dm" #include "modular_darkpack\modules\clothes\code\under.dm" +#include "modular_darkpack\modules\combat\code\combat_config.dm" +#include "modular_darkpack\modules\combat\code\directional_attack.dm" +#include "modular_darkpack\modules\combat\code\swing.dm" #include "modular_darkpack\modules\company_logos\code\company_logos.dm" #include "modular_darkpack\modules\company_logos\code\pentex.dm" #include "modular_darkpack\modules\curtains\code\curtains.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/darkpack_melee_combat.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/darkpack_melee_combat.tsx new file mode 100644 index 000000000000..b672e8ff389f --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/darkpack_melee_combat.tsx @@ -0,0 +1,10 @@ +import { CheckboxInput, type FeatureToggle } from '../base'; + +export const ranged_click_to_melee: FeatureToggle = { + name: 'Distant clicks trigger melee swings', + category: 'GAMEPLAY', + description: ` + Clicking on a tile out of your range creates a swing or directional attack. + `, + component: CheckboxInput, +};