|
-
Kann ich mit Ikarus irgendwie den Walkmode eines NPC abfragen?
Es gibt in oCNPC zwar state_walkmode_routine, das war aber (für den PC_Hero) immer 0.
-
Das ist in bisher undokumentierten Klassen versteckt.
Es gibt aber eine passende Funktion, die du aufrufen kannst, und zwar:
zString oCAniCtrl_Human::GetWalkMode()
Dabei wäre der this Pointer hero.anictrl.
Mit den CALL_ Funktionen kommst du somit ans Ziel:
Code:
const int oCAniCtrl_Human__GetWalkModeString = 6991424; //6AAE40
oCNpc oCHer = Hlp_GetNpc(hero);
CALL_RetValIszString();
CALL_thiscall(oCHer.anictrl, oCAniCtrl_Human__GetWalkModeString);
var string result;
result = CALL_RetValAszString();
Der Grund, warum das hier etwas komplizierter ausfällt (es muss angekündigt werden, dass das Ergebnis ein zString ist) ist der, dass zString große Strukturen sind und anders zurückgegeben werden als normale Rückgabewerte.
-
Danke! Ich benutze jetzt diese Funktion:
Code:
/*===================================================================
Npc_GetWalkMode
Den Walkmode eines NPC zurückgeben.
"RUN" - normales laufen
"WALK" - gehen
"SNEAK" - schleichen
"" - schwimmen, durch Wasser waten
==================================================================*/
const int NPC_INWATER = 3;
FUNC int Npc_GetWalkMode (VAR C_NPC slf)
{
const int oCAniCtrl_Human__GetWalkModeString = 6991424; //6AAE40
var oCNpc oCslf; oCslf = Hlp_GetNpc(slf);
CALL_RetValIszString();
CALL__thiscall(oCslf.anictrl, oCAniCtrl_Human__GetWalkModeString);
var string result;
result = CALL_RetValAszString();
if (Hlp_StrCmp (result, "RUN"))
{
return NPC_RUN;
}
else if (Hlp_StrCmp (result, "WALK"))
{
return NPC_WALK;
}
else if (Hlp_StrCmp (result, "SNEAK"))
{
return NPC_SNEAK;
} else if (Hlp_StrCmp (result, ""))
{
return NPC_INWATER;
};
};
(im Kommentar stehen die Strings, die Sektenspinners Funktion bekommt)
NPC_INWATER ist natürlich mit Vorsicht zu genießen und eigentlich nur für Rückgabewerte dieser Funktion gedacht. Bei meinen kurzen Tests gab es aber sonst keine Situation, in der "" zurückgegeben wurde.
-
Hätte es nicht gereicht den Bodystate abzufragen?
Code:
const int BS_STAND = 0 | BS_FLAG_INTERRUPTABLE | BS_FLAG_FREEHANDS;
const int BS_WALK = 1 | BS_FLAG_INTERRUPTABLE;
const int BS_SNEAK = 2 | BS_FLAG_INTERRUPTABLE;
const int BS_RUN = 3;
const int BS_SPRINT = 4;
const int BS_SWIM = 5;
const int BS_CRAWL = 6;
const int BS_DIVE = 7;
const int BS_JUMP = 8;
[...]
MfG Gottfried
-
Das war meine Alternative, die mir aber weniger gut gefallen hat, da man so immer auf mindestens zwei Sachen abfragen müsste (z.B. BS_STAND und BS_WALK). Und da ich mir recht sicher war, dass man mit Ikarus irgendwie auch an den Walkmode kommen müsste, habe ich nachgefragt.
-
Ich habe mal eine kleine STR_Replace-Funktion niedergeschrieben. Vielleicht hat jemand Verwendung dafür
Code:
//========================================
// String replace
//========================================
/* Ersetzt in "res" jedes Vorkommen von "s0" durch "s1" */
func string STR_Replace(var string res, var string s0, var string s1) {
var zString zs0; zs0 = MEM_PtrToInst(STRINT_GetStringAddress(s0));
var int s0l; s0l = zs0.len;
if(!s0l) {
return res;
};
var zString zres; zres = MEM_PtrToInst(STRINT_GetStringAddress(res));
var int l; l = zres.len;
if(!l) {
return res;
};
var int s0i; s0i = MEM_ReadInt(zs0.ptr)&255;
var int s; s = zres.ptr;
var int io; io = 0;
var int i; i = 0;
var string resC; resC = "";
var int p; p = MEM_StackPos.position;
if(i < l) {
if((MEM_ReadInt(s+i)&255) == s0i) {
var string bs; bs = STR_SubStr(res, i, s0l);
if(Hlp_StrCmp(bs, s0)) {
var int r; r = i-io;
if(r) {
resC = ConcatStrings(resC, STR_SubStr(res, io, r));
};
resC = ConcatStrings(resC, s1);
i += s0l;
io = i;
MEM_StackPos.position = p;
};
};
i += 1;
MEM_StackPos.position = p;
};
r = i-io;
if(r) {
resC = ConcatStrings(resC, STR_SubStr(res, io, r));
};
return resC;
};
MfG Gottfried
-
-
Bonne6 hat mich letztens unbewusst auf die Idee gebracht eine Möglichkeit zu basteln Dateien frei speichern und laden zu können, deshalb habe ich das mal spontan umgesetzt.
Ich denke es kann recht nützlich sein, gerade um eigene Klassen, Listen oder Arrays abzuspeichern.
Es sind recht viele Funktionen dabei herausgekommen und der Code ist meiner Meinung nach recht unübersichtlich, daher habe ich zu jeder eine kurze Erklärung verfasst. (Oft sind aber sowieso die Namen Programm.)
Alle Funktionen sind sehr simpel gestrickt, aber ich finde sie reichen für den vorgesehenen Gebrauch absolut aus.
Es folgt der Code mit einer kurzen Funktionsübersicht:
Code:
/* ==============================================
* BinaryWriter - Dateien anlegen und beschreiben
* ==============================================
* Grundfunktionen:
* int BW_NewFile (string file)
* void BW_Close ()
* void BW (int data, int length)
* Daten speichern:
* void BW_Int (int data)
* void BW_Char (string data)
* void BW_String (string data)
* void BW_Byte (int data)
* void BW_Bytes (int dataPtr, int length)
* Text schreiben:
* void BW_TextLine (string data)
* void BW_Text (string data)
* void BW_NextLine ()
*
* ==============================================
* BinaryReader - Dateien auslesen
* ==============================================
* Grundfunktionen:
* int BR_OpenFile (string file)
* void BR_Close ()
* int BR (int length)
* Daten lesen:
* int BR_Int ()
* string BR_Char ()
* string BR_String ()
* int BR_Byte ()
* int BR_Bytes (int length)
* Text lesen:
* string BR_TextLine ()
* string BR_Text (int length)
*/
/*--------------------
Enginecalls
--------------------*/
const int CREATE_ALWAYS = 2;
const int OPEN_EXISTING = 3;
const int GENERIC_ALL = 1073741824;
const int GENERIC_READ = -2147483648;
const int FILE_SHARE_READ = 1;
const int FILE_ATTRIBUTE_NORMAL = 128;
func int WIN_CreateFile(
var string lpFileName,
var int dwDesiredAccess,
var int dwShareMode,
var int lpSecurityAttributes,
var int dwCreationDisposition,
var int dwFlagsAndAttributes,
var int hTemplateFile) {
const int CreateFileA = 8079286; //0x7B47B6
CALL_IntParam(hTemplateFile);
CALL_IntParam(dwFlagsAndAttributes);
CALL_IntParam(dwCreationDisposition);
CALL_IntParam(lpSecurityAttributes);
CALL_IntParam(dwShareMode);
CALL_IntParam(dwDesiredAccess);
CALL_cStringPtrParam(lpFileName);
CALL__stdcall(CreateFileA);
return CALL_RetValAsPtr();
};
func void WIN_WriteFile(
var int hFile,
var int lpBuffer,
var int nNumberOfBytesToWrite,
var int lpNumberOfBytesWritten,
var int lpOverlapped) {
const int WriteFile = 8079292; //0x7B47BC
CALL_IntParam(lpOverlapped);
CALL_IntParam(lpNumberOfBytesWritten);
CALL_IntParam(nNumberOfBytesToWrite);
CALL_IntParam(lpBuffer);
CALL_IntParam(hFile);
CALL__stdcall(WriteFile);
};
func void WIN_ReadFile(
var int hFile,
var int lpBuffer,
var int nNumberOfBytesToRead,
var int lpNumberOfBytesRead,
var int lpOverlapped) {
const int ReadFile = 8272388; //0x7E3A04
CALL_IntParam(lpOverlapped);
CALL_IntParam(lpNumberOfBytesRead);
CALL_IntParam(nNumberOfBytesToRead);
CALL_IntParam(lpBuffer);
CALL_IntParam(hFile);
CALL__stdcall(ReadFile);
};
func void WIN_CloseHandle(
var int hObject) {
const int CloseHandle = 8079190; //0x7B4756
CALL_IntParam(hObject);
CALL__stdcall(CloseHandle);
};
func int WIN_GetFileSize(
var int hFile,
var int lpFileSizeHigh) {
const int GetFileSize = 8079310; //0x7B47CE
CALL_IntParam(lpFileSizeHigh);
CALL_IntParam(hFile);
CALL__stdcall(GetFileSize);
return CALL_RetValAsInt();
};
/*--------------------
Konstanten
--------------------*/
const int _BIN_BufferLength = 1024;
/*--------------------
Variablen
--------------------*/
var int _bin_open; // Handle des Streams
var int _bin_mode; // Mode (Write/Read)
var int _bin_ccnt; // Aktueller Content
var int _bin_crsr; // Cursor
var int _bin_clen; // Aktuelle Streamlänge
var string _bin_buffer; // Stringbuffer
var string _bin_prefix; // Debug-Präfix
/*--------------------
Hilfsfunktionen
--------------------*/
func string _BIN_Err(var string msg) {
msg = ConcatStrings(": ", msg);
MEM_Warn(ConcatStrings(_bin_prefix, msg));
};
func int _BIN_nRunning() {
if(_bin_open) {
_BIN_Err("Der aktuelle Stream muss zuerst geschlossen werden bevor ein weiterer geöffnet werden kann.");
return 0;
};
return 1;
};
func int _BIN_Running() {
if(!_bin_open) {
_BIN_Err("Es ist kein Stream aktiv.");
return 0;
};
return 1;
};
func int _BIN_nMode(var int m) {
if(_bin_mode != m) {
_BIN_Err("Falscher Modus.");
return 0;
};
return 1;
};
func void _BIN_StreamLen(var int nlen) {
nlen += _bin_crsr;
if(nlen >= _bin_clen) {
var int len; len = _bin_clen;
var int pos; pos = MEM_StackPos.position;
if(nlen >= len) {
len = len<<1;
pos = MEM_StackPos.position;
};
_bin_ccnt = MEM_Realloc(_bin_ccnt, _bin_clen, len);
_bin_clen = len;
};
};
func int _BIN_EOF(var int len) {
if(_bin_crsr + len > _bin_clen) {
_BIN_Err("Das Ende des Streams wurde bereits erreicht.");
return 1;
};
return 0;
};
/*============
BinaryWriter
============*/
func int BW_NewFile(var string file) {
_bin_prefix = "BW_NewFile";
if(!_BIN_nRunning()) { return 0; };
_bin_open = WIN_CreateFile(file, GENERIC_ALL, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(_bin_open==-1) {
_BIN_Err("Datei konnte nicht erstellt werden.");
return 0;
};
_bin_clen = _BIN_BufferLength;
_bin_mode = 0;
_bin_crsr = 0;
_bin_ccnt = MEM_Alloc(_bin_clen);
return 1;
};
func void BW(var int data, var int length) {
_bin_prefix = "BW";
if(!_BIN_Running()||!_BIN_nMode(0)) { return; };
if(length < 1) { length = 1; };
if(length > 4) { length = 4; };
_BIN_StreamLen(4);
MEM_WriteInt(_bin_ccnt + _bin_crsr, data);
_bin_crsr += length;
};
func void BW_Int(var int data) { BW(data, 4); };
func void BW_Byte(var int data) { BW(data, 1); };
func void BW_Char(var string data) { BW(Str_GetCharAt(data, 0), 1); };
func void BW_String(var string data) {
_bin_prefix = "BW_String";
if(!_BIN_Running()||!_BIN_nMode(0)) { return; };
var zString zdata; zdata = MEM_PtrToInst(STRINT_GetStringAddress(data));
var int len; len = zdata.len;
if(!zdata.len) {
BW(0, 1);
return;
};
_BIN_StreamLen(len+4);
MEM_CopyBytes(zdata.ptr, _bin_ccnt + _bin_crsr, len);
_bin_crsr += len;
BW(0, 1);
};
func void BW_Bytes(var int dataPtr, var int length) {
_bin_prefix = "BW_Struct";
if(!_BIN_Running()||!_BIN_nMode(0)||!length||!dataPtr) { return; };
_BIN_StreamLen(length);
MEM_CopyBytes(dataPtr, _bin_ccnt + _bin_crsr, length);
_bin_crsr += length;
};
func void BW_NextLine() { BW(2573, 2); };
func void BW_Textline(var string data) {
BW_String(data);
_bin_crsr -= 1;
BW(2573, 2);
};
func void BW_Text(var string data) {
BW_String(data);
_bin_crsr -= 1;
};
func void BW_Close() {
_bin_prefix = "BW_Close";
if(!_BIN_Running()||!_BIN_nMode(0)) { return; };
var int ptr; ptr = MEM_alloc(4);
WIN_WriteFile(_bin_open, _bin_ccnt, _bin_crsr, ptr, 0);
MEM_Free(ptr);
MEM_Free(_bin_ccnt);
WIN_CloseHandle(_bin_open);
_bin_open = 0;
};
/*============
BinaryReader
============*/
func int BR_OpenFile(var string file) {
_bin_prefix = "BR_OpenFile";
if(!_BIN_nRunning()) { return 0; };
_bin_open = WIN_CreateFile(file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(_bin_open==-1) {
_BIN_Err("Datei konnte nicht geöffnet werden.");
return 0;
};
var int len; len = WIN_GetFileSize(_bin_open, 0);
_bin_ccnt = MEM_Alloc(len);
var int ptr; ptr = MEM_Alloc(4);
WIN_ReadFile(_bin_open, _bin_ccnt, len, ptr, 0);
MEM_Free(ptr);
_bin_clen = len;
_bin_mode = 1;
_bin_crsr = 0;
return 1;
};
func int BR(var int length) {
_bin_prefix = "BR";
if(!_BIN_Running()||!_BIN_nMode(1)) { return 0; };
if(length < 1) { length = 1; };
if(length > 4) { length = 4; };
if(_BIN_EOF(length)) { return 0; };
var int b; b = MEM_ReadInt(_bin_ccnt + _bin_crsr);
if(length < 4) {
b = b&((256<<((length-1)<<3))-1);
};
_bin_crsr += length;
return b;
};
func int BR_Int() { return BR(4); };
func int BR_Byte() { return BR(1); };
func string BR_Char() {
_bin_buffer = " ";
var zString zs; zs = MEM_PtrToInst(STRINT_GetStringAddress(_bin_buffer));
MEM_WriteByte(zs.ptr, BR(1));
var string str; str = _bin_buffer;
_bin_buffer = "";
return str;
};
var int _BR_StringRes;
func string _BR_String(var string cond) {
_bin_prefix = "BR_String";
if(!_BIN_Running()||!_BIN_nMode(1)) { return ""; };
var int scpy; scpy = _bin_crsr;
var int pos; pos = MEM_StackPos.position;
MEM_CallByString(cond);
if(_BR_StringRes) {
MEM_StackPos.position = pos;
};
var zString zres; zres = MEM_PtrToInst(STRINT_GetHelpStringAddress());
var int len; len = _bin_crsr - scpy;
zres.ptr = MEM_Alloc(len);
zres.res = len;
MEM_CopyBytes(_bin_ccnt + scpy, zres.ptr, len);
zres.len = len;
var string str; str = MEMINT_HlpString;
MEMINT_HlpString = "";
return str;
};
func string BR_String() {
return _BR_String("_BR_STRING_DEFAULT");
};func void _BR_String_Default() {
_BR_StringRes = BR(1);
};
func int BR_Bytes(var int length) {
var int ptr;
if(length <= 4) {
ptr = MEM_Alloc(4);
MEM_WriteInt(ptr, BR(4));
return ptr;
};
_bin_prefix = "BR_Bytes";
if(!_BIN_Running()||!_BIN_nMode(1)) { return 0; };
if(_bin_crsr + length > _bin_clen) {
_bin_Err("Die angegebene Struktur ist in dieser Datei nicht vollständig enthalten.");
return 0;
};
ptr = MEM_Alloc(length);
MEM_CopyBytes(_bin_ccnt + _bin_crsr, ptr, length);
return ptr;
};
func string BR_Textline() {
return _BR_String("_BR_STRING_NEXTLINE");
};func void _BR_String_NextLine() {
var int curr; curr = BR(2);
if(!curr) { _BR_StringRes = 0; }
else {
_BR_StringRes = !(curr == 2573);
_bin_crsr -= 1;
};
};
func string BR_Text(var int length) {
if(length <= 0) { return ""; };
if(length == 1) { return BR_Char(); };
_BR_StringRes = length;
return _BR_String("_BR_STRING_LENGTH");
};func void _BR_String_Length() {
var int tmp; tmp = BR(1);
_BR_StringRes -= 1;
};
func void BR_Close() {
_bin_prefix = "BR_Close";
if(!_BIN_Running()||!_BIN_nMode(1)) { return; };
MEM_Free(_bin_ccnt);
WIN_CloseHandle(_bin_open);
_bin_open = 0;
};
Erklärungen zu dem Schreiber:Erklärungen zu dem Leser:Und noch drei kleine Beispiele:
Sinnvollerweise könnte man die EngineHooks verwenden um die Speicherfunktion abzufangen und dort den Slot herausfinden um eine zweite Speicherdatei für strings anzulegen oä., darauf hatte ich jetzt nur gerade keine Lust
MfG Gottfried
Geändert von Gottfried (24.05.2011 um 21:38 Uhr)
-
Cool, das ist genau das, wofür ich eigentlich mal anfangen wollte, mir Ikarus anzugucken.
Jetzt lass ich das wohl erstmal wieder bleiben
Alle fragen sich wie kann ich noch schöner werden,
aber keiner fragt sich für wen.
-
ich hab im moment ne ziemliche diskussion mit zaphod darüber ob es möglich ist Items auszutauschen.
ich meinte aber nicht so einfach, sondern folgende situation:
ich hab ja die krallen gemacht, an der hand passen sie perfekt aber wenn ich die wegstecke dann schweben sie an der hüfte rum und das sieht vollkommen.... naja aus.
darum dachte ich, ich bastel eine zweite kralle die perfekt an der Hüfte anliegt, dafür aber nicht gut an der hand und wenn der Held die Waffe zieht soll sie augenblicklich gegen die passende ausgetauscht werden.
dafür müsste ich aber abfragen können ob der Held gerade mit der unpassenden Kralle (also Dummy-item) in den Fightmode gegangen ist und dann auch noch darauf zugreifen können um das dummyitem gegen die waffe zu tauschen. dazu müsste das Dummy-item natürlich auch direkt aus dem inv entfernt werden sonst macht der spieler das inv auf und hat dummy-item und echte waffe drin. umgekehrt wenn der spieler das wieder wegsteckt muss man das auch wieder austauschen und den dummy kreiren sowie die waffe entfernen.
ist das möglich oder verlange ich da zu viel?
die normalen equipfunktionen sorgen nämlich dafür, dass der held garnichts mehr in der hand hat und das item an seinem gürtel erscheint obwohl es in die hand müsste
"Das erinnert doch sehr erfreulich an das, was man sich als Gothicfan wünscht!"
-Korallenkette
-
Mit den Hooks von Lehona könnte es klappen, wenn du folgende Funktionen hookst:
oCNpc::EquipItem(oCItem *)
oCNpc::UnequipItem(oCItem *)
Ich hab's nicht getestet, aber vllt. klappt's damit, wenn du eben überprüfst ob ECX der Hero ist und der Paramter deine Klaue (bei Equip und Unequip eben die richtige raussuchen) und die dann austauscht zu dem Zeitpunkt.
Kann das später auch mal versuchen, ich meld mich dann mal per PN
EDIT: Quatsch, du willst ja nicht beim Equippen, sondern beim ziehen. Ich guck nochmal ^^
Geändert von Bonne6 (25.05.2011 um 17:57 Uhr)
-
Ich würde
Code:
virtual void __thiscall zCVob::SetVisual(class zSTRING const &)
oder
Code:
virtual void __thiscall oCItem::SetVisual(class zCVisual *)
ausprobieren. Für letzteres bräuchte man wohl Objekten mit den passenden Visuals in der Welt um passende zCVisual Pointer herzubekommen.
Reagieren würde ich über eine Triggerschleife und auf Npc_GetReadiedWeapon oder Npc_GetEquippedMeleeWeapon arbeiten.
Aber das braucht einiges an Erfahrung im Skripten um das hinzukriegen.
Nichts, was man mal schnell aus dem Hut zaubert, wenn man noch nicht viel mit Ikarus gearbeitet hat.
-
EDIT: eine noch erweiterte Version gibt es hier:
http://forum.worldofplayers.de/forum...5#post18324335
Es wurde einmal gefragt, ob es möglich ist, die Tageszeit festzuhalten, so dass Himmel, Helligkeit, Sonne, Mond,... praktisch von der Uhrzeit entkoppelt werden, gleichzeitig aber die Uhrzeit weiterläuft (für Tagesabläufe wichtig).
Das Problem habe ich schon vor einiger Zeit mit großer Hilfe von Sektenspinner gelöst und bevor ich irgendwann versehentlich das Skript lösche, veröffentliche ich es hier:
Code:
FUNC void FixSkyTime (VAR int skyHour, VAR int skyMinute)
{
var int desiredSkyTime;
desiredSkyTime = divf(mkf(((skyHour+12)%24)*60 + skyMinute), mkf(24*60));
//Ein Float zwischen 0 ( = 12 Uhr) und 1 ( = 12 Uhr nächster Tag)
//Pointer auf desiredSkyTime
var int ptr;
ptr = MEM_GetParserSymbol("FIXSKYTIME.DESIREDSKYTIME"); //Annahme: desiredSkyTime ist in der Funktion FIXSKYTIME deklariert
ptr += 24; //die Variable steht an offset 0x18 im zCPar_Symbol (nachzulesen in zCParser.d).
var int cursor; //wo wir grade schreiben
cursor = 7868992; //das ist die Adresse wo GetSkyTime losgeht. 0x781240 -> IDA
MemoryProtectionOverride(cursor, 20); //Jetzt dürfen wir in GetSkyTime 20 Bytes schreiben (auch wenn wir hier nur 10 brauchen)
MEM_WriteInt (cursor, 1497); //der Opcode von fld 0x05D9 -> IDA (Achtung: Bytereihenfolge umdrehen!)
cursor += 2; //0x0509 war zwei Bytes lang, also die schreibposition um zwei weiter bewegen.
MEM_WriteInt(cursor, ptr); //ptr ist die oben berechnete Adresse von desiredSkyTime
cursor += 4; //ein Pointer ist vier Byte groß.
MEM_WriteInt(cursor, 195); //retn. 0xC3
//Jetzt gibt die Funktion GetSkyTime dem Spiel also die Uhrzeit aus, die in desiredSkyTime angegeben ist
};
FUNC void UnFixSkyTime ()
{
//Hier wird oCWorldTimer :: GetSkyTime wieder zurückgesetzt
//0xD9 05 68 E1 83 00 D8 0D D4 E8 -> IDA
var int cursor; //wo wir grade schreiben
cursor = 7868992; //das ist die Adresse wo GetSkyTime losgeht. 0x781240 -> IDA
MemoryProtectionOverride(cursor, 20); //Jetzt dürfen wir in GetSkyTime 20 Bytes schreiben (auch wenn wir hier nur 10 brauchen)
MEM_WriteByte (cursor, 217); //0xD9
cursor += 1; //ein Byte weiter
MEM_WriteByte (cursor, 5); //0x05
cursor += 1; //ein Byte weiter
MEM_WriteByte (cursor, 104); //0x68
cursor += 1; //ein Byte weiter
MEM_WriteByte (cursor, 225); //0xE1
cursor += 1; //ein Byte weiter
MEM_WriteByte (cursor, 131); //0x83
cursor += 1; //ein Byte weiter
MEM_WriteByte (cursor, 0); //0x00
cursor += 1; //ein Byte weiter
MEM_WriteByte (cursor, 216); //0xD8
cursor += 1; //ein Byte weiter
MEM_WriteByte (cursor, 13); //0x0D
cursor += 1; //ein Byte weiter
MEM_WriteByte (cursor, 212); //0xD4
cursor += 1; //ein Byte weiter
MEM_WriteByte (cursor, 232); //0xE8
};
Zu Benutzen so:
Ikarus notwendig!
Floatpaket notwendig!
(beides findet man in der Signatur von Sektenspinner)
Das Skript irgendwo danach parsen lassen.
FixSkyTime (stunde, minute); //aufrufen mit der Uhrzeit, auf die der Himmel gesetzt werden soll
UnFixSkyTime (); //aufrufen, damit sich der Himmel wieder normal verändert - der Himmel springt SOFORT auf den Zustand der aktuellen Uhrzeit
Wie es funktioniert: Es wird an die Stelle, an der normalerweise steht, dass sich die Funktion die aktuelle Uhrzeit holt (um den Himmel entsprechend zu setzen) geschrieben, dass die Variable desiredSkyTime als Uhrzeit für den Himmel genutzt wird.
Das Feststellen des Himmels bleibt auch nach dem Laden erhalten. Beim Starten eines neuen Spiels ist der Himmel auf die Startzeit festgesetzt und ändert sich erstmal nicht. Ein Neustart von Gothic stellt alle Änderungen zurück. Deshalb sollte man möglichst in der Init_Global die FixSkyTime und UnFixSkyTime aufrufen, je nachdem, wie es gerade sein soll.
Ich habe es schon ein kleines bisschen getestet, wenn euch noch was auffällt, dann kann ich das natürlich noch versuchen, auszubessern.
EDIT: den flüssigen Übergang wie von Ingenieur im verlinkten Beitrag beschrieben, kann man heutzutage bestimmt auch wunderbar mit Anim8 aus LeGo lösen. Das Floatpaket ist, glaube ich, mittlerweile Teil von Ikarus. Wenn da also eine float.d im Download beiliegt, braucht das Floatpaket wohl nicht extra installiert zu werden.
Geändert von Milky-Way (27.08.2016 um 16:42 Uhr)
Grund: kleine Notiz zum aktuellen Stand / aktuellen Möglichkeiten hinzugefügt
-
Schöne Arbeit
Aber mich interessiert, woher fld kommt? Das IntelManual kennt nur D9, das Präfix verwirrt mich.
-
-
Ich verstehe nicht, was genau du willst. Natürlich haben die Objekte Koordinaten und wenn du die Adresse eines Objektes hast, kannst du auch dessen Koordinaten in Erfahrung bringen oder ändern.
-
Und wie schaut das ganze dann im Code aus?
-
In der Dokumentation von Ikarus gibt es folgendes Beispiel:
Code:
func void PrintCameraPos() {
/* Globale Instanzen (die es nur einmal gibt) initialisieren: */
/* Initialisiert MEM_World, MEM_Game, etc. u.a. auch MEM_Camera */
MEM_InitGlobalInst();
/* Das Kameraobjekt ist kein vob (sondern was abstraktes),
* weiß nicht wo und wie da Positionsdaten stehen.
Ich arbeite lieber auf dem Kameravob: */
var zCVob camVob;
camVob = MEM_PtrToInst (MEM_Camera.connectedVob);
/*Hier muss man wissen wie die Transformationsmatrix aufgebaut ist:
Sie besteht aus drei Vektoren, die x, y und z Richtung
des lokalen Koordinatensystem des Kameravobs
in Weltkoordinaten angeben (dabei müsste z die
Blickrichtung sein). Ich habe diese Vektoren hier
mit v1, v2, v3 Bezeichnet.
Zusätzlich gibt es in der 4. Spalte die Translation,
das heißt die Position der Kamera.
v1_x v2_x v3_x x
v1_y v2_y v3_y y
v1_z v3_z v3_z z
0 0 0 0
Die Matrix ist Zeilenweise im Speicher abgelegt.
Da wir uns für die letzte Spalte interessieren sind die Indizes
im trafoWorld Array 3, 7 und 11, die wir brauchen.
*/
Print (ConcatStrings ("x: ", IntToString(roundf(camVob.trafoObjToWorld[ 3]))));
Print (ConcatStrings ("y: ", IntToString(roundf(camVob.trafoObjToWorld[ 7]))));
Print (ConcatStrings ("z: ", IntToString(roundf(camVob.trafoObjToWorld[11]))));
};
Ist das das, was du wissen willst?
-
-
Das sind die Indizes, das hat mit dem Speicherabbild wenig zu tun. Bei einem Integer-Array berechnet sich die Adresse halt aus Index*4.
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|
|