public List <NPCType> GetUniqueSpawns()
        {
            foreach (NPCType n in _NPCTypeList)
            {
                if (NPCType.IsPlayableRace(n.Race) || NPCType.IsGuardRace(n.Race))
                {
                    n.Unique = true;
                }
                else
                {
                    n.Unique = false;
                }
            }

            for (int i = 0; i < _NPCTypeList.Count; ++i)
            {
                for (int j = 0; j < _NPCTypeList.Count; ++j)
                {
                    if ((i != j) && (_NPCTypeList[i].Name == _NPCTypeList[j].Name))
                    {
                        _NPCTypeList[i].Unique = false;
                    }
                }
            }

            List <NPCType> Results = new List <NPCType>();

            foreach (NPCType n in _NPCTypeList)
            {
                if (n.Unique)
                {
                    Results.Add(n);
                }
            }

            return(Results);
        }
示例#2
0
        public void GenerateSpawnSQL(bool GenerateSpawns, bool GenerateGrids, bool GenerateMerchants,
                                     string ZoneName, UInt32 ZoneID, UInt32 SpawnVersion,
                                     bool UpdateExistingNPCTypes, bool UseNPCTypesTint, string SpawnNameFilter,
                                     bool CoalesceWaypoints, bool IncludeInvisibleMen, Action <string> SQLOut)
        {
            UInt32 NPCTypeDBID  = 0;
            UInt32 SpawnGroupID = 0;
            UInt32 SpawnEntryID = 0;
            UInt32 Spawn2ID     = 0;
            UInt32 GridDBID     = 0;
            UInt32 MerchantDBID = 0;

            List <ZoneEntryStruct> ZoneSpawns = PatchDecoder.GetSpawns();

            List <UInt32> FindableEntities = PatchDecoder.GetFindableSpawns();

            if (GenerateSpawns)
            {
                SQLOut("--");
                SQLOut("-- Spawns");
                SQLOut("--");
                if (SpawnVersion == 0)
                {
                    SQLOut("DELETE from npc_types where id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999 and version = " + SpawnVersion + ";");

                    if (UseNPCTypesTint)
                    {
                        SQLOut("DELETE from npc_types_tint where id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999;");
                    }

                    SQLOut("DELETE from spawngroup where id IN (select spawnGroupID from spawnentry where npcid between @StartingSpawnEntryID AND @StartingSpawnEntryID+999);");
                    SQLOut("DELETE from spawn2 where spawnGroupID IN (select spawnGroupID from spawnentry where npcid between @StartingSpawnEntryID AND @StartingSpawnEntryID+999) and version = " + SpawnVersion + ";");
                    SQLOut("DELETE from spawnentry where npcid between @StartingSpawnEntryID AND @StartingSpawnEntryID+999;");
                }
                else
                {
                    SQLOut("DELETE from npc_types where id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 99 and version = " + SpawnVersion + ";");
                    SQLOut("DELETE from spawngroup where id IN (select spawnGroupID from spawnentry where npcid between @StartingSpawnEntryID AND @StartingSpawnEntryID+99);");
                    SQLOut("DELETE from spawn2 where spawnGroupID IN (select spawnGroupID from spawnentry where npcid between @StartingSpawnEntryID AND @StartingSpawnEntryID+99) and version = " + SpawnVersion + ";");
                    SQLOut("DELETE from spawnentry where spawngroupID IN (select spawnGroupID from spawnentry where npcid between @StartingSpawnEntryID AND @StartingSpawnEntryID+99);");
                }
            }

            NPCTypeList NPCTL = new NPCTypeList();

            NPCSpawnList NPCSL = new NPCSpawnList();

            foreach (ZoneEntryStruct Spawn in ZoneSpawns)
            {
                if (NPCType.IsMount(Spawn.SpawnName))
                {
                    continue;
                }

                if (!IncludeInvisibleMen && (Spawn.Race == 127))
                {
                    continue;
                }

                Spawn.Findable = (FindableEntities.IndexOf(Spawn.SpawnID) >= 0);

                if (Spawn.IsNPC != 1)
                {
                    continue;
                }

                if (Spawn.PetOwnerID > 0)
                {
                    continue;
                }

                if ((SpawnNameFilter.Length > 0) && (Spawn.SpawnName.IndexOf(SpawnNameFilter) == -1))
                {
                    continue;
                }

                bool ColoursInUse = false;

                for (int ColourSlot = 0; ColourSlot < 9; ++ColourSlot)
                {
                    if (((Spawn.SlotColour[ColourSlot] & 0x00ffffff) != 0) && UseNPCTypesTint)
                    {
                        ColoursInUse = true;
                    }
                }

                if (Spawn.IsMercenary > 0)
                {
                    continue;
                }

                UInt32 ExistingDBID = NPCTL.FindNPCType(Spawn.SpawnName, Spawn.Level, Spawn.Gender, Spawn.Size, Spawn.Face, Spawn.WalkSpeed, Spawn.RunSpeed, Spawn.Race,
                                                        Spawn.BodyType, Spawn.HairColor, Spawn.BeardColor, Spawn.EyeColor1, Spawn.EyeColor2, Spawn.HairStyle, Spawn.Beard,
                                                        Spawn.DrakkinHeritage, Spawn.DrakkinTattoo, Spawn.DrakkinDetails, Spawn.Deity, Spawn.Class, Spawn.EquipChest2,
                                                        Spawn.Helm, Spawn.LastName);


                if (ExistingDBID == 0)
                {
                    NPCType NewNPCType = new NPCType(NPCTypeDBID, Spawn.SpawnName, Spawn.Level, Spawn.Gender, Spawn.Size, Spawn.Face, Spawn.WalkSpeed, Spawn.RunSpeed, Spawn.Race,
                                                     Spawn.BodyType, Spawn.HairColor, Spawn.BeardColor, Spawn.EyeColor1, Spawn.EyeColor2, Spawn.HairStyle, Spawn.Beard,
                                                     Spawn.DrakkinHeritage, Spawn.DrakkinTattoo, Spawn.DrakkinDetails, Spawn.Deity, Spawn.Class, Spawn.EquipChest2,
                                                     Spawn.Helm, Spawn.LastName, Spawn.Findable, Spawn.MeleeTexture1, Spawn.MeleeTexture2, Spawn.ArmorTintRed, Spawn.ArmorTintGreen, Spawn.ArmorTintBlue, Spawn.SlotColour, Spawn.StandState);

                    NPCTL.AddNPCType(NewNPCType);

                    ExistingDBID = NPCTypeDBID++;

                    UInt32 ArmorTintID = 0;

                    if (ColoursInUse)
                    {
                        ArmorTintID          = ExistingDBID;
                        Spawn.ArmorTintRed   = 0;
                        Spawn.ArmorTintGreen = 0;
                        Spawn.ArmorTintBlue  = 0;
                    }

                    string NPCTypesQuery = "INSERT INTO npc_types(`id`, `name`, `lastname`, `level`, `gender`, `size`, `runspeed`,`race`, `class`, `bodytype`, `hp`, `texture`, `helmtexture`, `face`, `luclin_hairstyle`, `luclin_haircolor`, `luclin_eyecolor`, `luclin_eyecolor2`,`luclin_beard`, `luclin_beardcolor`, `findable`, `version`, `d_meele_texture1`, `d_meele_texture2`, `armortint_red`, `armortint_green`, `armortint_blue`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`,`special_abilities`,`slow_mitigation`) VALUES(";

                    NPCTypesQuery += "@StartingNPCTypeID + " + ExistingDBID + ", '" + Spawn.SpawnName + "', " + "'" + Spawn.LastName + "', " + Spawn.Level + ", " + Spawn.Gender + ", " + Spawn.Size + ", ";
                    NPCTypesQuery += Spawn.RunSpeed + ", " + Spawn.Race + ", " + Spawn.Class + ", " + Spawn.BodyType + ", " + Spawn.Level * (10 + Spawn.Level) + ", ";
                    NPCTypesQuery += Spawn.EquipChest2 + ", " + Spawn.Helm + ", " + Spawn.Face + ", " + Spawn.HairStyle + ", " + Spawn.HairColor + ", " + Spawn.EyeColor1 + ", ";
                    NPCTypesQuery += Spawn.EyeColor2 + ", " + Spawn.Beard + ", " + Spawn.BeardColor + ", " + (Spawn.Findable ? 1 : 0) + ", " + SpawnVersion + ", ";
                    NPCTypesQuery += Spawn.MeleeTexture1 + ", " + Spawn.MeleeTexture2 + ", " + Spawn.ArmorTintRed + ", " + Spawn.ArmorTintGreen + ", " + Spawn.ArmorTintBlue + ", ";
                    NPCTypesQuery += Spawn.DrakkinHeritage + ", " + Spawn.DrakkinTattoo + ", " + Spawn.DrakkinDetails + ",'',0);";

                    if (GenerateSpawns)
                    {
                        SQLOut(NPCTypesQuery);
                    }

                    if (GenerateSpawns && ColoursInUse && NPCType.IsPlayableRace(Spawn.Race))
                    {
                        string TintQuery = "REPLACE INTO npc_types_tint(id, tint_set_name, ";
                        TintQuery += "red1h, grn1h, blu1h, ";
                        TintQuery += "red2c, grn2c, blu2c, ";
                        TintQuery += "red3a, grn3a, blu3a, ";
                        TintQuery += "red4b, grn4b, blu4b, ";
                        TintQuery += "red5g, grn5g, blu5g, ";
                        TintQuery += "red6l, grn6l, blu6l, ";
                        TintQuery += "red7f, grn7f, blu7f, ";
                        TintQuery += "red8x, grn8x, blu8x, ";
                        TintQuery += "red9x, grn9x, blu9x) values(@StartingNPCTypeID + " + ExistingDBID + ", '" + Spawn.SpawnName + "'";

                        for (int sc = 0; sc < 9; ++sc)
                        {
                            TintQuery += String.Format(", {0}, {1}, {2}", (Spawn.SlotColour[sc] >> 16) & 0xff,
                                                       (Spawn.SlotColour[sc] >> 8) & 0xff,
                                                       (Spawn.SlotColour[sc] & 0xff));
                        }

                        TintQuery += ");";
                        SQLOut(TintQuery);
                        SQLOut("UPDATE npc_types SET armortint_id = @StartingNPCTypeID + " + ArmorTintID + " WHERE id = @StartingNPCTypeID + " + ExistingDBID + " LIMIT 1;");
                    }
                }

                NPCSL.AddNPCSpawn(Spawn.SpawnID, Spawn2ID, ExistingDBID, Spawn.SpawnName);

                Position p = new Position(Spawn.XPos, Spawn.YPos, Spawn.ZPos, Spawn.Heading, DateTime.MinValue);

                NPCSL.AddWaypoint(Spawn.SpawnID, p, false);

                string SpawnGroupQuery = "INSERT INTO spawngroup(`id`, `name`, `spawn_limit`, `dist`, `max_x`, `min_x`, `max_y`, `min_y`, `delay`) VALUES(";
                SpawnGroupQuery += "@StartingSpawnGroupID + " + SpawnGroupID + ", CONCAT('" + ZoneName + "', @StartingSpawnGroupID + " + SpawnGroupID + "), 0, 0, 0, 0, 0, 0, 0);";

                string SpawnEntryQuery = "INSERT INTO spawnentry(`spawngroupID`, `npcID`, `chance`) VALUES(";
                SpawnEntryQuery += "@StartingSpawnEntryID + " + SpawnEntryID + ", @StartingNPCTypeID + " + ExistingDBID + ", " + "100);";

                string Spawn2EntryQuery = "INSERT INTO spawn2(`id`, `spawngroupID`, `zone`, `version`, `x`, `y`, `z`, `heading`, `respawntime`, `variance`, `pathgrid`, `_condition`, `cond_value`, `enabled`,`animation`) VALUES(";
                Spawn2EntryQuery += "@StartingSpawn2ID + " + Spawn2ID + ", @StartingSpawnGroupID + " + SpawnGroupID + ", '" + ZoneName + "', " + SpawnVersion + ", " + Spawn.XPos + ", " + Spawn.YPos + ", " + Spawn.ZPos + ", ";
                Spawn2EntryQuery += Spawn.Heading + ", 640, 0, 0, 0, 1, 1" + "," + StandStateMapper.MapEqStandStateToEmuAnimation(Spawn.StandState).ToString() + ");";

                SpawnGroupID++;
                SpawnEntryID++;
                Spawn2ID++;

                if (GenerateSpawns)
                {
                    SQLOut(SpawnGroupQuery);
                    SQLOut(SpawnEntryQuery);
                    SQLOut(Spawn2EntryQuery);
                }
            }

            if (UpdateExistingNPCTypes)
            {
                List <NPCType> UniqueSpawns = NPCTL.GetUniqueSpawns();

                foreach (NPCType n in UniqueSpawns)
                {
                    string UpdateQuery = "UPDATE npc_types set texture = {0}, helmtexture = {1}, size = {2}, face = {3}, luclin_hairstyle = {4}, ";
                    UpdateQuery += "luclin_haircolor = {5}, luclin_eyecolor = {6}, luclin_eyecolor2 = {7}, luclin_beardcolor = {8}, ";
                    UpdateQuery += "luclin_beard = {9}, drakkin_heritage = {10}, drakkin_tattoo = {11}, drakkin_details = {12}, ";
                    UpdateQuery += "armortint_red = {13}, armortint_green = {14}, armortint_blue = {15}, d_meele_texture1 = {16}, ";
                    UpdateQuery += "d_meele_texture2 = {17}, findable = {18}, gender = {20} where name = '{19}' and id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999 and version = {21};";

                    SQLOut(String.Format(UpdateQuery, n.EquipChest2, n.Helm, n.Size, n.Face, n.HairStyle, n.HairColor, n.EyeColor1, n.EyeColor2, n.BeardColor,
                                         n.Beard, n.DrakkinHeritage, n.DrakkinTattoo, n.DrakkinDetails, n.ArmorTintRed, n.ArmorTintGreen,
                                         n.ArmorTintBlue, n.MeleeTexture1, n.MeleeTexture2, n.Findable, n.Name, n.Gender, SpawnVersion));

                    if (!NPCType.IsPlayableRace(n.Race))
                    {
                        continue;
                    }

                    bool ColoursInUse = false;

                    for (int ColourSlot = 0; ColourSlot < 9; ++ColourSlot)
                    {
                        if (((n.SlotColour[ColourSlot] & 0x00ffffff) != 0) && UseNPCTypesTint)
                        {
                            ColoursInUse = true;
                        }
                    }

                    if (ColoursInUse)
                    {
                        string TintQuery = "REPLACE INTO npc_types_tint(id, tint_set_name, ";
                        TintQuery += "red1h, grn1h, blu1h, ";
                        TintQuery += "red2c, grn2c, blu2c, ";
                        TintQuery += "red3a, grn3a, blu3a, ";
                        TintQuery += "red4b, grn4b, blu4b, ";
                        TintQuery += "red5g, grn5g, blu5g, ";
                        TintQuery += "red6l, grn6l, blu6l, ";
                        TintQuery += "red7f, grn7f, blu7f, ";
                        TintQuery += "red8x, grn8x, blu8x, ";
                        TintQuery += "red9x, grn9x, blu9x) SELECT id, '" + n.Name + "'";

                        for (int sc = 0; sc < 9; ++sc)
                        {
                            TintQuery += String.Format(", {0}, {1}, {2}", (n.SlotColour[sc] >> 16) & 0xff,
                                                       (n.SlotColour[sc] >> 8) & 0xff,
                                                       (n.SlotColour[sc] & 0xff));
                        }

                        TintQuery += " from npc_types where name = '" + n.Name + "' and id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999 and version = " + SpawnVersion + " LIMIT 1;";
                        SQLOut(TintQuery);
                        SQLOut(String.Format("UPDATE npc_types set armortint_id = (SELECT id from npc_types_tint WHERE tint_set_name = '{0}' and id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999 and version = {1} LIMIT 1), armortint_red = 0, armortint_green = 0, armortint_blue = 0 WHERE name = '{0}' and id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999 and version = {1} LIMIT 1;",
                                             n.Name, SpawnVersion));
                    }
                }
                return;
            }

            if (GenerateGrids)
            {
                List <PositionUpdate> AllMovementUpdates = PatchDecoder.GetAllMovementUpdates();

                foreach (PositionUpdate Update in AllMovementUpdates)
                {
                    NPCSL.AddWaypoint(Update.SpawnID, Update.p, Update.HighRes);
                }

                SQLOut("--");
                SQLOut("-- Grids");
                SQLOut("--");

                SQLOut("DELETE from grid WHERE id >= @StartingGridID AND id <= @StartingGridID + 999;");
                SQLOut("DELETE from grid_entries WHERE gridid >= @StartingGridID AND gridid <= @StartingGridID + 999;");
                foreach (NPCSpawn ns in NPCSL._NPCSpawnList)
                {
                    if (ns.Waypoints.Count > 1)
                    {
                        bool AllWaypointsTheSame = true;

                        for (int WPNumber = 0; WPNumber < ns.Waypoints.Count; ++WPNumber)
                        {
                            if (WPNumber == 0)
                            {
                                continue;
                            }
                            if ((ns.Waypoints[WPNumber].x != ns.Waypoints[WPNumber - 1].x) ||
                                (ns.Waypoints[WPNumber].y != ns.Waypoints[WPNumber - 1].y) ||
                                (ns.Waypoints[WPNumber].z != ns.Waypoints[WPNumber - 1].z))
                            {
                                AllWaypointsTheSame = false;
                            }
                        }

                        if (AllWaypointsTheSame)
                        {
                            continue;
                        }

                        int WaypointsInserted = 0;

                        int WPNum = 1;

                        int Pause = 10;

                        int FirstUsableWaypoint = 0;

                        if (ns.DoesHaveHighResWaypoints())
                        {
                            FirstUsableWaypoint = 1;
                        }

                        for (int WPNumber = FirstUsableWaypoint; WPNumber < ns.Waypoints.Count; ++WPNumber)
                        {
                            Position p = ns.Waypoints[WPNumber];

                            if (CoalesceWaypoints)
                            {
                                if ((WPNumber > FirstUsableWaypoint) && (WPNumber < (ns.Waypoints.Count - 2)))
                                {
                                    Position np = ns.Waypoints[WPNumber + 1];

                                    if ((Math.Abs(p.heading - np.heading) < 1) || (Math.Abs(p.heading - np.heading) > 255))
                                    {
                                        // Skipping waypoint as heading is the same as next.
                                        continue;
                                    }
                                    if ((Math.Abs(p.heading - np.heading) < 5) || (Math.Abs(p.heading - np.heading) > 251))
                                    {
                                        // Setting pause to 0 because headings are similar
                                        Pause = 0;
                                    }
                                    else if ((p.x == np.x) && (p.y == np.y) && (p.z == np.z))
                                    {
                                        // Skipping waypoint as same as next");
                                        continue;
                                    }
                                    else
                                    {
                                        Pause = 10;
                                    }
                                }
                            }

                            // If this is the last waypoint, and we haven't inserted any of the previous ones, then don't bother
                            // with this one either.
                            if ((WPNumber == (ns.Waypoints.Count - 1)) && (WaypointsInserted == 0))
                            {
                                continue;
                            }

                            SQLOut("INSERT into grid_entries (`gridid`, `zoneid`, `number`, `x`, `y`, `z`, `heading`, `pause`) VALUES(@StartingGridID + " + GridDBID + ", " + ZoneID + ", " + (WPNum++) + ", " + p.x + ", " + p.y + ", " + p.z + ", " + p.heading + ", " + Pause + ");");

                            ++WaypointsInserted;
                        }
                        if (WaypointsInserted > 1)
                        {
                            SQLOut("INSERT into grid(`id`, `zoneid`, `type`, `type2`) VALUES(@StartingGridID + " + GridDBID + ", " + ZoneID + ", 3, 2); -- " + ns.Name);

                            SQLOut("UPDATE spawn2 set pathgrid = @StartingGridID + " + GridDBID + " WHERE id = @StartingSpawn2ID + " + ns.Spawn2DBID + ";");

                            if (ns.DoesHaveHighResWaypoints())
                            {
                                SQLOut("UPDATE spawn2 set x = " + ns.Waypoints[1].x + ", y = " + ns.Waypoints[1].y + ", z = " + ns.Waypoints[1].z + ", heading = " + ns.Waypoints[1].heading + " WHERE id = @StartingSpawn2ID + " + ns.Spawn2DBID + ";");
                            }

                            ++GridDBID;
                        }
                    }
                }
            }
            if (GenerateMerchants)
            {
                GenerateMerchantSQL(NPCSL, MerchantDBID, GenerateSpawns, SQLOut);
            }
        }
 public void AddNPCType(NPCType NewNPC)
 {
     _NPCTypeList.Add(NewNPC);
 }
 public void AddNPCType(NPCType NewNPC)
 {
     _NPCTypeList.Add(NewNPC);
 }
        public void GenerateSpawnSQL(bool GenerateSpawns, bool GenerateGrids, bool GenerateMerchants,
                                            string ZoneName, UInt32 ZoneID, UInt32 SpawnVersion,
                                            bool UpdateExistingNPCTypes, bool UseNPCTypesTint, string SpawnNameFilter,
                                            bool CoalesceWaypoints, bool IncludeInvisibleMen, Action<string> SQLOut)
        {
            UInt32 NPCTypeDBID = 0;
            UInt32 SpawnGroupID = 0;
            UInt32 SpawnEntryID = 0;
            UInt32 Spawn2ID = 0;
            UInt32 GridDBID = 0;
            UInt32 MerchantDBID = 0;

            List<ZoneEntryStruct> ZoneSpawns = PatchDecoder.GetSpawns();

            List<UInt32> FindableEntities = PatchDecoder.GetFindableSpawns();

            if (GenerateSpawns)
            {
                SQLOut("--");
                SQLOut("-- Spawns");
                SQLOut("--");
                if (SpawnVersion == 0)
                {
                    SQLOut("DELETE from npc_types where id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999 and version = " + SpawnVersion + ";");

                    if(UseNPCTypesTint)
                        SQLOut("DELETE from npc_types_tint where id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999;");

                    SQLOut("DELETE from spawngroup where id >= @StartingSpawnGroupID and id <= @StartingSpawnGroupID + 999;");
                    SQLOut("DELETE from spawnentry where spawngroupID >= @StartingSpawnEntryID and spawngroupID <= @StartingSpawnEntryID + 999;");
                    SQLOut("DELETE from spawn2 where id >= @StartingSpawn2ID and id <= @StartingSpawn2ID + 999 and version = " + SpawnVersion + ";");
                }
                else
                {
                    SQLOut("DELETE from npc_types where id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 99 and version = " + SpawnVersion + ";");
                    SQLOut("DELETE from spawngroup where id >= @StartingSpawnGroupID and id <= @StartingSpawnGroupID + 99;");
                    SQLOut("DELETE from spawnentry where spawngroupID >= @StartingSpawnEntryID and spawngroupID <= @StartingSpawnEntryID + 99;");
                    SQLOut("DELETE from spawn2 where id >= @StartingSpawn2ID and id <= @StartingSpawn2ID + 99 and version = " + SpawnVersion + ";");
                }

            }

            NPCTypeList NPCTL = new NPCTypeList();

            NPCSpawnList NPCSL = new NPCSpawnList();

            foreach(ZoneEntryStruct Spawn in ZoneSpawns)
            {
                if (NPCType.IsMount(Spawn.SpawnName))
                    continue;

                if (!IncludeInvisibleMen && (Spawn.Race == 127))
                    continue;

                Spawn.Findable = (FindableEntities.IndexOf(Spawn.SpawnID) >= 0);

                if (Spawn.IsNPC != 1)
                    continue;

                if (Spawn.PetOwnerID > 0)
                    continue;

                if ((SpawnNameFilter.Length > 0) && (Spawn.SpawnName.IndexOf(SpawnNameFilter) == -1))
                    continue;

                bool ColoursInUse = false;

                for (int ColourSlot = 0; ColourSlot < 9; ++ColourSlot)
                {
                    if (((Spawn.SlotColour[ColourSlot] & 0x00ffffff) != 0) && UseNPCTypesTint)
                        ColoursInUse = true;
                }

                if (Spawn.IsMercenary > 0)
                    continue;

                UInt32 ExistingDBID = NPCTL.FindNPCType(Spawn.SpawnName, Spawn.Level, Spawn.Gender, Spawn.Size, Spawn.Face, Spawn.WalkSpeed, Spawn.RunSpeed, Spawn.Race,
                       Spawn.BodyType, Spawn.HairColor, Spawn.BeardColor, Spawn.EyeColor1, Spawn.EyeColor2, Spawn.HairStyle, Spawn.Beard,
                       Spawn.DrakkinHeritage, Spawn.DrakkinTattoo, Spawn.DrakkinDetails, Spawn.Deity, Spawn.Class, Spawn.EquipChest2,
                       Spawn.Helm, Spawn.LastName);

                if (ExistingDBID == 0)
                {
                    NPCType NewNPCType = new NPCType(NPCTypeDBID, Spawn.SpawnName, Spawn.Level, Spawn.Gender, Spawn.Size, Spawn.Face, Spawn.WalkSpeed, Spawn.RunSpeed, Spawn.Race,
                       Spawn.BodyType, Spawn.HairColor, Spawn.BeardColor, Spawn.EyeColor1, Spawn.EyeColor2, Spawn.HairStyle, Spawn.Beard,
                       Spawn.DrakkinHeritage, Spawn.DrakkinTattoo, Spawn.DrakkinDetails, Spawn.Deity, Spawn.Class, Spawn.EquipChest2,
                       Spawn.Helm, Spawn.LastName, Spawn.Findable, Spawn.MeleeTexture1, Spawn.MeleeTexture2, Spawn.ArmorTintRed, Spawn.ArmorTintGreen, Spawn.ArmorTintBlue, Spawn.SlotColour);

                    NPCTL.AddNPCType(NewNPCType);

                    ExistingDBID = NPCTypeDBID++;

                    UInt32 ArmorTintID = 0;

                    if (ColoursInUse)
                    {
                        ArmorTintID = ExistingDBID;
                        Spawn.ArmorTintRed = 0;
                        Spawn.ArmorTintGreen = 0;
                        Spawn.ArmorTintBlue = 0;
                    }

                    string NPCTypesQuery = "INSERT INTO npc_types(`id`, `name`, `lastname`, `level`, `gender`, `size`, `runspeed`,`race`, `class`, `bodytype`, `hp`, `texture`, `helmtexture`, `face`, `luclin_hairstyle`, `luclin_haircolor`, `luclin_eyecolor`, `luclin_eyecolor2`,`luclin_beard`, `luclin_beardcolor`, `findable`, `version`, `d_meele_texture1`, `d_meele_texture2`, `armortint_red`, `armortint_green`, `armortint_blue`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`) VALUES(";

                    NPCTypesQuery += "@StartingNPCTypeID + " + ExistingDBID + ", '" + Spawn.SpawnName + "', " + "'" + Spawn.LastName + "', " + Spawn.Level + ", " + Spawn.Gender + ", " + Spawn.Size + ", ";
                    NPCTypesQuery += Spawn.RunSpeed + ", " + Spawn.Race + ", " + Spawn.Class + ", " + Spawn.BodyType + ", " + Spawn.Level * (10 + Spawn.Level) + ", ";
                    NPCTypesQuery += Spawn.EquipChest2 + ", " + Spawn.Helm + ", " + Spawn.Face + ", " + Spawn.HairStyle + ", " + Spawn.HairColor + ", " + Spawn.EyeColor1 + ", ";
                    NPCTypesQuery += Spawn.EyeColor2 + ", " + Spawn.Beard + ", " + Spawn.BeardColor + ", " + (Spawn.Findable ? 1 : 0) + ", " + SpawnVersion + ", ";
                    NPCTypesQuery += Spawn.MeleeTexture1 + ", " + Spawn.MeleeTexture2 + ", " + Spawn.ArmorTintRed + ", " + Spawn.ArmorTintGreen + ", " + Spawn.ArmorTintBlue + ", ";
                    NPCTypesQuery += Spawn.DrakkinHeritage + ", " + Spawn.DrakkinTattoo + ", " + Spawn.DrakkinDetails + ");";

                    if (GenerateSpawns)
                        SQLOut(NPCTypesQuery);

                    if (GenerateSpawns && ColoursInUse && NPCType.IsPlayableRace(Spawn.Race))
                    {
                        string TintQuery = "REPLACE INTO npc_types_tint(id, tint_set_name, ";
                        TintQuery += "red1h, grn1h, blu1h, ";
                        TintQuery += "red2c, grn2c, blu2c, ";
                        TintQuery += "red3a, grn3a, blu3a, ";
                        TintQuery += "red4b, grn4b, blu4b, ";
                        TintQuery += "red5g, grn5g, blu5g, ";
                        TintQuery += "red6l, grn6l, blu6l, ";
                        TintQuery += "red7f, grn7f, blu7f, ";
                        TintQuery += "red8x, grn8x, blu8x, ";
                        TintQuery += "red9x, grn9x, blu9x) values(@StartingNPCTypeID + " + ExistingDBID + ", '" + Spawn.SpawnName + "'";

                        for (int sc = 0; sc < 9; ++sc)
                        {
                            TintQuery += String.Format(", {0}, {1}, {2}", (Spawn.SlotColour[sc] >> 16) & 0xff,
                                                                           (Spawn.SlotColour[sc] >> 8) & 0xff,
                                                                           (Spawn.SlotColour[sc] & 0xff));
                        }

                        TintQuery += ");";
                        SQLOut(TintQuery);
                        SQLOut("UPDATE npc_types SET armortint_id = @StartingNPCTypeID + " + ArmorTintID + " WHERE id = @StartingNPCTypeID + " + ExistingDBID + " LIMIT 1;");
                    }

                }

                NPCSL.AddNPCSpawn(Spawn.SpawnID, Spawn2ID, ExistingDBID, Spawn.SpawnName);

                Position p = new Position(Spawn.XPos, Spawn.YPos, Spawn.ZPos, Spawn.Heading, DateTime.MinValue);

                NPCSL.AddWaypoint(Spawn.SpawnID, p, false);

                string SpawnGroupQuery = "INSERT INTO spawngroup(`id`, `name`, `spawn_limit`, `dist`, `max_x`, `min_x`, `max_y`, `min_y`, `delay`) VALUES(";
                SpawnGroupQuery += "@StartingSpawnGroupID + " + SpawnGroupID + ", CONCAT('" + ZoneName + "', @StartingSpawnGroupID + " + SpawnGroupID + "), 0, 0, 0, 0, 0, 0, 0);";

                string SpawnEntryQuery = "INSERT INTO spawnentry(`spawngroupID`, `npcID`, `chance`) VALUES(";
                SpawnEntryQuery += "@StartingSpawnEntryID + " + SpawnEntryID + ", @StartingNPCTypeID + " + ExistingDBID + ", " + "100);";

                string Spawn2EntryQuery = "INSERT INTO spawn2(`id`, `spawngroupID`, `zone`, `version`, `x`, `y`, `z`, `heading`, `respawntime`, `variance`, `pathgrid`, `_condition`, `cond_value`, `enabled`) VALUES(";
                Spawn2EntryQuery += "@StartingSpawn2ID + " + Spawn2ID + ", @StartingSpawnGroupID + " + SpawnGroupID + ", '" + ZoneName + "', " + SpawnVersion + ", " + Spawn.XPos + ", " + Spawn.YPos + ", " + Spawn.ZPos + ", ";
                Spawn2EntryQuery += Spawn.Heading + ", 640, 0, 0, 0, 1, 1);";

                SpawnGroupID++;
                SpawnEntryID++;
                Spawn2ID++;

                if (GenerateSpawns)
                {
                    SQLOut(SpawnGroupQuery);
                    SQLOut(SpawnEntryQuery);
                    SQLOut(Spawn2EntryQuery);
                }
            }

            if (UpdateExistingNPCTypes)
            {
                List<NPCType> UniqueSpawns = NPCTL.GetUniqueSpawns();

                foreach (NPCType n in UniqueSpawns)
                {
                    string UpdateQuery = "UPDATE npc_types set texture = {0}, helmtexture = {1}, size = {2}, face = {3}, luclin_hairstyle = {4}, ";
                    UpdateQuery += "luclin_haircolor = {5}, luclin_eyecolor = {6}, luclin_eyecolor2 = {7}, luclin_beardcolor = {8}, ";
                    UpdateQuery += "luclin_beard = {9}, drakkin_heritage = {10}, drakkin_tattoo = {11}, drakkin_details = {12}, ";
                    UpdateQuery += "armortint_red = {13}, armortint_green = {14}, armortint_blue = {15}, d_meele_texture1 = {16}, ";
                    UpdateQuery += "d_meele_texture2 = {17}, findable = {18}, gender = {20} where name = '{19}' and id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999 and version = {21};";

                    SQLOut(String.Format(UpdateQuery, n.EquipChest2, n.Helm, n.Size, n.Face, n.HairStyle, n.HairColor, n.EyeColor1, n.EyeColor2, n.BeardColor,
                                                      n.Beard, n.DrakkinHeritage, n.DrakkinTattoo, n.DrakkinDetails, n.ArmorTintRed, n.ArmorTintGreen,
                                                      n.ArmorTintBlue, n.MeleeTexture1, n.MeleeTexture2, n.Findable, n.Name, n.Gender, SpawnVersion));

                    if(!NPCType.IsPlayableRace(n.Race))
                        continue;

                    bool ColoursInUse = false;

                    for (int ColourSlot = 0; ColourSlot < 9; ++ColourSlot)
                    {
                        if (((n.SlotColour[ColourSlot] & 0x00ffffff) != 0) && UseNPCTypesTint)
                            ColoursInUse = true;
                    }

                    if (ColoursInUse)
                    {
                        string TintQuery = "REPLACE INTO npc_types_tint(id, tint_set_name, ";
                        TintQuery += "red1h, grn1h, blu1h, ";
                        TintQuery += "red2c, grn2c, blu2c, ";
                        TintQuery += "red3a, grn3a, blu3a, ";
                        TintQuery += "red4b, grn4b, blu4b, ";
                        TintQuery += "red5g, grn5g, blu5g, ";
                        TintQuery += "red6l, grn6l, blu6l, ";
                        TintQuery += "red7f, grn7f, blu7f, ";
                        TintQuery += "red8x, grn8x, blu8x, ";
                        TintQuery += "red9x, grn9x, blu9x) SELECT id, '" + n.Name + "'";

                        for (int sc = 0; sc < 9; ++sc)
                        {
                            TintQuery += String.Format(", {0}, {1}, {2}", (n.SlotColour[sc] >> 16) & 0xff,
                                                                           (n.SlotColour[sc] >> 8) & 0xff,
                                                                           (n.SlotColour[sc] & 0xff));
                        }

                        TintQuery += " from npc_types where name = '" + n.Name + "' and id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999 and version = " + SpawnVersion + " LIMIT 1;";
                        SQLOut(TintQuery);
                        SQLOut(String.Format("UPDATE npc_types set armortint_id = (SELECT id from npc_types_tint WHERE tint_set_name = '{0}' and id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999 and version = {1} LIMIT 1), armortint_red = 0, armortint_green = 0, armortint_blue = 0 WHERE name = '{0}' and id >= @StartingNPCTypeID and id <= @StartingNPCTypeID + 999 and version = {1} LIMIT 1;",
                            n.Name, SpawnVersion));
                    }
                }
                return;
            }

            if (GenerateGrids)
            {
                List<PositionUpdate> AllMovementUpdates = PatchDecoder.GetAllMovementUpdates();

                foreach (PositionUpdate Update in AllMovementUpdates)
                    NPCSL.AddWaypoint(Update.SpawnID, Update.p, Update.HighRes);

                SQLOut("--");
                SQLOut("-- Grids");
                SQLOut("--");

                SQLOut("DELETE from grid WHERE id >= @StartingGridID AND id <= @StartingGridID + 999;");
                SQLOut("DELETE from grid_entries WHERE gridid >= @StartingGridID AND gridid <= @StartingGridID + 999;");
                foreach (NPCSpawn ns in NPCSL._NPCSpawnList)
                {
                    if (ns.Waypoints.Count > 1)
                    {
                        bool AllWaypointsTheSame = true;

                        for (int WPNumber = 0; WPNumber < ns.Waypoints.Count; ++WPNumber)
                        {
                            if (WPNumber == 0)
                                continue;
                            if ((ns.Waypoints[WPNumber].x != ns.Waypoints[WPNumber - 1].x) ||
                               (ns.Waypoints[WPNumber].y != ns.Waypoints[WPNumber - 1].y) ||
                               (ns.Waypoints[WPNumber].z != ns.Waypoints[WPNumber - 1].z))
                            {
                                AllWaypointsTheSame = false;
                            }
                        }

                        if (AllWaypointsTheSame)
                            continue;

                        int WaypointsInserted = 0;

                        int WPNum = 1;

                        int Pause = 10;

                        int FirstUsableWaypoint = 0;

                        if (ns.DoesHaveHighResWaypoints())
                            FirstUsableWaypoint = 1;

                        for (int WPNumber = FirstUsableWaypoint; WPNumber < ns.Waypoints.Count; ++WPNumber)
                        {
                            Position p = ns.Waypoints[WPNumber];

                            if (CoalesceWaypoints)
                            {
                                if ((WPNumber > FirstUsableWaypoint) && (WPNumber < (ns.Waypoints.Count - 2)))
                                {
                                    Position np = ns.Waypoints[WPNumber + 1];

                                    if ((Math.Abs(p.heading - np.heading) < 1) || (Math.Abs(p.heading - np.heading) > 255))
                                    {
                                        // Skipping waypoint as heading is the same as next.
                                        continue;
                                    }
                                    if ((Math.Abs(p.heading - np.heading) < 5) || (Math.Abs(p.heading - np.heading) > 251))
                                    {
                                        // Setting pause to 0 because headings are similar
                                        Pause = 0;
                                    }
                                    else if ((p.x == np.x) && (p.y == np.y) && (p.z == np.z))
                                    {
                                        // Skipping waypoint as same as next");
                                        continue;
                                    }
                                    else
                                        Pause = 10;
                                }
                            }

                            // If this is the last waypoint, and we haven't inserted any of the previous ones, then don't bother
                            // with this one either.
                            if ((WPNumber == (ns.Waypoints.Count - 1)) && (WaypointsInserted == 0))
                                continue;

                            SQLOut("INSERT into grid_entries (`gridid`, `zoneid`, `number`, `x`, `y`, `z`, `heading`, `pause`) VALUES(@StartingGridID + " + GridDBID + ", " + ZoneID + ", " + (WPNum++) + ", " + p.x + ", " + p.y + ", " + p.z + ", " + p.heading + ", " + Pause + ");");

                            ++WaypointsInserted;
                        }
                        if (WaypointsInserted > 1)
                        {
                            SQLOut("INSERT into grid(`id`, `zoneid`, `type`, `type2`) VALUES(@StartingGridID + " + GridDBID + ", " + ZoneID + ", 3, 2); -- " + ns.Name);

                            SQLOut("UPDATE spawn2 set pathgrid = @StartingGridID + " + GridDBID + " WHERE id = @StartingSpawn2ID + " + ns.Spawn2DBID + ";");

                            if (ns.DoesHaveHighResWaypoints())
                                SQLOut("UPDATE spawn2 set x = " + ns.Waypoints[1].x + ", y = " + ns.Waypoints[1].y + ", z = " + ns.Waypoints[1].z + ", heading = " + ns.Waypoints[1].heading + " WHERE id = @StartingSpawn2ID + " + ns.Spawn2DBID + ";");

                            ++GridDBID;
                        }
                    }
                }
            }
            if(GenerateMerchants)
                GenerateMerchantSQL(NPCSL, MerchantDBID, GenerateSpawns, SQLOut);
        }