Larian Banner: Baldur's Gate Patch 9
Previous Thread
Next Thread
Print Thread
#560715 02/01/15 01:03 AM
Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
With the way that the text currently works in D:OS, it's nearly impossible to output the value of a String variable if you don't already know what is supposed to be in it.


If my character's name was Rhidian and stored within the variable STRING_name, then the following code:

Code
CharacterDisplayText(CHARACTER_Player1, _name);


...would look up "Rhidian" in the TranslatedStringKeys, and output the value listed there. If "Rhidian" isn't a Key in the table, then nothing happens. There's no real way to output information we don't already know.



Which leads to my current WIP workaround, with the aim of allowing developers to output the value of an unknown variable. Now, I'm practically inactive in terms of creating an actual mod, but I'm wanting to throw out this idea to see if it sounds reasonable.

Here's some (untested) Story code:

Code
INIT Section
DB_SingleLetter("A", 1);
DB_SingleLetter("B", 2);
DB_SingleLetter("C", 3);
DB_SingleLetter("D", 4);
DB_SingleLetter("E", 5);
DB_SingleLetter("F", 6);
DB_SingleLetter("G", 7);
DB_SingleLetter("H", 8);
DB_SingleLetter("I", 9);
DB_SingleLetter("J", 10);
DB_SingleLetter("K", 11);
DB_SingleLetter("L", 12);
DB_SingleLetter("M", 13);
DB_SingleLetter("N", 14);
DB_SingleLetter("O", 15);
DB_SingleLetter("P", 16);
DB_SingleLetter("Q", 17);
DB_SingleLetter("R", 18);
DB_SingleLetter("S", 19);
DB_SingleLetter("T", 20);
DB_SingleLetter("U", 21);
DB_SingleLetter("V", 22);
DB_SingleLetter("W", 23);
DB_SingleLetter("X", 24);
DB_SingleLetter("Y", 25);
DB_SingleLetter("Z", 26);



KB Section
//Function to be used elsewhere
PROC
PrintText(STRING_word)
THEN
DB_Forward(1);
DB_Backward(1);
CharacterSetVarString(CHARACTER_Player1, "DebugWord", "");
CharacterSetVarInteger(CHARACTER_Player1, "DebugLetterListIndex", 1);
Proc_FindFrequency(_word, 1);
Proc_GrowForward();
Proc_GrowBackward();




-----
//Find which letters the word contains, and then add to a temp database list

PROC
Proc_FindFrequency(STRING_word, INTEGER_index)
AND
DB_SingleLetter(_char, _index)
AND
IntegerSum(_index, 1, _nextIndex)
THEN
Proc_FindLetter(_word, _char);
Proc_FindFrequency(_word, _nextIndex);

PROC
Proc_FindLetter(STRING_word, STRING_char)
AND
StringContains(_word, _char, _output)
AND
_output > 0
THEN
Proc_AddToLetterList(_char);

PROC
Proc_AddToLetterList(STRING_char)
AND
CharacterGetVarInteger(CHARACTER_Player1, "DebugLetterListIndex", _index)
AND
IntegerSum(_index, 1, _nextIndex)
THEN
DB_TempLetterList(_char, _index);
CharacterSetVarInteger(CHARACTER_Player1, "DebugLetterListIndex", _nextIndex);


-------
//Concatenate letters with a growing word (going forward) and see if the word contains it.


PROC
Proc_GrowForward()
AND
DB_Forward(1)
THEN
NOT DB_Forward(1);
Proc_TestNextLetterForward(1);
Proc_GrowForward();


PROC
Proc_TestNextLetterForward(STRING_Word, INTEGER_index)
AND
NOT DB_Forward(1)
AND
IntegerSum(_index, 1, _nextIndex)
AND
CharacterGetVarString(CHARACTER_Player1, "DebugWord", _currentWord)
AND
DB_TempLetterList(_char, _index)
AND
StringConcatenate(_currentWord, _char, _testWord)
AND
StringContains(_Word, _testWord, _result)
AND
_result > 0
THEN
CharacterSetVarString(CHARACTER_Player1, "DebugWord", _testWord);
Proc_OutputLetter(_char, 1);
DB_Forward(1);

PROC
Proc_TestNextLetterForward(STRING_Word, INTEGER_index)
AND
IntegerSum(_index, 1, _nextIndex)
AND
DB_TempLetterList(_char, _index)
THEN
Proc_TestNextLetterForward(_Word, _nextIndex);



PROC
Proc_GrowBackward()
AND
DB_Backward(1)
THEN
NOT DB_Backward(1);
Proc_TestNextLetterBackward(1);
Proc_GrowBackward();


PROC
Proc_TestNextLetterBackward(STRING_Word, INTEGER_index)
AND
NOT DB_Forward(1)
AND
IntegerSum(_index, 1, _nextIndex)
AND
CharacterGetVarString(CHARACTER_Player1, "DebugWord", _currentWord)
AND
DB_TempLetterList(_char, _index)
AND
StringConcatenate(_char, _currentWord, _testWord)
AND
StringContains(_Word, _testWord, _result)
AND
_result > 0
THEN
CharacterSetVarString(CHARACTER_Player1, "DebugWord", _testWord);
Proc_OutputLetter(_char, 0);
DB_Backward(1);

