ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/reseller.ext
Revision: 1.19
Committed: Sun Jan 29 02:47:04 2017 UTC (7 years, 3 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.18: +3 -3 lines
Log Message:
remove eol whitespace

File Contents

# Content
1 #!perl # mandatory
2
3 sub ob2info {
4 my ($item, $rval) = @_;
5
6 sprintf "[%s from %s (%d:%d%s) nrof: %d uuid: %s]",
7 $item->name, $item->kv_get ('ext_reseller_seller'),
8 $item->kv_get ('ext_reseller_orig_value'), $item->value,
9 (defined $rval ? ":$rval" : ""), $item->nrof, $item->uuid
10 }
11
12 sub audit_log {
13 my ($who, $action, $info) = @_;
14 cf::info
15 sprintf "RESELLER_AUDIT(%s) %s %s: %s\n",
16 $who->map->path, $who->name, $action, $info;
17 }
18
19 sub find_rec;
20
21 sub find_rec {
22 my ($ob, $cb) = @_;
23
24 my @found;
25
26 for my $i ($ob->inv) {
27 push @found, $i if $cb->($i);
28 push @found, find_rec $i, $cb if $i->inv;
29 }
30
31 @found
32 }
33
34 sub find_unpaid {
35 my ($ob) = @_;
36
37 find_rec $ob, sub { $_[0]->flag (cf::FLAG_UNPAID) };
38 }
39
40 sub find_traded {
41 my ($ob) = @_;
42
43 find_rec $ob, sub { $_[0]->kv_get ('ext_reseller_seller') ne '' };
44 }
45
46 cf::register_script_function "reseller::list_sells" => sub {
47 my ($who, $msg, $npc) = @_;
48 my $ext_re_sales = $npc->kv_get ('ext_reseller_sales');
49 my $sells = $ext_re_sales && cf::decode_json $ext_re_sales;
50 my $hissells = $sells->{$who->name};
51
52 unless (keys %{$hissells || {}}) {
53 $who->reply ($npc, "I'm sorry, but you sold nothing.\n");
54 return 0;
55 }
56
57 my $reply = "T<You sold:>\n\n";
58
59 for (keys %$hissells) {
60 my $n = $_;
61 $n =~ s/\s*\(unpaid\)//g;
62 $reply .= " B<$n> (for " . cf::cost_string_from_value ($hissells->{$_}) . ")\n";
63 }
64
65 $who->reply ($npc, $reply);
66
67 0
68 };
69
70 cf::register_script_function "reseller::pay_player" => sub {
71 my ($who, $msg, $npc) = @_;
72 my $ext_re_sales = $npc->kv_get ('ext_reseller_sales');
73 my $sells = $ext_re_sales && cf::decode_json $ext_re_sales;
74 my $hissells = $sells->{$who->name};
75
76 unless (keys %{$hissells || {}}) {
77 $who->reply ($npc, "I'm sorry, but you sold nothing.\n");
78 return 0;
79 }
80
81 my $sum = 0;
82 $sum += $_ for values %$hissells;
83
84 $who->pay_player ($sum);
85 $who->reply ($npc, "Here are the " . cf::cost_string_from_value ($sum) . " for your sales.");
86
87 audit_log ($who, 'collects', "$sum silver");
88
89 $sells->{$who->name} = {};
90
91 $npc->kv_set (ext_reseller_sales => cf::encode_json $sells)
92 if $sells;
93
94 0
95 };
96
97 cf::object::attachment "reseller_shopmat",
98 on_move_trigger => sub {
99 my ($self, $who_caused, $who) = @_;
100
101 my @obs = grep { $_->name eq $self->{reseller_shopmat}{npc_name} }
102 $who->map->at ($self->{reseller_shopmat}{npc_x}, $self->{reseller_shopmat}{npc_y});
103
104 unless (@obs) {
105 cf::error "Couldn't find shop keeper in " . $who->map->path . "\n";
106 return cf::override;
107 }
108
109 my $ext_re_sales = $obs[0]->kv_get ('ext_reseller_sales');
110 my $sells = $ext_re_sales && cf::decode_json $ext_re_sales;
111
112 my $unpaid_items = {};
113
114 for my $item (find_unpaid ($who)) {
115 if ($item->kv_get ('ext_reseller_seller') eq $who->name) {
116 audit_log ($who, 'removes', ob2info ($item));
117 $item->flag (cf::FLAG_UNPAID, 0);
118 $item->remove;
119 give_back ($who, $item);
120 next;
121 }
122
123 my $value = $item->query_cost ($who, cf::F_BUY | cf::F_SHOP);
124
125 cf::debug "Object ", $item->name, " bought by ", $who->name, " on map " ,
126 $who->map->path, " for $value silver has no seller set\n"
127 if $item->kv_get ('ext_reseller_seller') eq '';
128
129 $unpaid_items->{$item} = [$value, $item];
130 }
131
132 audit_log ($who, 'wants', (join ",", map { ob2info ($_->[1], $_->[0]) } values %$unpaid_items))
133 if %$unpaid_items;
134
135 $self->apply_shop_mat ($who);
136
137 my @seller_noted;
138
139 for my $item (find_traded ($who)) {
140 next if $item->flag (cf::FLAG_UNPAID);
141 if (my $value = $unpaid_items->{$item}[0]) {
142 push @seller_noted, ob2info ($item, $value)."P";
143 $sells->{$item->kv_get ('ext_reseller_seller')}->{$item->name} += $value;
144 } else {
145 push @seller_noted, ob2info ($item)."T";
146 }
147
148 $item->value ($item->kv_get ('ext_reseller_orig_value'));
149 $item->kv_del ("ext_reseller_seller");
150 }
151
152 audit_log ($who, 'removed', (join ",", @seller_noted))
153 if @seller_noted;
154
155 $obs[0]->kv_set (ext_reseller_sales => cf::encode_json $sells)
156 if $sells;
157
158 cf::override;
159 },
160 ;
161
162 sub give_back {
163 my ($who, $what) = @_;
164 $who->insert ($what);
165 }
166
167 sub give_back_with_message {
168 my ($who, $what, $msg) = @_;
169 $who->message ($msg, cf::NDI_BROWN);
170 give_back ($who, $what);
171 }
172
173 cf::object::attachment "reseller_floor",
174 on_drop_on => sub {
175 my ($on, $what, $who) = @_;
176 my $name = $what->custom_name;
177
178 return if $what->flag (cf::FLAG_UNPAID);
179
180 if ($what->type == cf::MONEY) {
181 give_back_with_message ($who, $what,
182 "The shopkeeper says: Sorry, you can't sell money here.");
183 return cf::override;
184 }
185
186 if (!$what->flag (cf::FLAG_IDENTIFIED) && $what->need_identify) {
187 give_back_with_message ($who, $what,
188 "The shopkeeper says: Sorry, you can't sell unidentified stuff here.");
189 return cf::override;
190 }
191
192 my $orig_value = $what->value;
193 my $value = 0;
194
195 if ($name =~ m/\S/) {
196 unless ($name =~ m/\d+\s*\S+/) {
197 give_back_with_message ($who, $what,
198 "The shopkeeper says: Sorry, I don't recognize '$name' as currency. "
199 . "Please name your item like '17 platinum' or '10 gold 8 silver.'");
200 return cf::override;
201 }
202
203 while ($name =~ s/^\s*(\d+)\s*(\S+)//) {
204 my ($v, $c) = ($1, $2);
205 if (my $coin = cf::coin_from_name $c) {
206 $value += $v * $coin->value;
207 } else {
208 give_back_with_message ($who, $what,
209 "The shopkeeper says: I don't know the currency '$c', you can use one of these currencies: "
210 . (join ", ", cf::coin_names)
211 );
212 return cf::override;
213 }
214 }
215 } else {
216 # commented out the following line because too many just use the
217 # reseller shop as dumpyard:
218 # $value = $what->query_cost ($who, cf::F_SELL | cf::F_SHOP) / ($what->nrof || 1);
219 give_back_with_message ($who, $what,
220 "Sorry, you can't just sell stuff without assigning a price to it! "
221 . "Please name your item like '17 platinum' or '10 gold 8 silver' "
222 . "and drop it again. (To rename the item use the B<rename> "
223 . "entry in the inventory item popup menu)."
224 );
225 return cf::override;
226 }
227
228 if ($value > 100 ** 4) { # also for overflow prevention
229 give_back_with_message ($who, $what,
230 "The shopkeeper says: You can't sell something for such a high "
231 . "value. Please keep it below 100 royalty.");
232 return cf::override;
233 }
234
235 if ($value < 0) {
236 give_back_with_message ($who, $what,
237 "The shopkeeper says: You can't sell something for a negative value: $value.");
238 return cf::override;
239 }
240
241 my $fee = $value / 100; # 1% selling fee
242
243 unless ($who->pay_amount ($fee)) {
244 give_back_with_message ($who, $what,
245 "The shopkeeper says: You need " . cf::cost_string_from_value ($fee)
246 . " to pay the 1% fee for this item.");
247 return cf::override;
248 } else {
249 $who->message (
250 "The shopkeeper says: Ok, got the fee of " . cf::cost_string_from_value ($fee)
251 . " for the item.",
252 cf::NDI_BROWN
253 );
254 }
255
256 $what->value ($value);
257 my $cost = $what->query_cost ($who, cf::F_BUY | cf::F_SHOP) / ($what->nrof || 1);
258
259 my $fact = 0;
260 if ($cost) {
261 $fact = $value / $cost;
262 $what->value (cf::ceil ($value * $fact));
263 }
264
265 # warn "END VALUE: $value * $fact => " . $what->value . "\n";
266
267 # my $cost = $what->query_cost ($who, cf::F_BUY | cf::F_SHOP) / $what->nrof;
268 # warn "COSTS NOW: $cost\n";
269
270 $who->message (
271 "The shopkeeper says: Ok, I marked "
272 . ($what->nrof || 1) . " " . $what->name . " to be sold for at least "
273 . cf::cost_string_from_value ($value)
274 . ($what->nrof > 1 ? " each" : ""), cf::NDI_BROWN
275 );
276
277 $what->kv_set (ext_reseller_seller => $who->name);
278 $what->kv_set (ext_reseller_orig_value => $orig_value);
279 # warn "SET SELLER ON " . $what->name . " + " . $what->{seller}->[0] . "\n";
280 $what->custom_name ($what->name . " (by " . $who->name . ")");
281 $what->flag (cf::FLAG_UNPAID, 1);
282 $what->insert_ob_in_map_at ($who->map, $who, cf::INS_BELOW_ORIGINATOR, $who->x, $who->y);
283
284 audit_log ($who, 'sells', ob2info ($what));
285
286 cf::override;
287 },
288 ;
289