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 6 von 6
  1. Homepage besuchen Beiträge anzeigen #1 Zitieren
    Team Velen
    Registriert seit
    Aug 2015
    Beiträge
    952
     
    Bloodfly91 ist offline

    NPC soll alle Opfer in der Nähe plündern

    Ich habe für unsere Jäger ein Skript geschrieben, das sie die getöteten Viecher plündern lässt. Das funktioniert auch, allerdings plündern sie immer nur eins und ignorieren die anderen. Nun habe ich schon selbst ein bisschen herumprobiert und auch schon im Forum gesucht, aber nichts gefunden, das mir bei meinem Problem wirklich weiterhilft.
    Das Skript sieht so aus:

    Code:
    // *************************************
    // ZS_RansackDeadMonster
    // --------------
    // wird am Ende von ZS_Attack aufgerufen
    // *************************************
    
    func void ZS_RansackDeadMonster ()
    {
        Perception_Set_Normal();
    };
        
    func int ZS_RansackDeadMonster_Loop ()
    {
        AI_StandUp (self);
        
        // ------ zum Body gehen ------
        AI_GotoNpc (self, other);
        
        // ------ zum Body drehen ------
        B_TurnToNpc (self, other);
        
        // ------ Durchsuchen-Ani ------
        AI_PlayAni (self, "T_PLUNDER");
        
        B_TransferInventory(other, self);
        
        return LOOP_END;
    };
    
    func void ZS_RansackDeadMonster_End ()
    {    
        // ------ NSC heilt sich ------
        if (self.attribute[ATR_HITPOINTS] < (self.attribute[ATR_HITPOINTS_MAX]/2))
        {
            AI_StartState    (self, ZS_HealSelf, 0, "");
            return;
        };
    };
    Und wird in der ZS_Attack_End aufgerufen:

    Code:
    if (C_NpcIsDown(other))
        && (other.aivar[AIV_DEADMONSTERRANSACKED] == FALSE)
        && (Npc_GetDistToNpc(self, other) < PERC_DIST_INTERMEDIAT)
        && (other.aivar[AIV_MM_REAL_ID] != ID_GOBBO_BLACK)
        && (other.aivar[AIV_MM_REAL_ID] != ID_GOBBO_GREEN)
        && (other.aivar[AIV_MM_REAL_ID] != ID_GOBBO_SKELETON)
        && (other.aivar[AIV_MM_REAL_ID] != ID_SKELETON)
        && (other.aivar[AIV_MM_REAL_ID] != ID_DRAGONSNAPPER)
        && (other.aivar[AIV_MM_REAL_ID] != ID_MINECRAWLER)
        && (other.aivar[AIV_MM_REAL_ID] != ID_MINECRAWLERWARRIOR)
        && (other.aivar[AIV_MM_REAL_ID] != ID_SHADOWBEAST)
        && (other.aivar[AIV_MM_REAL_ID] != ID_STONEGOLEM)
        && (other.aivar[AIV_MM_REAL_ID] != ID_SWAMPSHARK)
        && (other.aivar[AIV_MM_REAL_ID] != ID_TROLL_BLACK)
        && (other.aivar[AIV_MM_REAL_ID] != ID_DEMON)
        && (other.aivar[AIV_MM_REAL_ID] != ID_DEMON_LORD)
        && (other.aivar[AIV_MM_REAL_ID] != ID_SHEEP)
        {
            if (other.guild > GIL_SEPERATOR_HUM) && (self.guild == GIL_DJG)
            {
                other.aivar[AIV_DEADMONSTERRANSACKED] = TRUE;
                    
                AI_StartState (self, ZS_RansackDeadMonster, 0, "");
                return;
            };
        };

  2. Beiträge anzeigen #2 Zitieren
    Knight
    Registriert seit
    Aug 2009
    Ort
    Hessen
    Beiträge
    1.487
     
    Cryp18Struct ist offline
    Dein Skriptablauf ist zurzeit in etwa:
    Wenn Kampf vorbei:
    > Ist der umgehauene Gegner von der Art welche ich plündern möchte? und noch nicht fürs plündern markiert?
    -->Falls Ja: markiere diesen Gegner als geplündert und starte Zustand ZS_RansackDeadMonster

    Im Zustand ZS_RansackDeadMonster:
    gehe zu other, plündere ihn und beende die Schleife(Verlasse den Zustand und gehe eventuell in ZS_HealSelf)


    Deiner Beschreibung nach möchtest du so etwas:
    Wenn Kampf vorbei: starte Zustand ZS_RansackDeadMonster

    Im Zustand ZS_RansackDeadMonster: Schaue nach ob in der nähe mindestens ein umgehauener Gegner von der Art herumliegt welche ich plündern möchte und noch nicht fürs plündern markiert ist.
    ->Falls ja: markiere und plündere einen. Wiederhole das ganze(ZS_RansackDeadMonster neu starten).
    ->Falls nein: Verlasse den Zustand und gehe eventuell in ZS_HealSelf.

  3. Homepage besuchen Beiträge anzeigen #3 Zitieren
    Team Velen
    Registriert seit
    Aug 2015
    Beiträge
    952
     
    Bloodfly91 ist offline
    Zitat Zitat von Cryp18Struct Beitrag anzeigen
    Dein Skriptablauf ist zurzeit in etwa:
    Wenn Kampf vorbei:
    > Ist der umgehauene Gegner von der Art welche ich plündern möchte? und noch nicht fürs plündern markiert?
    -->Falls Ja: markiere diesen Gegner als geplündert und starte Zustand ZS_RansackDeadMonster

    Im Zustand ZS_RansackDeadMonster:
    gehe zu other, plündere ihn und beende die Schleife(Verlasse den Zustand und gehe eventuell in ZS_HealSelf)


    Deiner Beschreibung nach möchtest du so etwas:
    Wenn Kampf vorbei: starte Zustand ZS_RansackDeadMonster

    Im Zustand ZS_RansackDeadMonster: Schaue nach ob in der nähe mindestens ein umgehauener Gegner von der Art herumliegt welche ich plündern möchte und noch nicht fürs plündern markiert ist.
    ->Falls ja: markiere und plündere einen. Wiederhole das ganze(ZS_RansackDeadMonster neu starten).
    ->Falls nein: Verlasse den Zustand und gehe eventuell in ZS_HealSelf.
    So ist es. Eigentlich müsste ich im ZS ja nur abfragen, ob in der Nähe noch mehr Gegner liegen und dann den ZS so oft wiederholen, bis alle geplündert sind. Nur wie mache ich das?

  4. Beiträge anzeigen #4 Zitieren
    Knight
    Registriert seit
    Aug 2009
    Ort
    Hessen
    Beiträge
    1.487
     
    Cryp18Struct ist offline
    Code für alle npc in der nähe des Spielers ausführen geht bequem mit dieser Funktion von Sektenspinner:
    https://forum.worldofplayers.de/foru...1#post17232705

    Oder du iterierst halt direkt durch die active vob List(kannst du dir auch in Sektenspinners Script abschauen)

    Code:
    if (sphereOnly) {
            /* to speed things up (and do the filtering)
             * we only search the (small) active Vob List */
            var int i;    i    = 0;
            var int loop; loop = MEM_StackPos.position;
            
            if (i < MEM_World.activeVobList_numInArray) {
                var int vob;
                vob = MEM_ReadIntArray(MEM_World.activeVobList_array, i);
                
                if (Hlp_Is_oCNpc(vob)) {
                    var C_NPC npc;
                    npc = MEM_PtrToInst(vob);
                    // mach was
                };
                
                i += 1;
                MEM_StackPos.position = loop;
            };
        }

  5. Beiträge anzeigen #5 Zitieren
    Knight Avatar von GenerationLost
    Registriert seit
    Apr 2009
    Ort
    Whereabouts Unknown
    Beiträge
    1.774
     
    GenerationLost ist offline
    Kann dir nicht sagen, ob es funktioniert, da ich gerade keine Möglichkeit zum Testen habe, aber ich würde es so versuchen:

    Code:
    // *************************************
    // ZS_RansackDeadMonster
    // --------------
    // wird am Ende von ZS_Attack aufgerufen
    // *************************************
    
    func void ZS_RansackDeadMonster ()
    {
        Perception_Set_Normal();
    };
        
    func int ZS_RansackDeadMonster_Loop ()
    {
        AI_StandUp (self);
        
        // ------ zum Body gehen ------
        AI_GotoNpc (self, other);
        
        // ------ zum Body drehen ------
        B_TurnToNpc (self, other);
        
        // ------ Durchsuchen-Ani ------
        AI_PlayAni (self, "T_PLUNDER");
        
        B_TransferInventory(other, self);
        
        if (//hier abfragen ob keine toten Viecher mehr in der Nähe des NPC sind)
        {
            return LOOP_END;
        }
        
        //falls das nicht der Fall ist -> Loop neu starten
        return LOOP_CONTINUE;
    };
    
    func void ZS_RansackDeadMonster_End ()
    {    
        // ------ NSC heilt sich ------
        if (self.attribute[ATR_HITPOINTS] < (self.attribute[ATR_HITPOINTS_MAX]/2))
        {
            AI_StartState    (self, ZS_HealSelf, 0, "");
            return;
        };
    };


    Edit: Ich würde mir vielleicht noch eine Funktion schreiben, die deine Abfragen in der ZS_Dead_End (Npc_IsDown(...)) zusammenfasst und diese als Abfrage an meiner markierten Stelle benutzen, so prüfst du am Ende jeden Loops noch einmal alle (Monster-)Gilden und deren Ransacked-Flag um den NPC um damit den Loop wieder von vorne zu beginnen.

    Diese könnte vielleicht so aussehen:
    Code:
    func int C_CanRansackLoop(var c_npc oth)
    {
        if (C_NpcIsDown(oth))
        && (other.aivar[AIV_DEADMONSTERRANSACKED] == FALSE)
        && (Npc_GetDistToNpc(self, other) < PERC_DIST_INTERMEDIAT)
        && (other.aivar[AIV_MM_REAL_ID] != ID_GOBBO_BLACK)
        && (other.aivar[AIV_MM_REAL_ID] != ID_GOBBO_GREEN)
        && (other.aivar[AIV_MM_REAL_ID] != ID_GOBBO_SKELETON)
        && (other.aivar[AIV_MM_REAL_ID] != ID_SKELETON)
        && (other.aivar[AIV_MM_REAL_ID] != ID_DRAGONSNAPPER)
        && (other.aivar[AIV_MM_REAL_ID] != ID_MINECRAWLER)
        && (other.aivar[AIV_MM_REAL_ID] != ID_MINECRAWLERWARRIOR)
        && (other.aivar[AIV_MM_REAL_ID] != ID_SHADOWBEAST)
        && (other.aivar[AIV_MM_REAL_ID] != ID_STONEGOLEM)
        && (other.aivar[AIV_MM_REAL_ID] != ID_SWAMPSHARK)
        && (other.aivar[AIV_MM_REAL_ID] != ID_TROLL_BLACK)
        && (other.aivar[AIV_MM_REAL_ID] != ID_DEMON)
        && (other.aivar[AIV_MM_REAL_ID] != ID_DEMON_LORD)
        && (other.aivar[AIV_MM_REAL_ID] != ID_SHEEP)
        {
            return TRUE;
        };
    
        return FALSE;
    };


    EDIT 2: other.aivar[AIV_DEADMONSTERRANSACKED] = TRUE; würde ich auch eher in deine ZS schreiben, damit auch für jedes geplünderte Viech das Flag gesetzt wird. Ansonsten wird das Flag evtl. nur für den zuletzt besiegten Gegner gesetzt, da dort der ZS_Attack ja endet.
    Geändert von GenerationLost (26.07.2017 um 12:48 Uhr)

  6. Homepage besuchen Beiträge anzeigen #6 Zitieren
    Team Velen
    Registriert seit
    Aug 2015
    Beiträge
    952
     
    Bloodfly91 ist offline
    Vielen Dank euch beiden. Ich hatte es gestern schon geschafft, aber keine große Lust mehr zu schreiben. ^^

    Mit diesem Skript funktioniert es:
    Code:
    // *************************************
    // ZS_RansackDeadMonster
    // ---------------------
    // wird am Ende von ZS_Attack aufgerufen
    // *************************************
    var int DeadMonsterWithLootNearMe;
    
    func void CheckDeadMonstersNearMe (var C_NPC Monster)
    {
        if (C_NpcIsDown(Monster))
        && (Npc_GetDistToNpc(self, Monster) < PERC_DIST_INTERMEDIAT)
        && (Monster.aivar[AIV_DEADMONSTERRANSACKED] == FALSE)
        && (Npc_GetInvItemBySlot (Monster, 0, 0) > 0)
        
        // --- FOLGENDE MONSTER WERDEN !NICHT! GEPLÜNDERT ---
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_GOBBO_BLACK)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_GOBBO_GREEN)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_GOBBO_SKELETON)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_SKELETON)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_DRAGONSNAPPER)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_MINECRAWLER)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_MINECRAWLERWARRIOR)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_SHADOWBEAST)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_STONEGOLEM)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_SWAMPSHARK)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_TROLL_BLACK)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_DEMON)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_DEMON_LORD)
        && (Monster.aivar[AIV_MM_REAL_ID] != ID_SHEEP)
        {
            DeadMonsterWithLootNearMe = TRUE;
            
            Monster.aivar[AIV_DEADMONSTERRANSACKED] = TRUE;
        
            AI_StandUp (self);
            AI_GotoNpc (self, Monster);
            B_TurnToNpc (self, Monster);
            AI_PlayAni (self, "T_PLUNDER");
        
            B_TransverInventory (Monster, self);
            
        } else {
        
            DeadMonsterWithLootNearMe = FALSE;
        };
    };
    
    func void ZS_RansackDeadMonster ()
    {
        Perception_Set_Normal();
        
        self.aivar[AIV_RANSACKDEADMONSTER] = TRUE;
    };
        
    func int ZS_RansackDeadMonster_Loop ()
    {
        DoForSphere (CheckDeadMonstersNearMe);
        
        if (DeadMonsterWithLootNearMe == FALSE)
        {
            self.aivar[AIV_RANSACKDEADMONSTER] = FALSE;
            return LOOP_END;    
        };    
    };
    
    func void ZS_RansackDeadMonster_End ()
    {    
        // ------ NSC heilt sich ------
        if (self.attribute[ATR_HITPOINTS] < (self.attribute[ATR_HITPOINTS_MAX]/2))
        {
            AI_StartState    (self, ZS_HealSelf, 0, "");
            return;
        };
        
        AI_ContinueRoutine (self);
    };
    Benötigt wird https://forum.worldofplayers.de/forum/threads/775333-Script-Broadcasts?p=17232705&viewfull=1#post17232705 und auch dieses Skript https://forum.worldofplayers.de/forum/threads/199081-npc-soll-anderen-npc-ausbeuten?p=3146927#post3146927, wenn man die Funktion B_TransverInventory verwenden will. Die Aivars AIV_RANSACKDEADMONSTER und AIV_DEADMONSTERRANSACKED müssen auch in die AI_Constants eingetragen werden.

    In die ZS_Attack muss unter AI_RemoveWeapon noch das:
    Code:
    if (other.guild > GIL_SEPERATOR_HUM) && (self.guild == GIL_DJG)
    {
       AI_StartState (self, ZS_RansackDeadMonster, 0, "");
    };
    Diese Funktion sollte man aber noch anpassen, da vermutlich nicht jeder will, dass alle NPCs mit der Gilde "Drachenjäger" tote Monster ausnehmen.
    Geändert von Bloodfly91 (26.07.2017 um 14:42 Uhr)

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