PROC
Proc_TestNextLetterBackward(STRING_Word, INTEGER_index)
AND
IntegerSum(_index, 1, _nextIndex)
AND
DB_TempLetterList(_char, _index)
THEN
Proc_TestNextLetterBackward(_Word, _nextIndex);



------
PROC
Proc_OutputLetter(STRING_char, INTEGER_dir)
AND
_dir > 0
THEN
CharacterDisplayText(CHARACTER_Player1, _char);


PROC
Proc_OutputLetter(STRING_char, INTEGER_dir)
AND
_dir < 1
THEN
CharacterDisplayText(CHARACTER_Player1, _char);



The idea is fairly simple.
1. Have a Key:Content list in the TranslatedString Keys comprised of the individual letters of the alphabet. IE Key: A, Content: A, etc etc.

2. Find out which letters the word contains and store them in a temp database.

3. Starting with a blank string, continue testing letters by concatenating them and seeing if the actual word contains the result.

4. Repeat #3, but with concatenating in the other direction

5. Output result

Now the code posted above doesn't clean itself up (yet) and probably outputs in an incorrect manner, but the gist of it should be usable (or not, since it's untested).

Consider this:

Say I'm wanting to output my name, "Rhidian", that is located in a String.

First I see what letters are present using StringContains-
Code
A
D
I
H
N
R


Then starting with a blank string, I start concatenating them:
Code
"" + "A" = "A"; Contains? Yes


Code
"A" + "A" = "AA"; Contains? No
"AD" No
"AI" No
"AH" No
"AN" Yes


Code
"AN" + everything; No, so start going backwards

"A" + "AN" = "AAN"; Contains? No
"DAN" No
"IAN" Yes


Code
"AIAN" No
"DIAN" Yes


Etc Etc, until it reconstructs "RHIDIAN".

Joined: Aug 2014
old hand
Offline
old hand
Joined: Aug 2014
This took me a while to get the purpose of, but I think I understand the idea of it now. Say you want to display your character's name, but since there's no way to predict what a player will name their character, there's no way to have a key and translated string prepared for their name. So this produces a translated string from a string.

But what I don't get is how you get the untranslated string (the key) in the code in the first place. Is the player's name stored somewhere automatically? And what if it's something besides a player name? I'm having trouble thinking of other uses for this since naming your character is the one place I can think of that players have control over creating an untranslated string. Unless I'm just seriously missing something obvious.

I still don't quite understand how you figure out what letters are in a string. Is "StringContains" a hardcoded function? If not, where did you define it? Is it operating as a database?

So this is going to represent things in all caps? Or all lower case. Figuring out the case of a letter might be possible, but it would probably take at least double the processing power. Not sure if that would be an issue already. Seems like a lot of actions (testing each letter, concatenating them, etc.), but maybe it's more efficient than I think. And I imagine spaces would be pretty hard to add since " " isn't really a character.

Looks pretty useful though if it works, if only as proof of concept for now. You think the code would be able to display the translated strings into actual dialogs? Script seems pretty limited for dialog imo, so that might not be possible.

Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
StringContains is a hard coded function listed on that big list of Story functions I pulled from the files. My character's name was just an example; what I'm thinking is that the String to debug will come from elsewhere if the developer wants to figure it out.

Consider something like this:
Code
IF
GlobalEventSet(_string)
THEN
PrintText(_string)


When those events fire, I don't know what their name is, but ideally I would be able to output them.

This idea is purely for development; it's only meant to give information to the developer. I don't have a lot of time to actually test it out with the Engine though, which is why I'm posting this in an untested form right now.

I could add characters to find (like caps or non caps) simply by having a Database entry for it at the beginning and a corresponding Key:Content entry in the TranslatedStringKeys. I do need to work out a better output method though.

Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
After fixing the code and plugging it into the Story Editor... nothing was outputted when I tried to print the word "ABSOLUTE".

First, the code I tried:

Code
INIT Section

DB_SingleLetter("A", 1);
DB_SingleLetter("B", 2);
DB_SingleLetter("C", 3);
DB_SingleLetter("D", 4);
DB_SingleLetter("E", 5);
DB_SingleLetter("F", 6);
DB_SingleLetter("G", 7);
DB_SingleLetter("H", 8);
DB_SingleLetter("I", 9);
DB_SingleLetter("J", 10);
DB_SingleLetter("K", 11);
DB_SingleLetter("L", 12);
DB_SingleLetter("M", 13);
DB_SingleLetter("N", 14);
DB_SingleLetter("O", 15);
DB_SingleLetter("P", 16);
DB_SingleLetter("Q", 17);
DB_SingleLetter("R", 18);
DB_SingleLetter("S", 19);
DB_SingleLetter("T", 20);
DB_SingleLetter("U", 21);
DB_SingleLetter("V", 22);
DB_SingleLetter("W", 23);
DB_SingleLetter("X", 24);
DB_SingleLetter("Y", 25);
DB_SingleLetter("Z", 26);


KB Section
IF
DB_CYSDoTutorial(1)
THEN
CharacterLevelUp(CHARACTER_Player1);

IF
CharacterLeveledUp(CHARACTER_Player1)
THEN
PrintText("ABSOLUTE");
CharacterLevelUp(CHARACTER_Player2);

