Text rewriter in the works (I18N on the table)

#1
Just to be sure no one misses this development, here is a thread announcing that I've in place a system that can rewrite SOM's text just before it's displayed in the game.

With this we can do a lot of things. For one we can use traditional internationalization methods (namely gettext) to make your games translatable into any language without modifying your game after it's produced. For already existing games like DoM/Trismegistus, you can enjoy this by just dropping some dlls and translation files into your game folder (I can implement this immediately btw)

Technically the system is just about as good as it will ever need to be. But I guess the rest of the work will be devising systems to make it easier and easier for everyone to take advantage of (eg. configuration)

Some examples of how I will be using it with my game project are...

A) I want to remove x1 from the inventory lists because it looks tacky and for most items there is only one of them in the game anyway.
B) I wanted all my stats to be single digits but once John worked out the stat formulas it was obvious this would never work. So I ended up multiply all my equip stats by 10, and now I can use the rewriter to chop of the 0s so they will look like single digits again.
C) I have shops setup that are really more like storage. So I had changed the Buy/Sell to be a more generic Take/Give dialog. But now I can recognize when the player is at a proper shop and change it back to Buy/Sell which seems obviously more appropriate.

So yeah, according to C, you can even change text based on what values are in your event counters on the fly. I have a feeling there will be many more instances where this will come in handy for me, and if you take the liberty to really open your mind about all the possibilities this will open up, you just might start to imagine how your own projects could take advantage of such a system.

In the meantime, if anyone wants to integrate this into your project, I will do what I can to help custom program whatever you need for you.

Can I get an amen Twisted
Reply

#2
Crap!

For the past few days I've been thinking something was wrong with the way I was hooking the DrawText/TextOut routines, because it seemed like they were being called twice in a row. I gotta admit I'm a total ditz. I even registered in the Easyhook forums to make sure I was doing things right...

Well!! Turns out SOM was actually drawing a drop shadow under the text. It took me a couple days to realize this (well not like I was thinking about it 24 -- or at all obviously)

I thought maybe I remembered a drop shadow under the dialogue text, which lead me to realize what was up. But it turns out there is actually a drop shadow on the menu text as well. It's just one pixel though, no matter how huge the fonts are, and if you're like me, on a 1920x1200 portable display then you'd just about never notice it.

Anyway, aside from my usual thankless blog style of posting... it's definitely possible to make this drop shadow bigger based on the display resolution or whatever -- or hell change the angle, or take it out for style/performance altogether. Might be an interesting option / add a little pizazz to SOM on modern hardware. Truth is it's really amazing just how nice SOM still holds up on modern hardware. Really it looks just fine on a widescreen HD display. Even in 16bit paletted mode with the trilinear filtering going on. We could even tweak the colour of the text and shadow and probably even the font to a large extent. We could change where text is displayed on the screen if you ever wanted to do a totally custom Menu system. Add pseudo stats etc.


Caveat: One thing that does make text substitution a little more problematic, is the numbers and the text for some reason tend to be displayed separately. So instead of seeing "Fire? 113" or whatever you see "Fire" then several text drawing routines later just " 113". Like I say, it's trickier, but I don't think it would stop you if you really wanted your game to do something. You could also edit the text in the exe at runtime so the print format string adds like a symbol to certain numbers to make them easier to pick out... like how I added % to my HP/MP numbers. You can hexedit the exe to do this. But you can also use the same memory management system I have setup to do this when the game starts up in the loaded program's memory (this way you don't have to vandalize the original exe)

Reply

#3
Pretty nifty... I was able to make my project do everything I wanted it to do with the text output (being the control freak that I am) with just the following code:

