Widzę że niektórzy mają problemy z B_SelectSpell najpierw wytłumaczę wam z grubsza mniej więcej orginalny skrypt: opis wszystkiego w zwykłym komentarzu aby było łatwiej, zresztą nawet wam, kopiujecie skrypt i macie to w notepadzie

No więc ciach:
// *************************************************************
// B_SelectSpell
// -------------
// Magieauswahl für Menschen und Monster
// Wenn Auswahlkriterien erfüllt (je nach Gilde unterschiedlich)
// --> TRUE, sonst FALSE
// Humans zaubern nur als KdF, PAL oder DMT
// *************************************************************
func int B_SelectSpell (var C_NPC slf, var C_NPC oth)// Funkcja ze zmiennymi c_npc
{
if (slf.npctype == NPCTYPE_FRIEND)//Jeśli typ npc naszego npc to przyjaciel
&& (Npc_IsPlayer (oth))// Jeśli gracz jest other czyli chyba bezim
&& (oth.guild < GIL_SEPERATOR_HUM) //Jeśli gracz znajduje się w przedziale dla gildii ludzkich
{
if (slf.guild == GIL_KDF) // Jeśli gildia naszego npc to mag ognia
|| (slf.aivar[AIV_MagicUser] == MAGIC_ALWAYS) // Albo ma wpisany AI magii ustawiony na używanie jej
{//to:
if (Npc_HasItems (slf, ItRu_Sleep) == 0)//Jeśli niema w eq runy pt "SEN"
{//to
CreateInvItems (slf, ItRu_Sleep, 1);//Towrzy ją
};
B_ReadySpell (slf, SPL_Sleep, SPL_Cost_Sleep);// Używa jej
return TRUE; //True story
}
else // A jak nie jest magiem ognia
{
return FALSE; //Nie potwierdzone info
};
};
// ------ Dementor -------
if (slf.guild == GIL_DMT) // Jeśli npc to poszukiwacz
&& (slf.aivar[AIV_MagicUser] == MAGIC_ALWAYS) //Jesli ma wpisany aivar magiczny ustawiony na używanie magii
{
// ------- in die Taschen -------
if (Npc_HasItems (slf, ItRu_InstantFireball) == 0) { CreateInvItems (slf, ItRu_InstantFireball, 1); };
if (Npc_HasItems (slf, ItRu_Deathbolt) == 0) { CreateInvItems (slf, ItRu_Deathbolt, 1); };
if (Npc_HasItems (slf, ItRu_Deathball) == 0) { CreateInvItems (slf, ItRu_Deathball, 1); };
if (Npc_HasItems (slf, ItRu_Firerain) == 0) { CreateInvItems (slf, ItRu_Firerain, 1); };// Tworzy te runy
if (Npc_HasItems (slf, ItRu_Thunderstorm) == 0) { CreateInvItems (slf, ItRu_Thunderstorm, 1); };
if (Npc_HasItems (slf, ItRu_LightningFlash) == 0) { CreateInvItems (slf, ItRu_LightningFlash, 1); };
if (Npc_HasItems (slf, ItRu_Firestorm) == 0) { CreateInvItems (slf, ItRu_Firestorm, 1); };
if (Npc_HasItems (slf, ItRu_Skull) == 0) { CreateInvItems (slf, ItRu_Skull, 1); };
// ------------------------------
if (Hlp_GetInstanceID(slf) == Hlp_GetInstanceID(DMT_1299_OberDementor_DI)) //Jeśli nasz npc to "Czarny mag"
{
B_ReadySpell (slf, SPL_Skull, SPL_Cost_Skull); // Nasz npc zajebie nam ze skull'a (Ta taka czaszka co killa każdego i zabiera całą manę)
return TRUE;//Prawda
}
else
{
if (Npc_IsDrawingWeapon(slf))
{
return TRUE; // Żeby nic się nie stało jak wyciągnie broń.
};
// ------ Random für eine Serie ------
if (slf.aivar[AIV_SelectSpell] <= 0)// Jeśli AI naszego npc to Wybór czaru mniejszy bądź równy 0.
{
var int dK_rnd; dK_rnd = Hlp_Random(10); // Zmienna randomu (losowania) równa 10
slf.aivar[AIV_SelectSpell] += dK_rnd; //Tym samym dodajemy ją do naszego AI aby jakiś czar mu wylosowało.
};
if (slf.aivar[AIV_SelectSpell] < 10) // Jeśli AI wyboru czaru jest mniejszy niż 10
{
if (Kapitel <= 3) { B_ReadySpell (slf, SPL_InstantFireball , SPL_Cost_InstantFireball); return TRUE; } //jesli rozdział niejszy bądź równy 3 użyje małej kuli ognia
else if (Kapitel <= 4) { B_ReadySpell (slf, SPL_DeathBolt , SPL_Cost_DeathBolt); return TRUE; }// jeśli rozdział mniejszy bądź równy 4 użyje śmiertelnej fali jak dobrze pamiętam.
else /*Kap 5+*/ { B_ReadySpell (slf, SPL_DeathBall , SPL_Cost_DeathBall); return TRUE; };// jak wyżej niż 4 rozdział też Death ball
}
else if (slf.aivar[AIV_SelectSpell] == 10)// Jeśli wybór czaru jest równy 10
{
slf.aivar[AIV_SelectSpell] = 11; // Zamień go na 11
var int dK_Mega; dK_Mega = Hlp_Random(100); // Nowa zmienna randoma. Tym razem liczymy do stu.
if (dK_Mega <= 2) { B_ReadySpell (slf, SPL_Firerain , SPL_Cost_Firerain); return TRUE; }//jak random mniejszy bądź równy 2 to użyje deszczu ognia
else if (dK_Mega <= 5) { B_ReadySpell (slf, SPL_Thunderstorm, SPL_Cost_Thunderstorm); return TRUE; }// jak random mniejszy lub równy 5 to użyje kurwa nie pamietam. No użyje thunderstorma
else if (dK_Mega <= 10) { B_ReadySpell (slf, SPL_LightningFlash, SPL_Cost_LightningFlash); return TRUE; }// Dobra chyba łapiecie ocb?
else /*11-99*/ { B_ReadySpell (slf, SPL_Firestorm, SPL_Cost_Firestorm); return TRUE; };
}
else if (slf.aivar[AIV_SelectSpell] == 12) // Jeśli równy 12
{
slf.aivar[AIV_SelectSpell]=0;// Zamień na 0 xd
};
};
return TRUE; // Tu ma zwracać zawsze true bo inaczej odłoży czar
};
// Co do tych randomów to nie wiem, grałem w g2 milion razy a ani razu nie widziałem aby poszukiwacz walił skullem bądź deszczem ognia xd
// ------ Magier ------
if (slf.guild == GIL_KDF)// Jeśli gildia npc to mag ognia
|| (slf.aivar[AIV_MagicUser] == MAGIC_ALWAYS) // Ma AI używania magii
{
if (Npc_HasItems (slf, ItRu_Concussionbolt) == 0)
{
CreateInvItems (slf, ItRu_Concussionbolt, 1);
};
if (Npc_HasItems (slf, ItRu_InstantFireBall) == 0)
{
CreateInvItems (slf, ItRu_InstantFireBall, 1);
};
if (Npc_HasItems (slf, ItRu_Deathball) == 0)
{
CreateInvItems (slf, ItRu_Deathball, 1);
};
if (Npc_HasItems (slf, ItRu_FullHeal) == 0)
{
CreateInvItems (slf, ItRu_FullHeal, 1); // Tworzy runy już to objaśniałem.
};
if (self.attribute[ATR_HITPOINTS] < 100) // Jak ma mało hp
{
B_ReadySpell (slf, SPL_FullHeal, SPL_Cost_FullHeal);// Się leczy.
return TRUE;// prawda
}
else if (C_NpcHasAttackReasonToKill (self)) // Jednak jeśli nas atakuje w celu zabicia. Noo nas/ czy tam innego npc
{// to
if (self.flags == NPC_FLAG_IMMORTAL) // Jeśli ma flagę immortial
|| (Hlp_GetInstanceID(other) == Hlp_GetInstanceID(Raven))// Lub jeśłi chodzi o kruka
{
B_ReadySpell (slf, SPL_Deathball, SPL_Cost_Deathball); // Nakurwia death ballem
}
else
{
B_ReadySpell (slf, SPL_InstantFireball, SPL_Cost_InstantFireBall);// A jak nie to mała kula ognia
};
return TRUE;
}
else// a jak nie to wyżej
{
B_ReadySpell (slf, SPL_Concussionbolt, SPL_Cost_Concussionbolt);// To zwyczajny concissionbolt
return TRUE;
};
};
// ------ Paladin ------
if (slf.guild == GIL_PAL)// Jeśli to palladyn
{
if (slf.fight_tactic == FAI_NAILED) //Jeśli jego taktyka walki to FAI_NAILED
{
return FALSE;//Nie zwraca prawdy
};
if (Npc_HasItems (slf, ItRu_PalHolyBolt) == 0)
{
CreateInvItems (slf, ItRu_PalHolyBolt, 1);//Tworzy runę
};
if (Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_MELEE)// Jeśli jejst w jakiejś odległości od swojego przeciwnika
&& (C_NpcIsEvil(oth))// Jeśli przeciwnik jest zły
{
B_ReadySpell (slf, SPL_PalHolyBolt, SPL_Cost_PalHolyBolt);// Uzywa runy
return TRUE;//Prawda
}
else
{
return FALSE; //Jak nie to nie prawda
};
};
// ------ Skelett Magier ------
if (slf.guild == GIL_SKELETON_MAGE)// Jeśli jest szkieletem magiem
{
if (Npc_HasItems (slf, ItRu_SumSkel) == 0)
{
CreateInvItems (slf, ItRu_SumSkel, 1);
};
if (Npc_HasItems (slf, ItRu_IceCube) == 0)
{
CreateInvItems (slf, ItRu_IceCube, 1);
};
if (Npc_HasItems (slf, ItRu_Icebolt) == 0)
{
CreateInvItems (slf, ItRu_Icebolt, 1);// Tworzy runy
};
// ------ Spruchzyklus bei SUMMON beginnen ------
if (slf.aivar[AIV_SelectSpell] >= 6)//Jeśli selekt spell jest większy bądź równy 6
{
slf.aivar[AIV_SelectSpell] = 1; // To zamień na 1
};
if (!Npc_IsInState (oth, ZS_MagicFreeze)) // Jeśli jego przeciwnik jest zamrożony
&& (slf.aivar[AIV_SelectSpell] == 0) // I selekt spell jest równy 0
{
B_ReadySpell (slf, SPL_IceCube, SPL_Cost_IceCube); // Użyje ajskjuba
return TRUE;
}
else if (slf.aivar[AIV_SelectSpell] == 1) //Jeśli jeden
{
B_ReadySpell (slf, SPL_SummonSkeleton, SPL_Cost_SummonSkeleton);// To przywoła szkielety
return TRUE;
}
else
{
B_ReadySpell (slf, SPL_Icebolt, SPL_Cost_Icebolt);// A jak inny to użyje ajsbolta xd
return TRUE;
};
};
// ------ Eisgolem ------
if (slf.guild == GIL_ICEGOLEM) // Jeśli npc to lodowy golem
{
if (Npc_HasItems (slf, ItRu_IceCube) == 0)
{
CreateInvItems (slf, ItRu_IceCube, 1); // Nie tłumaczę
};
if (Npc_GetDistToNpc(slf,oth) < FIGHT_DIST_MELEE) // Jeśli odległość między nim a przeciwnikiem to zmienna bądź stała o nazwie "Fight_Dist_Melee"
|| (Npc_IsInState (oth, ZS_MagicFreeze)) // Lub przeciwnik jest zamrożony
{
return FALSE; //Nie prawda
}
else //Ewentualnie
{
B_ReadySpell (slf, SPL_IceCube, SPL_Cost_IceCube); //Użyje ajskjuba
return TRUE;
};
};
// ------ Feuergolem ------
if (slf.guild == GIL_FIREGOLEM)// Podobnie jak z lodowym, tylko ten jest ognisty
{
if (Npc_HasItems (slf, ItRu_InstantFireball) == 0)
{
CreateInvItems (slf, ItRu_InstantFireball, 1);
};
if (Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_MELEE)
{
B_ReadySpell (slf, SPL_InstantFireball, SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE; //Nahkampfangriff
};
};
// ------ Sumpfdrache ------
if (slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_SWAMP)// Jeśli npc to bagienny smok
{
if (Npc_HasItems (slf, ItRu_InstantFireball) == 0)
{
CreateInvItems (slf, ItRu_InstantFireball, 1); //Wiecie
};
if (Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_DRAGON_MAGIC)// Wiecie
{
B_ReadySpell (slf, SPL_InstantFireball, SPL_Cost_InstantFireball);// Już chyba wiecie
return TRUE;
}
else
{
return FALSE; //Nahkampfangriff
};
};
// ------ Felsdrache ------
if (slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_ROCK)// Jak wyżej tylko smok z fortecy
{
if (Npc_HasItems (slf, ItRu_InstantFireball) == 0)
{
CreateInvItems (slf, ItRu_InstantFireball, 1);
};
if (Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_DRAGON_MAGIC)
{
B_ReadySpell (slf, SPL_InstantFireball, SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE; //Nahkampfangriff
};
};
// ------ Feuerdrache ------
if (slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_FIRE)// Jak wyżej tylko smok ognisty
{
if (Npc_HasItems (slf, ItRu_InstantFireball) == 0)
{
CreateInvItems (slf, ItRu_InstantFireball, 1);
};
if (Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_DRAGON_MAGIC)
{
B_ReadySpell (slf, SPL_InstantFireball, SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE; //Nahkampfangriff
};
};
// ------ Eisdrache ------
if (slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_ICE)// Jak wyżej tylko smok lodowy
{
if (Npc_HasItems (slf, ItRu_InstantFireball) == 0)
{
CreateInvItems (slf, ItRu_InstantFireball, 1);
};
if (Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_DRAGON_MAGIC)
{
B_ReadySpell (slf, SPL_InstantFireball, SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE; //Nahkampfangriff
};
};
// ------ Untoter Drache (ENDGEGNER) ------
if (slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_UNDEAD)// Jak wyżej tylko smok ożywieniec
{
Npc_ClearAIQueue(self);
if (Npc_HasItems (slf, ItRu_Deathball) == 0)
{
CreateInvItems (slf, ItRu_Deathball, 1);
};
if (Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_DRAGON_MAGIC)
{
B_ReadySpell (slf, SPL_Deathball, SPL_Cost_Deathball);
return TRUE;
}
else
{
return FALSE; //Nahkampfangriff
};
};
// ------ Ork Schamane ------
if (slf.aivar[AIV_MM_REAL_ID] == ID_ORCSHAMAN) // Jeśli ork szaman reszte wiecie
{
if (Npc_HasItems (slf, ItRu_InstantFireball) == 0)
{
CreateInvItems (slf, ItRu_InstantFireball, 1);
};
if (Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_MELEE)
{
B_ReadySpell (slf, SPL_InstantFireball, SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE; //Nahkampfangriff
};
};
return FALSE; //wszystkie inne gildie
};
Teraz tak, jeśli załapaliście z grubsza to, to jeszcze pokażę wam jak zrobić swój skrypt systemu czarów dla swojego npc. hmm więc tak kluczowe jest stworzenie nowego aivara noo w sumie stałej używania czarów:
Idziemy do: _Work/data/scripts/content/AI/Ai_Intern/AI_Constants.d
Szukamy:
const int AIV_MagicUser
zjeżdżacie na dół stałych AI
ostatni to powinien być:
const int AIV_SpellLevel = 88;
Jeśli robicie na orginalnych skryptach to w linijce 341:
wklejacie:
// ------ Mój aivar magiczny -----
const int AIV_MyAiMage = 89;
const int MAGIC_NOT = 0;
const int MAGIC_YES = 1;
macie spoko:) teraz skrypt npc.Jego nie tłumacze oczywiście:
INSTANCE NONE_9999_Toworish (Npc_Default)
{
// ------ NSC ------
name = "Toworish";
guild = GIL_NONE;
id = 9999;
voice = 14;
flags = 0;
npctype = NPCTYPE_AMBIENT;
// ------ AIVARS ------
//aivar[AIV_ToughGuy] = TRUE;
//aivar[AIV_ToughGuyNewsOverride] = TRUE;
aivar[AIV_IGNORE_Murder] = TRUE;
aivar[AIV_IGNORE_Theft] = TRUE;
aivar[AIV_IGNORE_Sheepkiller] = TRUE;
aivar[AIV_IgnoresArmor] = TRUE;
aivar[AIV_MyAiMage] = MAGIC_YES;//to jest kluczowe
// ------ Attribute ------
// B_SetAttributesToChapter (self, 6);
//----- Attribute ----
attribute [ATR_STRENGTH] = 0; //Siła
attribute [ATR_DEXTERITY] = 0; //Zręczność
attribute [ATR_HITPOINTS_MAX] = 300; //Maksymalna ilość życia
attribute [ATR_HITPOINTS] = 300; // Aktualna ilość życia
attribute [ATR_MANA_MAX] = 300; //Maksymalna ilość Many
attribute [ATR_MANA] = 300; // Aktualna ilość Many
// ------ Kampf-Taktik ------
fight_tactic = FAI_HUMAN_MASTER; // to jest kluczowe
// ------ Equippte Waffen ------
// ------ Inventory ------
//B_CreateAmbientInv (self);
// ------ visuals ------
B_SetNpcVisual (self, MALE, "Hum_Head_Psionic",Face_N_Xardas , BodyTex_N, ITAR_XARDAS);
Mdl_SetModelFatness (self, 0);
Mdl_ApplyOverlayMds (self, "Humans_Mage.mds");
// ------ NSC-relevante Talente vergeben ------
//B_GiveNpcTalents (self);
// ------ Kampf-Talente ------
//B_SetFightSkills (self, 30);
Npc_SetTalentSkill (self, NPC_TALENT_MAGE, 6);// to też się przyda
// ------ TA anmelden ------
daily_routine = Rtn_PreStart_9999;
};
FUNC VOID Rtn_PreStart_9999 ()
{
TA_Stand_ArmsCrossed (08,00,23,00,"WUJEK");
TA_Stand_ArmsCrossed (23,00,08,00,"WUJEK");
};
Jeśli nie potrafisz dodać tego npc. Daj se spokój xd
Noo i ostatnie Nasza linijka w B_SelectSpell.d
Zrobimy system w którym npc zależnie od tego ile mamy many lub ile on ma życia zaatakuje nas małą kulą ognia.
i kilka innych, wszystko z grubsza opisane.
Ważne aby było to przed tą na początku wyjaśnioną linijka:
return FALSE; //wszystkie inne gildie
//-------- Nowy system walki --------------
if (slf.aivar[AIV_MyAiMage] == MAGIC_YES) //Jeśli nasz stworzony wcześniej AI jest równy MAGIC_YES czyli 1
{
if (Npc_HasItems (NONE_9999_Toworish, ItRu_FireBolt) == 0) //Jeśli niema runy
{
CreateInvItems (NONE_9999_Toworish, ItRu_FireBolt, 1); // Tworzy ją
};
if (Npc_HasItems (NONE_9999_Toworish, ItRu_InstantFireball) == 0) //jak wyżej
{
CreateInvItems (NONE_9999_Toworish, ItRu_InstantFireball, 1);
};
if (Npc_HasItems (NONE_9999_Toworish, ItRu_Icelance) == 0)
{
CreateInvItems (NONE_9999_Toworish, ItRu_Icelance, 1); //Jak wyżej
};
if (Npc_HasItems (NONE_9999_Toworish, ItRu_SuckEnergy) == 0)
{
CreateInvItems (NONE_9999_Toworish, ItRu_SuckEnergy, 1);// Jak wyżej
};
if (Npc_HasItems (NONE_9999_Toworish, ItRu_Skull) == 0)
{
CreateInvItems (NONE_9999_Toworish, ItRu_Skull, 1);// Jak wyżej
};
if (Npc_HasItems (NONE_9999_Toworish, ItRu_FullHeal) == 0)
{
CreateInvItems (NONE_9999_Toworish, ItRu_FullHeal, 1);
};
if (NONE_9999_Toworish.attribute[ATR_HITPOINTS] <= 5) //Jeśli nasz npc ma mniej bądź równo 5 hp
{
B_ReadySpell (NONE_9999_Toworish, SPL_FullHeal, SPL_Cost_FullHeal); //Leczy się
return TRUE;
}
if (hero.attribute[ATR_MANA_MAX] <= 30) //Jeśli hero max mana jest mniejsz bądź równe 30
|| (NONE_9999_Toworish.attribute[ATR_HITPOINTS] >= 200) //Lub jeśli nasz npc ma więcej bądź równo 200 hp
// poniższe warunki nie spełnią się dopuki te dwa nie będą niespełnione, czyli jeśli hero będzie miał mniej niż 30 max many
// i jesli hp naszego npc nie będzie mniejsze niż 200
{
B_ReadySpell (NONE_9999_Toworish, SPL_FireBolt, SPL_Cost_FireBolt); //To używa czaru ognistej strzały
return TRUE; //Że potwierdzone info
}
if (Hero.guild == GIL_KDW) // Jeśli hero jest Magiem wody/spełni się dopiero jak dwa wyższe będa niestełnione
{
B_ReadySpell (NONE_9999_Toworish, SPL_InstantFireball, SPL_Cost_InstantFireball); //To npc się nie pierdoli i używa kuli ognia
return TRUE; //Że potwierdzone info
}
if (Hero.guild == GIL_KDF) //Jeśli hero to Mag Ognia
{
B_ReadySpell (NONE_9999_Toworish, SPL_Icelance, SPL_Cost_Icelance); //To npc używa czaru Lodowej lancy
return TRUE; //potwierdzone
}
if (NONE_9999_Toworish.attribute[ATR_HITPOINTS] <= 50) //jeśli nasz npc ma mniej bądź równo 50 hp
&& (NONE_9999_Toworish.attribute[ATR_HITPOINTS] > 10)//ale tylko jeśli ma więcej niż 10 aby argument niżej się wykonał.
{
B_ReadySpell (NONE_9999_Toworish, SPL_Skull, SPL_Cost_Skull); // To wali skullem
return TRUE;
}
if (NONE_9999_Toworish.attribute[ATR_HITPOINTS] == 10) //jeśli nasz npc ma równo 10 hp
{
B_ReadySpell (NONE_9999_Toworish, SPL_SuckEnergy, SPL_Cost_SuckEnergy); // To ssie naszą energię/ tylko przykład, ten czar jest stworzony dla hero, aby działał dla npc trzeba by było go przerobić
return TRUE;
};
};
Dodam tylko że można użyć multum warunków wszystko zależne od wyobraźni, można zrobić nawet warunek że jeśli jakiś tam npc w świecie gry ma ileśtam hp to nasz npc używa danego czaru.
Btw chciałem zrobić żeby npc się cofał o krok za każdym razem gdy zmienia czar, ale zapomniałem warunku xd może ktoś z modderów przeczyta i napisze
