<(common.inc.plp)><: 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'], }); :>

StarCraft units

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 ); } :> <: sub showrange { my ($row, @elements) = @_; my ($min, $max); my $value = $row; $value = ref $value eq 'HASH' && $value->{$_} or last for @elements; if (ref $value eq 'ARRAY') { $min = $value->[0]; $max = $value->[-1]; } else { $min = $max = $value; } defined $min or return ''; if ($row->{upgrade}) { for (@{ $row->{upgrade} }) { my $increase = $_ or next; $increase = ref $increase eq 'HASH' && $increase->{$_} or last for @elements; $increase = $increase->[-1] if ref $increase eq 'ARRAY'; $max += $increase if $increase; } } if ($elements[0] eq 'attack' and $elements[1] ne 'range' and $elements[2] eq 'cmp') {{ my $type = $row->{$elements[0]}->{$elements[1]}->{type} or next; if ($type eq 'explosive') { $min /= 2; } elsif ($type eq 'implosive') { $min /= 4; } $min = int($min + .5); # round halves up }} return $min == $max ? $min : "$min-$max"; } sub showattack { my ($row, $area) = @_; local $_ = $row->{attack}->{$area}; return '', sprintf('%s', $cat ne $_->{cat} ? ('h', $cat = $_->{cat}) : ('d', ' ')), '
<:= coltoggle('name', '') :> min gas <:= coltoggle(qw'build cost') :> <:= coltoggle(qw'size size') :> HP shield armor ground air range sight speed specials
' unless $_; my $tagbase = ''; my $out = showrange($row, 'attack', $area, 'damage'); $out .= '+' if $_->{splash}; $out .= '' . showrange($row, 'attack', $area, 'cmp'); return $tagbase . $out; } sub showmagic { my ($row) = @_; my $specials = $row->{special} or return ''; return join ' ', map { sprintf '%s', join('', $_->{name}, $_->{desc} ? ": $_->{desc}" : '', $_->{range} ? sprintf(' (%s)', join ', ', "range $_->{range}", # "cost $_->{cost}", ) : '', ), $_->{abbr}, } @$specials; } my $units = do 'sc-units.inc.pl'; 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 + $_->{size} + $_->{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; my $sizechar = [qw/? s m l/]->[$_->{size}]; print( '
' . $_->{name}, '' . ($_->{min} || '0'), '' . ($_->{gas} || ''), '' . sprintf('%.0f', $_->{build} || '0'), sprintf('%s', $sizechar, ucfirst $sizechar), '' . join('', $_->{unit} ? $_->{unit} == .5 ? '½' : $_->{unit} : ' ', defined $_->{organic} && sprintf( '%s', $_->{organic} ? 'o' : 'u', $_->{organic} ? 'organic' : 'mechanic', $_->{organic} ? 'o' : 'm', ), ), '' . $_->{hp}, '' . ($_->{shield} ? $_->{shield}.'%' : ' '), '' . showrange($_, 'armor'), showattack($_, 'ground'), showattack($_, 'air'), '' . showrange($_, 'attack', 'range'), '' . sprintf( $_->{detect} ? '%s' : '%s', showrange($_, 'sight') ), '' . showrange($_, 'speed'), '' . showmagic($_), "\n" ); for my $alt (grep { $_->{alt} } @{ $_->{special} }) { 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", ); } } :>

Legend

cost
minerals+gas required to create one unit
build
relative time needed to create at least one unit
size
Small, Medium, or Large unit damage
number of command points taken per unit
organic/mechanic unit
HP
total number of hitpoints (including shields)
shield
percentage of HP in shields
shields always take full damage, irrelevant of unit size
does not take armor bonuses, but upgrades can decrease damage to any shield hit by upto 3
armor
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 large plasma hit of 12 to 4 armor 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 50% damage to small units, 75% to medium, 100% to large
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
range
maximum range of weapon (note siege tank also has a minimum range)
speed
relative speed of movement (when in full motion, startup speed ignored)
specials
special abilities
parentheses () indicate that it needs to be researched first
hover for description
range is maximum range required to activate
cost is percentage of total energy lost

When two values are given (1-2), second value indicates attribute after all possible upgrades.