PROC
PrintText((STRING)_word)
THEN
DB_Forward(1);
DB_Backward(1);
CharacterSetVarString(CHARACTER_Player1, "DebugWord", "");
CharacterSetVarInteger(CHARACTER_Player1, "DebugLetterListIndex", 1);
Proc_FindFrequency(_word, 1);
Proc_GrowForward();
Proc_GrowBackward();

PROC
Proc_FindFrequency((STRING)_word, (INTEGER)_index)
AND
DB_SingleLetter(_char, _index)
AND
IntegerSum(_index, 1, _nextIndex)
THEN
Proc_FindLetter(_word, _char);
Proc_FindFrequency(_word, _nextIndex);

PROC
Proc_FindLetter((STRING)_word, (STRING)_char)
AND
StringContains(_word, _char, _output)
AND
_output > 0
THEN
Proc_AddToLetterList(_char);

PROC
Proc_AddToLetterList((STRING)_char)
AND
CharacterGetVarInteger(CHARACTER_Player1, "DebugLetterListIndex", _index)
AND
IntegerSum(_index, 1, _nextIndex)
THEN
DB_TempLetterList(_char, _index);
CharacterSetVarInteger(CHARACTER_Player1, "DebugLetterListIndex", _nextIndex);

PROC
Proc_GrowForward()
AND
DB_Forward(1)
THEN
NOT DB_Forward(1);
Proc_TestNextLetterForward(1);
Proc_GrowForward();


PROC
Proc_TestNextLetterForward((STRING)_word, (INTEGER)_index)
AND
NOT DB_Forward(1)
AND
IntegerSum(_index, 1, _nextIndex)
AND
CharacterGetVarString(CHARACTER_Player1, "DebugWord", _currentWord)
AND
DB_TempLetterList(_char, _index)
AND
StringConcatenate(_currentWord, _char, _testWord)
AND
StringContains(_Word, _testWord, _result)
AND
_result > 0
THEN
CharacterSetVarString(CHARACTER_Player1, "DebugWord", _testWord);
Proc_OutputLetter(_char, 1);
DB_Forward(1);

PROC
Proc_TestNextLetterForward((STRING)_word, (INTEGER)_index)
AND
IntegerSum(_index, 1, _nextIndex)
AND
DB_TempLetterList(_char, _index)
THEN
Proc_TestNextLetterForward(_Word, _nextIndex);



PROC
Proc_GrowBackward()
AND
DB_Backward(1)
THEN
NOT DB_Backward(1);
Proc_TestNextLetterBackward(1);
Proc_GrowBackward();


PROC
Proc_TestNextLetterBackward((STRING)_word, (INTEGER)_index)
AND
NOT DB_Forward(1)
AND
IntegerSum(_index, 1, _nextIndex)
AND
CharacterGetVarString(CHARACTER_Player1, "DebugWord", _currentWord)
AND
DB_TempLetterList(_char, _index)
AND
StringConcatenate(_char, _currentWord, _testWord)
AND
StringContains(_Word, _testWord, _result)
AND
_result > 0
THEN
CharacterSetVarString(CHARACTER_Player1, "DebugWord", _testWord);
Proc_OutputLetter(_char, 0);
DB_Backward(1);

PROC
Proc_TestNextLetterBackward((STRING)_word, (INTEGER)_index)
AND
IntegerSum(_index, 1, _nextIndex)
AND
DB_TempLetterList(_char, _index)
THEN
Proc_TestNextLetterBackward(_Word, _nextIndex);

PROC
Proc_OutputLetter((STRING)_char, (INTEGER)_dir)
AND
_dir > 0
THEN
CharacterDisplayText(CHARACTER_Player1, _char);


PROC
Proc_OutputLetter((STRING)_char, (INTEGER)_dir)
AND
_dir < 1
THEN
CharacterDisplayText(CHARACTER_Player1, _char);



I also found out that the TranslatedStringKey table treats "A" and "a" as the same. I can't have them be separate keys. I'm not sure what happens when I attempt to do lowercase, since I need the uppercase to work first.

Does anyone know of some sort of event I can easily respond to when play-testing within the editor? My current method is inefficient.

Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
I've made some progress with this script. It turns out that I wasn't passing the actual word along to the PROCs that are building up the word letter by letter. I have also figured out that I can just have two TranslatedStringKeys tables; one for upper case and one for lowercase.

Here's the code that I'm working on atm:

Code
INIT Section
DB_SingleLetter("A", 1);
DB_SingleLetter("B", 2);
DB_SingleLetter("C", 3);
DB_SingleLetter("D", 4);
DB_SingleLetter("E", 5);
DB_SingleLetter("F", 6);
DB_SingleLetter("G", 7);
DB_SingleLetter("H", 8);
DB_SingleLetter("I", 9);
DB_SingleLetter("J", 10);
DB_SingleLetter("K", 11);
DB_SingleLetter("L", 12);
DB_SingleLetter("M", 13);
DB_SingleLetter("N", 14);
DB_SingleLetter("O", 15);
DB_SingleLetter("P", 16);
DB_SingleLetter("Q", 17);
DB_SingleLetter("R", 18);
DB_SingleLetter("S", 19);
DB_SingleLetter("T", 20);
DB_SingleLetter("U", 21);
DB_SingleLetter("V", 22);
DB_SingleLetter("W", 23);
DB_SingleLetter("X", 24);
DB_SingleLetter("Y", 25);
DB_SingleLetter("Z", 26);


