1
Skrypty / System nauki walki bronią i atrybutów z G2NK w G1
« dnia: 2016-01-19, 17:00 »
Obydwa systemy przeniesiemy wprost ze skryptów G2NK, lekko je dostosowując tak by działały pod Gothic 1.
Dobrze jest mieć skrypty z G2nk gdzieś pod ręką, aczkolwiek nie jest to konieczne, jeśli chce się korzystać tylko z tego samouczka.
1. Część pierwsza - walka bronią
Zacznijmy od porównania jak wyglądają obydwa systemy nauki w g1 i g2nk.
System walki broniami w G1 jest trzystopniowy. Gracz zaczyna od zera z poziomem "brak" i może awansować na poziom "adept" oraz "mistrz" poprzez bezpośrednie wyuczenie się tych poziomów u NPC. Każdy z poziomów posiada odmienne animacje ataku oraz sztywno przydzieloną szansę na uderzenie krytyczne.
W G2NK wygląda to odmiennie. Gracz nie uczy się samych poziomów, lecz podnosi swą biegłość w używaniu danego rodzaju broni wyrażonej w procentowej szansie na obrażenia krytyczne. Po osiągnięciu odpowiednio wysokiej wartości gra automatycznie ustawia bohaterowi kolejny poziom. Tych podobnie jak w G1 jest trzy i również odpowiadają za animacje ataku, noszą jednak lekko odmienne nazwy (np. zielony, wojownik, mistrz). Gracz startuje z 10% szansą na trafienie krytyczne w każdym rodzaju broni, a gra automatycznie awansuje nas na drugi poziom po osiągnięciu 30% biegłości, oraz na trzeci - przy progu 60%. Progi to kolejna znacząca różnica pomiędzy G1, a G2nk. Przechodząc do rzeczy, istnieją 3 progi, od których zależny jest koszt Punktów Nauki (PN) jaki wydamy na 1% w biegłości danej broni. Do 30% biegłości: 1% = 1PN, od 30% do 60%: 1% = 2PN, od 60% do 90%: 1% = 3PN, od 90%: 1% = 4PN. Można by pociągnąć to jeszcze wyżej jednak osiągnięcie 100% biegłości jest zazwyczaj limitem.
Część teoretyczna za nami, a przed nami zadanie by przenieść to co wyżej zostało opisane do G1.
Interesuje nas kilka funkcji, pierwsza z nich nosi nazwę B_TeachFightTalentPercent. Otwieramy plik ze skryptów G2NK: Story\B_Story\B_TeachFighTalentPercent.d i kopiujemy naszą funkcję.
Wklejamy ją do skryptów G1 (ja umieściłem ją w pliku Story\B\B_GiveSkill.d, ale jeśli chcemy można utworzyć osobny plik na tą funkcję).
Pierwszym co edytujemy są linijki:
w G1 Hitchance nie istnieje, zmieniamy je więc na Npc_GetTalentValue (funkcja, która pobiera "wysokość skilla" danej umiejętności):
Następna rzecz, którą zmieniamy są linijki:
na:
Stała z tekstem PRINT_NoLearnOverPersonalMAX występuje tylko w G2, dlatego musimy albo dodać ją sami albo użyć w jej miejscu podobnej stałej z G1. Można też wpisać po prostu tekst w cudzysłowiu (ten sposób jest zaprezentowany na przykładzie).
Podobnie ma się sprawa ze stałą definiującą czcionkę. FONT_Screen nie występuje w G1 dlatego, od razu użyłem bezpośredniej nazwy czcionki "FONT_OLD_20_WHITE.TGA".
Z resztą przeniesionych stałych postępujemy podobnie.
Przejdźmy teraz do części funkcji odpowiedzialnej za podnoszenie umiejętności broni. Za przykład weźmy broń jednoręczną, pozostałe rodzaje broni zedytujemy analogicznie.
Widzimy, że do procentowego podnoszenia biegłości w danej broni używana jest kolejna funkcja: B_RaiseFightTalent. Oczywiście funkcja nie istnieje w G1, a przeniesienie jej było by trudne gdyż bazuje na nieobecnych w g1 aivarach. Dlatego posłużymy się obecną w G1 funkcją Npc_SetTalentValue.
Zastępujemy linijkę:
Teraz musimy edytować warunek, odpowiedzialny za automatyczny trening dwóch broni naraz. Zastępujemy linijkę:
Potem analogicznie jak przedtem:
Znów dodajemy stałą z tekstem lub dopisujemy tekst sami, zmieniając:
oraz
To jednak jeszcze nie wszystko. Teraz musimy zadbać o to, aby zależnie od wartości procentowej w umiejętności, gra odpowiednio zwiększała jej poziom (zielony, wojownik, adept). Do tego celu dodamy nową funkcję B_SetFightSkill (wzorowana na podobnej funkcji z g2notr B_AddFightSkill).
Jak widać, funkcja sprawdza obecną wartość umiejętności i w zależności pod jaki próg się kwalifikuje, ustawia skill od 0, 1, 2 (czyli dla broni jednoręcznej będzie to odpowiednio: zielony, wojownik, mistrz).
Wracamy więc do naszej pierwszej funkcji (B_TeachFightTalentPercent) i do warunku odpowiedzialnego za broń jednoręczną dodajemy na końcu:
Teraz po osiągnięciu 30% automatycznie powinniśmy uzyskać wojownika wraz ze zmienionymi animacjami ataku.
Pamiętajmy jednak, że w systemie nauki z nocy kruka istnieje możliwość nauki dwóch broni równocześnie, dlatego musimy wywołać funkcję jeszcze w jednym miejscu, tym razem definiując jaki talent ma podnieść (automatycznie wykrywany jest jedynie talent glowny, którego się uczymy):
Całość odpowiedzialna za naukę broni jednoręcznej powinna wyglądać mniej więcej tak:
Analogicznie postępujemy z pozostałymi rodzajami broni. W efekcie cała funkcja powinna wyglądać tak:
Ostatnią funkcję, którą przeniesiemy z Nocy Kruka będzie funkcja odpowiedzialna za obliczanie kosztu punktów nauki. Funkcja ta nosi nazwę: B_GetLearnCostTalent
W Nocy Kruka jest ona bardzo rozbudowana, gdyż oblicza koszt wszystkich umiejętności. Nas interesuje jedynie fragment odpowiedzialny za bronie. Oryginalna funkcja korzysta z hitchance i aivarów, więc tak jak poprzednio używamy zamiast tego funkcji z g1, Npc_GetTalentValue
Nie ma sensu tłumaczyć drugi raz tego samego, zaprezentuje więc od razu całość:
Wszystko powinno być jasne. Największa część pracy za nami. Teraz pozostało tylko parę szczegołów.
Musimy zmienić nazwy stopni władania bronią. Gothic 1 miał domyślnie ustawione dla wszystkich czterech rodzaji broni takie same poziomy brak, adept, mistrz. W g2 wygląda to inaczej. Otwieramy więc plik story\text.d i odnajdujemy linijkę: const string TXT_TALENTS_SKILLS[12]
Poniżej powinniśmy zobaczyć:
Pierwszą pozycję zostawiamy pustą, a kolejne zmieniamy na:
Pozostaje nam jeszcze ustawić poziom startowy umiejętności na 10% wzorem G2NK. W tym celu otwieramy plik Story\NPC\PC_Hero.d
Do instancji naszego bohatera (pierwsza z góry) dodajemy następujące linijki:
To właściwie tyle. Podam jeszcze przykład jak powinien wyglądać skrypt dialogu u trenera, wykorzystujący system nauki jaki zaimplementowaliśmy. Polecam wykorzystać do tego character helpera, by szybko przekonać się czy wszystko gra.
Otwieramy plik AI\Test_Scripts\CharacterHelper.d i wklejamy poniższy kod.
Następnie kompilujemy skrypty, odpalamy nową grę, włączamy konsole i przyzywamy character helpera komendą: "insert CH".
Ustawiamy sobie jeszcze Punkty Nauki (wpisujemy edit abilities w konsoli, a potem lp = 60), po czym rozmawiamy z przyzwaną postacią. Wybieramy dialog "TALENT: Walka Notr" i sprawdzamy jak działa system walki, który zaimplementowaliśmy.
2. Część druga - atrybuty
Część pierwsza za nami, teraz pora na część drugą, czyli przeniesienie systemu nauki atrybutów. Interesuje nas funkcja B_TeachAttributePoints, w nocy kruka wygląda ona tak:
Kopiujemy ją i umieszczamy np. w story\b\b_buyattributepoints.d
Nie musimy tutaj za dużo zmieniać, interesują nas stałe, odpowiadające za wyswietlany tekst oraz wywołanie funkcji B_RaiseAttribute.
Ta co prawda wystepuje już w G1, jednak rózni się nieco od tej z g2, dlatego najlepiej będzie jesli zamiast ją zastępowac, bądź edytować dodamy drugą o lekko zmienionej nazwie, powiedzmy B_RaiseAttribute_Gothic2
Zmieńmy więc jej nazwę w funkcji b_buyattributepoints:
I przejdzmy do funkcji B_RaiseAttribute.
Tu również zmieniamy jej nazwę na B_RaiseAttribute_Gothic2. Widzimy też, że wywoluje ona kolejna funkcje B_raiserealattributelearncounter.
Służy ona do liczenia prawdziwych wartości atrybutów (bez bonusów), jedak z racji tego, że opiera się ona na aivarach z g2, my z niej zrezygnujemy i będziemy opierać się po prostu na obecnych statystykach gracza.
Niestety rozwiązanie ten ma tę wadę, że w przypadku, gdy gracz założony będzie mieć przedmiot podnoszący atrybut, gra nie będzie w stanie rozróżnić, jaką wartość ma tenże atrybut "na czysto" (bez dodatkowego bonusu), co będzie skutkować w obliczaniu progów wliczając w nie dodatkowy bonus. Jeśli bardzo chcemy problem ten można oczywiście ominąć, np. wprowadzając własne zmienne i licząc na nich osobno aytrubuty przy nauce, ale to już zostawiam chętnym do własnej realizacji.
My nie będziemy sobie tutaj tego komplikować i z poprawiania tej funkcji po prostu zrezygnujemy.
Usuwamy więc (bądź zakomentowujemy) wywolanie funkcji B_RaiseRealAttributeLearnCounter. Tradycyjnie znowu też poprawiamy zmienne odpowiedzialne za tekst.
Usuwamy też warunek odpowiedzialny za automatyczną naukę akrobatyki po osiągnięciu 90 zręczności (chyba, że chcemy by tak to zostało) i otrzymujemy:
Następnie dodajemy funkcję liczącą koszt Pn atrybutów: B_GetLearnCostAttribute
W funkcji tej musimy pozmieniac wszystkie linijki zawierające odniesienia do aivarów określających prawdziwą wartość atrybutu, czyli np.
zmieniamy na :
Po poprawieniu wszystkich linijek powinniśmy mieć taki fragment kodu:
I to w zasadzie wszystko. Podobnie jak poprzednio podam jeszcze przyklad wykorzystanie systemu nauki w dialogu trenera. Znów posłużymy się do tego celu character helperem.
Dobrze jest mieć skrypty z G2nk gdzieś pod ręką, aczkolwiek nie jest to konieczne, jeśli chce się korzystać tylko z tego samouczka.
1. Część pierwsza - walka bronią
Zacznijmy od porównania jak wyglądają obydwa systemy nauki w g1 i g2nk.
System walki broniami w G1 jest trzystopniowy. Gracz zaczyna od zera z poziomem "brak" i może awansować na poziom "adept" oraz "mistrz" poprzez bezpośrednie wyuczenie się tych poziomów u NPC. Każdy z poziomów posiada odmienne animacje ataku oraz sztywno przydzieloną szansę na uderzenie krytyczne.
W G2NK wygląda to odmiennie. Gracz nie uczy się samych poziomów, lecz podnosi swą biegłość w używaniu danego rodzaju broni wyrażonej w procentowej szansie na obrażenia krytyczne. Po osiągnięciu odpowiednio wysokiej wartości gra automatycznie ustawia bohaterowi kolejny poziom. Tych podobnie jak w G1 jest trzy i również odpowiadają za animacje ataku, noszą jednak lekko odmienne nazwy (np. zielony, wojownik, mistrz). Gracz startuje z 10% szansą na trafienie krytyczne w każdym rodzaju broni, a gra automatycznie awansuje nas na drugi poziom po osiągnięciu 30% biegłości, oraz na trzeci - przy progu 60%. Progi to kolejna znacząca różnica pomiędzy G1, a G2nk. Przechodząc do rzeczy, istnieją 3 progi, od których zależny jest koszt Punktów Nauki (PN) jaki wydamy na 1% w biegłości danej broni. Do 30% biegłości: 1% = 1PN, od 30% do 60%: 1% = 2PN, od 60% do 90%: 1% = 3PN, od 90%: 1% = 4PN. Można by pociągnąć to jeszcze wyżej jednak osiągnięcie 100% biegłości jest zazwyczaj limitem.
Część teoretyczna za nami, a przed nami zadanie by przenieść to co wyżej zostało opisane do G1.
Interesuje nas kilka funkcji, pierwsza z nich nosi nazwę B_TeachFightTalentPercent. Otwieramy plik ze skryptów G2NK: Story\B_Story\B_TeachFighTalentPercent.d i kopiujemy naszą funkcję.
Kod: [Zaznacz]
func int B_TeachFightTalentPercent(var C_Npc slf,var C_Npc oth,var int talent,var int percent,var int teacherMAX)
{
var string concatText;
var int kosten;
var int realHitChance;
kosten = B_GetLearnCostTalent(oth,talent,1) * percent;
if((talent != NPC_TALENT_1H) && (talent != NPC_TALENT_2H) && (talent != NPC_TALENT_BOW) && (talent != NPC_TALENT_CROSSBOW))
{
Print("*** Błąd: Zły parametr ***");
return FALSE;
};
if(talent == NPC_TALENT_1H)
{
realHitChance = oth.HitChance[NPC_TALENT_1H];
}
else if(talent == NPC_TALENT_2H)
{
realHitChance = oth.HitChance[NPC_TALENT_2H];
}
else if(talent == NPC_TALENT_BOW)
{
realHitChance = oth.HitChance[NPC_TALENT_BOW];
}
else if(talent == NPC_TALENT_CROSSBOW)
{
realHitChance = oth.HitChance[NPC_TALENT_CROSSBOW];
};
if(realHitChance >= teacherMAX)
{
concatText = ConcatStrings(PRINT_NoLearnOverPersonalMAX,IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,FONT_Screen,2);
B_Say(slf,oth,"$NOLEARNYOUREBETTER");
return FALSE;
};
if((realHitChance + percent) > teacherMAX)
{
concatText = ConcatStrings(PRINT_NoLearnOverPersonalMAX,IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,FONT_Screen,2);
B_Say(slf,oth,"$NOLEARNOVERPERSONALMAX");
return FALSE;
};
if(oth.lp < kosten)
{
PrintScreen(PRINT_NotEnoughLP,-1,-1,FONT_Screen,2);
B_Say(slf,oth,"$NOLEARNNOPOINTS");
return FALSE;
};
oth.lp = oth.lp - kosten;
if(talent == NPC_TALENT_1H)
{
B_RaiseFightTalent(oth,NPC_TALENT_1H,percent);
if(oth.aivar[REAL_TALENT_1H] >= (oth.aivar[REAL_TALENT_2H] + 30))
{
B_RaiseFightTalent(oth,NPC_TALENT_2H,percent);
PrintScreen(PRINT_Learn1H_and_2H,-1,-1,FONT_Screen,2);
}
else
{
PrintScreen(PRINT_Learn1H,-1,-1,FONT_Screen,2);
};
return TRUE;
};
if(talent == NPC_TALENT_2H)
{
B_RaiseFightTalent(oth,NPC_TALENT_2H,percent);
if(oth.aivar[REAL_TALENT_2H] >= (oth.aivar[REAL_TALENT_1H] + 30))
{
B_RaiseFightTalent(oth,NPC_TALENT_1H,percent);
PrintScreen(PRINT_Learn2H_and_1H,-1,-1,FONT_Screen,2);
}
else
{
PrintScreen(PRINT_Learn2H,-1,-1,FONT_Screen,2);
};
return TRUE;
};
if(talent == NPC_TALENT_BOW)
{
B_RaiseFightTalent(oth,NPC_TALENT_BOW,percent);
if(oth.aivar[REAL_TALENT_BOW] >= (oth.aivar[REAL_TALENT_CROSSBOW] + 30))
{
B_RaiseFightTalent(oth,NPC_TALENT_CROSSBOW,percent);
PrintScreen(PRINT_LearnBow_and_Crossbow,-1,-1,FONT_Screen,2);
}
else
{
PrintScreen(PRINT_LearnBow,-1,-1,FONT_Screen,2);
};
return TRUE;
};
if(talent == NPC_TALENT_CROSSBOW)
{
B_RaiseFightTalent(oth,NPC_TALENT_CROSSBOW,percent);
if(oth.aivar[REAL_TALENT_CROSSBOW] >= (oth.aivar[REAL_TALENT_BOW] + 30))
{
B_RaiseFightTalent(oth,NPC_TALENT_BOW,percent);
PrintScreen(PRINT_LearnCrossbow_and_Bow,-1,-1,FONT_Screen,2);
}
else
{
PrintScreen(PRINT_LearnCrossbow,-1,-1,FONT_Screen,2);
};
return TRUE;
};
};
Wklejamy ją do skryptów G1 (ja umieściłem ją w pliku Story\B\B_GiveSkill.d, ale jeśli chcemy można utworzyć osobny plik na tą funkcję).
Pierwszym co edytujemy są linijki:
Kod: [Zaznacz]
realHitChance = oth.HitChance[NPC_TALENT_1H];
realHitChance = oth.HitChance[NPC_TALENT_2H];
realHitChance = oth.HitChance[NPC_TALENT_BOW];
realHitChance = oth.HitChance[NPC_TALENT_CROSSBOW];
w G1 Hitchance nie istnieje, zmieniamy je więc na Npc_GetTalentValue (funkcja, która pobiera "wysokość skilla" danej umiejętności):
Kod: [Zaznacz]
realHitChance = Npc_GetTalentValue(hero,NPC_TALENT_1H);
realHitChance = Npc_GetTalentValue(hero,NPC_TALENT_2H);
realHitChance = Npc_GetTalentValue(hero,NPC_TALENT_BOW);
realHitChance = Npc_GetTalentValue(hero,NPC_TALENT_CROSSBOW);
Następna rzecz, którą zmieniamy są linijki:
Kod: [Zaznacz]
concatText = ConcatStrings(PRINT_NoLearnOverPersonalMAX,IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,FONT_Screen,2);
na:
Kod: [Zaznacz]
concatText = ConcatStrings("Maksimum dla tego nauczyciela wynosi ",IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,"FONT_OLD_20_WHITE.TGA",2);
Stała z tekstem PRINT_NoLearnOverPersonalMAX występuje tylko w G2, dlatego musimy albo dodać ją sami albo użyć w jej miejscu podobnej stałej z G1. Można też wpisać po prostu tekst w cudzysłowiu (ten sposób jest zaprezentowany na przykładzie).
Podobnie ma się sprawa ze stałą definiującą czcionkę. FONT_Screen nie występuje w G1 dlatego, od razu użyłem bezpośredniej nazwy czcionki "FONT_OLD_20_WHITE.TGA".
Z resztą przeniesionych stałych postępujemy podobnie.
Przejdźmy teraz do części funkcji odpowiedzialnej za podnoszenie umiejętności broni. Za przykład weźmy broń jednoręczną, pozostałe rodzaje broni zedytujemy analogicznie.
Kod: [Zaznacz]
if(talent == NPC_TALENT_1H)
{
B_RaiseFightTalent(oth,NPC_TALENT_1H,percent);
if(oth.aivar[REAL_TALENT_1H] >= (oth.aivar[REAL_TALENT_2H] + 30))
{
B_RaiseFightTalent(oth,NPC_TALENT_2H,percent);
PrintScreen(PRINT_Learn1H_and_2H,-1,-1,FONT_Screen,2);
}
else
{
PrintScreen(PRINT_Learn1H,-1,-1,FONT_Screen,2);
};
return TRUE;
};
Widzimy, że do procentowego podnoszenia biegłości w danej broni używana jest kolejna funkcja: B_RaiseFightTalent. Oczywiście funkcja nie istnieje w G1, a przeniesienie jej było by trudne gdyż bazuje na nieobecnych w g1 aivarach. Dlatego posłużymy się obecną w G1 funkcją Npc_SetTalentValue.
Zastępujemy linijkę:
Kod: [Zaznacz]
B_RaiseFightTalent(oth,NPC_TALENT_1H,percent);
na:Kod: [Zaznacz]
Npc_SetTalentValue(hero, NPC_TALENT_1H, Npc_GetTalentValue(hero, NPC_TALENT_1H)+percent);
Teraz musimy edytować warunek, odpowiedzialny za automatyczny trening dwóch broni naraz. Zastępujemy linijkę:
Kod: [Zaznacz]
if(oth.aivar[REAL_TALENT_1H] >= (oth.aivar[REAL_TALENT_2H] + 30))
na:Kod: [Zaznacz]
if(Npc_GetTalentValue(hero,NPC_TALENT_1H) >= (Npc_GetTalentValue(hero,NPC_TALENT_2H) +30))
Potem analogicznie jak przedtem:
Kod: [Zaznacz]
B_RaiseFightTalent(oth,NPC_TALENT_2H,percent);
na:Kod: [Zaznacz]
Npc_SetTalentValue(hero, NPC_TALENT_2H, Npc_GetTalentValue(hero, NPC_TALENT_2H)+percent);
Znów dodajemy stałą z tekstem lub dopisujemy tekst sami, zmieniając:
Kod: [Zaznacz]
PrintScreen(PRINT_Learn1H_and_2H,-1,-1,FONT_Screen,2);
na:Kod: [Zaznacz]
PrintScreen("Trening: posługiwanie się bronią jedno- i dwuręczną", -1,10,"FONT_OLD_20_WHITE.TGA",2);
oraz
Kod: [Zaznacz]
PrintScreen(PRINT_Learn1H,-1,-1,FONT_Screen,2);
na:Kod: [Zaznacz]
PrintScreen("Trening: posługiwanie się bronią jednoręczną", -1,10,"FONT_OLD_20_WHITE.TGA",2);
To jednak jeszcze nie wszystko. Teraz musimy zadbać o to, aby zależnie od wartości procentowej w umiejętności, gra odpowiednio zwiększała jej poziom (zielony, wojownik, adept). Do tego celu dodamy nową funkcję B_SetFightSkill (wzorowana na podobnej funkcji z g2notr B_AddFightSkill).
Kod: [Zaznacz]
func void B_SetFightSkill(var C_Npc slf,var int talent,var int percent)
{
if(talent == NPC_TALENT_1H)
{
if(Npc_GetTalentValue(hero,NPC_TALENT_1H) >= 0)
{
Npc_SetTalentSkill(slf,NPC_TALENT_1H,0);
};
if(Npc_GetTalentValue(hero,NPC_TALENT_1H) >= 30)
{
Npc_SetTalentSkill(slf,NPC_TALENT_1H,1);
};
if(Npc_GetTalentValue(hero,NPC_TALENT_1H) >= 60)
{
Npc_SetTalentSkill(slf,NPC_TALENT_1H,2);
};
};
if(talent == NPC_TALENT_2H)
{
if(Npc_GetTalentValue(hero,NPC_TALENT_2H) >= 0)
{
Npc_SetTalentSkill(slf,NPC_TALENT_2H,0);
};
if(Npc_GetTalentValue(hero,NPC_TALENT_2H) >= 30)
{
Npc_SetTalentSkill(slf,NPC_TALENT_2H,1);
};
if(Npc_GetTalentValue(hero,NPC_TALENT_2H) >= 60)
{
Npc_SetTalentSkill(slf,NPC_TALENT_2H,2);
};
};
if(talent == NPC_TALENT_BOW)
{
if(Npc_GetTalentValue(hero,NPC_TALENT_BOW) >= 0)
{
Npc_SetTalentSkill(slf,NPC_TALENT_BOW,0);
};
if(Npc_GetTalentValue(hero,NPC_TALENT_BOW) >= 30)
{
Npc_SetTalentSkill(slf,NPC_TALENT_BOW,1);
};
if(Npc_GetTalentValue(hero,NPC_TALENT_BOW) >= 60)
{
Npc_SetTalentSkill(slf,NPC_TALENT_BOW,2);
};
};
if(talent == NPC_TALENT_CROSSBOW)
{
if(Npc_GetTalentValue(hero,NPC_TALENT_CROSSBOW) >= 0)
{
Npc_SetTalentSkill(slf,NPC_TALENT_CROSSBOW,0);
};
if(Npc_GetTalentValue(hero,NPC_TALENT_CROSSBOW) >= 30)
{
Npc_SetTalentSkill(slf,NPC_TALENT_CROSSBOW,1);
};
if(Npc_GetTalentValue(hero,NPC_TALENT_CROSSBOW) >= 60)
{
Npc_SetTalentSkill(slf,NPC_TALENT_CROSSBOW,2);
};
};
};
Jak widać, funkcja sprawdza obecną wartość umiejętności i w zależności pod jaki próg się kwalifikuje, ustawia skill od 0, 1, 2 (czyli dla broni jednoręcznej będzie to odpowiednio: zielony, wojownik, mistrz).
Wracamy więc do naszej pierwszej funkcji (B_TeachFightTalentPercent) i do warunku odpowiedzialnego za broń jednoręczną dodajemy na końcu:
Kod: [Zaznacz]
B_SetFightSkill(hero,talent,percent);
Teraz po osiągnięciu 30% automatycznie powinniśmy uzyskać wojownika wraz ze zmienionymi animacjami ataku.
Pamiętajmy jednak, że w systemie nauki z nocy kruka istnieje możliwość nauki dwóch broni równocześnie, dlatego musimy wywołać funkcję jeszcze w jednym miejscu, tym razem definiując jaki talent ma podnieść (automatycznie wykrywany jest jedynie talent glowny, którego się uczymy):
Kod: [Zaznacz]
B_SetFightSkill(hero,NPC_TALENT_2H,percent);
Całość odpowiedzialna za naukę broni jednoręcznej powinna wyglądać mniej więcej tak:
Kod: [Zaznacz]
if(talent == NPC_TALENT_1H)
{
Npc_SetTalentValue(hero, NPC_TALENT_1H, Npc_GetTalentValue(hero, NPC_TALENT_1H)+percent);
if(Npc_GetTalentValue(hero,NPC_TALENT_1H) >= (Npc_GetTalentValue(hero,NPC_TALENT_2H) +30))
{
Npc_SetTalentValue(hero, NPC_TALENT_2H, Npc_GetTalentValue(hero, NPC_TALENT_2H)+percent);
B_SetFightSkill(hero,NPC_TALENT_2H,percent);
PrintScreen ("Trening: posługiwanie się bronią jedno- i dwuręczną", -1,10,"FONT_OLD_20_WHITE.TGA",2);
}
else
{
PrintScreen ("Trening: posługiwanie się bronią jednoręczną", -1,10,"FONT_OLD_20_WHITE.TGA",2);
};
B_SetFightSkill(hero,talent,percent);
return TRUE;
};
Analogicznie postępujemy z pozostałymi rodzajami broni. W efekcie cała funkcja powinna wyglądać tak:
Kod: [Zaznacz]
func int B_TeachFightTalentPercent(var C_Npc slf,var C_Npc oth,var int talent,var int percent,var int teacherMAX)
{
var string concatText;
var int kosten;
var int realHitChance;
kosten = B_GetLearnCostTalent(oth,talent,1) * percent;
if((talent != NPC_TALENT_1H) && (talent != NPC_TALENT_2H) && (talent != NPC_TALENT_BOW) && (talent != NPC_TALENT_CROSSBOW))
{
Print("*** Błąd: Zły parametr ***");
return FALSE;
};
if(talent == NPC_TALENT_1H)
{
realHitChance = Npc_GetTalentValue(hero,NPC_TALENT_1H);
}
else if(talent == NPC_TALENT_2H)
{
realHitChance = Npc_GetTalentValue(hero,NPC_TALENT_2H);
}
else if(talent == NPC_TALENT_BOW)
{
realHitChance = Npc_GetTalentValue(hero,NPC_TALENT_BOW);
}
else if(talent == NPC_TALENT_CROSSBOW)
{
realHitChance = Npc_GetTalentValue(hero,NPC_TALENT_CROSSBOW);
};
if(realHitChance >= teacherMAX)
{
concatText = ConcatStrings("Maksimum dla tego nauczyciela wynosi ",IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,"FONT_OLD_20_WHITE.TGA",2);
B_Say(slf,oth,"$NOLEARNYOUREBETTER");
return FALSE;
};
if((realHitChance + percent) > teacherMAX)
{
concatText = ConcatStrings("Maksimum dla tego nauczyciela wynosi ",IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,"FONT_OLD_20_WHITE.TGA",2);
B_Say(slf,oth,"$NOLEARNOVERPERSONALMAX");
return FALSE;
};
if(oth.lp < kosten)
{
PrintScreen("Za mało punktów umiejętności!",-1,-1,"FONT_OLD_20_WHITE.TGA",2);
B_Say(slf,oth,"$NOLEARNNOPOINTS");
return FALSE;
};
oth.lp = oth.lp - kosten;
if(talent == NPC_TALENT_1H)
{
Npc_SetTalentValue(hero, NPC_TALENT_1H, Npc_GetTalentValue(hero, NPC_TALENT_1H)+percent);
if(Npc_GetTalentValue(hero,NPC_TALENT_1H) >= (Npc_GetTalentValue(hero,NPC_TALENT_2H) +30))
{
Npc_SetTalentValue(hero, NPC_TALENT_2H, Npc_GetTalentValue(hero, NPC_TALENT_2H)+percent);
PrintScreen("Trening: posługiwanie się bronią jedno- i dwuręczną", -1,10,"FONT_OLD_20_WHITE.TGA",2);
B_SetFightSkill(hero,NPC_TALENT_2H,percent);
}
else
{
PrintScreen("Trening: posługiwanie się bronią jednoręczną", -1,10,"FONT_OLD_20_WHITE.TGA",2);
};
B_SetFightSkill(hero,talent,percent);
return TRUE;
};
if(talent == NPC_TALENT_2H)
{
Npc_SetTalentValue(hero, NPC_TALENT_2H, Npc_GetTalentValue(hero, NPC_TALENT_2H)+percent);
if(Npc_GetTalentValue(hero,NPC_TALENT_2H) >= (Npc_GetTalentValue(hero,NPC_TALENT_1H) +30))
{
Npc_SetTalentValue(hero, NPC_TALENT_1H, Npc_GetTalentValue(hero, NPC_TALENT_1H)+percent);
B_SetFightSkill(hero,NPC_TALENT_1H,percent);
PrintScreen ("Trening: posługiwanie się bronią dwu- i jednoręczną", -1,10,"FONT_OLD_20_WHITE.TGA",2);
}
else
{
PrintScreen ("Trening: posługiwanie się bronią dwuręczną", -1,10,"FONT_OLD_20_WHITE.TGA",2);
};
B_SetFightSkill(hero,talent,percent);
return TRUE;
};
if(talent == NPC_TALENT_BOW)
{
Npc_SetTalentValue(hero, NPC_TALENT_BOW, Npc_GetTalentValue(hero, NPC_TALENT_BOW)+percent);
if(Npc_GetTalentValue(hero,NPC_TALENT_BOW) >= (Npc_GetTalentValue(hero,NPC_TALENT_CROSSBOW) +30))
{
Npc_SetTalentValue(hero, NPC_TALENT_CROSSBOW, Npc_GetTalentValue(hero, NPC_TALENT_CROSSBOW)+percent);
PrintScreen ("Trening: posługiwanie się łukiem i kuszą", -1,10,"FONT_OLD_20_WHITE.TGA",2);
B_SetFightSkill(hero,NPC_TALENT_CROSSBOW,percent);
}
else
{
PrintScreen ("Trening: posługiwanie się łukiem", -1,10,"FONT_OLD_20_WHITE.TGA",2);
};
B_SetFightSkill(hero,talent,percent);
return TRUE;
};
if(talent == NPC_TALENT_CROSSBOW)
{
Npc_SetTalentValue(hero, NPC_TALENT_CROSSBOW, Npc_GetTalentValue(hero, NPC_TALENT_CROSSBOW)+percent);
if(Npc_GetTalentValue(hero,NPC_TALENT_CROSSBOW) >= (Npc_GetTalentValue(hero,NPC_TALENT_BOW) +30))
{
Npc_SetTalentValue(hero, NPC_TALENT_BOW, Npc_GetTalentValue(hero, NPC_TALENT_BOW)+percent);
B_SetFightSkill(hero,NPC_TALENT_BOW,percent);
PrintScreen ("Trening: posługiwanie się kuszą i łukiem", -1,10,"FONT_OLD_20_WHITE.TGA",2);
}
else
{
PrintScreen ("Trening: posługiwanie się kuszą", -1,10,"FONT_OLD_20_WHITE.TGA",2);
};
B_SetFightSkill(hero,talent,percent);
return TRUE;
};
};
Ostatnią funkcję, którą przeniesiemy z Nocy Kruka będzie funkcja odpowiedzialna za obliczanie kosztu punktów nauki. Funkcja ta nosi nazwę: B_GetLearnCostTalent
W Nocy Kruka jest ona bardzo rozbudowana, gdyż oblicza koszt wszystkich umiejętności. Nas interesuje jedynie fragment odpowiedzialny za bronie. Oryginalna funkcja korzysta z hitchance i aivarów, więc tak jak poprzednio używamy zamiast tego funkcji z g1, Npc_GetTalentValue
Nie ma sensu tłumaczyć drugi raz tego samego, zaprezentuje więc od razu całość:
Kod: [Zaznacz]
func int B_GetLearnCostTalent(var C_Npc oth,var int talent,var int skill)
{
var int kosten;
kosten = 0;
if(talent == NPC_TALENT_1H)
{
if(Npc_GetTalentValue(hero,NPC_TALENT_1H) >= 90)
{
kosten = 4;
}
else if(Npc_GetTalentValue(hero,NPC_TALENT_1H) >= 60)
{
kosten = 3;
}
else if(Npc_GetTalentValue(hero,NPC_TALENT_1H) >= 30)
{
kosten = 2;
}
else
{
kosten = 1;
};
kosten = kosten * skill;
};
if(talent == NPC_TALENT_2H)
{
if(Npc_GetTalentValue(hero,NPC_TALENT_2H) >= 90)
{
kosten = 4;
}
else if(Npc_GetTalentValue(hero,NPC_TALENT_2H) >= 60)
{
kosten = 3;
}
else if(Npc_GetTalentValue(hero,NPC_TALENT_2H) >= 30)
{
kosten = 2;
}
else
{
kosten = 1;
};
kosten = kosten * skill;
};
if(talent == NPC_TALENT_BOW)
{
if(Npc_GetTalentValue(hero,NPC_TALENT_BOW) >= 90)
{
kosten = 4;
}
else if(Npc_GetTalentValue(hero,NPC_TALENT_BOW) >= 60)
{
kosten = 3;
}
else if(Npc_GetTalentValue(hero,NPC_TALENT_BOW) >= 30)
{
kosten = 2;
}
else
{
kosten = 1;
};
kosten = kosten * skill;
};
if(talent == NPC_TALENT_CROSSBOW)
{
if(Npc_GetTalentValue(hero,NPC_TALENT_CROSSBOW) >= 90)
{
kosten = 4;
}
else if(Npc_GetTalentValue(hero,NPC_TALENT_CROSSBOW) >= 60)
{
kosten = 3;
}
else if(Npc_GetTalentValue(hero,NPC_TALENT_CROSSBOW) >= 30)
{
kosten = 2;
}
else
{
kosten = 1;
};
kosten = kosten * skill;
};
return kosten;
};
Wszystko powinno być jasne. Największa część pracy za nami. Teraz pozostało tylko parę szczegołów.
Musimy zmienić nazwy stopni władania bronią. Gothic 1 miał domyślnie ustawione dla wszystkich czterech rodzaji broni takie same poziomy brak, adept, mistrz. W g2 wygląda to inaczej. Otwieramy więc plik story\text.d i odnajdujemy linijkę: const string TXT_TALENTS_SKILLS[12]
Poniżej powinniśmy zobaczyć:
Kod: [Zaznacz]
"",
"brak|adept|mistrz",
"brak|adept|mistrz",
"brak|adept|mistrz",
"brak|adept|mistrz",
Pierwszą pozycję zostawiamy pustą, a kolejne zmieniamy na:
Kod: [Zaznacz]
"",
"Zielony|Wojownik|Mistrz",
"Zielony|Wojownik|Mistrz",
"Zielony|Łucznik|Mistrz",
"Zielony|Kusznik|Mistrz",
Pozostaje nam jeszcze ustawić poziom startowy umiejętności na 10% wzorem G2NK. W tym celu otwieramy plik Story\NPC\PC_Hero.d
Do instancji naszego bohatera (pierwsza z góry) dodajemy następujące linijki:
Kod: [Zaznacz]
Npc_SetTalentValue(self, NPC_TALENT_1H,10);
Npc_SetTalentValue(self, NPC_TALENT_2H,10);
Npc_SetTalentValue(self, NPC_TALENT_BOW,10);
Npc_SetTalentValue(self, NPC_TALENT_CROSSBOW,10);
To właściwie tyle. Podam jeszcze przykład jak powinien wyglądać skrypt dialogu u trenera, wykorzystujący system nauki jaki zaimplementowaliśmy. Polecam wykorzystać do tego character helpera, by szybko przekonać się czy wszystko gra.
Otwieramy plik AI\Test_Scripts\CharacterHelper.d i wklejamy poniższy kod.
Kod: [Zaznacz]
instance CH_Training_NotRCombat(C_Info)
{
npc = ch;
condition = CH_Training_NotRCombat_Condition;
information = CH_Training_NotRCombat_Info;
important = 0;
permanent = 1;
description = "TALENT: Walka Notr";
};
func int CH_Training_NotRCombat_Condition()
{
return TRUE;
};
func void CH_Training_NotRCombat_Info()
{
Info_ClearChoices(CH_Training_NotRCombat);
Info_AddChoice(CH_Training_NotRCombat,"Wróć",CH_Training_NotRCombat_BACK);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_1H,1),0),CH_Training_NotRCombat_1H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_1H,5),0),CH_Training_NotRCombat_1H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_2H,1),0),CH_Training_NotRCombat_2H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_2H,5),0),CH_Training_NotRCombat_2H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +1",B_GetLearnCostTalent(other,NPC_TALENT_BOW,1),0),CH_Training_NotRCombat_Bow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +5",B_GetLearnCostTalent(other,NPC_TALENT_BOW,5),0),CH_Training_NotRCombat_Bow_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +1",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,1),0),CH_Training_NotRCombat_Crossbow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +5",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,5),0),CH_Training_NotRCombat_Crossbow_5);
};
func void CH_Training_NotRCombat_1H_1()
{
B_TeachFightTalentPercent(self,other,NPC_TALENT_1H,1,100);
Info_ClearChoices(CH_Training_NotRCombat);
Info_AddChoice(CH_Training_NotRCombat,Dialog_Back,CH_Training_NotRCombat_Back);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_1H,1),0),CH_Training_NotRCombat_1H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_1H,5),0),CH_Training_NotRCombat_1H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_2H,1),0),CH_Training_NotRCombat_2H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_2H,5),0),CH_Training_NotRCombat_2H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +1",B_GetLearnCostTalent(other,NPC_TALENT_BOW,1),0),CH_Training_NotRCombat_Bow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +5",B_GetLearnCostTalent(other,NPC_TALENT_BOW,5),0),CH_Training_NotRCombat_Bow_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +1",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,1),0),CH_Training_NotRCombat_Crossbow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +5",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,5),0),CH_Training_NotRCombat_Crossbow_5);
};
func void CH_Training_NotRCombat_1H_5()
{
B_TeachFightTalentPercent(self,other,NPC_TALENT_1H,5,100);
Info_ClearChoices(CH_Training_NotRCombat);
Info_AddChoice(CH_Training_NotRCombat,Dialog_Back,CH_Training_NotRCombat_Back);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_1H,1),0),CH_Training_NotRCombat_1H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_1H,5),0),CH_Training_NotRCombat_1H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_2H,1),0),CH_Training_NotRCombat_2H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_2H,5),0),CH_Training_NotRCombat_2H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +1",B_GetLearnCostTalent(other,NPC_TALENT_BOW,1),0),CH_Training_NotRCombat_Bow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +5",B_GetLearnCostTalent(other,NPC_TALENT_BOW,5),0),CH_Training_NotRCombat_Bow_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +1",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,1),0),CH_Training_NotRCombat_Crossbow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +5",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,5),0),CH_Training_NotRCombat_Crossbow_5);
};
func void CH_Training_NotRCombat_2H_1()
{
B_TeachFightTalentPercent(self,other,NPC_TALENT_2H,1,100);
Info_ClearChoices(CH_Training_NotRCombat);
Info_AddChoice(CH_Training_NotRCombat,Dialog_Back,CH_Training_NotRCombat_Back);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_1H,1),0),CH_Training_NotRCombat_1H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_1H,5),0),CH_Training_NotRCombat_1H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_2H,1),0),CH_Training_NotRCombat_2H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_2H,5),0),CH_Training_NotRCombat_2H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +1",B_GetLearnCostTalent(other,NPC_TALENT_BOW,1),0),CH_Training_NotRCombat_Bow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +5",B_GetLearnCostTalent(other,NPC_TALENT_BOW,5),0),CH_Training_NotRCombat_Bow_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +1",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,1),0),CH_Training_NotRCombat_Crossbow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +5",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,5),0),CH_Training_NotRCombat_Crossbow_5);
};
func void CH_Training_NotRCombat_2H_5()
{
B_TeachFightTalentPercent(self,other,NPC_TALENT_2H,5,100);
Info_ClearChoices(CH_Training_NotRCombat);
Info_AddChoice(CH_Training_NotRCombat,Dialog_Back,CH_Training_NotRCombat_Back);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_1H,1),0),CH_Training_NotRCombat_1H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_1H,5),0),CH_Training_NotRCombat_1H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_2H,1),0),CH_Training_NotRCombat_2H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_2H,5),0),CH_Training_NotRCombat_2H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +1",B_GetLearnCostTalent(other,NPC_TALENT_BOW,1),0),CH_Training_NotRCombat_Bow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +5",B_GetLearnCostTalent(other,NPC_TALENT_BOW,5),0),CH_Training_NotRCombat_Bow_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +1",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,1),0),CH_Training_NotRCombat_Crossbow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +5",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,5),0),CH_Training_NotRCombat_Crossbow_5);
};
func void CH_Training_NotRCombat_Bow_1()
{
B_TeachFightTalentPercent(self,other,NPC_TALENT_BOW,1,100);
Info_ClearChoices(CH_Training_NotRCombat);
Info_AddChoice(CH_Training_NotRCombat,Dialog_Back,CH_Training_NotRCombat_Back);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_1H,1),0),CH_Training_NotRCombat_1H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_1H,5),0),CH_Training_NotRCombat_1H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_2H,1),0),CH_Training_NotRCombat_2H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_2H,5),0),CH_Training_NotRCombat_2H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +1",B_GetLearnCostTalent(other,NPC_TALENT_BOW,1),0),CH_Training_NotRCombat_Bow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +5",B_GetLearnCostTalent(other,NPC_TALENT_BOW,5),0),CH_Training_NotRCombat_Bow_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +1",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,1),0),CH_Training_NotRCombat_Crossbow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +5",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,5),0),CH_Training_NotRCombat_Crossbow_5);
};
func void CH_Training_NotRCombat_Bow_5()
{
B_TeachFightTalentPercent(self,other,NPC_TALENT_BOW,5,100);
Info_ClearChoices(CH_Training_NotRCombat);
Info_AddChoice(CH_Training_NotRCombat,Dialog_Back,CH_Training_NotRCombat_Back);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_1H,1),0),CH_Training_NotRCombat_1H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_1H,5),0),CH_Training_NotRCombat_1H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_2H,1),0),CH_Training_NotRCombat_2H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_2H,5),0),CH_Training_NotRCombat_2H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +1",B_GetLearnCostTalent(other,NPC_TALENT_BOW,1),0),CH_Training_NotRCombat_Bow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +5",B_GetLearnCostTalent(other,NPC_TALENT_BOW,5),0),CH_Training_NotRCombat_Bow_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +1",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,1),0),CH_Training_NotRCombat_Crossbow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +5",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,5),0),CH_Training_NotRCombat_Crossbow_5);
};
func void CH_Training_NotRCombat_Crossbow_1()
{
B_TeachFightTalentPercent(self,other,NPC_TALENT_CROSSBOW,1,100);
Info_ClearChoices(CH_Training_NotRCombat);
Info_AddChoice(CH_Training_NotRCombat,Dialog_Back,CH_Training_NotRCombat_Back);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_1H,1),0),CH_Training_NotRCombat_1H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_1H,5),0),CH_Training_NotRCombat_1H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_2H,1),0),CH_Training_NotRCombat_2H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_2H,5),0),CH_Training_NotRCombat_2H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +1",B_GetLearnCostTalent(other,NPC_TALENT_BOW,1),0),CH_Training_NotRCombat_Bow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +5",B_GetLearnCostTalent(other,NPC_TALENT_BOW,5),0),CH_Training_NotRCombat_Bow_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +1",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,1),0),CH_Training_NotRCombat_Crossbow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +5",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,5),0),CH_Training_NotRCombat_Crossbow_5);
};
func void CH_Training_NotRCombat_Crossbow_5()
{
B_TeachFightTalentPercent(self,other,NPC_TALENT_CROSSBOW,5,100);
Info_ClearChoices(CH_Training_NotRCombat);
Info_AddChoice(CH_Training_NotRCombat,Dialog_Back,CH_Training_NotRCombat_Back);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_1H,1),0),CH_Training_NotRCombat_1H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń jednoręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_1H,5),0),CH_Training_NotRCombat_1H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +1",B_GetLearnCostTalent(other,NPC_TALENT_2H,1),0),CH_Training_NotRCombat_2H_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Broń dwuręczna +5",B_GetLearnCostTalent(other,NPC_TALENT_2H,5),0),CH_Training_NotRCombat_2H_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +1",B_GetLearnCostTalent(other,NPC_TALENT_BOW,1),0),CH_Training_NotRCombat_Bow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Łuki +5",B_GetLearnCostTalent(other,NPC_TALENT_BOW,5),0),CH_Training_NotRCombat_Bow_5);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +1",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,1),0),CH_Training_NotRCombat_Crossbow_1);
Info_AddChoice(CH_Training_NotRCombat,B_BuildLearnString("Kusze +5",B_GetLearnCostTalent(other,NPC_TALENT_CROSSBOW,5),0),CH_Training_NotRCombat_Crossbow_5);
};
func void CH_Training_NotRCombat_BACK()
{
Info_ClearChoices(CH_Training_NotRCombat);
};
Następnie kompilujemy skrypty, odpalamy nową grę, włączamy konsole i przyzywamy character helpera komendą: "insert CH".
Ustawiamy sobie jeszcze Punkty Nauki (wpisujemy edit abilities w konsoli, a potem lp = 60), po czym rozmawiamy z przyzwaną postacią. Wybieramy dialog "TALENT: Walka Notr" i sprawdzamy jak działa system walki, który zaimplementowaliśmy.
2. Część druga - atrybuty
Część pierwsza za nami, teraz pora na część drugą, czyli przeniesienie systemu nauki atrybutów. Interesuje nas funkcja B_TeachAttributePoints, w nocy kruka wygląda ona tak:
Kod: [Zaznacz]
func int B_TeachAttributePoints(var C_Npc slf,var C_Npc oth,var int attrib,var int points,var int teacherMAX)
{
var string concatText;
var int kosten;
var int realAttribute;
kosten = B_GetLearnCostAttribute(oth,attrib) * points;
if((attrib != ATR_STRENGTH) && (attrib != ATR_DEXTERITY) && (attrib != ATR_MANA_MAX))
{
Print("*** Błąd: Zły parametr ***");
return FALSE;
};
if(attrib == ATR_STRENGTH)
{
realAttribute = oth.attribute[ATR_STRENGTH];
}
else if(attrib == ATR_DEXTERITY)
{
realAttribute = oth.attribute[ATR_DEXTERITY];
}
else if(attrib == ATR_MANA_MAX)
{
realAttribute = oth.attribute[ATR_MANA_MAX];
};
if(realAttribute >= teacherMAX)
{
concatText = ConcatStrings(PRINT_NoLearnOverPersonalMAX,IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,FONT_Screen,2);
B_Say(slf,oth,"$NOLEARNYOUREBETTER");
return FALSE;
};
if((realAttribute + points) > teacherMAX)
{
concatText = ConcatStrings(PRINT_NoLearnOverPersonalMAX,IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,FONT_Screen,2);
B_Say(slf,oth,"$NOLEARNOVERPERSONALMAX");
return FALSE;
};
if(oth.lp < kosten)
{
PrintScreen(PRINT_NotEnoughLP,-1,-1,FONT_Screen,2);
B_Say(slf,oth,"$NOLEARNNOPOINTS");
return FALSE;
};
oth.lp = oth.lp - kosten;
B_RaiseAttribute(oth,attrib,points);
return TRUE;
};
Kopiujemy ją i umieszczamy np. w story\b\b_buyattributepoints.d
Nie musimy tutaj za dużo zmieniać, interesują nas stałe, odpowiadające za wyswietlany tekst oraz wywołanie funkcji B_RaiseAttribute.
Ta co prawda wystepuje już w G1, jednak rózni się nieco od tej z g2, dlatego najlepiej będzie jesli zamiast ją zastępowac, bądź edytować dodamy drugą o lekko zmienionej nazwie, powiedzmy B_RaiseAttribute_Gothic2
Zmieńmy więc jej nazwę w funkcji b_buyattributepoints:
Kod: [Zaznacz]
func int B_TeachAttributePoints(var C_Npc slf,var C_Npc oth,var int attrib,var int points,var int teacherMAX)
{
var string concatText;
var int kosten;
var int realAttribute;
kosten = B_GetLearnCostAttribute(oth,attrib) * points;
if((attrib != ATR_STRENGTH) && (attrib != ATR_DEXTERITY) && (attrib != ATR_MANA_MAX))
{
Print("*** Błąd: Zły parametr ***");
return FALSE;
};
if(attrib == ATR_STRENGTH)
{
realAttribute = oth.attribute[ATR_STRENGTH];
}
else if(attrib == ATR_DEXTERITY)
{
realAttribute = oth.attribute[ATR_DEXTERITY];
}
else if(attrib == ATR_MANA_MAX)
{
realAttribute = oth.attribute[ATR_MANA_MAX];
};
if(realAttribute >= teacherMAX)
{
concatText = ConcatStrings("Maksimum dla tego nauczyciela wynosi ",IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,"FONT_OLD_20_WHITE.TGA",2);
B_Say(slf,oth,"$NOLEARNYOUREBETTER");
return FALSE;
};
if((realAttribute + points) > teacherMAX)
{
concatText = ConcatStrings("Maksimum dla tego nauczyciela wynosi ",IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,"FONT_OLD_20_WHITE.TGA",2);
B_Say(slf,oth,"$NOLEARNOVERPERSONALMAX");
return FALSE;
};
if(oth.lp < kosten)
{
PrintScreen("Za mało Punktów Nauki!",-1,-1,"FONT_OLD_20_WHITE.TGA",2);
B_Say(slf,oth,"$NOLEARNNOPOINTS");
return FALSE;
};
oth.lp = oth.lp - kosten;
B_RaiseAttribute_Gothic2(oth,attrib,points);
return TRUE;
};
I przejdzmy do funkcji B_RaiseAttribute.
Kod: [Zaznacz]
func void B_RaiseAttribute(var C_Npc oth,var int attrib,var int points)
{
var string concatText;
if(attrib == ATR_STRENGTH)
{
oth.attribute[ATR_STRENGTH] = oth.attribute[ATR_STRENGTH] + points;
concatText = ConcatStrings(PRINT_LearnSTR,IntToString(points));
PrintScreen(concatText,-1,-1,FONT_Screen,2);
};
if(attrib == ATR_DEXTERITY)
{
oth.attribute[ATR_DEXTERITY] = oth.attribute[ATR_DEXTERITY] + points;
if((oth.attribute[ATR_DEXTERITY] >= 90) && (Npc_GetTalentSkill(oth,NPC_TALENT_ACROBAT) == 0))
{
Npc_SetTalentSkill(oth,NPC_TALENT_ACROBAT,1);
PrintScreen(PRINT_Addon_AcrobatBonus,-1,55,FONT_Screen,2);
};
concatText = ConcatStrings(PRINT_LearnDEX,IntToString(points));
PrintScreen(concatText,-1,-1,FONT_Screen,2);
};
if(attrib == ATR_MANA_MAX)
{
oth.attribute[ATR_MANA_MAX] = oth.attribute[ATR_MANA_MAX] + points;
concatText = ConcatStrings(PRINT_LearnMANA_MAX,IntToString(points));
PrintScreen(concatText,-1,-1,FONT_Screen,2);
};
if(attrib == ATR_HITPOINTS_MAX)
{
oth.attribute[ATR_HITPOINTS_MAX] = oth.attribute[ATR_HITPOINTS_MAX] + points;
concatText = ConcatStrings(PRINT_Learnhitpoints_MAX,IntToString(points));
PrintScreen(concatText,-1,-1,FONT_Screen,2);
};
B_RaiseRealAttributeLearnCounter(oth,attrib,points);
};
Tu również zmieniamy jej nazwę na B_RaiseAttribute_Gothic2. Widzimy też, że wywoluje ona kolejna funkcje B_raiserealattributelearncounter.
Służy ona do liczenia prawdziwych wartości atrybutów (bez bonusów), jedak z racji tego, że opiera się ona na aivarach z g2, my z niej zrezygnujemy i będziemy opierać się po prostu na obecnych statystykach gracza.
Niestety rozwiązanie ten ma tę wadę, że w przypadku, gdy gracz założony będzie mieć przedmiot podnoszący atrybut, gra nie będzie w stanie rozróżnić, jaką wartość ma tenże atrybut "na czysto" (bez dodatkowego bonusu), co będzie skutkować w obliczaniu progów wliczając w nie dodatkowy bonus. Jeśli bardzo chcemy problem ten można oczywiście ominąć, np. wprowadzając własne zmienne i licząc na nich osobno aytrubuty przy nauce, ale to już zostawiam chętnym do własnej realizacji.
My nie będziemy sobie tutaj tego komplikować i z poprawiania tej funkcji po prostu zrezygnujemy.
Usuwamy więc (bądź zakomentowujemy) wywolanie funkcji B_RaiseRealAttributeLearnCounter. Tradycyjnie znowu też poprawiamy zmienne odpowiedzialne za tekst.
Usuwamy też warunek odpowiedzialny za automatyczną naukę akrobatyki po osiągnięciu 90 zręczności (chyba, że chcemy by tak to zostało) i otrzymujemy:
Kod: [Zaznacz]
func void B_RaiseAttribute_Gothic2(var C_Npc oth,var int attrib,var int points)
{
var string concatText;
if(attrib == ATR_STRENGTH)
{
oth.attribute[ATR_STRENGTH] = oth.attribute[ATR_STRENGTH] + points;
concatText = ConcatStrings(NAME_RaiseStrength,IntToString(points));
PrintScreen(concatText,-1,-1,"FONT_OLD_20_WHITE.TGA",4);
};
if(attrib == ATR_DEXTERITY)
{
oth.attribute[ATR_DEXTERITY] = oth.attribute[ATR_DEXTERITY] + points;
concatText = ConcatStrings(NAME_RaiseDexterity,IntToString(points));
PrintScreen(concatText,-1,-1,"FONT_OLD_20_WHITE.TGA",4);
};
if(attrib == ATR_MANA_MAX)
{
oth.attribute[ATR_MANA_MAX] = oth.attribute[ATR_MANA_MAX] + points;
concatText = ConcatStrings(NAME_RaiseManaMax,IntToString(points));
PrintScreen(concatText,-1,-1,"FONT_OLD_20_WHITE.TGA",4);
};
if(attrib == ATR_HITPOINTS_MAX)
{
oth.attribute[ATR_HITPOINTS_MAX] = oth.attribute[ATR_HITPOINTS_MAX] + points;
concatText = ConcatStrings(NAME_RaiseHealthMax,IntToString(points));
PrintScreen(concatText,-1,-1,"FONT_OLD_20_WHITE.TGA",4);
};
//B_RaiseRealAttributeLearnCounter(oth,attrib,points);
};
Następnie dodajemy funkcję liczącą koszt Pn atrybutów: B_GetLearnCostAttribute
Kod: [Zaznacz]
func int B_GetLearnCostAttribute(var C_Npc oth,var int attribut)
{
var int kosten;
kosten = 0;
if(attribut == ATR_STRENGTH)
{
if(oth.aivar[REAL_STRENGTH] >= 120)
{
kosten = 5;
}
else if(oth.aivar[REAL_STRENGTH] >= 90)
{
kosten = 4;
}
else if(oth.aivar[REAL_STRENGTH] >= 60)
{
kosten = 3;
}
else if(oth.aivar[REAL_STRENGTH] >= 30)
{
kosten = 2;
}
else
{
kosten = 1;
};
};
if(attribut == ATR_DEXTERITY)
{
if(oth.aivar[REAL_DEXTERITY] >= 120)
{
kosten = 5;
}
else if(oth.aivar[REAL_DEXTERITY] >= 90)
{
kosten = 4;
}
else if(oth.aivar[REAL_DEXTERITY] >= 60)
{
kosten = 3;
}
else if(oth.aivar[REAL_DEXTERITY] >= 30)
{
kosten = 2;
}
else
{
kosten = 1;
};
};
if(attribut == ATR_MANA_MAX)
{
if(oth.aivar[REAL_MANA_MAX] >= 120)
{
kosten = 5;
}
else if(oth.aivar[REAL_MANA_MAX] >= 90)
{
kosten = 4;
}
else if(oth.aivar[REAL_MANA_MAX] >= 60)
{
kosten = 3;
}
else if(oth.aivar[REAL_MANA_MAX] >= 30)
{
kosten = 2;
}
else
{
kosten = 1;
};
};
return kosten;
};
W funkcji tej musimy pozmieniac wszystkie linijki zawierające odniesienia do aivarów określających prawdziwą wartość atrybutu, czyli np.
Kod: [Zaznacz]
if(oth.aivar[REAL_STRENGTH] >= 120)
zmieniamy na :
Kod: [Zaznacz]
if(oth.attribute[ATR_STRENGTH] >= 120)
Po poprawieniu wszystkich linijek powinniśmy mieć taki fragment kodu:
Kod: [Zaznacz]
func int B_GetLearnCostAttribute(var C_Npc oth,var int attribut)
{
var int kosten;
kosten = 0;
if(attribut == ATR_STRENGTH)
{
if(oth.attribute[ATR_STRENGTH] >= 120)
{
kosten = 5;
}
else if(oth.attribute[ATR_STRENGTH] >= 90)
{
kosten = 4;
}
else if(oth.attribute[ATR_STRENGTH] >= 60)
{
kosten = 3;
}
else if(oth.attribute[ATR_STRENGTH] >= 30)
{
kosten = 2;
}
else
{
kosten = 1;
};
};
if(attribut == ATR_DEXTERITY)
{
if(oth.attribute[ATR_DEXTERITY] >= 120)
{
kosten = 5;
}
else if(oth.attribute[ATR_DEXTERITY] >= 90)
{
kosten = 4;
}
else if(oth.attribute[ATR_DEXTERITY] >= 60)
{
kosten = 3;
}
else if(oth.attribute[ATR_DEXTERITY] >= 30)
{
kosten = 2;
}
else
{
kosten = 1;
};
};
if(attribut == ATR_MANA_MAX)
{
if(oth.attribute[ATR_MANA_MAX] >= 120)
{
kosten = 5;
}
else if(oth.attribute[ATR_MANA_MAX] >= 90)
{
kosten = 4;
}
else if(oth.attribute[ATR_MANA_MAX] >= 60)
{
kosten = 3;
}
else if(oth.attribute[ATR_MANA_MAX] >= 30)
{
kosten = 2;
}
else
{
kosten = 1;
};
};
return kosten;
};
I to w zasadzie wszystko. Podobnie jak poprzednio podam jeszcze przyklad wykorzystanie systemu nauki w dialogu trenera. Znów posłużymy się do tego celu character helperem.
Kod: [Zaznacz]
instance CH_Training_NotRAttributes(C_Info)
{
npc = ch;
condition = CH_Training_NotRAttributes_Condition;
information = CH_Training_NotRAttributes_Info;
important = 0;
permanent = 1;
description = "ATRYBUTY: NotR";
};
func int CH_Training_NotRAttributes_Condition()
{
return TRUE;
};
func void CH_Training_NotRAttributes_Info()
{
Info_ClearChoices(CH_Training_NotRAttributes);
Info_AddChoice(CH_Training_NotRAttributes,"Wróć",CH_Training_NotRAttributes_BACK);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +1",B_GetLearnCostAttribute(other,ATR_STRENGTH),0),CH_Training_NotRAttributes_STR_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +5",B_GetLearnCostAttribute(other,ATR_STRENGTH) * 5,0),CH_Training_NotRAttributes_STR_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +1",B_GetLearnCostAttribute(other,ATR_DEXTERITY),0),CH_Training_NotRAttributes_DEX_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +5",B_GetLearnCostAttribute(other,ATR_DEXTERITY) * 5,0),CH_Training_NotRAttributes_DEX_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +1",B_GetLearnCostAttribute(other,ATR_MANA_MAX),0),CH_Training_NotRAttributes_MAN_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +5",B_GetLearnCostAttribute(other,ATR_MANA_MAX) * 5,0),CH_Training_NotRAttributes_MAN_5);
};
func void CH_Training_NotRAttributes_STR_1()
{
B_TeachAttributePoints(self,other,ATR_STRENGTH,1,100);
Info_ClearChoices(CH_Training_NotRAttributes);
Info_AddChoice(CH_Training_NotRAttributes,"Wróć",CH_Training_NotRAttributes_BACK);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +1",B_GetLearnCostAttribute(other,ATR_STRENGTH),0),CH_Training_NotRAttributes_STR_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +5",B_GetLearnCostAttribute(other,ATR_STRENGTH) * 5,0),CH_Training_NotRAttributes_STR_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +1",B_GetLearnCostAttribute(other,ATR_DEXTERITY),0),CH_Training_NotRAttributes_DEX_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +5",B_GetLearnCostAttribute(other,ATR_DEXTERITY) * 5,0),CH_Training_NotRAttributes_DEX_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +1",B_GetLearnCostAttribute(other,ATR_MANA_MAX),0),CH_Training_NotRAttributes_MAN_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +5",B_GetLearnCostAttribute(other,ATR_MANA_MAX) * 5,0),CH_Training_NotRAttributes_MAN_5);
};
func void CH_Training_NotRAttributes_STR_5()
{
B_TeachAttributePoints(self,other,ATR_STRENGTH,5,100);
Info_ClearChoices(CH_Training_NotRAttributes);
Info_AddChoice(CH_Training_NotRAttributes,"Wróć",CH_Training_NotRAttributes_BACK);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +1",B_GetLearnCostAttribute(other,ATR_STRENGTH),0),CH_Training_NotRAttributes_STR_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +5",B_GetLearnCostAttribute(other,ATR_STRENGTH) * 5,0),CH_Training_NotRAttributes_STR_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +1",B_GetLearnCostAttribute(other,ATR_DEXTERITY),0),CH_Training_NotRAttributes_DEX_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +5",B_GetLearnCostAttribute(other,ATR_DEXTERITY) * 5,0),CH_Training_NotRAttributes_DEX_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +1",B_GetLearnCostAttribute(other,ATR_MANA_MAX),0),CH_Training_NotRAttributes_MAN_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +5",B_GetLearnCostAttribute(other,ATR_MANA_MAX) * 5,0),CH_Training_NotRAttributes_MAN_5);
};
func void CH_Training_NotRAttributes_DEX_1()
{
B_TeachAttributePoints(self,other,ATR_DEXTERITY,1,100);
Info_ClearChoices(CH_Training_NotRAttributes);
Info_AddChoice(CH_Training_NotRAttributes,"Wróć",CH_Training_NotRAttributes_BACK);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +1",B_GetLearnCostAttribute(other,ATR_STRENGTH),0),CH_Training_NotRAttributes_STR_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +5",B_GetLearnCostAttribute(other,ATR_STRENGTH) * 5,0),CH_Training_NotRAttributes_STR_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +1",B_GetLearnCostAttribute(other,ATR_DEXTERITY),0),CH_Training_NotRAttributes_DEX_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +5",B_GetLearnCostAttribute(other,ATR_DEXTERITY) * 5,0),CH_Training_NotRAttributes_DEX_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +1",B_GetLearnCostAttribute(other,ATR_MANA_MAX),0),CH_Training_NotRAttributes_MAN_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +5",B_GetLearnCostAttribute(other,ATR_MANA_MAX) * 5,0),CH_Training_NotRAttributes_MAN_5);
};
func void CH_Training_NotRAttributes_DEX_5()
{
B_TeachAttributePoints(self,other,ATR_DEXTERITY,5,100);
Info_ClearChoices(CH_Training_NotRAttributes);
Info_AddChoice(CH_Training_NotRAttributes,"Wróć",CH_Training_NotRAttributes_BACK);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +1",B_GetLearnCostAttribute(other,ATR_STRENGTH),0),CH_Training_NotRAttributes_STR_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +5",B_GetLearnCostAttribute(other,ATR_STRENGTH) * 5,0),CH_Training_NotRAttributes_STR_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +1",B_GetLearnCostAttribute(other,ATR_DEXTERITY),0),CH_Training_NotRAttributes_DEX_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +5",B_GetLearnCostAttribute(other,ATR_DEXTERITY) * 5,0),CH_Training_NotRAttributes_DEX_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +1",B_GetLearnCostAttribute(other,ATR_MANA_MAX),0),CH_Training_NotRAttributes_MAN_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +5",B_GetLearnCostAttribute(other,ATR_MANA_MAX) * 5,0),CH_Training_NotRAttributes_MAN_5);
};
func void CH_Training_NotRAttributes_MAN_1()
{
B_TeachAttributePoints(self,other,ATR_MANA_MAX,1,100);
Info_ClearChoices(CH_Training_NotRAttributes);
Info_AddChoice(CH_Training_NotRAttributes,"Wróć",CH_Training_NotRAttributes_BACK);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +1",B_GetLearnCostAttribute(other,ATR_STRENGTH),0),CH_Training_NotRAttributes_STR_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +5",B_GetLearnCostAttribute(other,ATR_STRENGTH) * 5,0),CH_Training_NotRAttributes_STR_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +1",B_GetLearnCostAttribute(other,ATR_DEXTERITY),0),CH_Training_NotRAttributes_DEX_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +5",B_GetLearnCostAttribute(other,ATR_DEXTERITY) * 5,0),CH_Training_NotRAttributes_DEX_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +1",B_GetLearnCostAttribute(other,ATR_MANA_MAX),0),CH_Training_NotRAttributes_MAN_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +5",B_GetLearnCostAttribute(other,ATR_MANA_MAX) * 5,0),CH_Training_NotRAttributes_MAN_5);
};
func void CH_Training_NotRAttributes_MAN_5()
{
B_TeachAttributePoints(self,other,ATR_MANA_MAX,5,100);
Info_ClearChoices(CH_Training_NotRAttributes);
Info_AddChoice(CH_Training_NotRAttributes,"Wróć",CH_Training_NotRAttributes_BACK);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +1",B_GetLearnCostAttribute(other,ATR_STRENGTH),0),CH_Training_NotRAttributes_STR_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Siła +5",B_GetLearnCostAttribute(other,ATR_STRENGTH) * 5,0),CH_Training_NotRAttributes_STR_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +1",B_GetLearnCostAttribute(other,ATR_DEXTERITY),0),CH_Training_NotRAttributes_DEX_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Zręczność +5",B_GetLearnCostAttribute(other,ATR_DEXTERITY) * 5,0),CH_Training_NotRAttributes_DEX_5);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +1",B_GetLearnCostAttribute(other,ATR_MANA_MAX),0),CH_Training_NotRAttributes_MAN_1);
Info_AddChoice(CH_Training_NotRAttributes,B_BuildLearnString("Mana +5",B_GetLearnCostAttribute(other,ATR_MANA_MAX) * 5,0),CH_Training_NotRAttributes_MAN_5);
};
func void CH_Training_NotRAttributes_BACK()
{
Info_ClearChoices(CH_Training_NotRAttributes);
};