qiaky
05.11.2013, 13:38
Wer sich mit der Preisbestimmung in Gothic 2 auseinander gesetzt hat ist früher oder später bestimmt über den Eintrag
const float TRADE_VALUE_MULTIPLIER = 0.15;
in der constants.d gestolpert.
Dieser bestimmt die Wertsenkung von Items beim Verkauf. 0.15 bedeutet z.B., dass der Spielercharakter Gegenstände mit einem Wert von 100 für 100 * 0.15 = 15 Gold verkauft.
Der Wert kann recht einfach geändert werden, constants.d öffnen, gewünschten Wert eintragen, speichern, Skripte parsen (Gothic.dat Kompilat erstellen).
Problem ist: Der Wert wird beim Start der Gothic2.exe einmalig von der Engine ausgelesen und dann wird der eingetragene Wert ignoriert. D.h um den Wert zu verändern würde es einen Gothic-Neustart brauchen und Skripte mit Statements wie
TRADE_VALUE_MULTIPLIER = NEW_VALUE;
sind hinfällig.
Mit den Ikarus Funktionen MEM_WriteInt und MEM_ReadInt kann der Wert auch während dem laufenden Spiel per Skript geändert werden.
Die benötigte Speicheradresse ist:
// TRADE_VALUE_MULTIPLIER ADDRESS:
const int Float__ENGINE_TRADEX = 11211032; //0x00AB1118
Auf diese kann bequem mit MEM_WriteInt und MEM_ReadInt zugegriffen werden.
MEM_WriteInt(Float__EngineMultiplier, NEW_MULTIPLIER);
MEM_ReadInt(Float__EngineMultiplier);
Nun handelt es sich aber bei der Wertübergabe jeweils um Integer, während der TRADE_VALUE_MULTIPLIER ja eine Kommazahl, eine sogenannte Float ist.
Zum Glück hat Sektenspinner Floats in Gothic implementiert. Da die reservierte Speicheradresse 32 bit groß ist, können wir per MEM_WriteInt auch einen 32 bit Float schreiben, solange der ByteCode (HexCode) stimmt. Das übernimmt die float-Funktion
CastToIntf(float)
für uns. Beim Lesen mit MEM_ReadInt ist die entsprechende Funktion
CastFromIntf(int)
Somit erhalten wir zwei Funktionen:
// TRADE_VALUE_MULTIPLIER ADDRESS:
const int Float__ENGINE_TRADEX = 11211032; //0x00AB1118
// Schreibt den neuen Wert NEW_MULTIPLIER an die Speicheradresse
func void SetTradeValueMultiplier(var float NEW_MULTIPLIER)
{
var int NEW_VALUE; NEW VALUE = CastToIntf(NEW_MULTIPLIER);
MEM_WriteInt(Float__EngineMultiplier, NEW_VALUE);
};
// fragt den Wert der Speicheradresse ab und übergibt ihn als Float
func float GetTradeValueMultiplier()
{
return CastFromIntf(MEM_ReadInt(Float__EngineMultiplier));
};
Somit kann man z.B. verschiedene Händler verschiedene Preise haben lassen (in den DIA_npc C_Info aufrufen) oder ein neues Talent für feilschen erstellen (bei der Talenterhöhung aufrufen).
Wichtig zu wissen ist, dass der gesetzte Wert für TRADE_VALUE_MULTIPLIER in der Adresse 0x00AB1118 nicht ins Savegame wandert. Deshalb ist eine Initialisierung des Wertes in der Init_Global() (startup.d) notwendig.
EDIT: Methode funktioniert nur für den angezeigten Wert des Gegenstandes, das übertragene Gold wird anderswo im Code berechnet, siehe hier und hier
Viel Spaß damit und danke an Sektenspinner und alle die an Ikarus mitgefeilt haben!
qiaky
EDIT: Hinweis auf Initialisierung in Init_Global() hinzugefügt.
EDIT2: Lösung für übertragenes Gold verlinkt.
const float TRADE_VALUE_MULTIPLIER = 0.15;
in der constants.d gestolpert.
Dieser bestimmt die Wertsenkung von Items beim Verkauf. 0.15 bedeutet z.B., dass der Spielercharakter Gegenstände mit einem Wert von 100 für 100 * 0.15 = 15 Gold verkauft.
Der Wert kann recht einfach geändert werden, constants.d öffnen, gewünschten Wert eintragen, speichern, Skripte parsen (Gothic.dat Kompilat erstellen).
Problem ist: Der Wert wird beim Start der Gothic2.exe einmalig von der Engine ausgelesen und dann wird der eingetragene Wert ignoriert. D.h um den Wert zu verändern würde es einen Gothic-Neustart brauchen und Skripte mit Statements wie
TRADE_VALUE_MULTIPLIER = NEW_VALUE;
sind hinfällig.
Mit den Ikarus Funktionen MEM_WriteInt und MEM_ReadInt kann der Wert auch während dem laufenden Spiel per Skript geändert werden.
Die benötigte Speicheradresse ist:
// TRADE_VALUE_MULTIPLIER ADDRESS:
const int Float__ENGINE_TRADEX = 11211032; //0x00AB1118
Auf diese kann bequem mit MEM_WriteInt und MEM_ReadInt zugegriffen werden.
MEM_WriteInt(Float__EngineMultiplier, NEW_MULTIPLIER);
MEM_ReadInt(Float__EngineMultiplier);
Nun handelt es sich aber bei der Wertübergabe jeweils um Integer, während der TRADE_VALUE_MULTIPLIER ja eine Kommazahl, eine sogenannte Float ist.
Zum Glück hat Sektenspinner Floats in Gothic implementiert. Da die reservierte Speicheradresse 32 bit groß ist, können wir per MEM_WriteInt auch einen 32 bit Float schreiben, solange der ByteCode (HexCode) stimmt. Das übernimmt die float-Funktion
CastToIntf(float)
für uns. Beim Lesen mit MEM_ReadInt ist die entsprechende Funktion
CastFromIntf(int)
Somit erhalten wir zwei Funktionen:
// TRADE_VALUE_MULTIPLIER ADDRESS:
const int Float__ENGINE_TRADEX = 11211032; //0x00AB1118
// Schreibt den neuen Wert NEW_MULTIPLIER an die Speicheradresse
func void SetTradeValueMultiplier(var float NEW_MULTIPLIER)
{
var int NEW_VALUE; NEW VALUE = CastToIntf(NEW_MULTIPLIER);
MEM_WriteInt(Float__EngineMultiplier, NEW_VALUE);
};
// fragt den Wert der Speicheradresse ab und übergibt ihn als Float
func float GetTradeValueMultiplier()
{
return CastFromIntf(MEM_ReadInt(Float__EngineMultiplier));
};
Somit kann man z.B. verschiedene Händler verschiedene Preise haben lassen (in den DIA_npc C_Info aufrufen) oder ein neues Talent für feilschen erstellen (bei der Talenterhöhung aufrufen).
Wichtig zu wissen ist, dass der gesetzte Wert für TRADE_VALUE_MULTIPLIER in der Adresse 0x00AB1118 nicht ins Savegame wandert. Deshalb ist eine Initialisierung des Wertes in der Init_Global() (startup.d) notwendig.
EDIT: Methode funktioniert nur für den angezeigten Wert des Gegenstandes, das übertragene Gold wird anderswo im Code berechnet, siehe hier und hier
Viel Spaß damit und danke an Sektenspinner und alle die an Ikarus mitgefeilt haben!
qiaky
EDIT: Hinweis auf Initialisierung in Init_Global() hinzugefügt.
EDIT2: Lösung für übertragenes Gold verlinkt.