This is a change to the Populator code to what I invisioned it before I tried to use it :-). This allows you to place a Spawnpoint much like a normal spawn point and call it POPULATOR_x and it will us that spawnpoint to randomly load mobs in that spawn group a 200x200 square around that area (100 in all directions). The mobs will roam around the area with the randomly generated walking points. You can use more than 1 populator in a zone and you can reuse populators to make the population more dense or what not.
This is good for open areas and probably not the best idea for a closed off area like a cave, fortress, city, etc.
--Xerves
mud/world/spawn.py
In the Spawnpoint class find the following bit of code:
if group.startswith("POPULATOR_"):
p,num=group.split("_")
num = int(num)
if zone.populatorGroups.has_key(num):
group = zone.populatorGroups[num]
else:
groups = []
fgroups = []
gengroups = []
for sg in zone.zone.spawnGroups:
if sg.targetName or sg.popFreq<0:
continue
unique = False
for sinfo in sg.spawninfos:
if sinfo.spawn.flags&RPG_SPAWN_UNIQUE:
unique=True
break
if unique:
print "Warning: pop group contains a unique spawn",sg.groupName
continue
if "CMT_RANK" in sg.groupName:
gengroups.append(sg)
elif "PRT_RANK" in sg.groupName:
gengroups.append(sg)
elif "MGE_RANK" in sg.groupName:
gengroups.append(sg)
elif "RGE_RANK" in sg.groupName:
gengroups.append(sg)
elif sg.popFreq>1:
fgroups.append(sg)
else:
groups.append(sg)
if len(gengroups):
g= None
if len(gengroups)==1:
g=gengroups[0]
else:
g=gengroups[random.randint(0,len(gengroups)-1)]
if g.popFreq>1:
fgroups.append(g)
else:
groups.append(g)
for g in fgroups:
if not random.randint(0,g.popFreq):
groups.append(g)
if not len(groups):
print "WARNING!!!!! No spawn for populator"
elif len(groups)==1:
group=groups[0].groupName.upper()
else:
group=groups[random.randint(0,len(groups)-1)].groupName.upper()
zone.populatorGroups[num]=group
You need to comment out this whole if check here using the """ at the begining of the check and """ at the end. You can delete it to if you like.
/mud/simulation/populator.py
Replace this whole file with this code. I made a variety of changes.
# Copyright (C) 2004-2007 Prairie Games, Inc
# Please see LICENSE.TXT for details
from tgenative import *
from mud.tgepython.console import TGEExport
import random
from mud.simulation.shared.simdata import SpawnpointInfo
import math
#Change the area covered. Will make the pops more dense too
POPULATOR_AREA = 200
#Maximum amount of enemies loaded. Also used to generated a random value
POPULATOR_POPMAX = 7
class Populator:
def __init__(self,spawnpoints,paths):
self.cspawnpoints = spawnpoints
self.paths = paths
self.minz = 1000000
self.maxz = -1000000
print "Loading Populators:"
#Find a middle ground for height among spawnpoints
for sp in self.cspawnpoints:
t = sp.transform
if t[2] < self.minz:
self.minz = t[2]
if t[2] > self.maxz:
self.maxz = t[2]
self.midZ = self.minz+(self.maxz-self.minz)/2
self.spawnpoints = []
self.paths = {}
self.waypoints = {}
#Create spawning points and wander groups now using actual POPULATOR_x placers
for sp in self.cspawnpoints:
if sp.group.startswith("POPULATOR_"):
p,popnum=sp.group.split("_")
popnum = int(popnum)
t = sp.transform
bx = t[0]
by = t[1]
#populator bin (only 1 now per populator) is a 200x200 area with 100 in each direction of the POPULATOR_x placer
self.bins = {}
self.binPaths = {}
#Going to build a list of points, increase /5 for more density
for y in xrange(by-POPULATOR_AREA/2,by+POPULATOR_AREA/2,POPULATOR_AREA/5):
for x in xrange(bx-POPULATOR_AREA/2,bx+POPULATOR_AREA/2,POPULATOR_AREA/5):
z = float(TGECall('MyCheckGridPoint',"%f %f %f"%(x,y,self.midZ)))
if z:
if not self.bins.has_key((bx,by)):
self.bins[(bx,by)]=[]
self.bins[(bx,by)].append((x,y,z))
numpoints = 0
#Make sure we have enough points to roam on
for bin,points in self.bins.items():
num = len(points)
if num < 4:
del self.bins[bin]
continue
numpoints += num
x = 0
for p1 in points:
y = 0
for p2 in points:
if x == y:
y+=1
continue
#if math.fabs(p1[2]-p2[2]<8) #XXX: We actually do need to do this so that mobs are'nt trying to walk up too steep of incluses
#but it messes with stuff below, and there might be a bug with waypoints/paths without it
result = TGECall('MyCastRay',"%f %f %f"%(p1[0],p1[1],p1[2]+4),"%f %f %f"%(p2[0],p2[1],p2[2]+4))
if int(result):
if not self.binPaths.has_key(bin):
self.binPaths[bin]={}
if not self.binPaths[bin].has_key(x):
self.binPaths[bin][x]=[]
self.binPaths[bin][x].append(y)
y+=1
x+=1
#Build Spawn Points now
for bin,points in self.bins.iteritems():
spcount = 0
if self.binPaths.has_key(bin):
#Create paths and waypoints if this is a wandering group
if len(self.binPaths[bin])>=4 and sp.wanderGroup > -1:
self.paths[sp.wanderGroup ]=self.binPaths[bin]
self.waypoints[sp.wanderGroup ]=[]
for p in points:
self.waypoints[sp.wanderGroup].append((p[0],p[1],p[2],1, 0, 0, 0))
for p in points:
randnum = math.floor(len(points)/POPULATOR_POPMAX)
if randnum < 1:
randnum = 1
#It is typical to have 20 or so points, 20 mobs will be VERY dense
if (random.randint(1,randnum) == 1 and spcount < POPULATOR_POPMAX):
spoint = SpawnpointInfo()
rot = TGECall("MyRandomRotation")
rot = rot.split(" ")
spoint.transform = (p[0],p[1],p[2],float(rot[0]),float(rot[1]),float(rot[2]),float(rot[3]))
spoint.group = "POPULATOR_%i"%popnum
spoint.wanderGroup = sp.wanderGroup
self.spawnpoints.append(spoint)
spcount += 1
print "POPULATOR_%i loaded with %i points and %i spawnpoints"%(popnum, numpoints, spcount)
def Populate(spawnpoints,paths):
p = Populator(spawnpoints,paths)
return p.spawnpoints,p.paths,p.waypoints
Usage
That is it :-). Now to actually make use of it you need to do the same thing as you would with a normal spawngroup. First create the spawn group.
mob2 = DBSpawnInfo(spawn="Wild Wolf") sg = DBSpawnGroup(zone="newzone",groupName="POPULATOR_0",popFreq=RPG_FREQ_ALWAYS) sg.addSpawnInfo(mob2) mob4 = DBSpawnInfo(spawn="Bat") sg = DBSpawnGroup(zone="newzone",groupName="POPULATOR_1",popFreq=RPG_FREQ_ALWAYS) sg.addSpawnInfo(mob4)
This is an example of two spawn groups with a wolf and a bat.
Second you need to create an rpgSpawnPoint for this populator. Go into the zone and edit it and place an rpgSpawnPoint. Call it POPULATOR_0 or any other number you have and then assign a Wandergroup value (-1 is no wander, anything after that will make the group wander). Make sure to set it to a unique value unless you want multiple populator roaming areas.
Save and either /imm recompile or exit out and come back into the game. You should see around 5-7 mobs in the area.
Notes:
* Mobs will load out of the playable area if near the border, they can come in and out of it though so beware of this.
* Not sure what happens if it roams into a teleporter or anything like that.
* Test test test
* You should notice a message that the Populator is loading per zone along with how many points and spawns. Keep an eye on this to make sure enough points are found to create a populator. If it is not check your terrain or use manual spawns.
* The Populator function needs to be turned on when testing offline. It is in the Game Options in the client.