Code:
    ? //Mauntstraut 09 HACKING///////////////////////

        LPTSTR out = (LPTSTR)txt; //hack
        
        if(len<5)
        {
            static int percents = 0;

            if(*out=='x') //inventory: x1
            {
                for(LPTSTR p=out+1;*p&&*p==' ';p++);

                if(*p=='1'&&!p[1])
                {
                    *p = ' '; *out = ' ';
                }
            }
            else if(out[len-1]!='%')
            {                
                for(LPTSTR p=out;*p&&*p==' ';p++);

                if(*p>='0'&&*p<='9')
                {
                    for(LPCTSTR q=p;*q&&*q!='.';q++);
                    
                    if(!*q) //without decimal point
                    if(!percents)
                    {
                        for(char carry=' ';p[1];p++) //memmove()
                        {
                            int swap = *p; *p = carry; //easier to do...
                            
                            carry = p[1]; p[1] = swap; //in reverse
                        }
                    }
                    else percents--;
                }
            }
            else percents++;
        }
        else if(len==5) //spell cost maybe...
        {
            for(LPTSTR p=out;*p&&*p==' ';p++);

            if(*p>='0'&&*p<='9')
            {
                for(LPCTSTR q=p;*q&&*q!='.';q++);

                if(!*q) //without decimal point
                while(*p)
                {
                    p[-1] = *p; if(!*++p) p[-1] = '%';
                }
            }
        }

    ? ///////////////////////////////////////////////

Of course the eventual goal is to make rebuilding the "injection" dll as unnecessary as possible. At the least I can make it modular, so you can just rebuild a module just for your game. But making sense of the SOM text stream can be a bit difficult to automate.

In this case for example, I pretty much divided all of the 3 character wide/whole numbers by 10 so to keep the numbers simpler for players (because the 1s place was always 0 anyway)

But the Magic/Strength numbers are also 3 wide/whole, and I didn't want those divided. So the only way I could recognize them was to watch for the HP/MP fields which are pretty flexible, count them by their percent signs (added for this project) and count down from the the number of such occurrences before treating numbers as divisible by 10 (because the two HP/MP fields always come before the Strength/Magic fields)

Still that is automatable (script-able) enough I think, but just an example of the cleverness required.

I stripped out the x1 counters from the inventories. But I think I might rearrange them to be like 2x instead of "x?? 2" ...still not sure what I prefer.

I was even able to add % to the magic cost numbers, which were thankfully not embroiled into the 3 wide formats for some reason.


I think this sort of flexibility is a must for my involvement in a project, so it's good to see these sorts of possibilities opening up.
Reply

#4
Oh hell!

I just had a good idea...

There's no reason to make people think about the way SOM spits out text.

We just need a profiler that resets itself every frame. Which collects all the text, then analyzes it to build a template of what it thinks SOM is showing on the screen (shouldn't be hard at all)

Then we can assign names to all the different fields in the different possible states. Then from there it'll be simple for people to configure the output to their liking. And there wouldn't be any limitations on anything at that point. ‎ 

Did that make sense? Anyway, trust me... it will be very easy to use/setup. And way easier for me to build a configuration system around!!
Reply

#5
OK, so this thing youre working on actually rewrites in game text not necessarily text created in events?

If that is the case, I will definitely need to use this. ‎  I first of all need to rewrite every instance of the word "holy" and have it use "dark" instead.

I can also think of some other areas this would be useful.

To start the game I am going to try to create a 'fist' weapon so when you have nothing equipped it will show a hand attacking (with very low attack). ‎  This should be easy just creating a blank weapon model, but I may have to figure a way to tweak the text in the equipment editor so it doesnt look like anything is equipped...may also want to do this with a default magic that is equipped but doesnt do anything to fix that bug I talked about yesterday.

That reminds me I have yet another bug I need to put on the list, but I will put that in a different post.

Well done on this btw, but how do we all use it ? ‎  5innocent2
- Todd DuFore (DMPDesign)
Site Founder
Reply

#6
Well you do know it's possible to unequip by choosing to equip then choosing No when it asks you to equip or not. So that can present some confusion. The fix I suggested would require being able to make events that would equip items for the player (I'll be working on this) which would mean finding the memory address that represents each equip slot and hopefully being able to write an item number into it in a meaningful way, and have SOM react accordingly (if not further hacks could ensue like adjusting the players parameters for som)

