[MIRROR] Beam Rifle Zooming Rework + Click catcher memes + bunch of other random stuff that players won't use (#2039)

* Beam Rifle Zooming Rework + Click catcher memes + bunch of other random stuff that players won't use

* Fixes beam rifle indent error

* Projectile target check hit code now uses a proc for resharing

* Update beam_rifle.dm

* Delete beam_rifle.dm.rej

* Changes clickcatcher to dynamically scale based on view range rather than making 1 tile for each tile viewed

* Update turf.dm

* Update turf.dm

* Delete click.dm.rej

* Update click.dm

* fxies

* woops

* Update turf.dm

* the actual rifle

* dumb clickcatcher

* actions
This commit is contained in:
CitadelStationBot
2017-08-03 08:12:27 -05:00
committed by kevinz000
parent 1b22c5fe0c
commit d4f15ff6da
15 changed files with 485 additions and 175 deletions

View File

@@ -182,3 +182,41 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
gaussian_next = R2 * working gaussian_next = R2 * working
return (mean + stddev * R1) return (mean + stddev * R1)
#undef ACCURACY #undef ACCURACY
/proc/mouse_angle_from_client(client/client)
var/list/mouse_control = params2list(client.mouseParams)
if(mouse_control["screen-loc"])
var/list/screen_loc_params = splittext(mouse_control["screen-loc"], ",")
var/list/screen_loc_X = splittext(screen_loc_params[1],":")
var/list/screen_loc_Y = splittext(screen_loc_params[2],":")
var/x = (text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32)
var/y = (text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32)
var/screenview = (client.view * 2 + 1) * world.icon_size //Refer to http://www.byond.com/docs/ref/info.html#/client/var/view for mad maths
var/ox = round(screenview/2) - client.pixel_x //"origin" x
var/oy = round(screenview/2) - client.pixel_y //"origin" y
var/angle = NORM_ROT(Atan2(y - oy, x - ox))
return angle
/proc/get_turf_in_angle(angle, turf/starting, increments)
var/pixel_x = 0
var/pixel_y = 0
for(var/i in 1 to increments)
pixel_x += sin(angle)+16*sin(angle)*2
pixel_y += cos(angle)+16*cos(angle)*2
var/new_x = starting.x
var/new_y = starting.y
while(pixel_x > 16)
pixel_x -= 32
new_x++
while(pixel_x < -16)
pixel_x += 32
new_x--
while(pixel_y > 16)
pixel_y -= 32
new_y++
while(pixel_y < -16)
pixel_y += 32
new_y--
new_x = Clamp(new_x, 0, world.maxx)
new_y = Clamp(new_y, 0, world.maxy)
return locate(new_x, new_y, starting.z)

View File

@@ -24,17 +24,6 @@
active_mousedown_item.onMouseUp(object, location, params, mob) active_mousedown_item.onMouseUp(object, location, params, mob)
active_mousedown_item = null active_mousedown_item = null
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
mouseParams = params
mouseLocation = over_location
mouseObject = over_object
mouseControlObject = over_control
if(selected_target[1] && over_object && over_object.IsAutoclickable())
selected_target[1] = over_object
selected_target[2] = params
if(active_mousedown_item)
active_mousedown_item.onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
/mob/proc/CanMobAutoclick(object, location, params) /mob/proc/CanMobAutoclick(object, location, params)
/mob/living/carbon/CanMobAutoclick(atom/object, location, params) /mob/living/carbon/CanMobAutoclick(atom/object, location, params)
@@ -63,9 +52,6 @@
/obj/item/proc/onMouseUp(object, location, params, mob) /obj/item/proc/onMouseUp(object, location, params, mob)
return return
/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
return
/obj/item /obj/item
var/canMouseDown = FALSE var/canMouseDown = FALSE
@@ -90,3 +76,23 @@
mouseLocation = location mouseLocation = location
mouseObject = object mouseObject = object
mouseControlObject = control mouseControlObject = control
if(mob && LAZYLEN(mob.mousemove_intercept_objects))
for(var/obj/item/I in mob.mousemove_intercept_objects)
I.onMouseMove(object, location, control, params)
/obj/item/proc/onMouseMove(object, location, control, params)
return
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
mouseParams = params
mouseLocation = over_location
mouseObject = over_object
mouseControlObject = over_control
if(selected_target[1] && over_object && over_object.IsAutoclickable())
selected_target[1] = over_object
selected_target[2] = params
if(active_mousedown_item)
active_mousedown_item.onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
return

View File

@@ -432,14 +432,26 @@
/obj/screen/click_catcher /obj/screen/click_catcher
icon = 'icons/mob/screen_gen.dmi' icon = 'icons/mob/screen_gen.dmi'
icon_state = "click_catcher" icon_state = "flash"
plane = CLICKCATCHER_PLANE plane = CLICKCATCHER_PLANE
mouse_opacity = 2 mouse_opacity = 2
screen_loc = "CENTER" screen_loc = "CENTER"
/obj/screen/click_catcher/New() /obj/screen/click_catcher/proc/UpdateGreed(view_size_x = 7, view_size_y = 7)
..() var/icon/newicon = icon('icons/mob/screen_gen.dmi', "flash")
transform = matrix(200, 0, 0, 0, 200, 0) if(view_size_x > 16 || view_size_y > 16)
newicon.Scale((16 * 2 + 1) * world.icon_size,(16 * 2 + 1) * world.icon_size)
icon = newicon
var/tx = view_size_x/16
var/ty = view_size_y/16
var/matrix/M = new
M.Scale(tx, ty)
transform = M
screen_loc = "CENTER-16,CENTER-16"
else
screen_loc = "CENTER-[view_size_x],CENTER-[view_size_y]"
newicon.Scale((view_size_x * 2 + 1) * world.icon_size,(view_size_y * 2 + 1) * world.icon_size)
icon = newicon
/obj/screen/click_catcher/Click(location, control, params) /obj/screen/click_catcher/Click(location, control, params)
var/list/modifiers = params2list(params) var/list/modifiers = params2list(params)
@@ -453,7 +465,6 @@
T.Click(location, control, params) T.Click(location, control, params)
. = 1 . = 1
/* MouseWheelOn */ /* MouseWheelOn */
/mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params) /mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params)

View File

@@ -145,6 +145,7 @@
return 0 return 0
screenmob.client.screen = list() screenmob.client.screen = list()
screenmob.client.apply_clickcatcher()
var/display_hud_version = version var/display_hud_version = version
if(!display_hud_version) //If 0 or blank, display the next hud version if(!display_hud_version) //If 0 or blank, display the next hud version

View File

@@ -450,6 +450,7 @@
for(var/i in 1 to allowed_contents.len) for(var/i in 1 to allowed_contents.len)
var/thing = allowed_contents[i] var/thing = allowed_contents[i]
qdel(thing, force=TRUE) qdel(thing, force=TRUE)
var/turf/newT = ChangeTurf(turf_type, baseturf_type, FALSE, FALSE, forceop = forceop) var/turf/newT = ChangeTurf(turf_type, baseturf_type, FALSE, FALSE, forceop = forceop)

View File

@@ -649,9 +649,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
set desc = "switches between 1x and custom views" set desc = "switches between 1x and custom views"
if(view == world.view) if(view == world.view)
view = input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128) change_view(input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128))
else else
view = world.view change_view(world.view)
log_admin("[key_name(usr)] changed their view range to [view].") log_admin("[key_name(usr)] changed their view range to [view].")
//message_admins("\blue [key_name_admin(usr)] changed their view range to [view].") //why? removed by order of XSI //message_admins("\blue [key_name_admin(usr)] changed their view range to [view].") //why? removed by order of XSI

View File

@@ -48,7 +48,7 @@
preload_rsc = PRELOAD_RSC preload_rsc = PRELOAD_RSC
var/global/obj/screen/click_catcher/void var/obj/screen/click_catcher/void
// Used by html_interface module. // Used by html_interface module.
var/hi_last_pos var/hi_last_pos

View File

@@ -301,10 +301,8 @@ GLOBAL_LIST(external_rsc_urls)
send_resources() send_resources()
if(!void) generate_clickcatcher()
void = new() apply_clickcatcher()
screen += void
if(prefs.lastchangelog != GLOB.changelog_hash) //bolds the changelog button on the interface so we know there are updates. if(prefs.lastchangelog != GLOB.changelog_hash) //bolds the changelog button on the interface so we know there are updates.
to_chat(src, "<span class='info'>You have unread updates in the changelog.</span>") to_chat(src, "<span class='info'>You have unread updates in the changelog.</span>")
@@ -667,6 +665,16 @@ GLOBAL_LIST(external_rsc_urls)
CRASH("change_view called without argument.") CRASH("change_view called without argument.")
view = new_size view = new_size
apply_clickcatcher()
/client/proc/generate_clickcatcher()
if(!void)
void = new()
screen += void
/client/proc/apply_clickcatcher()
generate_clickcatcher()
void.UpdateGreed(view,view)
/client/proc/AnnouncePR(announcement) /client/proc/AnnouncePR(announcement)
if(prefs && prefs.chat_toggles & CHAT_PULLR) if(prefs && prefs.chat_toggles & CHAT_PULLR)

View File

@@ -326,7 +326,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(mind.current.key && copytext(mind.current.key,1,2)!="@") //makes sure we don't accidentally kick any clients if(mind.current.key && copytext(mind.current.key,1,2)!="@") //makes sure we don't accidentally kick any clients
to_chat(usr, "<span class='warning'>Another consciousness is in your body...It is resisting you.</span>") to_chat(usr, "<span class='warning'>Another consciousness is in your body...It is resisting you.</span>")
return return
client.view = world.view client.change_view(world.view)
SStgui.on_transfer(src, mind.current) // Transfer NanoUIs. SStgui.on_transfer(src, mind.current) // Transfer NanoUIs.
mind.current.key = key mind.current.key = key
return 1 return 1
@@ -468,16 +468,16 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
views |= i views |= i
var/new_view = input("Choose your new view", "Modify view range", 7) as null|anything in views var/new_view = input("Choose your new view", "Modify view range", 7) as null|anything in views
if(new_view) if(new_view)
client.view = Clamp(new_view, 1, max_view) client.change_view(Clamp(new_view, 1, max_view))
else else
client.view = world.view client.change_view(world.view)
/mob/dead/observer/verb/add_view_range(input as num) /mob/dead/observer/verb/add_view_range(input as num)
set name = "Add View Range" set name = "Add View Range"
set hidden = TRUE set hidden = TRUE
var/max_view = client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT var/max_view = client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT
if(input) if(input)
client.view = Clamp(client.view + input, 1, max_view) client.change_view(Clamp(client.view + input, 1, max_view))
/mob/dead/observer/verb/boo() /mob/dead/observer/verb/boo()
set category = "Ghost" set category = "Ghost"

View File

@@ -44,7 +44,7 @@
var/mob/dead/observe = M var/mob/dead/observe = M
if(observe.client) if(observe.client)
observe.client.screen -= I observe.client.screen -= I
I.loc = src I.forceMove(src)
I.layer = ABOVE_HUD_LAYER I.layer = ABOVE_HUD_LAYER
I.plane = ABOVE_HUD_PLANE I.plane = ABOVE_HUD_PLANE
I.appearance_flags |= NO_CLIENT_COLOR I.appearance_flags |= NO_CLIENT_COLOR

View File

@@ -39,7 +39,7 @@
if(client) if(client)
client.click_intercept = null client.click_intercept = null
client.view = world.view // Resets the client.view in case it was changed. client.change_view(world.view) // Resets the client.view in case it was changed.
if(!GLOB.individual_log_list[ckey]) if(!GLOB.individual_log_list[ckey])
GLOB.individual_log_list[ckey] = logging GLOB.individual_log_list[ckey] = logging

View File

@@ -141,3 +141,5 @@
var/list/progressbars = null //for stacking do_after bars var/list/progressbars = null //for stacking do_after bars
var/list/can_ride_typecache = list() var/list/can_ride_typecache = list()
var/list/mousemove_intercept_objects

View File

@@ -488,11 +488,11 @@
if(WEST) if(WEST)
_x = -zoom_amt _x = -zoom_amt
user.client.view = zoom_out_amt user.client.change_view(zoom_out_amt)
user.client.pixel_x = world.icon_size*_x user.client.pixel_x = world.icon_size*_x
user.client.pixel_y = world.icon_size*_y user.client.pixel_y = world.icon_size*_y
else else
user.client.view = world.view user.client.change_view(world.view)
user.client.pixel_x = 0 user.client.pixel_x = 0
user.client.pixel_y = 0 user.client.pixel_y = 0
return zoomed return zoomed

View File

@@ -1,4 +1,16 @@
#define ZOOM_LOCK_AUTOZOOM_FREEMOVE 0
#define ZOOM_LOCK_AUTOZOOM_ANGLELOCK 1
#define ZOOM_LOCK_CENTER_VIEW 2
#define ZOOM_LOCK_OFF 3
#define ZOOM_SPEED_STEP 0
#define ZOOM_SPEED_INSTANT 1
#define AUTOZOOM_PIXEL_STEP_FACTOR 48
#define AIMING_BEAM_ANGLE_CHANGE_THRESHOLD 0.1
/obj/item/weapon/gun/energy/beam_rifle /obj/item/weapon/gun/energy/beam_rifle
name = "particle acceleration rifle" name = "particle acceleration rifle"
desc = "An energy-based anti material marksman rifle that uses highly charged particle beams moving at extreme velocities to decimate whatever is unfortunate enough to be targetted by one. \ desc = "An energy-based anti material marksman rifle that uses highly charged particle beams moving at extreme velocities to decimate whatever is unfortunate enough to be targetted by one. \
@@ -12,22 +24,13 @@
force = 15 force = 15
materials = list() materials = list()
origin_tech = "" origin_tech = ""
recoil = 5 recoil = 4
ammo_x_offset = 3 ammo_x_offset = 3
ammo_y_offset = 3 ammo_y_offset = 3
modifystate = FALSE modifystate = FALSE
zoomable = TRUE
zoom_amt = 17
zoom_out_amt = 20
weapon_weight = WEAPON_HEAVY weapon_weight = WEAPON_HEAVY
w_class = WEIGHT_CLASS_BULKY w_class = WEIGHT_CLASS_BULKY
ammo_type = list(/obj/item/ammo_casing/energy/beam_rifle/hitscan) ammo_type = list(/obj/item/ammo_casing/energy/beam_rifle/hitscan)
var/hipfire_inaccuracy = 2
var/hipfire_recoil = 10
var/scoped_inaccuracy = 0
var/scoped_recoil = 3
var/scoped = FALSE
var/noscope = FALSE //Can you fire this without a scope?
cell_type = /obj/item/weapon/stock_parts/cell/beam_rifle cell_type = /obj/item/weapon/stock_parts/cell/beam_rifle
canMouseDown = TRUE canMouseDown = TRUE
pin = null pin = null
@@ -37,13 +40,14 @@
var/aiming_time_left = 7 var/aiming_time_left = 7
var/aiming_time_increase_user_movement = 3 var/aiming_time_increase_user_movement = 3
var/scoped_slow = 1 var/scoped_slow = 1
var/aiming_time_increase_angle_multiplier = 0.6 var/aiming_time_increase_angle_multiplier = 0.3
var/lastangle = 0 var/lastangle = 0
var/aiming_lastangle = 0
var/mob/current_user = null var/mob/current_user = null
var/list/obj/effect/temp_visual/current_tracers = list() var/obj/effect/projectile_beam/current_tracer
var/structure_piercing = 2 //This doesn't always work! var/structure_piercing = 2 //Amount * 2. For some reason structures aren't respecting this unless you have it doubled. Probably with the objects in question's Bump() code instead of this but I'll deal with this later.
var/structure_bleed_coeff = 0.7 var/structure_bleed_coeff = 0.7
var/wall_pierce_amount = 0 var/wall_pierce_amount = 0
var/wall_devastate = 0 var/wall_devastate = 0
@@ -60,19 +64,122 @@
var/delay = 65 var/delay = 65
var/lastfire = 0 var/lastfire = 0
//ZOOMING
var/zoom_current_view_increase = 0
var/zoom_target_view_increase = 10
var/zoom_speed = ZOOM_SPEED_STEP
var/zooming = FALSE
var/zoom_lock = ZOOM_LOCK_AUTOZOOM_FREEMOVE
var/zooming_angle
var/current_zoom_x = 0
var/current_zoom_y = 0
var/zoom_animating = 0
var/static/image/charged_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_charged") var/static/image/charged_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_charged")
var/static/image/drained_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_empty") var/static/image/drained_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_empty")
var/datum/action/item_action/zoom_speed_action/zoom_speed_action
var/datum/action/item_action/zoom_lock_action/zoom_lock_action
/obj/item/weapon/gun/energy/beam_rifle/debug /obj/item/weapon/gun/energy/beam_rifle/debug
delay = 0 delay = 0
cell_type = /obj/item/weapon/stock_parts/cell/infinite cell_type = /obj/item/weapon/stock_parts/cell/infinite
aiming_time = 0 aiming_time = 0
recoil = 0 recoil = 0
scoped_recoil = 0 pin = /obj/item/device/firing_pin
hipfire_recoil = 0
hipfire_inaccuracy = 0 /obj/item/weapon/gun/energy/beam_rifle/equipped(mob/user)
scoped_inaccuracy = 0 set_user(user)
noscope = 1 . = ..()
/obj/item/weapon/gun/energy/beam_rifle/pickup(mob/user)
set_user(user)
. = ..()
/obj/item/weapon/gun/energy/beam_rifle/dropped()
set_user()
. = ..()
/obj/item/weapon/gun/energy/beam_rifle/ui_action_click(owner, action)
if(istype(action, /datum/action/item_action/zoom_speed_action))
zoom_speed++
if(zoom_speed > 1)
zoom_speed = ZOOM_SPEED_STEP
switch(zoom_speed)
if(ZOOM_SPEED_STEP)
to_chat(owner, "<span class='boldnotice'>You switch [src]'s digital zoom to stepper mode.</span>")
if(ZOOM_SPEED_INSTANT)
to_chat(owner, "<span class='boldnotice'>You switch [src]'s digital zoom to instant mode.</span>")
if(istype(action, /datum/action/item_action/zoom_lock_action))
zoom_lock++
if(zoom_lock > 3)
zoom_lock = 0
switch(zoom_lock)
if(ZOOM_LOCK_AUTOZOOM_FREEMOVE)
to_chat(owner, "<span class='boldnotice'>You switch [src]'s zooming processor to free directional.</span>")
if(ZOOM_LOCK_AUTOZOOM_ANGLELOCK)
to_chat(owner, "<span class='boldnotice'>You switch [src]'s zooming processor to locked directional.</span>")
if(ZOOM_LOCK_CENTER_VIEW)
to_chat(owner, "<span class='boldnotice'>You switch [src]'s zooming processor to center mode.</span>")
if(ZOOM_LOCK_OFF)
to_chat(owner, "<span class='boldnotice'>You disable [src]'s zooming system.</span>")
reset_zooming()
/obj/item/weapon/gun/energy/beam_rifle/proc/smooth_zooming(delay_override = null)
if(!check_user() || !zooming || zoom_lock == ZOOM_LOCK_OFF || zoom_lock == ZOOM_LOCK_CENTER_VIEW)
return
if(zoom_animating && delay_override != 0)
return smooth_zooming(zoom_animating + delay_override) //Automatically compensate for ongoing zooming actions.
var/total_time = SSfastprocess.wait
if(delay_override)
total_time = delay_override
if(zoom_speed == ZOOM_SPEED_INSTANT)
total_time = 0
zoom_animating = total_time
animate(current_user.client, pixel_x = current_zoom_x, pixel_y = current_zoom_y , total_time, SINE_EASING, ANIMATION_PARALLEL)
zoom_animating = 0
/obj/item/weapon/gun/energy/beam_rifle/proc/set_autozoom_pixel_offsets_immediate(current_angle)
if(zoom_lock == ZOOM_LOCK_CENTER_VIEW || zoom_lock == ZOOM_LOCK_OFF)
return
current_zoom_x = sin(current_angle) + sin(current_angle) * AUTOZOOM_PIXEL_STEP_FACTOR * zoom_current_view_increase
current_zoom_y = cos(current_angle) + cos(current_angle) * AUTOZOOM_PIXEL_STEP_FACTOR * zoom_current_view_increase
/obj/item/weapon/gun/energy/beam_rifle/proc/handle_zooming()
if(!zooming || !check_user())
return
if(zoom_speed == ZOOM_SPEED_INSTANT)
current_user.client.change_view(world.view + zoom_target_view_increase)
zoom_current_view_increase = zoom_target_view_increase
set_autozoom_pixel_offsets_immediate(zooming_angle)
smooth_zooming()
return
if(zoom_current_view_increase > zoom_target_view_increase)
return
zoom_current_view_increase++
current_user.client.change_view(zoom_current_view_increase + world.view)
set_autozoom_pixel_offsets_immediate(zooming_angle)
smooth_zooming(SSfastprocess.wait * zoom_target_view_increase * zoom_speed)
/obj/item/weapon/gun/energy/beam_rifle/proc/start_zooming()
if(zoom_lock == ZOOM_LOCK_OFF)
return
zooming = TRUE
/obj/item/weapon/gun/energy/beam_rifle/proc/stop_zooming()
zooming = FALSE
reset_zooming()
/obj/item/weapon/gun/energy/beam_rifle/proc/reset_zooming()
if(!check_user(FALSE))
return
zoom_animating = 0
animate(current_user.client, pixel_x = 0, pixel_y = 0, 0, FALSE, LINEAR_EASING, ANIMATION_END_NOW)
zoom_current_view_increase = 0
current_user.client.change_view(world.view)
zooming_angle = 0
current_zoom_x = 0
current_zoom_y = 0
/obj/item/weapon/gun/energy/beam_rifle/update_icon() /obj/item/weapon/gun/energy/beam_rifle/update_icon()
cut_overlays() cut_overlays()
@@ -85,9 +192,10 @@
/obj/item/weapon/gun/energy/beam_rifle/attack_self(mob/user) /obj/item/weapon/gun/energy/beam_rifle/attack_self(mob/user)
projectile_setting_pierce = !projectile_setting_pierce projectile_setting_pierce = !projectile_setting_pierce
to_chat(user, "<span class='boldnotice'>You set \the [src] to [projectile_setting_pierce? "pierce":"impact"] mode.</span>") to_chat(user, "<span class='boldnotice'>You set \the [src] to [projectile_setting_pierce? "pierce":"impact"] mode.</span>")
aiming_beam()
/obj/item/weapon/gun/energy/beam_rifle/proc/update_slowdown() /obj/item/weapon/gun/energy/beam_rifle/proc/update_slowdown()
if(scoped) if(aiming)
slowdown = scoped_slow slowdown = scoped_slow
else else
slowdown = initial(slowdown) slowdown = initial(slowdown)
@@ -95,140 +203,160 @@
/obj/item/weapon/gun/energy/beam_rifle/Initialize() /obj/item/weapon/gun/energy/beam_rifle/Initialize()
. = ..() . = ..()
START_PROCESSING(SSfastprocess, src) START_PROCESSING(SSfastprocess, src)
zoom_speed_action = new(src)
zoom_lock_action = new(src)
/obj/item/weapon/gun/energy/beam_rifle/Destroy() /obj/item/weapon/gun/energy/beam_rifle/Destroy()
STOP_PROCESSING(SSfastprocess, src) STOP_PROCESSING(SSfastprocess, src)
..() set_user(null)
QDEL_NULL(current_tracer)
/obj/item/weapon/gun/energy/beam_rifle/zoom(user, forced_zoom) return ..()
. = ..()
scope(user, .)
/obj/item/weapon/gun/energy/beam_rifle/proc/scope(mob/user, forced)
var/scoping
switch(forced)
if(TRUE)
scoping = TRUE
if(FALSE)
scoping = FALSE
else
scoping = !scoped
if(scoping)
spread = scoped_inaccuracy
recoil = scoped_recoil
scoped = TRUE
user << "<span class='boldnotice'>You bring your [src] up and use its scope...</span>"
else
spread = hipfire_inaccuracy
recoil = hipfire_recoil
scoped = FALSE
user << "<span class='boldnotice'>You lower your [src].</span>"
update_slowdown()
/obj/item/weapon/gun/energy/beam_rifle/can_trigger_gun(var/mob/living/user)
if(!scoped && !noscope)
user << "<span class='userdanger'>This beam rifle can only be used while scoped!</span>"
return FALSE
. = ..(user)
/obj/item/weapon/gun/energy/beam_rifle/emp_act(severity) /obj/item/weapon/gun/energy/beam_rifle/emp_act(severity)
chambered = null chambered = null
recharge_newshot() recharge_newshot()
/obj/item/weapon/gun/energy/beam_rifle/proc/aiming_beam() /obj/item/weapon/gun/energy/beam_rifle/proc/aiming_beam(force_update = FALSE)
var/atom/A = current_user.client.mouseObject var/diff = abs(aiming_lastangle - lastangle)
if(!istype(A) || !A.loc) check_user()
return if(diff < AIMING_BEAM_ANGLE_CHANGE_THRESHOLD && !force_update)
var/turf/T = get_turf(current_user.client.mouseObject)
if(!istype(T))
return return
aiming_lastangle = lastangle
var/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/P = new var/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/P = new
P.gun = src P.gun = src
P.wall_pierce_amount = wall_pierce_amount P.wall_pierce_amount = wall_pierce_amount
P.structure_pierce_amount = structure_piercing P.structure_pierce_amount = structure_piercing
P.do_pierce = projectile_setting_pierce P.do_pierce = projectile_setting_pierce
P.preparePixelProjectile(current_user.client.mouseObject, T, current_user, current_user.client.mouseParams, 0)
if(aiming_time) if(aiming_time)
var/percent = ((100/aiming_time)*aiming_time_left) var/percent = ((100/aiming_time)*aiming_time_left)
P.color = rgb(255 * percent,255 * ((100 - percent) / 100),0) P.color = rgb(255 * percent,255 * ((100 - percent) / 100),0)
else else
P.color = rgb(0, 255, 0) P.color = rgb(0, 255, 0)
clear_tracers() var/turf/curloc = get_turf(src)
P.fire() var/turf/targloc = get_turf(current_user.client.mouseObject)
if(!istype(targloc))
/obj/item/weapon/gun/energy/beam_rifle/proc/clear_tracers() if(!istype(curloc))
for(var/I in current_tracers) return
current_tracers -= I targloc = get_turf_in_angle(lastangle, curloc, 10)
var/obj/effect/temp_visual/projectile_beam/PB = I P.preparePixelProjectile(targloc, targloc, current_user, current_user.client.mouseParams, 0)
qdel(PB) P.fire(lastangle)
/obj/item/weapon/gun/energy/beam_rifle/proc/terminate_aiming()
stop_aiming()
clear_tracers()
/obj/item/weapon/gun/energy/beam_rifle/process() /obj/item/weapon/gun/energy/beam_rifle/process()
if(!aiming) if(!aiming)
return return
if(!istype(current_user) || !isturf(current_user.loc) || !(src in current_user.held_items) || current_user.incapacitated()) //Doesn't work if you're not holding it! check_user()
terminate_aiming() handle_zooming()
return
if(aiming_time_left > 0) if(aiming_time_left > 0)
aiming_time_left-- aiming_time_left--
aiming_beam() aiming_beam(TRUE)
process_aim()
/obj/item/weapon/gun/energy/beam_rifle/proc/check_user(automatic_cleanup = TRUE)
if(!istype(current_user) || !isturf(current_user.loc) || !(src in current_user.held_items) || current_user.incapacitated()) //Doesn't work if you're not holding it!
if(automatic_cleanup)
stop_aiming()
set_user(null)
return FALSE
return TRUE
/obj/item/weapon/gun/energy/beam_rifle/proc/process_aim() /obj/item/weapon/gun/energy/beam_rifle/proc/process_aim()
if(current_user.client.mouseParams) if(istype(current_user) && current_user.client && current_user.client.mouseParams)
var/list/mouse_control = params2list(current_user.client.mouseParams) var/angle = mouse_angle_from_client(current_user.client)
if(isturf(current_user.client.mouseLocation)) switch(angle)
current_user.face_atom(current_user.client.mouseLocation) if(316 to 360)
if(mouse_control["screen-loc"]) current_user.setDir(NORTH)
var/list/screen_loc_params = splittext(mouse_control["screen-loc"], ",") if(0 to 45)
var/list/screen_loc_X = splittext(screen_loc_params[1],":") current_user.setDir(NORTH)
var/list/screen_loc_Y = splittext(screen_loc_params[2],":") if(46 to 135)
var/x = (text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32) current_user.setDir(EAST)
var/y = (text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32) if(136 to 225)
var/screenview = (current_user.client.view * 2 + 1) * world.icon_size //Refer to http://www.byond.com/docs/ref/info.html#/client/var/view for mad maths current_user.setDir(SOUTH)
var/ox = round(screenview/2) - current_user.client.pixel_x //"origin" x if(226 to 315)
var/oy = round(screenview/2) - current_user.client.pixel_y //"origin" y current_user.setDir(WEST)
var/angle = NORM_ROT(Atan2(y - oy, x - ox)) var/difference = abs(lastangle - angle)
var/difference = abs(lastangle - angle) if(difference > 350) //Too lazy to properly math, detects 360 --> 0 changes.
delay_penalty(difference * aiming_time_increase_angle_multiplier) difference = (lastangle > 350? ((360 - lastangle) + angle) : ((360 - angle) + lastangle))
lastangle = angle delay_penalty(difference * aiming_time_increase_angle_multiplier)
lastangle = angle
/obj/item/weapon/gun/energy/beam_rifle/on_mob_move() /obj/item/weapon/gun/energy/beam_rifle/on_mob_move()
delay_penalty(aiming_time_increase_user_movement) check_user()
if(aiming)
delay_penalty(aiming_time_increase_user_movement)
process_aim()
aiming_beam(TRUE)
/obj/item/weapon/gun/energy/beam_rifle/proc/start_aiming() /obj/item/weapon/gun/energy/beam_rifle/proc/start_aiming()
aiming_time_left = aiming_time aiming_time_left = aiming_time
aiming = TRUE aiming = TRUE
process_aim()
aiming_beam(TRUE)
zooming_angle = lastangle
start_zooming()
/obj/item/weapon/gun/energy/beam_rifle/proc/stop_aiming() /obj/item/weapon/gun/energy/beam_rifle/proc/stop_aiming()
set waitfor = FALSE
aiming_time_left = aiming_time aiming_time_left = aiming_time
aiming = FALSE aiming = FALSE
QDEL_NULL(current_tracer)
stop_zooming()
/obj/item/weapon/gun/energy/beam_rifle/proc/set_user(mob/user)
if(user == current_user)
return
stop_aiming()
if(istype(current_user))
LAZYREMOVE(current_user.mousemove_intercept_objects, src)
current_user = null
if(istype(user))
current_user = user
LAZYADD(current_user.mousemove_intercept_objects, src)
/obj/item/weapon/gun/energy/beam_rifle/onMouseDrag(src_object, over_object, src_location, over_location, params, mob) /obj/item/weapon/gun/energy/beam_rifle/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
current_user = mob if(aiming)
process_aim()
aiming_beam()
if(zoom_lock == ZOOM_LOCK_AUTOZOOM_FREEMOVE)
zooming_angle = lastangle
set_autozoom_pixel_offsets_immediate(zooming_angle)
smooth_zooming(2)
return ..()
/obj/item/weapon/gun/energy/beam_rifle/onMouseDown(object, location, params, mob) /obj/item/weapon/gun/energy/beam_rifle/onMouseDown(object, location, params, mob/mob)
if(istype(mob))
set_user(mob)
if(istype(object, /obj/screen) && !istype(object, /obj/screen/click_catcher))
return
if((object in mob.contents) || (object == mob))
return
start_aiming() start_aiming()
current_user = mob return ..()
/obj/item/weapon/gun/energy/beam_rifle/onMouseUp(object, location, params, mob/M) /obj/item/weapon/gun/energy/beam_rifle/onMouseUp(object, location, params, mob/M)
if(istype(object, /obj/screen) && !istype(object, /obj/screen/click_catcher))
return
process_aim() process_aim()
if(aiming_time_left <= aiming_time_fire_threshold) if(aiming_time_left <= aiming_time_fire_threshold && check_user())
sync_ammo() sync_ammo()
afterattack(M.client.mouseObject, M, FALSE, M.client.mouseParams, passthrough = TRUE) afterattack(M.client.mouseObject, M, FALSE, M.client.mouseParams, passthrough = TRUE)
stop_aiming() stop_aiming()
clear_tracers() QDEL_NULL(current_tracer)
return ..()
/obj/item/weapon/gun/energy/beam_rifle/afterattack(atom/target, mob/living/user, flag, params, passthrough = FALSE) /obj/item/weapon/gun/energy/beam_rifle/afterattack(atom/target, mob/living/user, flag, params, passthrough = FALSE)
if(flag) //It's adjacent, is the user, or is on the user's person
if(target in user.contents) //can't shoot stuff inside us.
return
if(!ismob(target) || user.a_intent == INTENT_HARM) //melee attack
return
if(target == user && user.zone_selected != "mouth") //so we can't shoot ourselves (unless mouth selected)
return
if(!passthrough && (aiming_time > aiming_time_fire_threshold)) if(!passthrough && (aiming_time > aiming_time_fire_threshold))
return return
if(lastfire > world.time + delay) if(lastfire > world.time + delay)
return return
lastfire = world.time lastfire = world.time
. = ..() stop_aiming()
return ..()
/obj/item/weapon/gun/energy/beam_rifle/proc/sync_ammo() /obj/item/weapon/gun/energy/beam_rifle/proc/sync_ammo()
for(var/obj/item/ammo_casing/energy/beam_rifle/AC in contents) for(var/obj/item/ammo_casing/energy/beam_rifle/AC in contents)
@@ -298,6 +426,25 @@
HS_BB.do_pierce = do_pierce HS_BB.do_pierce = do_pierce
HS_BB.gun = host HS_BB.gun = host
/obj/item/ammo_casing/energy/beam_rifle/throw_proj(atom/target, turf/targloc, mob/living/user, params, spread)
var/turf/curloc = get_turf(user)
if(!istype(curloc) || !BB)
return FALSE
var/obj/item/weapon/gun/energy/beam_rifle/gun = loc
if(!targloc && gun)
targloc = get_turf_in_angle(gun.lastangle, curloc, 10)
else if(!targloc)
return FALSE
var/firing_dir
if(BB.firer)
firing_dir = BB.firer.dir
if(!BB.suppressed && firing_effect_type)
new firing_effect_type(get_turf(src), firing_dir)
BB.preparePixelProjectile(target, targloc, user, params, spread)
BB.fire(gun? gun.lastangle : null, null)
BB = null
return TRUE
/obj/item/ammo_casing/energy/beam_rifle/hitscan /obj/item/ammo_casing/energy/beam_rifle/hitscan
projectile_type = /obj/item/projectile/beam/beam_rifle/hitscan projectile_type = /obj/item/projectile/beam/beam_rifle/hitscan
select_name = "beam" select_name = "beam"
@@ -330,6 +477,7 @@
var/impact_structure_damage = 0 var/impact_structure_damage = 0
var/impact_direct_damage = 0 var/impact_direct_damage = 0
var/turf/cached var/turf/cached
var/list/pierced = list()
/obj/item/projectile/beam/beam_rifle/proc/AOE(turf/epicenter) /obj/item/projectile/beam/beam_rifle/proc/AOE(turf/epicenter)
set waitfor = FALSE set waitfor = FALSE
@@ -351,20 +499,29 @@
/obj/item/projectile/beam/beam_rifle/proc/check_pierce(atom/target) /obj/item/projectile/beam/beam_rifle/proc/check_pierce(atom/target)
if(!do_pierce) if(!do_pierce)
return FALSE return FALSE
if(pierced[target]) //we already pierced them go away
loc = get_turf(target)
return TRUE
if(isclosedturf(target)) if(isclosedturf(target))
if(wall_pierce++ < wall_pierce_amount) if(wall_pierce++ < wall_pierce_amount)
loc = target loc = target
if(prob(wall_devastate)) if(prob(wall_devastate))
target.ex_act(EXPLODE_HEAVY) if(istype(target, /turf/closed/wall))
var/turf/closed/wall/W = target
W.dismantle_wall(TRUE, TRUE)
else
target.ex_act(EXPLODE_HEAVY)
return TRUE return TRUE
if(ismovableatom(target)) if(ismovableatom(target))
var/atom/movable/AM = target var/atom/movable/AM = target
if(AM.density && !AM.CanPass(src, get_turf(target)) && !ismob(AM)) if(AM.density && !AM.CanPass(src, get_turf(target)) && !ismob(AM))
if(structure_pierce++ < structure_pierce_amount) if(structure_pierce < structure_pierce_amount)
if(isobj(AM)) if(isobj(AM))
var/obj/O = AM var/obj/O = AM
O.take_damage((impact_structure_damage + aoe_structure_damage) * structure_bleed_coeff * get_damage_coeff(AM), BURN, "energy", FALSE) O.take_damage((impact_structure_damage + aoe_structure_damage) * structure_bleed_coeff * get_damage_coeff(AM), BURN, "energy", FALSE)
pierced[AM] = TRUE
loc = get_turf(AM) loc = get_turf(AM)
structure_pierce++
return TRUE return TRUE
return FALSE return FALSE
@@ -396,22 +553,69 @@
handle_impact(target) handle_impact(target)
/obj/item/projectile/beam/beam_rifle/Collide(atom/target) /obj/item/projectile/beam/beam_rifle/Collide(atom/target)
paused = TRUE
if(check_pierce(target)) if(check_pierce(target))
permutated += target permutated += target
return FALSE return FALSE
if(!QDELETED(target)) if(!QDELETED(target))
cached = get_turf(target) cached = get_turf(target)
paused = FALSE
. = ..() . = ..()
/obj/item/projectile/beam/beam_rifle/on_hit(atom/target, blocked = FALSE) /obj/item/projectile/beam/beam_rifle/on_hit(atom/target, blocked = FALSE)
paused = TRUE
if(!QDELETED(target)) if(!QDELETED(target))
cached = get_turf(target) cached = get_turf(target)
handle_hit(target) handle_hit(target)
paused = FALSE
. = ..() . = ..()
/obj/item/projectile/beam/beam_rifle/hitscan /obj/item/projectile/beam/beam_rifle/hitscan
icon_state = "" icon_state = ""
var/tracer_type = /obj/effect/temp_visual/projectile_beam/tracer var/tracer_type = /obj/effect/projectile_beam/tracer
var/starting_z
var/starting_p_x
var/starting_p_y
var/constant_tracer = FALSE
var/travelled_p_x = 0
var/travelled_p_y = 0
var/tracer_spawned = FALSE
/obj/item/projectile/beam/beam_rifle/hitscan/Destroy()
paused = TRUE //STOP HITTING WHEN YOU'RE ALREADY BEING DELETED!
spawn_tracer(constant_tracer)
return ..()
/obj/item/projectile/beam/beam_rifle/hitscan/proc/spawn_tracer(put_in_rifle = FALSE)
if(tracer_spawned)
return
tracer_spawned = TRUE
//Remind me to port baystation trajectories so this shit isn't needed...
var/pixels_travelled = round(sqrt(travelled_p_x**2 + travelled_p_y**2),1)
var/scaling = pixels_travelled/world.icon_size
var/midpoint_p_x = round(starting_p_x + (travelled_p_x / 2))
var/midpoint_p_y = round(starting_p_y + (travelled_p_y / 2))
var/tracer_px = midpoint_p_x % world.icon_size
var/tracer_py = midpoint_p_y % world.icon_size
var/tracer_lx = (midpoint_p_x - tracer_px) / world.icon_size
var/tracer_ly = (midpoint_p_y - tracer_py) / world.icon_size
var/obj/effect/projectile_beam/PB = new tracer_type(src)
PB.apply_vars(Angle, tracer_px, tracer_py, color, scaling, locate(tracer_lx,tracer_ly,starting_z))
if(put_in_rifle && istype(gun))
if(gun.current_tracer)
QDEL_NULL(gun.current_tracer)
gun.current_tracer = PB
else
QDEL_IN(PB, 5)
/obj/item/projectile/beam/beam_rifle/hitscan/proc/check_for_turf_edge(turf/T)
if(!istype(T))
return TRUE
var/tx = T.x
var/ty = T.y
if(tx < 10 || tx > (world.maxx - 10) || ty < 10 || ty > (world.maxy-10))
return TRUE
return FALSE
/obj/item/projectile/beam/beam_rifle/hitscan/fire(setAngle, atom/direct_target) //oranges didn't let me make this a var the first time around so copypasta time /obj/item/projectile/beam/beam_rifle/hitscan/fire(setAngle, atom/direct_target) //oranges didn't let me make this a var the first time around so copypasta time
set waitfor = 0 set waitfor = 0
@@ -423,6 +627,12 @@
var/old_pixel_x = pixel_x var/old_pixel_x = pixel_x
var/old_pixel_y = pixel_y var/old_pixel_y = pixel_y
var/safety = 0 //The code works fine, but... just in case... var/safety = 0 //The code works fine, but... just in case...
var/turf/c2
var/starting_x = loc.x
var/starting_y = loc.y
starting_z = loc.z
starting_p_x = starting_x * world.icon_size + pixel_x
starting_p_y = starting_y * world.icon_size + pixel_y
while(loc) while(loc)
if(++safety > (range * 3)) //If it's looping for way, way too long... if(++safety > (range * 3)) //If it's looping for way, way too long...
return //Kill! return //Kill!
@@ -437,6 +647,8 @@
transform = M transform = M
var/Pixel_x=sin(Angle)+16*sin(Angle)*2 var/Pixel_x=sin(Angle)+16*sin(Angle)*2
var/Pixel_y=cos(Angle)+16*cos(Angle)*2 var/Pixel_y=cos(Angle)+16*cos(Angle)*2
travelled_p_x += Pixel_x
travelled_p_y += Pixel_y
var/pixel_x_offset = old_pixel_x + Pixel_x var/pixel_x_offset = old_pixel_x + Pixel_x
var/pixel_y_offset = old_pixel_y + Pixel_y var/pixel_y_offset = old_pixel_y + Pixel_y
var/new_x = x var/new_x = x
@@ -469,27 +681,23 @@
animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (delay <= 3 ? delay - 1 : delay)), flags = ANIMATION_END_NOW) animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (delay <= 3 ? delay - 1 : delay)), flags = ANIMATION_END_NOW)
old_pixel_x = pixel_x_offset old_pixel_x = pixel_x_offset
old_pixel_y = pixel_y_offset old_pixel_y = pixel_y_offset
if(original && (original.layer>=2.75) || ismob(original)) if(can_hit_target(original, permutated))
if(loc == get_turf(original)) Collide(original)
if(!(original in permutated)) c2 = loc
Collide(original)
Range() Range()
if(check_for_turf_edge(loc))
/obj/item/projectile/beam/beam_rifle/hitscan/Range() spawn_tracer(constant_tracer)
spawn_tracer_effect() if(istype(c2))
if(!QDELETED(src) && loc) cached = c2
cached = get_turf(src)
/obj/item/projectile/beam/beam_rifle/hitscan/proc/spawn_tracer_effect()
QDEL_IN((new tracer_type(loc, time = 5, angle_override = Angle, p_x = pixel_x, p_y = pixel_y, color_override = color)), 5)
/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam /obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam
tracer_type = /obj/effect/temp_visual/projectile_beam/tracer/aiming tracer_type = /obj/effect/projectile_beam/tracer/aiming
name = "aiming beam" name = "aiming beam"
hitsound = null hitsound = null
hitsound_wall = null hitsound_wall = null
nodamage = TRUE nodamage = TRUE
damage = 0 damage = 0
constant_tracer = TRUE
/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/prehit(atom/target) /obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/prehit(atom/target)
qdel(src) qdel(src)
@@ -499,37 +707,69 @@
qdel(src) qdel(src)
return FALSE return FALSE
/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/spawn_tracer_effect() /obj/effect/projectile_beam
var/obj/effect/temp_visual/projectile_beam/T = new tracer_type(loc, time = 5, angle_override = Angle, p_x = pixel_x, p_y = pixel_y, color_override = color)
if(istype(gun) && istype(T))
gun.current_tracers[T] = TRUE
/obj/effect/temp_visual/projectile_beam
icon = 'icons/obj/projectiles.dmi' icon = 'icons/obj/projectiles.dmi'
layer = ABOVE_MOB_LAYER layer = ABOVE_MOB_LAYER
anchored = TRUE anchored = TRUE
duration = 5
randomdir = FALSE
light_power = 1 light_power = 1
light_range = 2 light_range = 2
light_color = "#00ffff" light_color = "#00ffff"
mouse_opacity = 0
flags = ABSTRACT
appearance_flags = 0
/obj/effect/temp_visual/projectile_beam/New(time = 5, angle_override, p_x, p_y, color_override) /obj/effect/projectile_beam/proc/scale_to(nx,ny,override=TRUE)
duration = time var/matrix/M
if(!override)
M = transform
else
M = new
M.Scale(nx,ny)
transform = M
/obj/effect/projectile_beam/proc/turn_to(angle,override=TRUE)
var/matrix/M
if(!override)
M = transform
else
M = new
M.Turn(angle)
transform = M
/obj/effect/projectile_beam/New(angle_override, p_x, p_y, color_override, scaling = 1)
if(angle_override && p_x && p_y && color_override && scaling)
apply_vars(angle_override, p_x, p_y, color_override, scaling)
return ..()
/obj/effect/projectile_beam/proc/apply_vars(angle_override, p_x, p_y, color_override, scaling = 1, new_loc, increment = 0)
var/mutable_appearance/look = new(src) var/mutable_appearance/look = new(src)
look.pixel_x = p_x look.pixel_x = p_x
look.pixel_y = p_y look.pixel_y = p_y
if(color_override) if(color_override)
look.color = color_override look.color = color_override
var/matrix/M = new
M.Turn(angle_override)
look.transform = M
appearance = look appearance = look
..() scale_to(1,scaling, FALSE)
turn_to(angle_override, FALSE)
if(!isnull(new_loc)) //If you want to null it just delete it...
forceMove(new_loc)
for(var/i in 1 to increment)
pixel_x += round((sin(angle_override)+16*sin(angle_override)*2), 1)
pixel_y += round((cos(angle_override)+16*cos(angle_override)*2), 1)
/obj/effect/temp_visual/projectile_beam/tracer /obj/effect/projectile_beam/tracer
icon_state = "tracer_beam" icon_state = "tracer_beam"
/obj/effect/temp_visual/projectile_beam/tracer/aiming /obj/effect/projectile_beam/tracer/aiming
icon_state = "gbeam" icon_state = "gbeam"
duration = 1
/datum/action/item_action/zoom_speed_action
name = "Toggle Zooming Speed"
icon_icon = 'icons/mob/actions/actions_spells.dmi'
button_icon_state = "projectile"
background_icon_state = "bg_tech"
/datum/action/item_action/zoom_lock_action
name = "Switch Zoom Mode"
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "zoom_mode"
background_icon_state = "bg_tech"

