diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index a88f40a19f..6607b91695 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -388,6 +388,23 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define BEAT_SLOW 2 #define BEAT_NONE 0 +//Mouse buttons pressed/held/released +#define RIGHT_CLICK "right" +#define MIDDLE_CLICK "middle" +#define LEFT_CLICK "left" + +//Keys held down during the mouse action +#define CTRL_CLICK "ctrl" +#define ALT_CLICK "alt" +#define SHIFT_CLICK "shift" + +//Pixel coordinates within the icon, in the icon's coordinate space +#define ICON_X "icon-x" +#define ICON_Y "icon-y" + +//Pixel coordinates in screen_loc format ("[tile_x]:[pixel_x],[tile_y]:[pixel_y]") +#define SCREEN_LOC "screen-loc" + //https://secure.byond.com/docs/ref/info.html#/atom/var/mouse_opacity #define MOUSE_OPACITY_TRANSPARENT 0 #define MOUSE_OPACITY_ICON 1 diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 151cd17540..73b2dd3006 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -678,6 +678,22 @@ Turf and target are separate in case you want to teleport some distance from a t if(!modifiers) return null + var/screen_loc = splittext(LAZYACCESS(modifiers, SCREEN_LOC), ",") + var/list/actual_view = getviewsize(viewing_client ? viewing_client.view : world.view) + var/click_turf_x = splittext(screen_loc[1], ":") + var/click_turf_y = splittext(screen_loc[2], ":") + var/click_turf_z = origin.z + + var/click_turf_px = text2num(click_turf_x[2]) + var/click_turf_py = text2num(click_turf_y[2]) + click_turf_x = origin.x + text2num(click_turf_x[1]) - round(actual_view[1] / 2) - 1 + click_turf_y = origin.y + text2num(click_turf_y[1]) - round(actual_view[2] / 2) - 1 + + var/turf/click_turf = locate(clamp(click_turf_x, 1, world.maxx), clamp(click_turf_y, 1, world.maxy), click_turf_z) + LAZYSET(modifiers, ICON_X, "[(click_turf_px - click_turf.pixel_x) + ((click_turf_x - click_turf.x) * world.icon_size)]") + LAZYSET(modifiers, ICON_Y, "[(click_turf_py - click_turf.pixel_y) + ((click_turf_y - click_turf.y) * world.icon_size)]") + return click_turf + //Finds the distance between two atoms, in pixels //centered = FALSE counts from turf edge to edge //centered = TRUE counts from turf center to turf center diff --git a/code/datums/components/fullauto.dm b/code/datums/components/fullauto.dm index fb94688cd8..1882d0b511 100644 --- a/code/datums/components/fullauto.dm +++ b/code/datums/components/fullauto.dm @@ -1,3 +1,4 @@ + #define AUTOFIRE_MOUSEUP 0 #define AUTOFIRE_MOUSEDOWN 1 @@ -11,34 +12,16 @@ var/autofire_shot_delay = 0.3 SECONDS //Time between individual shots. var/mouse_status = AUTOFIRE_MOUSEUP //This seems hacky but there can be two MouseDown() without a MouseUp() in between if the user holds click and uses alt+tab, printscreen or similar. - ///windup autofire vars - ///Whether the delay between shots increases over time, simulating a spooling weapon - var/windup_autofire = FALSE - ///the reduction to shot delay for windup - var/current_windup_reduction = 0 - ///the percentage of autfire_shot_delay that is added to current_windup_reduction - var/windup_autofire_reduction_multiplier = 0.3 - ///How high of a reduction that current_windup_reduction can reach - var/windup_autofire_cap = 0.3 - ///How long it takes for weapons that have spooled-up to reset back to the original firing speed - var/windup_spindown = 3 SECONDS - ///Timer for tracking the spindown reset timings - var/timerid COOLDOWN_DECLARE(next_shot_cd) -/datum/component/automatic_fire/Initialize(autofire_shot_delay, windup_autofire, windup_autofire_reduction_multiplier, windup_autofire_cap, windup_spindown) +/datum/component/automatic_fire/Initialize(_autofire_shot_delay) . = ..() if(!isgun(parent)) return COMPONENT_INCOMPATIBLE var/obj/item/gun = parent RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/wake_up) - if(autofire_shot_delay) - src.autofire_shot_delay = autofire_shot_delay - if(windup_autofire) - src.windup_autofire = windup_autofire - src.windup_autofire_reduction_multiplier = windup_autofire_reduction_multiplier - src.windup_autofire_cap = windup_autofire_cap - src.windup_spindown = windup_spindown + if(_autofire_shot_delay) + autofire_shot_delay = _autofire_shot_delay if(autofire_stat == AUTOFIRE_STAT_IDLE && ismob(gun.loc)) var/mob/user = gun.loc wake_up(src, user) @@ -79,9 +62,9 @@ shooter = clicker.mob RegisterSignal(clicker, COMSIG_CLIENT_MOUSEDOWN, .proc/on_mouse_down) if(!QDELETED(shooter)) - RegisterSignal(shooter, COMSIG_MOB_CLIENT_LOGOUT, .proc/autofire_off) - UnregisterSignal(shooter, COMSIG_MOB_CLIENT_LOGIN) - RegisterSignal(parent, list(COMSIG_PARENT_QDELETING, COMSIG_ITEM_DROPPED), .proc/autofire_off) + RegisterSignal(shooter, COMSIG_MOB_CLIENT_LOGOUT, .proc/autofire_off) + UnregisterSignal(shooter, COMSIG_MOB_CLIENT_LOGIN) + RegisterSignal(parent, list(COMSIG_PARENT_PREQDELETED, COMSIG_ITEM_DROPPED), .proc/autofire_off) parent.RegisterSignal(src, COMSIG_AUTOFIRE_ONMOUSEDOWN, /obj/item/gun/.proc/autofire_bypass_check) parent.RegisterSignal(parent, COMSIG_AUTOFIRE_SHOT, /obj/item/gun/.proc/do_autofire) @@ -100,9 +83,9 @@ mouse_status = AUTOFIRE_MOUSEUP //In regards to the component there's no click anymore to care about. clicker = null if(!QDELETED(shooter)) - RegisterSignal(shooter, COMSIG_MOB_CLIENT_LOGIN, .proc/on_client_login) - UnregisterSignal(shooter, COMSIG_MOB_CLIENT_LOGOUT) - UnregisterSignal(parent, list(COMSIG_PARENT_QDELETING, COMSIG_ITEM_DROPPED)) + RegisterSignal(shooter, COMSIG_MOB_CLIENT_LOGIN, .proc/on_client_login) + UnregisterSignal(shooter, COMSIG_MOB_CLIENT_LOGOUT) + UnregisterSignal(parent, list(COMSIG_PARENT_PREQDELETED, COMSIG_ITEM_DROPPED)) shooter = null parent.UnregisterSignal(parent, COMSIG_AUTOFIRE_SHOT) parent.UnregisterSignal(src, COMSIG_AUTOFIRE_ONMOUSEDOWN) @@ -115,18 +98,17 @@ autofire_on(source.client) /datum/component/automatic_fire/proc/on_mouse_down(client/source, atom/_target, turf/location, control, params) - SIGNAL_HANDLER var/list/modifiers = params2list(params) //If they're shift+clicking, for example, let's not have them accidentally shoot. - if(LAZYACCESS(modifiers, COMSIG_CLICK_SHIFT)) + if(LAZYACCESS(modifiers, SHIFT_CLICK)) return - if(LAZYACCESS(modifiers, COMSIG_CLICK_CTRL)) + if(LAZYACCESS(modifiers, CTRL_CLICK)) return - if(LAZYACCESS(modifiers, MOUSE_MIDDLE_BUTTON)) + if(LAZYACCESS(modifiers, MIDDLE_CLICK)) return - if(LAZYACCESS(modifiers, MOUSE_RIGHT_BUTTON)) + if(LAZYACCESS(modifiers, RIGHT_CLICK)) return - if(LAZYACCESS(modifiers, COMSIG_CLICK_ALT)) + if(LAZYACCESS(modifiers, ALT_CLICK)) return if(source.mob.in_throw_mode) return @@ -135,11 +117,10 @@ if(get_dist(source.mob, _target) < 2) //Adjacent clicking. return - if(isnull(location) || istype(_target, /atom/movable/screen)) //Clicking on a screen object. + if(isnull(location)) //Clicking on a screen object. if(_target.plane != CLICKCATCHER_PLANE) //The clickcatcher is a special case. We want the click to trigger then, under it. return //If we click and drag on our worn backpack, for example, we want it to open instead. - _target = parse_caught_click_modifiers(modifiers, get_turf(source.eye), source) - params = list2params(modifiers) + _target = params2turf(modifiers["screen-loc"], get_turf(source.eye), source) if(!_target) CRASH("Failed to get the turf under clickcatcher") @@ -156,7 +137,7 @@ target = _target target_loc = get_turf(target) mouse_parameters = params - INVOKE_ASYNC(src, .proc/start_autofiring) + start_autofiring() //Dakka-dakka @@ -218,8 +199,7 @@ SIGNAL_HANDLER if(isnull(over_location)) //This happens when the mouse is over an inventory or screen object, or on entering deep darkness, for example. var/list/modifiers = params2list(params) - var/new_target = parse_caught_click_modifiers(modifiers, get_turf(source.eye), source) - params = list2params(modifiers) + var/new_target = params2turf(modifiers["screen-loc"], get_turf(source.eye), source) mouse_parameters = params if(!new_target) if(QDELETED(target)) //No new target acquired, and old one was deleted, get us out of here. @@ -250,38 +230,23 @@ stop_autofiring() //Elvis has left the building. return FALSE shooter.face_atom(target) - var/next_delay = autofire_shot_delay - if(windup_autofire) - next_delay = clamp(next_delay - current_windup_reduction, round(autofire_shot_delay * windup_autofire_cap), autofire_shot_delay) - current_windup_reduction = (current_windup_reduction + round(autofire_shot_delay * windup_autofire_reduction_multiplier)) - timerid = addtimer(CALLBACK(src, .proc/windup_reset, FALSE), windup_spindown, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE) -/* - if(HAS_TRAIT(shooter, TRAIT_DOUBLE_TAP)) - next_delay = round(next_delay * 0.5) -*/ - COOLDOWN_START(src, next_shot_cd, next_delay) + COOLDOWN_START(src, next_shot_cd, autofire_shot_delay) if(SEND_SIGNAL(parent, COMSIG_AUTOFIRE_SHOT, target, shooter, mouse_parameters) & COMPONENT_AUTOFIRE_SHOT_SUCCESS) return TRUE stop_autofiring() return FALSE -/// Reset for our windup, resetting everything back to initial values after a variable set amount of time (determined by var/windup_spindown). -/datum/component/automatic_fire/proc/windup_reset(deltimer) - current_windup_reduction = initial(current_windup_reduction) - if(deltimer && timerid) - deltimer(timerid) - // Gun procs. /obj/item/gun/proc/on_autofire_start(mob/living/shooter) - if(semicd || shooter.incapacitated() || !can_trigger_gun(shooter)) + if(semicd || shooter.stat || !can_trigger_gun(shooter)) return FALSE if(!can_shoot()) shoot_with_empty_chamber(shooter) return FALSE var/obj/item/bodypart/other_hand = shooter.has_hand_for_held_index(shooter.get_inactive_hand_index()) if(weapon_weight == WEAPON_HEAVY && (shooter.get_inactive_held_item() || !other_hand)) - to_chat(shooter, span_warning("You need two hands to fire [src]!")) + to_chat(shooter, "You need two hands to fire [src]!") return FALSE return TRUE @@ -294,7 +259,7 @@ /obj/item/gun/proc/do_autofire(datum/source, atom/target, mob/living/shooter, params) SIGNAL_HANDLER - if(semicd || shooter.incapacitated()) + if(semicd || shooter.stat) return NONE if(!can_shoot()) shoot_with_empty_chamber(shooter)