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.121 by root, Mon Apr 14 00:35:17 2008 UTC vs.
Revision 1.141 by root, Mon Mar 22 00:58:17 2010 UTC

1=head1 NAME 1=head1 NAME
2 2
3Deliantra - Deliantra suppport module to read/write archetypes, maps etc. 3Deliantra - Deliantra suppport module to read/write archetypes, maps etc.
4 4
5=over 4
6
5=cut 7=cut
6 8
7package Deliantra; 9package Deliantra;
8 10
9our $VERSION = '1.14'; 11our $VERSION = '1.30';
10 12
11use strict; 13use common::sense;
12 14
13use base 'Exporter'; 15use base 'Exporter';
14 16
15use Carp (); 17use Carp ();
16use File::Spec; 18use File::Spec;
24 editor_archs arch_extents 26 editor_archs arch_extents
25); 27);
26 28
27use JSON::XS qw(decode_json encode_json); 29use JSON::XS qw(decode_json encode_json);
28 30
29our $LIB = $ENV{DELIANTRA_LIBDIR} || $ENV{CROSSFIRE_LIBDIR}; 31our $LIB = $ENV{DELIANTRA_LIBDIR};
30
31our $OLDDIR = $ENV{HOME} ? "$ENV{HOME}/.crossfire"
32 : $ENV{AppData} ? "$ENV{APPDATA}/crossfire"
33 : File::Spec->tmpdir . "/crossfire";
34 32
35our $VARDIR = $ENV{HOME} ? "$ENV{HOME}/.deliantra" 33our $VARDIR = $ENV{HOME} ? "$ENV{HOME}/.deliantra"
36 : $ENV{AppData} ? "$ENV{APPDATA}/deliantra" 34 : $ENV{AppData} ? "$ENV{APPDATA}/deliantra"
37 : File::Spec->tmpdir . "/deliantra"; 35 : File::Spec->tmpdir . "/deliantra";
38 36
73 71
74 elevation 72 elevation
75 73
76 name name_pl custom_name attach title race 74 name name_pl custom_name attach title race
77 slaying skill msg lore other_arch 75 slaying skill msg lore other_arch
78 face animation is_animated 76 sound sound_destroy face animation is_animated
79 magicmap smoothlevel smoothface 77 magicmap smoothlevel smoothface
80 str dex con wis pow cha int 78 str dex con wis pow cha int
81 hp maxhp sp maxsp grace maxgrace 79 hp maxhp sp maxsp grace maxgrace
82 exp perm_exp expmul 80 exp perm_exp expmul
83 food dam luck wc ac x y speed speed_left move_state attack_movement 81 food dam luck wc ac x y speed speed_left move_state attack_movement
155 boat => MOVE_BOAT, 153 boat => MOVE_BOAT,
156 ship => MOVE_SHIP, 154 ship => MOVE_SHIP,
157 all => MOVE_ALL, 155 all => MOVE_ALL,
158); 156);
159 157
160our @MOVE_TYPE = keys %MOVE_TYPE; 158our @MOVE_TYPE = qw(all walk flying fly_low fly_high swim boat ship);
161 159
162{ 160{
163 package Deliantra::MoveType; 161 package Deliantra::MoveType;
164 162
165 use overload 163 use overload
166 '=' => sub { bless [@{$_[0]}], ref $_[0] }, 164 '=' => sub { bless [@{$_[0]}], ref $_[0] },
167 '""' => \&as_string, 165 '""' => \&as_string,
168 '>=' => sub { $_[0][0] & $MOVE_TYPE{$_[1]} ? $_[0][1] & $MOVE_TYPE{$_[1]} : undef }, 166 '>=' => sub { $_[0][0] & $MOVE_TYPE{$_[1]} ? $_[0][1] & $MOVE_TYPE{$_[1]} : undef },
167 '<=' => sub {
168 ($_[0][0] & $MOVE_TYPE{$_[1]}) == $MOVE_TYPE{$_[1]}
169 ? $_[0][1] & $MOVE_TYPE{$_[1]}
170 : undef
171 },
169 '+=' => sub { $_[0][0] |= $MOVE_TYPE{$_[1]}; $_[0][1] |= $MOVE_TYPE{$_[1]}; &normalise }, 172 '+=' => sub { $_[0][0] |= $MOVE_TYPE{$_[1]}; $_[0][1] |= $MOVE_TYPE{$_[1]}; &normalise },
170 '-=' => sub { $_[0][0] |= $MOVE_TYPE{$_[1]}; $_[0][1] &= ~$MOVE_TYPE{$_[1]}; &normalise }, 173 '-=' => sub { $_[0][0] |= $MOVE_TYPE{$_[1]}; $_[0][1] &= ~$MOVE_TYPE{$_[1]}; &normalise },
171 '/=' => sub { $_[0][0] &= ~$MOVE_TYPE{$_[1]}; &normalise }, 174 '/=' => sub { $_[0][0] &= ~$MOVE_TYPE{$_[1]}; &normalise },
172 'x=' => sub { 175 'x=' => sub { # toggle between off, + and -
173 my $cur = $_[0] >= $_[1]; 176 my $cur = $_[0] >= $_[1];
174 if (!defined $cur) { 177 if (!defined $cur) {
175 if ($_[0] >= "all") { 178 if ($_[0] >= "all") {
176 $_[0] -= $_[1]; 179 $_[0] -= $_[1];
177 } else { 180 } else {
186 $_[0] 189 $_[0]
187 }, 190 },
188 'eq' => sub { "$_[0]" eq "$_[1]" }, 191 'eq' => sub { "$_[0]" eq "$_[1]" },
189 'ne' => sub { "$_[0]" ne "$_[1]" }, 192 'ne' => sub { "$_[0]" ne "$_[1]" },
190 ; 193 ;
194
195 sub TO_JSON {
196 $_[0][0]
197 }
191} 198}
192 199
193sub Deliantra::MoveType::new { 200sub Deliantra::MoveType::new {
194 my ($class, $string) = @_; 201 my ($class, $string) = @_;
195 202
337 344
338# object as in "Object xxx", i.e. archetypes 345# object as in "Object xxx", i.e. archetypes
339sub normalize_object($) { 346sub normalize_object($) {
340 my ($ob) = @_; 347 my ($ob) = @_;
341 348
349 delete $ob->{editable}; # deprecated
350
342 # convert material bitset to materialname, if possible 351 # convert material bitset to materialname, if possible
343 if (exists $ob->{material}) { 352 if (exists $ob->{material}) {
344 if (!$ob->{material}) { 353 if (!$ob->{material}) {
345 delete $ob->{material}; 354 delete $ob->{material};
346 } elsif (exists $ob->{materialname}) { 355 } elsif (exists $ob->{materialname}) {
389 $ob->{$attr} = new Deliantra::MoveType $ob->{$attr}; 398 $ob->{$attr} = new Deliantra::MoveType $ob->{$attr};
390 } 399 }
391 400
392 # convert outdated movement flags to new movement sets 401 # convert outdated movement flags to new movement sets
393 if (defined (my $v = delete $ob->{no_pass})) { 402 if (defined (my $v = delete $ob->{no_pass})) {
394 $ob->{move_block} = new Deliantra::MoveType $v ? "all" : ""; 403 $ob->{move_block} = new Deliantra::MoveType $v ? "all" : "0";
395 } 404 }
396 if (defined (my $v = delete $ob->{slow_move})) { 405 if (defined (my $v = delete $ob->{slow_move})) {
397 $ob->{move_slow} += "walk"; 406 $ob->{move_slow} += "walk";
398 $ob->{move_slow_penalty} = $v; 407 $ob->{move_slow_penalty} = $v;
399 } 408 }
400 if (defined (my $v = delete $ob->{walk_on})) { 409 if (defined (my $v = delete $ob->{walk_on})) {
401 $ob->{move_on} ||= new Deliantra::MoveType; if ($v) { $ob->{move_on} += "walk" } else { $ob->{move_on} -= "walk" } 410 $ob->{move_on} ||= new Deliantra::MoveType; if ($v) { $ob->{move_on} += "walk" } else { $ob->{move_on} -= "walk" }
402 } 411 }
403 if (defined (my $v = delete $ob->{walk_off})) { 412 if (defined (my $v = delete $ob->{walk_off})) {
404 $ob->{move_off} ||= new Deliantra::MoveType; if ($v) { $ob->{move_off} += "walk" } else { $ob->{move_off} -= "walk" } 413 $ob->{move_off} ||= new Deliantra::MoveType; if ($v) { $ob->{move_off} += "walk" } else { $ob->{move_off} -= "walk" }
405 } 414 }
406 if (defined (my $v = delete $ob->{fly_on})) { 415 if (defined (my $v = delete $ob->{fly_on})) {
434# arch as in "arch xxx", ie.. objects 443# arch as in "arch xxx", ie.. objects
435sub normalize_arch($) { 444sub normalize_arch($) {
436 my ($ob) = @_; 445 my ($ob) = @_;
437 446
438 normalize_object $ob; 447 normalize_object $ob;
448
449 return if $ob->{_atype} eq "object";
439 450
440 my $arch = $ARCH{$ob->{_name}} 451 my $arch = $ARCH{$ob->{_name}}
441 or (warn "$ob->{_name}: no such archetype", return $ob); 452 or (warn "$ob->{_name}: no such archetype", return $ob);
442 453
443 if ($arch->{type} == 22) { # map 454 if ($arch->{type} == 22) { # map
518 529
519 my %arc; 530 my %arc;
520 my ($more, $prev); 531 my ($more, $prev);
521 my $comment; 532 my $comment;
522 533
523 open my $fh, "<:raw:perlio:utf8", $path 534 open my $fh, "<:utf8", $path
524 or Carp::croak "$path: $!"; 535 or Carp::croak "$path: $!";
525 536
526# binmode $fh; 537# binmode $fh;
527 538
528 my $parse_block; $parse_block = sub { 539 my $parse_block; $parse_block = sub {
803 } else { 814 } else {
804 $root = $Deliantra::Data::TYPE{Misc}; 815 $root = $Deliantra::Data::TYPE{Misc};
805 } 816 }
806 } 817 }
807 818
819 my (%ignore);
808 my @import = ($root); 820 my @import = ($root);
809
810 unshift @import, \%Deliantra::Data::DEFAULT_ATTR
811 unless $type == 116;
812 821
813 my (%ignore); 822 my @new_import;
814 my (@section_order, %section, @attr_order);
815
816 while (my $type = shift @import) { 823 while (my $type = shift @import) {
824 # first import everything we will need:
817 push @import, 825 push @import,
818 grep $_, 826 grep $_,
819 map $Deliantra::Data::TYPE{$_}, 827 map $Deliantra::Data::TYPE{$_},
820 @{$type->{import} || []}; 828 @{$type->{import} || []};
821 829
830 # and compute the ignored attributes
831 for (@{$type->{ignore} || []}) {
832 $ignore{$_}++ for ref $_ ? @$_ : $_;
833 }
834
835 push @new_import, $type;
836 }
837 (@import) = @new_import;
838
839 # then add defaults to the back of the list, so they are added
840 # as last resort.
841 push @import, \%Deliantra::Data::DEFAULT_ATTR
842 unless $type == 116;
843
844 my (@section_order, %section, @attr_order);
845
846 # @import = root, imported, default
847 while (my $type = pop @import) {
822 $attr->{$_} ||= $type->{$_} 848 $attr->{$_} ||= $type->{$_}
823 for qw(name desc use); 849 for qw(name desc use);
824
825 for (@{$type->{ignore} || []}) {
826 $ignore{$_}++ for ref $_ ? @$_ : $_;
827 }
828 850
829 for ([general => ($type->{attr} || [])], @{$type->{section} || []}) { 851 for ([general => ($type->{attr} || [])], @{$type->{section} || []}) {
830 my ($name, $attr) = @$_; 852 my ($name, $attr) = @$_;
831 push @section_order, $name; 853 push @section_order, $name;
832 for (@$attr) { 854 for (@$attr) {
833 my ($k, $v) = @$_; 855 my ($k, $v) = @$_;
834 push @attr_order, $k; 856 push @attr_order, $k;
835 $section{$name}{$k} ||= $v; 857 $section{$name}{$k} = $v; # overwrite, so that the root decides
836 }
837 } 858 }
859 }
860 }
861
862 # remove ignores for "root" type
863 for (
864 map @{$_->[1]}, # section attributes
865 [general => ($root->{attr} || [])],
866 @{$root->{section} || []}
867 ) {
868 my ($k, $v) = @$_;
869 # skip fixed attributes, if they are ignored thats fine
870 next if $v->{type} eq 'fixed';
871
872 delete $ignore{$k}; # if the attributes are defined explicitly they
873 # should NOT be ignored. ignore should mainly
874 # hit imported/inherited attributes.
838 } 875 }
839 876
840 $attr->{section} = [ 877 $attr->{section} = [
841 map !exists $section{$_} ? () : do { 878 map !exists $section{$_} ? () : do {
842 my $attr = delete $section{$_}; 879 my $attr = delete $section{$_};
846 map exists $attr->{$_} && !$ignore{$_} 883 map exists $attr->{$_} && !$ignore{$_}
847 ? [$_ => delete $attr->{$_}] : (), 884 ? [$_ => delete $attr->{$_}] : (),
848 @attr_order 885 @attr_order
849 ] 886 ]
850 }, 887 },
851
852 exists $section{$_} ? [$_ => delete $section{$_}] : (), 888 exists $section{$_} ? [$_ => delete $section{$_}] : (),
853 @section_order 889 @section_order
854 ]; 890 ];
855 891
856 $attr 892 $attr
857} 893}
985 1021
986 \%cache 1022 \%cache
987 }; 1023 };
988} 1024}
989 1025
1026=back
1027
990=head1 AUTHOR 1028=head1 AUTHOR
991 1029
992 Marc Lehmann <schmorp@schmorp.de> 1030 Marc Lehmann <schmorp@schmorp.de>
993 http://home.schmorp.de/ 1031 http://home.schmorp.de/
994 1032

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines