… | |
… | |
20 | |
20 | |
21 | =cut |
21 | =cut |
22 | |
22 | |
23 | our $CFG; |
23 | our $CFG; |
24 | |
24 | |
25 | sub read_config { |
25 | sub load_config { |
26 | my ($filename) = @_; |
26 | cf::trace "loading jeweler config from $cf::DATADIR/jeweler\n"; |
27 | |
27 | |
28 | if (my $meta = $cf::RESOURCE{$filename}) { |
28 | 0 < Coro::AIO::aio_load "$cf::DATADIR/jeweler", my $data |
|
|
29 | or die "$cf::DATADIR/jeweler: $!"; |
|
|
30 | |
29 | $CFG = cf::decode_json $meta->{data}; |
31 | $CFG = cf::decode_json $data; |
30 | } else { |
|
|
31 | warn "$filename doesn't exist! no config for jeweler skill loaded!\n"; |
|
|
32 | $CFG = {}; |
|
|
33 | } |
|
|
34 | } |
32 | } |
35 | |
33 | |
36 | sub getcfg { |
34 | sub getcfg { |
37 | my ($sect, $key) = @_; |
35 | my ($sect, $key) = @_; |
38 | return $CFG->{$sect} unless defined $key; |
36 | return $CFG->{$sect} unless defined $key; |
… | |
… | |
172 | next; |
170 | next; |
173 | } |
171 | } |
174 | $found = 1; |
172 | $found = 1; |
175 | my $r = Jeweler::Object->new (object => $_); |
173 | my $r = Jeweler::Object->new (object => $_); |
176 | my $msg = $r->analyze ($sk, $pl, $input_level); |
174 | my $msg = $r->analyze ($sk, $pl, $input_level); |
177 | $pl->message ($r->to_string . ": " . $msg); |
175 | $pl->message ("There is a '" . $r->to_string . "' in the workbench. Your analysis: " . $msg); |
178 | if ($pl->flag (cf::FLAG_WIZ)) { |
176 | if ($pl->flag (cf::FLAG_WIZ)) { |
179 | $r->wiz_analyze ($pl); |
177 | $r->wiz_analyze ($pl); |
180 | } |
178 | } |
181 | } |
179 | } |
182 | $pl->message ("You couldn't identify the other rings and not analyze them!") |
180 | $pl->message ("You couldn't identify the other rings and not analyze them!") |
… | |
… | |
251 | } |
249 | } |
252 | |
250 | |
253 | |
251 | |
254 | package Jeweler::CauldronHandler; |
252 | package Jeweler::CauldronHandler; |
255 | |
253 | |
256 | use strict; |
254 | use common::sense; |
257 | |
255 | |
258 | =head2 CauldronHandler |
256 | =head2 CauldronHandler |
259 | |
257 | |
260 | The Jeweler::CauldronHandler package, that helps you with handling the |
258 | The Jeweler::CauldronHandler package, that helps you with handling the |
261 | cauldron stuff. Can also be used for other skills. |
259 | cauldron stuff. Can also be used for other skills. |
… | |
… | |
369 | =back |
367 | =back |
370 | |
368 | |
371 | =cut |
369 | =cut |
372 | |
370 | |
373 | package Jeweler::Ingredients; |
371 | package Jeweler::Ingredients; |
|
|
372 | |
|
|
373 | use common::sense; |
|
|
374 | |
374 | use Storable qw/dclone/; |
375 | use Storable qw/dclone/; |
375 | use strict; |
|
|
376 | |
376 | |
377 | =head2 Ingredients |
377 | =head2 Ingredients |
378 | |
378 | |
379 | This class handles the ingredients. |
379 | This class handles the ingredients. |
380 | |
380 | |
… | |
… | |
591 | } |
591 | } |
592 | |
592 | |
593 | if ($do_remove) { |
593 | if ($do_remove) { |
594 | my $rem = $costs->{$key}; |
594 | my $rem = $costs->{$key}; |
595 | $self->do_grep (sub { |
595 | $self->do_grep (sub { |
|
|
596 | if ($rem) { |
596 | if ($rem) { $rem = Jeweler::Util::remove ($_[0], $rem); } |
597 | $rem = Jeweler::Util::remove ($_[0], $rem); |
|
|
598 | } |
597 | 1 |
599 | 1 |
598 | }, @grepar); |
600 | }, @grepar); |
599 | if ($rem > 0) { |
601 | if ($rem > 0) { |
600 | warn "JEWELER BUG: removed ingredients ($key) $rem > 0 after removing!"; |
602 | warn "JEWELER BUG: removed ingredients ($key) $rem > 0 after removing!"; |
601 | } |
603 | } |
… | |
… | |
626 | } |
628 | } |
627 | } |
629 | } |
628 | } |
630 | } |
629 | |
631 | |
630 | package Jeweler::Object; |
632 | package Jeweler::Object; |
631 | use strict; |
633 | |
|
|
634 | use common::sense; |
632 | use POSIX; |
635 | use POSIX; |
633 | use List::Util qw/max min sum/; |
636 | use List::Util qw/max min sum/; |
634 | |
637 | |
635 | sub new { |
638 | sub new { |
636 | my ($class, %arg) = @_; |
639 | my ($class, %arg) = @_; |
… | |
… | |
651 | return 1 if $self->{hash}->{resist}->{$resnum}; |
654 | return 1 if $self->{hash}->{resist}->{$resnum}; |
652 | } |
655 | } |
653 | return undef; |
656 | return undef; |
654 | } |
657 | } |
655 | |
658 | |
|
|
659 | sub lvl2exp { |
|
|
660 | my $lvl = shift; |
|
|
661 | (cf::level_to_min_exp ($lvl) - cf::level_to_min_exp ($lvl - 1)) |
|
|
662 | / (20 + max ($lvl - 1, 0)) # 20 + level times making such a ring |
|
|
663 | # should get you to the rings level at least. |
|
|
664 | } |
|
|
665 | |
656 | sub projected_exp { |
666 | sub projected_exp { |
657 | my ($self, $input_level) = @_; |
667 | my ($self, $input_level) = @_; |
658 | |
668 | |
659 | my $lvl = max ($self->power_to_level, 1); |
669 | my $lvl = max ($self->power_to_level, 1); |
660 | my $exp = |
670 | my $exp = lvl2exp ($lvl); |
661 | (cf::level_to_min_exp ($lvl) - cf::level_to_min_exp ($lvl - 1)) |
|
|
662 | / (10 + max ($lvl - 1, 0)); # 10 + level times making such a ring |
|
|
663 | # should get you to the rings level at least. |
|
|
664 | |
671 | |
665 | if (defined $input_level) { |
672 | if (defined $input_level) { # in case we merge rings: |
666 | my $subexp = |
673 | my $subexp = lvl2exp ($input_level); |
667 | (cf::level_to_min_exp ($input_level) |
|
|
668 | - cf::level_to_min_exp ($input_level - 1)) |
|
|
669 | / (10 + max ($input_level - 1, 0)); # see above for comment |
|
|
670 | |
|
|
671 | $exp -= $subexp; |
674 | $exp -= $subexp; |
672 | $exp = max ($exp, 0); |
675 | $exp = max ($exp, 0); |
673 | |
676 | |
674 | } else { |
677 | } else { |
675 | # the experience bonus here is to make level 1 rings give you at least |
678 | # the experience bonus here is to make level 1 rings give you at least |
… | |
… | |
845 | $obj->{arch} = $thing->arch->archname; |
848 | $obj->{arch} = $thing->arch->archname; |
846 | $obj->{face} = $thing->face; |
849 | $obj->{face} = $thing->face; |
847 | |
850 | |
848 | $obj->{value} = $thing->value; |
851 | $obj->{value} = $thing->value; |
849 | |
852 | |
|
|
853 | $obj->{is_ring} = ($thing->type == cf::RING); |
|
|
854 | |
850 | $self->{hash} = $obj |
855 | $self->{hash} = $obj |
851 | } |
856 | } |
852 | |
857 | |
853 | sub to_object { |
858 | sub to_object { |
854 | my ($self) = @_; |
859 | my ($self) = @_; |
855 | |
860 | |
856 | my $obj = cf::object::new $self->{hash}->{arch}; |
861 | my $obj = cf::object::new $self->{hash}->{arch}; |
857 | |
862 | |
858 | $obj->item_power (floor ($self->power_to_level / 3)); # there have to be strings attached! |
863 | $obj->item_power (floor ($self->power_to_level / 5)); # there have to be strings attached! |
859 | |
864 | |
860 | $obj->face ($self->{hash}{face}); |
865 | $obj->face ($self->{hash}{face}); |
861 | |
866 | |
862 | my $stats = $obj->stats; |
867 | my $stats = $obj->stats; |
863 | |
868 | |
… | |
… | |
987 | sub power_to_level { |
992 | sub power_to_level { |
988 | my ($self, $lvldescr) = @_; |
993 | my ($self, $lvldescr) = @_; |
989 | |
994 | |
990 | my $max_imprs = Jeweler::getcfg (maximprovements => 'improvements'); |
995 | my $max_imprs = Jeweler::getcfg (maximprovements => 'improvements'); |
991 | my $max_impr_lvl = Jeweler::getcfg (maxlevels => 'improve_level'); |
996 | my $max_impr_lvl = Jeweler::getcfg (maxlevels => 'improve_level'); |
|
|
997 | my $ring_offs = Jeweler::getcfg (maxlevels => 'ring_offset'); |
992 | |
998 | |
993 | my ($stat_lvl, $stat_imprs) = $self->stat_level; |
999 | my ($stat_lvl, $stat_imprs) = $self->stat_level; |
994 | my ($resist_lvl, $res_imprs) = $self->resist_level; |
1000 | my ($resist_lvl, $res_imprs) = $self->resist_level; |
995 | my ($spec_lvl, $spec_imprs) = $self->special_level; |
1001 | my ($spec_lvl, $spec_imprs) = $self->special_level; |
996 | |
1002 | |
997 | my $impr_sum = $stat_imprs + $res_imprs + $spec_imprs; |
1003 | my $impr_sum = $stat_imprs + $res_imprs + $spec_imprs; |
998 | |
1004 | |
999 | my $impr_lvl = ceil (($max_impr_lvl / ($max_imprs + 1)) * ($impr_sum - 1)); # 1 improvemnt bonus |
1005 | my $impr_lvl = |
|
|
1006 | ceil (($max_impr_lvl / ($max_imprs + 1)) |
|
|
1007 | * ($impr_sum - 1)); # 1 improvemnt bonus |
1000 | |
1008 | |
1001 | my $levl = int max ($stat_lvl, $resist_lvl, $impr_lvl, $spec_lvl, 0); |
1009 | my $levl = int max ($stat_lvl, $resist_lvl, $impr_lvl, $spec_lvl, 0); |
|
|
1010 | |
|
|
1011 | if ($self->{hash}->{is_ring}) { |
|
|
1012 | $levl += $ring_offs; |
|
|
1013 | } |
|
|
1014 | |
|
|
1015 | $levl = min ($levl, cf::settings->max_level); |
1002 | |
1016 | |
1003 | if ($lvldescr) { |
1017 | if ($lvldescr) { |
1004 | $$lvldescr = |
1018 | $$lvldescr = |
1005 | sprintf "%3d: %s\n", $levl, |
1019 | sprintf "%3d: %s\n", $levl, |
1006 | "stat: $stat_lvl, resist: $resist_lvl, improve: $impr_lvl, " |
1020 | "stat: $stat_lvl, resist: $resist_lvl, improve: $impr_lvl, " |
… | |
… | |
1097 | $cost->{gem} += ceil $sumvalue * $stat_split->[4] / max 1, $diarch->value; |
1111 | $cost->{gem} += ceil $sumvalue * $stat_split->[4] / max 1, $diarch->value; |
1098 | } |
1112 | } |
1099 | |
1113 | |
1100 | package Jeweler::Util; |
1114 | package Jeweler::Util; |
1101 | |
1115 | |
1102 | use strict; |
1116 | use common::sense; |
1103 | |
1117 | |
1104 | =head2 Util |
1118 | =head2 Util |
1105 | |
1119 | |
1106 | Some utility functions for the Jeweler skill. |
1120 | Some utility functions for the Jeweler skill. |
1107 | |
1121 | |
… | |
… | |
1114 | |
1128 | |
1115 | =cut |
1129 | =cut |
1116 | |
1130 | |
1117 | sub remove { |
1131 | sub remove { |
1118 | my ($obj, $nrof) = @_; |
1132 | my ($obj, $nrof) = @_; |
1119 | |
1133 | |
1120 | my $c = $obj->nrof || 1; |
1134 | my $c = $obj->number_of; |
1121 | my $r = $c > $nrof ? 0 : $nrof - $c; |
1135 | my $r = $c > $nrof ? 0 : $nrof - $c; |
1122 | $obj->decrease (defined ($nrof) ? $nrof : ($obj->nrof || 1)); |
1136 | $obj->decrease (defined ($nrof) ? $nrof : ($obj->nrof || 1)); |
1123 | |
1137 | |
1124 | $r |
1138 | $r |
1125 | } |
1139 | } |