Tracker for projectiles (#26026)

This commit is contained in:
ShiftyRail
2020-03-25 20:20:29 +01:00
committed by GitHub
parent 21efc9052f
commit a67f8798a3
7 changed files with 216 additions and 1 deletions

View File

@@ -133,6 +133,7 @@
if(istype(D,/atom/movable))
body += "<option value='?_src_=vars;teleport_here=\ref[D]'>Teleport Here</option>"
body += "<option value='?_src_=vars;throw_a_fucking_rod_at_it=\ref[D]'>Throw a rod at it</option>"
if(istype(D,/atom))
body += "<option value='?_src_=vars;teleport_to=\ref[D]'>Teleport To</option>"
@@ -834,6 +835,48 @@ function loadPage(list) {
A.alpha = 0
animate(A, alpha = 255, time = stealthy_level)
else if(href_list["throw_a_fucking_rod_at_it"])
if(!check_rights(R_FUN))
to_chat(usr, "<span class='warning'>You do not have sufficient permissions to do this.</span>")
return
var/atom/movable/A = locate(href_list["throw_a_fucking_rod_at_it"])
if(!istype(A))
to_chat(usr, "<span class='warning'>This can only be done to instances of movable atoms.</span>")
return
var/rod_size = input("What type of rod do you want to throw?","Throwing an Immovable Rod",null) as null|anything in list("Normal", "Pillar", "Monolith")
var/rod_type
if (!rod_size)
return
switch (rod_size)
if ("Normal")
rod_type = /obj/item/projectile/immovablerod
if ("Pillar")
rod_type = /obj/item/projectile/immovablerod/big
if ("Monolith")
rod_type = /obj/item/projectile/immovablerod/hyper
if(alert("Are you sure you want to do this?","Confirm","Yes","No") != "Yes")
return
var/obj/item/projectile/immovablerod/rod = new rod_type(random_start_turf(A.z))
rod.tracking = TRUE
rod.throw_at(A)
var/log_data = "[A]"
if (ismob(A))
var/mob/M = A
if (M.client)
log_data += " ([M.client.ckey])"
log_admin("[key_name(usr)] threw a rod at [log_data].")
message_admins("<span class='notice'>[key_name(usr)] threw a rod at [log_data].</span>")
to_chat(usr, "<span class='danger'>If you changed your mind, you can always stop the tracking by using the verb 'VIEW-ALL-RODS' and click the 'Untrack' link.</span>")
return
else if(href_list["teleport_to"])
if(!check_rights(0))
return

View File

@@ -57,6 +57,8 @@
var/last_explosion_push = 0
var/list/datum/tracker/trackers = list()
/atom/movable/New()
. = ..()
if((flags & HEAR) && !ismob(src))
@@ -1060,3 +1062,43 @@
forceMove(F)
return TRUE
return FALSE
// -- trackers
/atom/movable/proc/add_tracker(var/datum/tracker/T)
on_moved.Add(T, "recieve_position")
/datum/tracker
var/name = "Tracker"
var/active = TRUE
var/changed = FALSE
var/turf/target
var/tick_refresh = 5 // The number of moved events before we update the position.
var/current_tick = 1
var/lost_position_probability = 0 // Probability of losing the target
var/lost_position_distance = 0 // Distance at which the tracker loses the target
/datum/tracker/proc/recieve_position(var/list/loc)
ASSERT(loc)
if (!active)
return
if (current_tick < tick_refresh)
current_tick++
return
if (prob(lost_position_probability))
active = FALSE
return
var/target_loc = loc["loc"]
if (target != target_loc)
changed = TRUE
target = get_turf(target_loc)
current_tick = 1

View File

@@ -1618,3 +1618,17 @@ proc/formatPlayerPanel(var/mob/U,var/text="PP")
dat += "Max [T.max_per_turf] per turf. Lasts up to [T.max_age] rounds.<hr>"
usr << browse(dat, "window=persistencepanel;size=350x600")
/datum/admins/proc/ViewAllRods()
if(!check_rights(0))
return
var/dat = "<center><B>View all active rods</B></center><hr>"
for (var/obj/item/projectile/immovablerod/rod in all_rods)
dat += "<b>[rod]</b> in z = [rod.z] (<a href='?_src_=vars;Vars=\ref[rod]'>\[VV\]</A>)"
if (rod.tracking)
dat += "- <A href='?src=\ref[src];rod_to_untrack=\ref[rod]'>(UNTRACK)</A>"
dat += "<br/>"
usr << browse(dat, "window=rodswindow;size=350x300")

View File

@@ -128,7 +128,8 @@ var/list/admin_verbs_fun = list(
/client/proc/makepAI,
/client/proc/set_blob_looks,
/client/proc/set_teleport_pref,
/client/proc/deadchat_singularity
/client/proc/deadchat_singularity,
/client/proc/view_all_rods,
)
var/list/admin_verbs_spawn = list(
/datum/admins/proc/spawn_atom, // Allows us to spawn instances
@@ -1265,3 +1266,11 @@ var/list/admin_verbs_mod = list(
holder.PersistencePanel()
feedback_add_details("admin_verb","PEP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/view_all_rods()
set name = "VIEW-ALL-RODS"
set category = "Fun"
if(holder)
holder.ViewAllRods()
feedback_add_details("admin_verb","V-ROD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return

View File

@@ -5375,6 +5375,30 @@
PersistencePanel() //refresh!
// --- Rod tracking
else if (href_list["rod_to_untrack"])
if(!check_rights(R_FUN))
return
var/obj/item/projectile/P = locate(href_list["rod_to_untrack"])
if (!P)
return
P.tracking = FALSE
P.tracker_datum = null
qdel(P.tracker_datum)
var/log_data = "[P.original]"
if (ismob(P.original))
var/mob/M = P.original
if (M.client)
log_data += " (M.client.ckey)"
log_admin("[key_name(usr)] stopped a rod thrown at [log_data].")
message_admins("<span class='notice'>[key_name(usr)] stopped a rod thrown at [log_data].</span>")
ViewAllRods()
// ----- Religion and stuff
else if(href_list["ashpaper"])

View File

@@ -4,6 +4,8 @@
//As well as hurting all dense mobs
//Recoded as a projectile for better movement/appearance
var/list/all_rods = list()
/datum/event/immovable_rod
announceWhen = 1
@@ -71,6 +73,14 @@
lock_angle = 1
clongSound = 'sound/effects/immovablerod_clong.ogg'
/obj/item/projectile/immovablerod/New()
all_rods += src
..()
/obj/item/projectile/immovablerod/Destroy()
all_rods -= src
..()
/obj/item/projectile/immovablerod/hyper/New()
..()
var/image/I = image('icons/obj/objects_96x96.dmi',"immrod_bottom")
@@ -188,3 +198,29 @@
for (var/mob/M in range(loc,20))
to_chat(M,"<FONT size=[max(0, 5 - round(get_dist(src, M)/4))]>CLANG!</FONT>")
M.playsound_local(loc, clongSound, 100 - (get_dist(src,M)*5), 1)
/proc/random_start_turf(var/z)
var/startx
var/starty
var/chosen_dir = pick(NORTH, SOUTH, EAST, WEST)
switch(chosen_dir)
if(NORTH) //North, along the y = max edge
starty = world.maxy - (TRANSITIONEDGE + 2)
startx = rand((TRANSITIONEDGE + 2), world.maxx - (TRANSITIONEDGE + 2))
if(SOUTH) //South, along the y = 0 edge
starty = (TRANSITIONEDGE + 2)
startx = rand((TRANSITIONEDGE + 2), world.maxx - (TRANSITIONEDGE + 2))
if(EAST) //East, along the x = max edge
starty = rand((TRANSITIONEDGE + 2), world.maxy - (TRANSITIONEDGE + 2))
startx = world.maxx - (TRANSITIONEDGE + 2)
if(WEST) //West, along the x = 0 edge
starty = rand((TRANSITIONEDGE + 2), world.maxy - (TRANSITIONEDGE + 2))
startx = (TRANSITIONEDGE + 2)
var/turf/T = locate(startx, starty, z)
return T

View File

@@ -71,6 +71,9 @@ var/list/impact_master = list()
var/inaccurate = 0
var/turf/target = null
var/datum/tracker/tracker_datum = null
var/tracking = FALSE
var/dist_x = 0
var/dist_y = 0
var/dx = 0
@@ -115,6 +118,10 @@ var/list/impact_master = list()
X.apply_effects(stun, weaken, paralyze, irradiate, stutter, eyeblur, drowsy, agony, blocked)
/obj/item/projectile/proc/on_hit(var/atom/atarget, var/blocked = 0)
qdel(tracker_datum)
tracker_datum = null
if(blocked >= 100)
return 0//Full block
if(!isliving(atarget))
@@ -362,6 +369,16 @@ var/list/impact_master = list()
/obj/item/projectile/proc/OnFired(var/proj_target = original) //if assigned, allows for code when the projectile gets fired
target = get_turf(proj_target)
if (tracking)
if (istype(proj_target, /atom/movable))
var/atom/movable/the_target = proj_target
var/datum/tracker/T = new
T.name = "[src] tracker on [proj_target]"
T.target = target
src.tracker_datum = T
the_target.add_tracker(T)
dist_x = abs(target.x - starting.x)
dist_y = abs(target.y - starting.y)
@@ -419,6 +436,36 @@ var/list/impact_master = list()
bumped = 0
if (tracker_datum && tracker_datum.changed)
tracker_datum.changed = FALSE
var/dist = get_dist(tracker_datum.target, src)
if (tracker_datum.lost_position_distance && (dist > tracker_datum.lost_position_distance))
tracker_datum.active = FALSE
else
target = tracker_datum.target
var/turf/current = get_turf(src)
// recalculate trajectory based on new tracker data
if (target.x > current.x)
dx = EAST
else
dx = WEST
if (target.y > current.y)
dy = NORTH
else
dy = SOUTH
dist_x = abs(target.x - current.x)
dist_y = abs(target.y - current.y)
if(dist_x > dist_y)
error = dist_x/2 - dist_y
else
error = dist_y/2 - dist_x
if(rotate)
target_angle = round(Get_Angle(current,target))
sleep(projectile_speed)