public MagicEffect(TibiaGameData GameData, int ID) { this.ID = ID; Sprite = GameData.GetEffectSprite(ID); this.Duration = Sprite.AnimationLength / 10.0; }
public ItemType(UInt16 id, GameSprite Sprite) { this.ID = id; this.Sprite = Sprite; }
public TibiaGameData(Stream DatFile, Stream SpriteFile) { this.SpriteFile = SpriteFile; SprVersion = ReadU32(SpriteFile); DatVersion = ReadU32(DatFile); //get max id ItemCount = ReadU16(DatFile); CreatureCount = ReadU16(DatFile); EffectCount = ReadU16(DatFile); DistanceCount = ReadU16(DatFile); UInt16 MinClientID = 100; // tibia.dat start with id 100 // We don't load distance/effects, if we would, just add effect_count & distance_count here UInt16 MaxClientID = (UInt16)((int)ItemCount + (int)CreatureCount + (int)EffectCount + (int)DistanceCount); UInt16 ID = MinClientID; // loop through all ItemDatabase until we reach the end of file while(ID <= MaxClientID) { GameSprite sType = new GameSprite(ID); ItemType iType = new ItemType(ID, sType); Sprites[ID] = sType; Items[ID] = iType; // Is it an effect? if (ID >= ItemCount + CreatureCount) sType.AnimationSpeed = 100; if (ID >= ItemCount && ID < ItemCount + CreatureCount) { };// sType.RenderOffset = -16; // read the options until we find a 0xff byte lastopt; byte optbyte = 0xff; do { lastopt = optbyte; optbyte = (byte)DatFile.ReadByte(); { //7.4 switch(optbyte) { case 0x00: //is groundtile iType.IsGround = true; iType.WalkSpeed = ReadU16(DatFile); iType.AlwaysOnTop = 0; break; case 0x01: // all OnTop iType.AlwaysOnTop = 1; break; case 0x02: iType.CanSeeThrough = true; iType.AlwaysOnTop = 2; break; case 0x03: iType.IsContainer = true; break; case 0x04: iType.IsStackable = true; sType.IsStackable = true; break; case 0x05: iType.IsUseableWith = true; break; case 0x06: iType.IsLadder = true; break; case 0x07: iType.IsReadable = true; iType.IsWriteable = true; iType.MaxTextLength = ReadU16(DatFile); break; case 0x08: // writtable objects that can't be edited iType.IsReadable = true; break; case 0x09: //can contain fluids iType.IsFluidContainer = true; sType.IsFluidContainer = true; break; case 0x0A: iType.IsSplash = true; sType.IsSplash = true; break; case 0x0B: iType.IsSolid = true; break; case 0x0C: iType.Immoveable = true; //Log.Fatal("Unknown attribute 0x0C - " + ID, this); break; case 0x0D: // blocks missiles (walls, magic wall etc) iType.BlockProjectiles = true; break; case 0x0E: // blocks monster movement (flowers, parcels etc) iType.BlockPathfinding = true; break; case 0x0F: iType.CanPickup = true; break; case 0x10: iType.LightLevel = ReadU16(DatFile); iType.LightColor = ReadU16(DatFile); break; case 0x11: // can see what is under (ladder holes, stairs holes etc) sType.FloorTransparent = true; break; case 0x12: // ground tiles that don't cause level change iType.DontFallThrough = true; break; case 0x13: // mostly blocking items, but also items that can pile up in level (boxes, chairs etc) iType.HasHeight = true; sType.RenderHeight = ReadU16(DatFile); break; case 0x14: // player color templates sType.RenderOffset = -8; if (ID >=ItemCount) sType.ColorTemplate = true; break; case 0x18: // cropses that don't decay iType.StaticCorpse = true; break; case 0x16: // Blocking items, most ground //Log.Debug("Unknown attribute 0x16 - " + ID, this); ReadU16(DatFile); break; case 0x17: // seems like decorables with 4 states of turning (exception first 4 are unique statues) iType.CanTurn = true; break; case 0x19: // wall items iType.IsWall = true; break; case 0x1A: // House walls, horizontal and corner, maybe CIP uses them only in houses? break; case 0x1B: // walls 2 types of them same material (total 4 pairs) break; case 0x1C: // Creature related, draw health bar with offset perhaps? sType.HealthOffset = 16; break; case 0x1D: // line spot ... iType.IsFloorChanger = true; // Always between 1100 and 1115~ ReadU16(DatFile); //Log.Debug("Unknown attribute 0x1D - " + ID + " - " + ReadU16(file), this); break; case 0xFF: break; default: throw new System.IO.IOException("Malformed metadata file."); } } } while(optbyte != 0xFF); // Size and GameSprite data sType.Width = DatFile.ReadByte(); sType.Height = DatFile.ReadByte(); if((sType.Width > 1) || (sType.Height > 1)){ DatFile.ReadByte(); // Pointless? } sType.BlendFrames = DatFile.ReadByte(); sType.XDiv = DatFile.ReadByte(); sType.YDiv = DatFile.ReadByte(); // 7.6 + // sType.ZDiv = file.ReadByte(); // Is this ever used? Maybe it means something else? sType.AnimationLength = DatFile.ReadByte(); // Read the sprite ids for(int i = 0; i < sType.SpriteCount; ++i) { UInt16 SpriteID = ReadU16(DatFile); GameImage img = GetImage(SpriteID); if(img == null) { img = new GameImage(this, SpriteID); Images[SpriteID] = img; } sType.Images.Add(img); } ++ID; } }
public DistanceEffect(TibiaGameData GameData, int ID, MapPosition From, MapPosition To) { this.ID = ID; Sprite = GameData.GetDistanceEffectSprite(ID); int dx = To.X - From.X; int dy = To.Y - From.Y; /* * 0 = NW * 1 = N * 2 = NE * 3 = W * 4 = C * 5 = E * 6 = SW * 7 = S * 8 = SE * */ double tan = 10; if (dx != 0) tan = (float)dy / (float)dx; if(Math.Abs(tan) < 0.4142f) { if(dx > 0) Frame = 5;// EAST else Frame = 3;// WEST } else if(Math.Abs(tan) < 2.4142f) { if(tan > 0) { if(dy > 0) Frame = 8;// SOUTH EAST else Frame = 0;// NORTH WEST; } else { //tan < 0 if(dx > 0) Frame = 2;// NORTH EAST; else Frame = 6;// SOUTH WEST } } else { if(dy > 0) Frame = 7;// SOUTH else Frame = 1;// NORTH } Duration = Math.Sqrt(dx * dx + dy * dy) / 10; Offset = new Vector2( (From.X - Math.Max(From.X, To.X)) * 32, (From.Y - Math.Max(From.Y, To.Y)) * 32 ); Speed = new Vector2(Math.Sign(dx) * 160, Math.Sign(dy) * 160); //Speed -= Offset; }
public void DrawSprite(SpriteBatch Batch, GameTime Time, ClientTile Tile, GameSprite Sprite, int SubType, int Frame, ref Vector2 Position, Color clr) { if (Sprite == null) return; int xdiv = 0, ydiv = 0, zdiv = 0; if (Tile != null) { MapPosition mPos = Tile.Position; xdiv = mPos.X % Sprite.XDiv; ydiv = mPos.Y % Sprite.YDiv; zdiv = mPos.Z % Sprite.ZDiv; } /* if (Sprite.IsHangable) { if (Tile->hasProperty(ISVERTICAL)) { xdiv = 2; } else if (Tile->hasProperty(ISHORIZONTAL)) { xdiv = 1; } else { xdiv = -0; } } else */ if (Sprite.IsStackable) { if (SubType <= 1) SubType = 0; else if (SubType <= 2) SubType = 1; else if (SubType <= 3) SubType = 2; else if (SubType <= 4) SubType = 3; else if (SubType < 10) SubType = 4; else if (SubType < 25) SubType = 5; else if (SubType < 50) SubType = 6; else SubType = 7; } Vector2 Offset = Position; Offset.X += Sprite.RenderOffset; Offset.Y += Sprite.RenderOffset; if (Frame == -1) Frame = (int)(Time.TotalGameTime.TotalMilliseconds / Sprite.AnimationSpeed); for (int cx = 0; cx != Sprite.Width; cx++) { for (int cy = 0; cy != Sprite.Height; cy++) { for (int cf = 0; cf != Sprite.BlendFrames; cf++) { GameImage Image = Sprite.GetImage( cx, cy, cf, SubType, xdiv, ydiv, zdiv, Frame ); Rectangle rect = new Rectangle((int)Offset.X - 32 * cx, (int)Offset.Y - 32 * cy, 32, 32); DrawImage(Batch, Image, rect, clr); } } } if (Sprite.RenderHeight > 0) { Position.X -= Sprite.RenderHeight; Position.Y -= Sprite.RenderHeight; } }
public void DrawSprite(SpriteBatch Batch, GameTime Time, ClientTile Tile, GameSprite Sprite, int SubType, int Frame, Vector2 Position, Color clr) { Vector2 tmp = Position; DrawSprite(Batch, Time, Tile, Sprite, SubType, Frame, ref tmp, clr); }
public TibiaGameData(Stream DatFile, Stream SpriteFile) { this.SpriteFile = SpriteFile; SprVersion = ReadU32(SpriteFile); DatVersion = ReadU32(DatFile); //get max id ItemCount = ReadU16(DatFile); CreatureCount = ReadU16(DatFile); EffectCount = ReadU16(DatFile); DistanceCount = ReadU16(DatFile); UInt16 MinClientID = 100; // tibia.dat start with id 100 // We don't load distance/effects, if we would, just add effect_count & distance_count here UInt16 MaxClientID = (UInt16)((int)ItemCount + (int)CreatureCount + (int)EffectCount + (int)DistanceCount); UInt16 ID = MinClientID; // loop through all ItemDatabase until we reach the end of file while (ID <= MaxClientID) { GameSprite sType = new GameSprite(ID); ItemType iType = new ItemType(ID, sType); Sprites[ID] = sType; Items[ID] = iType; // Is it an effect? if (ID >= ItemCount + CreatureCount) { sType.AnimationSpeed = 100; } if (ID >= ItemCount && ID < ItemCount + CreatureCount) { } ; // sType.RenderOffset = -16; // read the options until we find a 0xff byte lastopt; byte optbyte = 0xff; do { lastopt = optbyte; optbyte = (byte)DatFile.ReadByte(); { //7.4 switch (optbyte) { case 0x00: //is groundtile iType.IsGround = true; iType.WalkSpeed = ReadU16(DatFile); iType.AlwaysOnTop = 0; break; case 0x01: // all OnTop iType.AlwaysOnTop = 1; break; case 0x02: iType.CanSeeThrough = true; iType.AlwaysOnTop = 2; break; case 0x03: iType.IsContainer = true; break; case 0x04: iType.IsStackable = true; sType.IsStackable = true; break; case 0x05: iType.IsUseableWith = true; break; case 0x06: iType.IsLadder = true; break; case 0x07: iType.IsReadable = true; iType.IsWriteable = true; iType.MaxTextLength = ReadU16(DatFile); break; case 0x08: // writtable objects that can't be edited iType.IsReadable = true; break; case 0x09: //can contain fluids iType.IsFluidContainer = true; sType.IsFluidContainer = true; break; case 0x0A: iType.IsSplash = true; sType.IsSplash = true; break; case 0x0B: iType.IsSolid = true; break; case 0x0C: iType.Immoveable = true; //Log.Fatal("Unknown attribute 0x0C - " + ID, this); break; case 0x0D: // blocks missiles (walls, magic wall etc) iType.BlockProjectiles = true; break; case 0x0E: // blocks monster movement (flowers, parcels etc) iType.BlockPathfinding = true; break; case 0x0F: iType.CanPickup = true; break; case 0x10: iType.LightLevel = ReadU16(DatFile); iType.LightColor = ReadU16(DatFile); break; case 0x11: // can see what is under (ladder holes, stairs holes etc) sType.FloorTransparent = true; break; case 0x12: // ground tiles that don't cause level change iType.DontFallThrough = true; break; case 0x13: // mostly blocking items, but also items that can pile up in level (boxes, chairs etc) iType.HasHeight = true; sType.RenderHeight = ReadU16(DatFile); break; case 0x14: // player color templates sType.RenderOffset = -8; if (ID >= ItemCount) { sType.ColorTemplate = true; } break; case 0x18: // cropses that don't decay iType.StaticCorpse = true; break; case 0x16: // Blocking items, most ground //Log.Debug("Unknown attribute 0x16 - " + ID, this); ReadU16(DatFile); break; case 0x17: // seems like decorables with 4 states of turning (exception first 4 are unique statues) iType.CanTurn = true; break; case 0x19: // wall items iType.IsWall = true; break; case 0x1A: // House walls, horizontal and corner, maybe CIP uses them only in houses? break; case 0x1B: // walls 2 types of them same material (total 4 pairs) break; case 0x1C: // Creature related, draw health bar with offset perhaps? sType.HealthOffset = 16; break; case 0x1D: // line spot ... iType.IsFloorChanger = true; // Always between 1100 and 1115~ ReadU16(DatFile); //Log.Debug("Unknown attribute 0x1D - " + ID + " - " + ReadU16(file), this); break; case 0xFF: break; default: throw new System.IO.IOException("Malformed metadata file."); } } } while(optbyte != 0xFF); // Size and GameSprite data sType.Width = DatFile.ReadByte(); sType.Height = DatFile.ReadByte(); if ((sType.Width > 1) || (sType.Height > 1)) { DatFile.ReadByte(); // Pointless? } sType.BlendFrames = DatFile.ReadByte(); sType.XDiv = DatFile.ReadByte(); sType.YDiv = DatFile.ReadByte(); // 7.6 + // sType.ZDiv = file.ReadByte(); // Is this ever used? Maybe it means something else? sType.AnimationLength = DatFile.ReadByte(); // Read the sprite ids for (int i = 0; i < sType.SpriteCount; ++i) { UInt16 SpriteID = ReadU16(DatFile); GameImage img = GetImage(SpriteID); if (img == null) { img = new GameImage(this, SpriteID); Images[SpriteID] = img; } sType.Images.Add(img); } ++ID; } }