|
-
G1/G2 Simple dialogs font change and color change
Hello folks,
I've been working on a feature, that would allow anyone to simply change font and color of each and every dialog option. Easiest way possible which came to my mind was to handle this directly with dialog description itself.
Here is an example on how to use it in dialogs:
Code:
INSTANCE DIA_TestDialog_Orange (C_Info) {
description = "f@font_15_white.tga fs@font_old_20_white.tga h@FF8000 hs@FFB266 Orange !";
};
Script will 'scan' dialog description for modifiers:"f@" fontname "fs@" fontname for selected option
"h@" color
"hs@" color for selected option
"al@" align text left
"ac@" align text center
"ar@" align text right
"a@" dialog will be enabled for answers (it will work as input field)
"s@spinnerID" dialog will be enables as a spinner
If any of these modifiers is found, script will extract font names + color hex codes and will apply them in dialog choice box.
Dialog in this example will apply font f@ 'font_15_white.tga' and dark orange color h@ 'FF8000' for greyed out option + hs@ 'font_old_20_white.tga' and light orange color hs@ 'FFB266' for selected option:
[Bild: GM-Dialog-Choice-01.png]
How can this be useful?
Well, visualisation is always useful
In my mod I have implemented in G1 a different method of Pickpocketing - one that is triggered via dialog option.
(https://forum.worldofplayers.de/foru...1#post26129042)
With my new pickpocketing system there is no punishment for player - you can either steal 1 item from NPC if your dexterity > NPCs dexterity or you can't steal anything.
If you don't have enough dexterity points - dialog option will be orange (and will tell you how much points you are missing).
If you have enough dexterity points - option will be green:
[Bild: GM-Dialog-Choice-02.png]
Within DIA_PickPocket condition function DIA_PickPocket_Condition I am changing description and color as I want:
(in this case I am not touching font type - only applying new colors to default font)
Code:
const string DIALOG_PICKPOCKET = "(pickpocketing)";
INSTANCE DIA_PickPocket (C_Info) {
nr = 787;
condition = DIA_PickPocket_Condition;
};
FUNC INT DIA_PickPocket_Condition () {
var string newDescription; newDescription = "";
//Adjust description
if (self.attribute [ATR_DEXTERITY] <= hero.attribute [ATR_DEXTERITY])
{
//Cocatenate green color with DIALOG_PICKPOCKET string
newDescription = ConcatStrings ("h@00CC66 hs@66FFB2 ", DIALOG_PICKPOCKET);
} else {
var int delta;
delta = self.attribute [ATR_DEXTERITY] - hero.attribute [ATR_DEXTERITY];
newDescription = ConcatStrings (DIALOG_PICKPOCKET, " ");
newDescription = ConcatStrings (newDescription, IntToString (delta));
//Cocatenate orange color with DIALOG_PICKPOCKET string
newDescription = ConcatStrings ("h@FF8000 hs@FFB266 ", newDescription);
};
DIA_PickPocket.description = newDescription;
...
};
Hook _HOOK_INFORMATIONMANAGER_UPDATE below is able to work with both dialog instances and dialog choices (those added via Info_ClearChoices + Info_AddChoice).
I tested it with Gothic 1 using both LeGo 2.5.1 and Ikarus 1.2.2 (might be it will work properly with older versions as well)
I am not sure about Gothic 2 compatibility - somebody will have to test it.
Requirements:
- Ikarus 1.2.2
- LeGo 2.5.1
- ScriptBin packages (because of hex2dec function):
Couple of notes:
I hooked oCInformationManager__Update to get dialog choices updated - but most likely there is a better address at which this hook function can be run (I am not using IDA, so I am quite limited!)
edit: this is fixed now:
(At the moment for a split second you can see dialogs in their full format - for example "f#font_15_white.tga fs#font_old_20_white.tga c#FF8000 cs#FFB266 Orange !".)
edit2:
I had to add back condition if (dlg.IsActivated == 1) - Gothic crashed occasionally without it. Also fixed calculation for STR_SubStr - which was raising:
MEM_WARN('STR_SubStr: The end of the desired substring exceeds the end of the string.') + 21 bytes
edit3:
Function oCInfoManager_GetInfo replaced with oCInfoManager_GetInfoUnimportant - to skip important dialogs.
edit4:
New feature 'Answers' added - basically giving user input field, into which an answer can be written.
edit5:
New feature 'Spinner' added - allowing you increase/decrease value of global variable 'InfoManagerSpinnerValue'.
edit6:
Text alignment added + Answer and spinner indicators.
The way the code is written - it is important to keep these modifiers in exact order as shown below - otherwise script will not work properly (you can omit any of them, but order should not change):
"f@", "fs@", "h@", "hs@", "al@", "ac@", "ar@", "a@", "s@spinnerID".
Modifiers have to be separated with space.
Color code which I have demonstrated - example h@00CC66 is containing RGB translated to hex code. But actually you can use R G B A h@00CC6660 and therefore play around with transparency of the text:
[Bild: GM-Dialog-Choice-03.png]
Code:
Code:
//G1 standard dialog - white color FFFFFF
const string InfoManagerDefaultDialogColorSelected = "FFFFFF";
//G1 standard dialog - grey color C8C8C8
const string InfoManagerDefaultColorDialogGrey = "C8C8C8";
//0 - left, 1 - center, 2 - center
const int InfoManagerDefaultDialogAlignment = 0;
//Dialog 'Answers'
var int InfoManagerAnswerPossible;
var int InfoManagerAnswerMode;
var string InfoManagerAnswer;
//Dialog 'Spiners'
var int InfoManagerSpinnerPossible;
var int InfoManagerSpinnerValue;
var string InfoManagerSpinnerID;
var int InfoManagerSpinnerPageSize; //Page Up/Page Down
var int InfoManagerSpinnerValueMin; //Home
var int InfoManagerSpinnerValueMax; //End
//Variables used for elimination of unnecessary code runs
var int InfoManagerLastChoiceSelected;
var int InfoManagerUpdateState;
const int cIM2BChanged = 0;
const int cIMChanged = 1;
//No idea where I got these class definition from :( most likely from Lehona :)
//(this was a dark era of me collecting different snippets of code and putting them to one ugly text file without any links to original source)
class zCViewText2 {
var int validcolor; // bool //0
var int remove; // bool //4
var int posx; // zCPosition //8
var int posy; // zCPosition //12
var int timer; //zREAL //übrige Zeit für PrintScreen anzeigen die nur eine bestimmte Zeit dauern? //16
var string text; //zstring //Die Entscheidende Eigenschaft. //20
var int alphaFunc; //24
var int font; //zCFont* //28
var int color; //zCOLOR //32
var int alpha; //zBOOL //36
var int useAlpha; //zBOOL //40
};
class zCViewDialogChoice {
var int _vtbl; //0
var int refctr; //4
var int hashindex; //8
var int next; //12
/*
Seems like at u16 there is actually a string! which was so far completely empty
var int u16; //16 //zString_vtbl = 8193768;
var int u20; //20
var int u24; //24
var int u28; //28
var int u32; //32
*/
var string uString;
var int _zCViewBase_vtbl; //36
var int vposx; //int //40
var int vposy; //int //44
var int vsizex; //int //48
var int vsizey; //int //52
//Aber auch "echt" Pixelpositionen
var int pposx; //int //56
var int pposy; //int //60
var int psizex; //int //64
var int psizey; //int //68
var int key; //72
var int parent; //76
// Childs
//zList <zCView> childs
var int childs_compare; //(*Compare)(zCView *ele1,zCView *ele2) // 80
var int childs_count; //int //84
var int childs_last; //zCView* //88
var int childs_wurzel; //zCView* //92
//var int alphafunc; //96
var int backTex; //zCTexture* //96
var int color; //100
var int alpha; //104
//zVEC2 TexturePosition [2]; // probably UV coords on texture
var int texPos_0[2]; // 108,112
var int texPos_1[2]; // 116,120
var int isOpen; //zBOOL //124
var int isClosed; //zBOOL //128
// time elapse during open/close, better not modify
var int timeOpen; //zREAL //132
var int timeClose; //zREAL //136
// duration open/close takes to finish
var int durOpen; //zREAL //140
var int durClose; //zREAL //144
/*
enum zTViewFX: {
VIEW_FX_NONE = 0,
VIEW_FX_ZOOM = 1,
VIEW_FX_FADE = VIEW_FX_ZOOM << 1,
VIEW_FX_BOUNCE = VIEW_FX_FADE << 1,
VIEW_FX_FORCE_DWORD = 0xffffffff
}*/
var int fxOpen; //zTViewFX //148
var int fxClose; //zTViewFX //152
//zVEC2 TextureOffset[2]; // offset to be added to texture coordinates
var int texOffset_0[2]; // 156,160
var int texOffset_1[2]; // 164,168
//typedef zCArray< zCViewText2* > zCListViewText;
var int m_listLines_array; //zstring* //172
var int m_listLines_numAlloc; //int //176
var int m_listLines_numInArray;//int //180
/*enum zEViewAlignment
{
VIEW_ALIGN_NONE ,
VIEW_ALIGN_MAX ,
VIEW_ALIGN_MIN ,
VIEW_ALIGN_CENTER
}
var int algin //zTViewAlign;*/
/*
enum zTRnd_AlphaBlendFunc { zRND_ALPHA_FUNC_MAT_DEFAULT,
zRND_ALPHA_FUNC_NONE,
zRND_ALPHA_FUNC_BLEND,
zRND_ALPHA_FUNC_ADD,
zRND_ALPHA_FUNC_SUB,
zRND_ALPHA_FUNC_MUL,
zRND_ALPHA_FUNC_MUL2,
zRND_ALPHA_FUNC_TEST,
zRND_ALPHA_FUNC_BLEND_TEST
}; */
var int alphaFunc; // 184
var int font; //188
var int fontColor; //zCOLOR b, g, r, a //192
var int fontAlpha; //int //196
var int u200; //200
var int cursorx; //204
var int cursory; //208
var int offsetTextpx; //212
var int offsetTextpy; //216
var int sizeMargin_0[2]; // 220,224
var int sizeMargin_1[2]; // 228,232
var int event; //236
var int IsDone; //zBOOL //240
var int IsActivated; //zBOOL //244
var int ColorSelected; //zCOLOR //248
var int ColorGrayed; //zCOLOR //252
var int ChoiceSelected; //256
var int Choices; //260
var int LineStart; //264
var int u268; //268
var int u272; //272
var int u276; //276
};
instance zCViewText2@ (zCViewText2);
var int InfoManagerSpinnerIndicator;
var int InfoManagerAnswerIndicator;
/***
Function will return specific instance of displayed dialog option
***/
/*
FUNC INT oCInfoManager_GetInfo (var int npcInstance, var int herInstance, var int index) //oCInfo *
{
//00664E50 .text Debug data ?GetInfo@oCInfoManager@@QAEPAVoCInfo@@PAVoCNpc@@0H@Z
const int oCInfoManager__GetInfo_G1 = 6704720;
//0x00702D60 public: class oCInfo * __thiscall oCInfoManager::GetInfo(class oCNpc *,class oCNpc *,int)
const int oCInfoManager__GetInfo_G2 = 7351648;
var int oCInfoManager__GetInfo;
oCInfoManager__GetInfo = MEMINT_SwitchG1G2(oCInfoManager__GetInfo_G1, oCInfoManager__GetInfo_G2);
var oCNpc slf; slf = Hlp_GetNpc (npcInstance);
var oCNpc her; Her = Hlp_GetNpc (herInstance);
CALL_IntParam (index);
CALL_PtrParam (MEM_InstToPtr (slf));
CALL_PtrParam (MEM_InstToPtr (Her));
CALL__thiscall (MEM_Game.infoman, oCInfoManager__GetInfo);
return CALL_RetValAsPtr();
};
*/
FUNC INT oCInfoManager_GetInfoUnimportant (var int npcInstance, var int herInstance, var int index) //oCInfo *
{
//00665120 .text Debug data ?GetInfoUnimportant@oCInfoManager@@QAEPAVoCInfo@@PAVoCNpc@@0H@Z
const int oCInfoManager__GetInfoUnimportant_G1 = 6705440;
//0x00703030 public: class oCInfo * __thiscall oCInfoManager::GetInfoUnimportant(class oCNpc *,class oCNpc *,int)
const int oCInfoManager__GetInfoUnimportant_G2 = 7352368;
var int oCInfoManager__GetInfoUnimportant;
oCInfoManager__GetInfoUnimportant = MEMINT_SwitchG1G2(oCInfoManager__GetInfoUnimportant_G1, oCInfoManager__GetInfoUnimportant_G2);
var oCNpc slf; slf = Hlp_GetNpc (npcInstance);
var oCNpc her; Her = Hlp_GetNpc (herInstance);
CALL_IntParam (index);
CALL_PtrParam (MEM_InstToPtr (slf));
CALL_PtrParam (MEM_InstToPtr (Her));
CALL__thiscall (MEM_Game.infoman, oCInfoManager__GetInfoUnimportant);
return CALL_RetValAsPtr();
};
/* R G B A
FF FF FF FF */
FUNC INT HEX2RGBA (var string hex)
{
var int R; R = 255;
var int G; G = 255;
var int B; B = 255;
var int A; A = 255;
if (STR_Len(hex) > 1) { R = hex2dec (STR_SubStr (hex, 0, 2)); };
if (STR_Len(hex) > 3) { G = hex2dec (STR_SubStr (hex, 2, 2)); };
if (STR_Len(hex) > 5) { B = hex2dec (STR_SubStr (hex, 4, 2)); };
if (STR_Len(hex) > 7) { A = hex2dec (STR_SubStr (hex, 6, 2)); };
return RGBA (R, G, B, A);
};
//0072BE90 .text Debug data ?Update@oCInformationManager@@QAIXXZ
const int oCInformationManager__Update_G1 = 7519888;
//0x00660BB0 public: void __fastcall oCInformationManager::Update(void)
const int oCInformationManager__Update_G2 = 6687664;
//00758A60 .text Debug data ?HandleEvent@zCViewDialogChoice@@UAEHH@Z
const int zCViewDialogChoice__HandleEvent_G1 = 7703136;
//0x0068EBA0 public: virtual int __thiscall zCViewDialogChoice::HandleEvent(int)
const int zCViewDialogChoice__HandleEvent_G2 = 6876064;
FUNC VOID _HOOK_VIEWDIALOGCHOICE_HANDLEEVENT ()
{
//'Refresh' dialogs (in case that there is just 1 dialog choice)
InfoManagerUpdateState = cIM2BChanged;
var int key; key = EDI;
var int cancel; cancel = FALSE;
//Work with input only in case InfoManager is waiting for an input
if (MEM_InformationMan.IsWaitingForSelection) {
//--- Answers -->
//InfoManagerAnswerPossible is set by _HOOK_INFORMATIONMANAGER_UPDATE
if (InfoManagerAnswerPossible)
{
//Cancel answer mode
if (key == KEY_ESCAPE) {
InfoManagerAnswerMode = FALSE;
InfoManagerAnswer = "";
};
//Enter answer mode / confirm answer
if (key == KEY_RETURN) {
//If answer mode was not enabled
if (!InfoManagerAnswerMode) {
//Reset answer
InfoManagerAnswer = "";
};
//on/off
InfoManagerAnswerMode = !InfoManagerAnswerMode;
};
var string s; s = "";
if (InfoManagerAnswerMode) {
var int shift;
shift = (MEM_KeyState (KEY_LSHIFT) == KEY_PRESSED) | (MEM_KeyState (KEY_LSHIFT) == KEY_HOLD) | (MEM_KeyState (KEY_RSHIFT) == KEY_PRESSED) | (MEM_KeyState (KEY_RSHIFT) == KEY_HOLD);
if (key == KEY_1) { if (shift) { s = "!"; } else { s = "1"; }; };
if (key == KEY_2) { if (shift) { s = "@"; } else { s = "2"; }; };
if (key == KEY_3) { if (shift) { s = "#"; } else { s = "3"; }; };
if (key == KEY_4) { if (shift) { s = "$"; } else { s = "4"; }; };
if (key == KEY_5) { if (shift) { s = "%"; } else { s = "5"; }; };
if (key == KEY_6) { if (shift) { s = "^"; } else { s = "6"; }; };
if (key == KEY_7) { if (shift) { s = "&"; } else { s = "7"; }; };
if (key == KEY_8) { if (shift) { s = "*"; } else { s = "8"; }; };
if (key == KEY_9) { if (shift) { s = "("; } else { s = "9"; }; };
if (key == KEY_0) { if (shift) { s = ")"; } else { s = "0"; }; };
if (key == KEY_MINUS) { if (shift) { s = "-"; } else { s = "_"; }; };
if (key == KEY_EQUALS) { if (shift) { s = "+"; } else { s = "="; }; };
//Backspace
if (key == KEY_BACK) {
var int len;
len = STR_Len (InfoManagerAnswer);
if (len == 1) {
InfoManagerAnswer = "";
} else
if (len > 1) {
InfoManagerAnswer = STR_SubStr (InfoManagerAnswer, 0, len - 1);
};
};
if (key == KEY_Q) { if (shift) { s = "Q"; } else { s = "q"; }; };
if (key == KEY_W) { if (shift) { s = "W"; } else { s = "w"; }; };
if (key == KEY_E) { if (shift) { s = "E"; } else { s = "e"; }; };
if (key == KEY_R) { if (shift) { s = "R"; } else { s = "r"; }; };
if (key == KEY_T) { if (shift) { s = "T"; } else { s = "t"; }; };
if (key == KEY_Y) { if (shift) { s = "Y"; } else { s = "y"; }; };
if (key == KEY_U) { if (shift) { s = "U"; } else { s = "u"; }; };
if (key == KEY_I) { if (shift) { s = "I"; } else { s = "i"; }; };
if (key == KEY_O) { if (shift) { s = "O"; } else { s = "o"; }; };
if (key == KEY_P) { if (shift) { s = "P"; } else { s = "p"; }; };
if (key == KEY_LBRACKET) { if (shift) { s = "{"; } else { s = "["; }; };
if (key == KEY_RBRACKET) { if (shift) { s = "}"; } else { s = "]"; }; };
if (key == KEY_A) { if (shift) { s = "A"; } else { s = "a"; }; };
if (key == KEY_S) { if (shift) { s = "S"; } else { s = "s"; }; };
if (key == KEY_D) { if (shift) { s = "D"; } else { s = "d"; }; };
if (key == KEY_F) { if (shift) { s = "F"; } else { s = "f"; }; };
if (key == KEY_G) { if (shift) { s = "G"; } else { s = "g"; }; };
if (key == KEY_H) { if (shift) { s = "H"; } else { s = "h"; }; };
if (key == KEY_J) { if (shift) { s = "J"; } else { s = "j"; }; };
if (key == KEY_K) { if (shift) { s = "K"; } else { s = "k"; }; };
if (key == KEY_L) { if (shift) { s = "L"; } else { s = "l"; }; };
if (key == KEY_SEMICOLON) { if (shift) { s = ":"; } else { s = ";"; }; };
if (key == KEY_APOSTROPHE) { if (shift) {
//Double quote
const int mem = 0;
if (!mem) { mem = MEM_Alloc(1); };
MEM_WriteByte (mem, 34);
s = STR_FromChar (mem);
} else { s = "'"; }; };
if (key == KEY_GRAVE) { if (shift) { s = "~"; } else { s = "`"; }; };
if (key == KEY_BACKSLASH) { if (shift) { s = "|"; } else { s = "\"; }; };
if (key == KEY_Z) { if (shift) { s = "Z"; } else { s = "z"; }; };
if (key == KEY_X) { if (shift) { s = "X"; } else { s = "x"; }; };
if (key == KEY_C) { if (shift) { s = "C"; } else { s = "c"; }; };
if (key == KEY_V) { if (shift) { s = "V"; } else { s = "v"; }; };
if (key == KEY_B) { if (shift) { s = "B"; } else { s = "b"; }; };
if (key == KEY_N) { if (shift) { s = "N"; } else { s = "n"; }; };
if (key == KEY_M) { if (shift) { s = "M"; } else { s = "m"; }; };
if (key == KEY_COMMA) { if (shift) { s = "<"; } else { s = ","; }; };
if (key == KEY_PERIOD) { if (shift) { s = ">"; } else { s = "."; }; };
if (key == KEY_SLASH) { if (shift) { s = "?"; } else { s = "/"; }; };
if (key == KEY_SPACE) { s = " "; };
if (key == KEY_NUMPAD0) { s = "0"; };
if (key == KEY_NUMPAD1) { s = "1"; };
if (key == KEY_NUMPAD2) { s = "2"; };
if (key == KEY_NUMPAD3) { s = "3"; };
if (key == KEY_NUMPAD4) { s = "4"; };
if (key == KEY_NUMPAD5) { s = "5"; };
if (key == KEY_NUMPAD6) { s = "6"; };
if (key == KEY_NUMPAD7) { s = "7"; };
if (key == KEY_NUMPAD8) { s = "8"; };
if (key == KEY_NUMPAD9) { s = "9"; };
if (key == KEY_MULTIPLY) { s = "*"; };
if (key == KEY_SUBTRACT) { s = "-"; };
if (key == KEY_ADD) { s = "+"; };
if (key == KEY_DECIMAL) { s = "."; };
if (STR_Len (s) > 0) {
InfoManagerAnswer = ConcatStrings (InfoManagerAnswer, s);
};
cancel = TRUE; //Cancel input
};
};
//--- Spinners -->
if (InfoManagerSpinnerPossible) {
//Default value if not set
if (InfoManagerSpinnerPageSize == 0) { InfoManagerSpinnerPageSize = 1; };
//Home
if (key == KEY_HOME) {
InfoManagerSpinnerValue = InfoManagerSpinnerValueMin;
cancel = TRUE;
};
//End
if (key == KEY_END) {
InfoManagerSpinnerValue = InfoManagerSpinnerValueMax;
cancel = TRUE;
};
//Page Up
if (key == KEY_PRIOR) {
//12 --> 10 --> 5 --> 1 --> 12
if (InfoManagerSpinnerValue > InfoManagerSpinnerValueMin) {
if (((InfoManagerSpinnerValue / InfoManagerSpinnerPageSize) * InfoManagerSpinnerPageSize) < InfoManagerSpinnerValue) {
InfoManagerSpinnerValue = (InfoManagerSpinnerValue / InfoManagerSpinnerPageSize) * InfoManagerSpinnerPageSize;
} else {
InfoManagerSpinnerValue -= InfoManagerSpinnerPageSize;
};
if (InfoManagerSpinnerValue < InfoManagerSpinnerValueMin) {
InfoManagerSpinnerValue = InfoManagerSpinnerValueMin;
};
} else {
InfoManagerSpinnerValue -= InfoManagerSpinnerPageSize;
};
cancel = TRUE;
};
//Page Down
if (key == KEY_NEXT) {
//1 --> 5 --> 10 --> 12 --> 1
if (InfoManagerSpinnerValue < InfoManagerSpinnerValueMax) {
InfoManagerSpinnerValue = (InfoManagerSpinnerValue / InfoManagerSpinnerPageSize) * InfoManagerSpinnerPageSize;
InfoManagerSpinnerValue += InfoManagerSpinnerPageSize;
if (InfoManagerSpinnerValue > InfoManagerSpinnerValueMax) {
InfoManagerSpinnerValue = InfoManagerSpinnerValueMax;
};
} else {
InfoManagerSpinnerValue += InfoManagerSpinnerPageSize;
};
cancel = TRUE;
};
if (key == KEY_LEFTARROW) {
InfoManagerSpinnerValue -= 1;
cancel = TRUE;
};
if (key == KEY_RIGHTARROW) {
InfoManagerSpinnerValue += 1;
cancel = TRUE; //Cancel input (just in case)
};
if (cancel) {
//Min/Max values
if (InfoManagerSpinnerValue < InfoManagerSpinnerValueMin) {
InfoManagerSpinnerValue = InfoManagerSpinnerValueMax;
};
if (InfoManagerSpinnerValue > InfoManagerSpinnerValueMax) {
InfoManagerSpinnerValue = InfoManagerSpinnerValueMin;
};
};
};
};
//Cancel input if InfoManager is waiting for anything
if (MEM_InformationMan.IsWaitingForEnd)
|| (MEM_InformationMan.IsWaitingForOpen)
|| (MEM_InformationMan.IsWaitingForClose)
// || (MEM_InformationMan.IsWaitingForScript) this would prevent us from cancelling output units
{
cancel = TRUE;
};
if (cancel) {
EDI = 0;
MEM_WriteInt (ESP + 4, 0);
};
};
FUNC VOID _HOOK_INFORMATIONMANAGER_UPDATE ()
{
var zCViewDialogChoice dlg; dlg = _^(MEM_InformationMan.DlgChoice);
/*
if (dlg.IsActivated == 1)
&& (dlg.IsOpen == 1)
&& (dlg.ChoiceSelected > -1)
{
*/
var int choiceView; choiceView = MEM_InformationMan.DlgChoice;
var zCArray arr;
var zCViewText2 txt;
var zCViewText2 txtIndicator;
//Remove added 'Indicator' dialogs
if (Hlp_StrCmp (MEM_InformationMan.LastMethod, "CollectInfos")) {
if (InfoManagerAnswerIndicator) {
//Is there an extra dialog ?
if (dlg.m_listLines_numInArray > dlg.Choices) {
arr = _^ (choiceView + 172);
if (arr.array) {
txtIndicator = _^ (MEM_ReadIntArray (arr.array, dlg.m_listLines_numInArray - 1));
//add remove flag - Gothic will take care of the rest
txtIndicator.remove = TRUE;
};
};
InfoManagerAnswerIndicator = 0;
};
//Is there an extra dialog ?
if (InfoManagerSpinnerIndicator) {
if (dlg.m_listLines_numInArray > dlg.Choices) {
arr = _^ (choiceView + 172);
if (arr.array) {
txtIndicator = _^ (MEM_ReadIntArray (arr.array, dlg.m_listLines_numInArray - 1));
//add remove flag - Gothic will take care of the rest
txtIndicator.remove = TRUE;
};
};
InfoManagerSpinnerIndicator = 0;
};
};
if (dlg.IsActivated == 1)
{
if (InfoManagerUpdateState == cIM2BChanged)
|| (InfoManagerLastChoiceSelected != dlg.ChoiceSelected)
{
//Reset by default, script will figure out whether Answer is possible below, when it updates all dialog descriptions
InfoManagerAnswerPossible = FALSE;
//Reset by default, script will figure out whether Spinning is poosible below, when it updates all dialog descriptions
InfoManagerSpinnerPossible = FALSE;
arr = _^ (choiceView + 172);
if (arr.array) {
var int nextPosY; nextPosY = 0;
//loop counter for dialog options in zCViewDialogChoice
var int i; i = 0;
var int p;
var string dlgFont;
p = MEM_StackPos.position;
if (i < dlg.Choices) {
txt = _^ (MEM_ReadIntArray(arr.array, i));
//Get current fontame
dlgFont = Print_GetFontName (txt.font);
//Get current dialog instance
var C_NPC slf; slf = _^ (MEM_InformationMan.npc);
var C_NPC her; her = _^ (MEM_InformationMan.player);
var int infoPtr; infoPtr = 0;
var oCInfo dlgInstance;
const int cINFO_MGR_MODE_IMPORTANT = 0;
const int cINFO_MGR_MODE_INFO = 1;
const int cINFO_MGR_MODE_CHOICE = 2;
const int cINFO_MGR_MODE_TRADE = 3;
//'Standard' dialog options
if (MEM_InformationMan.Mode == cINFO_MGR_MODE_INFO) {
infoPtr = oCInfoManager_GetInfoUnimportant (slf, her, i);
} else
//Choices - have to be extracted from oCInfo.listChoices_next
//MEM_InformationMan.Info is a pointer to oCInfo
if (MEM_InformationMan.Mode == cINFO_MGR_MODE_CHOICE) {
infoPtr = MEM_InformationMan.Info;
};
if (infoPtr) {
var int len;
var int index;
var string dlgDescription;
//Default colors
var string dlgColor; dlgColor = InfoManagerDefaultColorDialogGrey;
var string dlgColorSelected; dlgColorSelected = InfoManagerDefaultDialogColorSelected;
var string dlgFontSelected; dlgFontSelected = "";
//Get description from dialogInstance.description
dlgInstance = _^ (infoPtr);
dlgDescription = dlgInstance.description;
//Choices
if (MEM_InformationMan.Mode == cINFO_MGR_MODE_CHOICE) {
if (dlgInstance.listChoices_next) {
//loop counter for all Choices
var int j; j = 0;
var zCList l;
var int list; list = dlgInstance.listChoices_next;
while (list);
l = _^(list);
var oCInfoChoice dlgChoice; dlgChoice = MEM_PtrToInst (l.data);
//if our dialog option is dialog choice - put text to dlgDescription
if (i == j) {
dlgDescription = dlgChoice.Text;
};
list = l.next;
j += 1;
end;
};
};
/* Extract font, font selected, color and color selected from dlgDescription.
Clear dlgDescription in process. */
//Extract font name
if (STR_StartsWith (dlgDescription, "f@")) {
len = STR_Len (dlgDescription);
len -= 2;
dlgDescription = STR_SubStr (dlgDescription, 2, len);
index = STR_IndexOf (dlgDescription, " ");
if (index > 0) {
len = STR_Len (dlgDescription);
len -= (index + 1);
dlgFont = STR_Prefix (dlgDescription, index);
dlgDescription = STR_SubStr (dlgDescription, index + 1, len);
};
};
//Extract font selected name
if (STR_StartsWith (dlgDescription, "fs@")) {
len = STR_Len (dlgDescription);
len -= 3;
dlgDescription = STR_SubStr (dlgDescription, 3, len);
index = STR_IndexOf (dlgDescription, " ");
if (index > 0) {
len = STR_Len (dlgDescription);
len -= (index + 1);
dlgFontSelected = STR_Prefix (dlgDescription, index);
dlgDescription = STR_SubStr (dlgDescription, index + 1, len);
};
};
//Extract color grayed
if (STR_StartsWith (dlgDescription, "h@")) {
len = STR_Len (dlgDescription);
len -= 2;
dlgDescription = STR_SubStr (dlgDescription, 2, len);
index = STR_IndexOf (dlgDescription, " ");
if (index > 0) {
len = STR_Len (dlgDescription);
len -= (index + 1);
dlgColor = STR_Prefix (dlgDescription, index);
dlgDescription = STR_SubStr (dlgDescription, index + 1, len);
};
};
//Extract color selected
if (STR_StartsWith (dlgDescription, "hs@")) {
len = STR_Len (dlgDescription);
len -= 3;
dlgDescription = STR_SubStr (dlgDescription, 3, len);
index = STR_IndexOf (dlgDescription, " ");
if (index > 0) {
len = STR_Len (dlgDescription);
len -= (index + 1);
dlgColorSelected = STR_Prefix (dlgDescription, index);
dlgDescription = STR_SubStr (dlgDescription, index + 1, len);
};
};
var int alignment; alignment = InfoManagerDefaultDialogAlignment;
var int textWidth;
//al@ align left
if (STR_StartsWith (dlgDescription, "al@")) {
len = STR_Len (dlgDescription);
len -= 4;
dlgDescription = STR_SubStr (dlgDescription, 4, len);
alignment = 0;
};
//ac@ align center
if (STR_StartsWith (dlgDescription, "ac@")) {
len = STR_Len (dlgDescription);
len -= 4;
dlgDescription = STR_SubStr (dlgDescription, 4, len);
alignment = 1;
};
//ar@ align right
if (STR_StartsWith (dlgDescription, "ar@")) {
len = STR_Len (dlgDescription);
len -= 4;
dlgDescription = STR_SubStr (dlgDescription, 4, len);
alignment = 2;
};
var int answerDialog; answerDialog = -1;
//answer
if (STR_StartsWith (dlgDescription, "a@")) {
len = STR_Len (dlgDescription);
len -= 3;
dlgDescription = STR_SubStr (dlgDescription, 3, len);
answerDialog = i;
};
var int spinnerDialog; spinnerDialog = -1;
var string spinnerDialogID; spinnerDialogID = "";
//spinner s@
if (STR_StartsWith (dlgDescription, "s@")) {
len = STR_Len (dlgDescription);
len -= 2;
dlgDescription = STR_SubStr (dlgDescription, 2, len);
index = STR_IndexOf (dlgDescription, " ");
if (index > 0) {
len = STR_Len (dlgDescription);
len -= (index + 1);
spinnerDialogID = STR_Prefix (dlgDescription, index);
dlgDescription = STR_SubStr (dlgDescription, index + 1, len);
};
spinnerDialog = i;
};
//Apply dlgColor and dlgColorSelected --> Is current dialog choice selected one ?
if (i == dlg.ChoiceSelected) {
if (answerDialog == i) {
InfoManagerAnswerPossible = TRUE;
//Add answer indicator
if (!InfoManagerAnswerMode) {
if (!InfoManagerAnswerIndicator) {
txt.useAlpha = TRUE;
txt.alphaFunc = 1;
txt.alpha = 255;
//Create new zCViewText2 instance for our indicator
InfoManagerAnswerIndicator = create (zCViewText2@);
txtIndicator = _^ (InfoManagerAnswerIndicator);
//Insert indicator to dialog choices
MEM_ArrayInsert (choiceView + 172, InfoManagerAnswerIndicator);
txtIndicator.validcolor = txt.validcolor;
txtIndicator.useAlpha = txt.useAlpha;
txtIndicator.alphaFunc = txt.alphaFunc;
txtIndicator.alpha = 128;
txtIndicator.text = "...";
};
};
};
if (spinnerDialog == i) {
InfoManagerSpinnerPossible = TRUE;
InfoManagerSpinnerID = spinnerDialogID;
//Add spinner indicator
if (!InfoManagerSpinnerIndicator) {
txt.useAlpha = TRUE;
txt.alphaFunc = 1;
txt.alpha = 255;
//Create new zCViewText2 instance for our indicator
InfoManagerSpinnerIndicator = create (zCViewText2@);
txtIndicator = _^ (InfoManagerSpinnerIndicator);
//Insert indicator to dialog choices
MEM_ArrayInsert (choiceView + 172, InfoManagerSpinnerIndicator);
txtIndicator.validcolor = txt.validcolor;
txtIndicator.useAlpha = txt.useAlpha;
txtIndicator.alphaFunc = txt.alphaFunc;
txtIndicator.alpha = 128;
txtIndicator.text = "<>";
};
};
if (STR_Len (dlgColorSelected) > 0) {
txt.color = HEX2RGBA (dlgColorSelected);
};
if (STR_Len (dlgFontSelected) > 0) {
dlgFont = dlgFontSelected;
};
//Are we in answer mode? If yes replace description with current answer
if (InfoManagerAnswerMode) {
dlgDescription = ConcatStrings (InfoManagerAnswer, "_");
};
} else {
if (STR_Len (dlgColor) > 0) {
txt.color = HEX2RGBA (dlgColor);
};
};
//Replace dialog option text with 'cleared' dlgDescription
txt.text = dlgDescription;
//Alignment: 0 left, 1 center, 2 right
if (alignment == 0) {
txt.posx = txt.posx + dlg.offsetTextpx;
} else
if (alignment == 1) {
textWidth = Print_GetStringWidth (dlgDescription, dlgFont);
txt.posx = (dlg.psizex / 2) - (textWidth / 2) - dlg.offsetTextpx - dlg.sizeMargin_0;
} else
if (alignment == 2) {
textWidth = Print_GetStringWidth (dlgDescription, dlgFont);
txt.posx = dlg.psizex - textWidth - dlg.offsetTextpx - dlg.sizeMargin_0;
};
};
//Recalculate offsetTextpy and posY for dialog items in case fonts changed
if (i == 0) {
nextPosY = txt.posY;
dlg.offsetTextpy = 0;
} else {
txt.posY = nextPosY;
};
var int newFont; newFont = Print_GetFontPtr (dlgFont);
//Adjust X, Y pos in case dialog with indicators is selected
if (i == dlg.ChoiceSelected) {
if (InfoManagerAnswerIndicator) {
txtIndicator = _^ (InfoManagerAnswerIndicator);
if (answerDialog == i) {
txtIndicator.font = newFont;
txtIndicator.color = HEX2RGBA (dlgColor);
txtIndicator.posy = txt.posy;
textWidth = Print_GetStringWidth (txtIndicator.text, dlgFont);
txtIndicator.posx = dlg.psizex - textWidth - dlg.offsetTextpx - dlg.sizeMargin_0;
};
};
if (InfoManagerSpinnerIndicator) {
txtIndicator = _^ (InfoManagerSpinnerIndicator);
if (spinnerDialog == i) {
txtIndicator.font = newFont;
txtIndicator.color = HEX2RGBA (dlgColor);
txtIndicator.posy = txt.posy;
textWidth = Print_GetStringWidth (txtIndicator.text, dlgFont);
txtIndicator.posx = dlg.psizex - textWidth - dlg.offsetTextpx - dlg.sizeMargin_0;
};
};
};
if (i < dlg.LineStart) {
dlg.offsetTextpy -= Print_GetFontHeight (dlgFont);
};
//Apply new font (or re-apply old one)
txt.font = newFont;
nextPosY += Print_GetFontHeight (dlgFont);
i += 1;
MEM_StackPos.position = p;
};
} else {
InfoManagerUpdateState = cIMChanged;
InfoManagerLastChoiceSelected = dlg.ChoiceSelected;
};
};
};
/*
} else {
InfoManagerUpdateState = cIM2BChanged;
};
*/
//Remove if not required (or if we are already answering)
if (!InfoManagerAnswerPossible) || (InfoManagerAnswerMode) {
if (InfoManagerAnswerIndicator) {
//Is there an extra dialog ?
if (dlg.m_listLines_numInArray > dlg.Choices) {
arr = _^ (choiceView + 172);
if (arr.array) {
txtIndicator = _^ (MEM_ReadIntArray (arr.array, dlg.m_listLines_numInArray - 1));
//add remove flag - Gothic will take care of the rest
txtIndicator.remove = TRUE;
};
};
InfoManagerAnswerIndicator = 0;
};
};
//Remove if not required
if (!InfoManagerSpinnerPossible) {
if (InfoManagerSpinnerIndicator) {
//Is there an extra dialog ?
if (dlg.m_listLines_numInArray > dlg.Choices) {
arr = _^ (choiceView + 172);
if (arr.array) {
txtIndicator = _^ (MEM_ReadIntArray (arr.array, dlg.m_listLines_numInArray - 1));
//add remove flag - Gothic will take care of the rest
txtIndicator.remove = TRUE;
};
};
InfoManagerSpinnerIndicator = 0;
};
};
};
Hook it with:
Code:
HookEngine (MEMINT_SwitchG1G2 (oCInformationManager__Update_G1, oCInformationManager__Update_G2), 5, "_HOOK_INFORMATIONMANAGER_UPDATE");
HookEngine (MEMINT_SwitchG1G2 (zCViewDialogChoice__HandleEvent_G1, zCViewDialogChoice__HandleEvent_G2), 9, "_HOOK_VIEWDIALOGCHOICE_HANDLEEVENT");
Dialogs which I have used for testing purposes:
Code:
/******************************************************
TEST SCENARIOS:
1. Instances are not 'sorted' first instance is the one with nr 2
2. 1 dialog Instance will not be displayed, as condition will return FALSE
3. 1 dialog Instance will clear dialog options (Info_ClearChoices) and add choices instead (Info_AddChoice)
4. 1 dialog Instance description will be changed on the run in condition function
5. we will have more dialog options which will have to be scrolled down to
******************************************************/
FUNC INT Always_True () { return TRUE; };
FUNC INT Always_False () { return FALSE; };
FUNC VOID DIA_DO_NOTHING () {};
INSTANCE DIA_TestDialog_Orange (C_Info) {
nr = 2;
npc = GRD_1650_Gardist;
condition = DIA_TestDialog_Orange_Condition;
information = DIA_DO_NOTHING;
permanent = FALSE;
description = "dummy";
};
FUNC INT DIA_TestDialog_Orange_Condition () {
//Test scenario - adjust description on the run
DIA_TestDialog_Orange.description = "f@font_15_white.tga fs@font_old_20_white.tga h@FF8000 hs@FFB266 Orange !"; //orange, selected: Light orange
return TRUE;
};
INSTANCE DIA_TestDialog_Line01 (C_Info) {
nr = 1;
npc = GRD_1650_Gardist;
condition = Always_True;
information = DIA_DO_NOTHING;
permanent = FALSE;
description = "Line 1";
};
INSTANCE DIA_TestDialog_Line03 (C_Info) {
nr = 3;
npc = GRD_1650_Gardist;
condition = Always_True;
information = DIA_DO_NOTHING;
permanent = FALSE;
description = "Line 3";
};
INSTANCE DIA_TestDialog_Line04 (C_Info) {
nr = 4;
npc = GRD_1650_Gardist;
condition = Always_True;
information = DIA_DO_NOTHING;
permanent = FALSE;
description = "Line 4";
};
INSTANCE DIA_TestDialog_Standard04 (C_Info) {
nr = 6;
npc = GRD_1650_Gardist;
condition = Always_True;
information = DIA_DO_NOTHING;
permanent = FALSE;
description = "Line 6";
};
INSTANCE DIA_TestDialog_Trade (C_Info) {
nr = 5;
npc = GRD_1650_Gardist;
condition = Always_True;
information = DIA_DO_NOTHING;
permanent = TRUE;
trade = TRUE;
description = "fs@font_15_white.tga h@FFFF00 hs@FF0000 Let's trade."; //defaultfont yellow, selected: fontsize 15 red
};
INSTANCE DIA_TestDialog_Choices (C_Info) {
nr = GRD_1650_Gardist;
nr = 8;
condition = Always_True;
information = DIA_TestDialog_Choices_Test;
permanent = TRUE;
description = "Choices - test";
};
FUNC VOID DIA_TestDialog_Choices_Test () {
Info_ClearChoices (DIA_TestDialog_Choices);
Info_AddChoice (DIA_TestDialog_Choices, "Standard.", DIA_TestDialog_Choices_Test);
Info_AddChoice (DIA_TestDialog_Choices, "h@00CC66 hs@66FFB2 Green.", DIA_TestDialog_Choices_Test);
Info_AddChoice (DIA_TestDialog_Choices, "fs@font_15_white.tga Selected fontsize 15.", DIA_TestDialog_Choices_Test);
Info_AddChoice (DIA_TestDialog_Choices, "BACK", DIA_TestDialog_Choices_Test_Back);
};
FUNC VOID DIA_TestDialog_Choices_Test_Back () {
Info_ClearChoices (DIA_TestDialog_Choices);
};
INSTANCE DIA_TestDialog_NeverShown (C_Info) {
nr = 8;
npc = GRD_1650_Gardist;
condition = Always_False;
information = DIA_DO_NOTHING;
permanent = FALSE;
description = "This dialog option will never be displayed";
};
INSTANCE DIA_TestDialog_GreenColorNoFont (C_Info) {
nr = 9;
npc = GRD_1650_Gardist;
condition = Always_True;
information = DIA_DO_NOTHING;
permanent = FALSE;
description = "h@00CC66 hs@66FFB2 Green color."; //default font green, selected: light green
};
INSTANCE DIA_TestDialog_Exit (C_Info) {
nr = 999;
npc = GRD_1650_Gardist;
condition = Always_True;
information = Exit_Dialog;
permanent = TRUE;
description = "f@font_15_white.tga h@FFFFFF hs@FFFF00 Exit dialog."; //fontsize 15 white, selected: yellow
};
Let me know if you see any issues - this was not thoroughly tested - so it might not be 100 % working properly.
Geändert von F a w k e s (30.09.2020 um 18:32 Uhr)
-
Thats amazing. I am sure that we will use this in some way. Thank you for the work and documentation.
-
I just fixed problem with delayed text update - code above updated
-
Nice work! With appropriate/subtle enough colors, this looks like a cool feature.
-
Excellent.
Is there a similar for adding colors to the strings of items in the inventory with examples?
-
Hello folks, quick update - had to add back condition checking if (dlg.IsActivated == 1) as sometimes Gothic crashed on me without it.
Also fixed calculation for STR_SubStr - this led to warning:
MEM_WARN('STR_SubStr: The end of the desired substring exceeds the end of the string.') + 21 bytes
Code above update once again.
Zitat von ukur
Is there a similar for adding colors to the strings of items in the inventory with examples?
That's something I wanted to implement as well, but I cannot figure out how to change color of inventory item overview
-
Nice as always...really useful - thanks for sharing
-
Bugfix: replacing function oCInfoManager_GetInfo with oCInfoManager_GetInfoUnimportant
Hello folks,
Just recognized there is a rather rare bug - if NPC has assigned IMPORTANT dialog for which its condition would be fulfilled while you are in a dialog with NPC itself - this color-changing hooked function would completely mess up order of dialog choices. Only option would be to exit dialog, let the Important dialog play and then to open dialog choices again.
I was able to fix this bug by replacing function oCInfoManager_GetInfo with function oCInfoManager_GetInfoUnimportant, which seems to be ignoring all 'IMPORTANT = TRUE' dialogs, and therefore seems to be working correctly for the purposes of this color-changing hook. Code above updated, changes highlighted with yellow color.
-
G1 dialog options effects
Hello folks,
I have been playing around with fonts and colors recently - and I wanted to add for Baal Netbek dialog option, which would be showing randomly generated strings.
I was hoping for a cool effect, where part of a text would be readable, and part would be changing constantly - so player would be puzzled - not having a clue, what dialog choice is actually choosing.
My problem is - seems like each letter of the font has different width - so it makes whole dialog option almost unreadable (3rd dialog option in the video below)
Is there a simple way how to set font width for each letter to same size (maybe using some engine call)? Or do I have to create a completely new font for this?
[Video]
Code for these dialog options:
Code:
//http://www.perbang.dk/rgbgradient/
FUNC STRING RainbowHexColor ()
{
var int indexMain;
indexMain += 1;
if (indexMain < 0) { indexMain = 1; };
if (indexMain > 256) { indexMain = 1; };
var int index;
index = indexMain / 4;
if (index < 1) { index = 1; };
if (index > 64) { index = 1; };
if (index == 1) { return "1700D2"; };
if (index == 2) { return "0500D2"; };
if (index == 3) { return "000CD2"; };
if (index == 4) { return "001ED2"; };
if (index == 5) { return "0031D2"; };
if (index == 6) { return "0043D2"; };
if (index == 7) { return "0055D2"; };
if (index == 8) { return "0067D2"; };
if (index == 9) { return "0079D2"; };
if (index == 10) { return "008BD1"; };
if (index == 11) { return "009ED1"; };
if (index == 12) { return "00B0D1"; };
if (index == 13) { return "00C2D1"; };
if (index == 14) { return "00D1CE"; };
if (index == 15) { return "00D1BC"; };
if (index == 16) { return "00D1AA"; };
if (index == 17) { return "00D198"; };
if (index == 18) { return "00D185"; };
if (index == 19) { return "00D173"; };
if (index == 20) { return "00D061"; };
if (index == 21) { return "00D04F"; };
if (index == 22) { return "00D03D"; };
if (index == 23) { return "00D02B"; };
if (index == 24) { return "00D018"; };
if (index == 25) { return "00D006"; };
if (index == 26) { return "0BD000"; };
if (index == 27) { return "1DD000"; };
if (index == 28) { return "2FD000"; };
if (index == 29) { return "41CF00"; };
if (index == 30) { return "53CF00"; };
if (index == 31) { return "65CF00"; };
if (index == 32) { return "77CF00"; };
if (index == 33) { return "89CF00"; };
if (index == 34) { return "9ACF00"; };
if (index == 35) { return "ACCF00"; };
if (index == 36) { return "BECF00"; };
if (index == 37) { return "CFCD00"; };
if (index == 38) { return "CEBB00"; };
if (index == 39) { return "CEA900"; };
if (index == 40) { return "CE9700"; };
if (index == 41) { return "CE8500"; };
if (index == 42) { return "CE7300"; };
if (index == 43) { return "CE8100"; };
if (index == 44) { return "CE4F00"; };
if (index == 45) { return "CE3D00"; };
if (index == 46) { return "CE2B00"; };
if (index == 47) { return "CD1900"; };
if (index == 48) { return "CD0800"; };
if (index == 49) { return "CD0009"; };
if (index == 50) { return "CD001B"; };
if (index == 51) { return "CD002D"; };
if (index == 52) { return "CD003F"; };
if (index == 53) { return "CD0050"; };
if (index == 54) { return "CD0062"; };
if (index == 55) { return "CD0074"; };
if (index == 56) { return "CC0086"; };
if (index == 57) { return "CC0097"; };
if (index == 58) { return "CC00A9"; };
if (index == 59) { return "CC00BB"; };
if (index == 60) { return "CC00CC"; };
if (index == 61) { return "BA00CC"; };
if (index == 62) { return "A800CC"; };
if (index == 63) { return "9600CC"; };
return "8400CC";
};
INSTANCE DIA_Netbek_Rainbow_Colors (C_Info)
{
nr = 1;
npc = NOV_1371_BaalNetbek;
condition = DIA_Netbek_Rainbow_Colors_Condition;
information = DIA_Netbek_Rainbow_Colors_Info;
important = FALSE;
permanent = TRUE;
description = "dummy";
};
FUNC INT DIA_Netbek_Rainbow_Colors_Condition ()
{
var string newDescription; newDescription = "c#";
newDescription = ConcatStrings (newDescription, RainbowHexColor ());
newDescription = ConcatStrings (newDescription, " cs#");
newDescription = ConcatStrings (newDescription, RainbowHexColor ());
newDescription = ConcatStrings (newDescription, " Rainbow colors test");
DIA_Netbek_Rainbow_Colors.description = newDescription;
return TRUE;
};
FUNC VOID DIA_Netbek_Rainbow_Colors_Info ()
{
};
//White 'blinking' fully visible - transparent
//R G B A
//FF FF FF 01 - FF
FUNC STRING AlphaBlinkingHexColor ()
{
var int indexMain;
indexMain += 1;
if (indexMain < 0) { indexMain = 1; };
if (indexMain > 256) { indexMain = 1; };
var int index;
index = indexMain / 4;
if (index == 1) { return "FFFFFF01"; };
if (index == 2) { return "FFFFFF09"; };
if (index == 3) { return "FFFFFF11"; };
if (index == 4) { return "FFFFFF19"; };
if (index == 5) { return "FFFFFF21"; };
if (index == 6) { return "FFFFFF29"; };
if (index == 7) { return "FFFFFF31"; };
if (index == 8) { return "FFFFFF39"; };
if (index == 9) { return "FFFFFF41"; };
if (index == 10){ return "FFFFFF49"; };
if (index == 11){ return "FFFFFF51"; };
if (index == 12){ return "FFFFFF59"; };
if (index == 13){ return "FFFFFF61"; };
if (index == 14){ return "FFFFFF69"; };
if (index == 15){ return "FFFFFF71"; };
if (index == 16){ return "FFFFFF79"; };
if (index == 17){ return "FFFFFF81"; };
if (index == 18){ return "FFFFFF89"; };
if (index == 19){ return "FFFFFF91"; };
if (index == 20){ return "FFFFFF99"; };
if (index == 21){ return "FFFFFFA1"; };
if (index == 22){ return "FFFFFFA9"; };
if (index == 23){ return "FFFFFFB1"; };
if (index == 24){ return "FFFFFFB9"; };
if (index == 25){ return "FFFFFFC1"; };
if (index == 26){ return "FFFFFFC9"; };
if (index == 27){ return "FFFFFFD1"; };
if (index == 28){ return "FFFFFFD9"; };
if (index == 29){ return "FFFFFFE1"; };
if (index == 30){ return "FFFFFFE9"; };
if (index == 31){ return "FFFFFFF1"; };
if (index == 32){ return "FFFFFFF9"; };
//---
if (index == 33){ return "FFFFFFFF"; };
if (index == 34){ return "FFFFFFF1"; };
if (index == 35){ return "FFFFFFE9"; };
if (index == 36){ return "FFFFFFE1"; };
if (index == 37){ return "FFFFFFD9"; };
if (index == 38){ return "FFFFFFD1"; };
if (index == 39){ return "FFFFFFC9"; };
if (index == 40){ return "FFFFFFC1"; };
if (index == 41){ return "FFFFFFB9"; };
if (index == 42){ return "FFFFFFB1"; };
if (index == 43){ return "FFFFFFA9"; };
if (index == 44){ return "FFFFFFA1"; };
if (index == 45){ return "FFFFFF99"; };
if (index == 46){ return "FFFFFF91"; };
if (index == 47){ return "FFFFFF89"; };
if (index == 48){ return "FFFFFF81"; };
if (index == 49){ return "FFFFFF79"; };
if (index == 50){ return "FFFFFF71"; };
if (index == 51){ return "FFFFFF69"; };
if (index == 52){ return "FFFFFF61"; };
if (index == 53){ return "FFFFFF59"; };
if (index == 54){ return "FFFFFF51"; };
if (index == 55){ return "FFFFFF49"; };
if (index == 56){ return "FFFFFF41"; };
if (index == 57){ return "FFFFFF39"; };
if (index == 58){ return "FFFFFF31"; };
if (index == 59){ return "FFFFFF29"; };
if (index == 60){ return "FFFFFF21"; };
if (index == 61){ return "FFFFFF19"; };
if (index == 62){ return "FFFFFF11"; };
if (index == 63){ return "FFFFFF09"; };
return "FFFFFF01";
};
INSTANCE DIA_Netbek_Alpha_Test (C_Info)
{
nr = 2;
npc = NOV_1371_BaalNetbek;
condition = DIA_Netbek_Alpha_Test_Condition;
information = DIA_Netbek_Alpha_Test_Info;
important = FALSE;
permanent = TRUE;
description = "dummy";
};
FUNC INT DIA_Netbek_Alpha_Test_Condition ()
{
var string newDescription; newDescription = "c#";
newDescription = ConcatStrings (newDescription, AlphaBlinkingHexColor ());
newDescription = ConcatStrings (newDescription, " Transparence test");
DIA_Netbek_Alpha_Test.description = newDescription;
return TRUE;
};
FUNC VOID DIA_Netbek_Alpha_Test_Info ()
{
};
FUNC STRING RandomLetter ()
{
var int randomizer;
randomizer = Hlp_Random (101);
if (randomizer == 00) { return "Ý"; };
if (randomizer == 01) { return "Ţ"; };
if (randomizer == 02) { return "ß"; };
if (randomizer == 03) { return "ŕ"; };
if (randomizer == 04) { return "á"; };
if (randomizer == 05) { return "â"; };
if (randomizer == 06) { return "ă"; };
if (randomizer == 07) { return "ä"; };
if (randomizer == 08) { return "ĺ"; };
if (randomizer == 09) { return "ć"; };
if (randomizer == 10) { return "ç"; };
if (randomizer == 11) { return "č"; };
if (randomizer == 12) { return "é"; };
if (randomizer == 13) { return "ę"; };
if (randomizer == 14) { return "ë"; };
if (randomizer == 15) { return "ě"; };
if (randomizer == 16) { return "í"; };
if (randomizer == 17) { return "î"; };
if (randomizer == 18) { return "ď"; };
if (randomizer == 19) { return "đ"; };
if (randomizer == 20) { return "ń"; };
if (randomizer == 21) { return "ň"; };
if (randomizer == 22) { return "ó"; };
if (randomizer == 23) { return "ô"; };
if (randomizer == 24) { return "ő"; };
if (randomizer == 25) { return "ö"; };
if (randomizer == 26) { return "÷"; };
if (randomizer == 27) { return "ř"; };
if (randomizer == 28) { return "ů"; };
if (randomizer == 29) { return "ú"; };
if (randomizer == 30) { return "ű"; };
if (randomizer == 31) { return "ü"; };
if (randomizer == 32) { return "ý"; };
if (randomizer == 33) { return "ţ"; };
if (randomizer == 34) { return "˙"; };
if (randomizer == 35) { return "A"; };
if (randomizer == 36) { return "B"; };
if (randomizer == 37) { return "C"; };
if (randomizer == 38) { return "D"; };
if (randomizer == 39) { return "E"; };
if (randomizer == 40) { return "F"; };
if (randomizer == 41) { return "G"; };
if (randomizer == 42) { return "H"; };
if (randomizer == 43) { return "I"; };
if (randomizer == 44) { return "J"; };
if (randomizer == 45) { return "K"; };
if (randomizer == 46) { return "L"; };
if (randomizer == 47) { return "M"; };
if (randomizer == 48) { return "N"; };
if (randomizer == 49) { return "O"; };
if (randomizer == 50) { return "P"; };
if (randomizer == 51) { return "Q"; };
if (randomizer == 52) { return "R"; };
if (randomizer == 53) { return "S"; };
if (randomizer == 54) { return "T"; };
if (randomizer == 55) { return "U"; };
if (randomizer == 56) { return "V"; };
if (randomizer == 57) { return "W"; };
if (randomizer == 58) { return "X"; };
if (randomizer == 59) { return "Y"; };
if (randomizer == 60) { return "Z"; };
if (randomizer == 61) { return "a"; };
if (randomizer == 62) { return "b"; };
if (randomizer == 63) { return "c"; };
if (randomizer == 64) { return "d"; };
if (randomizer == 65) { return "e"; };
if (randomizer == 66) { return "f"; };
if (randomizer == 67) { return "g"; };
if (randomizer == 68) { return "h"; };
if (randomizer == 69) { return "i"; };
if (randomizer == 70) { return "j"; };
if (randomizer == 71) { return "k"; };
if (randomizer == 72) { return "l"; };
if (randomizer == 73) { return "m"; };
if (randomizer == 74) { return "n"; };
if (randomizer == 75) { return "o"; };
if (randomizer == 76) { return "p"; };
if (randomizer == 77) { return "q"; };
if (randomizer == 78) { return "r"; };
if (randomizer == 79) { return "s"; };
if (randomizer == 80) { return "t"; };
if (randomizer == 81) { return "u"; };
if (randomizer == 82) { return "v"; };
if (randomizer == 83) { return "w"; };
if (randomizer == 84) { return "x"; };
if (randomizer == 85) { return "y"; };
if (randomizer == 86) { return "z"; };
if (randomizer == 87) { return "0"; };
if (randomizer == 88) { return "1"; };
if (randomizer == 89) { return "2"; };
if (randomizer == 90) { return "3"; };
if (randomizer == 91) { return "4"; };
if (randomizer == 92) { return "5"; };
if (randomizer == 93) { return "6"; };
if (randomizer == 94) { return "7"; };
if (randomizer == 95) { return "8"; };
if (randomizer == 96) { return "9"; };
/*
In this case we should not use '#' randomly assigned to letters as it can in a combination with color/font modifiers: f#, fs#, c#, cs# cause crash in hook _HOOK_INFORMATIONMANAGER_UPDATE
if (randomizer == 97) { return "#"; };
*/
if (randomizer == 98) { return "$"; };
if (randomizer == 99) { return "%"; };
if (randomizer == 100) { return "&"; };
return "$";
};
INSTANCE DIA_Netbek_Random_Text (C_Info)
{
nr = 3;
npc = NOV_1371_BaalNetbek;
condition = DIA_Netbek_Random_Text_Condition;
information = DIA_Netbek_Random_Text_Info;
important = FALSE;
permanent = TRUE;
description = "dummy";
};
FUNC INT DIA_Netbek_Random_Text_Condition ()
{
//font_default
//font_10_book
//font_15_white
//font_old_10_white
//
var string newDescription; newDescription = "f#font_old_10_white.tga ";
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, " Random ");
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, " letters ");
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, " test ");
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
newDescription = ConcatStrings (newDescription, RandomLetter ());
DIA_Netbek_Random_Text.description = newDescription;
return TRUE;
};
FUNC VOID DIA_Netbek_Random_Text_Info ()
{
};
-
Maybe it would alternatively be possible to switch the font to one with fixed width? The width of each letter is set in the font's .fnt file. I'm not sure whether you have access to those rendering details even through engine calls (you could maybe manually add the right amount of space after each letter, but some people use font patches, so for those it would be wrong if you can't determine the size dynamically.)
-
You can't (easily) make a font monospaced in Gothic, but you can change which font a zCViewText is displayed in, so you can supply your own font or choose one of the preexisting ones, if there is a monospaced one.
LeGo also has a function to determine the width of a string so you could generate random strings until you find one that has a similar length (which may take a long time depending on how similar it has to be).
Edit: Maybe it looks a lot better if you only change one letter at a time, going from left to right. That would make it look a lot less busy.
-
Hello Milky-Way, Lehona,
Thank you for your inputs! This got me thinking - and one solution is to use Print_GetStringWidth and loop through letters to figure out what width is most used one. This way code should work even in case font_default.tga would be changed by some patch. Seems like in vanilla G1 there is 26 letters out of 100 I was searching within with same size of 9 pixels ('a' for example). I was hoping for more of these - randomly generated text is not as insane as I would hope for, but this will have to do for now. Thank you!
[Video]
Updated function RandomLetter:
Code:
FUNC STRING RandomLetter ()
{
const int maxLetters = 99;
var int letterWidth[100];
const int once = 0;
var int i;
var int j;
var int p1; //MEM_StackPos variable for loop 1
var int p2; //MEM_StackPos variable for loop 2
//Get width of each letter
if (!once) {
letterWidth[00] = Print_GetStringWidth (" ", "font_default.tga");
letterWidth[00] = Print_GetStringWidth ("Ý", "font_default.tga");
letterWidth[01] = Print_GetStringWidth ("Ţ", "font_default.tga");
letterWidth[02] = Print_GetStringWidth ("ß", "font_default.tga");
letterWidth[03] = Print_GetStringWidth ("ŕ", "font_default.tga");
letterWidth[04] = Print_GetStringWidth ("á", "font_default.tga");
letterWidth[05] = Print_GetStringWidth ("â", "font_default.tga");
letterWidth[06] = Print_GetStringWidth ("ă", "font_default.tga");
letterWidth[07] = Print_GetStringWidth ("ä", "font_default.tga");
letterWidth[08] = Print_GetStringWidth ("ĺ", "font_default.tga");
letterWidth[09] = Print_GetStringWidth ("ć", "font_default.tga");
letterWidth[10] = Print_GetStringWidth ("ç", "font_default.tga");
letterWidth[11] = Print_GetStringWidth ("č", "font_default.tga");
letterWidth[12] = Print_GetStringWidth ("é", "font_default.tga");
letterWidth[13] = Print_GetStringWidth ("ę", "font_default.tga");
letterWidth[14] = Print_GetStringWidth ("ë", "font_default.tga");
letterWidth[15] = Print_GetStringWidth ("ě", "font_default.tga");
letterWidth[16] = Print_GetStringWidth ("í", "font_default.tga");
letterWidth[17] = Print_GetStringWidth ("î", "font_default.tga");
letterWidth[18] = Print_GetStringWidth ("ď", "font_default.tga");
letterWidth[19] = Print_GetStringWidth ("đ", "font_default.tga");
letterWidth[20] = Print_GetStringWidth ("ń", "font_default.tga");
letterWidth[21] = Print_GetStringWidth ("ň", "font_default.tga");
letterWidth[22] = Print_GetStringWidth ("ó", "font_default.tga");
letterWidth[23] = Print_GetStringWidth ("ô", "font_default.tga");
letterWidth[24] = Print_GetStringWidth ("ő", "font_default.tga");
letterWidth[25] = Print_GetStringWidth ("ö", "font_default.tga");
letterWidth[26] = Print_GetStringWidth ("÷", "font_default.tga");
letterWidth[27] = Print_GetStringWidth ("ř", "font_default.tga");
letterWidth[28] = Print_GetStringWidth ("ů", "font_default.tga");
letterWidth[29] = Print_GetStringWidth ("ú", "font_default.tga");
letterWidth[30] = Print_GetStringWidth ("ű", "font_default.tga");
letterWidth[31] = Print_GetStringWidth ("ü", "font_default.tga");
letterWidth[32] = Print_GetStringWidth ("ý", "font_default.tga");
letterWidth[33] = Print_GetStringWidth ("ţ", "font_default.tga");
letterWidth[34] = Print_GetStringWidth ("˙", "font_default.tga");
letterWidth[35] = Print_GetStringWidth ("A", "font_default.tga");
letterWidth[36] = Print_GetStringWidth ("B", "font_default.tga");
letterWidth[37] = Print_GetStringWidth ("C", "font_default.tga");
letterWidth[38] = Print_GetStringWidth ("D", "font_default.tga");
letterWidth[39] = Print_GetStringWidth ("E", "font_default.tga");
letterWidth[40] = Print_GetStringWidth ("F", "font_default.tga");
letterWidth[41] = Print_GetStringWidth ("G", "font_default.tga");
letterWidth[42] = Print_GetStringWidth ("H", "font_default.tga");
letterWidth[43] = Print_GetStringWidth ("I", "font_default.tga");
letterWidth[44] = Print_GetStringWidth ("J", "font_default.tga");
letterWidth[45] = Print_GetStringWidth ("K", "font_default.tga");
letterWidth[46] = Print_GetStringWidth ("L", "font_default.tga");
letterWidth[47] = Print_GetStringWidth ("M", "font_default.tga");
letterWidth[48] = Print_GetStringWidth ("N", "font_default.tga");
letterWidth[49] = Print_GetStringWidth ("O", "font_default.tga");
letterWidth[50] = Print_GetStringWidth ("P", "font_default.tga");
letterWidth[51] = Print_GetStringWidth ("Q", "font_default.tga");
letterWidth[52] = Print_GetStringWidth ("R", "font_default.tga");
letterWidth[53] = Print_GetStringWidth ("S", "font_default.tga");
letterWidth[54] = Print_GetStringWidth ("T", "font_default.tga");
letterWidth[55] = Print_GetStringWidth ("U", "font_default.tga");
letterWidth[56] = Print_GetStringWidth ("V", "font_default.tga");
letterWidth[57] = Print_GetStringWidth ("W", "font_default.tga");
letterWidth[58] = Print_GetStringWidth ("X", "font_default.tga");
letterWidth[59] = Print_GetStringWidth ("Y", "font_default.tga");
letterWidth[60] = Print_GetStringWidth ("Z", "font_default.tga");
letterWidth[61] = Print_GetStringWidth ("a", "font_default.tga");
letterWidth[62] = Print_GetStringWidth ("b", "font_default.tga");
letterWidth[63] = Print_GetStringWidth ("c", "font_default.tga");
letterWidth[64] = Print_GetStringWidth ("d", "font_default.tga");
letterWidth[65] = Print_GetStringWidth ("e", "font_default.tga");
letterWidth[66] = Print_GetStringWidth ("f", "font_default.tga");
letterWidth[67] = Print_GetStringWidth ("g", "font_default.tga");
letterWidth[68] = Print_GetStringWidth ("h", "font_default.tga");
letterWidth[69] = Print_GetStringWidth ("i", "font_default.tga");
letterWidth[70] = Print_GetStringWidth ("j", "font_default.tga");
letterWidth[71] = Print_GetStringWidth ("k", "font_default.tga");
letterWidth[72] = Print_GetStringWidth ("l", "font_default.tga");
letterWidth[73] = Print_GetStringWidth ("m", "font_default.tga");
letterWidth[74] = Print_GetStringWidth ("n", "font_default.tga");
letterWidth[75] = Print_GetStringWidth ("o", "font_default.tga");
letterWidth[76] = Print_GetStringWidth ("p", "font_default.tga");
letterWidth[77] = Print_GetStringWidth ("q", "font_default.tga");
letterWidth[78] = Print_GetStringWidth ("r", "font_default.tga");
letterWidth[79] = Print_GetStringWidth ("s", "font_default.tga");
letterWidth[80] = Print_GetStringWidth ("t", "font_default.tga");
letterWidth[81] = Print_GetStringWidth ("u", "font_default.tga");
letterWidth[82] = Print_GetStringWidth ("v", "font_default.tga");
letterWidth[83] = Print_GetStringWidth ("w", "font_default.tga");
letterWidth[84] = Print_GetStringWidth ("x", "font_default.tga");
letterWidth[85] = Print_GetStringWidth ("y", "font_default.tga");
letterWidth[86] = Print_GetStringWidth ("z", "font_default.tga");
letterWidth[87] = Print_GetStringWidth ("0", "font_default.tga");
letterWidth[88] = Print_GetStringWidth ("1", "font_default.tga");
letterWidth[89] = Print_GetStringWidth ("2", "font_default.tga");
letterWidth[90] = Print_GetStringWidth ("3", "font_default.tga");
letterWidth[91] = Print_GetStringWidth ("4", "font_default.tga");
letterWidth[92] = Print_GetStringWidth ("5", "font_default.tga");
letterWidth[93] = Print_GetStringWidth ("6", "font_default.tga");
letterWidth[94] = Print_GetStringWidth ("7", "font_default.tga");
letterWidth[95] = Print_GetStringWidth ("8", "font_default.tga");
letterWidth[96] = Print_GetStringWidth ("9", "font_default.tga");
letterWidth[96] = Print_GetStringWidth ("$", "font_default.tga");
letterWidth[97] = Print_GetStringWidth ("%", "font_default.tga");
letterWidth[99] = Print_GetStringWidth ("&", "font_default.tga");
var int count;
var int maxCount; maxCount = 0;
var int widthMax; widthMax = -1;
//1st loop through each letter
i = 0;
p1 = MEM_StackPos.position;
j = i;
count = 0;
//2nd loop - count how many letters have same width
p2 = MEM_StackPos.position;
if (MEM_ReadIntArray (_@ (letterWidth), i) == MEM_ReadIntArray (_@ (letterWidth), j)) {
count += 1;
};
//remember width of this one, this is most common width
if (count > maxCount) {
maxCount = count;
widthMax = MEM_ReadIntArray (_@ (letterWidth), i);
};
j += 1;
if (j < maxLetters) {
MEM_StackPos.position = p2;
};
i += 1;
if (i < maxLetters) {
MEM_StackPos.position = p1;
};
once = 1;
};
var int randomizer;
randomizer = Hlp_Random (maxLetters + 1);
p1 = MEM_StackPos.position;
if (widthMax == MEM_ReadIntArray(_@ (letterWidth), randomizer)) {
if (randomizer == 00) { return "Ý"; };
if (randomizer == 01) { return "Ţ"; };
if (randomizer == 02) { return "ß"; };
if (randomizer == 03) { return "ŕ"; };
if (randomizer == 04) { return "á"; };
if (randomizer == 05) { return "â"; };
if (randomizer == 06) { return "ă"; };
if (randomizer == 07) { return "ä"; };
if (randomizer == 08) { return "ĺ"; };
if (randomizer == 09) { return "ć"; };
if (randomizer == 10) { return "ç"; };
if (randomizer == 11) { return "č"; };
if (randomizer == 12) { return "é"; };
if (randomizer == 13) { return "ę"; };
if (randomizer == 14) { return "ë"; };
if (randomizer == 15) { return "ě"; };
if (randomizer == 16) { return "í"; };
if (randomizer == 17) { return "î"; };
if (randomizer == 18) { return "ď"; };
if (randomizer == 19) { return "đ"; };
if (randomizer == 20) { return "ń"; };
if (randomizer == 21) { return "ň"; };
if (randomizer == 22) { return "ó"; };
if (randomizer == 23) { return "ô"; };
if (randomizer == 24) { return "ő"; };
if (randomizer == 25) { return "ö"; };
if (randomizer == 26) { return "÷"; };
if (randomizer == 27) { return "ř"; };
if (randomizer == 28) { return "ů"; };
if (randomizer == 29) { return "ú"; };
if (randomizer == 30) { return "ű"; };
if (randomizer == 31) { return "ü"; };
if (randomizer == 32) { return "ý"; };
if (randomizer == 33) { return "ţ"; };
if (randomizer == 34) { return "˙"; };
if (randomizer == 35) { return "A"; };
if (randomizer == 36) { return "B"; };
if (randomizer == 37) { return "C"; };
if (randomizer == 38) { return "D"; };
if (randomizer == 39) { return "E"; };
if (randomizer == 40) { return "F"; };
if (randomizer == 41) { return "G"; };
if (randomizer == 42) { return "H"; };
if (randomizer == 43) { return "I"; };
if (randomizer == 44) { return "J"; };
if (randomizer == 45) { return "K"; };
if (randomizer == 46) { return "L"; };
if (randomizer == 47) { return "M"; };
if (randomizer == 48) { return "N"; };
if (randomizer == 49) { return "O"; };
if (randomizer == 50) { return "P"; };
if (randomizer == 51) { return "Q"; };
if (randomizer == 52) { return "R"; };
if (randomizer == 53) { return "S"; };
if (randomizer == 54) { return "T"; };
if (randomizer == 55) { return "U"; };
if (randomizer == 56) { return "V"; };
if (randomizer == 57) { return "W"; };
if (randomizer == 58) { return "X"; };
if (randomizer == 59) { return "Y"; };
if (randomizer == 60) { return "Z"; };
if (randomizer == 61) { return "a"; };
if (randomizer == 62) { return "b"; };
if (randomizer == 63) { return "c"; };
if (randomizer == 64) { return "d"; };
if (randomizer == 65) { return "e"; };
if (randomizer == 66) { return "f"; };
if (randomizer == 67) { return "g"; };
if (randomizer == 68) { return "h"; };
if (randomizer == 69) { return "i"; };
if (randomizer == 70) { return "j"; };
if (randomizer == 71) { return "k"; };
if (randomizer == 72) { return "l"; };
if (randomizer == 73) { return "m"; };
if (randomizer == 74) { return "n"; };
if (randomizer == 75) { return "o"; };
if (randomizer == 76) { return "p"; };
if (randomizer == 77) { return "q"; };
if (randomizer == 78) { return "r"; };
if (randomizer == 79) { return "s"; };
if (randomizer == 80) { return "t"; };
if (randomizer == 81) { return "u"; };
if (randomizer == 82) { return "v"; };
if (randomizer == 83) { return "w"; };
if (randomizer == 84) { return "x"; };
if (randomizer == 85) { return "y"; };
if (randomizer == 86) { return "z"; };
if (randomizer == 87) { return "0"; };
if (randomizer == 88) { return "1"; };
if (randomizer == 89) { return "2"; };
if (randomizer == 90) { return "3"; };
if (randomizer == 91) { return "4"; };
if (randomizer == 92) { return "5"; };
if (randomizer == 93) { return "6"; };
if (randomizer == 94) { return "7"; };
if (randomizer == 95) { return "8"; };
if (randomizer == 96) { return "9"; };
if (randomizer == 96) { return "$"; };
if (randomizer == 97) { return "%"; };
if (randomizer == 99) { return "&"; };
/*
In this case we should not use '#' randomly assigned to letters as it can in a combination with color/font modifiers: f#, fs#, c#, cs# cause crash in hook _HOOK_INFORMATIONMANAGER_UPDATE
if (randomizer == 97) { return "#"; };
*/
};
randomizer = randomizer + 1;
if (randomizer > maxLetters) {
randomizer = 0;
};
MEM_StackPos.position = p1;
return "Impossible error!";
};
-
I think if you slow it down a lot - e.g. only change a few letters at a time and at a far slower frequency it might look even better. Currently it reminds me of a slot machine due to the speed.
-
G1/G2 Dialog Input field
Hello folks,
Bisasam's recent topic about Input fields inspired me to revisit script for dialog font & color change. I have implemented now new feature:
- by adding new dialog description modifier 'a@' you can now use dialog option as an Input field and you can enter free text into it.
[Video]
This is how you can use it ingame - usage is very simple:
Code:
INSTANCE DIA_Diego_Answer1 (C_Info) {
npc = PC_Thief;
nr = 900;
condition = DIA_Diego_Answer1_Condition;
information = DIA_Diego_Answer1_Info;
permanent = TRUE;
important = FALSE;
//Default color 00CC66, selected color 66FFB2, @a modifier enables this dialog option as an Input field
description = "h@00CC66 hs@66FFB2 a@ What secret password will allow you to visit Water Mages in New Camp ?";
};
FUNC INT DIA_Diego_Answer1_Condition () {
return TRUE;
};
FUNC VOID DIA_Diego_Answer1_Info () {
if (Hlp_StrCmp (InfoManagerAnswer, "TETRIANDOCH")) {
PrintScreen ("Yes that is correct!", -1, -1, "font_old_10_white.tga", 3);
} else {
PrintScreen ("No that is wrong!", -1, -1, "font_old_10_white.tga", 3);
};
};
INSTANCE DIA_Diego_Answer2 (C_Info) {
npc = PC_Thief;
nr = 901;
condition = DIA_Diego_Answer2_Condition;
information = DIA_Diego_Answer2_Info;
permanent = TRUE;
important = FALSE;
//@a modifier enables this dialog option as an Input field
description = "a@ Who is the pirate leader in G2A?";
};
FUNC INT DIA_Diego_Answer2_Condition () {
return TRUE;
};
FUNC VOID DIA_Diego_Answer2_Info () {
if (Hlp_StrCmp (InfoManagerAnswer, "GREG")) {
PrintScreen ("Yes that is correct!", -1, -1, "font_old_10_white.tga", 3);
} else {
PrintScreen ("No that is wrong!", -1, -1, "font_old_10_white.tga", 3);
};
};
INSTANCE DIA_Diego_Answer3 (C_Info) {
npc = PC_Thief;
nr = 902;
condition = DIA_Diego_Answer3_Condition;
information = DIA_Diego_Answer3_Info;
permanent = TRUE;
important = FALSE;
description = "Choice test";
};
FUNC INT DIA_Diego_Answer3_Condition () {
return TRUE;
};
FUNC VOID DIA_Diego_Answer3_Info () {
Info_ClearChoices (DIA_Diego_Answer3);
//@a modifier enables this dialog choice as an Input field
Info_AddChoice (DIA_Diego_Answer3, "a@ What secret password will allow you to visit Water Mages in New Camp ?", DIA_Diego_Validate_Answer3);
};
FUNC VOID DIA_Diego_Validate_Answer3 () {
Info_ClearChoices (DIA_Diego_Answer3);
if (Hlp_StrCmp (InfoManagerAnswer, "TETRIANDOCH")) {
PrintScreen ("Yes that is correct!", -1, -1, "font_old_10_white.tga", 3);
} else {
PrintScreen ("No that is wrong!", -1, -1, "font_old_10_white.tga", 3);
};
};
Script in first post updated.
Input field uses US english keyboard Layout:KEY_1 in combination with shift will give you exclamation mark '!'
KEY_9 in combination with shift will give you left bracket '(' ...
Important note --> if you were using older version, I have changed previous modifiers now, you will have to update old modifiers in your scripts:from 'c#' to 'h@'
from 'cs#' to 'hs@'
from 'f#' to 'f@'
from 'fs#' to 'fs@'
Apologies for any inconvenience. I have done this, because I wanted to remain consistent. In another thread I have implemented similar notation changing dialog colors by using modifier h@.
https://forum.worldofplayers.de/foru...1#post26255423
(I was not able to use # in dialogs, that's why I used @)
Let me know in case you see any issues.
-
G1/G2 Dialog Spinner
Hello folks,
Today I have added new feature 'Spinner' for dialogs. Spinner allows you to use Left / Right arrow key on a dialog option to decrease / increase numerical value of global variable InfoManagerSpinnerValue. If used properly this can improve both player's and modder's experience significantly.
Let's have a look for example on Meat cooking. With this feature as a modder you don't have to add any Info_AddChoice options into your dialog, as a player you don't have to go through any dialog choices.
You can just simply use navigation keys to countol amount of items:Left arrow key: InfoManagerSpinnerValue = InfoManagerSpinnerValue - 1 Right arrow key: InfoManagerSpinnerValue = InfoManagerSpinnerValue + 1 Page Up key: InfoManagerSpinnerValue = InfoManagerSpinnerValue - InfoManagerSpinnerPageSize Page Down key: InfoManagerSpinnerValue = InfoManagerSpinnerValue + InfoManagerSpinnerPageSize Home key: InfoManagerSpinnerValue = InfoManagerSpinnerValueMin End key: InfoManagerSpinnerValue = InfoManagerSpinnerValueMax
Check this video out to see how this feature can be used with both FaceHelper and Meat cooking:
[Video]
Unlike with Input field I have implemented previously - here usage is much more complex. But it is worth it!
Once again, you have to add modifier to your dialog description that enables this feature. Spinner modifier has to be in format 's@spinnerID' where 'spinnerID' is in text format (cannot contain spaces) and should be unique for each spinner in one dialog window.
SpinnerID is required because you can have multiple spinners in your dialogs. What is displayed in a dialog description is completely maintained from condition function --> see below examples.
Script in first post updated.
Both examples demonstrated in above video are here, you can use them as templates when creating your own spinners:
1. Meat cooking
Code:
INSTANCE PC_Pan_Cook_Meat (C_Info) {
nr = 1;
condition = PC_Pan_Cook_Meat_Condition;
information = PC_Pan_Cook_Meat_Info;
permanent = TRUE;
description = "dummy"; //Description is updated in PC_Pan_Cook_Meat_Condition
};
FUNC INT PC_Pan_Cook_Meat_Condition () {
if (PLAYER_MOBSI_PRODUCTION == MOBSI_DIALOG_PAN) {
var string lastSpinnerID; //Actually global variable! ;-) Will help us to recognize whether current spinner is this one, as we will store in it last spinner ID
var int selectedMeat; //Another global variable - number of items, which user selected
var int total; total = NPC_HasItems (self, ItFoMuttonRaw);
if (selectedMeat == 0) { selectedMeat = 1; }; //Default initial value
//Check currently selected spinned ID --> is it this one?
if (Hlp_StrCmp (InfoManagerSpinnerID, "CookMeat")) {
//Setup spinner if spinner ID has changed
if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID)) {
//Restore previous value
InfoManagerSpinnerValue = selectedMeat;
};
//Page Up/Down quantity
InfoManagerSpinnerPageSize = 5;
//Min/Max value (Home/End keys)
InfoManagerSpinnerValueMin = 1;
InfoManagerSpinnerValueMax = total;
//Update number which is shown in description (in case it was changed by _HOOK_VIEWDIALOGCHOICE_HANDLEEVENT
selectedMeat = InfoManagerSpinnerValue;
};
lastSpinnerID = InfoManagerSpinnerID; //Remember last active spinner ID
var string newDescription;
//Spinner ID 'CookMeat'
newDescription = "s@CookMeat Cook some meat: ";
newDescription = ConcatStrings (newDescription, IntToString (selectedMeat));
newDescription = ConcatStrings (newDescription, " / ");
newDescription = ConcatStrings (newDescription, IntToString (total));
//Update description
PC_Pan_Cook_Meat.description = newDescription;
return TRUE;
};
return FALSE;
};
FUNC VOID PC_Pan_Cook_Meat_Info () {
//If we don't have any meat ... don't cook any :)
if (!NPC_HasItems (self, ItFoMuttonRaw)) { return; };
//This should not happen - but you never know!
if (InfoManagerSpinnerValue < 1) { return; };
//This should not happen either! but just in case
if (InfoManagerSpinnerValue > (NPC_HasItems (self, ItFoMuttonRaw))) {
InfoManagerSpinnerValue = NPC_HasItems (self, ItFoMuttonRaw);
};
NPC_RemoveInvItems (self, ItFoMuttonRaw, InfoManagerSpinnerValue);
CreateInvItems (self, ItFoMutton, InfoManagerSpinnerValue);
B_GiveXP (XP_Bonus_Cooking * InfoManagerSpinnerValue);
//Reset value for next time
InfoManagerSpinnerValue = 1;
};
INSTANCE PC_Pan_Cook_Meat_Exit (C_Info) {
nr = 999;
condition = PC_Pan_Cook_Meat_Exit_Condition;
information = PC_Pan_Cook_Meat_Exit_Info;
permanent = TRUE;
description = "END";
};
FUNC INT PC_Pan_Cook_Meat_Exit_Condition ()
{
if (PLAYER_MOBSI_PRODUCTION == MOBSI_DIALOG_PAN) {
return TRUE;
};
return FALSE;
};
FUNC VOID PC_Pan_Cook_Meat_Exit_Info () {
if (PLAYER_MOBSI_PRODUCTION != MOBSI_DIALOG_NONE) {
PLAYER_MOBSI_PRODUCTION = MOBSI_DIALOG_NONE;
hero.aivar [AIV_INVINCIBLE] = FALSE;
AI_StopProcessInfos (hero);
};
};
FUNC VOID Pan_Dialog_S1 ()
{
var C_NPC her; her = Hlp_GetNpc (PC_Hero);
if (Hlp_GetInstanceID (self) == Hlp_GetInstanceID (her)) {
self.aivar [AIV_INVINCIBLE] = TRUE;
PLAYER_MOBSI_PRODUCTION = MOBSI_DIALOG_PAN;
//Default value
InfoManagerSpinnerValue = 1;
PC_Pan_Cook_Meat.npc = Hlp_GetInstanceID (self);
PC_Pan_Cook_Meat_Exit.npc = Hlp_GetInstanceID (self);
AI_ProcessInfos (self);
};
};
2. G1 FaceHelper
(this will not work if you just copy-paste it, I am using some functions in code, which are not defined in this post)
Code:
// body mesh, bdytex skin, head mesh, headtex, teethtex, ruestung
//Mdl_SetVisualBody (self, "hum_body_Naked0", FaceHelper_BodyTex, FaceHelper_Skin, FaceHelper_HeadMesh, FaceHelper_HeadTex, FaceHelper_TeethTex, itemInstance);
const int FaceHelper_BodyTex_Max = 4; //0 - 4 | 5 - 12 babes
const int FaceHelper_Skin_Max = 3; //0 - 3
const int FaceHelper_HeadTex_Max = 117; //0 - 117
const int FaceHelper_HeadMesh_Max = 6; //0 - 6
const int FaceHelper_TeethTex_Max = 3; //0 - 3
const int FaceHelper_Armor_Max = 36; //-1 - 36
var int FaceHelper_BodyTex;
var int FaceHelper_Skin;
var int FaceHelper_HeadMesh;
var string FaceHelper_HeadMesh_Name;
var int FaceHelper_HeadTex;
var int FaceHelper_TeethTex;
var int FaceHelper_Armor;
var string FaceHelper_Armor_Name;
var int FaceHelper_Armor_Instance;
FUNC VOID ZS_FH_Hangaround () {
NPC_PercEnable (self, PERC_ASSESSTALK, FH_Dialogs);
};
FUNC VOID ZS_FH_Hangaround_Loop () {};
FUNC VOID ZS_FH_Hangaround_End () {};
INSTANCE FH (Npc_Default) {
Name[0] = "Face Helper";
NPCType = NPCType_Main;
Guild = GIL_NONE;
Level = 10;
Voice = 15;
ID = 0;
senses = SENSE_HEAR | SENSE_SEE | SENSE_SMELL;
senses_range = 3000;
//Default values
FaceHelper_BodyTex = 3;
FaceHelper_Skin = 1;
FaceHelper_HeadMesh_Name = "HUM_HEAD_THIEF";
FaceHelper_HeadMesh = 2;
FaceHelper_HeadTex = 67;
FaceHelper_Armor = -1;
FaceHelper_Armor_Name = "NO ARMOR";
FaceHelper_Armor_Instance = -1;
Mdl_SetVisual (self, "HUMANS.MDS");
Mdl_SetVisualBody (self, "hum_body_Naked0", FaceHelper_BodyTex, FaceHelper_Skin, FaceHelper_HeadMesh_Name, FaceHelper_HeadTex, 0, -1);
//Create armors in inventory
CreateInvItem (self, VLK_ARMOR_L);
CreateInvItem (self, VLK_ARMOR_M);
CreateInvItem (self, SFB_ARMOR_L);
CreateInvItem (self, TPL_ARMOR_L);
CreateInvItem (self, TPL_ARMOR_M);
CreateInvItem (self, TPL_ARMOR_H);
CreateInvItem (self, STT_ARMOR_M);
CreateInvItem (self, STT_ARMOR_H);
CreateInvItem (self, GRD_ARMOR_L);
CreateInvItem (self, GRD_ARMOR_M);
CreateInvItem (self, GRD_ARMOR_H);
CreateInvItem (self, KDF_ARMOR_L);
CreateInvItem (self, KDF_ARMOR_H);
CreateInvItem (self, KDW_ARMOR_L);
CreateInvItem (self, KDW_ARMOR_H);
CreateInvItem (self, GUR_ARMOR_M);
CreateInvItem (self, GUR_ARMOR_H);
CreateInvItem (self, ORG_ARMOR_L);
CreateInvItem (self, ORG_ARMOR_M);
CreateInvItem (self, ORG_ARMOR_H);
CreateInvItem (self, SLD_ARMOR_L);
CreateInvItem (self, SLD_ARMOR_M);
CreateInvItem (self, SLD_ARMOR_H);
CreateInvItem (self, NOV_ARMOR_L);
CreateInvItem (self, NOV_ARMOR_M);
CreateInvItem (self, NOV_ARMOR_H);
CreateInvItem (self, CRW_ARMOR_H);
CreateInvItem (self, DMB_ARMOR_M);
CreateInvItem (self, ORE_ARMOR_M);
CreateInvItem (self, ORE_ARMOR_H);
CreateInvItem (self, EBR_ARMOR_M);
CreateInvItem (self, EBR_ARMOR_H);
CreateInvItem (self, EBR_ARMOR_H2);
CreateInvItem (self, GRD_ARMOR_I);
CreateInvItem (self, PIRATE_ARMOR_M);
CreateInvItem (self, DEMENTOR_ARMOR);
CreateInvItem (self, LAW_ARMOR);
start_aistate = ZS_FH_Hangaround;
};
FUNC VOID FH_ChangeVisual ()
{
var C_NPC npc; npc = Hlp_GetNPC (FH);
NPC_UnEquip_invCategory (npc, INV_ARMOR);
// body mesh, bdytex skin, head mesh, headtex, teethtex, ruestung
Mdl_SetVisualBody (npc, "hum_body_Naked0", FaceHelper_BodyTex, FaceHelper_Skin, FaceHelper_HeadMesh_Name, FaceHelper_HeadTex, FaceHelper_TeethTex, -1);
if (FaceHelper_Armor_Instance != -1) {
AI_EquipArmor (npc, FaceHelper_Armor_Instance);
};
};
INSTANCE FaceHelper_Exit (C_Info)
{
nr = 999;
condition = FaceHelper_Exit_Condition;
information = FaceHelper_Exit_Info;
important = FALSE;
permanent = TRUE;
description = DIALOG_ENDE;
};
FUNC INT FaceHelper_Exit_Condition () {
if (PLAYER_MOBSI_PRODUCTION == MOBSI_FACEHELPER) {
return TRUE;
};
return FALSE;
};
FUNC VOID FaceHelper_Exit_Info () {
PLAYER_MOBSI_PRODUCTION = MOBSI_NONE;
AI_StopProcessInfos (self);
};
INSTANCE FaceHelper_HeadMesh_Change (C_Info)
{
nr = 5;
condition = FaceHelper_HeadMesh_Change_Condition;
information = FaceHelper_Exit_Info ;
important = FALSE;
permanent = TRUE;
description = "dummy";
};
FUNC INT FaceHelper_HeadMesh_Change_Condition () {
if (PLAYER_MOBSI_PRODUCTION == MOBSI_FACEHELPER) {
//Figure out if we need to reset InfoManagerSpinnerValue value
var string lastSpinnerID; //Actually global variable! ;-)
if (Hlp_StrCmp (InfoManagerSpinnerID, "1")) {
//Setup spinner if spinner ID has changed
if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID)) {
InfoManagerSpinnerValue = FaceHelper_HeadMesh;
};
InfoManagerSpinnerValueMin = 0;
InfoManagerSpinnerValueMax = FaceHelper_HeadMesh_Max;
//Update Face Helper visual if spinner changed
if (FaceHelper_HeadMesh != InfoManagerSpinnerValue) {
FaceHelper_HeadMesh = InfoManagerSpinnerValue;
if (FaceHelper_HeadMesh == 0) { FaceHelper_HeadMesh_Name = "HUM_HEAD_PSIONIC"; } else
if (FaceHelper_HeadMesh == 1) { FaceHelper_HeadMesh_Name = "HUM_HEAD_FIGHTER"; } else
if (FaceHelper_HeadMesh == 2) { FaceHelper_HeadMesh_Name = "HUM_HEAD_THIEF"; } else
if (FaceHelper_HeadMesh == 3) { FaceHelper_HeadMesh_Name = "HUM_HEAD_STD_PONY"; } else
if (FaceHelper_HeadMesh == 4) { FaceHelper_HeadMesh_Name = "HUM_HEAD_PONY"; } else
if (FaceHelper_HeadMesh == 5) { FaceHelper_HeadMesh_Name = "HUM_HEAD_FATBALD"; } else
if (FaceHelper_HeadMesh == 6) { FaceHelper_HeadMesh_Name = "HUM_HEAD_BALD"; };
FH_ChangeVisual ();
};
};
lastSpinnerID = InfoManagerSpinnerID;
var string newDescription;
//Spinner ID 1
newDescription = "s@1 <-- ";
newDescription = ConcatStrings (newDescription, FaceHelper_HeadMesh_Name);
newDescription = ConcatStrings (newDescription, " --> ");
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_HeadMesh));
newDescription = ConcatStrings (newDescription, " / ");
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_HeadMesh_Max));
//Update description
FaceHelper_HeadMesh_Change.description = newDescription;
return TRUE;
};
return FALSE;
};
INSTANCE FaceHelper_BodyTex_Change (C_Info) {
nr = 10;
condition = FaceHelper_BodyTex_Change_Condition;
information = FaceHelper_Exit_Info ;
important = FALSE;
permanent = TRUE;
description = "dummy";
};
FUNC INT FaceHelper_BodyTex_Change_Condition () {
if (PLAYER_MOBSI_PRODUCTION == MOBSI_FACEHELPER) {
//Figure out if we need to reset InfoManagerSpinnerValue value
var string lastSpinnerID; //Actually global variable! ;-)
if (Hlp_StrCmp (InfoManagerSpinnerID, "2")) {
//Setup spinner if spinner ID has changed
if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID)) {
InfoManagerSpinnerValue = FaceHelper_BodyTex;
};
InfoManagerSpinnerValueMin = 0;
InfoManagerSpinnerValueMax = FaceHelper_BodyTex_Max;
//Update Face Helper visual if spinner changed
if (FaceHelper_BodyTex != InfoManagerSpinnerValue) {
FaceHelper_BodyTex = InfoManagerSpinnerValue;
FH_ChangeVisual ();
};
};
lastSpinnerID = InfoManagerSpinnerID;
var string newDescription;
//Spinner ID 2
newDescription = "s@2 <-- BodyTex --> ";
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_BodyTex));
newDescription = ConcatStrings (newDescription, " / ");
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_BodyTex_Max));
//Update description
FaceHelper_BodyTex_Change.description = newDescription;
return TRUE;
};
return FALSE;
};
INSTANCE FaceHelper_Skin_Change (C_Info) {
nr = 15;
condition = FaceHelper_Skin_Change_Condition;
information = FaceHelper_Exit_Info ;
important = FALSE;
permanent = TRUE;
description = "dummy";
};
FUNC INT FaceHelper_Skin_Change_Condition ()
{
if (PLAYER_MOBSI_PRODUCTION == MOBSI_FACEHELPER) {
//Figure out if we need to reset InfoManagerSpinnerValue value
var string lastSpinnerID; //Actually global variable! ;-)
if (Hlp_StrCmp (InfoManagerSpinnerID, "3")) {
//Setup spinner if spinner ID has changed
if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID)) {
InfoManagerSpinnerValue = FaceHelper_Skin;
};
InfoManagerSpinnerValueMin = 0;
InfoManagerSpinnerValueMax = FaceHelper_Skin_Max;
//Update Face Helper visual if spinner changed
if (FaceHelper_Skin != InfoManagerSpinnerValue) {
FaceHelper_Skin = InfoManagerSpinnerValue;
FH_ChangeVisual ();
};
};
lastSpinnerID = InfoManagerSpinnerID;
var string newDescription;
//Spinner ID 3
newDescription = "s@3 <-- Skin --> ";
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_Skin));
newDescription = ConcatStrings (newDescription, " / ");
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_Skin_Max));
//Update description
FaceHelper_Skin_Change.description = newDescription;
return TRUE;
};
return FALSE;
};
INSTANCE FaceHelper_HeadTex_Change (C_Info) {
nr = 20;
condition = FaceHelper_HeadTex_Change_Condition;
information = FaceHelper_Exit_Info ;
important = FALSE;
permanent = TRUE;
description = "dummy";
};
FUNC INT FaceHelper_HeadTex_Change_Condition () {
if (PLAYER_MOBSI_PRODUCTION == MOBSI_FACEHELPER) {
//Figure out if we need to reset InfoManagerSpinnerValue value
var string lastSpinnerID; //Actually global variable! ;-)
if (Hlp_StrCmp (InfoManagerSpinnerID, "4")) {
//Setup spinner if spinner ID has changed
if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID)) {
InfoManagerSpinnerValue = FaceHelper_HeadTex;
};
InfoManagerSpinnerValueMin = 0;
InfoManagerSpinnerValueMax = FaceHelper_HeadTex_Max;
//Update Face Helper visual if spinner changed
if (FaceHelper_HeadTex != InfoManagerSpinnerValue) {
FaceHelper_HeadTex = InfoManagerSpinnerValue;
FH_ChangeVisual ();
};
};
lastSpinnerID = InfoManagerSpinnerID;
var string newDescription;
//Spinner ID 4
newDescription = "s@4 <-- HeadTex --> ";
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_HeadTex));
newDescription = ConcatStrings (newDescription, " / ");
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_HeadTex_Max));
//Update description
FaceHelper_HeadTex_Change.description = newDescription;
return TRUE;
};
return FALSE;
};
INSTANCE FaceHelper_TeethTex_Change (C_Info) {
nr = 25;
condition = FaceHelper_TeethTex_Change_Condition;
information = FaceHelper_Exit_Info ;
important = FALSE;
permanent = TRUE;
description = "dummy";
};
FUNC INT FaceHelper_TeethTex_Change_Condition () {
if (PLAYER_MOBSI_PRODUCTION == MOBSI_FACEHELPER) {
//Figure out if we need to reset InfoManagerSpinnerValue value
var string lastSpinnerID; //Actually global variable! ;-)
if (Hlp_StrCmp (InfoManagerSpinnerID, "5")) {
//Setup spinner if spinner ID has changed
if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID)) {
InfoManagerSpinnerValue = FaceHelper_TeethTex;
};
InfoManagerSpinnerValueMin = 0;
InfoManagerSpinnerValueMax = FaceHelper_TeethTex_Max;
//Update Face Helper visual if spinner changed
if (FaceHelper_TeethTex != InfoManagerSpinnerValue) {
FaceHelper_TeethTex = InfoManagerSpinnerValue;
FH_ChangeVisual ();
};
};
lastSpinnerID = InfoManagerSpinnerID;
var string newDescription;
//Spinner ID 5
newDescription = "s@5 <-- TeethTex --> ";
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_TeethTex));
newDescription = ConcatStrings (newDescription, " / ");
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_TeethTex_Max));
//Update description
FaceHelper_TeethTex_Change.description = newDescription;
return TRUE;
};
return FALSE;
};
INSTANCE FaceHelper_Armor_Change (C_Info) {
nr = 30;
condition = FaceHelper_Armor_Change_Condition;
information = FaceHelper_Exit_Info ;
important = FALSE;
permanent = TRUE;
description = "dummy";
};
FUNC INT FaceHelper_Armor_Change_Condition ()
{
if (PLAYER_MOBSI_PRODUCTION == MOBSI_FACEHELPER) {
//Figure out if we need to reset InfoManagerSpinnerValue value
var string lastSpinnerID; //Actually global variable! ;-)
if (Hlp_StrCmp (InfoManagerSpinnerID, "6")) {
//Setup spinner if spinner ID has changed
if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID)) {
InfoManagerSpinnerValue = FaceHelper_Armor;
};
InfoManagerSpinnerValueMin = -1;
InfoManagerSpinnerValueMax = FaceHelper_Armor_Max;
//Update Face Helper visual if spinner changed
if (FaceHelper_Armor != InfoManagerSpinnerValue) {
FaceHelper_Armor = InfoManagerSpinnerValue;
if (FaceHelper_Armor == -1) { FaceHelper_Armor_Name = "NO ARMOR"; FaceHelper_Armor_Instance = -1; } else
if (FaceHelper_Armor == 0) { FaceHelper_Armor_Name = "VLK_ARMOR_L"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (VLK_ARMOR_L); } else
if (FaceHelper_Armor == 1) { FaceHelper_Armor_Name = "VLK_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (VLK_ARMOR_M); } else
if (FaceHelper_Armor == 2) { FaceHelper_Armor_Name = "SFB_ARMOR_L"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (SFB_ARMOR_L); } else
if (FaceHelper_Armor == 3) { FaceHelper_Armor_Name = "TPL_ARMOR_L"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (TPL_ARMOR_L); } else
if (FaceHelper_Armor == 4) { FaceHelper_Armor_Name = "TPL_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (TPL_ARMOR_M); } else
if (FaceHelper_Armor == 5) { FaceHelper_Armor_Name = "TPL_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (TPL_ARMOR_H); } else
if (FaceHelper_Armor == 6) { FaceHelper_Armor_Name = "STT_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (STT_ARMOR_M); } else
if (FaceHelper_Armor == 7) { FaceHelper_Armor_Name = "STT_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (STT_ARMOR_H); } else
if (FaceHelper_Armor == 8) { FaceHelper_Armor_Name = "GRD_ARMOR_L"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (GRD_ARMOR_L); } else
if (FaceHelper_Armor == 9) { FaceHelper_Armor_Name = "GRD_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (GRD_ARMOR_M); } else
if (FaceHelper_Armor == 10) { FaceHelper_Armor_Name = "GRD_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (GRD_ARMOR_H); } else
if (FaceHelper_Armor == 11) { FaceHelper_Armor_Name = "KDF_ARMOR_L"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (KDF_ARMOR_L); } else
if (FaceHelper_Armor == 12) { FaceHelper_Armor_Name = "KDF_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (KDF_ARMOR_H); } else
if (FaceHelper_Armor == 13) { FaceHelper_Armor_Name = "KDW_ARMOR_L"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (KDW_ARMOR_L); } else
if (FaceHelper_Armor == 14) { FaceHelper_Armor_Name = "KDW_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (KDW_ARMOR_H); } else
if (FaceHelper_Armor == 15) { FaceHelper_Armor_Name = "GUR_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (GUR_ARMOR_M); } else
if (FaceHelper_Armor == 16) { FaceHelper_Armor_Name = "GUR_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (GUR_ARMOR_H); } else
if (FaceHelper_Armor == 17) { FaceHelper_Armor_Name = "ORG_ARMOR_L"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (ORG_ARMOR_L); } else
if (FaceHelper_Armor == 18) { FaceHelper_Armor_Name = "ORG_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (ORG_ARMOR_M); } else
if (FaceHelper_Armor == 19) { FaceHelper_Armor_Name = "ORG_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (ORG_ARMOR_H); } else
if (FaceHelper_Armor == 20) { FaceHelper_Armor_Name = "SLD_ARMOR_L"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (SLD_ARMOR_L); } else
if (FaceHelper_Armor == 21) { FaceHelper_Armor_Name = "SLD_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (SLD_ARMOR_M); } else
if (FaceHelper_Armor == 22) { FaceHelper_Armor_Name = "SLD_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (SLD_ARMOR_H); } else
if (FaceHelper_Armor == 23) { FaceHelper_Armor_Name = "NOV_ARMOR_L"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (NOV_ARMOR_L); } else
if (FaceHelper_Armor == 24) { FaceHelper_Armor_Name = "NOV_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (NOV_ARMOR_M); } else
if (FaceHelper_Armor == 25) { FaceHelper_Armor_Name = "NOV_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (NOV_ARMOR_H); } else
if (FaceHelper_Armor == 26) { FaceHelper_Armor_Name = "CRW_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (CRW_ARMOR_H); } else
if (FaceHelper_Armor == 27) { FaceHelper_Armor_Name = "DMB_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (DMB_ARMOR_M); } else
if (FaceHelper_Armor == 28) { FaceHelper_Armor_Name = "ORE_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (ORE_ARMOR_M); } else
if (FaceHelper_Armor == 29) { FaceHelper_Armor_Name = "ORE_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (ORE_ARMOR_H); } else
if (FaceHelper_Armor == 30) { FaceHelper_Armor_Name = "EBR_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (EBR_ARMOR_M); } else
if (FaceHelper_Armor == 31) { FaceHelper_Armor_Name = "EBR_ARMOR_H"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (EBR_ARMOR_H); } else
if (FaceHelper_Armor == 32) { FaceHelper_Armor_Name = "EBR_ARMOR_H2"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (EBR_ARMOR_H2); } else
if (FaceHelper_Armor == 33) { FaceHelper_Armor_Name = "GRD_ARMOR_I"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (GRD_ARMOR_I); } else
if (FaceHelper_Armor == 34) { FaceHelper_Armor_Name = "PIRATE_ARMOR_M"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (PIRATE_ARMOR_M); } else
if (FaceHelper_Armor == 35) { FaceHelper_Armor_Name = "DEMENTOR_ARMOR"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (DEMENTOR_ARMOR); } else
if (FaceHelper_Armor == 36) { FaceHelper_Armor_Name = "LAW_ARMOR"; FaceHelper_Armor_Instance = Hlp_GetInstanceID (LAW_ARMOR); };
FH_ChangeVisual ();
};
};
lastSpinnerID = InfoManagerSpinnerID;
var string newDescription;
//Spinner ID 6
newDescription = "s@6 <-- ";
newDescription = ConcatStrings (newDescription, FaceHelper_Armor_Name);
newDescription = ConcatStrings (newDescription, " --> ");
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_Armor));
newDescription = ConcatStrings (newDescription, " / ");
newDescription = ConcatStrings (newDescription, IntToString (FaceHelper_Armor_Max));
//Update description
FaceHelper_Armor_Change.description = newDescription;
return TRUE;
};
return FALSE;
};
FUNC VOID FH_Dialogs () {
PLAYER_MOBSI_PRODUCTION = MOBSI_FACEHELPER;
FaceHelper_Exit.npc = Hlp_GetInstanceID (hero);
FaceHelper_HeadMesh_Change.npc = Hlp_GetInstanceID (hero);
FaceHelper_BodyTex_Change.npc = Hlp_GetInstanceID (hero);
FaceHelper_Skin_Change.npc = Hlp_GetInstanceID (hero);
FaceHelper_HeadTex_Change.npc = Hlp_GetInstanceID (hero);
FaceHelper_TeethTex_Change.npc = Hlp_GetInstanceID (hero);
FaceHelper_Armor_Change.npc = Hlp_GetInstanceID (hero);
AI_ProcessInfos (hero);
};
3. Sleep a bit
Script uses functions Wld_GetHour & Wld_GetMinute from Nodrog:
https://forum.worldofplayers.de/foru...=1#post7741998
Code:
func void PC_Sleep (var int t) {
AI_StopProcessInfos (self);
self.aivar[AIV_INVINCIBLE] = FALSE;
if (Wld_IsTime (00, 00, t, 00)) {
Wld_SetTime (t, 00);
} else {
t = t + 24;
Wld_SetTime (t, 00);
};
PrintScreen ("You slept well and feel better", -1,-1,"font_old_20_white.tga",3);
hero.attribute[ATR_HITPOINTS] = hero.attribute[ATR_HITPOINTS_MAX];
hero.attribute[ATR_MANA] = hero.attribute[ATR_MANA_MAX];
Npc_SendPassivePerc (hero, PERC_ASSESSENTERROOM, NULL, hero);
};
INSTANCE PC_NoSleep (c_Info) {
npc = PC_Hero;
nr = 999;
condition = PC_NoSleep_Condition;
information = PC_NoSleep_Info;
important = 0;
permanent = 1;
description = DIALOG_ENDE;
};
FUNC INT PC_NoSleep_Condition () {
return 1;
};
func VOID PC_NoSleep_Info () {
PLAYER_MOBSI_PRODUCTION = MOBSI_DIALOG_NONE;
AI_StopProcessInfos (self);
self.aivar[AIV_INVINCIBLE] = FALSE;
};
instance PC_Sleep_SetHour (C_Info)
{
nr = 1;
condition = PC_Sleep_SetHour_Condition;
information = PC_Sleep_SetHour_Info;
important = FALSE;
permanent = TRUE;
description = "dummy";
};
FUNC INT PC_Sleep_SetHour_Condition ()
{
if (PLAYER_MOBSI_PRODUCTION == MOBSI_DIALOG_SLEEP) {
//Figure out if we need to reset InfoManagerSpinnerValue value
var string lastSpinnerID; //Actually global variable! ;-)
const int sleepHour = -1;
if (Hlp_StrCmp (InfoManagerSpinnerID, "1")) {
//Setup spinner if spinner ID has changed
if (!Hlp_StrCmp (InfoManagerSpinnerID, lastSpinnerID)) {
InfoManagerSpinnerValue = Wld_GetHour (0, 23) + 1;
};
//Page Up/Down value
InfoManagerSpinnerPageSize = 4;
InfoManagerSpinnerValueMin = 0;
InfoManagerSpinnerValueMax = 23;
sleepHour = InfoManagerSpinnerValue;
};
lastSpinnerID = InfoManagerSpinnerID;
var string newDescription;
//Spinner ID 1
newDescription = "s@1 Current time: ";
var int hh; hh = Wld_GetHour (0, 23);
var int mm; mm = Wld_GetMinute (hh, 0, 59);
if (hh < 10) {
newDescription = ConcatStrings (newDescription, "0");
};
newDescription = ConcatStrings (newDescription, IntToString (hh));
newDescription = ConcatStrings (newDescription, ":");
if (mm < 10) {
newDescription = ConcatStrings (newDescription, "0");
};
newDescription = ConcatStrings (newDescription, IntToString (mm));
newDescription = ConcatStrings (newDescription, " sleep until time: ");
if (sleepHour < 10) {
newDescription = ConcatStrings (newDescription, "0");
};
newDescription = ConcatStrings (newDescription, IntToString (sleepHour));
newDescription = ConcatStrings (newDescription, ":00");
//Update description
PC_Sleep_SetHour.description = newDescription;
return TRUE;
};
return FALSE;
};
func void PC_Sleep_SetHour_Info () {
PC_Sleep (InfoManagerSpinnerValue);
};
func void SLEEPABIT_S1 () {
var C_NPC her; her = Hlp_GetNpc(PC_Hero);
var C_NPC rock; rock = Hlp_GetNpc(PC_Rockefeller);
if ((Hlp_GetInstanceID (self) == Hlp_GetInstanceID (her)) || (Hlp_GetInstanceID (self) == Hlp_GetInstanceID (rock))) {
PLAYER_MOBSI_PRODUCTION = MOBSI_DIALOG_SLEEP;
self.aivar[AIV_INVINCIBLE] = TRUE;
//Default
InfoManagerSpinnerID = "";
InfoManagerSpinnerValue = Wld_GetHour (0, 23) + 1;
PC_NoSleep.npc = Hlp_GetInstanceID (self);
PC_Sleep_SetHour.npc = Hlp_GetInstanceID (self);
AI_ProcessInfos (self);
};
};
Let me know in case you face any issues
Geändert von F a w k e s (19.09.2020 um 21:30 Uhr)
-
Thanks for sharing your code! Isn't strings.d already covered by LeGo or am I mistaking something?
I'm also unsure when to parse this. After the dialogue scripts or just right after Ikarus and LeGo?
I'll also make my important choices red now instead of writing ENTSCHEIDUNG in front of it. Will work better.
And creating items will be much better with your newest addition
"Das erinnert doch sehr erfreulich an das, was man sich als Gothicfan wünscht!"
-Korallenkette
-
Hello Bisasam, both strings.d and convert.d packages are still required, as script uses function hex2dec (convert.d), hex2dec then uses STR_ReplaceAll (strings.d). I think none of these are available in LeGo, only issue you might have with strings.d is function STR_Lower - comment that one out (it was part of Ikarus 1.2.2 I had to comment it out).
As for parsing - you can parse these functions after LeGo, that's how I am doing it (I hope I dind't forget anything, let me know in case you see something is wrong)
-
Wow F a w k e s! I am mega thankful and impressed with your awesome work!
-
@Moe I am thankful to Bisasam, without inspiration coming from her post it would probably not occur to me to try this !
Script in first post updated one more time. I have added two things:- 'spinner' dialog indicator in right corner '<>' hinting that you can use left-right arrows: 'answer' dialog indicator is three dots '...', probably not required as much, but wont harm.
- text alignment option, by adjusting constant InfoManagerDefaultDialogAlignment you can control alignment of all dialog options. When value is 0 (default), text is aligned to left, when value is 1 text is aligned in center of screen, when value is 2 text is aligned to right. Below example with alignment of all texts in center: + added new modifiers in case someone would want to use text alignment on individual dialogs "al@" align left, "ac@" align center, "ar@" align right.
-
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|
|