--- deliantra/server/ext/jeweler.ext 2006/12/15 19:29:18 1.1 +++ deliantra/server/ext/jeweler.ext 2010/04/27 17:08:09 1.22 @@ -1,9 +1,9 @@ #! perl -use Data::Dumper; +use strict; + use Jeweler; use List::Util qw/max min sum/; -use strict; sub ingred_alias { my ($ing) = @_; @@ -16,6 +16,7 @@ dex => 'dexterity', con => 'constitution', str => 'strength', + gem => 'diamond', ); if ($ing =~ m/resist_(\S+)/) { @@ -30,6 +31,9 @@ my $a = $aliases{lc $1} || $1; "something for the ". lc ($a). "' special"; + } elsif ($aliases{$ing}) { + $aliases{$ing} + } else { $ing } @@ -40,28 +44,36 @@ sub merge { my ($chdl, $sk, $pl, $do_analyze) = @_; - my $ingred = $chdl->extract_jeweler_ingredients; + my $ingred = get_ingred ($pl, $chdl) || return; + my @ring = $ingred->get_ring; my @rings = map { Jeweler::Object->new (object => $_) } @ring; @rings >= 2 - or return $pl->reply (undef, "You slap yourself, you forgot to put at least 2 jewels in!"); + or return $pl->message ("You slap yourself, you forgot to put at least 2 jewels in!"); + + my $input_level = 0; + my $value; + for (@rings) { + $input_level = max ($_->power_to_level, $input_level); + $value += $_->{hash}->{value}; + } my $ring = shift @rings; $ring->improve_by_ring (@rings); if ($do_analyze) { - $pl->reply (undef, "You want to make a " . $ring->to_string . ": " . $ring->analyze ($sk, $pl)); + $pl->message ("You want to make a " . $ring->to_string . ": " . $ring->analyze ($sk, $pl, $input_level)); $ring->wiz_analyze ($pl) if $pl->flag (cf::FLAG_WIZ); return; } - make_ring ($chdl, $ingred, $ring, $sk, $pl); + make_ring ($chdl, $ingred, $ring, $value, $sk, $pl, $input_level); } sub make_ring { - my ($chdl, $ingred, $ring, $sk, $pl) = @_; + my ($chdl, $ingred, $ring, $value, $sk, $pl, $input_level) = @_; if (!$pl->flag (cf::FLAG_WIZ)) { $ingred->remove ('rings'); @@ -70,20 +82,87 @@ my $ch = $ring->get_chance_perc ($sk); my $succ = 0; - my $r = cf::random_roll (0, 100, $pl, cf::PREFER_HIGH); + my $r = cf::random_roll (0, 100, $pl, cf::PREFER_LOW); + + my $make_status; + my $exp; + if ($r <= $ch or $pl->flag (cf::FLAG_WIZ)) { - my $lvl = max ($ring->power_to_level, 1); - my $exp = (cf::level_to_min_exp ($lvl) - cf::level_to_min_exp ($lvl - 1)) / 100; - $pl->change_exp ($exp, "jeweler", cf::SK_EXP_SKILL_ONLY); - $pl->message ("You succeed and get $exp experience."); + $exp = $ring->projected_exp ($input_level); + + $pl->change_exp ($exp, "jeweler"); + $pl->message ( + "You succeed and get " . int ($exp) . " experience points."); + $make_status = "succeeded"; + + $ring->set_value ($value); + } else { $pl->message ("You fail!"); $ring->negate; + $make_status = "fail"; + $exp = 0; } - $chdl->put ($ring->to_object); + + my $ring_ob = $ring->to_object; + + { # some audit info calculation + my $sklvl = cf::exp_to_level ($sk->stats->exp); + + my $make_info = sprintf + "JEWELER AUDIT: '%s' made '%s' (%s) (sk lvl %d, ring lvl %d, got %d exp): %s", + $pl->name, $ring->to_string, $ring_ob->uuid, $sklvl, + $ring->power_to_level, $exp, $make_status; + + warn "$make_info\n" if $make_status eq 'succeeded'; + } + + $chdl->put ($ring_ob); } -cf::attach_to_type cf::SKILL, cf::SK_JEWELER, +sub get_ingred { + my ($pl, $chdl) = @_; + my $ingred = eval { $chdl->extract_jeweler_ingredients }; + if ($@ =~ /cursed/) { + $pl->message ("There are cursed items in the workbench, take them out before you do anything."). + return + } elsif ($@ =~ /unidentified/) { + $pl->message ("There are unidentified items in the workbench, identify them before you do anything."). + return + } elsif ($@) { + warn "error in jeweler ingredient extraction: $@"; + return; + } + $ingred; +} + +cf::object::attachment check_ring_drop_on => + on_drop_on => sub { + my ($self, $obj, $who) = @_; + my $cfg = $self->{check_ring_drop_on}; + if ($obj->type == cf::RING + && !$obj->flag (cf::FLAG_CURSED) + && !$obj->flag (cf::FLAG_DAMNED) + ) { + my $ringo = Jeweler::Object->new (object => $obj); + for (grep { /^resist_/ } keys %$cfg) { + if (/^resist_(\S+)$/) { + if ($ringo->has_resist ($1)) { + $self->map->trigger ( + $cfg->{connection}, + $cfg->{state} + ); + $obj->decrease (1); + cf::override; + } + } + } + } + }; + +cf::object->attach ( + type => cf::SKILL, + subtype => cf::SK_JEWELER, on_use_skill => sub { my ($sk, $ob, $part, $dir, $msg) = @_; my $pl = $ob; @@ -94,7 +173,6 @@ my $rv = 1; eval { - Jeweler::read_config ($ENV{CROSSFIRE_LIBDIR} . '/jeweler.yaml'); $DEBUG = 1; my $player = $ob->contr; @@ -112,14 +190,16 @@ $pl->message ("You can make: " . (join ', ', keys %{Jeweler::getcfg ('conversions') || {}})); } elsif ($msg =~ m/^\s*make\s+(\S+)\s*$/i) { - my $ingred = $chdl->extract_jeweler_ingredients; + my $ingred = get_ingred ($pl, $chdl) || return; unless ($Jeweler::CFG->{conversions}->{lc $1}) { $pl->message ("You don't know how to make '$1', is does such a thing even exist?"); return } - Jeweler::simple_converter ($player, $ingred, $chdl, $1); + Jeweler::simple_converter ( + $player, $ingred, $chdl, $1, + cf::exp_to_level ($sk->stats->exp)); } elsif ($msg =~ m/^\s*merge\s*analy[sz]e\s*$/i) { merge ($chdl, $sk, $pl, 1); @@ -128,34 +208,41 @@ merge ($chdl, $sk, $pl, 0); } else { - my $ingred = $chdl->extract_jeweler_ingredients; + my $ingred = get_ingred ($pl, $chdl) || return; + my $plan = $ingred->get_plan; if ($plan) { my @ring = $ingred->get_ring; - if ((@ring > 1) || ($ring[0]->nrof > 1)) { - # actually the algorithm cant handle more than one improvement at a time - $pl->message ("You can't manage to improve more than one thing at a time!"); - return; - - } elsif (@ring < 1) { + if (!@ring) { # actually the algorithm cant $pl->message ("You slap yourself, you forgot the jewelery!"); return; + } elsif ((@ring > 1) || (grep { $_->nrof > 1 } @ring)) { + # actually the algorithm cant handle more than one improvement at a time + $pl->message ("You can't manage to improve more than one thing at a time!"); + return; } else { my $ringo = Jeweler::Object->new (object => $ring[0]); my $iring = $ingred->improve_ring_by_plan ($plan, $ringo); - my $c1 = $ringo->calc_costs; - my $c2 = $iring->calc_costs; + my $c1 = $ringo->calc_costs; + my $c2 = $iring->calc_costs; + my $value = $iring->calc_value_from_cost ($c2); + + if ((not defined $c1) || (not defined $c2)) { + $pl->message ("The jewel has or will become a resistancy above 99%,\n" + ."that is completly impossible to make!"); + return; + } my %keys; my %cdiff; for (keys %$c1, keys %$c2) { $keys{$_} = 1 } - for (keys %keys) { $cdiff{$_} = $c2->{$_} - $c1->{$_} } + for (keys %keys) { $cdiff{$_} = $c2->{$_} - $c1->{$_}; } - unless (grep { $_ > 0 } values %cdiff) { + unless ($iring->is_better_than ($ringo)) { $pl->message ("This plan doesn't improve anything, you find yourself puzzled about what you missed..."); return; } @@ -176,7 +263,7 @@ if (!$pl->flag (cf::FLAG_WIZ)) { $ingred->check_costs (\%cdiff, 1); } - make_ring ($chdl, $ingred, $iring, $sk, $pl); + make_ring ($chdl, $ingred, $iring, $value, $sk, $pl); } } } else { @@ -186,5 +273,7 @@ }; $@ and warn "ERROR: $@\n"; } -; +); + +Jeweler::read_config "res/jeweler.yaml";