using System; using System.Data; using System.Text; using System.Threading; using System.Collections; using Holo.Virtual.Users; using Holo.Virtual.Rooms.Pathfinding; using Ion.Storage; namespace Holo.Virtual.Rooms.Pets { internal class virtualPet { #region Declares internal int ID; internal int roomUID; internal int roomID; internal virtualRoom Room; internal string Name; internal int Owner; internal string Colour; internal string Race; internal int Type; internal int Train; internal int Hungry; internal int X; internal int Y; internal double H; internal byte Z1; internal byte Z2; internal int goalX; internal int goalY; internal int toyID = 0; private delegate void statusVoid(string Key, string Value, int Length); private Thread aiHandler; private string[] Shouts; private Coord[] Coords; #endregion #region Constructors/destructors private Hashtable Statuses; internal virtualPet(int petID, int roomUID, virtualRoom Room, int mX, int mY) { this.roomUID = roomUID; this.Room = Room; this.ID = petID; DataRow dRow; using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient()) { dRow = dbClient.getRow("SELECT * FROM pets WHERE id = '" + petID + "'"); dbClient.runQuery("UPDATE pets SET roomid = '" + Room.roomID + "', room_uid = '" + roomUID + "', x = '" + mX + "', y = '" + mY + "' WHERE id = '" + ID + "'"); } this.Name = dRow["name"].ToString(); this.Owner = int.Parse(dRow["owner"].ToString()); this.Type = int.Parse(dRow["type"].ToString()); this.Race = dRow["race"].ToString(); this.Colour = dRow["colour"].ToString(); this.Train = int.Parse(dRow["train"].ToString()); this.Hungry = int.Parse(dRow["hungry"].ToString()); this.roomID = int.Parse(dRow["roomid"].ToString()); if (mX == 0 && mY == 0) { Coord Next = new Coord(); int[] Borders = Room.getMapBorders(); Random RND = new Random(roomUID * DateTime.Now.Millisecond); Next = new Coord(RND.Next(0, Borders[0]), RND.Next(0, Borders[1])); X = Next.X; Y = Next.Y; Z1 = Room.sqFLOORHEIGHT[X, Y]; } else { X = mX; Y = mY; Z1 = 1; } Z2 = Z1; goalX = -1; DataColumn dCol; using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient()) { dCol = dbClient.getColumn("SELECT text FROM pets_texts WHERE animal = '" + Type + "'"); } this.Shouts = (string[])dataHandling.dColToArray(dCol); Statuses = new Hashtable(); aiHandler = new Thread(new ThreadStart(AI)); aiHandler.Priority = ThreadPriority.BelowNormal; aiHandler.Start(); } internal void Kill() { try { aiHandler.Abort(); } catch { } aiHandler = null; Room = null; Statuses = null; Coords = null; Shouts = null; Name = null; roomID = 0; roomUID = 0; ID = 0; } #endregion #region Bot properties internal string detailsString { get { string s = Encoding.encodeVL64(ID) + Name + Convert.ToChar(2) + Convert.ToChar(2) + Type + Convert.ToChar(32) + Race + Convert.ToChar(32) + Colour + Convert.ToChar(2) + Encoding.encodeVL64(roomUID) + Encoding.encodeVL64(X) + Encoding.encodeVL64(Y) + "0.0" + Convert.ToChar(2) + Encoding.encodeVL64(0) + Encoding.encodeVL64(2); return s; } } internal string statusString { get { string s = Encoding.encodeVL64(roomUID) + Encoding.encodeVL64(X) + Encoding.encodeVL64(Y) + H.ToString().Replace(",", ".") + Convert.ToChar(2) + Encoding.encodeVL64(Z1) + Encoding.encodeVL64(Z2); foreach (string Key in Statuses.Keys) { s += Key; string Value = (string)Statuses[Key]; if (Value != "") s += " " + Value; s += "/"; } return s; } } #endregion #region Actions internal void Interact(virtualRoomUser roomUser, string Message) { Random Random = new Random(); int Obey = Random.Next(0, ((this.Train / 2) + this.Hungry - (this.Hungry / 2))); string[] messageWords = Message.Split(' '); if (Obey >= this.Train) { if (messageWords[0] == this.Name) { int SumTrain = 0; switch (messageWords[1].ToLower()) { case "ven": { if (this.Owner == roomUser.userID) { Statuses.Clear(); Coord Next = new Coord(); Next = new Coord(roomUser.X - 1, roomUser.Y); if (Next.X == X && Next.Y == Y) Refresh(); else { goalX = Next.X; goalY = Next.Y; SumTrain = 2; } } break; } case "muertito": case "muerto": { if (this.Owner == roomUser.userID) { Statuses.Clear(); addStatus("ded", ""); Refresh(); SumTrain = 3; } break; } case "sientate": case "sentado": { Statuses.Clear(); addStatus("sit", ""); Refresh(); SumTrain = 2; break; } case "salta": case "brinca": { Statuses.Clear(); addStatus("jmp", ""); Refresh(); SumTrain = 2; break; } case "come": { using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient()) { DataColumn dColumn = dbClient.getColumn("SELECT * FROM furniture WHERE tid > 40 AND tid < 50 AND roomid = '" + this.roomID + "' ORDER BY RAND() LIMIT 1"); if (dColumn.Table.Columns.Count != 0 && this.Owner == roomUser.userID) { Statuses.Clear(); foreach (DataRow dRow in dColumn.Table.Rows) { Coord Next = new Coord(); Next = new Coord(Convert.ToInt32(dRow["x"]), Convert.ToInt32(dRow["y"])); if (Next.X == X && Next.Y == Y) { Z1 = (byte)Convert.ToInt32(dRow["z"]); Z2 = Z1; Refresh(); } else { goalX = Next.X; goalY = Next.Y; SumTrain = 1; } } } } break; } case "buena": case "bueno": { Statuses.Clear(); Room.sendShout(this, "*sonrojad@, agradeciendo con lambido*"); handleStatus("gest", "sml", 5000); SumTrain = 3; break; } case "mala": case "malo": { Statuses.Clear(); Room.sendShout(this, "*enojad@, rasguñando*"); handleStatus("gest", "sad", 5000); SumTrain = -2; break; } } using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient()) { dbClient.runQuery("UPDATE pets SET train = train + " + SumTrain + " WHERE id = '" + this.ID + "' AND (train + " + SumTrain + ") < 101 LIMIT 1"); this.Train = this.Train + SumTrain; } } } else { int Obey2 = Random.Next(0, 6); if (Obey2 == 1) Room.sendShout(this, "*pasando de ordenes*"); else if (Obey2 == 2) Room.sendShout(this, "*no*"); else if (Obey2 == 3) Room.sendShout(this, "*ignorando*"); else if (Obey2 == 4) Room.sendShout(this, "*¿por ti? no*"); else if (Obey2 == 5) Room.sendShout(this, "*volteando la cara para ignorar*"); else if (Obey2 == 6) Room.sendShout(this, "*pasando de obedecer*"); else Room.sendShout(this, "*ni lo pienses*"); } } internal void Rotate(int toX, int toY) { Rotate(Rotation.Calculate(X, Y, toX, toY)); } internal void Rotate(byte R) { if (R != Z1 && Statuses.ContainsKey("sit") == false) { Z1 = R; Z2 = R; Refresh(); } } #endregion #region Status management internal void addStatus(string Key, string Value) { if (Statuses.ContainsKey(Key)) Statuses.Remove(Key); Statuses.Add(Key, Value); } internal void removeStatus(string Key) { try { if (Statuses.ContainsKey(Key)) Statuses.Remove(Key); } catch { } } internal void removeStatus() { try { Statuses.Clear(); } catch { } } internal bool containsStatus(string Key) { return Statuses.ContainsKey(Key); } internal void Refresh() { Room.Refresh(this); } internal void handleStatus(string Key, string Value, int Length) { if (Statuses.ContainsKey(Key)) Statuses.Remove(Key); new statusVoid(HANDLESTATUS).BeginInvoke(Key, Value, Length, null, null); } private void HANDLESTATUS(string Key, string Value, int Length) { try { Statuses.Add(Key, Value); Refresh(); Thread.Sleep(Length); Statuses.Remove(Key); Refresh(); } catch { } } #endregion #region Misc private void AI() { int lastMessageID = -1; Random RND = new Random(roomUID * DateTime.Now.Millisecond); { while (true) { if (toyID != 0) { Room.sendData("AX" + Convert.ToInt32(toyID) + Convert.ToChar(2) + 0 + Convert.ToChar(2)); toyID = 0; } int ACTION = RND.Next(0, 8); switch (ACTION) { case 1: // Move { Statuses.Clear(); Coord Next = new Coord(); int[] Borders = Room.getMapBorders(); Next = new Coord(RND.Next(0, Borders[0]), RND.Next(0, Borders[1])); if (Next.X == X && Next.Y == Y) // Coord didn't changed { Z1 = (byte)RND.Next(0, 10); Z2 = Z1; Refresh(); } else { goalX = Next.X; goalY = Next.Y; } } break; case 2: // Rotate { Statuses.Clear(); byte R = (byte)RND.Next(0, 10); while (R == Z2) R = (byte)RND.Next(0, 10); Rotate(R); break; } case 3: // Shout { if (Shouts.Length > 0) { int messageID = RND.Next(0, Shouts.Length); if (Shouts.Length > 1) { while (messageID == lastMessageID) // Avoid shouting the same sentence two times in a row messageID = RND.Next(0, Shouts.Length); lastMessageID = messageID; } Room.sendShout(this, Shouts[messageID]); } break; } case 4: // Search food { using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient()) { DataColumn dColumn = dbClient.getColumn("SELECT * FROM furniture WHERE tid > 40 AND tid < 50 AND roomid = '" + this.roomID + "' ORDER BY RAND() LIMIT 1"); if (this.Hungry <= 50) { Room.sendShout(this, "*Cherche a boire*"); if (dColumn.Table.Columns.Count != 0) { foreach (DataRow dRow in dColumn.Table.Rows) { Coord Next = new Coord(); Next = new Coord(Convert.ToInt32(dRow["x"]), Convert.ToInt32(dRow["y"])); if (Next.X == X && Next.Y == Y) { Z1 = (byte)Convert.ToInt32(dRow["z"]); Z2 = Z1; addStatus("eat", ""); dbClient.runQuery("UPDATE pets SET hungry = hungry + 6 WHERE id = '" + ID + "' AND hungry < 101 LIMIT 1"); Hungry = Hungry + 6; Refresh(); Room.sendShout(this, "*agua fresquita, la mejor*"); } else { goalX = Next.X; goalY = Next.Y; Room.sendShout(this, "*agua fresquita, la mejor*"); } } } else Room.sendShout(this, "*¡no hay comida!*"); } } } break; case 5: // Random Object { Random Random = new Random(); int Status = Random.Next(0, 7); Statuses.Clear(); if (Status == 1) addStatus("ded", ""); else if (Status == 2) addStatus("jmp", ""); else if (Status == 3) { addStatus("wav", ""); handleStatus("gest", "sml", 5000); } else if (Status == 4) addStatus("snf", ""); else if (Status == 5) addStatus("scr", ""); Refresh(); break; } case 6: // Play { int Probabilty = RND.Next(0, 10); using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient()) { DataColumn dColumn = dbClient.getColumn("SELECT * FROM furniture WHERE tid > 53 AND tid < 59 AND roomid = '" + this.roomID + "' ORDER BY RAND() LIMIT 1"); if (this.Hungry >= 50 && Probabilty > 6) { Room.sendShout(this, "*quiero jugar*"); if (dColumn.Table.Columns.Count != 0) { Statuses.Clear(); addStatus("wav", ""); foreach (DataRow dRow in dColumn.Table.Rows) { Coord Next = new Coord(); Next = new Coord(Convert.ToInt32(dRow["x"]), Convert.ToInt32(dRow["y"])); toyID = Convert.ToInt32(dRow["id"]); if (Next.X == X && Next.Y == Y) { Z1 = (byte)Convert.ToInt32(dRow["z"]); Z2 = Z1; addStatus("pla", ""); Room.sendData("AX" + Convert.ToInt32(dRow["id"]) + Convert.ToChar(2) + 1 + Convert.ToChar(2)); Refresh(); Room.sendShout(this, "*jugando*"); } else { goalX = Next.X; goalY = Next.Y; } } } } } } break; } Thread.Sleep(3000); } } } #endregion } }