|
-
Npc_FindByID gibt -1 zurück wenn kein NPC gefunden wird.
Ich fände das schöner wenn da 0 zurück kommt, da das ja ein pointer sein soll.
Auch im Hinblick auf:
https://forum.worldofplayers.de/foru...1#post25929309
Oder gibt es für den -1 Rückgabewert einen Grund den ich nicht erkenne?
-
Ist mir auch aufgefallen, dass ich da Mist gebaut habe und auf dem Dev-Branch gibt das schon 0 zurück.
-
Okay, ich schau dann in Zukunft in den dev branch bevor ich was sage.
-
-
Zitat von pawbuj
have u also fix the bug with mobswitch state01 after save/load game? It causes the mover being stucked when mobswitch will be in position 1 (gate closed) while saving.
Zitat von F a w k e s
Hello pawbuj,
I was able to replicate this issue now:[...]
I've been in contact with pawbuj about this issue and have fixed the above mentioned "Negatives" of Fawkes solution (fixing of the animation) and updated the code. I took the liberty to reorganize the functions a bit.
This should completely fix the problem. It should also be the most robust way to do it. I had originally added state and state_target to the archive by hooking the oCMobInter-zCArchiver. While being slightly more elegant it had some issues of its own.
Code:
/*
* Complementary Hlp_Is_* function for zCTriggerList
*/
func int Hlp_Is_zCTriggerList(var int ptr) {
const int zCTriggerList_vftable_G1 = 8239436; //0x7DB94C
const int zCTriggerList_vftable_G2 = 8625812; //0x839E94
if (!ptr) { return 0; };
return (MEM_ReadInt(ptr) == MEMINT_SwitchG1G2(zCTriggerList_vftable_G1, zCTriggerList_vftable_G2));
};
/*
* Obtain the state of a vob or its trigger target vob recursively
*/
func int FixMobSwitches_GetTargetState(var string targetVobName) {
var int targetPtr; targetPtr = MEM_SearchVobByName(targetVobName);
if (Hlp_Is_zCMover(targetPtr)) {
var zCMover mover; mover = _^(targetPtr);
return mover.moverState == 0; // MOVER_STATE_OPEN
} else if (Hlp_Is_zCTriggerList(targetPtr)) {
const int zCTriggerList__activeTargetIdx_offset = 476; //0x1DC
const int zCTriggerList__triggerTargets_offset = 328; //0x148
var int idx; idx = MEM_ReadInt(targetPtr+zCTriggerList__activeTargetIdx_offset);
var int arr; arr = targetPtr+zCTriggerList__triggerTargets_offset;
return FixMobSwitches_GetTargetState(MEM_ReadStringArray(arr, idx)); // Recursion with new trigger target
} else {
// No target or non-triggerable (== another oCMobInter)
return 0;
};
};
/*
* These functions are called on loading and iterate over all oCMobInter objects to restore their state given the
* state of their trigger target vob
*/
func void FixMobSwitches_Restore_Sub(var int vobArrayPtr) {
var zCArray vobList; vobList = _^(vobArrayPtr);
repeat(i, vobList.numInArray); var int i;
var int vobPtr; vobPtr = MEM_ArrayRead(vobArrayPtr, i);
const int oCMobInter__Reset = 6803776; //0x67D140
const int call = 0;
if (CALL_Begin(call)) {
CALL__thiscall(_@(vobPtr), oCMobInter__Reset);
call = CALL_End();
};
end;
};
func void FixMobSwitches_Restore() {
var int vobArrayPtr; vobArrayPtr = MEM_ArrayCreate();
if (SearchVobsByClass("oCMobInter", vobArrayPtr)) {
FixMobSwitches_Restore_Sub(vobArrayPtr);
};
MEM_ArrayFree(vobArrayPtr);
};
/*
* Set the mob state according to its trigger target
*/
func void FixMobSwitches_ResetHook() {
var oCMobInter mob; mob = _^(EDI);
var int state; state = FixMobSwitches_GetTargetState(mob.triggerTarget);
mob.state = state;
mob.state_target = state;
};
/*
* Set the animation state according to the oCMobInter state when resetting oCMobInter objects
*/
func void FixMobSwitches_ResetAni() {
var oCMobInter mob; mob = _^(MEM_ReadInt(ESP+20)); //esp+3Ch-28h
var zString ani; ani = _^(ECX); // "S_S0"
const int ASCII_0 = 48;
MEM_WriteByte(ani.ptr+3, mob.state+ASCII_0); // Modify last character
};
/*
* Initialization: Call this function from Init_Global
*/
func void FixMobSwitches_Init() {
const int oCMobInter__Reset_nonrewind = 6803827; //0x67D173
const int oCMobInter__Reset_resetState = 6804058; //0x67D25A
const int oCMobInter__Reset_setAniState = 6803955; //0x67D1F3
MEM_InitAll();
// Match target state
HookEngineF(oCMobInter__Reset_nonrewind, 6, FixMobSwitches_ResetHook);
// Overwrite resetting of animation
HookEngineF(oCMobInter__Reset_setAniState, 7, FixMobSwitches_ResetAni);
// Remove resetting of mob state
MemoryProtectionOverride(oCMobInter__Reset_resetState, 12);
const int nop12Btyes[3] = { -1869574000, -1869574000, -1869574000 }; // 0x90 * 12
MEM_Copy(_@(nop12Btyes), oCMobInter__Reset_resetState, 3);
// Restore mob state manually on first load
FixMobSwitches_Restore();
};
Geändert von mud-freak (04.03.2019 um 21:23 Uhr)
Grund: Reimplemented using states of trigger targets
-
@mud-freak u're doing great job!
works perfectly !!!
Geändert von pawbuj (23.10.2018 um 22:20 Uhr)
-
@mud-freak - nice one, thank you !
-
Was that only a G1 bug, or also a G2 one?
-
LeGo ist umgezogen! Allerdings nicht das Wiki (das weiterhin netterweise von der WoP gehostet wird), sondern unser Repository. Anstatt SVN und assembla.com zu verwenden, benutzen wir jetzt git auf GitHub.com. Vielleicht fällt als kleiner Nebeneffekt ja dabei raus, dass es jetzt einfacher ist, Änderungen oder Erweiterungen per Pull Request vorzuschlagen
-
Was ist ein einfacher Weg, die Mana-Bar dauerhaft anzuzeigen?
Ich komme ja mit
Code:
var zCView bar; bar = _^(MEM_Game.manaBar);
an die manaBar dran. Dann hatte ich probiert, mit
Code:
const int call = 0;
if(CALL_Begin(call)) {
CALL__thiscall(_@(bar), 8023040); // 0x007A6C00 -- zCView::Open
call = CALL_End();
};
die Bar anzuzeigen, aber da stürzt das Spiel bei mir ab...
Code:
void __thiscall zCView::Open(void) 0x007A6C00 0 5 public: void __thiscall zCView::Open(void)
Für die LeGo-Funktionen zu bar und view ist mir nicht klar, wie ich von meinem zCView (oder oCViewStatusBar*) zu einem handle komme, und wie ich abfragen würde, ob der Balken gerade schon angezeigt wird.
PS: der Absturz kommt, wenn ich versuche, meinen view jedes Frame zu öffnen -- beim Versuch, es einmalig zu öffnen, schien es sofort wieder weg zu sein (oder nie dagewesen)
PPS: Nach noch etwas mehr Suche, habe ich nun wohl die Lösung gefunden
https://forum.worldofplayers.de/foru...1#post15483138
Falls mir jemand erklären könnte, wie ich von einem view / pointer Objekt zu einem handle für LeGo kommen kann, und wie ich abfragen kann, ob ein view bereits angezeigt wird, wäre ich allerdings noch dankbar
Geändert von Milky-Way (04.12.2018 um 20:09 Uhr)
-
Vaage Vermutung: Vielleicht liegt es daran das du die ManaBar als zCView behandelst statt als oCViewStatusBar?
Das hier funktioniert bei mir:
Code:
if(MEM_Game.manaBar != 0){
var oCViewStatusBar manaBar;
manaBar = MEM_PtrToInst(MEM_Game.manaBar);
if(manaDecreasePercentage == MANA_DECREASE_IN_PERCENT_GHOSTWOLF){
ViewPtr_SetTexture(manabar.range_bar, "Bar_TempMaxBlocked1.tga");
}else if(manaDecreasePercentage == MANA_DECREASE_IN_PERCENT_SUMSKELWARRIOR){
ViewPtr_SetTexture(manabar.range_bar, "Bar_TempMaxBlocked2.tga");
}else if(manaDecreasePercentage > 0){
ViewPtr_SetTexture(manabar.range_bar, "Bar_TempMaxBlocked3.tga");
}else{
ViewPtr_SetTexture(manabar.range_bar, "Bar_TempMax.tga"); // Gothic deafault, full transparency
};
manaDecreasePercentageBarSet = manaDecreasePercentage;
};
Und wenn du einen pointer auf die ManaBar haben willst um eine engine Funktion aufzurufen kannst du doch einfach MEM_Game.manaBar benutzen statt das hin- und her zu wandeln?
-
Zitat von Cryp18Struct
Vaage Vermutung: Vielleicht liegt es daran das du die ManaBar als zCView behandelst statt als oCViewStatusBar?
Das hier funktioniert bei mir:
Code:
if(MEM_Game.manaBar != 0){
var oCViewStatusBar manaBar;
manaBar = MEM_PtrToInst(MEM_Game.manaBar);
if(manaDecreasePercentage == MANA_DECREASE_IN_PERCENT_GHOSTWOLF){
ViewPtr_SetTexture(manabar.range_bar, "Bar_TempMaxBlocked1.tga");
}else if(manaDecreasePercentage == MANA_DECREASE_IN_PERCENT_SUMSKELWARRIOR){
ViewPtr_SetTexture(manabar.range_bar, "Bar_TempMaxBlocked2.tga");
}else if(manaDecreasePercentage > 0){
ViewPtr_SetTexture(manabar.range_bar, "Bar_TempMaxBlocked3.tga");
}else{
ViewPtr_SetTexture(manabar.range_bar, "Bar_TempMax.tga"); // Gothic deafault, full transparency
};
manaDecreasePercentageBarSet = manaDecreasePercentage;
};
Ich habe mich jetzt erst dank deines Beispiels wieder dran erinnert, dass es zu den View Funktionen auch jeweils die ViewPtr Funktionen gibt. Damit sollte es dann mit ViewPtr_Open wohl gehen.
Und wenn du einen pointer auf die ManaBar haben willst um eine engine Funktion aufzurufen kannst du doch einfach MEM_Game.manaBar benutzen statt das hin- und her zu wandeln?
Da hast du recht, das war mir nach ein wenig hin- und herprobieren wohl nicht mehr aufgefallen.
Dann wäre jetzt noch meine Frage offen, ob ich mit LeGo oder anderswie sicher abfragen kann, ob ein view bereits offen ist. ViewPtr_open scheint mir dasselbe zu machen, wie mein Versuchscode oben (dieselbe Engine-Funktion wird aufgerufen), so dass es da wohl ebenfalls zum Absturz kommen würde, wenn ich das in jedem Frame aufrufe.
-
Zitat von Milky-Way
Diese Frage hast du dir ja schon selbst beantwortet Aber zum Rest.
Zitat von Milky-Way
Falls mir jemand erklären könnte, wie ich von einem view / pointer Objekt zu einem handle für LeGo kommen kann, und wie ich abfragen kann, ob ein view bereits angezeigt wird, wäre ich allerdings noch dankbar
Falls du das an einer anderen Stelle nochmal brauchst: Wenn man nur einen Pointer hat, eine Funktion aber ein Handle erwartet (der selben Klasse natürlich), gibt es die Funktion wrap. Die erzeugt ein Handle einer bestimmten Instanz, das mit dem übergebenen Pointer befüllt ist. Da das Objekt höchstwahrscheinlich aber weiterhin der Engine "gehört", sollte man das Handle am besten* danach mit release freigeben, sonst wird der Speicher zum Beispiel beim Laden eines Spielstandes freigegeben, was meistens zu einem Absturz führt (entweder weil der Speicher bereits freigegeben wurde oder weil die Engine erwartet, dass er weiter gültig ist).
Zitat von Milky-Way
Dann wäre jetzt noch meine Frage offen, ob ich mit LeGo oder anderswie sicher abfragen kann, ob ein view bereits offen ist. ViewPtr_open scheint mir dasselbe zu machen, wie mein Versuchscode oben (dieselbe Engine-Funktion wird aufgerufen), so dass es da wohl ebenfalls zum Absturz kommen würde, wenn ich das in jedem Frame aufrufe.
Den Absturz gibt es, weil du ein oCViewStatusBar* anstatt eines zCView* übergibst. Ersteres ist keine Unterklasse von zweiterem, also ist das ungültig und stürzt zu 99% ab. Eine oCViewStatusBar* hat aber eine oder mehrere zCViews, also müsste man die verwenden (siehe Cryp18Struct).
zCView (definiert in zCMenu.d, Ikarus) hat die Eigenschaften isClosed und isOpen (warum auch immer es zwei gibt), eine oder beide werden vermutlich das beinhalten, was du suchst
*Falls man das sehr oft tut, könnte das dazu führen, dass dauernd Handles erstellt und gelöscht werden, so dass theoretisch irgendwann die Handle-Grenze von ca. 4 Milliarden erreicht wird. Dann funktioniert PermMem nicht mehr.
-
LeGo 2.5.1
- PermMem: Kritischer Quicksave-Fix zum korrekten Laden von Handles
- TimerGT: Neuer Timer, der nur im Spiel läuft und im Menü pausiert
- FrameFunctions: Neue Funktionen für den TimerGT, neue Funktion zum Entfernen aller FF, die auf eine bestimmte Funktion zeigen (Danke an das Team von Dirty Swamp!)
- Buffs + Anim8: Benutzen jetzt den TimerGT
- Buffs: Neue Konstante ("Buffs_DisplayForHero") in der UserConst.d, um Icons für den Spieler anzeigen zu lassen oder nicht
- Anim8: Kleine Fixes und eine neue On-Remove-Funktion, die wie ein Destruktor für Anim8-Objekte fungiert
- Talents: "Npc_FindByID" gibt nun 0 zurück, wenn kein NPC gefunden wird
- Buttons: "Button_Move" korrigiert
- DialogGestures: Fix beim Zurücksetzen der Animation
- HookEngine: Datenstack wird jetzt zwischen Funktionsaufrufen geleert
- Talents: Talents-Array wird beim einfachen Abfragen mit "TAL_GetValue" nicht mehr automatisch erstellt
- Interface: Vereinfachung vom PrintScreen-Fix (war vorher sehr un-performant bei vielen PrintScreens)
- HookDaedalus: NEU! Siehe Wiki.
- Bloodsplats: Eigene Damage-Perception wird nicht mehr überschrieben, d.h. man kann nun neben den Bloodsplats auch eine eigene Damage-Perception-Funktion für den Helden registrieren
- ConsoleCommands: Bei Eingabe von "LeGo" in die Konsole (vorausgesetzt ConsoleCommands sind initialisiert), wird sowohl die LeGo Version als auch die aktiven LeGo Flags in "human-readable" Form ausgegeben. Diese Information wird auch bei Initialisierung von LeGo an den zSpy gesendet (Screenshot).
- Separate G1 und G2 Header Dateien (Infos siehe unten)
Um das Einbinden von LeGo zugänglicher zu machen, gibt es jetzt - wie auch schon bei Ikarus 1.2.1 - separate SRC-Dateien für Gothic 1 und Gothic 2: Header_G1.src und Header_G2.src. Beim Aktualisieren auf diese neue LeGo Version muss man den Eintrag in der Gothic.src entsprechend anpassen.
Das Paket "Buffs" hat es mit diesem Release leider "immer noch nicht" aus dem experimentellen Status heraus geschafft. Wir würden uns sehr über Rückmeldungen freuen von Leuten, die die Buffs bereits benutzen.
-
can u also add description in English, pls?
-
Zitat von pawbuj
can u also add description in English, pls?
You can find the release notes on Github in English when you follow the download link.
-
Zitat von mud-freak
Das Paket "Buffs" hat es mit diesem Release leider "immer noch nicht" aus dem experimentellen Status heraus geschafft. Wir würden uns sehr über Rückmeldungen freuen von Leuten, die die Buffs bereits benutzen.
Inwiefern Rückmeldung? Was müsste denn getestet werden oder ob die Buffs allgemein funktionieren? Ich nutze sie für ein Gift-Feature bei Blutfliegen bzw einem Gegengift-Trank. Funktioniert alles bestens, außer dass der Buff manchmal auch beim Fallschaden aufgerufen wird, aber ich denke das liegt an einem Implementationsfehler meinerseits.
-
-
Ich sehe gerade, dass die Klasse lCBuff keine (Un-)Archiver Funktionen hat. Deshalb werden die Symbolindizes als Zahl mit PermMem gespeichert. Buffs sind deshalb nicht resistent gegen Mod-Updates (Speicherstände in fast allen Fällen nicht kompatibel). Das wäre auf jeden Fall etwas, was wir ändern sollten. Für ein bisschen mehr Performance könnte man auch die enthaltenen Funktionen als Pointer anstelle ihrer Symbol ID in der Klasse speichern, dann muss das nicht bei jedem Tick aufgelöst werden.
Ich vermerke das mal im Issue Tracker auf Github (dann können wir den mal einweihen).
-
Hallo,
wir haben in unserer Modifikation einige Tränke, die eine vorübergehende Wirkung haben. Diese funktionieren mit Buffs. Momentan ist es ja nur möglich, eine Textur für jeden Buff anzeigen zu lassen, solange dieser läuft. Dann verschwindet diese einfach nach Ablauf der Zeit ganz plötzlich. Das ist natürlich (zumindest mMn.) relativ ungünstig, da man so zum Beispiel bei einem "Trank der Giftresistenz" nicht weiß, ob man einen Kampf - zum Beispiel gegen eine Gruppe Blutfliegen, die den Spieler vergiften kann - noch vor Ablauf der Zeit schafft, oder ob man lieber fliehen sollte.
Wäre es also eventuell möglich, die Buffs so anzupassen, dass auf die eigentliche Buff-Textur eine zweite (transparente) Textur gelegt werden kann, die dann bis zum Ablauf der Zeit immer kleiner wird und sobald der Buff vorbei ist komplett verschwindet? Diese sollte natürlich dann auch wieder zurückgesetzt werden, falls der Buff noch vor Ablauf der Zeit erneuert wird.
Ich hätte es schon selbst gemacht... Kenne mich mit LeGo aber leider immer noch so ziemlich überhaupt nicht aus.
Geändert von Bloodfly91 (17.01.2019 um 00:13 Uhr)
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|
|