I am using ServUO.

I would like to figure out a spawnrange/homerange number to use based on a regions rectangle. Has anyone done this or tried this before? So basically finding the center of a rectangle based on the X/Y had height/width provided in the region file. then from that center find a valid spawn location within that region withing range of the spawner. Basically I am recreating a "Working" town invasion system. Unless you want to pay 70$ to use Voxpires (Way to much for a Free Source code (IE to use on ServUO/RunUO if you have vitanex core installed) btw, but I know some people had the money to throw away) none of the other ones I've tested work properly. So I'm starting over, I've got it so that the Spawner will spawn mobiles in a valid location within range of the spawner so they are not all stacked in the center, but I want to be able to dynamically find the center AND from that extrapolate a range to set as the mobs home range. I am using the Miniboss spawners that are using to spawn the Minibosses/renown in the Abyss as my base with some changes of my own to stop the clumping at the spawner. I am kinda stuck at this point, I could just throw in a generic range but that doesn't seem practical especially for the larger towns. I'd also need a main controller which I could probably write up eventually because I want only ONE to be active at a given interval (ie maybe every 2 hours they switch). Also going to be working on a way to randomly choose what invasion type spawns when the individual town invasion is active. After that I'll have to work on a gump or another way to display what wave it's on and how many more mobs need to be killed to advance to the next wave. I originally considered using the Champ system but it's overly complicated.

So any help/direction would be nice.
 
I was browsing through the code looking for things that might help me do what I asked before and stumbled on this bit of code in the Champion spawn code. Ignoring the extraneous bits, and focusing on the parts where it gets the locations. Is there anyway I can use stuff from the region definitions to fill in parts for like the spawn bounds and whatnot?



Code:
        private Rectangle2D m_SpawnArea;
        private ChampionSpawnRegion m_Region;

		[CommandProperty(AccessLevel.GameMaster)]
		public int SpawnRadius { get; set; }

        public void SetInitialSpawnArea()
        {
            //Previous default used to be 24;
            SpawnArea = new Rectangle2D(new Point2D(X - SpawnRadius, Y - SpawnRadius),
				new Point2D(X + SpawnRadius, Y + SpawnRadius));
        }
        public void UpdateRegion()
        {
            if (m_Region != null)
                m_Region.Unregister();
            if (!Deleted && Map != Map.Internal)
            {
                m_Region = new ChampionSpawnRegion(this);
                m_Region.Register();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public Rectangle2D SpawnArea
        {
            get
            {
                return m_SpawnArea;
            }
            set
            {
                m_SpawnArea = value;
                InvalidateProperties();
                UpdateRegion();
            }
        }

        public void Respawn()
        {
            if (!m_Active || Deleted || m_Champion != null)
                return;
			int currentLevel = Level;
			int currentRank = Rank;
			int maxSpawn = (int)((double)MaxKills * 0.5d * SpawnMod);
			if (currentLevel >= 16)
				maxSpawn = Math.Min(maxSpawn, MaxKills - m_Kills);
			if (maxSpawn < 3)
				maxSpawn = 3;
			int spawnRadius = (int)(SpawnRadius * ChampionSystem.SpawnRadiusModForLevel(Level));
			Rectangle2D spawnBounds = new Rectangle2D(new Point2D(X - spawnRadius, Y - spawnRadius),
				new Point2D(X + spawnRadius, Y + spawnRadius));
			int mobCount = 0;
			foreach(Mobile m in m_Creatures)
			{
				if (GetRankFor(m) == currentRank)
					++mobCount;
			}
			while (mobCount <= maxSpawn)
            {
                Mobile m = Spawn();
                if (m == null)
                    return;
                Point3D loc = GetSpawnLocation(spawnBounds, spawnRadius);
                // Allow creatures to turn into Paragons at Ilshenar champions.
                m.OnBeforeSpawn(loc, Map);
                m_Creatures.Add(m);
                m.MoveToWorld(loc, Map);
				++mobCount;
                if (m is BaseCreature)
                {
                    BaseCreature bc = m as BaseCreature;
                    bc.Tamable = false;
                    bc.IsChampionSpawn = true;
                    if (!m_ConfinedRoaming)
                    {
                        bc.Home = Location;
						bc.RangeHome = spawnRadius;
                    }
                    else
                    {
                        bc.Home = bc.Location;
                        Point2D xWall1 = new Point2D(spawnBounds.X, bc.Y);
                        Point2D xWall2 = new Point2D(spawnBounds.X + spawnBounds.Width, bc.Y);
                        Point2D yWall1 = new Point2D(bc.X, spawnBounds.Y);
                        Point2D yWall2 = new Point2D(bc.X, spawnBounds.Y + spawnBounds.Height);
                        double minXDist = Math.Min(bc.GetDistanceToSqrt(xWall1), bc.GetDistanceToSqrt(xWall2));
                        double minYDist = Math.Min(bc.GetDistanceToSqrt(yWall1), bc.GetDistanceToSqrt(yWall2));
                        bc.RangeHome = (int)Math.Min(minXDist, minYDist);
                    }
                }
            }
        }
		public Point3D GetSpawnLocation()
		{
			return GetSpawnLocation(m_SpawnArea, 24);
		}
        public Point3D GetSpawnLocation(Rectangle2D rect, int range)
        {
            Map map = Map;
            if (map == null)
                return Location;
			int cx = Location.X;
			int cy = Location.Y;
            // Try 20 times to find a spawnable location.
            for (int i = 0; i < 20; i++)
            {
				int dx = Utility.Random(range * 2);
				int dy = Utility.Random(range * 2);
				int x = rect.X + dx;
				int y = rect.Y + dy;
				// Make spawn area circular
				//if ((cx - x) * (cx - x) + (cy - y) * (cy - y) > range * range)
				//	continue;
                int z = Map.GetAverageZ(x, y);
                if (Map.CanSpawnMobile(new Point2D(x, y), z))
                    return new Point3D(x, y, z);
                /* try @ platform Z if map z fails */
                else if (Map.CanSpawnMobile(new Point2D(x, y), m_Platform.Location.Z))
                    return new Point3D(x, y, m_Platform.Location.Z);
            }
            return Location;
        }
 
Back