KB Section
IF
CharacterUsedSkill(_, _, _)
THEN
PrintText("ZONE");
PartyAddExperience(5);
CharacterDisplayText(CHARACTER_Player1, "A");

PROC
PrintText((STRING)_word)
THEN
DB_Forward(1);
DB_Backward(1);
CharacterSetVarString(CHARACTER_Player1, "DebugWord", "");
CharacterSetVarInteger(CHARACTER_Player1, "DebugLetterListIndex", 1);
Proc_FindFrequency(_word, 1);
Proc_GrowForward(_word);
Proc_GrowBackward(_word);

PROC
Proc_FindFrequency((STRING)_word, (INTEGER)_index)
AND
DB_SingleLetter(_char, _index)
AND
IntegerSum(_index, 1, _nextIndex)
THEN
Proc_FindLetter(_word, _char);
Proc_FindFrequency(_word, _nextIndex);

PROC
Proc_FindLetter((STRING)_word, (STRING)_char)
AND
StringContains(_word, _char, _output)
AND
_output > 0
THEN
Proc_AddToLetterList(_char);

PROC
Proc_AddToLetterList((STRING)_char)
AND
CharacterGetVarInteger(CHARACTER_Player1, "DebugLetterListIndex", _index)
AND
IntegerSum(_index, 1, _nextIndex)
THEN
DB_TempLetterList(_char, _index);
CharacterSetVarInteger(CHARACTER_Player1, "DebugLetterListIndex", _nextIndex);

PROC
Proc_GrowForward((STRING)_word)
AND
DB_Forward(1)
THEN
NOT DB_Forward(1);
Proc_TestNextLetterForward(_word, 1);
Proc_GrowForward();



PROC
Proc_TestNextLetterForward((STRING)_word, (INTEGER)_index)
AND
NOT DB_Forward(1)
AND
IntegerSum(_index, 1, _nextIndex)
AND
CharacterGetVarString(CHARACTER_Player1, "DebugWord", _currentWord)
AND
DB_TempLetterList(_char, _index)
AND
StringConcatenate(_currentWord, _char, _testWord)
AND
StringContains(_Word, _testWord, _result)
AND
_result > 0
THEN
CharacterSetVarString(CHARACTER_Player1, "DebugWord", _testWord);
Proc_OutputLetter(_char, 1);
DB_Forward(1);

PROC
Proc_TestNextLetterForward((STRING)_word, (INTEGER)_index)
AND
IntegerSum(_index, 1, _nextIndex)
AND
DB_TempLetterList(_char, _index)
THEN
Proc_TestNextLetterForward(_word, _nextIndex);




PROC
Proc_GrowBackward((STRING)_word)
AND
DB_Backward(1)
THEN
NOT DB_Backward(1);
Proc_TestNextLetterBackward(_word, 1);
Proc_GrowBackward();


PROC
Proc_TestNextLetterBackward((STRING)_word, (INTEGER)_index)
AND
NOT DB_Forward(1)
AND
IntegerSum(_index, 1, _nextIndex)
AND
CharacterGetVarString(CHARACTER_Player1, "DebugWord", _currentWord)
AND
DB_TempLetterList(_char, _index)
AND
StringConcatenate(_char, _currentWord, _testWord)
AND
StringContains(_Word, _testWord, _result)
AND
_result > 0
THEN
CharacterSetVarString(CHARACTER_Player1, "DebugWord", _testWord);
Proc_OutputLetter(_char, 0);
DB_Backward(1);

PROC
Proc_TestNextLetterBackward((STRING)_word, (INTEGER)_index)
AND
IntegerSum(_index, 1, _nextIndex)
AND
DB_TempLetterList(_char, _index)
THEN
Proc_TestNextLetterBackward(_Word, _nextIndex);

PROC
Proc_OutputLetter((STRING)_char, (INTEGER)_dir)
AND
_dir > 0
THEN
CharacterDisplayText(CHARACTER_Player1, _char);


PROC
Proc_OutputLetter((STRING)_char, (INTEGER)_dir)
AND
_dir < 1
THEN
CharacterDisplayText(CHARACTER_Player1, _char);



CharacterUsedSkill is an easy trigger for me to use. The problem though is that it's only outputting the first letter alphabetically within the word (ZONE prints E, ABSOLUTE prints A). It's probably about time that I changed the output functions, but with how it's set up it means that it's only testing the first letter it finds and then stops (since it outputs after a successful test of a letter).

Joined: Oct 2014
B
enthusiast
Offline
enthusiast
B
Joined: Oct 2014
I really wish I could help with this. I haven't really learned when / how / where to use PROCs yet (and as a result I'm sure I have a ton of redundant code). I'm following this though, hoping you find a way to get it working.

Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
After thinking about it a bit more, I think it would be better if I went with some sort of Brute Force method of printing the text. By Brute Force, I mean creating lsb files with every single combination of characters up to a certain length.

The question then would be how can a lsb file be created? Looking at the lsb format on the wiki, I'm not sure what I would need to be putting on the length fields of the file.

Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
I finally came back around to this and after a few hours of coding and testing I now have a functional version of outputting strings letter by letter.


