ID:140341
 
Code:
world

New()
spawn(2)
SpawnMons()

proc
SpawnMons()
while(src)
new /monsters(/area/random)
sleep(25)
area
var/list/tcontents = new()
New()
..()
for(var/turf/X in src.contents)
tcontents.Add(X)
random

monsters
parent_type = /mob

var
var_health
max_health

New(Spawn_pt)
spawn(1)
DIE()
Spawn_Mob(Spawn_pt)
sleep(20)
src.var_health = 0

proc
DIE()
while(src)
if(src.var_health <= 0)
world << "[src.name] died."
del src
else
sleep(1)

Spawn_Mob(area/A)
var/turf/T = pick(A.tcontents)
src.loc = T.loc
world << "[src.name] has been spawned at [src.x],[src.y],[src.z]"


Problem description:
runtime error: Cannot read /area/random (/area/random).tcontents
proc name: Spawn Mob (/monsters/proc/Spawn_Mob)
usr: the monsters (/monsters)
src: the monsters (/monsters)
call stack:
the monsters (/monsters): Spawn Mob(/area/random (/area/random))
the monsters (/monsters): New(/area/random (/area/random))
: SpawnMons()
: New()



I am using XML to store the mobs in a database and wanted to setup a spawn to randomly locate the mobs in a turf in the area.

I am attempting to recreate the area list, putting only the turfs in, then using this list to place the mob randomly in the area, but keep getting a runtime.

Any insight on what I did wrong ?

Thanks

You are giving the proc the typepath /area/random, but not an actual instance of that area. new() and Move() will handle area typepaths, but if you want to do something else with it you'll need to use locate() to actually find an instance of an area.
In response to Garthor
Wow, now that makes me feel stupid.

Thanks for the help!



The next thing that popped up was, it puts the monster in the bottom left corner. I know this was intended behavior for Byond, but how else would I go about selecting a random spot in an area?

Thanks,
Pirion
In response to Pirion
You'd need to pick a turf in the area's contents. However, this is a bit tricky as movables are in the contents of an area as well. The most straightforward (though perhaps not best) solution is just to keep on picking randomly until you get one:

area/proc/random_turf()
var/turf/T
do
T = pick(contents)
while(!isturf(T))
return T


A more complex solution would be to maintain a list of turfs in an area and simply pick from that, but that ends up getting convoluted rather quickly as there's no handle for when an area's contents change (or a turf's loc changes). Repeatedly picking randomly is probably your best bet, stupid as it is.

Just don't ever let there be NO valid turfs in an area.
In response to Garthor
Using pick(area.contents) always returns the bottom-left corner of the area location.



monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.
monsters has been spawned at 1,1,1
monsters died.


I tested by removing some from the bottom left corner, and it didn't spawn where i removed it.


Any idea how to work around it to pick ?

I am thinking finding how many area tiles are located in the world of that type - then looping though a random amount of them but that seems a little crazy to do...and would cause lag?

I guess I will try it out, please let me know if you have any other suggestions.
In response to Pirion
I tested it and had no issues. Are you sure you're actually creating it at the turf picked?
In response to Garthor
I have no idea. I deleted it and put it back in and it worked, so I must have made a mistake.

Thanks Garthor!