|
-
[Script] Eigene Schadensberechnung
Da es jetzt schon vermehrt direkte oder indirekte Nachfrage gab, hab ich mich hingesetzt und ein paar Sachen rausgesucht
Aber zum Script:
Code:
// Look for the function "DMG_OnDmg" to modify
class oSDamageDescriptor {
var int validFields; // zDWORD 0x00
var int attackerVob; // zCVob* 0x04
var int attackerNpc; // oCNpc* 0x08
var int hitVob; // zCVob* 0x0C
var int hitPfx; // oCVisualFX* 0x10
var int itemWeapon; // oCItem* 0x14
var int spellID; // zDWORD 0x18
var int spellCat; // zDWORD 0x1C
var int spellLevel; // zDWORD 0x20
var int dmgMode; // zDWORD 0x24
var int weaponMode; // zDWORD 0x28
var int dmgArray[8]; // zDWORD[8] 0x2C Vermutlich vor Abzug der Rüstungswerte
var int dmgTotal; // zREAL 0x4C // Nach Abzug der Rüstungswerte?
var int dmgMultiplier; // zREAL 0x50
var int locationHit[3]; // zVEC3 0x54
var int directionFly[3]; // zVEC3 0x58
var string visualFXStr; // zSTRING 0x5C
var int duration; // zREAL 0x60
var int interval; // zREAL 0x64
var int dmgPerInterval; // zREAL 0x68
var int dmgDontKill; // zBOOL 0x6C
var int bitfield; // 1 -> Once, 2 -> finished, 4 -> isDead, 8 -> isUnconscious
var int azimuth; // zREAL 0x74
var int elevation; // zREAL 0x78
var int timeCurrent; // zREAL 0x7C
var int dmgReal; // zREAL 0x80
var int dmgEffective; // zREAL 0x84
var int dmgArrayEffective[8]; // zDWORD[8] 0x104 // Vermutlich nach Abzug der Rüstungswerte, ohne Mindestschaden
var int vobParticleFX; // zCVob* 0x108
var int particleFX; // zCParticleFX* 0x10C
var int visualFX; // zCVisualFX* 0x110
};
func int DMG_OnDmg(var int victimPtr, var int attackerPtr, var int dmg, var int dmgDescriptorPtr) {
var oSDamageDescriptor dmgDesc; dmgDesc = _^(dmgDescriptorPtr);
var c_npc attackerNpc; attackerNpc = _^(attackerptr);
var c_npc victimNpc; victimNpc = _^(victimPtr);
// Diese Funktion anpassen, wenn ihr den Schaden verändern wollt! 'dmg' ist der von Gothic berechnete Schaden
return dmg;
};
var int _DMG_DmgDesc;
func void _DMG_OnDmg_Post() {
EDI = DMG_OnDmg(EBP, MEM_ReadInt(MEM_ReadInt(ESP+644)+8), EDI, _DMG_DmgDesc);
};
func void _DMG_OnDmg_Pre() {
_DMG_DmgDesc = ESI; // I'm preeeeetty sure it won't get moved in the meantime...
};
func void InitDamage() {
const int dmg = 0;
if (dmg) { return; };
HookEngineF(6736583/*0x66CAC7*/, 5, _DMG_OnDmg_Post);
const int oCNpc__OnDamage_Hit = 6710800;
HookEngineF(oCNpc__OnDamage_Hit, 7, _DMG_OnDmg_Pre);
dmg = 1;
};
Die Funktion InitDamage() einfach in der Init_Global() aufrufen, in der Funktion DMG_OnDmg() könnt ihr dann euren eigenen Schaden berechnen, wobei 'dmg' initial den von Gothic errechneten Wert hält. Die Funktion wird nur aufgerufen, wenn auch wirklich Schaden verursacht wird (soweit meine Tests), es funktioniert ebenfalls mit Magie.
Der DamageDescriptor beinhaltet einige weitere Informationen zum Schadensereignis, aber die meisten (einige?) der Werte wurden bereits verarbeitet und eine Veränderung wird keine Wirkung zeigen. In der Funktion _DMG_OnDmg_Pre wurden diese Werte noch nicht verarbeitet, das könnte also der passendere Ort sein, um einige Sachen (außer den Schaden) anzupassen.
Eine detailliertere Erklärung zur Benutzung findet man hier.
Um auf die NPCs zuzugreifen:
Code:
var c_npc slf; slf = _^(attackerptr);
var c_npc oth; oth = _^(victimPtr);
Edit: Code aktualisiert, enthält jetzt einen Pointer auf den DamageDescriptor des Ereignisses.
Geändert von Lehona (02.02.2021 um 10:53 Uhr)
-
hört sich ja toll an, das würde ich gerne nutzen
Aber ich kenne mich weder gut mit Ikarus noch mit Lego aus
ich sage dir mal was ich alles gemacht habe. Ikarus funktioniert wenn ich mich nicht irre bei mir.
LeGo habe ich jetzt zum ersten mal genutzt. LeGo runtergeladenund den LeGo Ordner in den Scripts Ordner kopiert. Sowie die alte HookVersion durch die neue ersetzt.
sowie die startup.d geändert
Code:
// *******************************************************************
// Startup und Init Funktionen der Level-zen-files
// -----------------------------------------------
// Die STARTUP-Funktionen werden NUR beim ersten Betreten eines Levels
// (nach NewGame) aufgerufen, die INIT-Funktionen jedesmal
// Die Funktionen müssen so heissen wie die zen-files
// *******************************************************************
// *********
// GLOBAL
// *********
func int DMG_OnDmg(var int victimPtr, var int attackerPtr, var int dmg)
{
// Diese Funktion anpassen, wenn ihr den Schaden verändern wollt! 'dmg' ist der von Gothic berechnete Schaden.
dmg = 10; ///jeder Angriff = 10 Schaden just testing
return dmg;
};
func void _DMG_OnDmg()
{
EDI = DMG_OnDmg(EBP, MEM_ReadInt(MEM_ReadInt(ESP+644)+8), EDI);
};
func void InitDamage()
{
const int dmg = 0;
if (dmg) { return; };
HookEngineF(6736583/*0x66CAC7*/, 5, _DMG_OnDmg);
dmg = 1;
};
func void STARTUP_GLOBAL()
{
// wird fuer jede Welt aufgerufen (vor STARTUP_<LevelName>)
Game_InitGerman();
};
func void INIT_GLOBAL()
{
// wird fuer jede Welt aufgerufen (vor INIT_<LevelName>)
Game_InitGerman();
MEM_InitAll();
LeGo_Init(LeGo_All);
InitDamage();
};
// *********
// Testlevel
// *********
Fehler
PAR: Unknown Inditifier EDI
wie gesagt kenne mich weder mit Ikarus noch mit LeGo aus.
-
Du musst die Header.src aus dem LeGo-Ordner noch in der Gothic.src eintragen. Desweiteren ist es vielleicht sinnvoll (Oder zumindest nicht unsinnvoll), nur die HookEngine.d zu parsen, da sie auch ohne weitere LeGo-Scripte lauffähig ist (Und du ja bisher nichts anderes brauchst). Wobei du es natürlich auch andersrum als Einladung sehen könntest, dich mit LeGo auseinander zu setzen, viel Vorwissen ist da nicht unbedingt nötig. Außerdem kannst du im Zweifelsfall ja immernoch fragen.
-
jetzt meckert er undefined function mkftimer in timer.d
habe jetzt den LeGo Ordner in den Content Ordner verschoben (weil die Gothic.src erst ab Content anfängt) und die gothic.scr geändert
Code:
_INTERN\CONSTANTS.D
_INTERN\CLASSES.D
_INTERN\Ikarus_Const_G2.d
_INTERN\EngineClasses_G2\*.d
_INTERN\Ikarus.d
LeGO\Header.src
AI\AI_INTERN\AI_CONSTANTS.D
weiß nicht ob die Reihenfolge richtig ist. Da Ikarus aber auch ohne LeGo funktioniert, tippe ich mal, dass die Reihenfolge nicht verkehrt ist.
habe dann mal in der gothic.src nicht header.src sondern nur die hookengine.d eingetragen
Dann meldet er in der HookEngine.d Undefined function _@line 77 einen Fehler.
Die scripts sehen mir alle viel zu kompliziert aus, da verstehe ich ja gar nichts.
-
Die Scripts sind recht kompliziert, aber sie sind ja auch zum Anwenden
Du musst dein Ikarus mal updaten, du brauchst 1.2 (alpha).
-
habe ich gemacht
Unknown Identifer LeGo_Init(LeGo_All);
habe draufhin das in der Klammer weggelassen da ich mich ja nur mit der Hookengine beschäftige, selbe Fehlermeldung
Habe jedoch beide ausversehen ausgeklammer, nächste Fehlermeldung
error, undenifed parser in hookengine.d
Ikarus wurde auf 1,2 gepacht
-
Hm, du hast Recht insofern als dass es die HookEngine.d alleine doch nicht tut, weil ein paar Konstanten ausgelagert sind. Also: Die Header.src wieder eintragen, den Aufruf an LeGo_Init(LeGo_All); kannst du komplett weglassen.
-
jetzt meckert er wieder mit dem mkf in timer.d
wieso werde ich das Gefühl nicht los, dass ich irgendwas wichtiges vergessen habe. Ikarus ist installiert, Lego 2.2.1/Scripts/Lego nach Content kopiert, (frage brauche ich auch den anderen teil die Resources, sah so nach Grafik sachen aus habe die daher nicht kopiert). Sonst noch was ???
-
Ich habe gerade mal nachgeschaut und Sektenspinner scheint das Floatpaket aus dem Download für 1.2 (alpha) entfernt zu haben. Da müsstest du die Datei "float.d" aus dem Download für 1.1.4 herunterladen und auch in die Gothic.src eintragen (nach Ikarus, vor LeGo).
Sorry für das Herumgeschnippel hier, aber sobald sowas einmal aufgesetzt ist macht man sich nie wieder Gedanken darüber.
-
ja wunderbar auf dich Lehona ist wie immer verlass. Habe jetzt einfach dmg = 10; dort hingeschrieben und alles und jeder fügt nun 10 Schaden zu.
Frage ist jetzt nur wie ich eine Schadensformel aufstelle.
Wie könnte ich das machen? Ich habe sowas ähnliches schonmal in einer B_meleehurtNPC.d geschrieben (ähnlich wie klaue beliar und magic hurt npc) nur dort war slf = angreifer und oth = Opfer.
Aber wie mache ich das hier?
-
Var c_npc slf; slf = _^(attackerptr);
Und das selbe auch mit victimptr und oth oder wie du die Variable nennen willst. Desweiteren hat dmg am Anfang ja schon den von Gothic errechneten Wert, das macht es einfacher wenn du bloß ein wenig Spielraum einbringen willst.
-
mhm irgendwie klappt das noch nicht so ganz, wobei kann auch daran liegen das ich Hundsmüde bin, werde mir morgen nochmal das script anschauen vielleicht entdecke ich ja dann den fehler
Code:
func int DMG_OnDmg(var int victimPtr, var int attackerPtr, var int dmg)
{
// Diese Funktion anpassen, wenn ihr den Schaden verändern wollt! 'dmg' ist der von Gothic berechnete Schaden.
///dmg = 10; ///jeder Angriff = 10 Schaden
Var c_npc slf; slf = _^(attackerptr);
Var c_npc oth; slf = _^(victimPtr);
var int meleedamage;
if (Npc_HasReadiedMeleeWeapon(slf)) //////Nahkampf ///////// Nahkampf
{
var c_item tmpItm; tmpItm = Npc_GetReadiedWeapon(slf);
var c_item wpn; wpn = Npc_GetReadiedWeapon(slf);
var int wpnDmg; wpnDmg = tmpItm.damageTotal;
var int armRes;
If tmpItm.damagetype == DAM_EDGE { armRes = oth.protection[PROT_EDGE]; }
else if tmpItm.damagetype == DAM_BLUNT { armRes = oth.protection[PROT_BLUNT]; }
else if tmpItm.damagetype == DAM_POINT { armRes = oth.protection[PROT_POINT]; };
if (wpn.flags & ITEM_2HD_AXE || wpn.flags & ITEM_2HD_SWD)
{
meleedamage = (wpnDmg+ slf.attribute[ATR_STRENGTH]*7/10 + slf.attribute[ATR_DEXTERITY]*15/100);
}
else ///Einhand
{
meleedamage = (wpnDmg+ slf.attribute[ATR_STRENGTH]*6/10 + slf.attribute[ATR_DEXTERITY]*2/10);
};
meleedamage = (meleedamage -armRes);
if (meleedamage < 0)
{
meleedamage = 0;
};
dmg = meleedamage; ///jeder Angriff = 10 Schaden
}; ///ende nahkampf
return dmg;
};
eine erhöhung meines Geschicks erhöht jedoch NICHT meinen Nahkampfschaden und Wölfe hauen mich ab und zu instant um auch wenn ich 1000HP habe.
-
fehler erkennt
Var c_npc slf; slf = _^(attackerptr);
Var c_npc oth; slf = _^(victimPtr);
kann so natürlich nichts werden, da sieht man mal wieder ich sollte nachts nicht mehr vorm PC sitzen werde dann immer so müde.
werde das so wie in meiner alten Schadensberechnung machen
///// Monster ///ausgelassen sumpfgolem, feuergolem, drache
if (slf.guild == GIL_MINECRAWLER)
|| ///alle monstergilden
{
}
else if (Npc_HasReadiedRangedWeapon(slf)) //Fernkampf
{
}
else if (Npc_HasReadiedMeleeWeapon(slf)) //////Nahkampf
{
///das klappt zumindest also wird der rest auch klappen
}
else ///Zauberei
{
};
Nur bei Monster, Fern und Distanzkampf ändere ich dmg von Grund auf, bei else lasse ich dmg einfach unverändert. Dann baue ich vielleicht noch eine variable wie altes wissen aus G3 ein womit man den Zauberschaden leicht verändern kann, und multipliziere das dann nochmal mit 0,9 bis 1.1 voila.
Und das tollste, ich muss nichtmal viel schreiben da ich das mehr oder weniger alles schon so bereit habe.
Einziger Nachteil, für Zauber würde es dann einen Mindestschaden geben aber egal was solls.
-
Also ich muss sagen das ist mal wieder sehr praktisch,
nie mehr stundenlang nach dem richtigem Punkt suchen um zusätzlichen Schaden dazuzugeben.
Danke
-
hi soweit klappt das ding super nur etwas klappt bei mir nicht.
Code:
else if (Npc_HasReadiedRangedWeapon(slf)) //Fernkampf ist buggy
{
var c_item wpn2; wpn2 = Npc_GetEquippedRangedWeapon(slf);
var int wpnDmg2; wpnDmg2 = tmpItm2.damageTotal;
var int rangecritchance;
if wpn2.flags & ITEM_BOW { rangecritchance = slf.HitChance[NPC_TALENT_BOW]; }
else if wpn2.flags & ITEM_CROSSBOW { rangecritchance = slf.HitChance[NPC_TALENT_CROSSBOW]; };
if (wpn2.flags & ITEM_BOW)
{
meleedamage = (wpnDmg2+ slf.attribute[ATR_STRENGTH]*0/100 + slf.attribute[ATR_DEXTERITY]*10/10); /////testing ändern
}
else ////armbrust
{
meleedamage = (wpnDmg2+ slf.attribute[ATR_STRENGTH]*0/10 + slf.attribute[ATR_DEXTERITY]*20/10);
};
var string concatText;
concatText = PRINT_XPGained;
concatText = ConcatStrings (concatText, IntToString(meleedamage));
PrintScreen (concatText, -1, YPOS_XPGained, FONT_ScreenSmall, 2);
} ///ende fernkampf
normalerweise hatte ich eine andere Schadensberechnung (hab sie jetzt nur zum testen geändert). Normalerweise erhält Bogen viel Boni aus Geschick und nur wenig aus Stärke und die Armbrust etwas mehr Bonus aus Stärke aber dafür weniger aus Geschick. Beim Spielen ist mir aufgefallen, dass ich weniger Schaden anrichte als ich theoretisch anrichten sollte. Bis mir der Fehler auffiel. Die Schadensberechnung war die der Armbrust und nicht des Bogens. Selbst wenn ich Bogen anlege wird der Schaden durch die Armbrustfunktion bestimmt
if (wpn2.flags & ITEM_BOW) {
scheint wohl irgendwie nicht zu klappen. Habe mich schon die ganze Zeit gefragt warum ich so ne miserable Kritischer Trefferchance hatte,
Wie lautet nochmal die richtige Abfrage.
-
Hm, das sollte eigentlich nicht passieren. Bist du dir sicher, dass in den Item-Scripten des jeweiligen Scripts auch "flags = ITEM_BOW;" steht?
-
ja hier eine bogeninstanz
mainflag = ITEM_KAT_FF;
flags = ITEM_BOW;
habs auch nochmal eben mit nahkampf getestet aber auch dort gilt egal ob Einhand oder Zweihand die Schadensberechnung für else, sprich die erste Abfrage
if (wpn.flags & ITEM_2HD_AXE || wpn.flags & ITEM_2HD_SWD)
wird nicht erfüllt obwohl ich eine waffe mit ITEM_2HD_AXE als flags hatte
-
Merkwürdig, ich habe keine Ahnung was das Auslösen könnte (es sollte allerdings nichts mit uns zu tun haben).
Versuche mal Npc_GetReadiedWeapon(slf) anstatt Npc_GetEquippedRangedWeapon(slf)... Ist aber auch nur ein Schuss ins Dunkle. Wenn das noch keinen Unterschied bringt, führe mal bitte Print(wpn2.name); in der Funktion aus. Wenn dann der richtige Name (der equippten Waffe) geprintet wird, habe ich keine Ahnung, was falsch sein könnte.
-
Zitat von Lehona
Versuche mal Npc_GetReadiedWeapon(slf) anstatt Npc_GetEquippedRangedWeapon(slf)... Ist aber auch nur ein Schuss ins Dunkle
War ein Schuss ins Richtige. danke
-
Zitat von Lehona
Die Scripts sind recht kompliziert, aber sie sind ja auch zum Anwenden
Du musst dein Ikarus mal updaten, du brauchst 1.2 (alpha).
verdammt ich wollte auch gerne die Schadensberechnung (die wirklich 1a ist) auf G1 anwenden. Aber Ikarus 1.2 gibt es bisher ja nur für G2. Gibts da ne Möglichkeit was zu machen?
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|
|