X-Git-Url: http://git.shiar.nl/sheet.git/blobdiff_plain/bd7288335390bc941dde7a1ad728bc0000d8386a..f5e90028e202fa9055c1e092cfe8219cbb1678f9:/sc.plp
diff --git a/sc.plp b/sc.plp
index 873c75b..3ebc4f1 100644
--- a/sc.plp
+++ b/sc.plp
@@ -1,146 +1,53 @@
<(common.inc.plp)><:
+my %scver = (
+ id => 'bw',
+ name => 'Brood War',
+ title => 'starcraft',
+ game => 'StarCraft',
+ major => 1,
+);
+
+if ($ENV{PATH_INFO} and $ENV{PATH_INFO} eq '/2') {
+ %scver = (
+ id => 'hots',
+ name => 'Heart of the Swarm',
+ title => 'starcraft2',
+ game => 'StarCraft II',
+ major => 2,
+ );
+}
+my $datafile = "sc-units-$scver{id}.inc.pl";
+
Html({
- title => 'starcraft unit cheat sheet',
- version => 'v1.0',
+ title => "$scver{title} unit cheat sheet",
+ version => 'v1.1',
description => [
- 'Reference of StarCraft unit properties,'
- . ' comparing various statistics of all the units in Brood War'
+ "Reference of $scver{game} unit properties,"
+ . " comparing various statistics of all the units in $scver{name}"
. ' including costs, damage, defense, speed, ranges, and abilities.',
],
- keywords => [qw'
+ keywords => [
+ qw'
starcraft game unit statistics stats comparison table sheet cheat
reference software attributes properties
- '],
+ ',
+ $scver{major} < 2 ? qw' bw broodwar brood war ' : qw' starcraft2 hots ',
+ ],
stylesheet => [qw'light'],
+ raw => ' ',
+ data => [$datafile],
});
-:>
-
StarCraft units
-
-
-Unit properties as seen or measured in Brood War
-versionâ¥1.08 .
-
-
-
+print "Unit properties as seen or measured in $scver{name}\n$patch.\n
\n\n";
-<:
sub coltoggle {
my ($name, $id) = @_;
return sprintf(
@@ -156,12 +63,14 @@ sub coltoggle {
<:= coltoggle(qw'build cost') :>
- <:= coltoggle(qw'size size') :>
+ <:= coltoggle(qw'size size') :>
HP
shield
- armor
- ground
- air
+ â¨
+ ground
+ dps
+ air
+ dps
range
sight
speed
@@ -169,6 +78,12 @@ sub coltoggle {
<:
sub showrange {
+ my ($min, $max) = @_;
+ $_ = int($_ + .5) for $min, $max; # round halves up
+ return $min == $max ? $min : "$min-$max";
+}
+
+sub showval {
my ($row, @elements) = @_;
my ($min, $max);
@@ -192,8 +107,10 @@ sub showrange {
}
}
- 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 ($elements[0] eq 'attack' and $elements[1] ne 'range' and $elements[2] eq 'dps') {{
+ my $attack = $row->{ $elements[0] }->{ $elements[1] };
+ ref $attack or $attack = $row->{ $elements[0] }->{$attack}; # follow
+ my $type = $attack->{type} or next;
if ($type eq 'explosive') {
$min /= 2;
}
@@ -201,31 +118,42 @@ sub showrange {
$min /= 4;
}
}}
- $_ = int($_ + .5) for $min, $max; # round halves up
-
- return $min == $max ? $min : "$min-$max";
+ return showrange($min, $max);
}
sub showattack {
my ($row, $area) = @_;
- local $_ = $row->{attack}->{$area};
+ my $attack = $row->{attack}->{$area};
+ if (not ref $attack) {
+ # reference to another area
+ $area = $attack;
+ $attack = $row->{attack}->{$area};
+ }
- return '' unless $_;
+ return ' ' unless $attack;
my $tagbase = ' ';
- my $out = showrange($row, 'attack', $area, 'damage');
- $out .= '+ ' if $_->{splash};
- $out .= ' ' . showrange($row, 'attack', $area, 'cmp');
+ my $out = showval($row, 'attack', $area, 'damage');
+ $out .= sprintf('%s ',
+ $attack->{splash} eq 'line' ? ('linear', 'Ã') : ('splash', '+')
+ ) if $attack->{splash};
+ $attack->{dps} = $attack->{cooldown} && [
+ map { $_ / $attack->{cooldown} * ($attack->{count} // 1) }
+ map { ref $_ ? @{$_} : $_ }
+ $attack->{damage}
+ #TODO: upgrade (zergling)
+ ];
+ $out .= ' ' . showval($row, 'attack', $area, 'dps');
return $tagbase . $out;
}
@@ -233,23 +161,103 @@ sub showrange {
my ($row) = @_;
my $specials = $row->{special} or return '';
return join ' ', map {
- sprintf '%s ',
+ sprintf '%s ',
+ $_->{duration} < 0 && ' class="magic-perma"',
join('',
$_->{name},
$_->{desc} ? ": $_->{desc}" : '',
- $_->{range} ? sprintf(' (%s)', join ', ',
- "range $_->{range}",
-# "cost $_->{cost}",
+ $_->{range} || $_->{cost} ? sprintf(' (%s)', join ', ',
+ $_->{range} ? "range $_->{range}" : (),
+ $_->{cost} ? sprintf('cost %.0f%%%s',
+ 100 * $_->{cost} / $row->{energy},
+ defined $_->{maint} && sprintf('+%.1f%%/s',
+ 100 * $_->{maint} / $row->{energy},
+ ),
+ ) : (),
) : '',
),
- $_->{abbr},
- } @$specials;
+ sprintf($_->{build} ? '(%s)' : '%s', $_->{abbr}),
+ } grep { defined $_->{abbr} } @{$specials};
}
- my $units = do 'sc-units.inc.pl';
- die "Cannot open unit data: $_\n" for $@ || $! || ();
- my $grouped = !exists $get{order};
+ sub showunitcols {
+ my ($row) = @_;
+ local $_ = $row;
+ $_->{hp} += $_->{shield} if $_->{shield};
+ my $suitchar = '';
+ if ($_->{attr}->{structure}) {
+ $suitchar = 'b';
+ }
+ elsif ($_->{suit}) {
+ $suitchar = [qw/? s m l/]->[$_->{suit}];
+ }
+ elsif ($_->{cargo} > 0) {
+ $suitchar = [qw/? s m l l h h h h/]->[abs $_->{cargo}];
+ }
+ elsif ($_->{size}) {
+ $suitchar = [qw/s m l h h h/]->[$_->{size}];
+ }
+ elsif ($_->{attr} and $_->{attr}->{light}) {
+ $suitchar = 's';
+ }
+ elsif ($_->{attr} and $_->{attr}->{armored}) {
+ $suitchar = 'l';
+ }
+
+ return (
+ ' ' . ($_->{min} // ''),
+ ' ' . ($_->{gas} || ''),
+ !defined $_->{build} ? ' ' : sprintf(' %s%.0f',
+ !!$_->{base} && '+ ',
+ $_->{build} || '0',
+ ),
+ !$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}
+ && 'Ï ',
+ ),
+ ' ' . join('', grep { $_ }
+ $_->{attr}->{armored}
+ && 'A ',
+ $_->{attr}->{light}
+ && 'L ',
+ ),
+ ' ' . $_->{hp} // '',
+ $_->{shield} ? sprintf(' %.0f%% {shield} / $_->{hp}
+ ) : ' ' . showval($_, 'armor'),
+ showattack($_, 'ground'),
+ showattack($_, 'air'),
+ ' ' . showval($_, 'attack', 'range'),
+ ' ' . sprintf(
+ $_->{detect} ? '%s ' : '%s',
+ showval($_, 'sight')
+ ),
+ ' ' . showval($_, 'speed'),
+ $_->{attr}->{jump}
+ && qq'â ',
+ $_->{attr}->{flying}
+ && qq'â ',
+ ' ' . showmagic($_),
+ "\n"
+ );
+ }
+
+ my $grouped = 1; # race headers
if (exists $get{order}) {
+ $grouped = 0;
$get{order} ||= '';
if ($get{order} eq 'size') {
$_->{order} = $_->{unit}*8 + $_->{suit} + $_->{hp}/512 + $_->{min}/8192 for @$units;
@@ -261,63 +269,32 @@ sub showrange {
$units->[$_]->{order} = $_ for 0 .. $#$units;
}
}
- my @rows = $grouped ? @$units : sort {$a->{order} <=> $b->{order}} @$units;
+ my @rows = @{$units};
+ @rows = sort {$a->{order} <=> $b->{order}} @rows unless $grouped;
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 $suitchar = [qw/? s m l/]->[$_->{suit}];
+ if ($grouped) {
+ printf '%s '."\n",
+ $race = $_->{race}, ucfirst $race
+ unless $race eq $_->{race};
+ }
+ else {
+ $_->{cat} = $_->{race};
+ }
+
print(
'',
- sprintf('%s', $cat ne $_->{cat} ? ('h', $cat = $_->{cat}) : ('d', ' ')),
- '' . $_->{name},
- ' ' . ($_->{min} || '0'),
- ' ' . ($_->{gas} || ''),
- 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',
- ),
- ),
- ' ' . $_->{hp},
- ' ' . ($_->{shield} ? $_->{shield}.'%' : ' '),
- ' ' . showrange($_, 'armor'),
- showattack($_, 'ground'),
- showattack($_, 'air'),
- ' ' . showrange($_, 'attack', 'range'),
- ' ' . sprintf(
- $_->{detect} ? '%s ' : '%s',
- showrange($_, 'sight')
- ),
- ' ' . showrange($_, 'speed'),
- ' ' . showmagic($_),
- "\n"
+ ' ', $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),
);
}
}
@@ -336,11 +313,32 @@ sub showrange {
excludes construction of dependencies such as buildings
and + parent units
size
- affected by S mall,
- M edium,
- or L arge unit damage
+ <:
+if ($scver{major} > 1) {
+ :>transports can fit 8 S mall,
+ 4 M edium,
+ 2 L arge,
+ or a single H uge unit
+ massive â units
+ cannot be lifted or slowed and can break force fields<:
+} else {
+ :>affected by S mall,
+ M edium, or
+ L arge unit damage<:
+} :>
number of command points taken per unit
- o rganic/m echanic unit
+ <:
+if ($scver{major} > 1) {
+ :>received damage depends on
+ o rganic,
+ m echanic,
+ Ï (ps)ionic,
+ L ight, and
+ A rmored
+ attributes<:
+} else {
+ :>o rganic/m echanic unit<:
+} :>
HP
total number of hitpoints (including shields)
shield
@@ -355,9 +353,9 @@ sub showrange {
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
+ 1 second of fastest game time
+ splash damage hits all objects nearby +
+ or in a straight line à .
explosive damage does only
50% damage to small units, 75% to medium, 100% to large
concussive/plasma damage does
@@ -370,7 +368,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