Big "yes" vote. The effort you put into this is evident and the "value added" commentary lua script really enhances the art of TASing. I have never read so fast in my life ;p
Just want to report that following these instructions, the movie synced perfectly on Win7 x64 for me. I think Hourglass is pretty incredible considering how young it is, and how insanely complex Windows game emulation must be. Hats off to the coder(s)!
Finish Master w/o Continue => ??? (I don't think it's been done. Master 3/9!!!)
It has been done. There are a handful of people with 9999 play points - no death, no warp runs. sdkess has even done it with all four characters! The only thing that changes is the dialog in the ending scene.
I'm still debating on whether or not to take the hit from Blade Man save time. I'd like to finish with Mr. Perfect and maximum lives so I really don't want to suffer damage or a death. Maybe I can find a find a faster way to the middle that doesn't take damage.
It sounds as if your two goals are conflicting. If they aren't yet, they will later in the run. You need to decide which goal has the higher priority. All of the site's megaman TASes take damage to save time (all of which I'm aware that is), and it doesn't bother me seeing megaman take damage because I know it's the fastest way to pass a particular area. Just some food for thought.
Completely agree. I like the realtime goal for that reason as well.
Thanks for the updates on your route planning. It's interesting to me to hear about that stuff.
Making a wiimote TAS plugin is certainly isn't trivial, but storing the data should be.
The accelerometer is well documented, and the movie file should just store the data with the same resolution (bits) as is used natively with padding if necessary for byte alignment.
I wouldn't worry about the Wii Motion Plus for now; I suggest the devs just work on getting all the wiimote and nunchuk data in the movie files.
The first duty of every speedrunner is to the speed - whether realtime speed, or in-game speed, or absolute speed. It is the guiding principle on which TASvideos is based, and if you can't find it within yourself to stand up and be as fast as possible, then you don't deserve to wear that uniform!
Am I the only one who got this awesome reference? Well done, sir! ^_^
I'd like to propose you shoot for real time, not in-game time. It's purely opinion, but I think that manipulating an in-game timer is about as esoteric as any other in-game variable. Speed is very simple to define in real terms for TASes: time length of the input file.
Nice job antd.
If the new emu version fixes a lot of problems, I hope the developers will help you sync your work with the new version - that's a lot of movie you already have done and it would be a shame to have to redo all that work.
Yep, Lua is great fun. Unlike other scripting, the fun for me with this comes from applying the interesting memory addresses you've found. I feel like an international spy when I have the ram search window open.
Sorry to resurrect the thread, but I wanted to post a lua script I just made here in case anyone playing dd2 would find it useful. It puts health bars on top of the enemies that are color coded to help you determine how to kill them quickly. I'm practicing for a speedrun.
Here's a short video of it in action:
Link to video
And here's the script itself:
Language: lua
-- Double Dragon II enemy health meter bars by Andypro
-- Helpful for speedrunning practice.
--
-- Red bars represent a "knee" amount of damage (30)
-- Orange bars represent an uppercut (20)
-- Yellow bars represent a spin kick (15)
-- Green bars represent a jump kick (8)
-- Blue bars represent a punch (4)
--
-- For instance, if an enemy has two red bars followed by a green bar, you know the fastest way to defeat
-- him is to knee him twice and then jump kick him. Obviously any enemy with no red bars will die from a single knee attack.
local function box(x1, y1, x2, y2, color)
if(x1 > 0 and x1 < 255 and x2 > 0 and x2 < 255 and y1 > 0 and y1 < 241 and y2 > 0 and y2 < 241) then
gui.drawbox(x1, y1, x2, y2, color);
end;
end;
-- Draw a life bar given a position and an integer life value
local function DrawLifeBar(x, y, life)
local lifeSegment = life;
local drawYPos = 0;
local Xstart = x-6;
local Ystart = y-44;
local Xend = x+4;
local Yend = y-40;
local Color = { Red = "#ff0000aa", Orange = "#FF9933aa", Yellow = "#ffdd00aa", Green = "#00ff00aa", Blue = "#0000ffaa" };
local chosenColor;
-- Progressively draw the heaviest to lightest bars moving upwards. Therefore the top health bar
-- is the one that is being "worked on" by the player.
while(lifeSegment > 0) do
if(lifeSegment >= 30) then
chosenColor = Color.Red;
lifeSegment = lifeSegment - 30;
elseif(lifeSegment >= 20) then
chosenColor = Color.Orange;
lifeSegment = lifeSegment - 20;
elseif(lifeSegment >= 15) then
chosenColor = Color.Yellow;
lifeSegment = lifeSegment - 15;
elseif(lifeSegment >= 8) then
chosenColor = Color.Green;
lifeSegment = lifeSegment - 8;
else
chosenColor = Color.Blue;
lifeSegment = lifeSegment - 4;
end;
box(Xstart, Ystart, Xend, Yend, chosenColor);
Ystart = Ystart - 4;
Yend = Yend - 4;
end;
end;
-- Calculates the positions of Billy and the enemies and draws
-- the health information. Adding Jimmy to this function should be trivial.
local function DrawHealthInfo()
-- Player 1 memory values
-- 77, d1d0, 880
-- 240 - 92, b6 8ad, 8d3 8d2
local HPp1 = memory.readbyte(0x41e)
local player1x = memory.readbyte(0x077) - (memory.readbyte(0x0D0) + (memory.readbyte(0x0D1) * 255)) + (memory.readbyte(0x880) * 255)
local player1y = 240 - memory.readbyte(0x092) - (memory.readbyte(0x8AD) + (memory.readbyte(0x0B6) * 255)) + (memory.readbyte(0x8D2) + (memory.readbyte(0x8D3) * 255))
if(HPp1 > 0) then
gui.text(player1x, player1y-8, HPp1)
end;
-- Enemy 1 memory values
-- X: 79, d5 d4, 882
-- Y: 240 - 94, xx 8af, 8d7 8d6
local HP1 = memory.readbyte(0x420)
local enemy1x = memory.readbyte(0x079) - (memory.readbyte(0x0D4) + (memory.readbyte(0x0D5) * 255)) + (memory.readbyte(0x882) * 255)
local enemy1y = 240 - memory.readbyte(0x094) - (memory.readbyte(0x8af) + (memory.readbyte(0x0B6) * 255)) + (memory.readbyte(0x8D6) + (memory.readbyte(0x8D7) * 255))
if(HP1 > 0) then
DrawLifeBar(enemy1x, enemy1y-8, HP1);
end;
-- Enemy 2 memory values
-- X: 7A, d9 d8, 883
-- Y: 240 - 95, xx 8b0, 8db 8da
local HP2 = memory.readbyte(0x421)
local enemy2x = memory.readbyte(0x07a) - (memory.readbyte(0x0D8) + (memory.readbyte(0x0D9) * 255)) + (memory.readbyte(0x883) * 255)
local enemy2y = 240 - memory.readbyte(0x095) - (memory.readbyte(0x8b0) + (memory.readbyte(0x0B6) * 255)) + (memory.readbyte(0x8da) + (memory.readbyte(0x8db) * 255))
if(HP2 > 0) then
DrawLifeBar(enemy2x, enemy2y-8, HP2);
end;
end;
gui.register(DrawHealthInfo) -- Register our draw routine so it is drawn on every frame
I believe that's not an emulator problem but rather is caused by the circumstances of the game. Sometimes they shoot fireballs and sometimes they do not.
I don't really know, I'm just speculating. Hopefully a developer will shed some light on your issue.
At least you found out how to make your movie sync!
That's quite strange. It sounds as if the emulator is doing something very bad by relying that the state's filename matches the rom's. I assume your rom is named identically to the state that works for you?
Tuppenfall: I think it's very safe to assume that he has heard your request, evaluated it, and decided not to comply. No need to continue asking.
antd: Glad you've been making progress. I was surprised to see you do the entire wall market cross-dressing scene. What exactly do you gain from the guy picking Cloud? I assume you timed whether it would be faster just to skip the optional items? Keep up the good work.