ID:157505
 
I'm working on a project, and one of the features I would like to add in is a pull mode. You know? Click on a button to turn the mode on then click another obj and the player's mob will start dragging the object the automatically with it following behind the mob, then click on the obj again to stop pulling it. I've seen many games with it, so I know it's possible somehow. I looked everywhere for some sort of tutorial or library and on the forums, but I found absolutely nothing. Can someone help me get started with a proc or something so I know where to go? Also, once I find something, would I be able to adapt it into a follow mode (turn on the follow then use it to have the player mob follow another mob)?

Thanks in advance!
Code:
mob/var/tmp/obj/Pulling

obj/Pullable/Click()
if(get_dist(usr, src) <= 1)
if(src == usr.Pulling)
walk(src, 0)
usr.Pulling = null
else
if(usr.Pulling) walk(usr.Pulling, 0)
usr.Pulling = src
walk_to(src, usr, 1)


This proc will first check to see if the player is close to the object, within one tile. Then it checks to see if the player is already pulling the object. If they are, it stops pulling it.

If they weren't already pulling the object, then it stops pulling anything the player may have been pulling before, and then starts pulling the object that was just clicked.
This is how I'd implement it.

obj
Click()
if(get_dist(src, usr) <= 1)
usr.PullSwap(src)

proc/Pull(atom/newloc, mob/m)
if(!src.Exit(loc))
// If the object can't exit the turf it's
// in, stop pulling.
m.PullSwap(src)
return 0

if(!src.Move(newloc))
// If the object can't enter the place it's
// being pulled into, stop pulling.
m.PullSwap(src)
return 0

return 1

mob
var/obj/pulling

Move(atom/newloc)
var/atom/oldloc = src // Used below.

if(pulling && !(newloc in view(src))
// If the user is pulling something, they can
// not move to something outside their view.
// This prevents them from, say, going through
// doors, which could make all of this wonky.
return 0

. = ..()

if(pulling)
// This makes sure they are facing the thing
// they're pulling.
dir = turn(get_dir(oldloc, newloc), 180)
pulling.Pull(oldloc, src) // Call the obj's Pull()
// proc.

proc/PullSwap(obj/o)
if(pulling == o)
pulling = null
else
pulling = o
In response to Popisfizzy
Fixing a typo before they come back because "it doesn't work".

    proc/Pull(atom/newloc, mob/m)
if(!src.Exit(loc))
// If the object can't exit the turf it's
// in, stop pulling.
m.PullSwap(src)
return 0

if(!src.Move(newloc))
// If the object can't enter the place it's
// being pulled into, stop pulling.
m.PullSwap(src)
return 0

return 1

You can simplify your PullSwap() proc by using the ? operator.
    proc/PullSwap(obj/o)
src.pulling = src.pulling == o ? null : o
In response to Ulterior Motives
Ulterior Motives wrote:
Also you can simplify your PullSwap() proc by simply using the ? operator.

>     proc/PullSwap(obj/o)
> src.pulling = src.pulling == o ? null : o
>


Yes, you can, but that doesn't make it any easier for newbies to understand.
In response to Popisfizzy
Popisfizzy wrote:
Yes, you can, but that doesn't make it any easier for newbies to understand.

because your code was so newbie friendly to begin with
In response to Zaole
Yes. Good logic. I should actively make my code more difficult to understand, because it's already not piss-easy to figure out.