1 package Data::StarCraft::Tileset;
7 use List::Util qw(sum);
12 my ($class, $filename) = @_;
13 my $self = bless {}, $class;
14 open my $groupfile, '<', "$filename.cv5" or return;
15 $self->readgroups($groupfile);
16 if (open my $groupfile, '<', "$filename.vx4") {
17 $self->readvx4($groupfile);
19 if (open my $groupfile, '<', "$filename.vf4") {
20 $self->readvf4($groupfile);
22 if (open my $groupfile, '<', "$filename.vr4") {
23 $self->readvr4($groupfile);
25 if (open my $groupfile, '<', "$filename.wpe") {
26 $self->readwpe($groupfile);
33 my ($fh, $size, $seek) = @_;
35 seek $fh, $seek, 0 if $seek;
36 read($fh, my $in, $size) eq $size or return undef;
45 while (defined (my $line = $self->_read($fh, 4))) {
46 push @{ $self->{palette} }, [ unpack 'CCCX', $line ];
55 # vx4 = minitile map (4x4 references per megatile)
56 while (defined (my $line = $self->_read($fh, 16*2))) {
57 push @{ $self->{tileref} }, [ unpack 'v*', $line ];
66 # vr4 = minitile sprites
67 while (defined (my $line = $self->_read($fh, 8**2))) {
68 push @{ $self->{minibmp} }, [ unpack 'C*', $line ];
78 while (defined (my $line = $self->_read($fh, 2))) {
79 push @{ $self->{minitype} }, unpack 'v', $line;
88 return $self->{bmp}->[$minitile] if defined $self->{bmp}->[$minitile];
90 my $pixels = $self->{minibmp}->[$minitile];
91 my $pal = $self->{palette};
94 for my $color (@$pixels) {
95 # $rgb[$_] += $self->{palette}->[$color]->[$_] for 0 .. 2;
96 # # ^ wow, this is really slow
97 $rgb[0] += $pal->[$color]->[0];
98 $rgb[1] += $pal->[$color]->[1];
99 $rgb[2] += $pal->[$color]->[2];
101 return $self->{bmp}->[$minitile] = [map {$_ >> 6} @rgb];
106 Average color [r,g,b] for minitile.
108 For example, using the Jungle tileset:
112 is a water minitile, giving a blue color C<[38, 38, 57]>.
120 my $minitiles = $self->{tileref}->[$id];
122 for my $tiley (0 .. 3) {
124 for my $tilex (0 .. 3) {
125 # minitile number is half of tileref
126 # if odd, the minitile is mirrored
127 my $minitile = $minitiles->[$tilex + $tiley*4];
129 for my $x ($minitile & 1 ? (reverse 0 .. 7) : (0 .. 7)) {
130 push @pix, $self->{minibmp}->[$minitile >> 1]->[$x + $y*8];
140 Returns bitmap of an entire tile, as 32x32 color indexes.
142 For example, the green value of the bottom center pixel of tile #1 would be:
144 $t->{palette}->[ $t->sprite(1)->[31*32 + 15] ]->[2]
152 my $tile = $self->{map}->[$id];
153 my $minitiles = $self->{tileref}->[$tile] || [];
156 group => $self->{group}->[$id >> 4],
157 # subtype => [ map { $self->{minitype}->[$_] } @$minitiles ],
158 subtype => [ map { $self->{minitype}->[$_] } $tile*16 .. $tile*16+15 ],
159 subcol => [ map { $self->col($_ >> 1) } @$minitiles ],
160 # sprite => $self->sprite($tile),
166 my $tile = $self->tile(shift);
168 my $info = $tile->{group};
169 $info->{walk} = sum(@{ $tile->{subtype} }) >> 4;
171 for my $subcol (@{ $tile->{subcol} }) {
172 $rgb[0] += $subcol->[0];
173 $rgb[1] += $subcol->[1]; # seperate for speed
174 $rgb[2] += $subcol->[2];
176 $info->{col} = [ map {$_ >> 4} @rgb ];
182 Tile details. For example a water tile:
193 subtype => [ 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1 ],
195 [39,40,59], [38,39,57], [40,41,60], [36,37,55],
196 [37,38,56], [39,40,60], [38,39,57], [40,41,61],
197 [37,38,56], [41,41,61], [40,40,60], [36,36,54],
198 [36,36,54], [37,37,55], [35,35,53], [38,38,57]
209 while (defined (my $line = $self->_read($fh, 52))) {
210 my @data = unpack "vCC v24", $line;
212 build => $data[1] & 0xF0,
213 height => $data[2] & 0xF,
214 # rawdata => [@data[0..10]],
216 push @{ $self->{group} }, \%row;
217 push @{ $self->{map} }, $_ for @data[11..26];
220 # index (ground_height unknown4 buildable unknown3) u6 u7 u8 u9 u10 u11 u12 u13
221 # 1 (ground_height unknown4 buildable unknown3) 35 0 doodad_group 0 58 6 6 0