1 | #! perl |
1 | #! perl |
2 | #CONVERSION: NONE |
2 | #CONVERSION: NONE |
3 | |
|
|
4 | use POSIX; |
|
|
5 | use Data::Dumper; |
3 | use Data::Dumper; |
|
|
4 | use Jeweler; |
6 | use List::Util qw/max min sum/; |
5 | use List::Util qw/max min sum/; |
7 | use Jeweler; |
|
|
8 | use strict; |
6 | use strict; |
9 | |
7 | |
10 | my $DEBUG = 1; |
8 | sub ingred_alias { |
11 | my $CFG; |
9 | my ($ing) = @_; |
12 | |
10 | |
13 | # this is a simple quad polynom, it takes it's factors from |
11 | my %aliases = ( |
14 | # the configuration |
12 | pow => 'power', |
15 | sub fx { |
13 | cha => 'charisma', |
16 | my ($x, $setting) = @_; |
14 | wis => 'wisdom', |
17 | my $facts = getcfg (functions => $setting); |
15 | int => 'intelligence', |
18 | return $facts->[0] * ($x ** 2) + $facts->[1] * $x + $facts->[2]; |
16 | dex => 'dexterity', |
|
|
17 | con => 'constitution', |
|
|
18 | str => 'strength', |
|
|
19 | ); |
|
|
20 | |
|
|
21 | if ($ing =~ m/resist_(\S+)/) { |
|
|
22 | my $a = $aliases{lc $1} || $1; |
|
|
23 | "something for '". lc ($a). "' resistance"; |
|
|
24 | |
|
|
25 | } elsif ($ing =~ m/stat_(\S+)/) { |
|
|
26 | my $a = $aliases{lc $1} || $1; |
|
|
27 | "something for the ". lc ($a). " stat"; |
|
|
28 | |
|
|
29 | } elsif ($ing =~ m/spec_(\S+)/) { |
|
|
30 | my $a = $aliases{lc $1} || $1; |
|
|
31 | "something for the ". lc ($a). "' special"; |
|
|
32 | |
|
|
33 | } else { |
|
|
34 | $ing |
|
|
35 | } |
19 | } |
36 | } |
20 | |
37 | |
21 | # makes a template arch (for example to get the value) |
38 | my $DEBUG = 1; |
22 | sub get_arch { |
|
|
23 | my ($outarch) = @_; |
|
|
24 | unless ($CFG->{arch}->{$outarch}) { |
|
|
25 | $CFG->{arch}->{$outarch} = cf::object::new $outarch; |
|
|
26 | |
39 | |
27 | unless ($CFG->{arch}->{$outarch}) { |
40 | sub merge { |
28 | warn "ERROR: Couldn't make $outarch in conversion for $outarch!"; |
41 | my ($chdl, $sk, $pl, $do_analyze) = @_; |
29 | return; |
|
|
30 | } |
|
|
31 | } |
|
|
32 | $CFG->{arch}->{$outarch} |
|
|
33 | } |
|
|
34 | |
42 | |
35 | sub calc_costs { |
43 | my $ingred = $chdl->extract_jeweler_ingredients; |
36 | my ($ring) = @_; |
44 | my @ring = $ingred->get_ring; |
|
|
45 | my @rings = map { Jeweler::Object->new (object => $_) } @ring; |
37 | |
46 | |
38 | my $costs = {}; |
47 | if (@rings < 2) { |
39 | |
48 | $pl->message ("You slap yourself, you forgot to put at least 2 jeweles in!"); |
40 | for my $resnam (keys %{$ring->{resist} || {}}) { |
|
|
41 | |
|
|
42 | my $res = $ring->{resist}->{$resnam}; |
|
|
43 | |
|
|
44 | next unless $res > 0; |
|
|
45 | |
|
|
46 | $costs->{"food_$resnam"} += $res; |
|
|
47 | $costs->{"resist_" . $Jeweler::RESMAP{$resnam} . "_potion"}++; |
|
|
48 | |
|
|
49 | my $diamonds; |
|
|
50 | if (grep { $resnam eq $_ } @Jeweler::EFFECT_RESISTS) { |
|
|
51 | $diamonds += fx ($res, 'effect_resist_diamonds'); |
|
|
52 | } else { |
|
|
53 | $diamonds += fx ($res, 'attack_resist_diamonds'); |
|
|
54 | } |
|
|
55 | $costs->{diamonds} += $diamonds; |
|
|
56 | } |
|
|
57 | |
|
|
58 | $costs = calc_stat_costs ($ring->{stat}, $costs); |
|
|
59 | $costs = calc_special_costs ($ring->{spec}, $costs); |
|
|
60 | |
|
|
61 | warn |
|
|
62 | sprintf "JEWEL ANALYSE: %40s: %s" , |
|
|
63 | $ring->{name}, |
|
|
64 | join (', ', map { "$_: " . sprintf "%.2f", $costs->{$_} } keys %$costs); |
|
|
65 | return $costs; |
|
|
66 | } |
|
|
67 | |
|
|
68 | sub read_config { |
|
|
69 | my ($filename) = @_; |
|
|
70 | |
|
|
71 | # open my $fh, $filename |
|
|
72 | # or die "Couldn't open '$filename': $!"; |
|
|
73 | |
|
|
74 | my $cfg = {}; #LoadFile $filename; |
|
|
75 | |
|
|
76 | # my $section = 'main'; |
|
|
77 | # |
|
|
78 | # my $cont = join '', <$fh>; |
|
|
79 | # |
|
|
80 | # for (<$fh>) { |
|
|
81 | # s/#.*$//; |
|
|
82 | # |
|
|
83 | # if (m/^\[([^\]]+)\]/) { |
|
|
84 | # $section = $1; |
|
|
85 | # |
|
|
86 | # } elsif (m/^\s*(\S+)\s*=\s*(.*?)\s*$/) { |
|
|
87 | # my ($k, $v) = ($1, $2); |
|
|
88 | # |
|
|
89 | # my @v = split /\s*,\s*/, $v; |
|
|
90 | # |
|
|
91 | # if (@v > 1) { |
|
|
92 | # $v = [ @v ]; |
|
|
93 | # } |
|
|
94 | # |
|
|
95 | # $cfg->{$section}->{$k} = $v; |
|
|
96 | # } |
|
|
97 | # } |
|
|
98 | |
|
|
99 | return $cfg; |
|
|
100 | } |
|
|
101 | |
|
|
102 | sub getcfg { |
|
|
103 | my ($sect, $key) = @_; |
|
|
104 | my $cfg = $CFG->{$sect}->{$key} |
|
|
105 | or die "Couldn't find $sect/$key in configuration!"; |
|
|
106 | |
|
|
107 | $cfg |
|
|
108 | } |
|
|
109 | |
|
|
110 | sub ring_or_ammy_to_hash { |
|
|
111 | my ($thing) = @_; |
|
|
112 | |
|
|
113 | my $obj = {}; |
|
|
114 | |
|
|
115 | for (@Jeweler::RESISTS) { |
|
|
116 | $obj->{resist}->{$_} = $thing->get_resistance ($_); |
|
|
117 | } |
|
|
118 | |
|
|
119 | my $stats = $thing->stats; |
|
|
120 | |
|
|
121 | for (qw/Str Dex Con Wis Cha Int Pow/) { |
|
|
122 | $obj->{stat}->{$_} = $stats->$_; |
|
|
123 | } |
|
|
124 | |
|
|
125 | $obj->{spec}->{regen} = $thing->hp; |
|
|
126 | $obj->{spec}->{magic} = $thing->sp; |
|
|
127 | $obj->{spec}->{wc} = $thing->wc; |
|
|
128 | $obj->{spec}->{dam} = $thing->dam; |
|
|
129 | $obj->{spec}->{ac} = $thing->ac; |
|
|
130 | $obj->{spec}->{speed} = $thing->stats->exp; |
|
|
131 | $obj->{spec}->{suste} = $thing->food; |
|
|
132 | |
|
|
133 | $obj->{name} = $thing->name; |
|
|
134 | |
|
|
135 | $obj |
|
|
136 | } |
|
|
137 | |
|
|
138 | sub split_diamonds { |
|
|
139 | my ($cost, $diamonds, $category) = @_; |
|
|
140 | |
|
|
141 | my $stat_split = getcfg (diamond_split => $category); |
|
|
142 | |
|
|
143 | my $emarch = get_arch ('emerald'); |
|
|
144 | my $saarch = get_arch ('sapphire'); |
|
|
145 | my $pearch = get_arch ('pearl'); |
|
|
146 | my $ruarch = get_arch ('ruby'); |
|
|
147 | my $diarch = get_arch ('gem'); |
|
|
148 | |
|
|
149 | my $sumvalue = $diarch->value * $diamonds; |
|
|
150 | |
|
|
151 | $cost->{emeralds} += ceil (($sumvalue * $stat_split->[0]) / $emarch->{value}); |
|
|
152 | $cost->{sapphires} += ceil (($sumvalue * $stat_split->[1]) / $saarch->{value}); |
|
|
153 | $cost->{pearls} += ceil (($sumvalue * $stat_split->[2]) / $pearch->{value}); |
|
|
154 | $cost->{rubies} += ceil (($sumvalue * $stat_split->[3]) / $ruarch->{value}); |
|
|
155 | $cost->{diamonds} += ceil (($sumvalue * $stat_split->[4]) / $diarch->{value}); |
|
|
156 | |
|
|
157 | return $cost; |
|
|
158 | } |
|
|
159 | |
|
|
160 | sub calc_stat_level { |
|
|
161 | my ($stats) = @_; |
|
|
162 | |
|
|
163 | my $maxlevel = getcfg (maxlevels => 'stat_level'); |
|
|
164 | my $maxstat = getcfg (maximprovements => 'stats'); |
|
|
165 | |
|
|
166 | my $stat_cnt = scalar (grep { $_ > 0 } values %$stats); |
|
|
167 | my $stat_sum = sum (values %$stats); |
|
|
168 | my $level = int (($maxlevel / $maxstat) * $stat_sum); |
|
|
169 | |
|
|
170 | ($level, $stat_cnt) |
|
|
171 | } |
|
|
172 | |
|
|
173 | sub calc_resist_level { |
|
|
174 | my ($resists) = @_; |
|
|
175 | |
|
|
176 | my $att_res_lvl = getcfg (maxlevels => 'resist_level'); |
|
|
177 | my $efc_res_lvl = getcfg (maxlevels => 'effect_resist_level'); |
|
|
178 | my $max_att_res = getcfg (maximprovements => 'attack_resistances'); |
|
|
179 | my $max_efc_res = getcfg (maximprovements => 'effect_resistances'); |
|
|
180 | my $max_ovr_res = getcfg (maximprovements => 'resistances'); |
|
|
181 | |
|
|
182 | my $ressum = 0; |
|
|
183 | my $rescnt = 0; |
|
|
184 | my @reslevels; |
|
|
185 | |
|
|
186 | for my $resnam (keys %$resists) { |
|
|
187 | my $res = $resists->{$resnam}; |
|
|
188 | |
|
|
189 | $rescnt++ |
|
|
190 | if $res > 0; # negative resistancies are not an improvement |
|
|
191 | |
|
|
192 | $ressum += $res; # note: negative resistancies lower the sum |
|
|
193 | |
|
|
194 | next unless $res > 0; |
|
|
195 | |
|
|
196 | my $level = 0; |
|
|
197 | if (grep { $resnam eq $_ } @Jeweler::EFFECT_RESISTS) { |
|
|
198 | $level = ceil (($efc_res_lvl / $max_efc_res) * $res); |
|
|
199 | } else { |
|
|
200 | $level = ceil (($att_res_lvl / $max_att_res) * $res); |
|
|
201 | } |
|
|
202 | push @reslevels, $level; |
|
|
203 | } |
|
|
204 | |
|
|
205 | my $overall_lvl = ($att_res_lvl / $max_ovr_res) * $ressum; |
|
|
206 | |
|
|
207 | (max (@reslevels, $overall_lvl), $rescnt); |
|
|
208 | } |
|
|
209 | |
|
|
210 | sub calc_special_level { |
|
|
211 | my ($specials) = @_; |
|
|
212 | |
|
|
213 | my $max_spc_lvl = getcfg (maxlevels => 'spec_level'); |
|
|
214 | my $max_specials = getcfg (maximprovements => 'specials'); |
|
|
215 | |
|
|
216 | my @speclvls; |
|
|
217 | my $specsum = 0; |
|
|
218 | my $imprs = 0; |
|
|
219 | |
|
|
220 | for my $spcnam (keys %$specials) { |
|
|
221 | my $spc = $specials->{$spcnam}; |
|
|
222 | next unless $spc > 0; |
|
|
223 | |
|
|
224 | $specsum += $spc; |
|
|
225 | $imprs++; |
|
|
226 | |
|
|
227 | my $max_spc = getcfg (maxspecial => $spcnam); |
|
|
228 | |
|
|
229 | my $lvl = ($max_spc_lvl / $max_spc) * $spc; |
|
|
230 | push @speclvls, $lvl; |
|
|
231 | } |
|
|
232 | |
|
|
233 | my $sumlvl = ($max_spc_lvl / $max_specials) * $specsum; |
|
|
234 | |
|
|
235 | (max (@speclvls, $sumlvl), $imprs) |
|
|
236 | } |
|
|
237 | |
|
|
238 | sub calc_stat_costs { |
|
|
239 | my ($stats, $cost) = @_; |
|
|
240 | |
|
|
241 | my $sum = sum grep { $_ > 0 } values %$stats; |
|
|
242 | |
|
|
243 | return $cost unless $sum > 0; |
|
|
244 | |
|
|
245 | $cost->{stat_potions} += fx ($sum, 'stat_potions'); |
|
|
246 | $cost->{diamonds} += fx ($sum, 'stat_diamonds'); |
|
|
247 | |
|
|
248 | $cost |
|
|
249 | } |
|
|
250 | |
|
|
251 | sub calc_special_costs { |
|
|
252 | my ($specials, $cost) = @_; |
|
|
253 | |
|
|
254 | my $sum = sum grep { $_ > 0 } values %$specials; |
|
|
255 | |
|
|
256 | return $cost unless $sum > 0; |
|
|
257 | |
|
|
258 | $cost->{spec_potions} += fx ($sum, 'spec_potions'); |
|
|
259 | $cost->{diamonds} += fx ($sum, 'spec_diamonds'); |
|
|
260 | |
|
|
261 | $cost |
|
|
262 | } |
|
|
263 | |
|
|
264 | # this function calculated the 'level' of an amulet or a ring |
|
|
265 | sub power_to_level { |
|
|
266 | my ($ring) = @_; |
|
|
267 | |
|
|
268 | my $max_imprs = getcfg (maximprovements => 'improvements'); |
|
|
269 | my $max_impr_lvl = getcfg (maxlevels => 'improve_level'); |
|
|
270 | |
|
|
271 | my ($stat_lvl, $stat_imprs) = calc_stat_level ($ring->{stat} || {}); |
|
|
272 | my ($resist_lvl, $res_imprs) = calc_resist_level ($ring->{resist} || {}); |
|
|
273 | my ($spec_lvl, $spec_imprs) = calc_special_level ($ring->{spec} || {}); |
|
|
274 | |
|
|
275 | my $impr_lvl = ceil (($max_impr_lvl / ($max_imprs + 1)) * ($stat_imprs + $res_imprs + $spec_imprs - 1)); |
|
|
276 | |
|
|
277 | my $levl = int max ($stat_lvl, $resist_lvl, $impr_lvl, $spec_lvl, 0); |
|
|
278 | |
|
|
279 | my $cost = calc_costs ($ring); |
|
|
280 | warn sprintf "%3d: %50s: %s\n", $levl, $ring->{name}, "stat: $stat_lvl, resist: $resist_lvl, improve: $impr_lvl, spec: $spec_lvl (num impr $stat_imprs + $res_imprs + $spec_imprs - 1)"; |
|
|
281 | # warn sprintf " %s\n", join (',', map { sprintf "$_: %5d", $cost->{$_} } keys %$cost); |
|
|
282 | |
|
|
283 | $levl |
|
|
284 | } |
|
|
285 | |
|
|
286 | # this function converts metals/minerals into a raw ring (of adornment) |
|
|
287 | sub simple_converter { |
|
|
288 | my ($pl, $ingred, $chdl, $conv) = @_; |
|
|
289 | |
|
|
290 | $conv = lc $conv; |
|
|
291 | my $cnvs = $CFG->{conversions}; |
|
|
292 | |
|
|
293 | return unless $cnvs->{$conv}; |
|
|
294 | |
|
|
295 | my %ingred_groups; |
|
|
296 | |
|
|
297 | my @conv_cfg = @{$cnvs->{$conv}}; |
|
|
298 | my $outarch = $conv; |
|
|
299 | my ($ingr_grp, $outarchvalfact, $srcarchname, $xp_gain) = @conv_cfg; |
|
|
300 | |
|
|
301 | unless (@conv_cfg <= 4) { |
|
|
302 | warn "ERROR: Conversion for '$outarch' has only " . (@conv_cfg) . " arguments!"; |
|
|
303 | return; |
49 | return; |
304 | } |
50 | } |
305 | |
51 | |
306 | unless ($xp_gain > 0) { |
52 | my $ring = shift @rings; |
307 | warn "WARNING: xp gain isn't > 0 in convesion '$outarch'\n"; |
53 | $ring->improve_by_ring (@rings); |
|
|
54 | |
|
|
55 | if ($do_analyze) { |
|
|
56 | $pl->message ("You want to make a " . $ring->to_string . ": " . $ring->analyze ($sk, $pl)); |
|
|
57 | if ($pl->flag (cf::FLAG_WIZ)) { |
|
|
58 | $ring->wiz_analyze ($pl); |
|
|
59 | } |
308 | return; |
60 | return; |
309 | } |
61 | } |
310 | |
62 | |
311 | unless ($outarchvalfact) { |
63 | make_ring ($chdl, $ingred, $ring, $sk, $pl); |
312 | warn "ERROR: source-arch-value-multiplier == 0 in convesion '$outarch'\n"; |
64 | } |
313 | return; |
65 | |
|
|
66 | sub make_ring { |
|
|
67 | my ($chdl, $ingred, $ring, $sk, $pl) = @_; |
|
|
68 | |
|
|
69 | if (!$pl->flag (cf::FLAG_WIZ)) { |
|
|
70 | $ingred->remove ('rings'); |
|
|
71 | $ingred->remove ('ammys'); |
314 | } |
72 | } |
315 | |
73 | |
316 | unless ($outarchvalfact >= 1) { |
74 | my $ch = $ring->get_chance_perc ($sk); |
317 | warn "WARNING: source-arch-value-multiplier < 1 in convesion '$outarch', results in more valuable output!\n"; |
75 | my $succ = 0; |
|
|
76 | my $r = cf::random_roll (0, 100, $pl, cf::PREFER_HIGH); |
|
|
77 | if ($r <= $ch or $pl->flag (cf::FLAG_WIZ)) { |
|
|
78 | my $lvl = max ($ring->power_to_level, 1); |
|
|
79 | my $exp = (cf::level_to_min_exp ($lvl) - cf::level_to_min_exp ($lvl - 1)) / 100; |
|
|
80 | $pl->change_exp ($exp, "jeweler", cf::SK_EXP_SKILL_ONLY); |
|
|
81 | $pl->message ("You succeed and get $exp experience."); |
|
|
82 | } else { |
|
|
83 | $pl->message ("You fail!"); |
|
|
84 | $ring->negate; |
318 | } |
85 | } |
319 | |
86 | $chdl->put ($ring->to_object); |
320 | my $archvalsum = $ingred->value ($cnvs->{$outarch}->[0], $cnvs->{$outarch}->[2]); |
|
|
321 | $ingred->remove ($cnvs->{$outarch}->[0], $cnvs->{$outarch}->[2]); |
|
|
322 | |
|
|
323 | my $outarchval = get_arch ($outarch)->value; |
|
|
324 | |
|
|
325 | my $nrof = int ($archvalsum / (($outarchval || 1000) * $outarchvalfact)); |
|
|
326 | if ($nrof) { |
|
|
327 | # XXX: yes, i know what i'm doing here, i don't set nrof, but it didn't work somehow (pls. chek sometimes) |
|
|
328 | $chdl->put (cf::object::new $outarch) for 1..$nrof; |
|
|
329 | |
|
|
330 | my $xp_sum = ($xp_gain * $nrof); |
|
|
331 | |
|
|
332 | if ($xp_sum) { |
|
|
333 | $pl->ob->message ("You got $xp_sum xp by making $nrof ${outarch}s"); |
|
|
334 | $pl->ob->change_exp ($xp_sum, "jeweler", cf::SK_EXP_ADD_SKILL); |
|
|
335 | } |
|
|
336 | } |
|
|
337 | } |
87 | } |
338 | |
88 | |
|
|
89 | cf::attach_to_type cf::SKILL, cf::SK_JEWELER, |
|
|
90 | on_use_skill => sub { |
|
|
91 | my ($sk, $ob, $part, $dir, $msg) = @_; |
|
|
92 | my $pl = $ob; |
|
|
93 | warn ($pl->name . " uses jeweler skill [$msg]!\n"); |
339 | |
94 | |
|
|
95 | my $skobj = $sk; |
340 | |
96 | |
341 | sub put_ingred_to_bench { |
97 | my $chdl = new Jeweler::CauldronHandler; |
342 | my ($ingred, $bench) = @_; |
|
|
343 | |
98 | |
344 | for my $ik (keys %$ingred) { |
99 | my $rv = 1; |
345 | for (@{$ingred->{$ik} || []}) { |
100 | eval { |
346 | $_->insert_ob_in_ob ($bench); |
101 | Jeweler::read_config ($ENV{CROSSFIRE_LIBDIR} . '/jeweler.yaml'); |
347 | } |
102 | $DEBUG = 1; |
348 | } |
|
|
349 | } |
|
|
350 | |
103 | |
351 | my %lvl_diff_chances = ( |
104 | my $player = $ob->contr; |
352 | +5 => 100, |
|
|
353 | +4 => 95, |
|
|
354 | +3 => 85, |
|
|
355 | +2 => 75, |
|
|
356 | +1 => 65, |
|
|
357 | 0 => 50, |
|
|
358 | -1 => 45, |
|
|
359 | -2 => 35, |
|
|
360 | -3 => 25, |
|
|
361 | -4 => 10, |
|
|
362 | -5 => 0 |
|
|
363 | ); |
|
|
364 | |
105 | |
365 | my %lvl_diff_msg = ( |
106 | unless ($chdl->find_cauldron ('jeweler_bench', $ob->map->at ($ob->x, $ob->y))) { |
366 | -5 => '%s is way above your skill', |
107 | return; |
367 | -4 => 'The chance to make %s is very low', |
108 | } |
368 | -3 => 'You hava a slight chance to make %s', |
|
|
369 | -2 => 'There is a low chance you finish %s', |
|
|
370 | -1 => 'You could make %s with a chance of nearly 50:50', |
|
|
371 | 0 => 'The chances to fininsh %s is 50:50', |
|
|
372 | 1 => 'To make %s your chance is slightly above 50:50', |
|
|
373 | 2 => 'You could make with a good chance %s if you concentrate a lot', |
|
|
374 | 3 => 'The chance you finish %s with some efford is high', |
|
|
375 | 4 => 'You are nearly confident to finish %s', |
|
|
376 | 5 => 'There is no chance you could fail to make %s', |
|
|
377 | ); |
|
|
378 | |
109 | |
379 | sub level_diff_to_str { |
110 | cf::override; |
380 | my ($delta) = @_; |
|
|
381 | $delta = -5 if $delta < -5; |
|
|
382 | $delta = 5 if $delta > 5; |
|
|
383 | return $lvl_diff_msg{$delta} |
|
|
384 | } |
|
|
385 | |
111 | |
386 | sub level_diff_to_chance_perc { |
112 | if ($msg =~ m/^\s*analy[sz]e\s*$/i) { |
387 | my ($delta) = @_; |
113 | Jeweler::analyze ($sk, $chdl, $pl); |
388 | $delta = -5 if $delta < -5; |
|
|
389 | $delta = 5 if $delta > 5; |
|
|
390 | return $lvl_diff_chances{$delta} |
|
|
391 | } |
|
|
392 | |
114 | |
393 | sub grep_for_match { |
115 | } elsif ($msg =~ m/^\s*make\s*$/i) { |
394 | my ($thing, @matchar) = @_; |
116 | $pl->message ("You can make: " . (join ', ', keys %{Jeweler::getcfg ('conversions') || {}})); |
395 | |
117 | |
396 | my $i = 0; |
118 | } elsif ($msg =~ m/^\s*make\s+(\S+)\s*$/i) { |
397 | for my $match (@matchar) { |
119 | my $ingred = $chdl->extract_jeweler_ingredients; |
398 | if ($match =~ m/^\s*$/) { |
|
|
399 | $i++; |
|
|
400 | next; |
|
|
401 | } |
|
|
402 | |
120 | |
403 | if ($i % 3 == 0) { |
121 | unless ($Jeweler::CFG->{conversions}->{lc $1}) { |
404 | # warn ":FE1:" . $thing->name . ": $match\n"; |
122 | $pl->message ("You don't know how to make '$1', is does such a thing even exist?"); |
405 | $thing->name eq $match |
|
|
406 | and return 1; |
123 | return |
407 | } elsif ($i % 3 == 1) { |
124 | } |
408 | # warn ":FE2:" . $thing->title . ": $match\n"; |
|
|
409 | $thing->title eq $match |
|
|
410 | and return 1; |
|
|
411 | } else { # $i % 3 == 2 |
|
|
412 | # warn ":FE3:" . $thing->archetype->name . ": $match\n"; |
|
|
413 | $thing->archetype->name eq $match |
|
|
414 | and return 1; |
|
|
415 | } |
|
|
416 | $i++; |
|
|
417 | } |
|
|
418 | return 0; |
|
|
419 | } |
|
|
420 | |
125 | |
421 | sub get_plan { |
126 | Jeweler::simple_converter ($player, $ingred, $chdl, $1); |
422 | my ($ingred) = @_; |
|
|
423 | |
127 | |
424 | for my $pot (@{$ingred->{potions}}) { |
128 | } elsif ($msg =~ m/^\s*merge\s*analy[sz]e\s*$/i) { |
425 | for my $plan (keys %{$CFG->{plans}}) { |
129 | merge ($chdl, $sk, $pl, 1); |
426 | my $plg = $CFG->{plans}->{$plan}; |
130 | |
427 | my @plga = (); |
131 | } elsif ($msg =~ m/^\s*merge\s*$/i) { |
428 | unless (ref $plg eq 'ARRAY') { |
132 | merge ($chdl, $sk, $pl, 0); |
429 | push @plga, $plg; |
133 | |
430 | } else { |
134 | } else { |
431 | @plga = @$plg; |
135 | my $ingred = $chdl->extract_jeweler_ingredients; |
432 | } |
136 | my $plan = $ingred->get_plan; |
433 | next unless @plga > 0; |
|
|
434 | if (grep_for_match ($pot, @plga)) { |
|
|
435 | warn "MATCHED: $plan: @plga\n"; |
|
|
436 | return $plan; |
|
|
437 | } |
|
|
438 | } |
|
|
439 | } |
|
|
440 | } |
|
|
441 | |
137 | |
442 | sub get_ring { |
138 | if ($plan) { |
443 | my ($ingred) = @_; |
139 | my @ring = $ingred->get_ring; |
444 | return @{$ingred->{rings} || []}; |
|
|
445 | } |
|
|
446 | |
140 | |
447 | sub get_improv_amount { |
141 | if ((@ring > 1) || ($ring[0]->nrof > 1)) { |
448 | my ($plan, $ingred) = @_; |
142 | # actually the algorithm cant handle more than one improvement at a time |
|
|
143 | $pl->message ("You can't manage to improve more than one thing at a time!"); |
|
|
144 | return; |
449 | |
145 | |
450 | if ($plan =~ m/^stat_(\S+)$/) { |
146 | } elsif (@ring < 1) { |
451 | my $plingred = getcfg (plan_ingred => $plan) |
147 | # actually the algorithm cant |
452 | or die "ingredients for plan '$plan' not defined!"; |
148 | $pl->message ("You slap yourself, you forgot the jewelery!"); |
|
|
149 | return; |
453 | |
150 | |
454 | my $cnt = 0; |
151 | } else { |
455 | for my $pot (@{$ingred->{potions}}) { |
152 | my $ringo = Jeweler::Object->new (object => $ring[0]); |
456 | if (grep_for_match ($pot, @$plingred)) { |
153 | my $iring = $ingred->improve_ring_by_plan ($plan, $ringo); |
457 | $cnt += $pot->nrof; |
154 | my $c1 = $ringo->calc_costs; |
458 | } |
155 | my $c2 = $iring->calc_costs; |
459 | } |
|
|
460 | warn "Found $cnt potions for plan $plan\n"; |
|
|
461 | |
156 | |
462 | my $amount = 0; |
157 | my %keys; |
463 | for my $x (1..10) { |
158 | my %cdiff; |
464 | my $y = fx ($x, 'stat_potions'); |
159 | for (keys %$c1, keys %$c2) { $keys{$_} = 1 } |
465 | warn "TEST: fx($x): $y <= $cnt \n"; |
160 | for (keys %keys) { $cdiff{$_} = $c2->{$_} - $c1->{$_} } |
466 | warn "FE: " . ($y == $cnt) . "\n"; |
|
|
467 | if ($y <= $cnt) { |
|
|
468 | $amount = $x; |
|
|
469 | warn "Found stat increase at: $x\n"; |
|
|
470 | last; |
|
|
471 | } |
|
|
472 | } |
|
|
473 | |
161 | |
474 | return $amount; |
162 | unless (grep { $_ > 0 } values %cdiff) { |
475 | } elsif ($plan =~ m/^spec_(\S+)$/) { |
163 | $pl->message ("This plan doesn't improve anything, you find yourself puzzled about what you missed..."); |
476 | return 0; |
164 | return; |
477 | } elsif ($plan =~ m/^resist_(\S+)$/) { |
165 | } |
478 | return 0; |
|
|
479 | } |
|
|
480 | } |
|
|
481 | |
166 | |
482 | sub get_plan_costs { |
167 | my $remcosts = $ingred->check_costs (\%cdiff); |
483 | my ($plan, $ring, $amount) = @_; |
|
|
484 | |
168 | |
485 | my $pre_costs = calc_costs ($ring); |
169 | if (grep { $_ > 0 } values %$remcosts) { |
|
|
170 | $pl->message ("You want to make a " . $iring->to_string . ": " . $iring->analyze ($sk, $pl)); |
|
|
171 | $pl->message ("You recognize that you are short of: " |
|
|
172 | . (join ", ", |
|
|
173 | map { my $cost = $remcosts->{$_}; $cost . " " . ($cost > 1 ? "times" : "time") . " " . ingred_alias ($_) } |
|
|
174 | grep { $remcosts->{$_} > 0 } keys %$remcosts)); |
486 | |
175 | |
487 | # alter ring spec |
|
|
488 | if ($plan =~ m/^stat_(\S+)$/) { |
|
|
489 | } elsif ($plan =~ m/^spec_(\S+)$/) { |
|
|
490 | } elsif ($plan =~ m/^resist_(\S+)$/) { |
|
|
491 | my ($resid) = map { $Jeweler::RESMAP{$_} } grep { $Jeweler::RESMAP{$_} eq $1 } keys %Jeweler::RESMAP; |
|
|
492 | unless (defined $resid) { |
|
|
493 | die "Couldn't find resistancy for plan: '$plan'\n"; |
|
|
494 | } |
|
|
495 | |
|
|
496 | $ring->{resist}->{$resid} += $amount; |
|
|
497 | } |
|
|
498 | |
|
|
499 | my $post_costs = calc_costs ($ring); |
|
|
500 | |
|
|
501 | my $delta_costs = {}; |
|
|
502 | for (keys %{$post_costs}) { |
|
|
503 | my $cost = $post_costs->{$_} - $pre_costs->{$_}; |
|
|
504 | if ($cost > 0) { |
|
|
505 | warn "DELTA COST: $_ => $cost\n"; |
|
|
506 | $delta_costs->{$_} = $cost; |
|
|
507 | } |
|
|
508 | } |
|
|
509 | return $delta_costs |
|
|
510 | } |
|
|
511 | |
|
|
512 | sub on_player_use_skill { |
|
|
513 | return 0; # disabled not yet ready#d##TODO# |
|
|
514 | my ($ob, $part, $sk, $dir, $msg) = @_; |
|
|
515 | my $pl = $ob; |
|
|
516 | |
|
|
517 | my $skobj = $sk; |
|
|
518 | |
|
|
519 | my $chdl = new Jeweler::CauldronHandler; |
|
|
520 | |
|
|
521 | return 0 unless $sk->subtype == cf::SK_JEWELER; |
|
|
522 | |
|
|
523 | my $rv = 1; |
|
|
524 | eval { |
|
|
525 | $CFG = read_config ($ENV{CROSSFIRE_LIBDIR} . '/jeweler.yaml'); #XXX: This has to become cached properly! |
|
|
526 | $DEBUG ||= $CFG->{main}->{debug}; |
|
|
527 | |
|
|
528 | my $player = $ob->contr;#cf::player::find $ob->name; |
|
|
529 | |
|
|
530 | unless ($chdl->find_cauldron ('jeweler_bench', $ob->map->at ($ob->x, $ob->y))) { |
|
|
531 | $rv = 0; |
|
|
532 | return # return 0 if no cauldron found (default action: identify) |
|
|
533 | } |
|
|
534 | |
|
|
535 | my $ingred = $chdl->extract_jeweler_ingredients; |
|
|
536 | |
|
|
537 | if ($msg =~ m/^\s*analy[sz]e\s*$/i) { |
|
|
538 | for ($chdl->grep_by_type (cf::RING, cf::AMULET)) { |
|
|
539 | my $sklvl = cf::exp_to_level ($sk->stats->exp); |
|
|
540 | my $ringlvl = power_to_level (ring_or_ammy_to_hash ($_)); |
|
|
541 | |
|
|
542 | if ($pl->get_flag (cf::FLAG_WIZ)) { |
176 | if ($pl->flag (cf::FLAG_WIZ)) { |
543 | $pl->message ("The " . $_->name . " is at level $ringlvl chance for you: " . level_diff_to_chance_perc ($sklvl - $ringlvl)); |
177 | $iring->wiz_analyze ($pl); |
|
|
178 | } |
|
|
179 | } else { |
|
|
180 | if (!$pl->flag (cf::FLAG_WIZ)) { |
|
|
181 | $ingred->check_costs (\%cdiff, 1); |
|
|
182 | } |
|
|
183 | make_ring ($chdl, $ingred, $iring, $sk, $pl); |
|
|
184 | } |
|
|
185 | } |
544 | } else { |
186 | } else { |
545 | my $tmpl = level_diff_to_str ($sklvl - $ringlvl); |
187 | $pl->message ("You've got no idea what you are planning to do!"); |
546 | my $msg = sprintf $tmpl, $_->name; |
|
|
547 | $pl->message ($msg); |
|
|
548 | } |
188 | } |
549 | } |
189 | } |
550 | |
|
|
551 | } elsif ($msg =~ m/^\s*make\s+(\S+)\s*$/i) { |
|
|
552 | unless ($CFG->{conversions}->{lc $1}) { |
|
|
553 | $pl->message ("You don't know how to make '$1', is does such a thing even exist?"); |
|
|
554 | return |
|
|
555 | } |
|
|
556 | |
|
|
557 | simple_converter ($player, $ingred, $chdl, $1); |
|
|
558 | |
|
|
559 | # for (@{$ingred->{rings}}) { |
|
|
560 | # ring_or_ammy_to_hash ($_); |
|
|
561 | # } |
|
|
562 | #put_ingred_to_bench ($ingred, $c[0]); |
|
|
563 | |
|
|
564 | } else { |
|
|
565 | my $plan = get_plan ($ingred); |
|
|
566 | |
|
|
567 | if ($plan) { |
|
|
568 | my @ring = get_ring ($ingred); |
|
|
569 | |
|
|
570 | if (@ring > 1) { |
|
|
571 | # actually the algorithm cant handle more than one improvement at a time |
|
|
572 | $pl->message ("You can't manage to improve more than one ring!"); |
|
|
573 | |
|
|
574 | } elsif (@ring < 1) { |
|
|
575 | # actually the algorithm cant |
|
|
576 | $pl->message ("You slap yourself, you forgot the ring!"); |
|
|
577 | |
|
|
578 | } else { |
|
|
579 | my $ringh = ring_or_ammy_to_hash ($ring[0]); |
|
|
580 | my $amount = get_improv_amount ($plan, $ingred); |
|
|
581 | # my $costs = get_plan_costs ($plan[0], $ringh, $amount); |
|
|
582 | # |
|
|
583 | # if (my $chk = check_plan_costs ($costs, $ingred)) { |
|
|
584 | # # output some error that he lacks the ingredients |
|
|
585 | # } else { |
|
|
586 | # execute_plan ($costs, $ringh, $ingred); |
|
|
587 | # } |
|
|
588 | } |
|
|
589 | |
|
|
590 | } else { |
|
|
591 | $pl->message ("You've got no idea what you are planning to do!"); |
|
|
592 | } |
|
|
593 | } |
190 | }; |
594 | }; |
|
|
595 | $@ and warn "ERROR: $@\n"; |
191 | $@ and warn "ERROR: $@\n"; |
596 | |
192 | } |
597 | my $r = cf::random_roll (0, 101, $pl, cf::PREFER_LOW); |
|
|
598 | $rv; |
|
|
599 | } |
|
|