|
-
Zitat von Marthog
Geht das mit StartRain_Time denn? Ich hab das irgendwann mal ausprobiert, nur halt mit den ganzen Tag Regen und da war der Himmel immernoch sehr blau, und es hat geregnet.
Dann war es vielleicht gerade um die Mittagszeit. Da beginnt der Regen gerade (er endet um die Mittagszeit des nächsten Tages). Einblendphase ist 20%, das macht also 24/5 =~ 5 Stunden aus. Zwischen 7 Uhr morgens und 17 Uhr abend wird also der Regen aus und eingeblendet, weshalb der Regen dort nicht stark ist und der Himmel auch noch nicht so dunkel wie normal.
Wird der Regen präziser gesetzt, zum Beispiel von 6 Uhr bis 11 Uhr, dann ist das Einblenden auch nur eine Stunde lang.
-
Zitat von Assasine91
kann man eigentlich mit ikarus auch einstellen, dass es NUR BEI EINER BESTIMMTEN .zen nicht regnet aber bei den anderen ganz normal?
wäre nämlich richtig schön fürs Varant-Feeling geeignet
Hab grad noch was interessantes gefunden:
var int m_bDontRain; //zBOOL
in zCSkyController.d von Ikarus. Klingt so, als könnte man damit den Regen abstellen oder aber das ist nur für die Abfrage, ob es regnet, das weiß ich jetzt nicht
EDIT: Hab's eben getestet, stellt den Regen ab. D.h. du müsstest nur in der Init_Varant.d nach der Initialisierung der Ikarus-Sachen MEM_SkyController.m_bDontRain = TRUE; schreiben und fertig.
Geändert von Bonne6 (09.02.2011 um 15:10 Uhr)
-
Zitat von Bonne6
oder aber das ist nur für die Abfrage, ob es regnet, das weiß ich jetzt nicht
Als Ergänzung, falls jemand den Thread über die Forensuche findet:
Code:
func int Wld_IsRaining () { return 0; };
(aus den erweiterten Externals von Nico)
Die Funktion liefert true zurück, wenn es gerade regnet.
-
Ist es momentan irgendwie möglich die aktuell abgespielte Musik zu beeinflussen, lautstärketechnisch oder auch ob sie laufen soll oder nicht? Das würde mir eine gigantische leere Musikzone ersparen.
oCGame enthält lediglich music_delay und das scheint nicht das zu sein wonach ich suche.
-
Auskommentierter Teil in der zCZoneFog:
Code:
/*
//zCZone / zCZoneMusic sind relativ uninteressante Klassen.
class zCZone / zCZoneMusic { //beide Klassen vom Speicherbild identisch
//[zVob Stuff....]
zCWorld *world; //einzige neue Eigenschaft
};
*/
Scheint Sekti nicht als wichtig empfunden zu haben, daher nicht vorhanden, würde ich mal vermuten.
-
In zCSkyController gibt es noch einige Eigenschaften, die mit Sound zutun haben - die referenzierten Klassen sind aber nicht dokumentiert bzw. in Daedalus abgebildet...
Edit: Wenn der Sound nur mit der Namensgebung der Zonen zu tun hat, kann man damit evtl. was machen - vermutlich wirst du aber noch einen Engine-Call brauchen, um die Zone hinzuzufügen.
-
Auskommentierter Teil in der zCZoneFog:
zCZoneMusic ist wirklich uninteressant, aber es gibt noch oCZoneMusic und die ist nicht uninteressant. Hab sie mir jetzt mal angeschaut.
Mit der Musikzone könnte man auch vermutlich etwas machen, aber dazu müsste man die aktuelle Musikzone kennen. Ich habe etwas herumprobiert aber das vielversprechende Datum oCZoneMusic* oCZoneMusic::s_musiczone war bei mir kurz nach dem Start null (direkt beim Start noch initialisiert), hab das dann nicht weiter verfolgt.
Was dagegen gut funktioniert hat war das:
Code:
func void SetMusicVolume (var int percent) {
const int zmusic_address = 9248532; //0x8D1F14 //zCMusicSys_DirectMusic*
const int zCMusicSys_DirectMusic__SetVolume_ptr = 5152720; //0x4E9FD0
var int zmusic; zmusic = MEM_ReadInt (zmusic_address);
if (zmusic) {
CALL_FloatParam(divf(mkf(percent),mkf(100)));
CALL__thiscall (zmusic, zCMusicSys_DirectMusic__SetVolume_ptr);
} else {
MEM_Info ("SetMusicVolume failed: zmusic is null?");
};
};
Hier wird letztendlich zmusic.SetVolume( percent / 100); ausgeführt. Und es funktioniert prima.
Allerdings ist die Lautstärke des Musiksystem dann nicht mehr mit der eingetragenen Lautstärke in zoptions synchronisiert. Das kann man aber manuell leicht korrigieren (mit MEM_SetGothOpt / MEM_GetGothOpt), wenn das gewünscht ist.
-
Console Extensions
Ich habe mir ein Skript gebaut mit dessen Hilfe ich neue Konsolenbefehle einführen kann.
Es ist relativ primitiv: Ich prüfe ob die Konsole sich einen neuen Eintrag in ihrer Kommandohistorie gespeichert hat (sie merkt sich ja in Gothic 2 welche Kommandos kamen).
Diesen parse ich dann eben nochmal und schaue, ob er für mich interessant ist.
Etwas unschön ist dabei, dass die Konsole sich beschwert ein Kommando nicht zu kennen, selbst wenn es dann im Nachhinein skriptseitig behandelt wird. Und die Autovervollständigung ist natürlich auch nicht auf neue Befehle abgestimmt. Aber seis drum. Zu Debugzwecken ist das ziemlich nützlich.
Ich habe bisher implementiert:
- put var value
setze Skriptvariable var auf Wert value. Implementiert für Strings und Integer - peek var
gebe aktuellen Wert der Skriptvariable var aus. Implementiert für Strings und Integer. - xct function
Führt eine (parameterfreie) Daedalusfunktion function aus. Der Name kommt von "execute". - toggle told info
Sucht die oCInfo mit Namen info und schaltet um ob diese Info schon bekannt ist oder nicht. - sleep
Zeigt eine einfache MessageBox an. Sinn: Bis man "ok" klickt, zieht Gothic keine CPU Leistung mehr. So kann man Gothic im Hintergrund laufen lassen ohne dass es das System blockiert. Vor allem für schlechte Rechner wie meinen Laptop interessant.
Denkbar sind aber auch andere Befehle jeglicher Art.
Vielleicht nützt das Skript ja jemandem, auch wenn es sicher nicht pefekt ist.
Code:
//#################################################
//
// Line Lexer
//
//#################################################
/* Init this Lexer with a string.
* Every time you call "next", the lexer will write
* the next word (space seperated) into the global
* variable LLX_tok.
* next() returns false iff there was no further token in the string.
usage (pseudocode):
LLX_Init (stringWithSpaceSeperatedTokens);
while (LLX_Next()) {
proccessToken(LLX_Tok);
}
endOfInput();
*/
var string LLX_str;
var int LLX_pos;
var int LLX_len;
var string LLX_tok;
func void LLX_Init(var string str) {
LLX_str = str;
LLX_pos = 0;
LLX_tok = "";
LLX_len = STR_Len(str);
};
func int LLX_next() {
var int start; start = -1;
var int loop;
loop = MEM_StackPos.position;
/* string zu Ende? */
if (LLX_pos >= LLX_len) {
if (start != -1) {
LLX_tok = STR_SubStr(LLX_str, start, LLX_len - start);
return true;
};
return false;
};
var int isBlank;
isBlank = STR_GetCharAt(LLX_str, LLX_pos) == 32;
if (isBlank) {
/* am Anfang überspringen, später als Ende vom Wort werten */
if (start != -1) {
LLX_tok = STR_SubStr(LLX_str, start, LLX_pos - start);
return true;
};
} else if (start == -1) {
start = LLX_pos; //wurde schon inkrementiert
};
LLX_pos += 1;
MEM_StackPos.position = loop;
};
//#################################################
//
// Console Observer
//
//#################################################
func void ProcessCommand(var string command) {
MEM_InitAll();
var string msg;
LLX_Init(command);
if (!LLX_Next()) {
return;
};
if (Hlp_StrCmp ("XCT", LLX_Tok)) {
/* xct myfunction */
if(!LLX_Next()) {
Print("Which script function should I execute?");
return;
};
msg = ConcatStrings("Calling: ", LLX_Tok);
PrintDebug(msg);
Print(msg);
MEM_CallByString(LLX_Tok);
} else if (Hlp_StrCmp ("PUT", LLX_Tok))
|| (Hlp_StrCmp ("PEEK", LLX_Tok)) {
/* put myVar 42
* peak myVar */
var int putting; putting = Hlp_StrCmp ("PUT", LLX_Tok);
var string variable; var string value;
var int succ; succ = 1;
succ = succ && LLX_Next();
variable = LLX_Tok;
if (putting) {
succ = succ && LLX_Next();
value = LLX_Tok;
};
if (!succ) {
if (putting) {
Print("Usage example: 'put myVar 42'");
} else {
Print("Usage example: 'peek myVar'");
};
return;
};
var zCPar_Symbol sym;
var int ptr;
ptr = MEM_GetParserSymbol(variable);
if (!ptr) {
Print("Variable not found.");
return;
};
sym = MEM_PtrToInst (ptr);
var int type;
type = sym.bitfield & zCPar_Symbol_bitfield_type;
if (type != zPAR_TYPE_INT)
&& (type != zPAR_TYPE_STRING) {
Print("Only string and integer variables supported!");
return;
};
if ((sym.bitfield & zCPar_Symbol_bitfield_ele) != 1) {
Print("Arrays currently not supported!");
return;
};
if (type == zPAR_TYPE_INT) {
if (putting) {
var int IntVal;
IntVal = STR_ToInt(value);
if (!Hlp_StrCmp(IntToString(IntVal), value)) {
Print("String to Int conversion failed.");
return;
};
sym.content = IntVal;
Print("Done.");
} else {
msg = ConcatStrings("value of int ", variable);
msg = ConcatStrings(msg, " is: ");
msg = ConcatStrings(msg, IntToString(sym.content));
Print(msg);
PrintDebug(msg);
};
} else {
//type == zPAR_TYPE_STRING
if (putting) {
MEM_WriteString(sym.content, value);
Print("Done.");
} else {
msg = ConcatStrings("value of string ", variable);
msg = ConcatStrings(msg, " is: '");
msg = ConcatStrings(msg, MEM_ReadString(sym.content));
msg = ConcatStrings(msg, "'");
Print(msg);
PrintDebug(msg);
};
};
} else if (Hlp_StrCmp (LLX_Tok, "TOGGLE")) {
if (!LLX_Next()) { return; };
if (Hlp_StrCmp (LLX_Tok, "TOLD")) {
if (!LLX_Next()) {
Print("Which Dialog (C_INFO) should I tell/untell?");
return;
};
var int ID;
ID = MEM_FindParserSymbol(LLX_Tok);
if (ID == -1) {
Print("Dialog not found.");
return;
};
const int oCInfoManager__GetInformation = 7350544; //0x702910
CALL_IntParam(ID);
CALL__thiscall(MEM_Game.infoman, oCInfoManager__GetInformation);
var oCInfo info;
info = MEM_PtrToInst (CALL_RetValAsPtr());
info.told = !info.told;
msg = ConcatStrings(LLX_Tok, " is now ");
if (info.told) {
ConcatStrings(msg, "told.");
} else {
ConcatStrings(msg, "not told.");
};
PrintDebug(msg);
Print(msg);
};
} else if (Hlp_StrCmp (LLX_Tok, "SLEEP")) {
MEM_InfoBox ("Sleeping...");
};
};
func void ObserveConsole() {
var zCConsole zcon;
zcon = MEM_PtrToInst (zcon_address);
var int lastcommand_numInArray;
if (lastcommand_numInArray != zcon.lastcommand_numInArray) {
lastcommand_numInArray = zcon.lastcommand_numInArray;
if (lastcommand_numInArray <= 0) {
return;
};
ProcessCommand (MEM_ReadString (zcon.lastcommand_array + (lastcommand_numInArray - 1) * sizeOf_zString));
};
};
Benutzung: In regelmäßigen Abständen (z.B. jeden Frame) sollte ObserveConsole aufgerufen werden. Neue Konsolenbefehle können in ProcessCommand hinzugefügt werden.
Damit das Skript läuft wird die Klasse zCConsole benötigt, in die nächste Ikarusversion packe ich sie rein, hier ist sie schonmal vorab:
Code:
const int zCON_MAX_EVAL = 15;
const int zcon_address = 11221088; //0xAB3860
class zCConsole {
var int _vtbl;
var string id; //zSTRING
var string instr; //zSTRING
var string savemsg; //zSTRING
//zCArray<zSTRING> lastcommand;
var int lastcommand_array; //zString*
var int lastcommand_numAlloc; //int
var int lastcommand_numInArray; //int
var int lastCommandPos;
var int px; var int py;
var int lx; var int ly;
var int showmax; var int skip;
var int dynsize; //zBOOL
var int _var; //zBOOL
var int autocomplete; //zBOOL
//zList <zCConDat> list;
var int compare; //int (*Compare)(const zCConDat* ele1,const zCConDat* ele2);
var int count; //int
var int last; //zCConDat*
var int wurzel; //zCConDat*
var int conview; //zCView*
var int evalcount;
var int evalfunc[zCON_MAX_EVAL]; //zBOOL (*evalfunc[]) ( const zSTRING &s, zSTRING &msg )
var int changedfunc; //void (*changedfunc) ( const zSTRING &s )
var int world; //zCWorld*
var int cparser; //zCParser*
var int edit_index; //int
var int edit_adr; //void*
};
Sauberer als das, was ich gemacht habe, wäre eine Maschinencode-Funktion zu schreiben und sie ins evalFunc Array der Konsole einzutragen. Aber das ist schwierig (wäre mehr was für G2Ext).
-
Nette Sache, ermöglicht es den Testern dann, Variablen-Fehler direkt bei sich zu beheben, muss ich nicht immer die Savegames fixen Mal gucken, ob mir noch andere Sachen dazu einfallen
-
Super Sache
Ich hab mir gleich mal die Freiheit genommen und Argumente/Rückgabewerte zu der xct Funktion geschrieben:
Code:
/* xct myfunction */
if(!LLX_Next()) {
Print("Which script function should I execute?");
return;
};
// Eventuellen Rückgabewert erkennen
var int chr; var int ret; ret = -1;
if(STR_Len(LLX_Tok)==1) {
chr = STR_GetCharAt(LLX_Tok, 0);
if(chr==83||chr==73) {
ret = (chr==83);
if(!LLX_Next()) {
Print("Which script function should I execute?");
return;
};
};
};
var int fnc; fnc = MEM_FindParserSymbol(LLX_Tok);
if (fnc == -1) {
Print("Function not found");
return;
};
msg = ConcatStrings("Calling: ", LLX_Tok);
PrintDebug(msg);
Print(msg);
// Tut mir wirklich leid dieses Chaos.. Ich hab nur leider keine
// Ahnung wie man sonst die strings direkt pushen könnte?
var string argstr0; var string argstr1; var string argstr2; var string argstr3; var string argstr4; var string argstr5; var string argstr6; var string argstr7; var string argstr8;
var int argint0; var int argint1; var int argint2; var int argint3; var int argint4; var int argint5; var int argint6; var int argint7; var int argint8;
var int args; var int argcnt; var int argstrcnt; var int argintcnt; args = 0; argcnt = 0; argstrcnt = 0; argintcnt = 0;
// Argumente einlesen
var int i;
var int pos; pos = MEM_StackPos.position;
if(LLX_Next()) {
chr = STR_GetCharAt(LLX_Tok, 0);
if(chr==83||chr==73) {
LLX_Tok = STR_SubStr(LLX_Tok, 1, STR_Len(LLX_Tok)-1);
if(chr==83) {
PrintDebug("SaveString");
if(argstrcnt==0) { argstr0 = LLX_Tok; };
if(argstrcnt==1) { argstr1 = LLX_Tok; };
if(argstrcnt==2) { argstr2 = LLX_Tok; };
if(argstrcnt==3) { argstr3 = LLX_Tok; };
if(argstrcnt==4) { argstr4 = LLX_Tok; };
if(argstrcnt==5) { argstr5 = LLX_Tok; };
if(argstrcnt==6) { argstr6 = LLX_Tok; };
if(argstrcnt==7) { argstr7 = LLX_Tok; };
if(argstrcnt==8) { argstr8 = LLX_Tok; };
argstrcnt += 1;
args = (args<<1)+1;
argcnt += 1;
}
else {
PrintDebug("SaveInt");
i = STR_ToInt(LLX_Tok);
if(argintcnt==0) { argint0 = i; };
if(argintcnt==1) { argint1 = i; };
if(argintcnt==2) { argint2 = i; };
if(argintcnt==3) { argint3 = i; };
if(argintcnt==4) { argint4 = i; };
if(argintcnt==5) { argint5 = i; };
if(argintcnt==6) { argint6 = i; };
if(argintcnt==7) { argint7 = i; };
if(argintcnt==8) { argint8 = i; };
argintcnt += 1;
args = (args<<1)+0;
argcnt += 1;
};
};
MEM_StackPos.position = pos;
};
// Argumente umdrehen (freundlicher bei der Verwendung..)
PrintDebug(IntToString(args));
var int argsc; argsc = 0;
i = 0;
pos = MEM_StackPos.position;
if(i < argcnt) {
argsc += (args&1)<<(argcnt-1-i);
args = args>>1;
i += 1;
MEM_StackPos.position = pos;
};
args = argsc;
PrintDebug(IntToString(args));
// Argumente pushen
argstrcnt = 0; argintcnt = 0;
var int argcurr;
pos = MEM_StackPos.position;
if(argcnt) {
argcnt -= 1;
argcurr = args&1;
args = args>>1;
if(argcurr) {
if(argstrcnt==0) { MEM_PushStringParam(argstr0); };
if(argstrcnt==1) { MEM_PushStringParam(argstr1); };
if(argstrcnt==2) { MEM_PushStringParam(argstr2); };
if(argstrcnt==3) { MEM_PushStringParam(argstr3); };
if(argstrcnt==4) { MEM_PushStringParam(argstr4); };
if(argstrcnt==5) { MEM_PushStringParam(argstr5); };
if(argstrcnt==6) { MEM_PushStringParam(argstr6); };
if(argstrcnt==7) { MEM_PushStringParam(argstr7); };
if(argstrcnt==8) { MEM_PushStringParam(argstr8); };
argstrcnt += 1;
}
else {
if(argintcnt==0) { MEM_PushIntParam(argint0); };
if(argintcnt==1) { MEM_PushIntParam(argint1); };
if(argintcnt==2) { MEM_PushIntParam(argint2); };
if(argintcnt==3) { MEM_PushIntParam(argint3); };
if(argintcnt==4) { MEM_PushIntParam(argint4); };
if(argintcnt==5) { MEM_PushIntParam(argint5); };
if(argintcnt==6) { MEM_PushIntParam(argint6); };
if(argintcnt==7) { MEM_PushIntParam(argint7); };
if(argintcnt==8) { MEM_PushIntParam(argint8); };
argintcnt += 1;
};
MEM_StackPos.position = pos;
};
MEM_CallByID(fnc);
if(ret!=-1) {
if(ret) {
Print(MEM_PopStringResult());
}
else {
Print(IntToString(MEM_PopIntResult()));
};
};
Um die Anwendung zu verdeutlichen:
Code:
func int Add(var int x, var int y) {
return x+y;
};
Würde so verwendet werden:Hier würde zB. '10' geprintet werden.
Erklärung: Funktion mit Integer (i) als Rückgabe und zwei Integer-Argumenten.
Alternativ kann auch 's' für strings verwendet werden:
Code:
func string cs2(var string s0, var string s1) {
return ConcatStrings(s0, s1);
};
Ergibt also logischerweise "HALLO" (Kleinbuchstaben können leider nicht übergeben werden)
MfG Gottfried
-
Hab da mal wieder 'ne Frage
Kann man mit Ikarus einen Zugriff auf VFX Instanzen bekommen?
Die beispielsweise mit Wld_PlayEffect() gestartet worden?
Hintergrund ist das hier
Vielen Dank schon einmal
What do you think I am? Human?
- the Architect
-
Zitat von Neok
Hab da mal wieder 'ne Frage
Kann man mit Ikarus einen Zugriff auf VFX Instanzen bekommen?
Die beispielsweise mit Wld_PlayEffect() gestartet worden?
Hintergrund ist das hier
Vielen Dank schon einmal
Wenn der Effekt an einem NPC hängt, auf jeden Fall:
Code:
//zCArray<oCVisualFX*> {
var int effectList_array; // 0x0750 oCVisualFX**
var int effectList_numAlloc; // 0x0754 int
var int effectList_numInArray; // 0x0758 int
Aber die Klasse ist glaube ich noch nicht dokumentiert.
-
Zitat von Lehona
Wenn der Effekt an einem NPC hängt, auf jeden Fall:
Code:
//zCArray<oCVisualFX*> {
var int effectList_array; // 0x0750 oCVisualFX**
var int effectList_numAlloc; // 0x0754 int
var int effectList_numInArray; // 0x0758 int
Aber die Klasse ist glaube ich noch nicht dokumentiert.
Hmm das hilft mir nicht so recht weiter, ich bin da noch nicht so ganz firm mit Ikarus. Also der Effekt wird an dem Hero angehangen. Wie verwende ich das denn jetzt konkret, wenn ich die visAlpha-Eigenschaft auf 0 setzen will?
What do you think I am? Human?
- the Architect
-
Zitat von Neok
Hmm das hilft mir nicht so recht weiter, ich bin da noch nicht so ganz firm mit Ikarus. Also der Effekt wird an dem Hero angehangen. Wie verwende ich das denn jetzt konkret, wenn ich die visAlpha-Eigenschaft auf 0 setzen will?
In diesem Array sind alle aktiven Effekte des NPCs gespeichert... Wenn die referenzierte Klasse (oCVisualFX) aber nicht dokumentiert ist, kannst du da wenig machen. Entweder also hoffen, dass Sekti das macht, oder ihn dazu bringen, seine Methode zum dokumentieren der Klassen offenzulegen (Würde mich interessieren...?).
@Sekti: Werden External-Parameter genauso gepoppt wie in "normalen" Funktionen? So könnte man wohl mindestens parameterlose Externals aufrufen:
Code:
func void callExternal(var string function) {
var int symbId; symbId = MEM_FindParserSymbol(function);
MEM_WriteInt(6/*5+5+4*/+MEM_StackPos.position, symbId);
ExitSession ();
};
Edit: Zumindest fast, momentan schießt sie mir Gothic ab...
Geändert von Lehona (17.02.2011 um 13:10 Uhr)
-
Mittlerweile kann man einiges machen ohne die Klassen intern zu kennen.
In diesem Fall würde ich versuchen die genannte Effektliste durchzugehen und mit oCVisualFX :: GetName den mit dem richtigen Namen suchen.
Dann sollte oCVisualFX::SetShowVisual weiterhelfen um den Effekt auszuschalten.
Das heißt da kommt gleich einiges an Ikarus Spezialitäten zusammen:
Eine Schleife bauen die von 0 bis hero.effectList_numInArray - 1 iteriert, in jedem Schleifendurchlauf den entsprechenden Array Eintrag aus hero.effectList_array holen und diesen dann mit einem __thiscall mit den Adressen der beiden oben genannten Funktionen verwursten (die Adressen vorher mit IDA rausfinden).
Harter Tobak für jemanden der noch nichts mit Ikarus gemacht hat.
Zitat von Lehona
@Sekti: Werden External-Parameter genauso gepoppt wie in "normalen" Funktionen? So könnte man wohl mindestens parameterlose Externals aufrufen:
Parameter und Rückgabewerte von Externals unterscheiden sich in der Handhabung nicht von Parametern und Rückgabewerten von anderen Funktionen.
Aber deine Rechnerei mit dem Stackpointer ist verwirrend. Nach dem zPAR_OP_PLUS, durch das MEM_StackPos.position ausgewertet wird, kommt noch zPAR_TOK_CALL (1 byte), das Callziel, nämlich MEM_WriteInt (4 byte) und zPAR_TOK_CALLEXTERN. Das sollten doch nur 6 Bytes sein, oder?
[falsch]Beachte, dass die Parameter von rechts nach links auf den Stack wandern[/falsch] und das nur die Adresse von MEM_StackPos.position auf dem Stack liegt (und der Wert dahinter sich ständig ändert) bis zur Plus Operation.
(Mich scheint das selbst zu verwirren: Parameter wandern von links nach rechts auf den Stack, werden aber entsprechend von rechts nach links wieder runtergepoppt)
Einfacher wärs eine gesonderte Funktion zu machen und im Parsersymbol dieser Funktion nachzuschauen wo diese Funktion beginnt. In der kann man dann bequem rumschreiben und zwar mit absoluten Adresse nicht relativ zu MEM_StackPos.position. Und dann ruft man diese Funktion einfach auf.
Zitat von Lehona
ihn dazu bringen, seine Methode zum dokumentieren der Klassen offenzulegen (Würde mich interessieren...?).
Kann ich hier nicht diskutieren, ich schreib dir ne PN.
Geändert von Sektenspinner (27.02.2011 um 16:20 Uhr)
-
Mir ist gestern Abend noch eingefallen, dass die Parameter von links nach rechts auf den Stack fliegen, hatte mich erst einige Stunden vorher noch darüber unterhalten
Insofern hast du natürlich recht, es müssen 5 Byte weniger sein und somit dann +6... Könntest du evtl. in MEM_CallFuncByID/String aufnehmen, denn afaik klappt das mit Externals ja nicht... (Ob External oder Funktion lässt sich ja simpel am Symbol feststellen)
Ist sym.offset bei Funktionen eigentlich vom Typ
Code:
enum { zPAR_TYPE_VOID, zPAR_TYPE_FLOAT, zPAR_TYPE_INT,
zPAR_TYPE_STRING, zPAR_TYPE_CLASS, zPAR_TYPE_FUNC,
zPAR_TYPE_PROTOTYPE,zPAR_TYPE_INSTANCE };
Denn eigene Variablen für den Rückgabewert gibt es ja afaik nicht...
-
Zitat von Lehona
Mir ist gestern Abend noch eingefallen, dass die Parameter von links nach rechts auf den Stack fliegen, hatte mich erst einige Stunden vorher noch darüber unterhalten
[falsch]Von rechts nach links meinst du. [/falsch] <- von links nach rechts stimmt schon, hab Unfug erzählt.
Zitat von Lehona
Könntest du evtl. in MEM_CallFuncByID/String aufnehmen, denn afaik klappt das mit Externals ja nicht... (Ob External oder Funktion lässt sich ja simpel am Symbol feststellen)
Stimmt, sehr guter Vorschlag. Bislang stürzt es einfach ab, wenn Externalsymbole übergeben werden. MEM_CallByID sieht jetzt so aus:
Code:
func void MEM_CallByID (var int symbID) {
if (currParserID != PARSER_CONTENT) {
MEM_Error("Calling Functions within another parser is evil. Dont do it.");
return;
};
MEM_ReinitParser();
var zCPar_Symbol sym;
MEM_AssignInst (sym, MEM_ReadIntArray (contentSymbolTableAddress, symbID));
var int type;
type = (sym.bitfield & zCPar_Symbol_bitfield_type);
if (type != zPAR_TYPE_FUNC) && (type != zPAR_TYPE_PROTOTYPE) && (type != zPAR_TYPE_INSTANCE) {
MEM_Error (ConcatStrings ("MEM_CallByID: Provided symbol is not callable (not function, prototype or instance): ", sym.name));
return;
};
if (sym.bitfield & zPAR_FLAG_EXTERNAL) {
CALL__stdcall(sym.content);
} else {
MEM_InitLabels();
MEM_StackPos.position = sym.content + currParserStackAddress; //Jump statt Call. Geht auch. Sogar bequemer.
};
};
In der nächsten Version ist das so drin.
Ist sym.offset bei Funktionen eigentlich vom Typ
Code:
enum { zPAR_TYPE_VOID, zPAR_TYPE_FLOAT, zPAR_TYPE_INT,
zPAR_TYPE_STRING, zPAR_TYPE_CLASS, zPAR_TYPE_FUNC,
zPAR_TYPE_PROTOTYPE,zPAR_TYPE_INSTANCE };
Denn eigene Variablen für den Rückgabewert gibt es ja afaik nicht...
Ja, das ist so.
@Gottfried: Sieht nützlich aus der Code. Wenn er auch nicht sonderlich elegant aussieht. Aber eine wirklich elegante Lösung fällt mir auch nicht ein.
Geändert von Sektenspinner (27.02.2011 um 16:20 Uhr)
-
Weil ich die nächste Elemental War - Version auch in englischer Sprache releasen will, wollte ich mal fragen, ob die Report-Version mit deren G2-Version kompatibel ist. Dann müsste doch deren G2-Installation eine 2.6er Version sein und somit Installer-kompatibel (ich nutz da immer die Vorlage aus dem Modkit), oder? Sonst ist ja das ganze Ikarus-Zeug nicht kompatibel, wäre ja doof
-
2.6(fix) lässt sich über 2.7 installieren.
-
Zitat von Lehona
2.6(fix) lässt sich über 2.7 installieren.
Ok, das ist super
Gleich noch ein Fehler hinterher, der bestimmt was mit Ikarus zu tun hat:
Fehlermeldung:
Code:
U: NPC: Object tries to save reference of player during levelchange. This is not allowed.
Kommt, wenn ich in Elemental War fertig bin und zurück ins Start-Level komm, also während des Levelchanges. Wenn ich danach ins das Level zurück will, dann crasht es. Liegt das daran, dass da ein Save erstellt wird von dem Level?
zSpy dazu:
Code:
[i] 06:37 Info: 5 B: GAME: OpenLoadscreen .... <oGame.cpp,#980>
[i] 06:38 Info: 5 B: GAME: OpenLoadscreen finished .... <oGame.cpp,#1028>
[w] 06:38 Warn: 0 C: zSndMSS(zCSndSys_MSS::LoadSoundFXByIdentifier): Sound Identifier "LOADING_SFX_START" unknown ! .... <zSndMss.cpp,#1155>
[i] 06:38 Info: 3 B: ---------- 0% ---------- .... <zViewProgressbar.cpp,#142>
[i] 06:38 Info: 10 U: (oCWorld::RemoveVob) PC_HERO (1) .... <oWorld.cpp,#475>
[i] 06:38 Info: 8 B: TRIGGER: oCTriggerScript untriggered -> .... <oTrigger.cpp,#166>
[i] 06:38 Info: 3 B: ---------- 2% ---------- .... <zViewProgressbar.cpp,#142>
[i] 06:38 Info: 3 B: ---------- 5% ---------- .... <zViewProgressbar.cpp,#142>
[i] 06:38 Info: 3 B: ---------- 6% ---------- .... <zViewProgressbar.cpp,#142>
[i] 06:38 Info: 3 B: ---------- 8% ---------- .... <zViewProgressbar.cpp,#142>
[i] 06:38 Info: 10 B: zDSK: Created file SAVEHDR.SAV .... <zDisk.cpp,#514>
[i] 06:38 Info: 10 B: zDSK: Closed file SAVEHDR.SAV .... <zDisk.cpp,#616>
[i] 06:38 Info: 9 U: (oCWorld::SaveWorld) \SAVES_ELEMENTALWAR\current\TD01.sav .... <oWorld.cpp,#401>
[i] 06:38 Info: 5 U: WAYNET: Clearing VobDependencies... .... <zWaynet.cpp,#432>
[i] 06:38 Info: 5 D: WORLD: Saving World: "\SAVES_ELEMENTALWAR\current\TD01.sav" .... <zWorld.cpp,#2937>
[i] 06:38 Info: 10 U: (oCWorld::RemoveVob) ZCAICAMERA (1) .... <oWorld.cpp,#475>
[i] 06:38 Info: 10 B: zDSK: Created file TD01.SAV .... <zDisk.cpp,#514>
[i] 06:38 Info: 3 B: ---------- 11% ---------- .... <zViewProgressbar.cpp,#142>
[f] 06:38 Fault: 0 U: NPC: Object tries to save reference of player during levelchange. This is not allowed. .... <oNpc.cpp,#9224>
[i] 06:38 Info: 5 X: Vid_SetScreenMode: No changes ... .... <zRndD3D_Vid.cpp,#559>
[i] 06:38 Info: 5 X: Vid_SetScreenMode: No changes ... .... <zRndD3D_Vid.cpp,#559>
[i] 06:38 Info: 8 C: WM_CANCELMODE received .... <zWin32.cpp,#1728>
[i] 06:38 Info: 8 C: WM_ACTIVATE received .... <zWin32.cpp,#1720>
[i] 06:42 Info: 8 C: WM_ACTIVATEAPP received .... <zWin32.cpp,#1738>
Könnte man das Problem umgehen, indem man vorher mal speichert? Ist so ja nicht so pralle, wenn man dann immer neues Save anfangen muss, nur weil man beim aktuellen nicht mehr zurück kommt Prinzipiell egal, weil im Save nichts wichtiges gespeichert wird, aber trotzdem.
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|
|