Code
INIT Section
DB_SingleLetter("A", 1);
DB_SingleLetter("B", 2);
DB_SingleLetter("C", 3);
DB_SingleLetter("D", 4);
DB_SingleLetter("E", 5);
DB_SingleLetter("F", 6);
DB_SingleLetter("G", 7);
DB_SingleLetter("H", 8);
DB_SingleLetter("I", 9);
DB_SingleLetter("J", 10);
DB_SingleLetter("K", 11);
DB_SingleLetter("L", 12);
DB_SingleLetter("M", 13);
DB_SingleLetter("N", 14);
DB_SingleLetter("O", 15);
DB_SingleLetter("P", 16);
DB_SingleLetter("Q", 17);
DB_SingleLetter("R", 18);
DB_SingleLetter("S", 19);
DB_SingleLetter("T", 20);
DB_SingleLetter("U", 21);
DB_SingleLetter("V", 22);
DB_SingleLetter("W", 23);
DB_SingleLetter("X", 24);
DB_SingleLetter("Y", 25);
DB_SingleLetter("Z", 26);



KB Section

PROC
StringSplit((STRING)_word)
THEN
StringSplitForward(_word, "", 1, 0);
DisplaySplitResult();
ClearSplitResult();

IF
StringSplitForward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
NOT DB_SingleLetter(_, _int)
THEN
StringSplitBackward(_word, _current, 1, -1);

IF
StringSplitBackward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
NOT DB_SingleLetter(_, _int)
AND
IntegerSum(_counter, 1, _result)
THEN
DB_SplitMin(_result);

IF
StringSplitForward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
DB_SingleLetter(_char, _int)
AND
StringConcatenate(_current, _char, _test)
AND
StringContains(_word, _test, _result)
AND
_result != 0
AND
IntegerSum(_counter, 1, _nextCounter)
THEN
DB_SplitResult(_char, _counter);
StringSplitForward(_word, _test, 1, _nextCounter);

IF
StringSplitForward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
DB_SingleLetter(_char, _int)
AND
StringConcatenate(_current, _char, _test)
AND
StringContains(_word, _test, _result)
AND
_result == 0
AND
IntegerSum(_int, 1, _nextInt)
THEN
StringSplitForward(_word, _current, _nextInt, _counter);


PROC
ClearSplitResult()
AND
DB_SplitResult(_char, _counter)
THEN
NOT DB_SplitResult(_char, _counter);
ClearSplitResult();

PROC
ClearSplitResult()
AND
DB_SplitMin(_min)
THEN
NOT DB_SplitMin(_min);

IF
StringSplitBackward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
DB_SingleLetter(_char, _int)
AND
StringConcatenate(_char, _current, _test)
AND
StringContains(_word, _test, _result)
AND
_result != 0
AND
IntegerSubtract(_counter, 1, _nextCounter)
THEN
DB_SplitResult(_char, _counter);
StringSplitBackward(_word, _test, 1, _nextCounter);

IF
StringSplitBackward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
DB_SingleLetter(_char, _int)
AND
StringConcatenate(_char, _current, _test)
AND
StringContains(_word, _test, _result)
AND
_result == 0
AND
IntegerSum(_int, 1, _nextInt)
THEN
StringSplitBackward(_word, _current, _nextInt, _counter);

IF
DisplaySplitResult()
AND
DB_SplitMin(_start)
THEN
DisplaySplitResult(_start);

IF
DisplaySplitResult((INTEGER)_counter)
AND
DB_SplitResult(_char, _counter)
AND
IntegerSum(_counter, 1, _nextCounter)
THEN
CharacterDisplayText(CHARACTER_FirstCharacter, _char);
DisplaySplitResult(_nextCounter);



CHARACTER_FirstCharacter is the Player character I used in my testing for displaying the result. For each of the single letters there is an entry in the TranslatedStringKeys that matches up.

I also found out that PROC doesn't even need to be used at all for "modder defined" functions.

Edit:
Or I spoke too soon, since it appears that it only works once, after which it doesn't display anything until after the Story is rebuilt/reloaded.

Edit:
Changing the IFs to PROCs fixed the issue. Now I just need to find out what the memory limit is for this, since it's crashing after trying to print a certain length of Strings.

Last edited by Rhidian; 07/03/15 04:08 AM.
Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014

[Linked Image]



This code makes use of Localization files that contain each letter of the alphabet and certain special characters like punctuation.
Code
INIT Section

DB_SingleLetter("A", 1);
DB_SingleLetter("B", 2);
DB_SingleLetter("C", 3);
DB_SingleLetter("D", 4);
DB_SingleLetter("E", 5);
DB_SingleLetter("F", 6);
DB_SingleLetter("G", 7);
DB_SingleLetter("H", 8);
DB_SingleLetter("I", 9);
DB_SingleLetter("J", 10);
DB_SingleLetter("K", 11);
DB_SingleLetter("L", 12);
DB_SingleLetter("M", 13);
DB_SingleLetter("N", 14);
DB_SingleLetter("O", 15);
DB_SingleLetter("P", 16);
DB_SingleLetter("Q", 17);
DB_SingleLetter("R", 18);
DB_SingleLetter("S", 19);
DB_SingleLetter("T", 20);
DB_SingleLetter("U", 21);
DB_SingleLetter("V", 22);
DB_SingleLetter("W", 23);
DB_SingleLetter("X", 24);
DB_SingleLetter("Y", 25);
DB_SingleLetter("Z", 26);

