(* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * http://www.opensource.org/licenses/cddl1.php. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * http://www.opensource.org/licenses/cddl1.php. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2007 Andreas Schneider *) unit UTiledata; {$mode objfpc}{$H+} interface uses Classes, UMulBlock; const tdfBackground = $00000001; tdfWeapon = $00000002; tdfTransparent = $00000004; tdfTranslucent = $00000008; tdfWall = $00000010; tdfDamaging = $00000020; tdfImpassable = $00000040; tdfWet = $00000080; tdfUnknown1 = $00000100; tdfSurface = $00000200; tdfBridge = $00000400; tdfGeneric = $00000800; tdfWindow = $00001000; tdfNoShoot = $00002000; tdfArticleA = $00004000; tdfArticleAn = $00008000; tdfInternal = $00010000; tdfFoliage = $00020000; tdfPartialHue = $00040000; tdfUnknown2 = $00080000; tdfMap = $00100000; tdfContainer = $00200000; tdfWearable = $00400000; tdfLightSource = $00800000; tdfAnimation = $01000000; tdfNoDiagonal = $02000000; tdfArtUsed = $04000000; tdfArmor = $08000000; tdfRoof = $10000000; tdfDoor = $20000000; tdfStairBack = $40000000; tdfStairRight = $80000000; LandTileDataSize = 26; LandTileGroupSize = 4 + 32 * LandTileDataSize; StaticTileDataSize = 37; StaticTileGroupSize = 4 + 32 * StaticTileDataSize; type { TTiledata } TTiledata = class(TMulBlock) protected FFlags: LongWord; FTileName: string; public property Flags: LongWord read FFlags write FFlags; property TileName: string read FTileName write FTileName; function HasFlag(AFlag: LongWord): Boolean; end; TLandTiledata = class(TTiledata) constructor Create(AData: TStream); destructor Destroy; override; function Clone: TLandTiledata; override; function GetSize: Integer; override; procedure Write(AData: TStream); override; protected FTextureID: Word; public property TextureID: Word read FTextureID write FTextureID; end; TStaticTiledata = class(TTiledata) constructor Create(AData: TStream); destructor Destroy; override; function Clone: TStaticTiledata; override; function GetSize: Integer; override; procedure Write(AData: TStream); override; protected FWeight: Byte; FQuality: Byte; FUnknown1: Word; FUnknown2: Byte; FQuantity: Byte; FAnimID: Word; FUnknown3: Byte; FHue: Byte; FUnknown4: Word; FHeight: Byte; public property Weight: Byte read FWeight write FWeight; property Quality: Byte read FQuality write FQuality; property Unknown1: Word read FUnknown1 write FUnknown1; property Unknown2: Byte read FUnknown2 write FUnknown2; property Quantity: Byte read FQuantity write FQuantity; property AnimID: Word read FAnimID write FAnimID; property Unknown3: Byte read FUnknown3 write FUnknown3; property Hue: Byte read FHue write FHue; property Unknown4: Word read FUnknown4 write FUnknown4; property Height: Byte read FHeight write FHeight; end; TLandTileGroup = class(TMulBlock) constructor Create(AData: TStream); destructor Destroy; override; function Clone: TLandTileGroup; override; function GetSize: Integer; override; procedure Write(AData: TStream); override; protected FUnknown: LongInt; public LandTileData: array[0..31] of TLandTiledata; property Unknown: LongInt read FUnknown write FUnknown; end; TStaticTileGroup = class(TMulBlock) constructor Create(AData: TStream); destructor Destroy; override; function Clone: TStaticTileGroup; override; function GetSize: Integer; override; procedure Write(AData: TStream); override; protected FUnknown: LongInt; public StaticTileData: array[0..31] of TStaticTiledata; property Unknown: LongInt read FUnknown write FUnknown; end; function GetTileDataOffset(ABlock: Integer): Integer; implementation function GetTileDataOffset(ABlock: Integer): Integer; var group, tile: Integer; begin if ABlock > $3FFF then begin ABlock := ABlock - $4000; group := ABlock div 32; tile := ABlock mod 32; Result := 512 * LandTileGroupSize + group * StaticTileGroupSize + 4 + tile * StaticTileDataSize; end else begin group := ABlock div 32; tile := ABlock mod 32; Result := group * LandTileGroupSize + 4 + tile * LandTileDataSize; end; end; constructor TLandTiledata.Create(AData: TStream); begin SetLength(FTileName, 20); if assigned(AData) then begin AData.Read(FFlags, SizeOf(LongWord)); AData.Read(FTextureID, SizeOf(Word)); AData.Read(PChar(FTileName)^, 20); end; end; destructor TLandTiledata.Destroy; begin SetLength(FTileName, 0); inherited; end; function TLandTiledata.Clone: TLandTiledata; begin Result := TLandTiledata.Create(nil); Result.FFlags := FFlags; Result.FTextureID := FTextureID; Result.FTileName := FTileName; end; procedure TLandTiledata.Write(AData: TStream); var i: Integer; begin if Length(FTileName) < 20 then for i := Length(FTileName) to 20 do FTileName := FTileName + #0; AData.Write(FFlags, SizeOf(LongWord)); AData.Write(FTextureID, SizeOf(Word)); AData.Write(PChar(FTileName)^, 20); end; function TLandTiledata.GetSize: Integer; begin GetSize := LandTileDataSize; end; constructor TStaticTiledata.Create(AData: TStream); begin SetLength(FTileName, 20); if assigned(AData) then begin AData.Read(FFlags, SizeOf(LongWord)); AData.Read(FWeight, SizeOf(Byte)); AData.Read(FQuality, SizeOf(Byte)); AData.Read(FUnknown1, SizeOf(Word)); AData.Read(FUnknown2, SizeOf(Byte)); AData.Read(FQuantity, SizeOf(Byte)); AData.Read(FAnimID, SizeOf(Word)); AData.Read(FUnknown3, SizeOf(Byte)); AData.Read(FHue, SizeOf(Byte)); AData.Read(FUnknown4, SizeOf(Word)); AData.Read(FHeight, SizeOf(Byte)); AData.Read(PChar(FTileName)^, 20); end; end; destructor TStaticTiledata.Destroy; begin SetLength(FTileName, 0); inherited; end; function TStaticTiledata.Clone: TStaticTiledata; begin Result := TStaticTiledata.Create(nil); Result.FFlags := FFlags; Result.FWeight := FWeight; Result.FQuality := FQuality; Result.FUnknown1 := FUnknown1; Result.FUnknown2 := FUnknown2; Result.FQuantity := FQuantity; Result.FAnimID := FAnimID; Result.FUnknown3 := FUnknown3; Result.FHue := FHue; Result.FUnknown4 := FUnknown4; Result.FHeight := FHeight; Result.FTileName := FTileName; end; procedure TStaticTiledata.Write(AData: TStream); var i: Integer; begin if Length(FTileName) < 20 then for i := Length(FTileName) to 20 do FTileName := FTileName + #0; AData.Write(FFlags, SizeOf(LongWord)); AData.Write(FWeight, SizeOf(Byte)); AData.Write(FQuality, SizeOf(Byte)); AData.Write(FUnknown1, SizeOf(Word)); AData.Write(FUnknown2, SizeOf(Byte)); AData.Write(FQuantity, SizeOf(Byte)); AData.Write(FAnimID, SizeOf(Word)); AData.Write(FUnknown3, SizeOf(Byte)); AData.Write(FHue, SizeOf(Byte)); AData.Write(FUnknown4, SizeOf(Word)); AData.Write(FHeight, SizeOf(Byte)); AData.Write(PChar(FTileName)^, 20); end; function TStaticTiledata.GetSize: Integer; begin GetSize := StaticTileDataSize; end; constructor TLandTileGroup.Create(AData: TStream); var i: Integer; begin if assigned(AData) then begin AData.Read(FUnknown, SizeOf(LongInt)); end; for i := 0 to 31 do LandTileData[i] := TLandTiledata.Create(AData); end; destructor TLandTileGroup.Destroy; var i: Integer; begin for i := 0 to 31 do LandTileData[i].Free; inherited; end; function TLandTileGroup.Clone: TLandTileGroup; var i: Integer; begin Result := TLandTileGroup.Create(nil); Result.FUnknown := FUnknown; for i := 0 to 31 do Result.LandTileData[i] := LandTileData[i].Clone; end; procedure TLandTileGroup.Write(AData: TStream); var i: Integer; begin AData.Write(FUnknown, SizeOf(LongInt)); for i := 0 to 31 do LandTileData[i].Write(AData); end; function TLandTileGroup.GetSize: Integer; begin GetSize := LandTileGroupSize; end; constructor TStaticTileGroup.Create(AData: TStream); var i: Integer; begin if assigned(AData) then begin AData.Read(FUnknown, SizeOf(LongInt)); end; for i := 0 to 31 do StaticTileData[i] := TStaticTiledata.Create(AData); end; destructor TStaticTileGroup.Destroy; var i: Integer; begin for i := 0 to 31 do StaticTileData[i].Free; inherited; end; function TStaticTileGroup.Clone: TStaticTileGroup; var i: Integer; begin Result := TStaticTileGroup.Create(nil); Result.FUnknown := FUnknown; for i := 0 to 31 do Result.StaticTileData[i] := StaticTileData[i].Clone; end; procedure TStaticTileGroup.Write(AData: TStream); var i: Integer; begin AData.Write(FUnknown, SizeOf(LongInt)); for i := 0 to 31 do StaticTileData[i].Write(AData); end; function TStaticTileGroup.GetSize: Integer; begin GetSize := StaticTileGroupSize; end; { TTiledata } function TTiledata.HasFlag(AFlag: LongWord): Boolean; begin Result := (FFlags and AFlag) = AFlag; end; end.