%s', $cat ne $_->{cat} ? ('h', $cat = $_->{cat}) : ('d', ' ')),
- '' . $_->{name},
- ' | ' . ($_->{min} || '0'),
+ return (
+ ' | ' . ($_->{min} // ''),
' | ' . ($_->{gas} || ''),
- sprintf(' | %s%.0f',
+ !defined $_->{build} ? ' | ' : sprintf(' | %s%.0f',
!!$_->{base} && '+',
$_->{build} || '0',
),
- sprintf(' | %s', $suitchar, ucfirst $suitchar),
- ' | ' . join('',
- $_->{unit} ? $_->{unit} == .5 ? '½' : $_->{unit} : ' ',
- defined $_->{organic} && sprintf(
- '%s',
- $_->{organic} ? 'o' : 'u',
- $_->{organic} ? 'organic' : 'mechanic',
- $_->{organic} ? 'o' : 'm',
- ),
+ !$suitchar ? ' | ' : sprintf(' | %s%s',
+ $suitchar, ucfirst $suitchar,
+ $_->{attr}->{massive}
+ && 'â',
+ ),
+ ' | ' . (
+ defined $_->{unit} && $_->{unit} == .5 ? '½' : $_->{unit}
+ ),
+ ' | ' . join('', grep { $_ }
+ (defined $_->{organic} ? !$_->{organic} : $_->{attr}->{mech})
+ && 'm',
+ ($_->{organic} || $_->{attr}->{organic})
+ && 'o',
+ $_->{attr}->{psionic}
+ && 'Ï',
),
- ' | ' . $_->{hp},
- ' | ' . (
- $_->{shield} ? sprintf('%.0f%%', 100 * $_->{shield} / $_->{hp}) : ' '
+ ' | ' . join('', grep { $_ }
+ $_->{attr}->{armored}
+ && 'A',
+ $_->{attr}->{light}
+ && 'L',
),
- ' | ' . showrange($_, 'armor'),
- showattack($_, 'ground'),
- showattack($_, 'air'),
- ' | ' . showrange($_, 'attack', 'range'),
+ ' | ' . $_->{hp} // '',
+ $_->{shield} ? sprintf(' | %.0f%% | {shield} / $_->{hp}
+ ) : ' | ' .
+ showrange($_->{armor}, $_->{upgraded}->{armor}),
+ showattack($_, 0),
+ ' | ' .
+ showrange(map { $_->{attack}->[0]->{range} } $_, $_->{upgraded}),
' | ' . sprintf(
$_->{detect} ? '%s' : '%s',
- showrange($_, 'sight')
+ showrange($_->{sight}, $_->{upgraded}->{sight})
),
- ' | ' . showrange($_, 'speed'),
+ ' | ' .
+ showrange($_->{speed}, $_->{upgraded}->{speed}),
+ $_->{attr}->{jump}
+ && qq'â',
+ $_->{attr}->{flying}
+ && qq'â',
' | ' . showmagic($_),
+ !$_->{attack}->[1] ? () : (
+ ' | ', showattack($_, 1), ' | '
+ ),
"\n"
);
+ }
+
+ my $grouped = 1; # race headers
+ if (exists $get{order}) {
+ $grouped = 0;
+ $get{order} ||= '';
+ if ($get{order} eq 'size') {
+ $_->{order} = (
+ $_->{unit}*16 + ($_->{size} // $_->{suit}) + $_->{cargo}/8
+ + $_->{hp}/512 + $_->{min}/8192
+ ) for @$units;
+ }
+ elsif ($get{order} eq 'cost') {
+ $_->{order} = (
+ $_->{gas}*1.5 + $_->{min} + $_->{unit}/8 + $_->{build}/256/8
+ ) for @$units;
+ }
+ elsif ($get{order} eq 'attack') {
+ $_->{order} = $_->{hp} / 1024 + $_->{shield} / 1008 + max(
+ map {
+ ((map { ref $_ ? $_->[-1] : $_ } $_->{damage})[0])
+ * ($_->{count} // 1) / ($_->{cooldown} // 1)
+ * ($_->{splash} ? 1.01 : 1)
+ * ($_->{type} eq 'implosive' ? .96 : 1)
+ * ($_->{type} eq 'explosive' ? .98 : 1)
+ } @{ $_->{attack} }
+ ) for @$units;
+ }
+ else {
+ $units->[$_]->{order} = $_ for 0 .. $#$units;
+ }
+ }
+ my @rows = @{$units};
+ @rows = sort {$a->{order} <=> $b->{order}} @rows unless $grouped;
+
+ my ($race, $cat) = ('', '');
+ for (@rows) {
+ if ($grouped) {
+ printf ' |
%s'."\n",
+ $race = $_->{race}, ucfirst $race
+ unless $race eq $_->{race};
+ }
+ else {
+ $_->{cat} = $_->{race};
+ }
+
+ print(
+ ' |
---|
',
+ '', $cat ne $_->{cat} && ($cat = $_->{cat}),
+ ' | ', $_->{name},
+ showunitcols($_),
+ );
- for my $alt (grep { $_->{alt} } @{ $_->{special} }) {
+ for my $subrow (@{ $_->{special} }) {
+ $subrow->{alt} or next;
print(
- ' |
| ' . $alt->{alt},
- showattack($alt, 'ground'),
- showattack($alt, 'air'),
- ' | ' . showrange($alt, 'attack', 'range'),
- ' | ' . sprintf(
- $alt->{detect} ? '%s' : '%s',
- showrange($alt, 'sight')
- ),
- ' | ' . showrange($alt, 'speed'),
- ' | ',
- "\n",
+ ' |
| ', $subrow->{alt},
+ showunitcols($subrow),
);
}
}
@@ -339,11 +354,32 @@ sub showrange {
excludes construction of dependencies such as buildings
and +parent units
size
- affected by Small,
- Medium,
- or Large unit damage
+ <:
+if ($scver{major} > 1) {
+ :>transports can fit 8 Small,
+ 4 Medium,
+ 2 Large,
+ or a single Huge unit
+ massive â units
+ cannot be lifted or slowed and can break force fields<:
+} else {
+ :>affected by Small,
+ Medium, or
+ Large unit damage<:
+} :>
number of command points taken per unit
- organic/mechanic unit
+ <:
+if ($scver{major} > 1) {
+ :>received damage depends on
+ organic,
+ mechanic,
+ Ï(ps)ionic,
+ Light, and
+ Armored
+ attributes<:
+} else {
+ :>organic/mechanic unit<:
+} :>
HP
total number of hitpoints (including shields)
shield
@@ -354,17 +390,26 @@ sub showrange {
base unit armor
can be increased by upto 3 at various facilities
each point decreases damage per hit by one, upto a minimum of ½
- reduction applies to initial damage, before size penalties (so a plasma hit of 12 to 4 armor large deals 2 damage, not ½)
-ground/air
- damage done per single attack against ground/air units
- 2nd column indicates relative amount of damage done in
- a certain
- amount of time
- splash damage+ hits nearby objects as well
- explosive damage does only
+ reduction applies to initial damage, before size penalties
+ (so a plasma hit of 12 to 4 armor large deals 2 damage, not ½)
+attack
+ targets â½ ground
+ and/or â³ air
+ damage given per single hit
+ dps indicates relative amount of damage
+ done in 1 second of in-game time
+ splash damage hits all objects nearby +
+ or in a straight line Ã.
+ <:
+if ($scver{major} > 1) {
+ :>does not include ≥bonus damage
+ dealt to susceptible unit types<:
+} else {
+ :>*explosive damage does only
50% damage to small units, 75% to medium, 100% to large
- concussive/plasma damage does
- 25% to large, 50% medium, 100% to small units
+ ~concussive/plasma damage does
+ 25% to large, 50% medium, 100% to small units<:
+} :>
sight
range in which the unit detects other units
emphasis indicates ability to detect cloaked units
@@ -373,7 +418,7 @@ sub showrange {
speed
relative speed of movement (when in full motion, startup speed ignored)
specials
- special abilities
+ special abilities are usually casted manually, but some are always active
parentheses () indicate that it needs to be researched first
hover for description
range is maximum range required to activate
|
---|