ID:170516
 
Anything wrong with this pet system?

mob
Pet
icon = 'Pet.dmi'
icon_state = "1"
var/mob/owner
proc/AI()
while(1)
step_towards(src,owner)
sleep(2)

mob
Login()
..()
src.icon = 'playerboy.dmi'
src.icon_state = "1"
var/mob/Pet/P = new(locate(src.x,src.y+1,src.z))
P.owner = src
P.AI()


The point is to get a pet to follow you around.

Oh and what do you guys think of this:

id:319976
DeathAwaitsU wrote:
Anything wrong with this pet system?

Yup. Plenty:

mob
Pet
proc/AI()
while(1)
step_towards(src,owner)
sleep(2)


Now, look at AI() for a second. First of all, since it isn't set in the background it will crash after 255 run throughs. The problem occurs when either the pet is deleted or the owner logs out. If there is no owner, then it will be walking towards null, and if the pet gets deleted, then since AI() keeps running as long as the world exists, it will keep running, and therefore, cause a runtime.

Finally, I think that with that proc, you'll find some diffculties. First and foremost, if the player gets teleoprted somewhere or switches z levels, it wouldn't work. Second, you'll probably find the pet's movement relatively erratic when the player is standing still.

Of course, all of these problems can be avoided by overriding mob/Player/Move(). However, if you're doing that, you'll find it much, much more convenient to have a list of a player's pets.

Finally, alot of the things you're doing in mob/Login() should probably be done in mob/Pet/New() instead.

world/mob=/mob/Player

mob

Player

icon='playerboy.dmi'
icon_state="1"

var/list/pets=list()

Login()
..()
var/mob/Pet/P=new/mob/Pet(locate(src.x,src.y+1,src.z),src)

Move()
.=..()//Don't override Move()!
if(src.pets.len>0)//If src has any pets
for(var/mob/Pet/P as mob in pets)
if(P.follow)
if(P.z==src.z)//If src and P are on the same plain
step_towards(P,src)
else
P.loc=src.loc

Pet

icon='Pet.dmi'
icon_state="1"

var
owner
follow=1

New(NewLoc,mob/Player/P)
..()
src.owner=P.key
In response to Wizkidd0123
Your approach is good (using mob/Move()) but there are some problems too. :)

Wizkidd0123 wrote:
> world/mob=/mob/Player
>
> mob
>
> Player
>
> icon='playerboy.dmi'
> icon_state="1"
>
> var/list/pets=list()
>
> //
> // You forgot to add the pet to the list, so let's make a proc to do it.
> //
> proc/AddPet()
> var/mob/Pet/P=new/mob/Pet(locate(src.x,src.y+1,src.z),src)
> src.pets += P
>
> Login()
> ..()
> src.AddPet()
>
> Move()
> .=..()//Don't override Move()!
> //
> // The if statement is redundant - for() will do nothing if the list is empty.
> //
> //if(src.pets.len>0)//If src has any pets
> //
> // Took out "as mob" because it is meaningless here.
> // "as mob" is only useful to specify expected argument types for verbs.
> //
> for(var/mob/Pet/P in pets)
> if(P.follow)
> if(P.z==src.z)//If src and P are on the same plane
> step_towards(P,src)
> else
> P.loc=src.loc
>
> Pet
>
> icon='Pet.dmi'
> icon_state="1"
>
> var
> //
> // It's probably most useful to refer to the owner's mob, rather than \his key.
> //
> mob/owner=null
> follow=1
>
> New(NewLoc,mob/Player/P)
> ..()
> src.owner=P
>


Hope this helps!
In response to Wizkidd0123
Wizkidd0123 wrote:
Now, look at AI() for a second. First of all, since it isn't set in the background it will crash after 255 run throughs.

Huh? I've never heard anything about that, I'd like to know more.

The problem occurs when either the pet is deleted or the owner logs out. If there is no owner, then it will be walking towards null, and if the pet gets deleted, then since AI() keeps running as long as the world exists, it will keep running, and therefore, cause a runtime.

Just a note, when an object is deleted all procs belonging to that object go with it. You'd still have to worry that owner running off, of course. =)
In response to YMIHere
Take this exemple:
proc
MyProc()
world<<"Hello"
OtherProc()
world<<"Bye"
OtherProc()
world<<"Bob"


The result is:
Hello
Bob
Bye

When a procedure calls another, the first will pause until the second is complete. If you "stack" more then 255 procedure in this way, an error occures.

var/Counter=0 as num
proc
MyLoop()
Counter++
world<<Counter
MyLoop()

The result is:
1
2
...
254
255
ERROR

In this exemple, the procedure calls itself over and over, but none ever finish until 255 are called, which crashes. To get around this probleme, use spawn()

var/Counter=0 as num
proc
MyLoop()
Counter++
world<<Counter
spawn(5)
MyLoop()

This exemple, MyLoop will run ever 5 times ever second. I suggest you look up spawn in the reference.
In response to FranquiBoy
There is no stacking in the AI() proc though, it uses while(). =)
In response to YMIHere
Good Point
In response to YMIHere
YMIHere wrote:
There is no stacking in the AI() proc though, it uses while(). =)
The problem is that it is an infinate while() loop, which, unless you say otherwise with a set background, will crash with a runtime error eventually. They are best avoided, and the spawn example given by Franquiboy is a good idea to use in place of a while(1).

Franquiboy wrote:
MyLoop will run ever 5 times ever second.
Wrong. spawn(5) will run 2 times per second. 5 means 5/10 seconds to spawn().
In response to Mike H
Mike, I agree with everything you said there except for one thing:

//
// It's probably most useful to refer to the owner's mob, rather than \his key.
//


If owner referred to the mob, and not the key, in the case of a save, it wouldn't work correctly anymore. Of course, the owner variable could be temporary, but that wouldn't be very useful either, as we (probably) want it to remember the owner.

One solution is to have a temporary mob/ownerMob variable, but to keep the owner variable as a recording of the owner's key.
In response to YMIHere
YMIHere wrote:
Wizkidd0123 wrote:
Now, look at AI() for a second. First of all, since it isn't set in the background it will crash after 255 run throughs.

Huh? I've never heard anything about that, I'd like to know more.

Oops. I was thinking about stacked loops there when I said 255. Regardless, it still needs to be kept in the background.

If you want to know about stacked loops anyway (you probably already do), here's an example:

proc/MyLoop(n as num)
world << "We're looping for the [n]\th time."
MyLoop(++n)


If that proc were to be called, after 255 loops, it would crash. This is because each call of MyLoop() gets "stacked" on to the original call of MyLoop(). To fix this, we need spawn:

proc/MyLoop(n as num)
world << "We're looping for the [n]\th time."
spawn()
MyLoop(++n)
In response to Wizkidd0123
Wizkidd0123 wrote:
If you want to know about stacked loops anyway (you probably already do), here's an example:

I didn't know they stopped at 255, that information could prove useful. =)

Nova, I'm testing that out right now with this:

mob/verb/testwhile()
var/counter=0
while(1)
counter++
world<<counter
sleep(2)


I've only known infinite loops to lock up Dream Seeker, so naturally, I have to run a test. =)

p.s. I'm at 2900.


*Edit
Speaking of testing, I can only get stacking to go to 198. Which I think on my system shows the error when trying to stack on the 200th proc.

mob/verb/teststack()
stack(0)
mob/proc/stack(n)
world<<++n
sleep(2)
stack(n)