ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra/Deliantra.pm
(Generate patch)

Comparing deliantra/Deliantra/Deliantra.pm (file contents):
Revision 1.72 by root, Mon Sep 4 17:58:51 2006 UTC vs.
Revision 1.101 by root, Tue Apr 10 09:37:03 2007 UTC

4 4
5=cut 5=cut
6 6
7package Crossfire; 7package Crossfire;
8 8
9our $VERSION = '0.9'; 9our $VERSION = '0.98';
10 10
11use strict; 11use strict;
12 12
13use base 'Exporter'; 13use base 'Exporter';
14 14
19 19
20our @EXPORT = qw( 20our @EXPORT = qw(
21 read_pak read_arch *ARCH TILESIZE $TILE *FACE editor_archs arch_extents 21 read_pak read_arch *ARCH TILESIZE $TILE *FACE editor_archs arch_extents
22); 22);
23 23
24use JSON::Syck (); #TODO#d# replace by JSON::PC when it becomes available == working 24use JSON::XS qw(from_json to_json);
25
26sub from_json($) {
27 $JSON::Syck::ImplicitUnicode = 1;
28 JSON::Syck::Load $_[0]
29}
30
31sub to_json($) {
32 $JSON::Syck::ImplicitUnicode = 0;
33 JSON::Syck::Dump $_[0]
34}
35 25
36our $LIB = $ENV{CROSSFIRE_LIBDIR}; 26our $LIB = $ENV{CROSSFIRE_LIBDIR};
37 27
38our $VARDIR = $ENV{HOME} ? "$ENV{HOME}/.crossfire" : File::Spec->tmpdir . "/crossfire"; 28our $VARDIR = $ENV{HOME} ? "$ENV{HOME}/.crossfire"
29 : $ENV{AppData} ? "$ENV{APPDATA}/crossfire"
30 : File::Spec->tmpdir . "/crossfire";
39 31
40mkdir $VARDIR, 0777; 32mkdir $VARDIR, 0777;
41 33
42sub TILESIZE (){ 32 } 34sub TILESIZE (){ 32 }
43 35
56 qw(move_type move_block move_allow move_on move_off move_slow); 48 qw(move_type move_block move_allow move_on move_off move_slow);
57 49
58# same as in server save routine, to (hopefully) be compatible 50# same as in server save routine, to (hopefully) be compatible
59# to the other editors. 51# to the other editors.
60our @FIELD_ORDER_MAP = (qw( 52our @FIELD_ORDER_MAP = (qw(
53 file_format_version
61 name attach swap_time reset_timeout fixed_resettime difficulty region 54 name attach swap_time reset_timeout fixed_resettime difficulty region
62 shopitems shopgreed shopmin shopmax shoprace 55 shopitems shopgreed shopmin shopmax shoprace
63 darkness width height enter_x enter_y msg maplore 56 darkness width height enter_x enter_y msg maplore
64 unique template 57 unique template
65 outdoor temp pressure humid windspeed winddir sky nosmooth 58 outdoor temp pressure humid windspeed winddir sky nosmooth
68 61
69our @FIELD_ORDER = (qw( 62our @FIELD_ORDER = (qw(
70 elevation 63 elevation
71 64
72 name name_pl custom_name attach title race 65 name name_pl custom_name attach title race
73 slaying skill msg lore other_arch face 66 slaying skill msg lore other_arch
74 #todo-events 67 is_animated animation face
75 animation is_animated 68 magicmap smoothlevel smoothface
76 str dex con wis pow cha int 69 str dex con wis pow cha int
77 hp maxhp sp maxsp grace maxgrace 70 hp maxhp sp maxsp grace maxgrace
78 exp perm_exp expmul 71 exp perm_exp expmul
79 food dam luck wc ac x y speed speed_left move_state attack_movement 72 food dam luck wc ac x y speed speed_left move_state attack_movement
80 nrof level direction type subtype attacktype 73 nrof level direction type subtype attacktype
136sub MOVE_FLY_HIGH (){ 0x04 } 129sub MOVE_FLY_HIGH (){ 0x04 }
137sub MOVE_FLYING (){ 0x06 } 130sub MOVE_FLYING (){ 0x06 }
138sub MOVE_SWIM (){ 0x08 } 131sub MOVE_SWIM (){ 0x08 }
139sub MOVE_BOAT (){ 0x10 } 132sub MOVE_BOAT (){ 0x10 }
140sub MOVE_KNOWN (){ 0x1f } # all of above 133sub MOVE_KNOWN (){ 0x1f } # all of above
141sub MOVE_ALLBIT (){ 0x10000 }
142sub MOVE_ALL (){ 0x1001f } # very special value, more PITA 134sub MOVE_ALL (){ 0x10000 } # very special value
135
136our %MOVE_TYPE = (
137 walk => MOVE_WALK,
138 fly_low => MOVE_FLY_LOW,
139 fly_high => MOVE_FLY_HIGH,
140 flying => MOVE_FLYING,
141 swim => MOVE_SWIM,
142 boat => MOVE_BOAT,
143 all => MOVE_ALL,
144);
145
146our @MOVE_TYPE = qw(all walk flying fly_low fly_high swim boat);
147
148{
149 package Crossfire::MoveType;
150
151 use overload
152 '=' => sub { bless [@{$_[0]}], ref $_[0] },
153 '""' => \&as_string,
154 '>=' => sub { $_[0][0] & $MOVE_TYPE{$_[1]} ? $_[0][1] & $MOVE_TYPE{$_[1]} : undef },
155 '+=' => sub { $_[0][0] |= $MOVE_TYPE{$_[1]}; $_[0][1] |= $MOVE_TYPE{$_[1]}; &normalise },
156 '-=' => sub { $_[0][0] |= $MOVE_TYPE{$_[1]}; $_[0][1] &= ~$MOVE_TYPE{$_[1]}; &normalise },
157 '/=' => sub { $_[0][0] &= ~$MOVE_TYPE{$_[1]}; &normalise },
158 'x=' => sub {
159 my $cur = $_[0] >= $_[1];
160 if (!defined $cur) {
161 if ($_[0] >= "all") {
162 $_[0] -= $_[1];
163 } else {
164 $_[0] += $_[1];
165 }
166 } elsif ($cur) {
167 $_[0] -= $_[1];
168 } else {
169 $_[0] /= $_[1];
170 }
171
172 $_[0]
173 },
174 'eq' => sub { "$_[0]" eq "$_[1]" },
175 'ne' => sub { "$_[0]" ne "$_[1]" },
176 ;
177}
178
179sub Crossfire::MoveType::new {
180 my ($class, $string) = @_;
181
182 my $mask;
183 my $value;
184
185 if ($string =~ /^\s*\d+\s*$/) {
186 $mask = MOVE_ALL;
187 $value = $string+0;
188 } else {
189 for (split /\s+/, lc $string) {
190 if (s/^-//) {
191 $mask |= $MOVE_TYPE{$_};
192 $value &= ~$MOVE_TYPE{$_};
193 } else {
194 $mask |= $MOVE_TYPE{$_};
195 $value |= $MOVE_TYPE{$_};
196 }
197 }
198 }
199
200 (bless [$mask, $value], $class)->normalise
201}
202
203sub Crossfire::MoveType::normalise {
204 my ($self) = @_;
205
206 if ($self->[0] & MOVE_ALL) {
207 my $mask = ~(($self->[1] & MOVE_ALL ? $self->[1] : ~$self->[1]) & $self->[0] & ~MOVE_ALL);
208 $self->[0] &= $mask;
209 $self->[1] &= $mask;
210 }
211
212 $self->[1] &= $self->[0];
213
214 $self
215}
216
217sub Crossfire::MoveType::as_string {
218 my ($self) = @_;
219
220 my @res;
221
222 my ($mask, $value) = @$self;
223
224 for (@Crossfire::MOVE_TYPE) {
225 my $bit = $Crossfire::MOVE_TYPE{$_};
226 if (($mask & $bit) == $bit && (($value & $bit) == $bit || ($value & $bit) == 0)) {
227 $mask &= ~$bit;
228 push @res, $value & $bit ? $_ : "-$_";
229 }
230 }
231
232 join " ", @res
233}
143 234
144sub load_ref($) { 235sub load_ref($) {
145 my ($path) = @_; 236 my ($path) = @_;
146 237
147 open my $fh, "<:raw:perlio", $path 238 open my $fh, "<:raw:perlio", $path
193 284
194sub _add_resist($$$) { 285sub _add_resist($$$) {
195 my ($ob, $mask, $value) = @_; 286 my ($ob, $mask, $value) = @_;
196 287
197 while (my ($k, $v) = each %attack_mask) { 288 while (my ($k, $v) = each %attack_mask) {
198 $ob->{"resist_$k"} += $value if $mask & $v; 289 $ob->{"resist_$k"} = min 100, max -100, $ob->{"resist_$k"} + $value if $mask & $v;
199 } 290 }
200} 291}
292
293my %MATERIAL = reverse
294 paper => 1,
295 iron => 2,
296 glass => 4,
297 leather => 8,
298 wood => 16,
299 organic => 32,
300 stone => 64,
301 cloth => 128,
302 adamant => 256,
303 liquid => 512,
304 tin => 1024,
305 bone => 2048,
306 ice => 4096,
307
308 # guesses
309 runestone => 12,
310 bronze => 18,
311 "ancient wood" => 20,
312 glass => 36,
313 marble => 66,
314 ice => 68,
315 stone => 70,
316 stone => 80,
317 cloth => 136,
318 ironwood => 144,
319 adamantium => 258,
320 glacium => 260,
321 blood => 544,
322;
201 323
202# object as in "Object xxx", i.e. archetypes 324# object as in "Object xxx", i.e. archetypes
203sub normalize_object($) { 325sub normalize_object($) {
204 my ($ob) = @_; 326 my ($ob) = @_;
205 327
328 # convert material bitset to materialname, if possible
329 if (exists $ob->{material}) {
330 if (!$ob->{material}) {
331 delete $ob->{material};
332 } elsif (exists $ob->{materialname}) {
333 if ($MATERIAL{$ob->{material}} eq $ob->{materialname}) {
334 delete $ob->{material};
335 } else {
336 warn "object $ob->{_name} has both materialname ($ob->{materialname}) and material ($ob->{material}) set.\n";
337 delete $ob->{material}; # assume materilname is more specific and nuke material
338 }
339 } elsif (my $name = $MATERIAL{$ob->{material}}) {
340 delete $ob->{material};
341 $ob->{materialname} = $name;
342 } else {
343 warn "object $ob->{_name} has unknown material ($ob->{material}) set.\n";
344 }
345 }
346
347 # color_fg is used as default for magicmap if magicmap does not exist
348 $ob->{magicmap} ||= delete $ob->{color_fg} if exists $ob->{color_fg};
349
206 # nuke outdated or never supported fields 350 # nuke outdated or never supported fields
207 delete @$ob{qw( 351 delete @$ob{qw(
208 can_knockback can_parry can_impale can_cut can_dam_armour 352 can_knockback can_parry can_impale can_cut can_dam_armour
209 can_apply pass_thru can_pass_thru 353 can_apply pass_thru can_pass_thru color_bg color_fg
210 )}; 354 )};
211 355
212 if (my $mask = delete $ob->{immune} ) { _add_resist $ob, $mask, 100; } 356 if (my $mask = delete $ob->{immune} ) { _add_resist $ob, $mask, 100; }
213 if (my $mask = delete $ob->{protected} ) { _add_resist $ob, $mask, 30; } 357 if (my $mask = delete $ob->{protected} ) { _add_resist $ob, $mask, 30; }
214 if (my $mask = delete $ob->{vulnerable}) { _add_resist $ob, $mask, -100; } 358 if (my $mask = delete $ob->{vulnerable}) { _add_resist $ob, $mask, -100; }
215 359
216 # convert movement strings to bitsets 360 # convert movement strings to bitsets
217 for my $attr (keys %FIELD_MOVEMENT) { 361 for my $attr (keys %FIELD_MOVEMENT) {
218 next unless exists $ob->{$attr}; 362 next unless exists $ob->{$attr};
219 363
220 $ob->{$attr} = MOVE_ALL if $ob->{$attr} == 255; #d# compatibility 364 $ob->{$attr} = new Crossfire::MoveType $ob->{$attr};
221
222 next if $ob->{$attr} =~ /^\d+$/;
223
224 my $flags = 0;
225
226 # assume list
227 for my $flag (map lc, split /\s+/, $ob->{$attr}) {
228 $flags |= MOVE_WALK if $flag eq "walk";
229 $flags |= MOVE_FLY_LOW if $flag eq "fly_low";
230 $flags |= MOVE_FLY_HIGH if $flag eq "fly_high";
231 $flags |= MOVE_FLYING if $flag eq "flying";
232 $flags |= MOVE_SWIM if $flag eq "swim";
233 $flags |= MOVE_BOAT if $flag eq "boat";
234 $flags |= MOVE_ALL if $flag eq "all";
235
236 $flags &= ~MOVE_WALK if $flag eq "-walk";
237 $flags &= ~MOVE_FLY_LOW if $flag eq "-fly_low";
238 $flags &= ~MOVE_FLY_HIGH if $flag eq "-fly_high";
239 $flags &= ~MOVE_FLYING if $flag eq "-flying";
240 $flags &= ~MOVE_SWIM if $flag eq "-swim";
241 $flags &= ~MOVE_BOAT if $flag eq "-boat";
242 $flags &= ~MOVE_ALL if $flag eq "-all";
243 }
244
245 $ob->{$attr} = $flags;
246 } 365 }
247 366
248 # convert outdated movement flags to new movement sets 367 # convert outdated movement flags to new movement sets
249 if (defined (my $v = delete $ob->{no_pass})) { 368 if (defined (my $v = delete $ob->{no_pass})) {
250 $ob->{move_block} = $v ? MOVE_ALL : 0; 369 $ob->{move_block} = new Crossfire::MoveType $v ? "all" : "";
251 } 370 }
252 if (defined (my $v = delete $ob->{slow_move})) { 371 if (defined (my $v = delete $ob->{slow_move})) {
253 $ob->{move_slow} |= MOVE_WALK; 372 $ob->{move_slow} += "walk";
254 $ob->{move_slow_penalty} = $v; 373 $ob->{move_slow_penalty} = $v;
255 } 374 }
256 if (defined (my $v = delete $ob->{walk_on})) { 375 if (defined (my $v = delete $ob->{walk_on})) {
257 $ob->{move_on} = MOVE_ALL unless exists $ob->{move_on}; 376 $ob->{move_on} ||= new Crossfire::MoveType; if ($v) { $ob->{move_on} += "walk" } else { $ob->{move_on} -= "walk" }
258 $ob->{move_on} = $v ? $ob->{move_on} | MOVE_WALK
259 : $ob->{move_on} & ~MOVE_WALK;
260 } 377 }
261 if (defined (my $v = delete $ob->{walk_off})) { 378 if (defined (my $v = delete $ob->{walk_off})) {
262 $ob->{move_off} = MOVE_ALL unless exists $ob->{move_off}; 379 $ob->{move_off} ||= new Crossfire::MoveType; if ($v) { $ob->{move_off} += "walk" } else { $ob->{move_off} -= "walk" }
263 $ob->{move_off} = $v ? $ob->{move_off} | MOVE_WALK
264 : $ob->{move_off} & ~MOVE_WALK;
265 } 380 }
266 if (defined (my $v = delete $ob->{fly_on})) { 381 if (defined (my $v = delete $ob->{fly_on})) {
267 $ob->{move_on} = MOVE_ALL unless exists $ob->{move_on}; 382 $ob->{move_on} ||= new Crossfire::MoveType; if ($v) { $ob->{move_on} += "fly_low" } else { $ob->{move_on} -= "fly_low" }
268 $ob->{move_on} = $v ? $ob->{move_on} | MOVE_FLY_LOW
269 : $ob->{move_on} & ~MOVE_FLY_LOW;
270 } 383 }
271 if (defined (my $v = delete $ob->{fly_off})) { 384 if (defined (my $v = delete $ob->{fly_off})) {
272 $ob->{move_off} = MOVE_ALL unless exists $ob->{move_off}; 385 $ob->{move_off} ||= new Crossfire::MoveType; if ($v) { $ob->{move_off} += "fly_low" } else { $ob->{move_off} -= "fly_low" }
273 $ob->{move_off} = $v ? $ob->{move_off} | MOVE_FLY_LOW
274 : $ob->{move_off} & ~MOVE_FLY_LOW;
275 } 386 }
276 if (defined (my $v = delete $ob->{flying})) { 387 if (defined (my $v = delete $ob->{flying})) {
277 $ob->{move_type} = MOVE_ALL unless exists $ob->{move_type}; 388 $ob->{move_type} ||= new Crossfire::MoveType; if ($v) { $ob->{move_type} += "fly_low" } else { $ob->{move_type} -= "fly_low" }
278 $ob->{move_type} = $v ? $ob->{move_type} | MOVE_FLY_LOW
279 : $ob->{move_type} & ~MOVE_FLY_LOW;
280 } 389 }
281 390
282 # convert idiotic event_xxx things into objects 391 # convert idiotic event_xxx things into objects
283 while (my ($event, $subtype) = each %EVENT_TYPE) { 392 while (my ($event, $subtype) = each %EVENT_TYPE) {
284 if (exists $ob->{"event_${event}_plugin"}) { 393 if (exists $ob->{"event_${event}_plugin"}) {
288 slaying => delete $ob->{"event_${event}"}, 397 slaying => delete $ob->{"event_${event}"},
289 name => delete $ob->{"event_${event}_options"}, 398 name => delete $ob->{"event_${event}_options"},
290 }; 399 };
291 } 400 }
292 } 401 }
402
403 # some archetypes had "+3" instead of the canonical "3", so fix
404 $ob->{dam} *= 1 if exists $ob->{dam};
293 405
294 $ob 406 $ob
295} 407}
296 408
297# arch as in "arch xxx", ie.. objects 409# arch as in "arch xxx", ie.. objects
379sub read_arch($;$) { 491sub read_arch($;$) {
380 my ($path, $toplevel) = @_; 492 my ($path, $toplevel) = @_;
381 493
382 my %arc; 494 my %arc;
383 my ($more, $prev); 495 my ($more, $prev);
496 my $comment;
384 497
385 open my $fh, "<:raw:perlio:utf8", $path 498 open my $fh, "<:raw:perlio:utf8", $path
386 or Carp::croak "$path: $!"; 499 or Carp::croak "$path: $!";
387 500
388# binmode $fh; 501# binmode $fh;
392 505
393 while (<$fh>) { 506 while (<$fh>) {
394 s/\s+$//; 507 s/\s+$//;
395 if (/^end$/i) { 508 if (/^end$/i) {
396 last; 509 last;
510
397 } elsif (/^arch (\S+)$/i) { 511 } elsif (/^arch (\S+)$/i) {
398 push @{ $arc{inventory} }, attr_thaw normalize_arch $parse_block->(_name => $1); 512 push @{ $arc{inventory} }, attr_thaw normalize_arch $parse_block->(_name => $1);
513
399 } elsif (/^lore$/i) { 514 } elsif (/^lore$/i) {
400 while (<$fh>) { 515 while (<$fh>) {
401 last if /^endlore\s*$/i; 516 last if /^endlore\s*$/i;
402 $arc{lore} .= $_; 517 $arc{lore} .= $_;
403 } 518 }
412 chomp; 527 chomp;
413 push @{ $arc{anim} }, $_; 528 push @{ $arc{anim} }, $_;
414 } 529 }
415 } elsif (/^(\S+)\s*(.*)$/) { 530 } elsif (/^(\S+)\s*(.*)$/) {
416 $arc{lc $1} = $2; 531 $arc{lc $1} = $2;
417 } elsif (/^\s*($|#)/) { 532 } elsif (/^\s*#/) {
533 $arc{_comment} .= "$_\n";
534
535 } elsif (/^\s*$/) {
418 # 536 #
419 } else { 537 } else {
420 warn "$path: unparsable line '$_' in arch $arc{_name}"; 538 warn "$path: unparsable line '$_' in arch $arc{_name}";
421 } 539 }
422 } 540 }
428 s/\s+$//; 546 s/\s+$//;
429 if (/^more$/i) { 547 if (/^more$/i) {
430 $more = $prev; 548 $more = $prev;
431 } elsif (/^object (\S+)$/i) { 549 } elsif (/^object (\S+)$/i) {
432 my $name = $1; 550 my $name = $1;
433 my $arc = attr_thaw normalize_object $parse_block->(_name => $name); 551 my $arc = attr_thaw normalize_object $parse_block->(_name => $name, _comment => $comment);
552 undef $comment;
553 delete $arc{_comment} unless length $arc{_comment};
434 $arc->{_atype} = 'object'; 554 $arc->{_atype} = 'object';
435 555
436 if ($more) { 556 if ($more) {
437 $more->{more} = $arc; 557 $more->{more} = $arc;
438 } else { 558 } else {
440 } 560 }
441 $prev = $arc; 561 $prev = $arc;
442 $more = undef; 562 $more = undef;
443 } elsif (/^arch (\S+)$/i) { 563 } elsif (/^arch (\S+)$/i) {
444 my $name = $1; 564 my $name = $1;
445 my $arc = attr_thaw normalize_arch $parse_block->(_name => $name); 565 my $arc = attr_thaw normalize_arch $parse_block->(_name => $name, _comment => $comment);
566 undef $comment;
567 delete $arc{_comment} unless length $arc{_comment};
446 $arc->{_atype} = 'arch'; 568 $arc->{_atype} = 'arch';
447 569
448 if ($more) { 570 if ($more) {
449 $more->{more} = $arc; 571 $more->{more} = $arc;
450 } else { 572 } else {
459 push @{$toplevel->{lev_array}}, $_+0; 581 push @{$toplevel->{lev_array}}, $_+0;
460 } 582 }
461 } else { 583 } else {
462 $toplevel->{$1} = $2; 584 $toplevel->{$1} = $2;
463 } 585 }
586 } elsif (/^\s*#/) {
587 $comment .= "$_\n";
464 } elsif (/^\s*($|#)/) { 588 } elsif (/^\s*($|#)/) {
465 # 589 #
466 } else { 590 } else {
467 die "$path: unparseable top-level line '$_'"; 591 die "$path: unparseable top-level line '$_'";
468 } 592 }
488 if (exists $a{attack_movement_bits_0_3} or exists $a{attack_movement_bits_4_7}) { 612 if (exists $a{attack_movement_bits_0_3} or exists $a{attack_movement_bits_4_7}) {
489 $a{attack_movement} = (delete $a{attack_movement_bits_0_3}) 613 $a{attack_movement} = (delete $a{attack_movement_bits_0_3})
490 | (delete $a{attack_movement_bits_4_7}); 614 | (delete $a{attack_movement_bits_4_7});
491 } 615 }
492 616
617 if (my $comment = delete $a{_comment}) {
618 if ($comment =~ /[^\n\s#]/) {
619 $str .= $comment;
620 }
621 }
622
493 $str .= ((exists $a{_atype}) ? $a{_atype} : 'arch'). " $a{_name}\n"; 623 $str .= ((exists $a{_atype}) ? $a{_atype} : 'arch'). " $a{_name}\n";
494 624
495 my $inv = delete $a{inventory}; 625 my $inv = delete $a{inventory};
496 my $more = delete $a{more}; # arches do not support 'more', but old maps can contain some 626 my $more = delete $a{more}; # arches do not support 'more', but old maps can contain some
497 my $anim = delete $a{anim}; 627 my $anim = delete $a{anim};
628
629 if ($a{_atype} eq 'object') {
630 $str .= join "\n", "anim", @$anim, "mina\n"
631 if $anim;
632 }
498 633
499 my @kv; 634 my @kv;
500 635
501 for ($a{_name} eq "map" 636 for ($a{_name} eq "map"
502 ? @Crossfire::FIELD_ORDER_MAP 637 ? @Crossfire::FIELD_ORDER_MAP
514 my ($k, $v) = @$_; 649 my ($k, $v) = @$_;
515 650
516 if (my $end = $Crossfire::FIELD_MULTILINE{$k}) { 651 if (my $end = $Crossfire::FIELD_MULTILINE{$k}) {
517 $v =~ s/\n$//; 652 $v =~ s/\n$//;
518 $str .= "$k\n$v\n$end\n"; 653 $str .= "$k\n$v\n$end\n";
519 } elsif (exists $Crossfire::FIELD_MOVEMENT{$k}) {
520 if ($v & ~Crossfire::MOVE_ALL or !$v) {
521 $str .= "$k $v\n";
522
523 } elsif ($v & Crossfire::MOVE_ALLBIT) {
524 $str .= "$k all";
525
526 $str .= " -walk" unless $v & Crossfire::MOVE_WALK;
527 $str .= " -fly_low" unless $v & Crossfire::MOVE_FLY_LOW;
528 $str .= " -fly_high" unless $v & Crossfire::MOVE_FLY_HIGH;
529 $str .= " -swim" unless $v & Crossfire::MOVE_SWIM;
530 $str .= " -boat" unless $v & Crossfire::MOVE_BOAT;
531
532 $str .= "\n";
533
534 } else {
535 $str .= $k;
536
537 $str .= " walk" if $v & Crossfire::MOVE_WALK;
538 $str .= " fly_low" if $v & Crossfire::MOVE_FLY_LOW;
539 $str .= " fly_high" if $v & Crossfire::MOVE_FLY_HIGH;
540 $str .= " swim" if $v & Crossfire::MOVE_SWIM;
541 $str .= " boat" if $v & Crossfire::MOVE_BOAT;
542
543 $str .= "\n";
544 }
545 } else { 654 } else {
546 $str .= "$k $v\n"; 655 $str .= "$k $v\n";
547 } 656 }
548 } 657 }
549 658
550 if ($inv) { 659 if ($inv) {
551 $append->($_) for @$inv; 660 $append->($_) for @$inv;
552 } 661 }
553 662
663 $str .= "end\n";
664
554 if ($a{_atype} eq 'object') { 665 if ($a{_atype} eq 'object') {
555 $str .= join "\n", "anim", @$anim, "mina\n" 666 if ($more) {
556 if $anim;
557 }
558
559 $str .= "end\n";
560
561 if (($a{_atype} eq 'object') && $more) {
562 $str .= "\nmore\n"; 667 $str .= "more\n";
563 $append->($more) if $more; 668 $append->($more) if $more;
669 } else {
670 $str .= "\n";
671 }
564 } 672 }
565 }; 673 };
566 674
567 for (@$arch) { 675 for (@$arch) {
568 $append->($_); 676 $append->($_);
597 my ($a) = @_; 705 my ($a) = @_;
598 706
599 my $o = $ARCH{$a->{_name}} 707 my $o = $ARCH{$a->{_name}}
600 or return; 708 or return;
601 709
602 my $face = $FACE{$a->{face} || $o->{face} || "blank.111"} 710 my $face = $FACE{$a->{face} || $o->{face} || "blank.111"};
711 unless ($face) {
712 $face = $FACE{"blank.x11"}
603 or (warn "no face data found for arch '$a->{_name}'"), return; 713 or (warn "no face data found for arch '$a->{_name}'"), return;
714 }
604 715
605 if ($face->{w} > 1 || $face->{h} > 1) { 716 if ($face->{w} > 1 || $face->{h} > 1) {
606 # bigface 717 # bigface
607 return (0, 0, $face->{w} - 1, $face->{h} - 1); 718 return (0, 0, $face->{w} - 1, $face->{h} - 1);
608 719
715 ]; 826 ];
716 827
717 $attr 828 $attr
718} 829}
719 830
720sub arch_edit_sections {
721# if (edit_type == IGUIConstants.TILE_EDIT_NONE)
722# edit_type = 0;
723# else if (edit_type != 0) {
724# // all flags from 'check_type' must be unset in this arch because they get recalculated now
725# edit_type &= ~check_type;
726# }
727#
728# }
729# if ((check_type & IGUIConstants.TILE_EDIT_MONSTER) != 0 &&
730# getAttributeValue("alive", defarch) == 1 &&
731# (getAttributeValue("monster", defarch) == 1 ||
732# getAttributeValue("generator", defarch) == 1)) {
733# // Monster: monsters/npcs/generators
734# edit_type |= IGUIConstants.TILE_EDIT_MONSTER;
735# }
736# if ((check_type & IGUIConstants.TILE_EDIT_WALL) != 0 &&
737# arch_type == 0 && getAttributeValue("no_pass", defarch) == 1) {
738# // Walls
739# edit_type |= IGUIConstants.TILE_EDIT_WALL;
740# }
741# if ((check_type & IGUIConstants.TILE_EDIT_CONNECTED) != 0 &&
742# getAttributeValue("connected", defarch) != 0) {
743# // Connected Objects
744# edit_type |= IGUIConstants.TILE_EDIT_CONNECTED;
745# }
746# if ((check_type & IGUIConstants.TILE_EDIT_EXIT) != 0 &&
747# arch_type == 66 || arch_type == 41 || arch_type == 95) {
748# // Exit: teleporter/exit/trapdoors
749# edit_type |= IGUIConstants.TILE_EDIT_EXIT;
750# }
751# if ((check_type & IGUIConstants.TILE_EDIT_TREASURE) != 0 &&
752# getAttributeValue("no_pick", defarch) == 0 && (arch_type == 4 ||
753# arch_type == 5 || arch_type == 36 || arch_type == 60 ||
754# arch_type == 85 || arch_type == 111 || arch_type == 123 ||
755# arch_type == 124 || arch_type == 130)) {
756# // Treasure: randomtreasure/money/gems/potions/spellbooks/scrolls
757# edit_type |= IGUIConstants.TILE_EDIT_TREASURE;
758# }
759# if ((check_type & IGUIConstants.TILE_EDIT_DOOR) != 0 &&
760# arch_type == 20 || arch_type == 23 || arch_type == 26 ||
761# arch_type == 91 || arch_type == 21 || arch_type == 24) {
762# // Door: door/special door/gates + keys
763# edit_type |= IGUIConstants.TILE_EDIT_DOOR;
764# }
765# if ((check_type & IGUIConstants.TILE_EDIT_EQUIP) != 0 &&
766# getAttributeValue("no_pick", defarch) == 0 && ((arch_type >= 13 &&
767# arch_type <= 16) || arch_type == 33 || arch_type == 34 ||
768# arch_type == 35 || arch_type == 39 || arch_type == 70 ||
769# arch_type == 87 || arch_type == 99 || arch_type == 100 ||
770# arch_type == 104 || arch_type == 109 || arch_type == 113 ||
771# arch_type == 122 || arch_type == 3)) {
772# // Equipment: weapons/armour/wands/rods
773# edit_type |= IGUIConstants.TILE_EDIT_EQUIP;
774# }
775#
776# return(edit_type);
777#
778#
779}
780
781sub cache_file($$&&) { 831sub cache_file($$&&) {
782 my ($src, $cache, $load, $create) = @_; 832 my ($src, $cache, $load, $create) = @_;
783 833
784 my ($size, $mtime) = (stat $src)[7,9] 834 my ($size, $mtime) = (stat $src)[7,9]
785 or Carp::croak "$src: $!"; 835 or Carp::croak "$src: $!";

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines