Destro
2nd Lieutenant
Also, I forgot to mention, in terms of the KM issue. I've noticed that there are two buffers that hold the onscreen text in WC1 as well. Buffer1 is mostly used but Buffer2 is used randomly for in-flight coms and some other things. Then reused for flight speed.Time flies when you're having fun I guess, seems only yesterday that I saw the front page post about someone playing with this, and it turns out that it's 3 years later and now there is a working port of the sega-cd speech into Kilrathi Saga!
First up, this is incredible - I've only played a little bit, but I love it! Inspired and curious about how it was working - I decided to take a look at how hard a similar scripting exercise would be for WC2 (I know that EmuMusicFan did some sterling analysis on doing this the 'proper' way by modding the game files). I've managed to identify the memory address where onscreen text is printed during cutscenes and where the game stores the playercharacter names (oddly it stores them twice, once for the savegame, and once for the cutscenes, which will be relevant later...)
From that, I managed to whip up a quick prototype WC2 script file that does what I need here, but identified a couple of issues with the engine/scripting logic (at least as I understand it) as it stands:
Firstly, WC2 uses the same memory address for the cutscene text, as it uses for the 'distance to target' during flight. That means that the console gets spammed during flight, and that the script will be parsed to some degree almost continually during gameplay (which seems to be causing performance impacts).
Logically, I can use the HasWord function in Destro's scripting to check for this - if the string contains ' km' then we can skip the rest of the script - but that doesn't help for the ' m' case. Destro, would it be possible to have an 'EndsWith' string test (without the code I can't be sure, but I don't think there is one)?
Secondly, in the scripting I had real issues with the string replacement - specifically in wanting to check for the below example from the 1st mission debriefing:
If|String|[String.Buffer1]|=|No, I'm not. That patrol scared me, s{[String.Name]}
For those curious, these are the memory addresses I have found so far:
0x0049345E - Mission Series (1-12) - updated during flight and on game-load - indicates Last (current) Mission flown
0x00493460 - Mission Number (0-3) - updated during flight and on game-load - indicates Last (current) Mission flown
0x00499EF8 - Player callsign
0x00499F10 - Player surname
0x00499F28 - Player firstname
0x005D1C41 - Cutscene text - Technically the address is 0x005D1C40 but both CheatEngine and the peek seem to fail to spot this as a string most of the time - using 0x005D1C41 just means that you chop off the first character. This is also the distance to current target counter address during spaceflight.
0x005D3C10 - Mission Letter (e.g. A/B/C/D) - updated during flight - updated during flight (not on game load) - indicates last (current) mission flown
0x005D3C41 - Mission Series Name (e.g. Gwynedd/Niven/Ghorah Khar)- updated during flight - updated during flight (not on game load) - indicates last (current) mission flown
0x0A33A1C1 - During spoken cutscenes this address, or one near it gets the original dos text - it can move though.
I remedied this a bit by creating a string state check.. This checks the data and compares it to the data previously in the string. If the data is the same, the String state is 0. If there is a change to the content, it's a 1.
//|Check the Buffers|
Peek|[Peek.WC1]|PeekAtString|[PEEK_ADDRESS_1]|[String.Buffer1]|
Peek|[Peek.WC1]|PeekAtString|[PEEK_ADDRESS_2]|[String.Buffer2]|
//|Check the string states for a change in data|
String|[String.Buffer1]|State|[Num.CheckState1]|
String|[String.Buffer2]|State|[Num.CheckState2]|
//|Add the two numbers together (Into [Num.CheckState1])|
Num|[Num.CheckState1]|N+|[Num.CheckState2]|
//|If they both equal 0. No change in the text. Break current script and script 0|
If|Num|[Num.CheckState1]|=|0|
BreakScriptZero|
BreakScriptCurrent|
EndIf|
This helps a lot so you are not reading and comparing every singe cycle. If there is no change to the string, it breaks the loop. Having an EndsWith will improve things a lot, but the above helps. At least with WC1 it only updates every few seconds rather than every millisecond. Again, I'm not sure how often WC2 updates the speed so this might not be that helpful.
Cheers.