Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Makes wayfinding great again #56055

Merged
merged 23 commits into from Jan 16, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 24 additions & 0 deletions code/game/atoms.dm
Expand Up @@ -1769,3 +1769,27 @@
/atom/proc/InitializeAIController()
if(ai_controller)
ai_controller = new ai_controller(src)

/**
* Point at an atom
*
* Moved from pointed() verb in mob.dm
cacogen marked this conversation as resolved.
Show resolved Hide resolved
*
* Intended to enable and standardise the pointing animation for all atoms
*
* Not intended as a replacement for the mob verb
*/
/atom/proc/pointat(atom/A as mob|obj|turf in view())
cacogen marked this conversation as resolved.
Show resolved Hide resolved
if(!src || !isturf(src.loc))
cacogen marked this conversation as resolved.
Show resolved Hide resolved
return FALSE

var/turf/tile = get_turf(A)
if (!tile)
return FALSE

var/turf/our_tile = get_turf(src)
var/obj/visual = new /obj/effect/temp_visual/point(our_tile, invisibility)

animate(visual, pixel_x = (tile.x - our_tile.x) * world.icon_size + A.pixel_x, pixel_y = (tile.y - our_tile.y) * world.icon_size + A.pixel_y, time = 1.7, easing = EASE_OUT)

return TRUE
92 changes: 50 additions & 42 deletions code/game/objects/items/wayfinding.dm
Expand Up @@ -2,18 +2,26 @@
name = "wayfinding pinpointer synthesizer"
icon = 'icons/obj/machines/wayfinding.dmi'
icon_state = "pinpointersynth"
desc = "Having trouble finding your way? This machine synthesizes pinpointers that point to common locations."
desc = "A machine given the thankless job of trying to sell these pinpointers. They point to common locations."
density = FALSE
layer = HIGH_OBJ_LAYER
///List of user-specific cooldowns to prevent pinpointer spam.
var/list/user_spawn_cooldowns = list()
///List of user-specific cooldowns to prevent message spam.
var/list/user_interact_cooldowns = list()
var/spawn_cooldown = 5 MINUTES //time per person to spawn another pinpointer
var/interact_cooldown = 20 SECONDS //time per person for subsequent interactions
var/start_bal = 200 //how much money it starts with to cover wayfinder refunds
var/refund_amt = 40 //how much money recycling a pinpointer rewards you
///Time per person to spawn another pinpointer.
var/spawn_cooldown = 2 MINUTES
///Time per person for subsequent interactions.
var/interact_cooldown = 4 SECONDS
///How many credits the dispenser account starts with to cover wayfinder refunds.
var/start_bal = 200
///How many credits recycling a pinpointer rewards you.
var/refund_amt = 40
cacogen marked this conversation as resolved.
Show resolved Hide resolved
var/datum/bank_account/synth_acc = new /datum/bank_account/remote
var/ppt_cost = 65 //Jan 6 '20: Assistant can buy one roundstart (125 cr starting)
var/ppt_cost = 0 //Jan 9 '21: 2560 had its difficulties for NT as well
var/expression_timer
///Avoid being Reddit.
var/funnyprob = 5

/obj/machinery/pinpointer_dispenser/Initialize(mapload)
. = ..()
Expand All @@ -23,40 +31,35 @@

synth_acc.account_holder = name

desc += " Only [ppt_cost] credits! It also likes making costumes..."
desc += " [ppt_cost ? "Only [ppt_cost] credits! " : ""]It also synthesises costumes for some reason."

set_expression("neutral")
set_expression("happy") //actual first law of robotics it needs to be friendly in a mindless way

/obj/machinery/pinpointer_dispenser/attack_hand(mob/living/user)
if(world.time < user_interact_cooldowns[user.real_name])
to_chat(user, "<span class='warning'>It doesn't respond.</span>")
to_chat(user, "<span class='notice'>It just grins at you. Maybe you should give it a few seconds?</span>")
set_expression("veryhappy", 2 SECONDS)
cacogen marked this conversation as resolved.
Show resolved Hide resolved
return

user_interact_cooldowns[user.real_name] = world.time + interact_cooldown

for(var/obj/item/pinpointer/wayfinding/WP in user.GetAllContents())
set_expression("unsure", 2 SECONDS)
say("<span class='robot'>I can detect the pinpointer on you, [user.first_name()].</span>")
user_spawn_cooldowns[user.real_name] = world.time + spawn_cooldown //spawn timer resets for trickers
set_expression("veryhappy", 2 SECONDS)
say("<span class='robot'>You already have a pinpointer!</span>")
return

var/msg
var/dispense = TRUE
var/obj/item/pinpointer/wayfinding/pointat
for(var/obj/item/pinpointer/wayfinding/WP in range(7, user))
if(WP.Adjacent(user))
set_expression("facepalm", 2 SECONDS)
say("<span class='robot'>[WP.owner == user.real_name ? "Your" : "A"] pinpointer is right there.</span>")
pointat(WP)
user_spawn_cooldowns[user.real_name] = world.time + spawn_cooldown
return
else if(WP in oview(7, user))
pointat = WP
break
set_expression("veryhappy", 2 SECONDS)
say("<span class='robot'>[WP.owner == user.real_name ? "Your" : "A"] pinpointer is there!</span>")
pointat(WP)
return

