Zamrożenie przy walce ze specialnym przeciwnikiem. 2378 3

O temacie

Autor lucki666

Zaczęty 27.02.2021 roku

Wyświetleń 2378

Odpowiedzi 3

lucki666

lucki666

Użytkownicy
posty133
Propsy65
ProfesjaSkrypter
  • Użytkownicy
Robię coś na podobieństwo "bossów", gdzie podczas walki przeciwnik używa różnych czarów i przyzywa kompanów do pomocy.

Wszystko działa tak jak trzeba - gdy punkty życia przeciwnika spadną poniżej określonego poziomu, jest animacja czaru, zadawane obrażenia bohaterowi czy przyzwanie pomocnika. Problem pojawia się w momencie, gdy za pomocą bryły lodu/ lodowej fali zamrozimy "ów bossa". Wtedy określone efekty zwyczajnie nie występują.

Myślę, że może to być spowodowane miejscem w pliku, gdzie umiejscowiłem funkcję. Plik: ZS_MM_Attack . Próbowałem potem przenieść to gdzie indzie, ale w ogóle efekty nie działały. Jakieś rady? Bo wprowadzenie odporności na zamrożenie konkretnego potwora raczej nie wchodzi w grę.

Może w innym pliku umiejscowić tą funkcję lub stworzyć jakiś nowy plik i jak miałby on wyglądać?

Mój plik: Gothic II\_Work\Data\Scripts\Content\AI\Monster\ZS_Monster\ZS_MM_Attack
Dodanie linijki na czerwono.
Spoiler
// ********************
// ZS_MM_Attack
// ------------
// für Monster und Orks
// ********************

func void B_MM_AssessSurprise()
{
   Npc_SetTarget (self, other); //Ziel wechseln
};


func void ZS_MM_Attack ()
{                                    
   Npc_SetPercTime    (self, 1);
   
   Npc_PercEnable      (self, PERC_ASSESSBODY         ,    B_MM_AssessBody);   //wenn Monster in Attack leckeren Body wittert
      
   Npc_PercEnable      (self, PERC_ASSESSMAGIC         ,     B_AssessMagic);          //selbe Rkt wie Humans
   Npc_PercEnable      (self, PERC_ASSESSDAMAGE      ,   B_MM_AssessDamage);
   Npc_PercEnable      (self, PERC_ASSESSWARN         ,    B_MM_AssessWarn);
   
   // ------ lokale Wahrnehmung für verwandelten SC ------
   Npc_PercEnable (self, PERC_ASSESSSURPRISE , B_MM_AssessSurprise);

   B_ValidateOther();

   // EXIT IF...
   
   // ------ Schafe fliehen immer ------
   if (self.guild == GIL_SHEEP)
   {
      Npc_ClearAIQueue    (self);
      B_ClearPerceptions    (self);
      Npc_SetTarget      (self, other);
      AI_StartState       (self, ZS_MM_Flee, 0, "");
      return;
   };
   
   // FUNC
      
   AI_StandUp      (self);
   AI_SetWalkmode    (self, NPC_RUN);
   
   // ------ Hilfe anfordern ------
   Npc_SendPassivePerc   (self, PERC_ASSESSWARN,   other, self); //Opfer,Täter   
   
   // ------ init aivars -------
   self.aivar[AIV_PursuitEnd] = FALSE;
   self.aivar[AIV_StateTime] = 0;
   self.aivar[AIV_HitByOtherNpc] = 0;
   self.aivar[AIV_SelectSpell] = 0; //Für Magier
   self.aivar[AIV_TAPOSITION] = 0; //für Regeneration

};

