public static void Send(Client cli, NonPlayerCharacterClass knubotTarget, string[] choices) { PacketWriter pw = new PacketWriter(); pw.PushByte(0xdf); pw.PushByte(0xdf); pw.PushShort(0xa); pw.PushShort(1); pw.PushShort(0); pw.PushInt(3086); pw.PushInt(cli.Character.Id); pw.PushInt(0x55704d31); pw.PushIdentity(cli.Character.Type, cli.Character.Id); pw.PushByte(0); pw.PushShort(2); pw.PushIdentity(knubotTarget.Type, knubotTarget.Id); pw.PushInt(choices.Length); foreach (string choice in choices) { pw.PushInt(choice.Length); pw.PushString(choice); } byte[] packet = pw.Finish(); cli.SendCompressed(packet); }
public static void Send(Client cli, NonPlayerCharacterClass knubotTarget, string message) { PacketWriter packetWriter = new PacketWriter(); packetWriter.PushByte(0xdf); packetWriter.PushByte(0xdf); packetWriter.PushShort(0xa); packetWriter.PushShort(1); packetWriter.PushShort(0); packetWriter.PushInt(3086); packetWriter.PushInt(cli.Character.Id); packetWriter.PushInt(0x5d70532a); packetWriter.PushIdentity(cli.Character.Type, cli.Character.Id); packetWriter.PushByte(0); packetWriter.PushShort(2); packetWriter.PushIdentity(knubotTarget.Type, knubotTarget.Id); packetWriter.PushInt(0); packetWriter.PushInt(message.Length); packetWriter.PushString(message); packetWriter.PushInt(0); byte[] packet = packetWriter.Finish(); cli.SendCompressed(packet); }
public static void DespawnPacket(int targetId) { PacketWriter packetWriter = new PacketWriter(); packetWriter.PushByte(0xDF); packetWriter.PushByte(0xDF); packetWriter.PushShort(10); packetWriter.PushShort(1); packetWriter.PushShort(0x1d); packetWriter.PushInt(3086); packetWriter.PushInt(0); packetWriter.PushInt(0x36510078); packetWriter.PushIdentity(50000, targetId); packetWriter.PushByte(1); byte[] packet = packetWriter.Finish(); Dynel dyn = FindDynel.FindDynelById(50000, targetId); if (dyn != null) { NonPlayerCharacterClass npc = dyn as NonPlayerCharacterClass; if (npc != null) { npc.RemoveFromCache(); } Announce.PlayfieldOthers(dyn.PlayField, packet); } }
public static void Send(Character talkingTo, NonPlayerCharacterClass talker) { Client client = talkingTo.Client; PacketWriter pw = new PacketWriter(); pw.PushByte(0xdf); pw.PushByte(0xdf); pw.PushShort(10); pw.PushShort(1); pw.PushShort(0); pw.PushInt(3086); pw.PushInt(client.Character.Id); pw.PushInt(0x270a4c62); pw.PushIdentity(50000, talkingTo.Id); pw.PushByte(0); pw.PushShort(2); pw.PushIdentity(50000, talker.Id); pw.PushInt(5); pw.PushInt(0); byte[] packet = pw.Finish(); client.SendCompressed(packet); // Closing KnuBot window from server side needs to clear KnuBot's variables talker.KnuBot.KnuBotCloseChatWindow(talkingTo); }
public static void Send(Client cli, NonPlayerCharacterClass knubotTarget, AOItem[] items) { PacketWriter packetWriter = new PacketWriter(); packetWriter.PushByte(0xdf); packetWriter.PushByte(0xdf); packetWriter.PushShort(0xa); packetWriter.PushShort(1); packetWriter.PushShort(0); packetWriter.PushInt(3086); packetWriter.PushInt(cli.Character.Id); packetWriter.PushInt(0x7864401d); packetWriter.PushIdentity(cli.Character.Type, cli.Character.Id); packetWriter.PushByte(0); packetWriter.PushShort(2); packetWriter.PushIdentity(knubotTarget.Type, knubotTarget.Id); packetWriter.PushInt(items.Length); foreach (AOItem item in items) { packetWriter.PushInt(item.LowID); packetWriter.PushInt(item.HighID); packetWriter.PushInt(item.Quality); packetWriter.PushInt(0x499602d2); // 1234567890 ??????? } packetWriter.PushInt(0); byte[] packet = packetWriter.Finish(); cli.SendCompressed(packet); }
public static void Read(byte[] packet, Client client) { PacketReader packetReader = new PacketReader(packet); Header header = packetReader.PopHeader(); packetReader.PopByte(); packetReader.PopShort(); Identity identity = packetReader.PopIdentity(); NonPlayerCharacterClass npc = (NonPlayerCharacterClass)FindDynel.FindDynelById(identity.Type, identity.Instance); Character character = FindClient.FindClientById(header.Sender).Character; packetReader.PopInt(); packetReader.PopInt(); packetReader.PopInt(); int container = packetReader.PopInt(); int place = packetReader.PopInt(); InventoryEntries ie = character.GetInventoryAt(place); AOItem aoi = ie.Item.ShallowCopy(); character.Inventory.Remove(ie); // Silent remove, no message given to client. Client handles this on its own npc.KnuBotTrade(character, aoi); }
public bool FunctionExecute(Dynel self, Dynel caller, object target, object[] arguments) { int actionnumber = (Int32)arguments[0]; NonPlayerCharacterClass knubotTarget = (NonPlayerCharacterClass)self; knubotTarget.KnuBot.Action((Int32)arguments[0]); return(true); }
// This will be called by ZoneServer at startup after loading all Spawns/Vendors etc. // The Character parameter is not used here, but has to be defined (yet) public void Init(Character ch) { NonPlayerCharacterClass target = (NonPlayerCharacterClass)FindDynel.FindDynelById(50000, 100001); if (target != null) { target.KnuBot = new KnuBotNPC100001(target); Console.WriteLine("Registered KnuBot100001 Script with NPC"); } }
// Adding our event handlers public KnuBotNPC100001(NonPlayerCharacterClass _parent) : base(_parent) { this.CallKnuBotCloseChatWindow += this.MyCloseChatWindow; this.CallKnuBotAnswer += this.MyAnswer; this.CallKnuBotOpenChatWindow += this.MyOpenChatWindow; this.CallKnuBotAcceptTrade += this.MyAcceptTrade; this.CallKnuBotDeclineTrade += this.MyDeclineTrade; this.CallKnuBotStartTrade += this.MyStartTrade; }
public KnuBotClass(NonPlayerCharacterClass parentNpc) { this.TalkingTo = null; this.Parent = parentNpc; this.CallKnuBotAcceptTrade += this.OnKnuBotAcceptTrade; this.CallKnuBotAnswer += this.OnKnuBotAnswer; this.CallKnuBotCloseChatWindow += this.OnKnuBotCloseChatWindow; this.CallKnuBotDeclineTrade += this.OnKnuBotDeclineTrade; this.CallKnuBotOpenChatWindow += this.OnKnuBotOpenChatWindow; this.CallKnuBotStartTrade += this.OnKnuBotStartTrade; this.CallKnuBotTrade += this.OnKnuBotTrade; }
public static void Read(byte[] packet) { PacketReader packetReader = new PacketReader(packet); Header header = packetReader.PopHeader(); packetReader.PopByte(); packetReader.PopShort(); int type = packetReader.PopInt(); int instance = packetReader.PopInt(); NonPlayerCharacterClass npc = (NonPlayerCharacterClass)FindDynel.FindDynelById(type, instance); Character character = FindClient.FindClientById(header.Sender).Character; character.KnuBotTarget = npc; }
public static void Read(byte[] packet, Client cli) { PacketReader pr = new PacketReader(packet); Header header = pr.PopHeader(); pr.PopByte(); pr.PopShort(); Identity id = pr.PopIdentity(); NonPlayerCharacterClass npc = (NonPlayerCharacterClass)FindDynel.FindDynelById(id.Type, id.Instance); if (npc != null) { npc.KnuBotStartTrade(cli.Character); } }
public static void Read(byte[] packet, Client client) { PacketReader packetReader = new PacketReader(packet); Header header = packetReader.PopHeader(); packetReader.PopByte(); packetReader.PopShort(); int type = packetReader.PopInt(); int instance = packetReader.PopInt(); NonPlayerCharacterClass npc = (NonPlayerCharacterClass)FindDynel.FindDynelById(type, instance); Character ch = FindClient.FindClientById(header.Sender).Character; if (npc != null) { npc.KnuBotFinishTrade(ch, packetReader.PopInt()); } }
/// <summary> /// Spawns new NPC to world. /// </summary> /// <param name="cli">Client that spawns NPC</param> /// <param name="hash">Hash of NPC to spawn</param> /// <param name="level">Level of NPC to spawn</param> /// <returns></returns> public static void SpawnMonster(Client cli, string hash, uint level) { NonPlayerCharacterClass mMonster = new NonPlayerCharacterClass(0, 0); //(cli, hash, level); mMonster.LoadTemplate(hash, level); mMonster.PurgeTimer(-1); mMonster.PurgeTimer(0); mMonster.PurgeTimer(1); mMonster.Id = FindNextFreeId(); mMonster.RawCoord = cli.Character.RawCoord; mMonster.RawHeading = cli.Character.RawHeading; mMonster.PlayField = cli.Character.PlayField; mMonster.AddHpnpTick(); if (String.IsNullOrEmpty(mMonster.Name)) { return; } mMonster.CalculateSkills(); mMonster.AddToCache(); mMonster.SpawnToPlayfield(mMonster.PlayField); }
public static void Send(Client client, NonPlayerCharacterClass knubotTarget) { PacketWriter packetWriter = new PacketWriter(); packetWriter.PushByte(0xdf); packetWriter.PushByte(0xdf); packetWriter.PushShort(0xa); packetWriter.PushShort(1); packetWriter.PushShort(0); packetWriter.PushInt(3086); packetWriter.PushInt(client.Character.Id); packetWriter.PushInt(0x3b132d64); packetWriter.PushIdentity(client.Character.Type, client.Character.Id); packetWriter.PushByte(0); packetWriter.PushShort(2); packetWriter.PushIdentity(knubotTarget.Type, knubotTarget.Id); packetWriter.PushInt(1); packetWriter.PushInt(0); byte[] packet = packetWriter.Finish(); client.SendCompressed(packet); }
public static List <AOItem> GetLoot(NonPlayerCharacterClass npc) { List <AOItem> drops = new List <AOItem>(); int minql = (int)Math.Ceiling(npc.Stats.Level.Value - 0.2 * npc.Stats.Level.Value); int maxql = (int)Math.Floor(npc.Stats.Level.Value + 0.2 * npc.Stats.Level.Value); var lootinfo = new SqlWrapper().ReadDatatable( "SELECT drophashes, dropslots, droppercents FROM mobtemplate WHERE hash = " + npc.Hash + ";").Rows; int numberOfSlots = 0; string[] hashes = lootinfo[0][0].ToString().ToLower().Split(','); string[] slots = lootinfo[0][1].ToString().ToLower().Split(','); string[] percents = lootinfo[0][2].ToString().ToLower().Split(','); if (!hashes.Any()) { return(null); } if (hashes[0] == string.Empty) { return(null); } foreach (string s in slots) { numberOfSlots = Math.Max(numberOfSlots, Convert.ToInt32(s.Trim())); } List <PartialSlot> list = new List <PartialSlot>(); for (int hashNumber = 0; hashNumber < hashes.Count(); ++hashNumber) { list.Add( new PartialSlot(hashes[hashNumber].Trim(), slots[hashNumber].Trim(), percents[hashNumber].Trim())); } for (int slotNumber = 1; slotNumber <= numberOfSlots; ++slotNumber) { var fullSlot = list.Where(match => match.Slot == slotNumber).Select(match => match); Random rand = new Random(); double num = rand.NextDouble(); double chance = 0; foreach (PartialSlot slot in fullSlot) { chance = chance + (slot.Chance / (double)10000); if (num <= chance) { List <LootItem> union = new List <LootItem>(); foreach (string hash in slot.HashList) { var matches = FullDropList.Where( match => ((match.MinQL <= minql && match.MaxQL >= maxql) || (match.MinQL < maxql && match.MaxQL >= maxql) || (match.MinQL <= minql && match.MaxQL > minql) || (match.MinQL >= minql && match.MaxQL <= maxql) || !match.RangeCheck) && match.Hash == hash).Select(match => match); foreach (LootItem li in matches) { if ( !union.Exists( duplicate => duplicate.HighId == li.HighId && duplicate.MaxQL == li.MaxQL)) { union.Add(li); } } } int ql = rand.Next(minql - 1, maxql + 1); if (union.Any()) { int select = rand.Next(-1, union.Count()); AOItem item = ItemHandler.interpolate( union.ElementAt(@select).LowId, union.ElementAt(@select).HighId, ql); if (item.ItemType != 1) { item.MultipleCount = Math.Max(1, item.getItemAttribute(212)); } else { bool found = false; foreach (AOItemAttribute a in item.Stats) { if (a.Stat != 212) { continue; } found = true; a.Value = Math.Max(1, item.getItemAttribute(212)); break; } if (!found) { AOItemAttribute aoi = new AOItemAttribute { Stat = 212, Value = Math.Max(1, item.getItemAttribute(212)) }; item.Stats.Add(aoi); } } drops.Add(item); break; } } } } return(drops); }
public KnuBotClass(Character target, NonPlayerCharacterClass parentNpc) { this.TalkingTo = target; this.Parent = parentNpc; }
// Call this _only_ on server startup! /// <summary> /// Reads all NPCs from database and adds them to servers list. /// </summary> /// <returns>Number of NPCs loaded</returns> public static int CacheAllFromDB() { int npcCount = 0; SqlWrapper sqlWrapper = new SqlWrapper(); // TODO:COUNT string sql = "SELECT count(*) FROM `mobspawns`"; int numberOfNpc = sqlWrapper.SqlCount(sql); Console.Write("Reading spawns: 0/" + numberOfNpc.ToString()); sql = "SELECT * FROM `mobspawns`"; DataTable dt = sqlWrapper.ReadDatatable(sql); sqlWrapper = new SqlWrapper(); DataTable dtstats = sqlWrapper.ReadDatatable("SELECT * from mobspawns_stats ORDER BY id, stat ASC"); sqlWrapper = new SqlWrapper(); DataTable dtinventory = sqlWrapper.ReadDatatable("SELECT * from mobspawnsinventory order by id, placement ASC"); int statcount = 0; int invcount = 0; foreach (DataRow row in dt.Rows) { NonPlayerCharacterClass monster = new NonPlayerCharacterClass(0, 0) { Starting = true, Id = (Int32)row["ID"], PlayField = (Int32)row["Playfield"] }; monster.Name = (string)row["Name"] #if DEBUG + " " + monster.Id.ToString() // ID is for debug purpose only #endif ; monster.readcoordsheadingfast(row); statcount = monster.ReadStatsfast(dtstats, statcount); invcount = monster.readInventoryfromSqlfast(dtinventory, invcount); // mMonster.readMeshsfromSql(); // mMonster.readNanosfromSql(); // mMonster.readTimersfromSql(); // mMonster.readWaypointsfromSql(); // mMonster.readWeaponpairsfromSql(); monster.readTexturesfromSqlfast(row); byte[] bytes; long counter; if (!(row[15] is DBNull)) { bytes = (byte[])row[15]; // Waypoints counter = 0; while (counter < bytes.Length) { AOCoord aoCoord = new AOCoord(); aoCoord.x = BitConverter.ToSingle(bytes, (int)counter); counter += 4; aoCoord.y = BitConverter.ToSingle(bytes, (int)counter); counter += 4; aoCoord.z = BitConverter.ToSingle(bytes, (int)counter); counter += 4; monster.Waypoints.Add(aoCoord); } } if (!(row[16] is DBNull)) { bytes = (byte[])row[16]; // Weaponpairs counter = 0; while (counter < bytes.Length) { AOWeaponpairs tempWeaponpairs = new AOWeaponpairs(); tempWeaponpairs.value1 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempWeaponpairs.value2 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempWeaponpairs.value3 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempWeaponpairs.value4 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; monster.Weaponpairs.Add(tempWeaponpairs); } } if (!(row[17] is DBNull)) { bytes = (byte[])row[17]; // Running Nanos counter = 0; while (counter < bytes.Length) { AONano tempNano = new AONano(); tempNano.Nanotype = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempNano.Instance = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempNano.Value3 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempNano.Time1 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempNano.Time2 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; monster.ActiveNanos.Add(tempNano); } } if (!(row[18] is DBNull)) { counter = 0; bytes = (byte[])row[18]; // Meshs while (counter < bytes.Length) { AOMeshs tempMeshs = new AOMeshs(); tempMeshs.Position = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempMeshs.Mesh = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempMeshs.OverrideTexture = BitConverter.ToInt32(bytes, (int)counter); counter += 4; monster.Meshs.Add(tempMeshs); } } if (!(row[19] is DBNull)) { counter = 0; bytes = (byte[])row[19]; // Additional Meshs while (counter < bytes.Length) { AOAddMeshs tempAdditionalMeshs = new AOAddMeshs(); tempAdditionalMeshs.position = bytes[counter++]; tempAdditionalMeshs.meshvalue1 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempAdditionalMeshs.meshvalue2 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempAdditionalMeshs.priority = bytes[counter++]; monster.AdditionalMeshs.Add(tempAdditionalMeshs); } } monster.Starting = false; Program.zoneServer.Monsters.Add(monster); npcCount += 1; if ((npcCount % 100) == 0) { Console.Write("\rReading spawns: " + npcCount.ToString() + "/" + numberOfNpc.ToString()); } } Console.Write("\r \r"); return(npcCount); }
public static void SpawnNpcToClient( NonPlayerCharacterClass nonPlayerCharacter, Client targetClient, bool wholePlayfield) { int unknown1 = 0; int unknown2 = 0; int unknown3 = 0; PacketWriter spawn = new PacketWriter(); int counter; int packetflags = 0x0001; // We want to spawn a NPC packetflags |= 0x0200; // Heading flag packetflags |= 0x0040; // packet has playfield packetflags |= 0x1000; // push level as 2 byte // if (mob.Stats.GetStat(466) <= 255) { packetflags |= 0x80000; // LOS Height 1 byte } if (nonPlayerCharacter.Attacking != 0) { packetflags |= 0x400; } packetflags |= 0x2000000; packetflags |= 0x0200000; packetflags |= 0x0000002; spawn.PushByte(0xDF); spawn.PushByte(0xDF); spawn.PushShort(10); spawn.PushShort(1); spawn.PushShort(0); // Length, packetwriter will take care of this spawn.PushInt(3086); if (targetClient == null) { spawn.PushInt(0); // will be sent to whole playfield } else { spawn.PushInt(targetClient.Character.Id); } spawn.PushInt(0x271B3A6B); spawn.PushIdentity(50000, nonPlayerCharacter.Id); spawn.PushByte(0); spawn.PushByte(0x39); // version 0x39 spawn.PushInt(packetflags); // packetflags spawn.PushInt(nonPlayerCharacter.PlayField); spawn.PushCoord(nonPlayerCharacter.Coordinates); spawn.PushQuat(nonPlayerCharacter.Heading); // Side, Fatness, Breed, Sex, Race // 33, 47, 4, 59, 89 spawn.PushUInt( nonPlayerCharacter.Stats.Side.Value + (nonPlayerCharacter.Stats.Fatness.Value * 8) + (nonPlayerCharacter.Stats.Breed.Value * 32) + (nonPlayerCharacter.Stats.Sex.Value * 256) + (nonPlayerCharacter.Stats.Race.Value * 1024)); spawn.PushByte((byte)(nonPlayerCharacter.Name.Length + 1)); spawn.PushBytes(Encoding.ASCII.GetBytes(nonPlayerCharacter.Name)); spawn.PushByte(0); spawn.PushUInt(nonPlayerCharacter.Stats.Flags.Value); spawn.PushShort(0); // AccountFlags spawn.PushShort(0); // Expansion if (nonPlayerCharacter.Stats.NpcFamily.Value <= 255) // NPCFamily { packetflags |= 0x20000; // NPC Family 1 byte spawn.PushByte((byte)nonPlayerCharacter.Stats.NpcFamily.Value); } else { packetflags &= ~0x20000; // NPC Family 2 byte spawn.PushShort((short)nonPlayerCharacter.Stats.NpcFamily.Value); } spawn.PushByte(0); spawn.PushByte(0); spawn.PushShort(0); // TODO: set packetflag for levelsize spawn.PushShort((short)nonPlayerCharacter.Stats.Level.Value); // 54 = Level // TODO: set packetflag for Healthsize/damagesize spawn.PushUInt(nonPlayerCharacter.Stats.Life.Value); // 1 = Life (max HP) spawn.PushUInt(nonPlayerCharacter.Stats.Health.Value); // 27 = Health left?? (same Size as Health, flag for 1byte not set) // If NPC is in grid or fixer grid // make him look like nice upside down pyramid if ((nonPlayerCharacter.PlayField == 152) || (nonPlayerCharacter.PlayField == 4107)) { spawn.PushInt(99902); } else { spawn.PushUInt(nonPlayerCharacter.Stats.MonsterData.Value); // 359=Monsterdata } spawn.PushShort((short)nonPlayerCharacter.Stats.MonsterScale.Value); // 360 = monsterscale spawn.PushShort(0x1F); // VisualFlags spawn.PushByte(0); // Visible title? spawn.PushInt(0x1C); spawn.PushInt(unknown1); // KnuBot values? spawn.PushInt(unknown2); spawn.PushInt(unknown3); // TODO: Movement Modes spawn.PushByte(1); // CurrentMovementMode spawn.PushByte(1); // Don't change spawn.PushShort(1); spawn.PushShort(1); spawn.PushShort(1); spawn.PushShort(1); spawn.PushShort(0); spawn.PushShort(2); spawn.PushShort(0); if (nonPlayerCharacter.Stats.HeadMesh.Value != 0) // 64 = headmesh { packetflags |= 0x80; spawn.PushUInt(nonPlayerCharacter.Stats.HeadMesh.Value); } // TODO: runspeedsize+flag if (nonPlayerCharacter.Stats.RunSpeed.Value > 255) { packetflags |= 0x2000; spawn.PushShort((short)nonPlayerCharacter.Stats.RunSpeed.Value); // 156 = RunSpeed } else { spawn.PushByte((byte)nonPlayerCharacter.Stats.RunSpeed.Value); // 156 = RunSpeed } if (nonPlayerCharacter.Attacking != 0) { spawn.PushInt(0xc350); spawn.PushInt(nonPlayerCharacter.Attacking); } if (nonPlayerCharacter.Meshs.Count > 0) { packetflags |= 0x10; // Meshs on mob spawn.Push3F1Count(nonPlayerCharacter.Meshs.Count); for (counter = 0; counter < nonPlayerCharacter.Meshs.Count; counter++) { // Name for meshtemplate not needed, sending 32byte 00 instead, thx to Suiv int counter2; for (counter2 = 0; counter2 < 8; counter2++) { spawn.PushInt(0); } spawn.PushInt(nonPlayerCharacter.Meshs[counter].Position); spawn.PushInt(nonPlayerCharacter.Meshs[counter].Mesh); spawn.PushInt(nonPlayerCharacter.Meshs[counter].OverrideTexture); } } // Running Nanos/Nano Effects spawn.Push3F1Count(nonPlayerCharacter.ActiveNanos.Count); for (counter = 0; counter < nonPlayerCharacter.ActiveNanos.Count; counter++) { spawn.PushInt(nonPlayerCharacter.ActiveNanos[counter].Nanotype); spawn.PushInt(nonPlayerCharacter.ActiveNanos[counter].Instance); spawn.PushInt(nonPlayerCharacter.ActiveNanos[counter].Value3); spawn.PushInt(nonPlayerCharacter.ActiveNanos[counter].Time1); spawn.PushInt(nonPlayerCharacter.ActiveNanos[counter].Time2); } // Waypoints if (nonPlayerCharacter.Waypoints.Count > 0) { packetflags |= 0x10000; // Waypoints spawn.PushInt(0xc350); spawn.PushInt(nonPlayerCharacter.Id); spawn.Push3F1Count(nonPlayerCharacter.Waypoints.Count); // Waypoints for (counter = 0; counter < nonPlayerCharacter.Waypoints.Count; counter++) { spawn.PushCoord(nonPlayerCharacter.Waypoints[counter]); } } // Textures have to be rewritten too // mobs should get a equip table // and get the textures from the equipped items spawn.Push3F1Count(nonPlayerCharacter.Textures.Count); // Texture count (should be 5 at all times iirc) int c; for (c = 0; c < nonPlayerCharacter.Textures.Count; c++) { spawn.PushInt(nonPlayerCharacter.Textures[c].place); spawn.PushInt(nonPlayerCharacter.Textures[c].Texture); spawn.PushInt(0); } // same as texture part, equip table should define the additional meshs // data could be stored with the item entries int addmeshs = 0; if (nonPlayerCharacter.Stats.WeaponMeshRight.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.WeaponMeshLeft.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.HeadMesh.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.BackMesh.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.ShoulderMeshRight.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.ShoulderMeshLeft.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.HairMesh.Value != 0) { addmeshs++; } // if (mob.Stats.GetStat(42) != 0) // 42 = CATMesh, what is this? // addmeshs++; if (nonPlayerCharacter.Stats.HairMesh.Value != 0) { addmeshs++; } spawn.Push3F1Count(addmeshs); if (addmeshs > 0) { // 0 head, 1 r_hand, 2 l_hand, 3 r_shoulder, 4 l_shoulder, 5 back, 6 hip, 7 r_thigh, 8 l_thigh, 9 r_crus, 10 l_crus, 11 r_arm, 12 l_arm, 13 r_forearm, 14 l_forearm if (nonPlayerCharacter.Stats.HeadMesh.Value != 0) { spawn.PushByte(0); spawn.PushUInt(nonPlayerCharacter.Stats.HeadMesh.Value); spawn.PushInt(0); spawn.PushByte(4); } if (nonPlayerCharacter.Stats.WeaponMeshRight.Value != 0) { spawn.PushByte(1); // Position spawn.PushUInt(nonPlayerCharacter.Stats.WeaponMeshRight.Value); // Mesh ID spawn.PushInt(0); // Unknown spawn.PushByte(4); // Priority } if (nonPlayerCharacter.Stats.WeaponMeshLeft.Value != 0) { spawn.PushByte(2); // Position spawn.PushUInt(nonPlayerCharacter.Stats.WeaponMeshLeft.Value); // Mesh ID spawn.PushInt(0); // Unknown spawn.PushByte(4); // Priority } if (nonPlayerCharacter.Stats.ShoulderMeshRight.Value != 0) { spawn.PushByte(3); spawn.PushUInt(nonPlayerCharacter.Stats.ShoulderMeshRight.Value); spawn.PushInt(0); spawn.PushByte(4); } if (nonPlayerCharacter.Stats.ShoulderMeshLeft.Value != 0) { spawn.PushByte(4); spawn.PushUInt(nonPlayerCharacter.Stats.ShoulderMeshLeft.Value); spawn.PushInt(0); spawn.PushByte(4); } if (nonPlayerCharacter.Stats.BackMesh.Value != 0) { spawn.PushByte(5); spawn.PushUInt(nonPlayerCharacter.Stats.BackMesh.Value); spawn.PushInt(0); spawn.PushByte(4); } if (nonPlayerCharacter.Stats.HairMesh.Value != 0) { spawn.PushByte(0); spawn.PushUInt(nonPlayerCharacter.Stats.HairMesh.Value); spawn.PushInt(0); spawn.PushByte(2); // Hairmesh is prio 2? } /* if (mob.Stats.GetStat(20001) != 0) * { * spawn.PushByte(0); * spawn.PushUInt(mob.Stats.GetStat(20001)); * spawn.PushInt(0); * spawn.PushByte(0); // Attractor Mesh prio = 0 * } */ } if (nonPlayerCharacter.Weaponpairs.Count > 0) { spawn.Push3F1Count(nonPlayerCharacter.Weaponpairs.Count); for (counter = 0; counter < nonPlayerCharacter.Weaponpairs.Count; counter++) { spawn.PushInt(nonPlayerCharacter.Weaponpairs[counter].value1); spawn.PushInt(nonPlayerCharacter.Weaponpairs[counter].value2); spawn.PushInt(nonPlayerCharacter.Weaponpairs[counter].value3); spawn.PushInt(nonPlayerCharacter.Weaponpairs[counter].value4); } } // Finishing output with 5byte 00 spawn.PushInt(0); spawn.PushByte(0); byte[] spawnReply = spawn.Finish(); // setting the packetflags spawnReply[30] = (byte)((packetflags >> 24) & 0xff); spawnReply[31] = (byte)((packetflags >> 16) & 0xff); spawnReply[32] = (byte)((packetflags >> 8) & 0xff); spawnReply[33] = (byte)(packetflags & 0xff); if (wholePlayfield) { Announce.Playfield(nonPlayerCharacter.PlayField, spawnReply); } else { targetClient.SendCompressed(spawnReply); } }
// Call this _only_ on server startup! /// <summary> /// Reads all NPCs from database and adds them to servers list. /// </summary> /// <returns>Number of NPCs loaded</returns> public static int CacheAllFromDB() { int npcCount = 0; SqlWrapper sqlWrapper = new SqlWrapper(); // TODO:COUNT string sql = "SELECT count(*) FROM `mobspawns`"; int numberOfNpc = sqlWrapper.SqlCount(sql); Console.Write("Reading spawns: 0/" + numberOfNpc.ToString()); sql = "SELECT * FROM `mobspawns`"; DataTable dt = sqlWrapper.ReadDatatable(sql); sqlWrapper = new SqlWrapper(); DataTable dtstats = sqlWrapper.ReadDatatable("SELECT * from mobspawns_stats ORDER BY id, stat ASC"); sqlWrapper = new SqlWrapper(); DataTable dtinventory = sqlWrapper.ReadDatatable("SELECT * from mobspawnsinventory order by id, placement ASC"); int statcount = 0; int invcount = 0; foreach (DataRow row in dt.Rows) { NonPlayerCharacterClass monster = new NonPlayerCharacterClass(0, 0) { Starting = true, Id = (Int32)row["ID"], PlayField = (Int32)row["Playfield"] }; monster.Name = (string)row["Name"] #if DEBUG + " " + monster.Id.ToString() // ID is for debug purpose only #endif ; monster.readcoordsheadingfast(row); statcount = monster.ReadStatsfast(dtstats, statcount); invcount = monster.readInventoryfromSqlfast(dtinventory, invcount); // mMonster.readMeshsfromSql(); // mMonster.readNanosfromSql(); // mMonster.readTimersfromSql(); // mMonster.readWaypointsfromSql(); // mMonster.readWeaponpairsfromSql(); monster.readTexturesfromSqlfast(row); byte[] bytes; long counter; if (!(row[15] is DBNull)) { bytes = (byte[])row[15]; // Waypoints counter = 0; while (counter < bytes.Length) { AOCoord aoCoord = new AOCoord(); aoCoord.x = BitConverter.ToSingle(bytes, (int)counter); counter += 4; aoCoord.y = BitConverter.ToSingle(bytes, (int)counter); counter += 4; aoCoord.z = BitConverter.ToSingle(bytes, (int)counter); counter += 4; monster.Waypoints.Add(aoCoord); } } if (!(row[16] is DBNull)) { bytes = (byte[])row[16]; // Weaponpairs counter = 0; while (counter < bytes.Length) { AOWeaponpairs tempWeaponpairs = new AOWeaponpairs(); tempWeaponpairs.value1 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempWeaponpairs.value2 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempWeaponpairs.value3 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempWeaponpairs.value4 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; monster.Weaponpairs.Add(tempWeaponpairs); } } if (!(row[17] is DBNull)) { bytes = (byte[])row[17]; // Running Nanos counter = 0; while (counter < bytes.Length) { AONano tempNano = new AONano(); tempNano.Nanotype = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempNano.Instance = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempNano.Value3 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempNano.Time1 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempNano.Time2 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; monster.ActiveNanos.Add(tempNano); } } if (!(row[18] is DBNull)) { counter = 0; bytes = (byte[])row[18]; // Meshs while (counter < bytes.Length) { AOMeshs tempMeshs = new AOMeshs(); tempMeshs.Position = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempMeshs.Mesh = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempMeshs.OverrideTexture = BitConverter.ToInt32(bytes, (int)counter); counter += 4; monster.Meshs.Add(tempMeshs); } } if (!(row[19] is DBNull)) { counter = 0; bytes = (byte[])row[19]; // Additional Meshs while (counter < bytes.Length) { AOAddMeshs tempAdditionalMeshs = new AOAddMeshs(); tempAdditionalMeshs.position = bytes[counter++]; tempAdditionalMeshs.meshvalue1 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempAdditionalMeshs.meshvalue2 = BitConverter.ToInt32(bytes, (int)counter); counter += 4; tempAdditionalMeshs.priority = bytes[counter++]; monster.AdditionalMeshs.Add(tempAdditionalMeshs); } } monster.Starting = false; Program.zoneServer.Monsters.Add(monster); npcCount += 1; if ((npcCount % 100) == 0) { Console.Write("\rReading spawns: " + npcCount.ToString() + "/" + numberOfNpc.ToString()); } } Console.Write("\r \r"); return npcCount; }
public KnuBotNPC100001(Character target, NonPlayerCharacterClass _parent) : base(target, _parent) { }
public static void Read(byte[] packet, Client client) { SqlWrapper mys = new SqlWrapper(); // Packet Reader Unknown Values are Returning 0 Integers, Unable to Store Needed Packet data To Reply. #region PacketReader PacketReader packetReader = new PacketReader(packet); Header m_header = packetReader.PopHeader(); // 0 - 28 byte unknown = packetReader.PopByte(); // 29 int actionNum = packetReader.PopInt(); // 30 - 33 int unknown1 = packetReader.PopInt(); // 34 - 37 Identity m_ident = packetReader.PopIdentity(); // 38 - 35 int unknown2 = packetReader.PopInt(); // 36 - 39 int unknown3 = packetReader.PopInt(); // 40 - 43 short unknown4 = packetReader.PopShort(); // 44 - 45 #endregion switch (actionNum) { #region Cast nano case 19: // Cast nano { // CastNanoSpell PacketWriter castNanoSpell = new PacketWriter(); castNanoSpell.PushByte(0xDF); castNanoSpell.PushByte(0xDF); castNanoSpell.PushShort(10); castNanoSpell.PushShort(1); castNanoSpell.PushShort(0); castNanoSpell.PushInt(3086); castNanoSpell.PushInt(client.Character.Id); castNanoSpell.PushInt(0x25314D6D); castNanoSpell.PushIdentity(50000, client.Character.Id); castNanoSpell.PushByte(0); castNanoSpell.PushInt(unknown3); // Nano ID castNanoSpell.PushIdentity(m_ident); // Target castNanoSpell.PushInt(0); castNanoSpell.PushIdentity(50000, client.Character.Id); // Caster byte[] castNanoSpellA = castNanoSpell.Finish(); Announce.Playfield(client.Character.PlayField, castNanoSpellA); // CharacterAction 107 PacketWriter characterAction107 = new PacketWriter(); characterAction107.PushByte(0xDF); characterAction107.PushByte(0xDF); characterAction107.PushShort(10); characterAction107.PushShort(1); characterAction107.PushShort(0); characterAction107.PushInt(3086); characterAction107.PushInt(client.Character.Id); characterAction107.PushInt(0x5E477770); characterAction107.PushIdentity(50000, client.Character.Id); characterAction107.PushByte(0); characterAction107.PushInt(107); characterAction107.PushInt(0); characterAction107.PushInt(0); characterAction107.PushInt(0); characterAction107.PushInt(1); characterAction107.PushInt(unknown3); characterAction107.PushShort(0); byte[] characterAction107A = characterAction107.Finish(); Announce.Playfield(client.Character.PlayField, characterAction107A); // CharacterAction 98 PacketWriter characterAction98 = new PacketWriter(); characterAction98.PushByte(0xDF); characterAction98.PushByte(0xDF); characterAction98.PushShort(10); characterAction98.PushShort(1); characterAction98.PushShort(0); characterAction98.PushInt(3086); characterAction98.PushInt(client.Character.Id); characterAction98.PushInt(0x5E477770); characterAction98.PushIdentity(m_ident); characterAction98.PushByte(0); characterAction98.PushInt(98); characterAction98.PushInt(0); characterAction98.PushInt(0xCF1B); characterAction98.PushInt(unknown3); characterAction98.PushInt(client.Character.Id); characterAction98.PushInt(0x249F0); // duration? characterAction98.PushShort(0); byte[] characterAction98A = characterAction98.Finish(); Announce.Playfield(client.Character.PlayField, characterAction98A); } break; #endregion #region search /* this is here to prevent server crash that is caused by * search action if server doesn't reply if something is * found or not */ case 66: // If action == search { /* Msg 110:136744723 = "No hidden objects found." */ client.SendFeedback(110, 136744723); } break; #endregion #region info case 105: // If action == Info Request { Client tPlayer = null; if ((tPlayer = FindClient.FindClientById(m_ident.Instance)) != null) { #region Titles uint LegacyScore = tPlayer.Character.Stats.PvpRating.StatBaseValue; string LegacyTitle = null; if (LegacyScore < 1400) { LegacyTitle = ""; } else if (LegacyScore < 1500) { LegacyTitle = "Freshman"; } else if (LegacyScore < 1600) { LegacyTitle = "Rookie"; } else if (LegacyScore < 1700) { LegacyTitle = "Apprentice"; } else if (LegacyScore < 1800) { LegacyTitle = "Novice"; } else if (LegacyScore < 1900) { LegacyTitle = "Neophyte"; } else if (LegacyScore < 2000) { LegacyTitle = "Experienced"; } else if (LegacyScore < 2100) { LegacyTitle = "Expert"; } else if (LegacyScore < 2300) { LegacyTitle = "Master"; } else if (LegacyScore < 2500) { LegacyTitle = "Champion"; } else { LegacyTitle = "Grand Master"; } #endregion int orgGoverningForm = 0; SqlWrapper ms = new SqlWrapper(); DataTable dt = ms.ReadDatatable( "SELECT `GovernmentForm` FROM organizations WHERE ID=" + tPlayer.Character.OrgId); if (dt.Rows.Count > 0) { orgGoverningForm = (Int32)dt.Rows[0][0]; } string orgRank = OrgClient.GetRank( orgGoverningForm, tPlayer.Character.Stats.ClanLevel.StatBaseValue); // Uses methods in ZoneEngine\PacketHandlers\OrgClient.cs /* Known packetFlags-- * 0x40 - No org | 0x41 - Org | 0x43 - Org and towers | 0x47 - Org, towers, player has personal towers | 0x50 - No pvp data shown * Bitflags-- * Bit0 = hasOrg, Bit1 = orgTowers, Bit2 = personalTowers, Bit3 = (Int32) time until supression changes (Byte) type of supression level?, Bit4 = noPvpDataShown, Bit5 = hasFaction, Bit6 = ?, Bit 7 = null. */ byte packetFlags = 0x40; // Player has no Org if (tPlayer.Character.OrgId != 0) { packetFlags = 0x41; // Player has Org, no towers } PacketWriter infoPacket = new PacketWriter(); // Start packet header infoPacket.PushByte(0xDF); infoPacket.PushByte(0xDF); infoPacket.PushShort(10); infoPacket.PushShort(1); infoPacket.PushShort(0); infoPacket.PushInt(3086); // sender (server ID) infoPacket.PushInt(client.Character.Id); // receiver infoPacket.PushInt(0x4D38242E); // packet ID infoPacket.PushIdentity(50000, tPlayer.Character.Id); // affected identity infoPacket.PushByte(0); // ? // End packet header infoPacket.PushByte(packetFlags); // Based on flags above infoPacket.PushByte(1); // esi_001? infoPacket.PushByte((byte)tPlayer.Character.Stats.Profession.Value); // Profession infoPacket.PushByte((byte)tPlayer.Character.Stats.Level.Value); // Level infoPacket.PushByte((byte)tPlayer.Character.Stats.TitleLevel.Value); // Titlelevel infoPacket.PushByte((byte)tPlayer.Character.Stats.VisualProfession.Value); // Visual Profession infoPacket.PushShort(0); // Side XP Bonus infoPacket.PushUInt(tPlayer.Character.Stats.Health.Value); // Current Health (Health) infoPacket.PushUInt(tPlayer.Character.Stats.Life.Value); // Max Health (Life) infoPacket.PushInt(0); // BreedHostility? infoPacket.PushUInt(tPlayer.Character.OrgId); // org ID infoPacket.PushShort((short)tPlayer.Character.FirstName.Length); infoPacket.PushBytes(Encoding.ASCII.GetBytes(tPlayer.Character.FirstName)); infoPacket.PushShort((short)tPlayer.Character.LastName.Length); infoPacket.PushBytes(Encoding.ASCII.GetBytes(tPlayer.Character.LastName)); infoPacket.PushShort((short)LegacyTitle.Length); infoPacket.PushBytes(Encoding.ASCII.GetBytes(LegacyTitle)); infoPacket.PushShort(0); // Title 2 // If receiver is in the same org as affected identity, whom is not orgless, send org rank and city playfield if ((client.Character.OrgId == tPlayer.Character.OrgId) && (tPlayer.Character.OrgId != 0)) { infoPacket.PushShort((short)orgRank.Length); infoPacket.PushBytes(Encoding.ASCII.GetBytes(orgRank)); infoPacket.PushInt(0); //infoPacket.PushIdentity(0, 0); // City (50201, Playfield) // Pushed 1 zero to much and screwed info for characters in orgs, but I´ll leave it for later just incase. } infoPacket.PushUInt(tPlayer.Character.Stats.InvadersKilled.Value); // Invaders Killed infoPacket.PushUInt(tPlayer.Character.Stats.KilledByInvaders.Value); // Killed by Invaders infoPacket.PushUInt(tPlayer.Character.Stats.AlienLevel.Value); // Alien Level infoPacket.PushUInt(tPlayer.Character.Stats.PvpDuelKills.Value); // Pvp Duel Kills infoPacket.PushUInt(tPlayer.Character.Stats.PvpDuelDeaths.Value); // Pvp Duel Deaths infoPacket.PushUInt(tPlayer.Character.Stats.PvpProfessionDuelDeaths.Value); // Pvp Profession Duel Kills infoPacket.PushUInt(tPlayer.Character.Stats.PvpRankedSoloKills.Value); // Pvp Solo Kills infoPacket.PushUInt(tPlayer.Character.Stats.PvpRankedSoloDeaths.Value); // Pvp Team Kills infoPacket.PushUInt(tPlayer.Character.Stats.PvpSoloScore.Value); // Pvp Solo Score infoPacket.PushUInt(tPlayer.Character.Stats.PvpTeamScore.Value); // Pvp Team Score infoPacket.PushUInt(tPlayer.Character.Stats.PvpDuelScore.Value); // Pvp Duel Score byte[] infoPacketA = infoPacket.Finish(); client.SendCompressed(infoPacketA); } else { NonPlayerCharacterClass npc = (NonPlayerCharacterClass)FindDynel.FindDynelById(m_ident.Type, m_ident.Instance); if (npc != null) { PacketWriter infoPacket = new PacketWriter(); // Start packet header infoPacket.PushByte(0xDF); infoPacket.PushByte(0xDF); infoPacket.PushShort(10); infoPacket.PushShort(1); infoPacket.PushShort(0); infoPacket.PushInt(3086); // sender (server ID) infoPacket.PushInt(client.Character.Id); // receiver infoPacket.PushInt(0x4D38242E); // packet ID infoPacket.PushIdentity(50000, npc.Id); // affected identity infoPacket.PushByte(0); // ? // End packet header infoPacket.PushByte(0x50); // npc's just have 0x50 infoPacket.PushByte(1); // esi_001? infoPacket.PushByte((byte)npc.Stats.Profession.Value); // Profession infoPacket.PushByte((byte)npc.Stats.Level.Value); // Level infoPacket.PushByte((byte)npc.Stats.TitleLevel.Value); // Titlelevel infoPacket.PushByte((byte)npc.Stats.VisualProfession.Value); // Visual Profession infoPacket.PushShort(0); // no idea for npc's infoPacket.PushUInt(npc.Stats.Health.Value); // Current Health (Health) infoPacket.PushUInt(npc.Stats.Life.Value); // Max Health (Life) infoPacket.PushInt(0); // BreedHostility? infoPacket.PushUInt(0); // org ID infoPacket.PushShort(0); infoPacket.PushShort(0); infoPacket.PushShort(0); infoPacket.PushShort(0); infoPacket.PushInt(0x499602d2); infoPacket.PushInt(0x499602d2); infoPacket.PushInt(0x499602d2); byte[] infoPacketA = infoPacket.Finish(); client.SendCompressed(infoPacketA); } } } break; #endregion #region logout case 120: // If action == Logout { //Start 30 second logout timer if client is not a GM (statid 215) if (client.Character.Stats.GMLevel.Value == 0) { client.startLogoutTimer(); } else // If client is a GM, disconnect without timer { client.Server.DisconnectClient(client); } } break; case 121: // If action == Stop Logout { //Stop current logout timer and send stop logout packet client.Character.UpdateMoveType((byte)client.Character.PreviousMoveMode); client.CancelLogOut(); } break; #endregion #region stand case 87: // If action == Stand { client.Character.UpdateMoveType(37); //Send stand up packet, and cancel timer/send stop logout packet if timer is enabled client.StandCancelLogout(); } break; #endregion #region Team case 22: //Kick Team Member { } break; case 24: //Leave Team { TeamClass team = new TeamClass(); team.LeaveTeam(client); } break; case 25: //Transfer Team Leadership { } break; case 26: //Team Join Request { // Send Team Invite Request To Target Player TeamClass team = new TeamClass(); team.SendTeamRequest(client, m_ident); } break; case 28: //Request Reply { // Check if positive or negative response // if positive TeamClass team = new TeamClass(); uint teamID = TeamClass.GenerateNewTeamId(client, m_ident); // Destination Client 0 = Sender, 1 = Reciever // Reciever Packets /////////////////// // CharAction 15 team.TeamRequestReply(client, m_ident); // CharAction 23 team.TeamRequestReplyCharacterAction23(client, m_ident); // TeamMember Packet team.TeamReplyPacketTeamMember(1, client, m_ident, "Member1"); // TeamMemberInfo Packet team.TeamReplyPacketTeamMemberInfo(1, client, m_ident); // TeamMember Packet team.TeamReplyPacketTeamMember(1, client, m_ident, "Member2"); // Sender Packets ///////////////// // TeamMember Packet team.TeamReplyPacketTeamMember(0, client, m_ident, "Member1"); // TeamMemberInfo Packet team.TeamReplyPacketTeamMemberInfo(0, client, m_ident); // TeamMember Packet team.TeamReplyPacketTeamMember(0, client, m_ident, "Member2"); } break; #endregion #region Delete Item case 0x70: mys.SqlDelete( "DELETE FROM " + client.Character.GetSqlTablefromDynelType() + "inventory WHERE placement=" + m_ident.Instance.ToString() + " AND container=" + m_ident.Type.ToString()); InventoryEntries i_del = client.Character.GetInventoryAt(m_ident.Instance); client.Character.Inventory.Remove(i_del); byte[] action2 = new byte[0x37]; Array.Copy(packet, action2, 0x37); action2[8] = 0x00; action2[9] = 0x00; action2[10] = 0x0C; action2[11] = 0x0E; client.SendCompressed(action2); break; #endregion #region Split item case 0x34: int nextid = client.Character.GetNextFreeInventory(m_ident.Type); InventoryEntries i = client.Character.GetInventoryAt(m_ident.Instance); i.Item.MultipleCount -= unknown3; InventoryEntries i2 = new InventoryEntries(); i2.Item = i.Item.ShallowCopy(); i2.Item.MultipleCount = unknown3; i2.Placement = nextid; client.Character.Inventory.Add(i2); client.Character.WriteInventoryToSql(); break; #endregion #region Join item case 0x35: InventoryEntries j1 = client.Character.GetInventoryAt(m_ident.Instance); InventoryEntries j2 = client.Character.GetInventoryAt(unknown3); j1.Item.MultipleCount += j2.Item.MultipleCount; client.Character.Inventory.Remove(j2); client.Character.WriteInventoryToSql(); byte[] joined = new byte[0x37]; Array.Copy(packet, joined, 0x37); joined[8] = 0x00; joined[9] = 0x00; joined[10] = 0x0C; joined[11] = 0x0E; client.SendCompressed(joined); break; #endregion #region Sneak Action // ################################################################################### // Spandexpants: This is all i have done so far as to make sneak turn on and off, // currently i cannot find a missing packet or link which tells the server the player // has stopped sneaking, hidden packet or something, will come back to later. // ################################################################################### // Sneak Packet Received case 163: { PacketWriter Sneak = new PacketWriter(); // TODO: IF SNEAKING IS ALLOWED RUN THIS CODE. // Send Action 162 : Enable Sneak Sneak.PushByte(0xDF); Sneak.PushByte(0xDF); Sneak.PushShort(0xA); Sneak.PushShort(1); Sneak.PushShort(0); Sneak.PushInt(3086); // Send Sneak.PushInt(client.Character.Id); // Reciever Sneak.PushInt(0x5e477770); // Packet ID Sneak.PushIdentity(50000, client.Character.Id); // TYPE / ID Sneak.PushInt(0); Sneak.PushByte(0xA2); // Action ID Sneak.PushInt(0); Sneak.PushInt(0); Sneak.PushInt(0); Sneak.PushInt(0); Sneak.PushInt(0); Sneak.PushShort(0); byte[] sneakpacket = Sneak.Finish(); client.SendCompressed(sneakpacket); // End of Enable sneak // TODO: IF SNEAKING IS NOT ALLOWED SEND REJECTION PACKET } break; #endregion #region Use Item on Item case 81: { Identity item1 = new Identity(); Identity item2 = new Identity(); item1.Type = m_ident.Type; item1.Instance = m_ident.Instance; item2.Type = unknown2; item2.Instance = unknown3; Tradeskill cts = new Tradeskill(client, item1.Instance, item2.Instance); cts.ClickBuild(); break; } #endregion #region Change Visual Flag case 166: { client.Character.Stats.VisualFlags.Set(unknown3); // client.SendChatText("Setting Visual Flag to "+unknown3.ToString()); AppearanceUpdate.AnnounceAppearanceUpdate(client.Character); break; } #endregion #region Tradeskill Source Changed case 0xdc: TradeSkillReceiver.TradeSkillSourceChanged(client, unknown2, unknown3); break; #endregion #region Tradeskill Target Changed case 0xdd: TradeSkillReceiver.TradeSkillTargetChanged(client, unknown2, unknown3); break; #endregion #region Tradeskill Build Pressed case 0xde: TradeSkillReceiver.TradeSkillBuildPressed(client, m_ident.Instance); break; #endregion #region default default: { byte[] action = new byte[0x37]; Array.Copy(packet, action, 0x37); action[8] = 0x00; action[9] = 0x00; action[10] = 0x0C; action[11] = 0x0E; Announce.Playfield(client.Character.PlayField, action); } break; #endregion } packetReader.Finish(); }
public static void SpawnNpcToClient( NonPlayerCharacterClass nonPlayerCharacter, Client targetClient, bool wholePlayfield) { int unknown1 = 0; int unknown2 = 0; int unknown3 = 0; PacketWriter spawn = new PacketWriter(); int counter; int packetflags = 0x0001; // We want to spawn a NPC packetflags |= 0x0200; // Heading flag packetflags |= 0x0040; // packet has playfield packetflags |= 0x1000; // push level as 2 byte // if (mob.Stats.GetStat(466) <= 255) { packetflags |= 0x80000; // LOS Height 1 byte } if (nonPlayerCharacter.Attacking != 0) { packetflags |= 0x400; } packetflags |= 0x2000000; packetflags |= 0x0200000; packetflags |= 0x0000002; spawn.PushByte(0xDF); spawn.PushByte(0xDF); spawn.PushShort(10); spawn.PushShort(1); spawn.PushShort(0); // Length, packetwriter will take care of this spawn.PushInt(3086); if (targetClient == null) { spawn.PushInt(0); // will be sent to whole playfield } else { spawn.PushInt(targetClient.Character.Id); } spawn.PushInt(0x271B3A6B); spawn.PushIdentity(50000, nonPlayerCharacter.Id); spawn.PushByte(0); spawn.PushByte(0x39); // version 0x39 spawn.PushInt(packetflags); // packetflags spawn.PushInt(nonPlayerCharacter.PlayField); spawn.PushCoord(nonPlayerCharacter.Coordinates); spawn.PushQuat(nonPlayerCharacter.Heading); // Side, Fatness, Breed, Sex, Race // 33, 47, 4, 59, 89 spawn.PushUInt( nonPlayerCharacter.Stats.Side.Value + (nonPlayerCharacter.Stats.Fatness.Value * 8) + (nonPlayerCharacter.Stats.Breed.Value * 32) + (nonPlayerCharacter.Stats.Sex.Value * 256) + (nonPlayerCharacter.Stats.Race.Value * 1024)); spawn.PushByte((byte)(nonPlayerCharacter.Name.Length + 1)); spawn.PushBytes(Encoding.ASCII.GetBytes(nonPlayerCharacter.Name)); spawn.PushByte(0); spawn.PushUInt(nonPlayerCharacter.Stats.Flags.Value); spawn.PushShort(0); // AccountFlags spawn.PushShort(0); // Expansion if (nonPlayerCharacter.Stats.NpcFamily.Value <= 255) // NPCFamily { packetflags |= 0x20000; // NPC Family 1 byte spawn.PushByte((byte)nonPlayerCharacter.Stats.NpcFamily.Value); } else { packetflags &= ~0x20000; // NPC Family 2 byte spawn.PushShort((short)nonPlayerCharacter.Stats.NpcFamily.Value); } spawn.PushByte(0); spawn.PushByte(0); spawn.PushShort(0); // TODO: set packetflag for levelsize spawn.PushShort((short)nonPlayerCharacter.Stats.Level.Value); // 54 = Level // TODO: set packetflag for Healthsize/damagesize spawn.PushUInt(nonPlayerCharacter.Stats.Life.Value); // 1 = Life (max HP) spawn.PushUInt(nonPlayerCharacter.Stats.Health.Value); // 27 = Health left?? (same Size as Health, flag for 1byte not set) // If NPC is in grid or fixer grid // make him look like nice upside down pyramid if ((nonPlayerCharacter.PlayField == 152) || (nonPlayerCharacter.PlayField == 4107)) { spawn.PushInt(99902); } else { spawn.PushUInt(nonPlayerCharacter.Stats.MonsterData.Value); // 359=Monsterdata } spawn.PushShort((short)nonPlayerCharacter.Stats.MonsterScale.Value); // 360 = monsterscale spawn.PushShort(0x1F); // VisualFlags spawn.PushByte(0); // Visible title? spawn.PushInt(0x1C); spawn.PushInt(unknown1); // KnuBot values? spawn.PushInt(unknown2); spawn.PushInt(unknown3); // TODO: Movement Modes spawn.PushByte(1); // CurrentMovementMode spawn.PushByte(1); // Don't change spawn.PushShort(1); spawn.PushShort(1); spawn.PushShort(1); spawn.PushShort(1); spawn.PushShort(0); spawn.PushShort(2); spawn.PushShort(0); if (nonPlayerCharacter.Stats.HeadMesh.Value != 0) // 64 = headmesh { packetflags |= 0x80; spawn.PushUInt(nonPlayerCharacter.Stats.HeadMesh.Value); } // TODO: runspeedsize+flag if (nonPlayerCharacter.Stats.RunSpeed.Value > 255) { packetflags |= 0x2000; spawn.PushShort((short)nonPlayerCharacter.Stats.RunSpeed.Value); // 156 = RunSpeed } else { spawn.PushByte((byte)nonPlayerCharacter.Stats.RunSpeed.Value); // 156 = RunSpeed } if (nonPlayerCharacter.Attacking != 0) { spawn.PushInt(0xc350); spawn.PushInt(nonPlayerCharacter.Attacking); } if (nonPlayerCharacter.Meshs.Count > 0) { packetflags |= 0x10; // Meshs on mob spawn.Push3F1Count(nonPlayerCharacter.Meshs.Count); for (counter = 0; counter < nonPlayerCharacter.Meshs.Count; counter++) { // Name for meshtemplate not needed, sending 32byte 00 instead, thx to Suiv int counter2; for (counter2 = 0; counter2 < 8; counter2++) { spawn.PushInt(0); } spawn.PushInt(nonPlayerCharacter.Meshs[counter].Position); spawn.PushInt(nonPlayerCharacter.Meshs[counter].Mesh); spawn.PushInt(nonPlayerCharacter.Meshs[counter].OverrideTexture); } } // Running Nanos/Nano Effects spawn.Push3F1Count(nonPlayerCharacter.ActiveNanos.Count); for (counter = 0; counter < nonPlayerCharacter.ActiveNanos.Count; counter++) { spawn.PushInt(nonPlayerCharacter.ActiveNanos[counter].Nanotype); spawn.PushInt(nonPlayerCharacter.ActiveNanos[counter].Instance); spawn.PushInt(nonPlayerCharacter.ActiveNanos[counter].Value3); spawn.PushInt(nonPlayerCharacter.ActiveNanos[counter].Time1); spawn.PushInt(nonPlayerCharacter.ActiveNanos[counter].Time2); } // Waypoints if (nonPlayerCharacter.Waypoints.Count > 0) { packetflags |= 0x10000; // Waypoints spawn.PushInt(0xc350); spawn.PushInt(nonPlayerCharacter.Id); spawn.Push3F1Count(nonPlayerCharacter.Waypoints.Count); // Waypoints for (counter = 0; counter < nonPlayerCharacter.Waypoints.Count; counter++) { spawn.PushCoord(nonPlayerCharacter.Waypoints[counter]); } } // Textures have to be rewritten too // mobs should get a equip table // and get the textures from the equipped items spawn.Push3F1Count(nonPlayerCharacter.Textures.Count); // Texture count (should be 5 at all times iirc) int c; for (c = 0; c < nonPlayerCharacter.Textures.Count; c++) { spawn.PushInt(nonPlayerCharacter.Textures[c].place); spawn.PushInt(nonPlayerCharacter.Textures[c].Texture); spawn.PushInt(0); } // same as texture part, equip table should define the additional meshs // data could be stored with the item entries int addmeshs = 0; if (nonPlayerCharacter.Stats.WeaponMeshRight.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.WeaponMeshLeft.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.HeadMesh.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.BackMesh.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.ShoulderMeshRight.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.ShoulderMeshLeft.Value != 0) { addmeshs++; } if (nonPlayerCharacter.Stats.HairMesh.Value != 0) { addmeshs++; } // if (mob.Stats.GetStat(42) != 0) // 42 = CATMesh, what is this? // addmeshs++; if (nonPlayerCharacter.Stats.HairMesh.Value != 0) { addmeshs++; } spawn.Push3F1Count(addmeshs); if (addmeshs > 0) { // 0 head, 1 r_hand, 2 l_hand, 3 r_shoulder, 4 l_shoulder, 5 back, 6 hip, 7 r_thigh, 8 l_thigh, 9 r_crus, 10 l_crus, 11 r_arm, 12 l_arm, 13 r_forearm, 14 l_forearm if (nonPlayerCharacter.Stats.HeadMesh.Value != 0) { spawn.PushByte(0); spawn.PushUInt(nonPlayerCharacter.Stats.HeadMesh.Value); spawn.PushInt(0); spawn.PushByte(4); } if (nonPlayerCharacter.Stats.WeaponMeshRight.Value != 0) { spawn.PushByte(1); // Position spawn.PushUInt(nonPlayerCharacter.Stats.WeaponMeshRight.Value); // Mesh ID spawn.PushInt(0); // Unknown spawn.PushByte(4); // Priority } if (nonPlayerCharacter.Stats.WeaponMeshLeft.Value != 0) { spawn.PushByte(2); // Position spawn.PushUInt(nonPlayerCharacter.Stats.WeaponMeshLeft.Value); // Mesh ID spawn.PushInt(0); // Unknown spawn.PushByte(4); // Priority } if (nonPlayerCharacter.Stats.ShoulderMeshRight.Value != 0) { spawn.PushByte(3); spawn.PushUInt(nonPlayerCharacter.Stats.ShoulderMeshRight.Value); spawn.PushInt(0); spawn.PushByte(4); } if (nonPlayerCharacter.Stats.ShoulderMeshLeft.Value != 0) { spawn.PushByte(4); spawn.PushUInt(nonPlayerCharacter.Stats.ShoulderMeshLeft.Value); spawn.PushInt(0); spawn.PushByte(4); } if (nonPlayerCharacter.Stats.BackMesh.Value != 0) { spawn.PushByte(5); spawn.PushUInt(nonPlayerCharacter.Stats.BackMesh.Value); spawn.PushInt(0); spawn.PushByte(4); } if (nonPlayerCharacter.Stats.HairMesh.Value != 0) { spawn.PushByte(0); spawn.PushUInt(nonPlayerCharacter.Stats.HairMesh.Value); spawn.PushInt(0); spawn.PushByte(2); // Hairmesh is prio 2? } /* if (mob.Stats.GetStat(20001) != 0) { spawn.PushByte(0); spawn.PushUInt(mob.Stats.GetStat(20001)); spawn.PushInt(0); spawn.PushByte(0); // Attractor Mesh prio = 0 } */ } if (nonPlayerCharacter.Weaponpairs.Count > 0) { spawn.Push3F1Count(nonPlayerCharacter.Weaponpairs.Count); for (counter = 0; counter < nonPlayerCharacter.Weaponpairs.Count; counter++) { spawn.PushInt(nonPlayerCharacter.Weaponpairs[counter].value1); spawn.PushInt(nonPlayerCharacter.Weaponpairs[counter].value2); spawn.PushInt(nonPlayerCharacter.Weaponpairs[counter].value3); spawn.PushInt(nonPlayerCharacter.Weaponpairs[counter].value4); } } // Finishing output with 5byte 00 spawn.PushInt(0); spawn.PushByte(0); byte[] spawnReply = spawn.Finish(); // setting the packetflags spawnReply[30] = (byte)((packetflags >> 24) & 0xff); spawnReply[31] = (byte)((packetflags >> 16) & 0xff); spawnReply[32] = (byte)((packetflags >> 8) & 0xff); spawnReply[33] = (byte)(packetflags & 0xff); if (wholePlayfield) { Announce.Playfield(nonPlayerCharacter.PlayField, spawnReply); } else { targetClient.SendCompressed(spawnReply); } }
public override void ExecuteCommand(Client client, Identity target, string[] args) { if ((target.Type != 50000) && (target.Type != 51035)) { this.CommandHelp(client); return; } NonPlayerCharacterClass targetMonster = null; foreach (NonPlayerCharacterClass mMonster in Program.zoneServer.Monsters) { if (mMonster.Id != target.Instance) { continue; } targetMonster = mMonster; break; } if (targetMonster == null) // Perhaps a vendor? { foreach (VendingMachine vm in Program.zoneServer.Vendors) { if (vm.Id != target.Instance) { continue; } targetMonster = vm; break; } } if (targetMonster == null) { return; } switch (args[1].ToLower()) { case "save": { if (targetMonster is VendingMachine) { ((VendingMachine)targetMonster).AddToDB(); } else { targetMonster.AddToDB(); } } break; case "delete": { targetMonster.RemoveFromDB(); } break; case "remove": { targetMonster.RemoveFromDB(); } break; case "despawn": { targetMonster.Despawn(); } break; default: this.CommandHelp(client); break; } }
public static List<AOItem> GetLoot(NonPlayerCharacterClass npc) { List<AOItem> drops = new List<AOItem>(); int minql = (int)Math.Ceiling(npc.Stats.Level.Value - 0.2 * npc.Stats.Level.Value); int maxql = (int)Math.Floor(npc.Stats.Level.Value + 0.2 * npc.Stats.Level.Value); var lootinfo = new SqlWrapper().ReadDatatable( "SELECT drophashes, dropslots, droppercents FROM mobtemplate WHERE hash = " + npc.Hash + ";").Rows; int numberOfSlots = 0; string[] hashes = lootinfo[0][0].ToString().ToLower().Split(','); string[] slots = lootinfo[0][1].ToString().ToLower().Split(','); string[] percents = lootinfo[0][2].ToString().ToLower().Split(','); if (!hashes.Any()) { return null; } if (hashes[0] == string.Empty) { return null; } foreach (string s in slots) { numberOfSlots = Math.Max(numberOfSlots, Convert.ToInt32(s.Trim())); } List<PartialSlot> list = new List<PartialSlot>(); for (int hashNumber = 0; hashNumber < hashes.Count(); ++hashNumber) { list.Add( new PartialSlot(hashes[hashNumber].Trim(), slots[hashNumber].Trim(), percents[hashNumber].Trim())); } for (int slotNumber = 1; slotNumber <= numberOfSlots; ++slotNumber) { var fullSlot = list.Where(match => match.Slot == slotNumber).Select(match => match); Random rand = new Random(); double num = rand.NextDouble(); double chance = 0; foreach (PartialSlot slot in fullSlot) { chance = chance + (slot.Chance / (double)10000); if (num <= chance) { List<LootItem> union = new List<LootItem>(); foreach (string hash in slot.HashList) { var matches = FullDropList.Where( match => ((match.MinQL <= minql && match.MaxQL >= maxql) || (match.MinQL < maxql && match.MaxQL >= maxql) || (match.MinQL <= minql && match.MaxQL > minql) || (match.MinQL >= minql && match.MaxQL <= maxql) || !match.RangeCheck) && match.Hash == hash).Select(match => match); foreach (LootItem li in matches) { if ( !union.Exists( duplicate => duplicate.HighId == li.HighId && duplicate.MaxQL == li.MaxQL)) { union.Add(li); } } } int ql = rand.Next(minql - 1, maxql + 1); if (union.Any()) { int select = rand.Next(-1, union.Count()); AOItem item = ItemHandler.interpolate( union.ElementAt(@select).LowId, union.ElementAt(@select).HighId, ql); if (item.ItemType != 1) { item.MultipleCount = Math.Max(1, item.getItemAttribute(212)); } else { bool found = false; foreach (AOItemAttribute a in item.Stats) { if (a.Stat != 212) { continue; } found = true; a.Value = Math.Max(1, item.getItemAttribute(212)); break; } if (!found) { AOItemAttribute aoi = new AOItemAttribute { Stat = 212, Value = Math.Max(1, item.getItemAttribute(212)) }; item.Stats.Add(aoi); } } drops.Add(item); break; } } } } return drops; }