DB_SingleLetter("a",27);
DB_SingleLetter("b",28);
DB_SingleLetter("c",29);
DB_SingleLetter("d",30);
DB_SingleLetter("e",31);
DB_SingleLetter("f",32);
DB_SingleLetter("g",33);
DB_SingleLetter("h",34);
DB_SingleLetter("i",35);
DB_SingleLetter("j",36);
DB_SingleLetter("k",37);
DB_SingleLetter("l",38);
DB_SingleLetter("m",39);
DB_SingleLetter("n",40);
DB_SingleLetter("o",41);
DB_SingleLetter("p",42);
DB_SingleLetter("q",43);
DB_SingleLetter("r",44);
DB_SingleLetter("s",45);
DB_SingleLetter("t",46);
DB_SingleLetter("u",47);
DB_SingleLetter("v",48);
DB_SingleLetter("w",49);
DB_SingleLetter("x",50);
DB_SingleLetter("y",51);
DB_SingleLetter("z",52);

DB_SingleLetter(" ",53);
DB_SingleLetter("1",54);
DB_SingleLetter("2",55);
DB_SingleLetter("3",56);
DB_SingleLetter("4",57);
DB_SingleLetter("5",58);
DB_SingleLetter("6",59);
DB_SingleLetter("7",60);
DB_SingleLetter("8",61);
DB_SingleLetter("9",62);
DB_SingleLetter("0",63);
DB_SingleLetter(".",64);
DB_SingleLetter(",",65);
DB_SingleLetter("?",66);
DB_SingleLetter("!",67);


Code
KB Section

PROC
StringSplit((STRING)_word)
AND
NOT DB_SplitProcessing(1)
THEN
DB_SplitProcessing(1);
StringSplitForward(_word, "", 1, 0);

PROC
StringSplitForward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
NOT DB_SingleLetter(_, _int)
THEN
StringSplitBackward(_word, _current, 1, -1);

PROC
StringSplitBackward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
NOT DB_SingleLetter(_, _int)
AND
IntegerSum(_counter, 1, _result)
THEN
DB_SplitMin(_result);
DisplaySplitResult();


PROC
StringSplitForward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
DB_SingleLetter(_char, _int)
AND
StringConcatenate(_current, _char, _test)
AND
StringContains(_word, _test, _result)
AND
_result != 0
AND
IntegerSum(_counter, 1, _nextCounter)
THEN
DB_SplitResult(_char, _counter);
DB_SplitTempBreak(_word, _test, _nextCounter);
TimerLaunch("SplitForwardBreak", 200);

IF
TimerFinished("SplitForwardBreak")
AND
DB_SplitTempBreak(_word, _test, _nextCounter)
THEN
NOT DB_SplitTempBreak(_word, _test, _nextCounter);
StringSplitForward(_word, _test, 1, _nextCounter);

PROC
StringSplitForward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
DB_SingleLetter(_char, _int)
AND
StringConcatenate(_current, _char, _test)
AND
StringContains(_word, _test, _result)
AND
_result == 0
AND
IntegerSum(_int, 1, _nextInt)
THEN
StringSplitForward(_word, _current, _nextInt, _counter);


PROC
ClearSplitResult()
AND
DB_SplitResult(_char, _counter)
THEN
NOT DB_SplitResult(_char, _counter);
ClearSplitResult();

PROC
ClearSplitMin()
AND
DB_SplitMin(_min)
THEN
NOT DB_SplitMin(_min);
ClearSplitMin();

PROC
StringSplitBackward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
DB_SingleLetter(_char, _int)
AND
StringConcatenate(_char, _current, _test)
AND
StringContains(_word, _test, _result)
AND
_result != 0
AND
IntegerSubtract(_counter, 1, _nextCounter)
THEN
DB_SplitResult(_char, _counter);
DB_SplitTempBreak(_word, _test, _nextCounter);
TimerLaunch("SplitBackwardBreak", 200);

IF
TimerFinished("SplitBackwardBreak")
AND
DB_SplitTempBreak(_word, _test, _nextCounter)
THEN
NOT DB_SplitTempBreak(_word, _test, _nextCounter);
StringSplitBackward(_word, _test, 1, _nextCounter);

PROC
StringSplitBackward((STRING)_word, (STRING)_current, (INTEGER)_int, (INTEGER)_counter)
AND
DB_SingleLetter(_char, _int)
AND
StringConcatenate(_char, _current, _test)
AND
StringContains(_word, _test, _result)
AND
_result == 0
AND
IntegerSum(_int, 1, _nextInt)
THEN
StringSplitBackward(_word, _current, _nextInt, _counter);

PROC
DisplaySplitResult()
AND
DB_SplitMin(_start)
THEN
DisplaySplitResult(_start);

PROC
DisplaySplitResult((INTEGER)_counter)
AND
DB_SplitResult(_char, _counter)
AND
IntegerSum(_counter, 1, _nextCounter)
THEN
CharacterDisplayText(CHARACTER_FirstCharacter, _char);
DB_SplitDisplayBreak(_nextCounter);
TimerLaunch("SplitDisplayBreak", 200);