func int ZS_MM_Attack_Loop ()
{
   Npc_GetTarget (self); // other = target
   
   // ------ Regeneration ------

//--------------------------------Boss Figth-----------------------------------
var int SShadowbeastBoss;
var int SShadowbeastBoss2;
var int SShadowbeastBoss3;

   if  Hlp_GetInstanceID (self) == Hlp_GetInstanceID (SShadowbeast_Skeleton)
   {         
      if (self.attribute[ATR_HITPOINTS] < 900)
      && (SShadowbeastBoss == FALSE)
      {   
         Wld_SpawnNpcRange   (hero,   Shadowbeast_Skeleton,   1,   700);
         SShadowbeastBoss = TRUE;
      };
      if (self.attribute[ATR_HITPOINTS] < 1350)
      && (SShadowbeastBoss2 == FALSE)
      {   
         Wld_PlayEffect("spellFX_FireRain_RAIN",  hero, hero, 0, 0, 0, FALSE );
         hero.attribute[ATR_HITPOINTS] -= 100;
         SShadowbeastBoss2 = TRUE;
      };
      if (self.attribute[ATR_HITPOINTS] < 1800)
      && (SShadowbeastBoss3 == FALSE)
      {   
         Wld_SpawnNpcRange   (hero,   BeachShadowbeast1,   1,   700);
         SShadowbeastBoss3 = TRUE;
      };
   };
//-----------------------------------------------------------------------------

   
   //ADDON>
   if (RavenIsDead == TRUE)
   && (self.guild == GIL_STONEGUARDIAN)
   {   
      B_KillNpc (self);
   };
   //ADDON<
      
   // EXIT LOOP IF...
   
   // ------ HACK: Orks nicht in die Burg ------
   if (CurrentLevel == OLDWORLD_ZEN) //Joly: verbessert Performance in anderen Leveln
   {
      if (Npc_GetDistToWP (self, "OC_RAMP_07") <= 500)
      {
         Npc_ClearAIQueue(self);
         AI_StandUp      (self);
         AI_PlayAni      (self, "T_WARN");    //nochmal zum Abschied Drohen
         self.aivar[AIV_PursuitEnd] = TRUE;
         return LOOP_END;
      };
   };      
   // ------ Kampfabbruch, wenn zu weit weg ------
   if (Npc_GetDistToNpc (self, other) > FIGHT_DIST_CANCEL)
   {
      Npc_ClearAIQueue(self);
      AI_StandUp      (self);
      self.aivar[AIV_PursuitEnd] = TRUE;
      return LOOP_END;
   };
   
   // ------ Gegner wird schon zu lange verfolgt ------
   if (Npc_GetStateTime (self) > self.aivar[AIV_MM_FollowTime])
   && (self.aivar[AIV_PursuitEnd] == FALSE)
   {
      Npc_ClearAIQueue(self);
      AI_StandUp      (self);
      self.aivar[AIV_PursuitEnd] = TRUE;
      self.aivar[AIV_Dist] = Npc_GetDistToNpc(self, other);
      self.aivar[AIV_StateTime] = Npc_GetStateTime (self);
         
      AI_PlayAni      (self, "T_WARN");    //nochmal zum Abschied Drohen
   };
   
   // ------ Warten, ob Feind auch wirklich flieht ------
   if (self.aivar[AIV_PursuitEnd] == TRUE)
   {
      // ------ weit genug weg ------
      if (Npc_GetDistToNpc (self, other) > self.senses_range)
      {
         return LOOP_END;
      };
            
      // ------ einmal pro Sekunde ------   
      if (Npc_GetStateTime (self) > self.aivar[AIV_StateTime])
      {
         // ------ Feind kommt zurück ODER bleibt stehen ------
         if (Npc_GetDistToNpc(self, other) < self.aivar[AIV_Dist])
         || ( (!C_BodyStateContains(other,BS_RUN)) && (!C_BodyStateContains(other, BS_JUMP)) )
         {
            self.aivar[AIV_PursuitEnd] = FALSE;
            Npc_SetStateTime (self, 0);
            self.aivar[AIV_StateTime] = 0;
            // --> und weiter im Text!   
         }
         else
         {
            AI_TurnToNpc (self, other);
            self.aivar[AIV_Dist] = Npc_GetDistToNpc(self, other);
            self.aivar[AIV_StateTime] = Npc_GetStateTime (self);
         };
      };
      
      return LOOP_CONTINUE;
   };
   
   // ------ Gegner geht ins Wasser und ich will nicht schwimmen ------
   if (C_BodyStateContains(other,BS_SWIM) || C_BodyStateContains(other,BS_DIVE))
   && (self.aivar[AIV_MM_FollowInWater] == FALSE)
   {
      Npc_ClearAIQueue(self);
      AI_StandUp      (self);
      return LOOP_END;
   };
   
   
   // LOOP FUNC
   
   // ------ Vor Attacke kurz warten (bei Angriff aus Dialog) ------
   if (self.aivar[AIV_WaitBeforeAttack] == 1) //nur einmal
   {
      AI_Wait (self, 0.8);
      self.aivar[AIV_WaitBeforeAttack] = 0;
   };
   
   // ------ Summon Time ------
   if (self.level == 0)
   {
      if (Npc_GetStateTime (self) > self.aivar[AIV_StateTime])
      {
         self.aivar[AIV_SummonTime] = (self.aivar[AIV_SummonTime] + 1);
      
         self.aivar[AIV_StateTime] = Npc_GetStateTime (self);
      };
      
      if (self.aivar[AIV_SummonTime] >= MONSTER_SUMMON_TIME)
      {
         Npc_ChangeAttribute (self, ATR_HITPOINTS, -self.attribute[ATR_HITPOINTS_MAX]);
      };
   };

   // ------ Verfolgungstimer resetten ------
   if ( (!C_BodyStateContains(other,BS_RUN)) && (!C_BodyStateContains(other,BS_JUMP)) )
   && (Npc_GetStateTime (self) > 0)
   {
      Npc_SetStateTime (self, 0);
      self.aivar[AIV_StateTime] = 0;
   };
   
   // ------ Wenn Max-Entfernung zum WP angegeben ------
   if (self.aivar[AIV_MaxDistToWp] > 0)
   {
      if (Npc_GetDistToWP(self, self.wp) > self.aivar[AIV_MaxDistToWp])
      && (Npc_GetDistToWP(other, self.wp) > self.aivar[AIV_MaxDistToWp])
      {
         self.fight_tactic = FAI_NAILED;
      }
      else //einer von beiden nah genug am self.wp
      {
         self.fight_tactic = self.aivar[AIV_OriginalFightTactic];
      };
   };
   
   // ------ MonsterMage zieht Spruch / Orc zieht Waffe ------
   if (C_NpcIsMonsterMage(self))
   || (self.guild == GIL_SKELETON)
   || (self.guild == GIL_SUMMONED_SKELETON)
   || (self.guild > GIL_SEPERATOR_ORC)
   {
      B_CreateAmmo   (self);   //ggf. Muni generieren
      Npc_ChangeAttribute   (self, ATR_MANA, ATR_MANA_MAX); //immer volles MANA
      B_SelectWeapon    (self, other);
   };
   
   // ------ ATTACK ------   
   if (Hlp_IsValidNpc(other))             // wenn target da ist, ist hier auch other valid
   && (!C_NpcIsDown(other))             // sonst "attackiert" der NPC ein z.B. totes Opfer weiter
   {
      if (other.aivar[AIV_INVINCIBLE] == FALSE)    // Nur NSCs angreifen, die NICHT im Talk sind
      {
         AI_Attack (self);    //In der Funktion, in der AI_Attack aufgerufen wird DARF KEIN AI_ Befehl VOR AI_Attack kommen, da sonst AI_Attack ignoriert wird
                        //(AI-Attack funktioniert NUR, wenn die AIqueue leer ist!)
      }
      else
      {
         Npc_ClearAIQueue(self); //killt den letzten AI_Attack-Befehl, verhindert z.B. stumpfes weiterrennen.
      };
      
      self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID (other);
      
      return LOOP_CONTINUE;
   }
   else                               // NPC_GetTarget(self) == FALSE, also tot - other hier automatisch gelöscht
   {
      // ------ Monster auf der Jagd --> Beute fressen kommt VOR NextTarget ------
      if (self.aivar[AIV_MM_PRIORITY] == PRIO_EAT)
      && (C_WantToEat (self, other))
      {
         Npc_ClearAIQueue(self);
         AI_StandUp      (self);
         return LOOP_END;
      };
      
      // ------ Monster NICHT auf der Jagd - weitere Feinde Attacken ------
      Npc_PerceiveAll   (self);               // nötig, da Npc_GetNextTarget() auf der Liste der zuletzt Wahrgenommenen VOBs beruht, und das kann hier schon ne Weile her sein, denn ZS_Attack hat keine aktiven Wahrnehmungen
      Npc_GetNextTarget (self);             // wenn True, wird hier target neu ermittelt (NUR die zu denen ich Hostile bin!)
      
      // ----- ist neues Ziel gefunden, in Reichweite, nicht down, nicht im Dialog? Dann neues Ziel, sonst End ------
      if (Hlp_IsValidNpc(other))
      && (!C_NpcIsDown(other))
      && ( (Npc_GetDistToNpc(self, other) < PERC_DIST_INTERMEDIAT) || (Npc_IsPlayer(other)) ) //Bei Nicht-Player Enemies nur auf 1000m reagieren (sonst ACTIVE_MAX)
      && (other.aivar[AIV_INVINCIBLE] == FALSE)
      {
         self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID (other);
         return LOOP_CONTINUE;
      }
      else                            // wenn false, wird other gelöscht!
      {
         Npc_ClearAIQueue(self);
         AI_StandUp      (self);
         return LOOP_END;
      };
   };
};

