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 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; } }