if(world.time < user_spawn_cooldowns[user.real_name])
var/secsleft = (user_spawn_cooldowns[user.real_name] - world.time) / 10
msg += "to wait another [secsleft/60 > 1 ? "[round(secsleft/60,1)] minute\s" : "[round(secsleft)] second\s"]"
msg += "to wait another [secsleft/60 > 1 ? "[round(secsleft/60,1)] minute\s" : "[round(secsleft)] second\s"] before I can dispense a pinpointer"
dispense = FALSE

var/datum/bank_account/cust_acc = user.get_bank_account()
Expand All @@ -69,14 +72,14 @@
if(!dispense)
set_expression("sad", 2 SECONDS)
if(pointat)
msg += ". I suggest you get [pointat.owner == user.real_name ? "your" : "that"] pinpointer over there instead"
msg += ". Get [pointat.owner == user.real_name ? "your" : "that"] pinpointer over there instead"
pointat(pointat)
say("<span class='robot'>You will need [msg], [user.first_name()].</span>")
say("<span class='robot'>Sorry, [user.first_name()]. You need [msg]!</span>")
return

if(synth_acc.transfer_money(cust_acc, ppt_cost))
set_expression("veryhappy", 2 SECONDS)
say("<span class='robot'>That is [ppt_cost] credits. Here is your pinpointer.</span>")
say("<span class='robot'>Here's your pinpointer!</span>")
var/obj/item/pinpointer/wayfinding/P = new /obj/item/pinpointer/wayfinding(get_turf(src))
user_spawn_cooldowns[user.real_name] = world.time + spawn_cooldown
user.put_in_hands(P)
Expand All @@ -86,36 +89,41 @@
if(istype(I, /obj/item/pinpointer/wayfinding))
var/obj/item/pinpointer/wayfinding/WP = I
to_chat(user, "<span class='notice'>You put \the [WP] in the return slot.</span>")
var/rfnd_amt
if((!WP.roundstart || WP.owner != user.real_name) && synth_acc.has_money(TRUE)) //can't recycle own pinpointer for money if not bought; given by a neutral quirk
if(synth_acc.has_money(refund_amt))
rfnd_amt = refund_amt
else
rfnd_amt = synth_acc.account_balance
synth_acc._adjust_money(-rfnd_amt)
var/obj/item/holochip/HC = new /obj/item/holochip(user.loc)
HC.credits = rfnd_amt
var/refundiscredits = TRUE
if(synth_acc.has_money(refund_amt) && !WP.roundstart && WP.owner != user.real_name) //exploiters bring a friend
synth_acc._adjust_money(-refund_amt)
var/obj/item/holochip/HC = new /obj/item/holochip(loc)
HC.credits = refund_amt
HC.name = "[HC.credits] credit holochip"
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
H.put_in_hands(HC)
else
var/crap = pick(subtypesof(/obj/effect/spawner/bundle/costume)) //harmless garbage some people may appreciate
new crap(user.loc)
refundiscredits = FALSE
var/costume = pick(subtypesof(/obj/effect/spawner/bundle/costume))
new costume(user.loc)
qdel(WP)
set_expression("happy", 2 SECONDS)
say("<span class='robot'>Thank you for recycling, [user.first_name()]! Here is [rfnd_amt ? "[rfnd_amt] credits." : "a freshly synthesized costume!"]</span>")
set_expression("veryhappy", 2 SECONDS)
var/refund = "some credits."
var/whatyoudid = "recycling"
if(!refundiscredits)
refund = "freshly synthesised costume!"
if(prob(funnyprob))
refund = "pulse rifle! Just kidding it's a costume."
else if(prob(funnyprob))
whatyoudid = "feeding me"
say("<span class='robot'>Thank you for [whatyoudid], [user.first_name()]! Here is a [refund]</span>")

/obj/machinery/pinpointer_dispenser/proc/set_expression(type, duration)
cut_overlays()
deltimer(expression_timer)
add_overlay(type)
if(duration)
expression_timer = addtimer(CALLBACK(src, .proc/set_expression, "neutral"), duration, TIMER_STOPPABLE)
expression_timer = addtimer(CALLBACK(src, .proc/set_expression, "happy"), duration, TIMER_STOPPABLE)

/obj/machinery/pinpointer_dispenser/proc/pointat(atom)
visible_message("<span class='name'>[src]</span> points at [atom].")
new /obj/effect/temp_visual/point(atom,invisibility)
/obj/machinery/pinpointer_dispenser/pointat(A)
. = ..()
visible_message("<span class='name'>[src]</span> points at [A].")

//Pinpointer itself
/obj/item/pinpointer/wayfinding //Help players new to a station find their way around
Expand Down
10 changes: 1 addition & 9 deletions code/modules/mob/mob.dm
Expand Up @@ -571,20 +571,12 @@
set name = "Point To"
set category = "Object"

if(!src || !isturf(src.loc))
return FALSE
if(client && !(A in view(client.view, src)))
return FALSE
if(istype(A, /obj/effect/temp_visual/point))
return FALSE

var/turf/tile = get_turf(A)
if (!tile)
return FALSE

var/turf/our_tile = get_turf(src)
var/obj/visual = new /obj/effect/temp_visual/point(our_tile, invisibility)
animate(visual, pixel_x = (tile.x - our_tile.x) * world.icon_size + A.pixel_x, pixel_y = (tile.y - our_tile.y) * world.icon_size + A.pixel_y, time = 1.7, easing = EASE_OUT)
pointat(A)

return TRUE

Expand Down