func void ZS_MM_Attack_End ()
{
   // ------ other wieder holen, ist hier auf jeden Fall gelöscht! ------
   other = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]);

   // ------ MonsterMage steckt Spruch weg / Orc steckt Waffe weg ------
   if (C_NpcIsMonsterMage(self))
   || (self.guild == GIL_SKELETON)
   || (self.guild == GIL_SUMMONED_SKELETON)
   || (self.guild > GIL_SEPERATOR_ORC)
   {
      AI_RemoveWeapon (self);
   };
         
   // ------ Beute fressen ------
   if (Npc_IsDead(other))
   && (C_WantToEat (self, other))               
   {
      Npc_ClearAIQueue(self);
      AI_StartState    (self, ZS_MM_EatBody, 0, "");
      return;
   };
};



   
 

Czudak

Czudak

Użytkownicy
posty144
Propsy61
ProfesjaSkrypter
  • Użytkownicy
Zamrożony przeciwnik, za pomocą Bryły/Fali Lodu, ma włączoną specjalną percepcję "B_AssessMagic", która czyści wszystkie inne za pomocą "B_ClearPerceptions" dla tych dwóch czarów, włączając w to różne "oszacuj" percepcje, w tym "oszacuj obrażenia". Wtedy to możesz ładować zamrożonego bossika, ale on nie zarejestruje że spadły mu Hit Pointsy, więc nie będzie przywoływania potworasów w myśl twojej funkcji powyżej.