IF
TimerFinished("SplitDisplayBreak")
AND
DB_SplitDisplayBreak(_nextCounter)
THEN
NOT DB_SplitDisplayBreak(_nextCounter);
DisplaySplitResult(_nextCounter);

PROC
DisplaySplitResult((INTEGER)_counter)
AND
NOT DB_SplitResult(_, _counter)
THEN
ClearSplitResult();
ClearSplitMin();
NOT DB_SplitProcessing(1);



I fixed the memory issue by making the code use timers, such that there is 200 milliseconds between each letter being processed (and between each letter being displayed).

Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
Alright, I have tweaked the code such that there are no timers. It kind of freezes the gameplay while the String is being processed (moreso if it's a big string), but it doesn't crash.

INIT

You can change CHARACTER_Player1 to whichever character you want to be displaying the text.
There needs to be Localization files that have each letter defined as itself.

Code
DB_MainCharacter(CHARACTER_Player1);


DB_SingleLetter("A", 1);
DB_SingleLetter("B", 2);
DB_SingleLetter("C", 3);
DB_SingleLetter("D", 4);
DB_SingleLetter("E", 5);
DB_SingleLetter("F", 6);
DB_SingleLetter("G", 7);
DB_SingleLetter("H", 8);
DB_SingleLetter("I", 9);
DB_SingleLetter("J", 10);
DB_SingleLetter("K", 11);
DB_SingleLetter("L", 12);
DB_SingleLetter("M", 13);
DB_SingleLetter("N", 14);
DB_SingleLetter("O", 15);
DB_SingleLetter("P", 16);
DB_SingleLetter("Q", 17);
DB_SingleLetter("R", 18);
DB_SingleLetter("S", 19);
DB_SingleLetter("T", 20);
DB_SingleLetter("U", 21);
DB_SingleLetter("V", 22);
DB_SingleLetter("W", 23);
DB_SingleLetter("X", 24);
DB_SingleLetter("Y", 25);
DB_SingleLetter("Z", 26);

DB_SingleLetter("a",27);
DB_SingleLetter("b",28);
DB_SingleLetter("c",29);
DB_SingleLetter("d",30);
DB_SingleLetter("e",31);
DB_SingleLetter("f",32);
DB_SingleLetter("g",33);
DB_SingleLetter("h",34);
DB_SingleLetter("i",35);
DB_SingleLetter("j",36);
DB_SingleLetter("k",37);
DB_SingleLetter("l",38);
DB_SingleLetter("m",39);
DB_SingleLetter("n",40);
DB_SingleLetter("o",41);
DB_SingleLetter("p",42);
DB_SingleLetter("q",43);
DB_SingleLetter("r",44);
DB_SingleLetter("s",45);
DB_SingleLetter("t",46);
DB_SingleLetter("u",47);
DB_SingleLetter("v",48);
DB_SingleLetter("w",49);
DB_SingleLetter("x",50);
DB_SingleLetter("y",51);
DB_SingleLetter("z",52);

DB_SingleLetter(" ",53);
DB_SingleLetter("1",54);
DB_SingleLetter("2",55);
DB_SingleLetter("3",56);
DB_SingleLetter("4",57);
DB_SingleLetter("5",58);
DB_SingleLetter("6",59);
DB_SingleLetter("7",60);
DB_SingleLetter("8",61);
DB_SingleLetter("9",62);
DB_SingleLetter("0",63);
DB_SingleLetter(".",64);
DB_SingleLetter(",",65);
DB_SingleLetter("?",66);
DB_SingleLetter("!",67);



KB Section

Code
PROC
StringSplit((STRING)_string)
THEN
ClearResults();
ClearSynchro();
ClearCurrent();
SS_ClearCounter();
SS_Current("");
SS_MinCounter(0);
SS_Forward(_string, 0);
SS_Backward(_string, -1);
DisplayResult();

PROC
DisplayResult()
AND
SS_MinCounter(_counter)
THEN
SS_DisplayResult(_counter);

PROC
SS_DisplayResult((INTEGER)_counter)
AND
DB_MainCharacter(_player)
AND
DB_Result(_str, _counter)
AND
IntegerSum(_counter, 1, _nextCounter)
THEN
CharacterDisplayText(_player, _str);
SS_DisplayResult(_nextCounter);


PROC
ClearResults()
AND
DB_Result(_char, _counter)
THEN
NOT DB_Result(_char, _counter);

PROC
SS_ClearCounter()
AND
SS_MinCounter(_counter)
THEN
NOT SS_MinCounter(_counter);


PROC
ClearSynchro()
AND
SS_Synchro(_val)
THEN
NOT SS_Synchro(_val);

PROC
ClearCurrent()
AND
SS_Current(_str)
THEN
NOT SS_Current(_str);

PROC
SS_Forward((STRING)_string, (INTEGER)_counter)
AND
NOT SS_Synchro(_counter)
AND
DB_SingleLetter(_char, _)
AND
SS_Current(_current)
AND
StringConcatenate(_current, _char, _test)
AND
StringContains(_string, _test, _result)
AND
_result > 0
AND
IntegerSum(_counter, 1, _nextCounter)
AND
DB_MainCharacter(_player)
THEN
SS_Synchro(_counter);
ClearCurrent();
SS_Current(_test);
DB_Result(_char, _counter);
SS_Forward(_string, _nextCounter);


PROC
SS_Backward((STRING)_string, (INTEGER)_counter)
AND
NOT SS_Synchro(_counter)
AND
SS_Current(_current)
AND
DB_SingleLetter(_char, _)
AND
StringConcatenate(_char, _current, _test)
AND
StringContains(_string, _test, _result)
AND
_result > 0
AND
IntegerSubtract(_counter, 1, _nextCounter)
AND
DB_MainCharacter(_player)
THEN
SS_Synchro(_counter);
ClearCurrent();
SS_Current(_test);
DB_Result(_char, _counter);
SS_ClearCounter();
SS_MinCounter(_counter);
SS_Backward(_string, _nextCounter);



Just call the function StringSplit((STRING)_str) and it'll output the String, one letter per line.

--------

I have also created a Utility script that converts Integers into Strings. I'm not completely sure where this could be useful yet, but it works.


Code
INIT

DB_Digit(1, "1");
DB_Digit(2, "2");
DB_Digit(3, "3");
DB_Digit(4, "4");
DB_Digit(5, "5");
DB_Digit(6, "6");
DB_Digit(7, "7");
DB_Digit(8, "8");
DB_Digit(9, "9");
DB_Digit(0, "0");


KB

PROC
ITS_MakeResult((STRING)_val)
THEN
ClearResults();
DB_Result(_val);

PROC
ClearResults()
AND
DB_Result(_val)
THEN
NOT DB_Result(_val);

PROC
IntegerToString((INTEGER)_int)
THEN
ITS_DivideByTen(_int, "");

PROC
ITS_DivideByTen((INTEGER)_int,(STRING)_str)
AND
IntegerDivide(_int, 10, _quot)
AND
_quot < 1
THEN
ITS_GetDigit(_int, _str);

PROC
ITS_DivideByTen((INTEGER)_int,(STRING)_str)
AND
IntegerDivide(_int, 10, _quot)
AND
_quot > 0
AND
IntegerModulo(_int, 10, _ret)
AND
DB_Digit(_ret, _aStr)
AND
StringConcatenate(_aStr, _str, _nStr)
THEN
ITS_DivideByTen(_quot, _nStr);

PROC
ITS_GetDigit((INTEGER)_int, (STRING)_str)
AND
DB_Digit(_int, _ITS)
AND
StringConcatenate(_ITS, _str, _finalString)
THEN
ITS_MakeResult(_finalString);



For this one you need to call IntegerToString((INTEGER)_int), and it will store the result into DB_Result((STRING)_num). I used this code to test it out, for example:

Code
IF
CharacterUsedSkill(CHARACTER_Player1, _, _)
THEN
IntegerToString(9001);
CheckResult();


PROC
CheckResult()
AND
DB_Result("9001")
THEN
PartyAddExperience(9001);



Edit:
You can combine the two scripts to output unknown Integer variables, with the result of the IntegerToString function being passed into the StringSplit function.

Joined: Jun 2013
old hand
Offline
old hand
Joined: Jun 2013
Dunno if you still browse the boards or not, but this INT to STRING is very helpful. Working on this quest where I check the skills of NPCs to simulate the results of battle and this is perfect for debugging it.

I added a DebugBreak to ITS_MakeResult so that it prints out the result in the message box.

Also helpful in creating my Day/Night cycle.

Originally Posted by Rhidian


I have also created a Utility script that converts Integers into Strings. I'm not completely sure where this could be useful yet, but it works.


Code
INIT

DB_Digit(1, "1");
DB_Digit(2, "2");
DB_Digit(3, "3");
DB_Digit(4, "4");
DB_Digit(5, "5");
DB_Digit(6, "6");
DB_Digit(7, "7");
DB_Digit(8, "8");
DB_Digit(9, "9");
DB_Digit(0, "0");


KB

PROC
ITS_MakeResult((STRING)_val)
THEN
ClearResults();
DB_Result(_val);

PROC
ClearResults()
AND
DB_Result(_val)
THEN
NOT DB_Result(_val);

PROC
IntegerToString((INTEGER)_int)
THEN
ITS_DivideByTen(_int, "");

PROC
ITS_DivideByTen((INTEGER)_int,(STRING)_str)
AND
IntegerDivide(_int, 10, _quot)
AND
_quot < 1
THEN
ITS_GetDigit(_int, _str);

PROC
ITS_DivideByTen((INTEGER)_int,(STRING)_str)
AND
IntegerDivide(_int, 10, _quot)
AND
_quot > 0
AND
IntegerModulo(_int, 10, _ret)
AND
DB_Digit(_ret, _aStr)
AND
StringConcatenate(_aStr, _str, _nStr)
THEN
ITS_DivideByTen(_quot, _nStr);

PROC
ITS_GetDigit((INTEGER)_int, (STRING)_str)
AND
DB_Digit(_int, _ITS)
AND
StringConcatenate(_ITS, _str, _finalString)
THEN
ITS_MakeResult(_finalString);



For this one you need to call IntegerToString((INTEGER)_int), and it will store the result into DB_Result((STRING)_num). I used this code to test it out, for example:


Link Copied to Clipboard
Powered by UBB.threads™ PHP Forum Software 7.7.5