(common.inc.plp)><: my $datafile = 'sc-units.inc.pl'; if ($ENV{PATH_INFO} and $ENV{PATH_INFO} eq '/2') { $datafile = 'sc2-units.inc.pl'; } Html({ title => 'starcraft unit cheat sheet', version => 'v1.0', description => [ 'Reference of StarCraft unit properties,' . ' comparing various statistics of all the units in Brood War' . ' including costs, damage, defense, speed, ranges, and abilities.', ], keywords => [qw' starcraft game unit statistics stats comparison table sheet cheat reference software attributes properties '], stylesheet => [qw'light'], data => [$datafile], }); :>
Unit properties as seen or measured in Brood War version≥1.08.
<: sub coltoggle { my ($name, $id) = @_; return sprintf( (defined $get{order} ? $get{order} eq $id : !$id) ? '%2$s ▼' : '%s', $id && "order=$id", $name ); } :><:= coltoggle('name', '') :> | <:= coltoggle(qw'build cost') :> | <:= coltoggle(qw'size size') :> | HP | shield | armor | ground | air | range | sight | speed | specials | ' unless $attack; my $tagbase = ' | '; my $out = showrange($row, 'attack', $area, 'damage'); $out .= '+' if $attack->{splash}; $attack->{dps} = $attack->{cooldown} && [ map { 24 * $_ / $attack->{cooldown} * ($attack->{count} // 1) } map { ref $_ ? @{$_} : $_ } $attack->{damage} #TODO: upgrade (zergling) ]; $out .= ' | ' . showrange($row, 'attack', $area, 'dps'); return $tagbase . $out; } sub showmagic { my ($row) = @_; my $specials = $row->{special} or return ''; return join ' ', map { sprintf '%s', $_->{duration} < 0 && ' class="magic-perma"', join('', $_->{name}, $_->{desc} ? ": $_->{desc}" : '', $_->{range} || $_->{cost} ? sprintf(' (%s)', join ', ', $_->{range} ? "range $_->{range}" : (), $_->{cost} ? sprintf('cost %.0f%%', 100 * $_->{cost} / $row->{energy} ) : (), ) : '', ), sprintf($_->{build} ? '(%s)' : '%s', $_->{abbr}), } grep { defined $_->{abbr} } @{$specials}; } sub showunitcols { my ($row) = @_; local $_ = $row; $_->{hp} += $_->{shield} if $_->{shield}; my $suitchar = ''; if ($_->{suit}) { $suitchar = [qw/? s m l/]->[$_->{suit}]; } return ( ' | ' . ($_->{min} // ''), ' | ' . ($_->{gas} || ''), !defined $_->{build} ? ' | ' : sprintf(' | %s%.0f', !!$_->{base} && '+', $_->{build} || '0', ), !$suitchar ? ' | ' : sprintf(' | %s', $suitchar, ucfirst $suitchar), ' | ' . join('', defined $_->{unit} && $_->{unit} == .5 ? '½' : $_->{unit}, defined $_->{organic} && sprintf( '%s', $_->{organic} ? 'o' : 'u', $_->{organic} ? 'organic' : 'mechanic', $_->{organic} ? 'o' : 'm', ), ), ' | ' . $_->{hp} // '', ' | ' . ( $_->{shield} ? sprintf('%.0f%%', 100 * $_->{shield} / $_->{hp}) : ' ' ), ' | ' . showrange($_, 'armor'), showattack($_, 'ground'), showattack($_, 'air'), ' | ' . showrange($_, 'attack', 'range'), ' | ' . sprintf( $_->{detect} ? '%s' : '%s', showrange($_, 'sight') ), ' | ' . showrange($_, 'speed'), ' | ' . showmagic($_), "\n" ); } my $units = do $datafile; die "Cannot open unit data: $_\n" for $@ || $! || (); my $grouped = !exists $get{order}; if (exists $get{order}) { $get{order} ||= ''; if ($get{order} eq 'size') { $_->{order} = $_->{unit}*8 + $_->{suit} + $_->{hp}/512 + $_->{min}/8192 for @$units; } elsif ($get{order} eq 'cost') { $_->{order} = $_->{gas}*1.5 + $_->{min} + $_->{unit}/8 + $_->{build}/256/8 for @$units; } else { $units->[$_]->{order} = $_ for 0 .. $#$units; } } my @rows = $grouped ? @$units : sort {$a->{order} <=> $b->{order}} @$units; my ($race, $cat) = ('', ''); for (@rows) { $race = $_->{race}, printf ' |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
%s'."\n", $race, ucfirst $race if $grouped and $race ne $_->{race}; $_->{cat} = $_->{race} if not $grouped; print( ' | |||||||||||||||||
' . $_->{name}, showunitcols($_), ); for my $alt (grep { $_->{alt} } @{ $_->{special} }) { print( ' | |||||||||||||||||
' . $alt->{alt}, showunitcols($alt), ); } } :> |
When two values are given (1-2), second value indicates attribute after all possible upgrades.