Musisz dodać wyjątek do "ZS_MagicFreeze" dla bossików.

Pozdrawiam.
 

lucki666

lucki666

Użytkownicy
posty133
Propsy65
ProfesjaSkrypter
  • Użytkownicy
@Czudak
Podpowiesz mi, w jaki sposób dodać wyjątek i w którym miejscu w pliku ZS_MagicFreeze ?
 

Czudak

Czudak

Użytkownicy
posty144
Propsy61
ProfesjaSkrypter
  • Użytkownicy
Tutaj. Tylko popatrz, czy reszta funkcji się zgadza, bo wiem, że tutaj dopisywałem sobie różne takie do swojego moda. W razie czego porównaj z oryginalnymi, czystymi skryptami Nocy Kruka z WoGa.

Cytuj
func void ZS_MagicFreeze()
{
   if(Hlp_GetInstanceID(self) != Hlp_GetInstanceID(ID_MOJEGO_BOSSIKA)) // Tutaj "identyfikator" ("ID_MOJEGO_BOSSIKA") swojego BNa musisz sam sobie zorganizować w skryptach, czy to za pomocą tego co tutaj napisałem, czy self.guild != GIL_XXX albo self.aivar[AIV_MM_REAL_ID] != ID_XXX, czy czego tam używasz, you feel me?
   {
           Npc_PercEnable(self,PERC_ASSESSMAGIC,B_RestartFreeze);
   };
   Npc_StopAni(self,"S_FIRE_VICTIM");
   if(!C_BodyStateContains(self,BS_UNCONSCIOUS))
   {
      AI_PlayAniBS(self,"T_STAND_2_FREEZE_VICTIM",BS_UNCONSCIOUS);
   };
   B_ClearRuneInv(self);
   if((self.guild != GIL_DMT) && Npc_HasItems(self,ItAr_Dementor))
   {
      Npc_RemoveInvItems(self,ItAr_Dementor,Npc_HasItems(self,ItAr_Dementor));
   };
   self.aivar[AIV_FREEZESTATETIME] = 0;
};

EDYCJA: Hmm, myślałem, że włączenie percypowania magii jest automatyczne w funkcji kolizji czarów dla tych dwóch, ale okazuje się, że nie. Pewnie dlatego też wyjątek jednak będzie trzeba dodać do tego co już sam ustaliłeś: "ZS_MM_Attack", zamiast w "ZS_MagicFreeze". Albo trzeba będzie go aktywować w samym "B_AssessMagic". Jedno z tych, więc testuj.
 


0 użytkowników i 1 Gość przegląda ten wątek.
0 użytkowników
Do góry