ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/Util.pm
Revision: 1.3
Committed: Sun Mar 12 12:18:55 2006 UTC (18 years, 2 months ago) by elmex
Branch: MAIN
Changes since 1.2: +7 -1 lines
Log Message:
Implemented first parts of the new attribute editor.

File Contents

# User Rev Content
1 elmex 1.1 package GCE::Util;
2     =head1 NAME
3    
4     GCE::Util - some utility functions
5    
6     =over 4
7    
8     =cut
9    
10     use base 'Exporter';
11    
12     use Crossfire;
13    
14     use Carp ();
15     use Storable;
16     use List::Util qw(min max);
17    
18 elmex 1.2 use Crossfire;
19     use Crossfire::MapWidget;
20    
21 elmex 1.3 our @EXPORT = qw(insert_arch_stack_layer replace_arch_stack_layer new_arch_pb fill_pb_from_arch arch_is_floor stack_find_floor stack_find_wall stack_find arch_is_wall arch_is_monster);
22 elmex 1.2
23     sub new_arch_pb {
24     # this is awful, is this really the best way?
25     my $pb = new Gtk2::Gdk::Pixbuf 'rgb', 1, 8, TILESIZE, TILESIZE;
26     return $pb;
27     }
28    
29     sub fill_pb_from_arch {
30     my ($pb, $arch) = @_;
31    
32     $pb->fill (0x00000000);
33     $TILE->composite ($pb,
34     0, 0,
35     TILESIZE, TILESIZE,
36     - ($arch->{_face} % 64) * TILESIZE, - TILESIZE * int $arch->{_face} / 64,
37     1, 1, 'nearest', 255
38     );
39     }
40 elmex 1.1
41     sub classify_arch_layer {
42     my ($arch) = @_;
43    
44     if ($arch->{invisible}) { # just a heuristic for 'special' tiles (er. pedestals)
45    
46     return 'below';
47    
48     } elsif ($arch->{monster}) {
49    
50     return 'top';
51    
52     } else { # $arch->{is_floor} and all other arches are 'between' monsters and floor
53    
54     return 'between';
55     }
56     }
57    
58 elmex 1.2 sub arch_is_floor {
59     my ($a) = @_;
60     return $Crossfire::ARCH{$a->{_name}}->{is_floor};
61     }
62    
63     sub arch_is_wall {
64     my ($a) = @_;
65     return $Crossfire::ARCH{$a->{_name}}->{no_pass};
66     }
67    
68 elmex 1.3 sub arch_is_monster {
69     my ($a) = @_;
70     my $arch = $Crossfire::ARCH{$a->{_name}};
71     return $arch->{alive} and ($arch->{monster} or $arch->{generator});
72     }
73    
74 elmex 1.2 sub stack_find {
75     my ($stack, $dir, $pred) = @_;
76    
77    
78     if ($dir eq 'from_top') {
79     my $i = scalar (@$stack) - 1;
80     if ($i < 0) { $i = 0 }
81    
82     for (reverse @$stack) {
83     $pred->($_)
84     and return $i;
85    
86     $i--;
87     }
88    
89     } else {
90     my $i = 0;
91    
92     for (@$stack) {
93     $pred->($_)
94     and return $i;
95    
96     $i++;
97     }
98     }
99    
100     return 0;
101    
102     }
103    
104     sub stack_find_floor {
105     my ($stack, $dir) = @_;
106     return stack_find ($stack, $dir, \&arch_is_floor);
107     }
108    
109     sub stack_find_wall {
110     my ($stack, $dir) = @_;
111     return stack_find ($stack, $dir, \&arch_is_wall);
112     }
113    
114 elmex 1.1 sub insert_arch_stack_layer {
115     my ($stack, $arch) = @_;
116    
117     unless (@$stack) {
118     return [ $arch ];
119     }
120    
121     my @outstack;
122    
123     my $l = classify_arch_layer ($Crossfire::ARCH{$arch->{_name}});
124    
125     if ($l eq 'between') {
126    
127     # loop until we reached the first 'between' arch above 'below' arches and the floor
128     while (my $a = shift @$stack) {
129    
130     unless ($Crossfire::ARCH{$a->{_name}}->{is_floor}
131     or classify_arch_layer ($Crossfire::ARCH{$a->{_name}}) eq 'below') {
132    
133     unshift @$stack, $a;
134     last;
135     }
136    
137     push @outstack, $a;
138     }
139    
140     # ignore duplicates
141     # FIXME: Broken if non-floor are drawn (too tired to fix)
142     return [ @outstack, @$stack ]
143     if @outstack and $outstack[-1]->{_name} eq $arch->{_name};
144    
145     push @outstack, ($arch, @$stack);
146    
147     } elsif ($l eq 'top') {
148    
149     # ignore duplicates
150     return [ @$stack ]
151     if $stack->[-1]->{_name} eq $arch->{_name};
152    
153     @outstack = (@$stack, $arch);
154    
155     } else {
156    
157     # ignore duplicates
158     return [ @$stack ]
159     if $stack->[0]->{_name} eq $arch->{_name};
160    
161     @outstack = ($arch, @$stack);
162     }
163    
164     return \@outstack;
165     }
166    
167     sub replace_arch_stack_layer {
168     my ($stack, $arch) = @_;
169    
170     my @outstack;
171    
172     my $l = classify_arch_layer ($Crossfire::ARCH{$arch->{_name}});
173    
174     if ($l eq 'between') {
175    
176     while (shift @$stack) {
177     last unless $Crossfire::ARCH{$_->{_name}}->{is_floor};
178     push @outstack, $_;
179     }
180    
181     if (@outstack and $Crossfire::ARCH{$outstack[-1]->{_name}}->{is_floor}) {
182     pop @outstack;
183     }
184    
185     push @outstack, ($arch, @$stack);
186    
187     } elsif ($l eq 'top') {
188    
189     @outstack = (@$stack, $arch);
190    
191     } else {
192    
193     @outstack = ($arch, @$stack);
194     }
195    
196     return \@outstack;
197     }
198    
199     =head1 AUTHOR
200    
201     Marc Lehmann <schmorp@schmorp.de>
202     http://home.schmorp.de/
203    
204     Robin Redeker <elmex@ta-sa.org>
205     http://www.ta-sa.org/
206    
207     =cut
208     1;