View File

@@ -264,11 +264,8 @@
animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (delay <= 3 ? delay - 1 : delay)), flags = ANIMATION_END_NOW) animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (delay <= 3 ? delay - 1 : delay)), flags = ANIMATION_END_NOW)
old_pixel_x = pixel_x_offset old_pixel_x = pixel_x_offset
old_pixel_y = pixel_y_offset old_pixel_y = pixel_y_offset
if(can_hit_target(original, permutated))
if(original && (original.layer >= PROJECTILE_HIT_THRESHHOLD_LAYER) || ismob(original)) Collide(original)
if(loc == get_turf(original))
if(!(original in permutated))
Collide(original)
Range() Range()
if (delay > 0) if (delay > 0)
sleep(delay) sleep(delay)
@@ -280,13 +277,19 @@
if((!( current ) || loc == current)) if((!( current ) || loc == current))
current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z) current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z)
step_towards(src, current) step_towards(src, current)
if(original && (original.layer >= PROJECTILE_HIT_THRESHHOLD_LAYER) || ismob(original)) if(can_hit_target(original, permutated))
if(loc == get_turf(original)) Collide(original)
if(!(original in permutated))
Collide(original)
Range() Range()
sleep(config.run_speed * 0.9) sleep(config.run_speed * 0.9)
//Returns true if the target atom is on our current turf and above the right layer
/obj/item/projectile/proc/can_hit_target(atom/target, var/list/passthrough)
if(target && (target.layer >= PROJECTILE_HIT_THRESHHOLD_LAYER) || ismob(target))
if(loc == get_turf(target))
if(!(target in passthrough))
return TRUE
return FALSE
/obj/item/projectile/proc/preparePixelProjectile(atom/target, var/turf/targloc, mob/living/user, params, spread) /obj/item/projectile/proc/preparePixelProjectile(atom/target, var/turf/targloc, mob/living/user, params, spread)
var/turf/curloc = get_turf(user) var/turf/curloc = get_turf(user)
forceMove(get_turf(user)) forceMove(get_turf(user))