Portal-Zone Gothic-Zone Gothic II-Zone Gothic 3-Zone Gothic 4-Zone Modifikationen-Zone Download-Zone Foren-Zone RPG-Zone Almanach-Zone Spirit of Gothic

 

Ergebnis 1 bis 12 von 12
  1. Beiträge anzeigen #1 Zitieren
    Ritter Avatar von aebo
    Registriert seit
    Oct 2008
    Beiträge
    1.278
     
    aebo ist offline

    AOE Damage

    Moin Zusammen,

    ich wollte mir nun noch ein letztes Feature meiner Modifikation vornehmen. Es geht um eine Art 'AOE Damge'. Also Flächenschaden.
    Hat jemand da zufällig schon mal etwas probiert und teilt hier seine bisherigen Erfahrungen? Wo treten Probleme auf? Muss man auf etwas besonderes Achten?
    Bin gespannt auf Eure Kommentare.

    Beste Grüße
    Das Wappen
    -Eine fantastische Spielwelt erwartet dich-
    -bis zu 100 Stunden Spielzeit-

  2. Beiträge anzeigen #2 Zitieren
    Knight Avatar von Draxes
    Registriert seit
    Aug 2007
    Ort
    Mainz
    Beiträge
    1.920
     
    Draxes ist offline
    Eins meiner absoluten Top-Themen, da ich mich viel mit neuen Zaubern beschäftigt habe und dort auch der ein oder andere AOE Zauber am Start ist.
    Jetzt gibt es natürlich verschiedene Möglichkeiten Flächenschaden umzusetzen, je nachdem, was dein konkretes Ziel ist. Deshalb hole ich einfach mal etwas aus.

    1) Broadcasts

    Broadcasts sind klasse. Du rufst damit eine Funktion aus, die für alle Npcs (meistens mit Einschränkung "in der KI-Glocke") aufgerufen wird. Dort kannst du dann lustig Dinge prüfen wie "stehe ich nah genug am hero dran, um Flächenschaden zu kassieren"?
    Soeinen Broadcast kann man dann zum Beispiel für Nahkampf/Fernkampf-Flächenschaden in einem damageHook (falls du sowas hast) oder auch in der B_AssessDamage() aufrufen.

    Die Broadcasts selber sind von Sektenspinner implementiert worden.
    https://forum.worldofplayers.de/foru...1#post17232705

    Einsatzweise:
    Code:
    // Aufruf zum Beispiel in B_AssessDamage()
    broadcast(self, broadcastLightningWeaponEnchantmentSplash);
    
    [...]
    
    const int LIGHTNING_WEAPON_ENCHANTMENT_SPLASH_RANGE = 160;
    
    func void broadcastLightningWeaponEnchantmentSplash(var C_NPC me, var C_NPC caster) {
           // lustige Prüfungen, damit sich Nahkampf-Flächenschaden auch einigermaßen nativ anfühlt (Gegner sollten im Kampf sein etc.)
    	if(Npc_GetDistToNpc(me, caster) <= LIGHTNING_WEAPON_ENCHANTMENT_SPLASH_RANGE) 
    	&& (Npc_IsInState(me, ZS_Attack) || Npc_IsInState(me, ZS_MM_Attack)) // sollte im Kampf sein
    	&& (!me.aivar[AIV_PARTYMEMBER]) { // sollte dazu kein Partymember sein wie z.B. beschworenes Skelett
    		var int lightningWeaponEnchantmentSplashDamage;
    		lightningWeaponEnchantmentSplashDamage = lustigeSchadenKalkulierungsfunktionFuerDenZauber();
                    // hier kann man dem Gegner dann den Schaden hinzufügen
    	};
    };

    2) Flächenzauber über die Partikeleffekte

    Jetzt haben die Piranhas das Ganze ja auch irgendwie ohne Brotkasten hingekriegt. Nämlich bei den Zaubern (Eiswelle, Todeswelle, ...). Für Zauber kann man sich diese Funktionalitäten auf jeden Fall zu nutze machen. Dafür müssen dann passende Partikeleffekte bereitgestellt werden, die entsprechende Parameter gesetzt haben müssen.

    Hier ein beispielhafter Flächenzauber.

    VisualFXInst.d
    Code:
    INSTANCE spellFX_ArcaneExplosion (CFx_Base_Proto)
    {
        visname_S               = "MFX_ENERGYBALL_INIT";
        emtrjmode_s             = "FIXED";
        emTrjOriginNode         = "ZS_RIGHTHAND";
        emtrjloopmode_s         = "NONE";
        emtrjeasefunc_s         = "LINEAR";
        };
        INSTANCE spellFX_ArcaneExplosion_KEY_CAST (C_ParticleFXEmitKey)
        {
            visname_S           = "MFX_ENERGYBALL_INIT";
            emCreateFXID        = "spellFX_ArcaneExplosion_CAST";
            pfx_ppsIsLoopingChg = 1;
        };
    INSTANCE spellFX_ArcaneExplosion_CAST (CFx_Base_Proto)
    {
        visname_S               = "MFX_ArcaneExplosion_Circle";
        emTrjOriginNode         = "Bip01";
        emFXCreate_S            = "spellFX_ArcaneExplosion_Sphere";
        emFXCreatedOwnTrj       = 1;
        emFXCollDyn_S           = "spellFX_ArcaneExplosion_COLLIDEDYNFX";
    
        emActionCollDyn_S       = "CREATEONCE"; // WICHTIG FÜR FLÄCHENZAUBER
        emFXCollDynPerc_S       = "spellFX_ArcaneExplosion_SENDPERCEPTION"; // WICHTIG FÜR FLÄCHENZAUBER
        emFXCollDynAlign_S      = "COLLISIONNORMAL"; // WICHTIG FÜR FLÄCHENZAUBER
        emCheckCollision        = 1; // WICHTIG FÜR FLÄCHENZAUBER
        
        emtrjmode_s 		= "FIXED";
    	emtrjoriginnode		= "="; // Ausgangspunkt für Pfx (hier: Mitte des Helden)
    	lightpresetname		= "AURA"; // Licht-Preset (leuchtet lustig)
    	sfxid				= "MFX_ArcaneExplosion_Cast"; // Sound
    	sfxisambient		= 1;
    	emfxlifespan        = 1.5; // Zauber hält 1.5 Sekunden
    };
    INSTANCE spellFX_ArcaneExplosion_COLLIDEDYNFX (CFx_Base_Proto)
    {
        visname_S               = "MFX_ARCANEEXPLOSION_TARGET";
        sfxid                   = "ARCANE_MISSILES_1";
    };
    INSTANCE spellFX_ArcaneExplosion_SENDPERCEPTION (CFx_Base_Proto)  // Send perception
    {
        visname_S               = "";
        sendAssessMagic         = 1;
    };
    PFXInstMagic.d
    Code:
    INSTANCE MFX_ArcaneExplosion_Circle (C_PARTICLEFX)
    {
         ppsvalue = 200;
         ppsscalekeys_s = "3 4 5 6 7 7 8 8"; // Wird mit der Zeit größer
         ppsissmooth = 1;
         ppsfps = 14; // Wie schnell wird es mit der Zeit größer?
         shptype_s = "CIRCLE"; // Hier ist entweder CIRCLE oder SPHERE interessant
         shpfor_s = "WORLD";
         shpoffsetvec_s = "0 0 0";
         shpdistribtype_s = "BOX";
         shpdim_s = "120"; // Wirkungsradius
         shpscalekeys_s = "1 2 3 4 5 6 6 6"; // Wird mit der Zeit größer #2
         shpscaleissmooth = 1;
         shpscalefps = 3; // Wie schnell wird es mit der Zeit größer? #2
         dirmode_s = "RAND";
         dirfor_s = "object";
         diranglehead = 90;
         dirangleheadvar = 45;
         dirangleelev = 90;
         dirangleelevvar = 45;
         velavg = 0.150000001;
         lsppartavg = 500; // Wie viele Millisekunden überlebt ein Partikel (fix)
         lsppartvar = 200; // Wie viele Millisekunden überlebt ein Partikel (variabel, wird random auf fix gerechnet)
         flygravity_s = "0 0.00003 0"; // Partikel dürfen über die Zeit etwas nach oben fliegen
         visname_s = "Kopfball2.TGA";
         visorientation_s = "VELO";
         vistexisquadpoly = 1;
         vistexanifps = 30;
         vistexaniislooping = 2;
         vistexcolorstart_s = "102 0 204";
         vistexcolorend_s = "30 0 60";
         vissizestart_s = "8 8"; // Größe der Textur beim Start des Effekts
         vissizeendscale = 15; // Größe der Textur beim Ende des Effekts
         visalphafunc_s = "ADD";
         visalphastart = 255;
         trlfadespeed = 0.00999999978;
         trltexture_s = "Kopfball2.TGA";
    };
    Das wäre jetzt ein Beispiel für einen "Wellen-Zauber". Natürlich kriegt man genauso gut ein größeres Projektil damit hin, was durch Gegner hindurchfliegt und jedem Gegner Schaden hinzufügt. Wichtig dabei sind auf jeden Fall die folgenden Parameter im SpellFX_XYZ:

    Code:
    emactioncollstat_s = "COLLIDE CREATE";
    emActionCollDyn_S       = "CREATEONCE"; // Erreiche alle
    emFXCollDynAlign_S      = "COLLISIONNORMAL";
    Ein ABER gibt es an dieser Stelle: Flächenzauber haben leider das Problem, dass sie Gegner bei einer einzigen Anwendung häufiger treffen können, wenn zum Beispiel der Effekt etwas länger ist (wie zum Beispiel der Todeswelleneffekt). Hier habe ich eine etwas hackige Lösung bei mir eingebaut, das Problem löst. Dabei setze ich den Initialschaden des Zaubers auf 0 und füge den Schaden erst in der B_AssessMagic() zu. Dann setze ich den Wert einer neuen AIVAR. Falls dieser gesetzt ist, füge ich keinen Schaden mehr hinzu. Der AIVAR wird dann nach einer gewissen Zeit resetted. Mit FrameFunctions aus LeGo geht das ganz gut.
    Zusätzlich sind in dem Code auch noch ein paar Tweeks, damit das gegnerische Verhalten auch vernünftig ist/bleibt.

    B_AssessMagic.d

    Code:
    [...]
      	if (Npc_GetLastHitSpellID(self) == SPL_ArcaneExplosion) {
      		if(!self.aivar[AIV_WasHitByAOESpell]) { // Hier die erwähnte Klausel, damit nur einmalig Schaden zugefügt wird
      			self.aivar[AIV_WasHitByAOESpell] = true;
    
    			if(mayIAttackHim(self, other)) { // Prüfung, ob Gegner zum Beispiel eingefroren
    				if (self.guild < GIL_SEPERATOR_HUM) { // Bin ich ein Mensch?
    					Npc_ClearAIQueue(self);
    					B_ClearPerceptions(self);   // Sonst reagiert der NPC manchmal nicht!
    
    					// Das ist wichtig, falls self noch nicht im Kampfmodus (hostile) ist
    					Npc_SetTarget(self, other);
    					B_AssessDamage();
    				};
    
    				// Und das ist wichtig, damit self nicht plötzlich aufhört mit dem Kämpfen
    				Npc_SetTarget(self, other);
    				Npc_SetTempAttitude(self, ATT_HOSTILE); // Falls nicht schon Gilden-Attitüde hostile ist
    			};
    
    	        // Hier füge ich den Schaden zu
      		};
      		
            return;
        };

    "Aber was ist denn jetzt besser von den beiden Varianten?"

    Broadcasts sind super, wenn man konkrete Abfragen für zum Beispiel Distanz machen möchte. So kann man implementieren, dass eine Flammenwelle von nahem mehr Schaden anrichtet, als wenn ein Gegner am äußersten Rand der Welle ist.
    Vorteil an der Effekt-Geschichte ist ganz klar, dass man sich keine großen Sorgen um das Treffen machen muss. Das regelt dann der Effekt selber. Es fühlt sich häufig schöner an, wenn der Schaden genau DANN zugefügt wird, wenn der Effekt visuell auch wirklich trifft. Das ist bei broadcasts meistens nur bedingt machbar.


    Ich hoffe, das hilft dir erstmal weiter Das Ganze war natürlich nicht ganz uneigennützig, ich habe großes Interesse daran in "Das Wappen" auf tolle Magie zurückzugreifen

  3. Beiträge anzeigen #3 Zitieren
    Ritter Avatar von aebo
    Registriert seit
    Oct 2008
    Beiträge
    1.278
     
    aebo ist offline
    Zitat Zitat von Draxes Beitrag anzeigen
    Eins meiner absoluten Top-Themen, da ich mich viel mit neuen Zaubern beschäftigt habe und dort auch der ein oder andere AOE Zauber am Start ist.
    Jetzt gibt es natürlich verschiedene Möglichkeiten Flächenschaden umzusetzen, je nachdem, was dein konkretes Ziel ist. Deshalb hole ich einfach mal etwas aus.

    1) Broadcasts

    Broadcasts sind klasse. Du rufst damit eine Funktion aus, die für alle Npcs (meistens mit Einschränkung "in der KI-Glocke") aufgerufen wird. Dort kannst du dann lustig Dinge prüfen wie "stehe ich nah genug am hero dran, um Flächenschaden zu kassieren"?
    Soeinen Broadcast kann man dann zum Beispiel für Nahkampf/Fernkampf-Flächenschaden in einem damageHook (falls du sowas hast) oder auch in der B_AssessDamage() aufrufen.

    Die Broadcasts selber sind von Sektenspinner implementiert worden.
    https://forum.worldofplayers.de/foru...1#post17232705

    Einsatzweise:
    Code:
    // Aufruf zum Beispiel in B_AssessDamage()
    broadcast(self, broadcastLightningWeaponEnchantmentSplash);
    
    [...]
    
    const int LIGHTNING_WEAPON_ENCHANTMENT_SPLASH_RANGE = 160;
    
    func void broadcastLightningWeaponEnchantmentSplash(var C_NPC me, var C_NPC caster) {
           // lustige Prüfungen, damit sich Nahkampf-Flächenschaden auch einigermaßen nativ anfühlt (Gegner sollten im Kampf sein etc.)
    	if(Npc_GetDistToNpc(me, caster) <= LIGHTNING_WEAPON_ENCHANTMENT_SPLASH_RANGE) 
    	&& (Npc_IsInState(me, ZS_Attack) || Npc_IsInState(me, ZS_MM_Attack)) // sollte im Kampf sein
    	&& (!me.aivar[AIV_PARTYMEMBER]) { // sollte dazu kein Partymember sein wie z.B. beschworenes Skelett
    		var int lightningWeaponEnchantmentSplashDamage;
    		lightningWeaponEnchantmentSplashDamage = lustigeSchadenKalkulierungsfunktionFuerDenZauber();
                    // hier kann man dem Gegner dann den Schaden hinzufügen
    	};
    };

    2) Flächenzauber über die Partikeleffekte

    Jetzt haben die Piranhas das Ganze ja auch irgendwie ohne Brotkasten hingekriegt. Nämlich bei den Zaubern (Eiswelle, Todeswelle, ...). Für Zauber kann man sich diese Funktionalitäten auf jeden Fall zu nutze machen. Dafür müssen dann passende Partikeleffekte bereitgestellt werden, die entsprechende Parameter gesetzt haben müssen.

    Hier ein beispielhafter Flächenzauber.

    VisualFXInst.d
    Code:
    INSTANCE spellFX_ArcaneExplosion (CFx_Base_Proto)
    {
        visname_S               = "MFX_ENERGYBALL_INIT";
        emtrjmode_s             = "FIXED";
        emTrjOriginNode         = "ZS_RIGHTHAND";
        emtrjloopmode_s         = "NONE";
        emtrjeasefunc_s         = "LINEAR";
        };
        INSTANCE spellFX_ArcaneExplosion_KEY_CAST (C_ParticleFXEmitKey)
        {
            visname_S           = "MFX_ENERGYBALL_INIT";
            emCreateFXID        = "spellFX_ArcaneExplosion_CAST";
            pfx_ppsIsLoopingChg = 1;
        };
    INSTANCE spellFX_ArcaneExplosion_CAST (CFx_Base_Proto)
    {
        visname_S               = "MFX_ArcaneExplosion_Circle";
        emTrjOriginNode         = "Bip01";
        emFXCreate_S            = "spellFX_ArcaneExplosion_Sphere";
        emFXCreatedOwnTrj       = 1;
        emFXCollDyn_S           = "spellFX_ArcaneExplosion_COLLIDEDYNFX";
    
        emActionCollDyn_S       = "CREATEONCE"; // WICHTIG FÜR FLÄCHENZAUBER
        emFXCollDynPerc_S       = "spellFX_ArcaneExplosion_SENDPERCEPTION"; // WICHTIG FÜR FLÄCHENZAUBER
        emFXCollDynAlign_S      = "COLLISIONNORMAL"; // WICHTIG FÜR FLÄCHENZAUBER
        emCheckCollision        = 1; // WICHTIG FÜR FLÄCHENZAUBER
        
        emtrjmode_s 		= "FIXED";
    	emtrjoriginnode		= "="; // Ausgangspunkt für Pfx (hier: Mitte des Helden)
    	lightpresetname		= "AURA"; // Licht-Preset (leuchtet lustig)
    	sfxid				= "MFX_ArcaneExplosion_Cast"; // Sound
    	sfxisambient		= 1;
    	emfxlifespan        = 1.5; // Zauber hält 1.5 Sekunden
    };
    INSTANCE spellFX_ArcaneExplosion_COLLIDEDYNFX (CFx_Base_Proto)
    {
        visname_S               = "MFX_ARCANEEXPLOSION_TARGET";
        sfxid                   = "ARCANE_MISSILES_1";
    };
    INSTANCE spellFX_ArcaneExplosion_SENDPERCEPTION (CFx_Base_Proto)  // Send perception
    {
        visname_S               = "";
        sendAssessMagic         = 1;
    };
    PFXInstMagic.d
    Code:
    INSTANCE MFX_ArcaneExplosion_Circle (C_PARTICLEFX)
    {
         ppsvalue = 200;
         ppsscalekeys_s = "3 4 5 6 7 7 8 8"; // Wird mit der Zeit größer
         ppsissmooth = 1;
         ppsfps = 14; // Wie schnell wird es mit der Zeit größer?
         shptype_s = "CIRCLE"; // Hier ist entweder CIRCLE oder SPHERE interessant
         shpfor_s = "WORLD";
         shpoffsetvec_s = "0 0 0";
         shpdistribtype_s = "BOX";
         shpdim_s = "120"; // Wirkungsradius
         shpscalekeys_s = "1 2 3 4 5 6 6 6"; // Wird mit der Zeit größer #2
         shpscaleissmooth = 1;
         shpscalefps = 3; // Wie schnell wird es mit der Zeit größer? #2
         dirmode_s = "RAND";
         dirfor_s = "object";
         diranglehead = 90;
         dirangleheadvar = 45;
         dirangleelev = 90;
         dirangleelevvar = 45;
         velavg = 0.150000001;
         lsppartavg = 500; // Wie viele Millisekunden überlebt ein Partikel (fix)
         lsppartvar = 200; // Wie viele Millisekunden überlebt ein Partikel (variabel, wird random auf fix gerechnet)
         flygravity_s = "0 0.00003 0"; // Partikel dürfen über die Zeit etwas nach oben fliegen
         visname_s = "Kopfball2.TGA";
         visorientation_s = "VELO";
         vistexisquadpoly = 1;
         vistexanifps = 30;
         vistexaniislooping = 2;
         vistexcolorstart_s = "102 0 204";
         vistexcolorend_s = "30 0 60";
         vissizestart_s = "8 8"; // Größe der Textur beim Start des Effekts
         vissizeendscale = 15; // Größe der Textur beim Ende des Effekts
         visalphafunc_s = "ADD";
         visalphastart = 255;
         trlfadespeed = 0.00999999978;
         trltexture_s = "Kopfball2.TGA";
    };
    Das wäre jetzt ein Beispiel für einen "Wellen-Zauber". Natürlich kriegt man genauso gut ein größeres Projektil damit hin, was durch Gegner hindurchfliegt und jedem Gegner Schaden hinzufügt. Wichtig dabei sind auf jeden Fall die folgenden Parameter im SpellFX_XYZ:

    Code:
    emactioncollstat_s = "COLLIDE CREATE";
    emActionCollDyn_S       = "CREATEONCE"; // Erreiche alle
    emFXCollDynAlign_S      = "COLLISIONNORMAL";
    Ein ABER gibt es an dieser Stelle: Flächenzauber haben leider das Problem, dass sie Gegner bei einer einzigen Anwendung häufiger treffen können, wenn zum Beispiel der Effekt etwas länger ist (wie zum Beispiel der Todeswelleneffekt). Hier habe ich eine etwas hackige Lösung bei mir eingebaut, das Problem löst. Dabei setze ich den Initialschaden des Zaubers auf 0 und füge den Schaden erst in der B_AssessMagic() zu. Dann setze ich den Wert einer neuen AIVAR. Falls dieser gesetzt ist, füge ich keinen Schaden mehr hinzu. Der AIVAR wird dann nach einer gewissen Zeit resetted. Mit FrameFunctions aus LeGo geht das ganz gut.
    Zusätzlich sind in dem Code auch noch ein paar Tweeks, damit das gegnerische Verhalten auch vernünftig ist/bleibt.

    B_AssessMagic.d

    Code:
    [...]
      	if (Npc_GetLastHitSpellID(self) == SPL_ArcaneExplosion) {
      		if(!self.aivar[AIV_WasHitByAOESpell]) { // Hier die erwähnte Klausel, damit nur einmalig Schaden zugefügt wird
      			self.aivar[AIV_WasHitByAOESpell] = true;
    
    			if(mayIAttackHim(self, other)) { // Prüfung, ob Gegner zum Beispiel eingefroren
    				if (self.guild < GIL_SEPERATOR_HUM) { // Bin ich ein Mensch?
    					Npc_ClearAIQueue(self);
    					B_ClearPerceptions(self);   // Sonst reagiert der NPC manchmal nicht!
    
    					// Das ist wichtig, falls self noch nicht im Kampfmodus (hostile) ist
    					Npc_SetTarget(self, other);
    					B_AssessDamage();
    				};
    
    				// Und das ist wichtig, damit self nicht plötzlich aufhört mit dem Kämpfen
    				Npc_SetTarget(self, other);
    				Npc_SetTempAttitude(self, ATT_HOSTILE); // Falls nicht schon Gilden-Attitüde hostile ist
    			};
    
    	        // Hier füge ich den Schaden zu
      		};
      		
            return;
        };

    "Aber was ist denn jetzt besser von den beiden Varianten?"

    Broadcasts sind super, wenn man konkrete Abfragen für zum Beispiel Distanz machen möchte. So kann man implementieren, dass eine Flammenwelle von nahem mehr Schaden anrichtet, als wenn ein Gegner am äußersten Rand der Welle ist.
    Vorteil an der Effekt-Geschichte ist ganz klar, dass man sich keine großen Sorgen um das Treffen machen muss. Das regelt dann der Effekt selber. Es fühlt sich häufig schöner an, wenn der Schaden genau DANN zugefügt wird, wenn der Effekt visuell auch wirklich trifft. Das ist bei broadcasts meistens nur bedingt machbar.


    Ich hoffe, das hilft dir erstmal weiter Das Ganze war natürlich nicht ganz uneigennützig, ich habe großes Interesse daran in "Das Wappen" auf tolle Magie zurückzugreifen
    Hi Draxes,

    danke für die von dir zur Verfügung gestellten Informationen. Ich werde mir das genauer angucken
    Das Wappen
    -Eine fantastische Spielwelt erwartet dich-
    -bis zu 100 Stunden Spielzeit-

  4. Beiträge anzeigen #4 Zitieren
    Ritter Avatar von aebo
    Registriert seit
    Oct 2008
    Beiträge
    1.278
     
    aebo ist offline
    So, habe mich jetzt mal mit deinem Post auseinander gesetzt.
    Problem für mich:
    Der Gegner wird überall in Range getroffen (auch hinter dem Helden). Ich würde gerne im Nahkampfbereich abfragen wollen ob Npc XY von meiner Waffe getroffen wurde.
    Ich glaube man müsste hierzu abfragen ob die Waffe die in der ZS_RightHand getragen wird mit dem NPC kollidiert. Gibt es dafür ne Lösung?
    Das Wappen
    -Eine fantastische Spielwelt erwartet dich-
    -bis zu 100 Stunden Spielzeit-

  5. Beiträge anzeigen #5 Zitieren
    Knight Avatar von Draxes
    Registriert seit
    Aug 2007
    Ort
    Mainz
    Beiträge
    1.920
     
    Draxes ist offline
    Zitat Zitat von aebo Beitrag anzeigen
    So, habe mich jetzt mal mit deinem Post auseinander gesetzt.
    Problem für mich:
    Der Gegner wird überall in Range getroffen (auch hinter dem Helden). Ich würde gerne im Nahkampfbereich abfragen wollen ob Npc XY von meiner Waffe getroffen wurde.
    Ich glaube man müsste hierzu abfragen ob die Waffe die in der ZS_RightHand getragen wird mit dem NPC kollidiert. Gibt es dafür ne Lösung?

    Argh, ich habe vergessen dir zurückzuschreiben Das wird jetzt nachgeholt.

    So spontan fällt mir da keine konkrete Lösung ein. Das wäre auch ein komplizierter Ansatz. Aber ich habe Alternativvorschläge, die dir vermutlich reichen könnten.

    1) Du prüfst in dem Broadcast nicht die Distanz vom Helden zu potentiellen Gegnern, die du triffst, sondern von dem Gegner, den du mit deinem "normalen" Angriff getroffen hast zu den potentiellen Gegnern. Da dieser auf jeden Fall getroffene Gegner vor dir steht sollten mit der richtigen Distanz keine Gegner hinter dir getroffen werden.

    2) Du prüfst mit
    Code:
    Npc_CanSeeNpc(hero, me)
    ob du den Gegner siehst bzw. ob der Gegner dich sieht.

  6. Beiträge anzeigen #6 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.246
     
    Milky-Way ist offline
    Zitat Zitat von aebo Beitrag anzeigen
    So, habe mich jetzt mal mit deinem Post auseinander gesetzt.
    Problem für mich:
    Der Gegner wird überall in Range getroffen (auch hinter dem Helden). Ich würde gerne im Nahkampfbereich abfragen wollen ob Npc XY von meiner Waffe getroffen wurde.
    Ich glaube man müsste hierzu abfragen ob die Waffe die in der ZS_RightHand getragen wird mit dem NPC kollidiert. Gibt es dafür ne Lösung?
    Inwiefern ist es dann noch Flächenschaden? Wie soll es sich von herkömmlichem Schaden unterscheiden?

  7. Beiträge anzeigen #7 Zitieren
    Serima Avatar von Fisk2033
    Registriert seit
    Dec 2010
    Ort
    Dresden
    Beiträge
    5.803
     
    Fisk2033 ist offline
    Zitat Zitat von Milky-Way Beitrag anzeigen
    Inwiefern ist es dann noch Flächenschaden? Wie soll es sich von herkömmlichem Schaden unterscheiden?
    Ich glaube fast hier handelt es sich um eine Verwechslung? Ich denke Aebo möchte gern Schaden wie in G3 (mit dem Schwert nach vorn schlagen und ggf. 2/mehrere Gegner treffen) und nicht Flächenschaden im Sinne von Zaubern.?

  8. Beiträge anzeigen #8 Zitieren
    Ritter Avatar von aebo
    Registriert seit
    Oct 2008
    Beiträge
    1.278
     
    aebo ist offline
    Zitat Zitat von Fisk2033 Beitrag anzeigen
    Ich glaube fast hier handelt es sich um eine Verwechslung? Ich denke Aebo möchte gern Schaden wie in G3 (mit dem Schwert nach vorn schlagen und ggf. 2/mehrere Gegner treffen) und nicht Flächenschaden im Sinne von Zaubern.?
    Du triffst den Nagel auf den Kopf

    Ich befürchte aber, dass es nur mit diesem Trick (einen "Zauber") gehen wird, dieses umzusetzten. Bin aber auch noch nicht so 100% von der Lösung überzeugt.
    Ich habe mal einen Post hier von Thanduriel aus dem Jahre 2014 gefunden. Hier der Post

    Code:
    For a clean solution you need to hook melee attacks. This functions could work(just guessed from their names):
    
    oCNpc::EV_AttackForward(oCMsgAttack *) 0x0074F400
    oCNpc::EV_AttackLeft(oCMsgAttack *) 0x00750160
    oCNpc::EV_AttackRight(oCMsgAttack *) 0x00750D00
    oCNpc::EV_AttackRun(oCMsgAttack *) 0x007517D0
    oCNpc::EV_AttackFinish(oCMsgAttack *) 0x00751AF0
    In the hook you can use broadcasts to get other near targets. On those you can either try out some enginefunctions or build your own attack with rangecalculations, dmg and animations.
    Leider weiß ich damit nicht wirklich viel anzufangen.
    Ich habe bereits ja einen Damage-Hook eingerichtet, weil ich ja sowieso eine eigene Schadensberechnung inplementiert habe.
    Das Wappen
    -Eine fantastische Spielwelt erwartet dich-
    -bis zu 100 Stunden Spielzeit-

  9. Beiträge anzeigen #9 Zitieren
    Knight
    Registriert seit
    Aug 2009
    Ort
    Hessen
    Beiträge
    1.487
     
    Cryp18Struct ist offline
    Wenn du schon einen damage hook hast, könntest du dort einen broadcast starten um weitere Ziele zu ermitteln. Wie schon vorgeschlagen mit Abstand eines NPCs zu dem NPC welcher geschädigt wurde. Und dann evt. auch Sichtcheck vom hero aus:
    Lustige skizze:
    [Bild: attachment.php?s=37c5b69bb768df5fcb015812b6e4ca79&attachmentid=47397&d=1540467753&thumb=1]
    Wenn du Wolf 1 mit einem Schwert schlägst, könntest du dann feststellen das Wolf 2 nah genug ist das er auch Schaden abbekommen soll.
    Du kannst zum testen ja erst mal mit B_MagicHurtNpc Schaden verteilen und dann Schauen ob/wie du das noch verschönern kannst.

  10. Beiträge anzeigen #10 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.246
     
    Milky-Way ist offline
    Oder pfx an jede Waffe hängen und dann schaffen darüber verteilen

  11. Beiträge anzeigen #11 Zitieren
    Ritter Avatar von aebo
    Registriert seit
    Oct 2008
    Beiträge
    1.278
     
    aebo ist offline
    Zitat Zitat von Cryp18Struct Beitrag anzeigen
    Wenn du schon einen damage hook hast, könntest du dort einen broadcast starten um weitere Ziele zu ermitteln. Wie schon vorgeschlagen mit Abstand eines NPCs zu dem NPC welcher geschädigt wurde. Und dann evt. auch Sichtcheck vom hero aus:
    Lustige skizze:
    [Bild: attachment.php?s=37c5b69bb768df5fcb015812b6e4ca79&attachmentid=47397&d=1540467753&thumb=1]
    Wenn du Wolf 1 mit einem Schwert schlägst, könntest du dann feststellen das Wolf 2 nah genug ist das er auch Schaden abbekommen soll.
    Du kannst zum testen ja erst mal mit B_MagicHurtNpc Schaden verteilen und dann Schauen ob/wie du das noch verschönern kannst.
    Ja, das wäre eine Option. Aber relativ aufwändig. Wüsste da gar nicht wo ich anfangen sollte :-D


    Zitat Zitat von Milky-Way Beitrag anzeigen
    Oder pfx an jede Waffe hängen und dann schaffen darüber verteilen
    Das klingt doch sehr gut. Pfx kann man ja auch dann für den Spieler nicht sichtbar machen. Wie könnte das aussehen?
    Hast du nen Vorschlag?
    Das Wappen
    -Eine fantastische Spielwelt erwartet dich-
    -bis zu 100 Stunden Spielzeit-

  12. Beiträge anzeigen #12 Zitieren
    Knight
    Registriert seit
    Aug 2009
    Ort
    Hessen
    Beiträge
    1.487
     
    Cryp18Struct ist offline
    Ich versuch jetzt doch dir die broadcast Lösung aufzuschwatzen, weil man da doch recht schnell ein funktionierendes Grundgerüst bauen kann.
    Im damage hook(https://forum.worldofplayers.de/foru...1#post19002341)
    ganz unten:
    Code:
    	if(dmg > 0){
    		if(Hlp_GetInstanceID(attackerNpc) == Hlp_GetInstanceID(hero)){
    			if(Npc_HasReadiedMeleeWeapon(attackerNpc)){ // wäre besser im oSDamageDescriptor nachzuschauen wie Schaden zugefügt wurde
    				broadcastEx(victimNpc, doAOEDamage, 1, 0, 0); // exclude caster:1, includeDead:0, includeShrinked:0
    			};
    		};
    	};
    	
    	return dmg;
    }; // Ende von DMG_OnDmg()
    Und dann die Funktion die von broadcast für alle NPCs aufgerufen wird:
    Code:
    func void doAOEDamage(var c_npc me, var c_npc caster){
    	if(Npc_GetDistToNpc(me, caster) > 150){return;};
    	if(Npc_GetDistToNpc(me, hero) > 250){return;}; // Distanzwerte jetzt nur PI * Daumen, man könnte auch Waffenreichweite berücksichtigen
    	if(!Npc_CanSeeNpc(hero, me)){return;};
    	
    	var int dam;
    	dam = 1000; // Schadenswert kann auch beliebig anders berechnet werden, Waffenschaden - Rüstungsschutz oder so, Grundschaden könnte man auch im damage hook vorbereiten und über globale variable hierher reichen
    	dam = dam - me.protection[DAM_INDEX_MAGIC];
    	if(dam < 1){return;};
    	
    	MEM_PushInstParam(hero);
    	MEM_PushInstParam(me);
    	MEM_PushIntParam(dam);
    	MEM_Call(B_MagicHurtNPC);
    };

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
Impressum | Link Us | intern
World of Gothic © by World of Gothic Team
Gothic, Gothic 2 & Gothic 3 are © by Piranha Bytes & Egmont Interactive & JoWooD Productions AG, all rights reserved worldwide