1 package Data::StarCraft::Replay;
29 0x09 => "Science Vessel",
32 0x0C => "Battlecruiser",
54 0x32 => "Infested Terran",
59 0x3D => "Dark Templar",
65 0x43 => "High Templar",
78 0x6A => "Command Center",
80 0x6C => "Nuclear Silo",
81 0x6D => "Supply Depot",
82 0x6E => "Refinery", # refinery?
84 0x70 => "Academy", # Academy?
87 0x73 => "Control Tower",
88 0x74 => "Science Facility",
90 0x76 => "Physics Lab",
92 0x78 => "Machine Shop",
94 0x7A => "Engineering Bay",
96 0x7C => "Missile Turret",
99 0x82 => "Infested CC",
103 0x86 => "Nydus Canal",
104 0x87 => "Hydralisk Den",
105 0x88 => "Defiler Mound",
106 0x89 => "Greater Spire",
107 0x8A => "Queens Nest",
108 0x8B => "Evolution Chamber",
109 0x8C => "Ultralisk Cavern",
111 0x8E => "Spawning Pool",
112 0x8F => "Creep Colony",
113 0x90 => "Spore Colony",
115 0x92 => "Sunken Colony",
121 0x9B => "Robotics Facility",
123 0x9D => "Assimilator",
125 0x9F => "Observatory",
128 0xA2 => "Photon Cannon",
129 0xA3 => "Citadel of Adun",
130 0xA4 => "Cybernetics Core",
131 0xA5 => "Templar Archives",
135 0xA9 => "Fleet Beacon",
136 0xAA => "Arbiter Tribunal",
137 0xAB => "Robotics Support Bay",
138 0xAC => "Shield Battery",
142 0xC2 => "Dark Archon",
145 0xC5 => "Interceptor",
146 0xC6 => "Interceptor/Scarab",
149 "Terran Infantry Armor",
150 "Terran Vehicle Plating",
151 "Terran Ship Plating",
153 "Zerg Flyer Carapace",
154 "Protoss Ground Armor",
156 "Terran Infantry Weapons",
157 "Terran Vehicle Weapons",
158 "Terran Ship Weapons",
159 "Zerg Melee Attacks",
160 "Zerg Missile Attacks",
161 "Zerg Flyer Attacks",
162 "Protoss Ground Weapons",
163 "Protoss Air Weapons",
164 "Protoss Plasma Shields",
166 "U-238 Shells (Marine Range)",
167 "Ion Thrusters (Vulture Speed)",
169 "Titan Reactor (Science Vessel Energy)",
170 "Ocular Implants (Ghost Sight)",
171 "Moebius Reactor (Ghost Energy)",
172 "Apollo Reactor (Wraith Energy)",
173 "Colossus Reactor (Battle Cruiser Energy)",
174 "Ventral Sacs (Overlord Transport)",
175 "Antennae (Overlord Sight)",
176 "Pneumatized Carapace (Overlord Speed)",
177 "Metabolic Boost (Zergling Speed)",
178 "Adrenal Glands (Zergling Attack)",
179 "Muscular Augments (Hydralisk Speed)",
180 "Grooved Spines (Hydralisk Range)",
181 "Gamete Meiosis (Queen Energy)",
184 "Singularity Charge (Dragoon Range)",
185 "Leg Enhancement (Zealot Speed)",
188 "Gravitic Drive (Shuttle Speed)",
189 "Sensor Array (Observer Sight)",
190 "Gravitic Booster (Observer Speed)",
191 "Khaydarin Amulet (Templar Energy)",
192 "Apial Sensors (Scout Sight)",
193 "Gravitic Thrusters (Scout Speed)",
195 "Khaydarin Core (Arbiter Energy)",
198 "Argus Jewel (Corsair Energy)",
201 "Argus Talisman (Dark Archon Energy)",
202 "Caduceus Reactor (Medic Energy)",
203 "Chitinous Plating (Ultralisk Armor)",
204 "Anabolic Synthesis (Ultralisk Speed)",
205 "Charon Boosters (Goliath Range)",
217 "Cloaking Field (wraith)",
218 "Personal Cloaking (ghost)",
246 0x02 => "Unallowed Move?",
247 0x06 => "Force move",
250 0x0E => "Attack Move",
251 0x13 => "Failed Casting (?)",
255 0x27 => "Clear Rally",
262 0x77 => "Dark Swarm",
264 0x79 => "Spawn Broodling",
266 0x7E => "Launch Nuke",
268 0x8B => "ComSat Scan",
269 0x8D => "Defense Matrix",
270 0x8E => "Psionic Storm",
276 0x94 => "Hallucination",
280 0xB5 => "Disruption Web",
281 0xB6 => "Mind Control",
283 0xB9 => "Optic Flare",
289 0x09 => ["select", 1, 2 | CMD_REPEAT],
290 0x0A => ["add", 1, 2 | CMD_REPEAT],
291 0x0B => ["deselect", 1, 2 | CMD_REPEAT],
292 0x0C => ["build", 1, \%build, 2, 2, 2, \%unit],
293 0x0D => ["vision", 2],
294 0x0E => ["ally", 2, 2],
295 0x13 => ["hotkey", 1, [qw"assign select"], 1],
296 0x14 => ["move", 2, 2, 2, 2, 1], # 1 = queued?
297 0x15 => ["action", 2, 2, 2, 2, 1, \%action, 1, [qw"normal queued"]],
299 0x19 => ["cancel hatch"],
301 # 0x1B => ["move-thing??"], # tim: after hotkey (unit, reaver??) select; soon after reselected and moved
302 0x1E => ["return cargo", 1],
303 0x1F => ["train", 2, \%unit],
304 0x20 => ["cancel train", 2], # == 254
305 0x21 => ["cloak", 1],
306 0x22 => ["decloak", 1],
307 0x23 => ["hatch", 2, \%unit],
308 0x25 => ["unsiege", 1],
309 0x26 => ["siege", 1],
310 0x27 => ["arm", 0], # scarab/interceptor
311 0x28 => ["unload all", 1],
312 0x29 => ["unload", 2],
313 0x2A => ["merge archon", 0],
314 0x2B => ["hold position", 1],
315 0x2C => ["burrow", 1],
316 0x2D => ["unburrow", 1],
317 0x2E => ["cancel nuke", 0],
318 0x2F => ["lift", 2, 2],
319 0x30 => ["research", 1, \@research],
320 0x31 => ["cancel research", 0],
321 0x32 => ["upgrade", 1, \@upgrade],
322 # 0x33 => ["forge-thing??"], # right after forge select: probably unpowered, iirc cancel research
323 0x35 => ["morph", 2, \%unit],
325 0x57 => ["part", 1, {qw"1 quit 6 drop"}],
326 0x5A => ["merge dark archon", 0],
336 my ($fh, $size, $seek) = @_;
337 seek *$fh, $seek, 0 if $seek;
338 read(*$fh, my $in, $size) eq $size or return undef;
346 while (not eof $file) {
347 local $_ = $self->_read($file, 5)
348 and my ($time, $size) = unpack "VC", $_
349 or die "Couldn't read time block head\n";
350 local $_ = $self->_read($file, $size)
351 and my @block = unpack "C*", $_
352 or die "Couldn't read time block data\n";
354 my $player = shift @block;
355 my $cmd = shift @block;
356 if (not defined $cmdread{$cmd}) {
357 warn sprintf "command #%X not defined: %d bytes ignored\n",
359 push @$self, [$time, $player, "??? $cmd"] if $SHOWWARN;
364 my ($data, $byte) = @_;
365 my $out = shift @$data;
366 if (($byte & 3) == 2) {
367 @$data ? ($out += shift(@$data) << 8)
368 : warn "high byte not present\n";
373 my @format = @{ $cmdread{$cmd} };
374 my $desc = shift @format;
376 for my $bit (@format) {
378 if (ref $bit eq "ARRAY") {
379 $data[-1] = defined $bit->[$data[-1]] ? $bit->[$data[-1]]
382 $data[-1] = defined $bit->{$data[-1]} ? $bit->{$data[-1]}
388 if ($bit & CMD_REPEAT) {
389 push @data, readbyte(\@block, $bit) for 1 .. shift @data;
391 push @data, readbyte(\@block, $bit);
394 $desc eq "move" and $data[2] == 0 and $desc = "rally";
395 push @$self, [$time, $player, $desc, @data];