You can make what I call a pseudo-item which I usually name with all caps, like BARE HANDS or NONE or something. Since your game is directly in line with KF, I think it might be better not to introduce something non traditional like fist fights. Even with a scary gauntlet I'm not sure I'd feel safe fighting any of the SOM monsters with my barehands Geno


About replace Holy with Dark, that is of course doable. But it's also something you can very easily do by opening your output .exe into a hexeditor, search for all cases of Holy and just type Dark on top of them and save, voila.

I mean, if that's all you want, I'd do it that way... since John has already overwritten the file gratuitously (that's how he translates it)

Still wouldn't hurt to integrate this "technology" with DD... I think we will easily set something up for you so players could easily help translate DD into any language of their choice. The way this would work in in the english translation file, we'd just translate ?/??(or whatever the original word was) to Dark, and for the Japanese we'd translate it to ?/? (Dark or Unholy or whatever you prefer).

So in other words, before setting this up, I'd like to to translate DD back into the original SOM Japanese. At least for the stuff in the exe. That much is probably as easy as copying over John's exe with the original.


PS: We could probably easily work out a text hack so that after you equip the NONE pseudo items, instead of looking like you're equipped with an item called NONE with stats of 0, it could look in the Menu just like it would if you unequipped your weapon/magic.

PPS: There are a number of enemy magics that look like nothing happened and don't connect to anything. I'd recommend using one of those for the none magic equip. You will still drain your bar if you hit the magic button though. If I can get the controller working through my proxy dll though we can fix that (it's giving me problems)
Reply

#7
(2009-10-16, 06:54 PM)dmpdesign link Wrote: Well done on this btw, but how do we all use it ? ‎  ‎ 5innocent2

Well there will be an elaborate .ini file separate from the one SOM uses. And there will be .po and .mo files for translation purposes.

But for now, you can just ask and I will hardcode whatever you need for your project and send your the files.
Reply

#8
Here is what an ini file will look like:

Quote:;Anything not in a section (delimited by brackets, ie. [])
;Should be named with the section in which it belongs, then
;followed by a period and the key name. This practiced is
;better used sparingly and only for casual testing of values??

[Player]

;This section can assign different ini files per Windows user
;account (instead of this one)

[Remote]

;This section will fetch/merge additional configuration info
;from somewhere on the internet.

[Locale]

;This section is for manually overriding the environment locale
;settings (of your Microsoft Windows enivironment)

[Keymap]

;Each key (named variable) in this section represents a key
;on a keyboard and the corresponding value assigned is the
;key the player must press instead of the original key...

;Sword of Moonlight assigns the following keys to the
;following actions...

;In normal play
;TAB: Enter menu? ? ? ? ?? ;0F
;LCONTROL: Shoot magic? ?? ;1D
;LSHIFT: Swing weapon? ? ? ;2A
;SPACE: Dash/Interact? ? ? ;39
;END: Reset view? ? ? ? ?? ;CF
;PGDN: Look up? ? ? ? ? ?? ;D1 (also known as NEXT)
;DELETE: Look down? ? ? ?? ;D3
;UP: Walk forward? ? ? ? ? ;C8
;LEFT: Turn left? ? ? ? ?? ;CB
;RIGHT: Turn right? ? ? ?? ;CD
;DOWN: Walk backward? ? ?? ;D0
;??: Step left
;??: Step right
?
;In the menu of message dialog
;ENTER: Choose/Choice #1
;ESCAPE: Leave/Choice #2

;Any hexidecimal number or DirectInput code can be used to
;name a key or value. For a complete reference please visit:
;https://www.gamespp.com/directx/directInputKeyboardScanCodes.html
;Or search the WWW for "DirectInput keyboard scan codes"

[Action]

;The Action section assigns action names to keys (like a macro)
;The action names are up to you, and will supercede the names of
;keys during assignment. Actions can be a series of keys as well

Enter_menu = TAB
Shoot_magic = LCONTROL
Swing_weapon = LSHIFT
Dash_or_interact = SPACE
Dash = SPACE
Interact = SPACE
Reset_view = END
Look_up = PGDN
Look_down = DELETE
Walk_forawrd = UP
Turn_left = LEFT
Turn_right = RIGHT
Walk_backward = DOWN
Step_left = ??
Step_right = ??
Select = ENTER
Exit = ESCAPE
Yes = ENTER
No = ESCAPE

[Joypad]

;This section can be used to spoof Sword of Moonlight's keyboard
;inputs, by simulating a keyboard via a Windows "Game Controller"
;you should set hide_controllers_from_som = yes so to avoid any
;conflicts with your Sword of Moonlight game.

hide_controllers_from_som = yes ;SOM will not detect any controllers

joypad_to_use_for_play = 0 ;A number or name with wildcards will do?

;"Analog" stick/button functions

simulate_analog_signals = yes ;throttles look/move keys per frame
?
;Pseudo-Buttons: you can create digital and analog buttons from your
;controller's feature set, such as joystick axes and pov hats. Even
;button combinations. This is necessary because only buttons can
;be used to simulate the keyboard.?
?
pseudo_x_axis = 13
pseudo_y_axis = 14
pseudo_z_axis = 15
pseudo_z_rotation = 16
pseudo_hat_north = 17
pseudo_hat_east = 18
pseudo_hat_south = 19
pseudo_hat_west = 20
?
;Buttons: each button is a number (see: Control Panel->Game Controllers)
;which is assigned to a key values (see: [Keymap] section) or series of
;keys called a macro. Assigned keys should correspond to the keymap!!

1 = Look_down
2 = Enter_menu
3 = Look_up
6 = Interact
7 = Shoot_magic
8 = Swing_weapon
11 = Dash
12 = Reset_view
;Negative/positive numbers have meaning for calibrated analog "buttons"

-13 = Step_left
+13 = Step_right
-14 = Walk_backward
+14 = Walk_forward
-15 = Turn_left
+15 = Turn_right
-16 = Look_down
+16 = Look_up

;Menu buttons are special. They begin with an M

M2 = Select
M3 = Exit
M17 = UP
M18 = RIGHT
M19 = DOWN
M20 = LEFT

;Message buttons begin with a question mark

?17 = Yes
?19 = No

;The following keys can be used for on the fly modification of the
;existing joypad configuration

;flip_button_poles = ;list of analog buttons for which to flip polarity
;swap_button_pairs =? ;list of button pairs for which to swap assignments?

[Joypad1]

;Here you could define another joypad configuration...

[Motion]

;This section lets you simulate keys with a mouse-type devices

[Memmap]

;Changing this section is not advised for players and may
;break your game or very likely constitute cheating.?

[Editor]

;This section is for dynamically rewriting text on the fly before
;it is drawn to the screen for the player to see. Not to be confused
;with translation or menu customization.

[MenuRx]

;This section is for menu customization

[Module]

;Section for modules to be loaded...

;Sections for each module should be named after the loaded module

[System]

;This section should not be edited by anyone

[Config]

;This section (Config) should not be edited by hand!!
;It is reserved for saving the player's menu settings
;per Windows user account.

We will need documentation for all of this stuff on the website somewhere. I mean, documentation can come with the SDK, but it wouldn't be right to include documentation with each game. Still the ini file itself can be a little self documenting with comments.
Reply

#9
PS: I never knew it, but Windows actually has an ini file API builtin to it. The "Registry" was actually designed to replace the ini file system. Though I think the Registry is a pretty sore spot for Microsoft (internally considered to be a bad decision that is)

Anyway, there seems to be a way to basically have binary keys with associated checksums (like with the registry) embedded into the ini file... unless I misread something and that only works for the registry which still uses the ini file API?? Anyway, point is... geez it's late, there is probably a way to convert sections of the ini file into checksummed binary if you want to keep players from having easy access to important sections which would break your game one way or another if goobered with.
Reply





Users browsing this thread:
3 Guest(s)