line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Games::Lacuna::Task::Role::Ships; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
1649
|
use 5.010; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
63
|
|
4
|
|
|
|
|
|
|
our $VERSION = $Games::Lacuna::Task::VERSION; |
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
517
|
use Moose::Role; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
use List::Util qw(min sum max first); |
9
|
|
|
|
|
|
|
use Games::Lacuna::Task::Utils qw(parse_ship_type); |
10
|
|
|
|
|
|
|
use Games::Lacuna::Client::Types qw(ship_tags); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub name_ship { |
13
|
|
|
|
|
|
|
my ($self, %params) = @_; |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
my $spaceport = $params{spaceport}; |
16
|
|
|
|
|
|
|
my $name = $params{name}; |
17
|
|
|
|
|
|
|
my $ignore = $params{ignore}; |
18
|
|
|
|
|
|
|
my $prefix = $params{prefix}; |
19
|
|
|
|
|
|
|
my $ship = $params{ship}; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
my ($old_name,$old_prefix,$old_ignore); |
22
|
|
|
|
|
|
|
$ship->{name} ||= $ship->{type_human}; |
23
|
|
|
|
|
|
|
$old_name = $ship->{name} ; |
24
|
|
|
|
|
|
|
if ($old_name =~ s/!//g) { |
25
|
|
|
|
|
|
|
$old_ignore = 1; |
26
|
|
|
|
|
|
|
} else { |
27
|
|
|
|
|
|
|
$old_ignore = 0; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
if ($old_name =~ m/^([^:]+):(.+)$/) { |
31
|
|
|
|
|
|
|
$old_prefix = $1; |
32
|
|
|
|
|
|
|
$old_name = $2; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
$prefix ||= $old_prefix; # not defined or! |
36
|
|
|
|
|
|
|
$ignore //= $old_ignore; |
37
|
|
|
|
|
|
|
$name //= $old_name; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
$prefix = join(',', grep { defined $_ && $_ !~ /^\s*$/ } @{$prefix} ) |
40
|
|
|
|
|
|
|
if ref $prefix eq 'ARRAY'; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# Normalize name |
43
|
|
|
|
|
|
|
$prefix = Games::Lacuna::Task::Utils::clean_name($prefix); |
44
|
|
|
|
|
|
|
$name = Games::Lacuna::Task::Utils::clean_name($name); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# Get max name length |
47
|
|
|
|
|
|
|
my $max_length = 30; |
48
|
|
|
|
|
|
|
$max_length -= 1 |
49
|
|
|
|
|
|
|
if $ignore; |
50
|
|
|
|
|
|
|
$max_length -= ( 1 + length($prefix)) |
51
|
|
|
|
|
|
|
if $prefix; |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# Build new name |
54
|
|
|
|
|
|
|
my $new_name = ''; |
55
|
|
|
|
|
|
|
$new_name .= $prefix.':' |
56
|
|
|
|
|
|
|
if defined $prefix; |
57
|
|
|
|
|
|
|
$new_name .= substr($name,0,$max_length); |
58
|
|
|
|
|
|
|
$new_name .= '!' |
59
|
|
|
|
|
|
|
if $ignore; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
if ($new_name ne $ship->{name}) { |
63
|
|
|
|
|
|
|
$self->log('notice',"Renaming ship from '%s' to '%s'",$ship->{name},$new_name); |
64
|
|
|
|
|
|
|
$ship->{name} = $new_name; |
65
|
|
|
|
|
|
|
$self->request( |
66
|
|
|
|
|
|
|
object => $spaceport, |
67
|
|
|
|
|
|
|
method => 'name_ship', |
68
|
|
|
|
|
|
|
params => [$ship->{id},$new_name], |
69
|
|
|
|
|
|
|
); |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub push_ships { |
74
|
|
|
|
|
|
|
my ($self,$form_id,$to_id,$ships) = @_; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
my $trade_object = $self->get_building_object($form_id,'Trade'); |
77
|
|
|
|
|
|
|
my $spaceport_object = $self->get_building_object($form_id,'SpacePort'); |
78
|
|
|
|
|
|
|
my $target_spaceport_object = $self->get_building_object($to_id,'SpacePort'); |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
return 0 |
81
|
|
|
|
|
|
|
unless $trade_object |
82
|
|
|
|
|
|
|
&& $spaceport_object |
83
|
|
|
|
|
|
|
&& $target_spaceport_object; |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
my $docks_available = $self->request( |
86
|
|
|
|
|
|
|
object => $target_spaceport_object, |
87
|
|
|
|
|
|
|
method => 'view', |
88
|
|
|
|
|
|
|
)->{docks_available}; |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
if (scalar @{$ships} > $docks_available) { |
91
|
|
|
|
|
|
|
$ships = [ @{$ships}[0..$docks_available-1] ]; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# Loop all ships |
95
|
|
|
|
|
|
|
my (@cargo_ships,@other_ships); |
96
|
|
|
|
|
|
|
foreach my $ship (@{$ships}) { |
97
|
|
|
|
|
|
|
if ($ship->{type} ~~ [qw(galleon hulk cargo freighter hulk smuggler barge dory)]) { |
98
|
|
|
|
|
|
|
push(@cargo_ships,$ship); |
99
|
|
|
|
|
|
|
} else { |
100
|
|
|
|
|
|
|
push(@other_ships,$ship); |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
$self->name_ship( |
104
|
|
|
|
|
|
|
spaceport => $spaceport_object, |
105
|
|
|
|
|
|
|
ship => $ship, |
106
|
|
|
|
|
|
|
ignore => 0 |
107
|
|
|
|
|
|
|
); |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# Loop all cargo ships to be sent |
111
|
|
|
|
|
|
|
foreach my $cargo_ship (sort { $b->{speed} <=> $a->{speed} } @cargo_ships) { |
112
|
|
|
|
|
|
|
my $available_hold_size = $cargo_ship->{hold_size}; |
113
|
|
|
|
|
|
|
my @cargo; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
while (scalar @other_ships |
116
|
|
|
|
|
|
|
&& $available_hold_size >= $Games::Lacuna::Task::Constants::CARGO{ship}) { |
117
|
|
|
|
|
|
|
my $ship = shift @other_ships; |
118
|
|
|
|
|
|
|
push (@cargo,{ |
119
|
|
|
|
|
|
|
"type" => "ship", |
120
|
|
|
|
|
|
|
"ship_id" => $ship->{id}, |
121
|
|
|
|
|
|
|
}); |
122
|
|
|
|
|
|
|
$available_hold_size -= $Games::Lacuna::Task::Constants::CARGO{ship} |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# Add minimum cargo |
126
|
|
|
|
|
|
|
push(@cargo,{ |
127
|
|
|
|
|
|
|
"type" => "water", |
128
|
|
|
|
|
|
|
"quantity" => 1, |
129
|
|
|
|
|
|
|
}) unless scalar(@cargo); |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
$self->request( |
132
|
|
|
|
|
|
|
object => $trade_object, |
133
|
|
|
|
|
|
|
method => 'push_items', |
134
|
|
|
|
|
|
|
params => [ |
135
|
|
|
|
|
|
|
$to_id, |
136
|
|
|
|
|
|
|
\@cargo, |
137
|
|
|
|
|
|
|
{ |
138
|
|
|
|
|
|
|
ship_id => $cargo_ship->{id}, |
139
|
|
|
|
|
|
|
stay => 1, |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
] |
142
|
|
|
|
|
|
|
); |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# We have non-cargo ships left |
146
|
|
|
|
|
|
|
if (scalar @other_ships) { |
147
|
|
|
|
|
|
|
my @cargo; |
148
|
|
|
|
|
|
|
foreach my $other_ship (@other_ships) { |
149
|
|
|
|
|
|
|
push(@cargo,{ |
150
|
|
|
|
|
|
|
type => 'ship', |
151
|
|
|
|
|
|
|
ship_id => $other_ship->{id}, |
152
|
|
|
|
|
|
|
}); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
my $trade_ships = $self->trade_ships($form_id,\@cargo); |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
foreach my $ship_id (keys %{$trade_ships}) { |
158
|
|
|
|
|
|
|
$self->request( |
159
|
|
|
|
|
|
|
object => $trade_object, |
160
|
|
|
|
|
|
|
method => 'push_items', |
161
|
|
|
|
|
|
|
params => [ |
162
|
|
|
|
|
|
|
$to_id, |
163
|
|
|
|
|
|
|
$trade_ships->{$ship_id}, |
164
|
|
|
|
|
|
|
{ |
165
|
|
|
|
|
|
|
ship_id => $ship_id, |
166
|
|
|
|
|
|
|
stay => 0, |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
] |
169
|
|
|
|
|
|
|
); |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
return; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub trade_ships { |
177
|
|
|
|
|
|
|
my ($self,$body_id,$cargo) = @_; |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
my $trade = $self->find_building($body_id,'Trade'); |
180
|
|
|
|
|
|
|
return |
181
|
|
|
|
|
|
|
unless defined $trade; |
182
|
|
|
|
|
|
|
my $trade_object = $self->build_object($trade); |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# Calculate cargo capacity |
185
|
|
|
|
|
|
|
my $required_hold_size = 0; |
186
|
|
|
|
|
|
|
foreach my $position (@$cargo) { |
187
|
|
|
|
|
|
|
$position->{hold_size_per_item} = $Games::Lacuna::Task::Constants::CARGO{$position->{type}}; |
188
|
|
|
|
|
|
|
$position->{quantity} //= 1; |
189
|
|
|
|
|
|
|
$required_hold_size += $position->{hold_size_per_item} * $position->{quantity}; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
# Get all trade ships |
193
|
|
|
|
|
|
|
my $trade_ships = $self->request( |
194
|
|
|
|
|
|
|
object => $trade_object, |
195
|
|
|
|
|
|
|
method => 'get_trade_ships', |
196
|
|
|
|
|
|
|
)->{ships}; |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# Get max hold size |
199
|
|
|
|
|
|
|
my $max_hold_size = max map { $_->{hold_size} } @{$trade_ships}; |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
my $return = {}; |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# One cargo ship is enough |
204
|
|
|
|
|
|
|
if ($max_hold_size > $required_hold_size) { |
205
|
|
|
|
|
|
|
foreach my $cargo_ship (sort { $b->{speed} <=> $a->{speed} } @{$trade_ships}) { |
206
|
|
|
|
|
|
|
next |
207
|
|
|
|
|
|
|
if $cargo_ship->{name} =~ m/!/; |
208
|
|
|
|
|
|
|
if ($cargo_ship->{hold_size} > $required_hold_size) { |
209
|
|
|
|
|
|
|
$return->{$cargo_ship->{id}} = $cargo; |
210
|
|
|
|
|
|
|
last; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
# We need multiple cargo ships |
214
|
|
|
|
|
|
|
} else { |
215
|
|
|
|
|
|
|
foreach my $cargo_ship (sort { $b->{hold_size} <=> $a->{hold_size} } @{$trade_ships}) { |
216
|
|
|
|
|
|
|
next |
217
|
|
|
|
|
|
|
if $cargo_ship->{name} =~ m/!/; |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
my $available_hold_size = $cargo_ship->{hold_size}; |
220
|
|
|
|
|
|
|
my @cargo_for_ship; |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
foreach my $position (sort { $b->{hold_size_per_item} <=> $a->{hold_size_per_item} } @{$cargo}) { |
223
|
|
|
|
|
|
|
next |
224
|
|
|
|
|
|
|
if $position->{quantity} == 0; |
225
|
|
|
|
|
|
|
if ($available_hold_size > $position->{hold_size_per_item}) { |
226
|
|
|
|
|
|
|
my $this_position = \%{$position}; # shallow copy |
227
|
|
|
|
|
|
|
$this_position->{quantity} = min( ($available_hold_size/$position->{hold_size_per_item}), $position->{quantity} ); |
228
|
|
|
|
|
|
|
$position->{quantity} -= $this_position->{quantity}; |
229
|
|
|
|
|
|
|
$available_hold_size -= $this_position->{quantity} * $position->{hold_size_per_item}; |
230
|
|
|
|
|
|
|
push(@cargo_for_ship,$this_position); |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
last |
235
|
|
|
|
|
|
|
if scalar @cargo_for_ship == 0; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
$return->{$cargo_ship->{id}} = \@cargo_for_ship; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
# # Remove temporary values from return value |
242
|
|
|
|
|
|
|
# foreach my $cargo_for_ship (values %{$return}) { |
243
|
|
|
|
|
|
|
# foreach my $position (@$cargo_for_ship) { |
244
|
|
|
|
|
|
|
# delete $cargo_for_ship->{hold_size_per_item}; |
245
|
|
|
|
|
|
|
# } |
246
|
|
|
|
|
|
|
# } |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
return $return; |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub spaceport_slots { |
252
|
|
|
|
|
|
|
my ($self,$planet_id) = @_; |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
my $spaceport = $self->find_building($planet_id,'SpacePort'); |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
return (0,0) |
257
|
|
|
|
|
|
|
unless $spaceport; |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
my $spaceport_data = $self->request( |
260
|
|
|
|
|
|
|
object => $self->build_object($spaceport), |
261
|
|
|
|
|
|
|
method => 'view', |
262
|
|
|
|
|
|
|
); |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
return ($spaceport_data->{docks_available},$spaceport_data->{max_ships}); |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub shipyard_slots { |
268
|
|
|
|
|
|
|
my ($self,$planet_id) = @_; |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
my @shipyards = $self->find_building($planet_id,'Shipyard'); |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
return (0,{}) |
273
|
|
|
|
|
|
|
unless (scalar @shipyards); |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
my $total_current_queue_size = 0; |
276
|
|
|
|
|
|
|
my $total_max_queue_size = 0; |
277
|
|
|
|
|
|
|
my $available_shipyards = {}; |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
SHIPYARDS: |
280
|
|
|
|
|
|
|
foreach my $shipyard (@shipyards) { |
281
|
|
|
|
|
|
|
my $shipyard_id = $shipyard->{id}; |
282
|
|
|
|
|
|
|
my $shipyard_object = $self->build_object($shipyard); |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
# Get build queue |
285
|
|
|
|
|
|
|
my $shipyard_queue_data = $self->request( |
286
|
|
|
|
|
|
|
object => $shipyard_object, |
287
|
|
|
|
|
|
|
method => 'view_build_queue', |
288
|
|
|
|
|
|
|
params => [1], |
289
|
|
|
|
|
|
|
); |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
my $shipyard_queue_size = $shipyard_queue_data->{number_of_ships_building} // 0; |
292
|
|
|
|
|
|
|
$total_max_queue_size += $shipyard->{level}; |
293
|
|
|
|
|
|
|
$total_current_queue_size += $shipyard_queue_size; |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# Check available build slots |
296
|
|
|
|
|
|
|
next SHIPYARDS |
297
|
|
|
|
|
|
|
if $shipyard->{level} <= $shipyard_queue_size; |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
$available_shipyards->{$shipyard_id} = { |
300
|
|
|
|
|
|
|
id => $shipyard_id, |
301
|
|
|
|
|
|
|
object => $shipyard_object, |
302
|
|
|
|
|
|
|
level => $shipyard->{level}, |
303
|
|
|
|
|
|
|
seconds_remaining => ($shipyard_queue_data->{building}{work}{seconds_remaining} // 0), |
304
|
|
|
|
|
|
|
available => ($shipyard->{level} - $shipyard_queue_size), |
305
|
|
|
|
|
|
|
}; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
return ( ($total_max_queue_size - $total_current_queue_size) , $available_shipyards ); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
sub get_ships { |
312
|
|
|
|
|
|
|
my ($self,%params) = @_; |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# Get params |
315
|
|
|
|
|
|
|
my $planet_stats = $params{planet}; |
316
|
|
|
|
|
|
|
my $type = parse_ship_type($params{type}); |
317
|
|
|
|
|
|
|
my $name_prefix = $params{name_prefix}; |
318
|
|
|
|
|
|
|
my $quantity = $params{quantity}; |
319
|
|
|
|
|
|
|
my $travelling = $params{travelling} // 0; |
320
|
|
|
|
|
|
|
my $build = $params{build} // 1; |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# Initialize vars |
323
|
|
|
|
|
|
|
my @known_ships; |
324
|
|
|
|
|
|
|
my @avaliable_ships; |
325
|
|
|
|
|
|
|
my $building_ships = 0; |
326
|
|
|
|
|
|
|
my $travelling_ships = 0; |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
return |
329
|
|
|
|
|
|
|
unless defined $type && defined $planet_stats; |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
# Get space port |
332
|
|
|
|
|
|
|
my @spaceports = $self->find_building($planet_stats->{id},'SpacePort'); |
333
|
|
|
|
|
|
|
return |
334
|
|
|
|
|
|
|
unless scalar @spaceports; |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
my $spaceport_object = $self->build_object($spaceports[0]); |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
# Get all available ships |
339
|
|
|
|
|
|
|
my $ships_data = $self->request( |
340
|
|
|
|
|
|
|
object => $spaceport_object, |
341
|
|
|
|
|
|
|
method => 'view_all_ships', |
342
|
|
|
|
|
|
|
params => [ { no_paging => 1 } ], |
343
|
|
|
|
|
|
|
); |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
# Get available slots |
346
|
|
|
|
|
|
|
my $max_spaceport_slots = sum map { $_->{level} * 2 } @spaceports; |
347
|
|
|
|
|
|
|
my $available_spaceport_slots = max($max_spaceport_slots - $ships_data->{number_of_ships},0); |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
# Find all avaliable and buildings ships |
350
|
|
|
|
|
|
|
SHIPS: |
351
|
|
|
|
|
|
|
foreach my $ship (@{$ships_data->{ships}}) { |
352
|
|
|
|
|
|
|
next |
353
|
|
|
|
|
|
|
unless $type eq $ship->{type}; |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
push(@known_ships,$ship->{id}); |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# Check ship prefix and flags |
358
|
|
|
|
|
|
|
if (defined $name_prefix) { |
359
|
|
|
|
|
|
|
next SHIPS |
360
|
|
|
|
|
|
|
unless $ship->{name} =~ m/^$name_prefix/i; |
361
|
|
|
|
|
|
|
} else { |
362
|
|
|
|
|
|
|
next SHIPS |
363
|
|
|
|
|
|
|
if $ship->{name} =~ m/\!/; # Indicates reserved ship |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# Get ship activity |
367
|
|
|
|
|
|
|
if ($ship->{task} eq 'Docked') { |
368
|
|
|
|
|
|
|
push(@avaliable_ships,$ship->{id}); |
369
|
|
|
|
|
|
|
} elsif ($ship->{task} eq 'Building') { |
370
|
|
|
|
|
|
|
$building_ships ++; |
371
|
|
|
|
|
|
|
} elsif ($ship->{task} eq 'Travelling') { |
372
|
|
|
|
|
|
|
$travelling_ships ++; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
# Check if we have enough ships |
376
|
|
|
|
|
|
|
return @avaliable_ships |
377
|
|
|
|
|
|
|
if defined $quantity |
378
|
|
|
|
|
|
|
&& $quantity > 0 |
379
|
|
|
|
|
|
|
&& scalar(@avaliable_ships) >= $quantity; |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# Check if we should build new ships |
383
|
|
|
|
|
|
|
return @avaliable_ships |
384
|
|
|
|
|
|
|
unless $build; |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
if (defined $quantity |
387
|
|
|
|
|
|
|
&& $quantity > 0) { |
388
|
|
|
|
|
|
|
$quantity -= $building_ships; |
389
|
|
|
|
|
|
|
$quantity -= $travelling_ships |
390
|
|
|
|
|
|
|
if $travelling; |
391
|
|
|
|
|
|
|
$quantity -= scalar(@avaliable_ships); |
392
|
|
|
|
|
|
|
$quantity = max($quantity,0); |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
return @avaliable_ships |
397
|
|
|
|
|
|
|
if ! defined $quantity || $quantity <= 0 || ! defined $type; |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
my $new_building = $self->build_ships( |
400
|
|
|
|
|
|
|
planet => $planet_stats, |
401
|
|
|
|
|
|
|
quantity => $quantity, |
402
|
|
|
|
|
|
|
type => $type, |
403
|
|
|
|
|
|
|
spaceports_slots => $available_spaceport_slots, |
404
|
|
|
|
|
|
|
(defined $name_prefix ? (name_prefix => $name_prefix):()), |
405
|
|
|
|
|
|
|
); |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
# # Rename new ships |
408
|
|
|
|
|
|
|
# if ($new_building > 0 |
409
|
|
|
|
|
|
|
# && defined $name_prefix) { |
410
|
|
|
|
|
|
|
# |
411
|
|
|
|
|
|
|
# # Get all available ships |
412
|
|
|
|
|
|
|
# my $ships_data = $self->request( |
413
|
|
|
|
|
|
|
# object => $spaceport_object, |
414
|
|
|
|
|
|
|
# method => 'view_all_ships', |
415
|
|
|
|
|
|
|
# params => [ { no_paging => 1 } ], |
416
|
|
|
|
|
|
|
# ); |
417
|
|
|
|
|
|
|
# |
418
|
|
|
|
|
|
|
# NEW_SHIPS: |
419
|
|
|
|
|
|
|
# foreach my $ship (@{$ships_data->{ships}}) { |
420
|
|
|
|
|
|
|
# next NEW_SHIPS |
421
|
|
|
|
|
|
|
# if $ship->{id} ~~ \@known_ships; |
422
|
|
|
|
|
|
|
# next NEW_SHIPS |
423
|
|
|
|
|
|
|
# unless $ship->{type} eq $type; |
424
|
|
|
|
|
|
|
# |
425
|
|
|
|
|
|
|
# my $name = $name_prefix .': '.$ship->{name}.'!'; |
426
|
|
|
|
|
|
|
# |
427
|
|
|
|
|
|
|
# $self->log('notice',"Renaming new ship to %s on %s",$name,$planet_stats->{name}); |
428
|
|
|
|
|
|
|
# |
429
|
|
|
|
|
|
|
# # Rename ship |
430
|
|
|
|
|
|
|
# $self->request( |
431
|
|
|
|
|
|
|
# object => $spaceport_object, |
432
|
|
|
|
|
|
|
# method => 'name_ship', |
433
|
|
|
|
|
|
|
# params => [$ship->{id},$name], |
434
|
|
|
|
|
|
|
# ); |
435
|
|
|
|
|
|
|
# } |
436
|
|
|
|
|
|
|
# } |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
return @avaliable_ships; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
sub build_ships { |
442
|
|
|
|
|
|
|
my ($self,%params) = @_; |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
# Get params |
445
|
|
|
|
|
|
|
my $planet_stats = $params{planet}; |
446
|
|
|
|
|
|
|
my $quantity = $params{quantity}; |
447
|
|
|
|
|
|
|
my $type = parse_ship_type($params{type}); |
448
|
|
|
|
|
|
|
my $available_spaceport_slots = $params{spaceports_slots}; |
449
|
|
|
|
|
|
|
my $available_shipyard_slots = $params{shipyard_slots}; |
450
|
|
|
|
|
|
|
my $available_shipyards = $params{shipyards}; |
451
|
|
|
|
|
|
|
my $name_prefix = $params{name_prefix}; |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
# Initialize vars |
454
|
|
|
|
|
|
|
my $max_build_quantity = 0; |
455
|
|
|
|
|
|
|
my $new_building = 0; |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
# Get Buildings |
458
|
|
|
|
|
|
|
my @spaceports = $self->find_building($planet_stats->{id},'SpacePort'); |
459
|
|
|
|
|
|
|
return 0 |
460
|
|
|
|
|
|
|
unless scalar @spaceports; |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
my $spaceport_object = $self->build_object($spaceports[0]); |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
# Get shipyard slots |
465
|
|
|
|
|
|
|
unless (defined $available_shipyard_slots && defined $available_shipyard_slots) { |
466
|
|
|
|
|
|
|
($available_shipyard_slots,$available_shipyards) = $self->shipyard_slots($planet_stats->{id}); |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
# Get spaceport slots |
470
|
|
|
|
|
|
|
unless (defined $available_spaceport_slots) { |
471
|
|
|
|
|
|
|
($available_spaceport_slots,undef) = $self->spaceport_slots($planet_stats->{id}); |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
# Calc max spaceport capacity |
475
|
|
|
|
|
|
|
my $max_ships_possible = sum map { $_->{level} * 2 } @spaceports; |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
# Quantity is defined as free-spaceport slots |
478
|
|
|
|
|
|
|
if ($quantity < 0) { |
479
|
|
|
|
|
|
|
$max_build_quantity = max($max_ships_possible - $available_spaceport_slots + $quantity,0); |
480
|
|
|
|
|
|
|
# Quantity is defined as number of ships |
481
|
|
|
|
|
|
|
} else { |
482
|
|
|
|
|
|
|
$max_build_quantity = min($max_ships_possible - $available_spaceport_slots,$quantity); |
483
|
|
|
|
|
|
|
$max_build_quantity = max($max_build_quantity,0); |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
# Check max build queue size |
487
|
|
|
|
|
|
|
$max_build_quantity = min($available_shipyard_slots,$max_build_quantity); |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
# Check if we can build new ships |
491
|
|
|
|
|
|
|
return 0 |
492
|
|
|
|
|
|
|
unless ($max_build_quantity > 0); |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
my @ships_building; |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
# Repeat until we have enough ships |
497
|
|
|
|
|
|
|
BUILD_QUEUE: |
498
|
|
|
|
|
|
|
while ($new_building < $max_build_quantity) { |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
my $shipyard = |
501
|
|
|
|
|
|
|
first { $_->{available} > 0 } |
502
|
|
|
|
|
|
|
sort { $a->{seconds_remaining} <=> $b->{seconds_remaining} } |
503
|
|
|
|
|
|
|
values %{$available_shipyards}; |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
last BUILD_QUEUE |
506
|
|
|
|
|
|
|
unless defined $shipyard; |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
# Get build quantity |
509
|
|
|
|
|
|
|
my $build_per_shipyard = int(($max_build_quantity - $new_building) / scalar (keys %{$available_shipyards}) / 1.5) || 1; |
510
|
|
|
|
|
|
|
my $build_quantity = min($shipyard->{available},$max_build_quantity,$build_per_shipyard); |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
eval { |
513
|
|
|
|
|
|
|
# Build ship |
514
|
|
|
|
|
|
|
my $response = $self->request( |
515
|
|
|
|
|
|
|
object => $shipyard->{object}, |
516
|
|
|
|
|
|
|
method => 'build_ship', |
517
|
|
|
|
|
|
|
params => [$type,$build_quantity], |
518
|
|
|
|
|
|
|
); |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
$shipyard->{seconds_remaining} = $response->{building}{work}{seconds_remaining}; |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
$self->log('notice',"Building %i %s(s) on %s at shipyard level %i",$build_quantity,$type,$planet_stats->{name},$shipyard->{level}); |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
# Remove shipyard slot |
525
|
|
|
|
|
|
|
$shipyard->{available} -= $build_quantity; |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
# Remove from available shipyards |
528
|
|
|
|
|
|
|
delete $available_shipyards->{$shipyard->{id}} |
529
|
|
|
|
|
|
|
if $shipyard->{available} <= 0; |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
# Add ship to list and rename |
532
|
|
|
|
|
|
|
for (1..$build_quantity) { |
533
|
|
|
|
|
|
|
my $ship_building = pop(@{$response->{ships_building}}); |
534
|
|
|
|
|
|
|
push(@ships_building,$ship_building); |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
if (defined $name_prefix) { |
537
|
|
|
|
|
|
|
$self->name_ship( |
538
|
|
|
|
|
|
|
spaceport => $spaceport_object, |
539
|
|
|
|
|
|
|
ship => $ship_building, |
540
|
|
|
|
|
|
|
prefix => $name_prefix, |
541
|
|
|
|
|
|
|
name => $ship_building->{type_human}, |
542
|
|
|
|
|
|
|
ignore => 1, |
543
|
|
|
|
|
|
|
); |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
}; |
548
|
|
|
|
|
|
|
if ($@) { |
549
|
|
|
|
|
|
|
$self->log('warn','Could not build %s: %s',$type,$@); |
550
|
|
|
|
|
|
|
last BUILD_QUEUE; |
551
|
|
|
|
|
|
|
} |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
$new_building += $build_quantity; |
554
|
|
|
|
|
|
|
} |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
return wantarray ? @ships_building : scalar @ships_building; |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
no Moose::Role; |
560
|
|
|
|
|
|
|
1; |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
=encoding utf8 |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
=head1 NAME |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
Games::Lacuna::Task::Role::Ships -Â Helper methods for fetching and building ships |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
=head1 SYNOPSIS |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
package Games::Lacuna::Task::Action::MyTask; |
571
|
|
|
|
|
|
|
use Moose; |
572
|
|
|
|
|
|
|
extends qw(Games::Lacuna::Task::Action); |
573
|
|
|
|
|
|
|
with qw(Games::Lacuna::Task::Role::Ships); |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
=head1 DESCRIPTION |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
This role provides ship-related helper methods. |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
=head1 METHODS |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
=head2 get_ships |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
my @avaliable_scows = $self->get_ships( |
584
|
|
|
|
|
|
|
planet => $planet_stats, |
585
|
|
|
|
|
|
|
ships_needed => 3, # get three |
586
|
|
|
|
|
|
|
ship_type => 'scow', |
587
|
|
|
|
|
|
|
); |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
Tries to fetch the given number of available ships. If there are not enough |
590
|
|
|
|
|
|
|
ships available then the required number of ships are built. |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
The following arguments are accepted |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
=over |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=item * planet |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
Planet data has [Required] |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
=item * ships_needed |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
Number of required ships. If ships_needed is a negative number it will return |
603
|
|
|
|
|
|
|
all matching ships and build as many new ships as possible while keeping |
604
|
|
|
|
|
|
|
ships_needed * -1 space port slots free [Required] |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
=item * ship_type |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
Ship type [Required] |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
=item * travelling |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
If true will not build new ships if there are matchig ships currently |
613
|
|
|
|
|
|
|
travelling |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
=item * name_prefix |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
Will only return ships with the given prefix in their names. Newly built ships |
618
|
|
|
|
|
|
|
will be renamed to add the prefix. |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
=back |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
=head2 trade_ships |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
my $trade_ships = $self->trade_ships($body_id,$cargo_list); |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
Returns a hashref with cargo ship ids as keys and cargo lists as values. |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
=head2 push_ships |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
$self->push_ships($from_body_id,$to_body_id,\@ships); |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
Pushes the selected ships from one body to another |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
=cut |