Is there any possibility to create a text multi-colored in one line?
What do you mean with a multi-colored text?
Every zCViewText can at most be colored with 1 value, so you'll have to emulate that and create multiple zCViewTexts according to your (coloring) needs.
When I'm trying to change hero to for example: "PAL_203_LOTHAR" code work's correct, but when I'm trying change to PC_HERO i have error-box, and after box crash.
Message in infobox:
Code:
U: NPC: Object tries to save reference of player during levelchange. This is not allowed.
Ok I found info about this message. This message is displayed only when you using zSpy. This message is called in oCNpc:rchive(zCArchiver&), when game tries save hero data before load world. I think that if I remove old hero from world this code can work correct (without message).
// HookEngine
const int oCNpc__OpenScreenStatus_Addr = 7593693; // 0x0073DEDD
const int oCNpc__OpenScreenStatus_Len = 5; // 0x05
HookEngineF(oCNpc__OpenScreenStatus_Addr,
oCNpc__OpenScreenStatus_Len,
hShowPlayerStatus);
I always have debug print, but position is changed only one time. Better way is get zCView* object from "MENU_STATUS", but every pointer to zCView* in class zCMenu return NULL!
zCMenu isn't inheritance zCView class :/
I have some questions about Assembler and Ikarus.
I hooked this:
[img]https://i.imgur.com/0vve6yF.png[/img]
1) And how can i get default ECX? (It's method oCItemContainer:raw, so in begining ECX is oCItemContainer, but now I don't know what's ECX, and how can i get oCItemContainer pointer from this address)
2) How can i get pointer to zCView from previous address?
3) How it's work? It's exist a tutorial about registers?
I have some questions about Assembler and Ikarus.
I hooked this:
[img]https://i.imgur.com/0vve6yF.png[/img]
1) And how can i get default ECX? (It's method oCItemContainer:raw, so in begining ECX is oCItemContainer, but now I don't know what's ECX, and how can i get oCItemContainer pointer from this address)
2) How can i get pointer to zCView from previous address?
3) How it's work? It's exist a tutorial about registers?
Regards.
1) You will have to look at the function and see where ecx is stored before it's overwritten (I think ECX is supposed to be preserved, so the function has to store it). It will probably be on the stack somewhere, so you can use ESP or EBP and an offset to get the pointer.
2) Looks like it should either be in ECX or definitely at MEM_RedInt(EBP+128).
3) A brief description can be found here (the General Purpose Registers are the important ones). Generally a registers is nothing else than a variable that can have a 32bit (or 16/8bit) value, but of course there are some special registers and some that are used in a certain way by convention (e.g. ecx, eax).
Now it's easy
It's logic BASE POINTER...
Anyway, I have question - I have code in IDA: https://i.imgur.com/0iglYMB.png
And I want to disable "jmb loc_70813D.
I have code:
This code is intended to remove red numbers in inventory (Remove print forever). I think it's good address, but number is not removed.
(I don't have crash etc.)
@mud-freak i don't understand :/ Address in decimal is wrong?
I checked address, but it's don't work :/ (View everytime prints number)
I'm trying to disable this part of code: https://i.imgur.com/Utee57Z.png
Code:
func void QS_WriteNOP(var int address, var int numBytes)
{
if(!IsHooked(address)) {
return;
};
MemoryProtectionOverride(address, numBytes);
repeat(i, numBytes); var int i;
MEM_WriteByte(address+i, ASMINT_OP_nop);
end;
};
// Init global
QS_WriteNOP(7372773, 5);
But it's don't work. Every time engine print's this numbers :/
1. If you remove the call at that address, you will leave a corrupt stack, because several values have been pushed onto the stack, which are usually removed by the return instruction of the function. If the function is not called, these values stay on the stack. You either need to overwrite the function with something like add esp, X (where X is the number of values pushed on the stack times their size, typically 4 bytes), or you also overwrite all the push instructions with no-ops.
2. You copied the code from the function incorrectly. The condition has to be reversed, otherwise you jump out of the function immediately.
On a related note: This code originally stems from GFA. Since this forum is a way to share ideas, posting code is a form of publishing it publicly. These are 10 lines of code, i.e. a substantial portion of GFA. You'll have to adhere to the license conditions and name the original author/project. This might seem a bit nitpicky, but I'm trying to make a point. If you'd have included the source, anyone (including yourself) would have been able to tell you that the if-condition is wrong.
Ok I have - I changed positon of text, and it's work very good
About GFA - I have in every file, licence for my script (QuickSlots), and it's there:
"I used some scripts from GFA (Author: @mud-freak Link: https://github.com/szapp/GothicFreeAim)"
It's my mistake, because I didn't write about this in my post - sorry
Ikarus make memory dump after close game? I'm have every time crash, after trying load save when, game was reinited. It's stacktrace: https://i.imgur.com/x15xgVJ.png
So, problem is in QS_Remove slot:
Code:
func void QS_RemoveSlot(var int nr)
{
var int slotPtr; slotPtr = MEM_ReadStatArr(QS_Data, nr);
if(!slotPtr) {
return;
};
if(nr == QS_LastWeaponSlot) { QS_LastWeaponSlot = -1; };
var int pView; pView = MEM_ReadInt(slotPtr + CSlot__pView_offset);
var int pViewText; pViewText = MEM_ReadInt(slotPtr + CSlot__pViewText_offset);
if(pView) {
ViewPtr_Delete(pView);
};
if(pViewText) {
ViewPtr_Delete(pViewText);
};
MEM_Free(slotPtr);
MEM_WriteStatArr (QS_Data, nr, 0);
MEM_WriteStatArr (QS_ArchData, nr, 0);
};
Slot is created in this function:
Code:
func void QS_CreateSlot(var int nr, var int itemPtr)
{
if(!itemPtr) { return; };
var int slotPtr; slotPtr = MEM_Alloc(CSlot__sizeof);
var int x; x = QS_GetPosX(nr);
var oCItem it; it = _^(itemPtr);
var int pView; pView = ViewPtr_CreateCenter( QS_anx(x), QS_any(QS_SlotPosY),
QS_anx(QS_SlotSize), QS_any(QS_SlotSize));
MEM_WriteInt (slotPtr + CSlot__pItem_offset, itemPtr);
MEM_WriteInt (slotPtr + CSlot__pView_offset, pView);
MEM_WriteInt (slotPtr + CSlot__pViewText_offset, pView);
MEM_WriteStatArr (QS_Data, nr, slotPtr);
MEM_WriteStatArr (QS_ArchData, nr, it.instanz);
pView = 0;
};
And I use this two functions in "Archive data"
Code:
func void QS_RestorePointer()
{
repeat(i, 10); var int i;
var int slotPtr; slotPtr = MEM_ReadStatArr(QS_Data, i);
var int itemInst; itemInst = MEM_ReadStatArr(QS_ArchData, i);
if(slotPtr && itemInst)
{
var int itemPtr; itemPtr = ITM_GetPtr(itemInst);
QS_RemoveSlot(i);
QS_CreateSlot(i, itemPtr);
//MEM_WriteInt(slotPtr + CSlot__pItem_offset, itemPtr);
};
end;
};
func void QS_RestorePointer_Listener(var int state)
{
if (state == GAMESTATE_SAVING || state == GAMESTATE_LOADED) {
QS_RestorePointer();
};
};
// Called in init global
func void QS_RestoreData()
{
QS_RestorePointer();
GameState_AddListener(QS_RestorePointer_Listener);
};
So how I must destroy slots (zCView objects)? I can't use PermMem, so I'm using pointers. But I don't know about memory dump - how can i made this good?
//######################################################
//
// Speicherkontrolle
//
//######################################################
/* Von Dir auszufullende Funktion!
* Entscheide ob man gerade Speichern darf oder nicht.
* Gibt den entsprechenden Wert zuruck. */
func int AllowSaving() {
/* Voreingestellt: Speichern immer erlaubt */
return TRUE;
};
/* Wird aufgerufen, wenn Speichern verboten war,
* jetzt aber gerade wieder erlaubt wurde. */
/*func void OnAllowSaving() {
Print ("Сохранения разрешены!");
};*/
/* Wird aufgerufen, wenn Speichern erlaubt war,
* jetzt aber gerade wieder verboten wurde. */
/*func void OnDisallowSaving() {
Print ("Сохранения запрещены!");
};*/
//######################################################
//
// INTERNAS - Andern auf eigene Gefahr
//
//######################################################
/* Benotigte Konstante */
const INT IT_ONLY_OUT_GAME = 256;
/* War speichern beim letzten Check erlaubt? Fur Benachrichtigungsfunktionen. */
var int SavingDisabled_LastCheck;
/* Hier steht ob Quicksaves an sind: */
const int s_bUseQuickSave_address = 9118160; //0x8B21D0
/* Funktion fur den Nutzer, die AllowSaving auswertet und umsetzt */
instance saveMenuItem (zCMenuItem);
func void EnforceSavingPolicy() {
//--------------------------------------
// Menuitem holen:
//--------------------------------------
var int saveMenuItemPtr;
saveMenuItemPtr = MEM_GetMenuItemByString ("MENUITEM_MAIN_SAVEGAME_SAVE");
if (!saveMenuItemPtr) {
//wtf?
var string err; err = "EnforceSavingPolicy: MENUITEM_MAIN_SAVEGAME_SAVE not found!?";
Print (err); PrintDebug (err);
return;
};
MEM_AssignInst (saveMenuItem, saveMenuItemPtr);
//--------------------------------------
// Der eigentliche Code:
//--------------------------------------
if (!AllowSaving()) {
saveMenuItem.m_parItemFlags = saveMenuItem.m_parItemFlags | IT_ONLY_OUT_GAME;
/* Scripter benachrichten, falls wirkliche Anderung */
if (!SavingDisabled_LastCheck) {
SavingDisabled_LastCheck = TRUE;
//OnDisallowSaving();
//Quicksave aus.
MEM_WriteInt (s_bUseQuickSave_address, 0);
};
} else {
/* Speichern ist erlaubt */
saveMenuItem.m_parItemFlags = saveMenuItem.m_parItemFlags &~ IT_ONLY_OUT_GAME;
/* Scripter benachrichten, falls wirkliche Anderung */
if (SavingDisabled_LastCheck) {
SavingDisabled_LastCheck = 0;
//OnAllowSaving();
//Quicksave an:
MEM_WriteInt (s_bUseQuickSave_address, 1);
};
};
};
Hello. I would like to use this function, but due to the fact that I did not quite understand how to change the state, AllowSaving() had to give up. The idea was the following, to prohibit the use of save in the state of conversation ZS_Talk. For earlier you put FALSE, everything works, and I think it will be useful to return the state to TRUE everywhere, because saving in the dialog causes numerous bugs and damage to the save.
zs_talk.d