--- deliantra/Deliantra/Deliantra.pm 2006/02/11 16:17:14 1.14 +++ deliantra/Deliantra/Deliantra.pm 2006/02/12 04:50:24 1.15 @@ -14,21 +14,22 @@ use Carp (); use Storable; +use List::Util qw(min max); #XXX: The map_* procedures scream for a map-object our @EXPORT = - qw(read_pak read_arch $ARCH TILESIZE editor_archs - arch_extends - map_get_tile_stack map_push_tile_stack map_pop_tile_stack - ); + qw(read_pak read_arch %ARCH TILESIZE $TILE %FACE editor_archs arch_extents); our $LIB = $ENV{CROSSFIRE_LIBDIR} or Carp::croak "\$CROSSFIRE_LIBDIR must be set\n"; sub TILESIZE (){ 32 } -our $ARCH; +our $CACHEDIR; +our %ARCH; +our %FACE; +our $TILE; our %FIELD_MULTILINE = ( msg => "endmsg", @@ -48,7 +49,7 @@ sub normalize_arch($) { my ($ob) = @_; - my $arch = $ARCH->{$ob->{_name}} + my $arch = $ARCH{$ob->{_name}} or (warn "$ob->{_name}: no such archetype", return $ob); delete $ob->{$_} for qw(can_knockback can_parry can_impale can_cut can_dam_armour can_apply); @@ -100,6 +101,7 @@ # if value matches archetype default, delete while (my ($k, $v) = each %$ob) { if (exists $arch->{$k} and $arch->{$k} eq $v) { + next if $k eq "_name"; delete $ob->{$k}; } } @@ -210,101 +212,67 @@ } } -# returns the arch/object stack from a tile on a map -sub map_get_tile_stack { - my ($map, $x, $y) = @_; - my $as; - - if ($x > 0 || $x < $map->{width} - || $y > 0 || $y < $map->{height}) { - - $as = $map->{map}{map}[$x][$y] || []; - } - - return $as; -} - -# pop the topmost arch/object from the stack of a tile on a map -sub map_pop_tile_stack { - my ($map, $x, $y) = @_; - - if ($x > 0 || $x < $map->{width} - || $y > 0 || $y < $map->{height}) { - - pop @{$map->{map}{map}[$x][$y]}; - } -} - -# pushes the arch/object on the stack of a tile on a map -sub map_push_tile_stack { - my ($map, $x, $y, $arch) = @_; - - if ($x > 0 || $x < $map->{width} - || $y > 0 || $y < $map->{height}) { - - push @{$map->{map}{map}[$x][$y]}, $arch; - } -} - - # put all archs into a hash with editor_face as it's key # NOTE: the arrays in the hash values are references to # the archs from $ARCH sub editor_archs { my %paths; - for (keys %$ARCH) { - my $arch = $ARCH->{$_}; + for (keys %ARCH) { + my $arch = $ARCH{$_}; push @{$paths{$arch->{editor_folder}}}, \$arch; } - return \%paths; + \%paths } -# arch_extends determines how the arch looks like on the map, +# arch_extents determines the extents of a given arch # bigfaces, linked faces and single faces are handled here -# it returns (, , , ) -# NOTE: non rectangular linked faces are not considered -sub arch_extends { +# it returns (minx, miny, maxx, maxy) +sub arch_extents { my ($a) = @_; - my $TC = \%Crossfire::Tilecache::TILECACHE; + my $o = $ARCH{$a->{_name}} + or return; - my $facename = - $a->{face} || $ARCH->{$a->{_name}}->{face} - or return (); - - my $tile = $TC->{$facename} - or (warn "no gfx found for arch '$facename' in arch_size ()"), return; - - if ($tile->{w} > 1 || $tile->{h} > 1) { - # bigfaces - return (0, 0, $tile->{w}, $tile->{h}); - - } elsif ($a->{more}) { - # linked faces - my ($miw, $mih, $maw, $mah) = (0, 0, 0, 0); - do { - $miw > (0 + $a->{x}) and $miw = $a->{x}; - $mih > (0 + $a->{y}) and $mih = $a->{y}; - $maw < (0 + $a->{x}) and $maw = $a->{x}; - $mah < (0 + $a->{y}) and $mah = $a->{y}; - } while $a = $a->{more}; + my $face = $FACE{$a->{face} || $o->{face}} + or (warn "no face data found for arch '$a->{_name}'"), return; - return ($miw, $mih, ($maw - $miw) + 1, ($mah - $mih) + 1) + if ($face->{w} > 1 || $face->{h} > 1) { + # bigface + return (0, 0, $face->{w} - 1, $face->{h} - 1); + + } elsif ($o->{more}) { + # linked face + my ($minx, $miny, $maxx, $maxy) = ($o->{x}, $o->{y}) x 2; + + for (; $o; $o = $o->{more}) { + $minx = min $minx, $o->{x}; + $miny = min $miny, $o->{y}; + $maxx = max $maxx, $o->{x}; + $maxy = max $maxy, $o->{y}; + } + + return ($minx, $miny, $maxx, $maxy); } else { # single face - return (0, 0, 1, 1); + return (0, 0, 0, 0); } } sub init($) { my ($cachedir) = @_; - $ARCH = read_arch "$LIB/archetypes", "$cachedir/archetypes.pst"; + return if %ARCH; + + *ARCH = read_arch "$LIB/archetypes", "$cachedir/archetypes.pst"; } +$CACHEDIR ||= "$ENV{HOME}/.crossfire"; + +init $CACHEDIR; + =head1 AUTHOR Marc Lehmann