Pokaż wiadomości

Ta sekcja pozwala Ci zobaczyć wszystkie wiadomości wysłane przez tego użytkownika. Zwróć uwagę, że możesz widzieć tylko wiadomości wysłane w działach do których masz aktualnie dostęp.


Pokaż wątki - bgb

Strony: [1]
1
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ę.

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:

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):

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:

concatText = ConcatStrings(PRINT_NoLearnOverPersonalMAX,IntToString(teacherMAX));
PrintScreen(concatText,-1,-1,FONT_Screen,2);

na:

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.

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ę:

B_RaiseFightTalent(oth,NPC_TALENT_1H,percent);na:
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ę:

if(oth.aivar[REAL_TALENT_1H] >= (oth.aivar[REAL_TALENT_2H] + 30))na:
if(Npc_GetTalentValue(hero,NPC_TALENT_1H) >= (Npc_GetTalentValue(hero,NPC_TALENT_2H) +30))
Potem analogicznie jak przedtem:

B_RaiseFightTalent(oth,NPC_TALENT_2H,percent);na:
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:

PrintScreen(PRINT_Learn1H_and_2H,-1,-1,FONT_Screen,2);na:
PrintScreen("Trening: posługiwanie się bronią jedno- i dwuręczną", -1,10,"FONT_OLD_20_WHITE.TGA",2);
oraz

PrintScreen(PRINT_Learn1H,-1,-1,FONT_Screen,2);na:
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).

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:

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):

B_SetFightSkill(hero,NPC_TALENT_2H,percent);
Całość odpowiedzialna za naukę broni jednoręcznej powinna wyglądać mniej więcej tak:

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:   

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ść:      

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ć:
"",
"brak|adept|mistrz",
"brak|adept|mistrz",
"brak|adept|mistrz",
"brak|adept|mistrz",

Pierwszą pozycję zostawiamy pustą, a kolejne zmieniamy na:
"",
"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:
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.

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:

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:

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.

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:

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

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.

if(oth.aivar[REAL_STRENGTH] >= 120)
zmieniamy na :

if(oth.attribute[ATR_STRENGTH] >= 120)

Po poprawieniu wszystkich linijek powinniśmy mieć taki fragment kodu:

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.

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);
};

2
Archiwum / [G2NK] Classic PL
« dnia: 2015-12-31, 15:48 »
Gothic II: Classic mod PL

Modyfikacja ta daje możliwość grania w podstawową wersję Gothica 2 już po zainstalowaniu dodatku. Została stworzoną z myślą o graczach, posiadających Gothic 2 + Noc Kruka w wersji, która nie pozwala na zainstalowanie samej podstawki.

Polska wersja bazuje na niemieckim modzie o tym samym tytule (autorstwa Lorda Sargona). Co prawda modyfikacja ta nie jest nowa bo opublikowana została już w roku 2006, do tej pory nikt jednak nie pokusił się o stworzenie jej polskiej wersji.

Z uwagi na to, że DirectX11 mod nie jest kompatybilny z klasycznym G2, a jedynie z G2NK, modyfikacja ta pozwala ominąć ten problem.

Instalacja moda:
Spoiler
Uwaga! Modyfikacja  wymaga zainstalowanego GothicStartera w wersji dla Gothica 2 NK.

1. Wypakuj zawartość paczki do folderu Gothic II
2. Uruchom GothicStarter z prawami administratora, wybierz: Gothic II Classic-Mod PL.
3. Ciesz się grą.

Download:
https://mega.nz/#!f5E3UCSD!l6DdmFfdv5hkzmgLreLCv73IBxfkX_WYbKgnGO0mgik

Screeny:
Spoiler




3
Archiwum / [G2] L'HIVER Edition 0.9.3 PL
« dnia: 2015-07-23, 22:16 »
Gothic II - L'HIVER Edition 0.9.3 PL

Typ modyfikacji: Re-Texture, Re-Model, Re-Balance, Re-World

Autorem moda jest unknown111. W modzie zostały wykorzystane materiały z różnych texture packów i innych gier takich jak Wiedźmin, Skyrim. Autor zezwala na edycję i wykorzystywanie moda w innych modyfikacjach pod warunkiem podania linku do jego oryginalnej wersji.

Link do oryginalnego tematu z modem: http://worldofplayers.ru/threads/36390

Generalnie o modyfikacji:
L'hiver Edition to mod, wprowadzający znaczne zmiany w stronie wizualnej oraz balansowej gry. Grafika jest atrakcyjniejsza, a rozgrywka znacznie trudniejsza niż w oryginalnym Gothicu 2 NK. Rozszerzone i uatrakcyjnione wizualnie zostały lokacje w Khorinis i (w mniejszym stopniu) Górniczej Doliny. W Jarkendarze zaszło kilka głównie kosmetycznych zmian. Mod nie ingeruje w żaden sposób w fabułę Gothica 2 - nie dodaje nowych questów, ani nie zmienia tych istniejących. Zmiany w grafice to jednak nie wszystko. Mod znacząco wpływa na balans rozgrywki i zwiększa jej poziom trudności. Oto krótka (niepełna) lista zmian:
- Zmodyfikowano szate graficzną (nowe tekstury, obiekty).
- Przemodelowano lokacje.
- Zmodyfikowane oświetlenie.
- Dodano nowe przedmioty (w tym pancerze i bronie)
- Dodano kilku nowych przeciwników.
- Potwory mają zwiększone statystyki oraz zasięg z którego reagują na gracza.
- Obniżono statystyki obrony wielu zbroi.
- Obniżono wartość przedmiotów, przy ich sprzedaży kupcom.
- Usunięto tabliczki dające stałe bonusy do statystyk.
- Dodano nową umiejętność - patroszenie zwierząt - od teraz wymagana do zbierania mięsa z zabitych potworów. Do wyuczenia u: Bospera (tylko po zostaniu jego czeladnikiem), Niclasa, Jacka Alligatora.
- Zmieniono efekty pożywienia (przykładowo: pieczone mięso przywraca teraz sporą wartość życia w procentach).
- Będąc czeladnikiem Harada, możemy nauczyć się wykuwania nowych mieczy.
- Możemy ulepszać na kowadle niektóre zbroje (skórzana zbroja + nowe pancerze).
- Dodano nowy przedmiot: sztaba metalu (używana do ulepszania zbroii).
- Bennet może nauczyć łowców smoków wykuwania nowych ostrzy w 5 rozdziale.
- Po wykonaniu zadania z krwawymi kielichami, jako nagrodę możemy wybrać nowy pancerz.
- Podział obrony i obrażeń na ostrza i obuchy.
- Styl chodzenia bezimiennego zmienia się zależnie od gildii.
- I wiele innych, mniejszych zmian...

Uwaga! Autor moda doradza, by ustawić widoczność na 180%.
W razie problemów z zawieszaniem podczas gry uruchamiać w trybie zgodności z win xp. (thx to podkopek )
By uniknąć różnych dziwnych problemów zawsze zalecana jest nowa gra, w przypadku zainstalowania nowej wersji moda.

Changelog wersji 0.93
Spoiler
- naprawiono wyświetlanie obrony przed ostrzami (tylko w wersji rosyjskiej, w polskiej zostało to naprawione już w wersji 0.91).
- dodano animacje otwierania sarkofagów.
- dodano nowe animacje (by Mark56).
- dodano pancerz wzorowany na temerskim pancerzu z gry wiedźmin 2: zabójcy królów.
- dodano możliwość wzmacniania najlepszych mieczy, ktorych wykuwania uczy Harad (Wspaniały miecz półtoraręczny oraz Flamberg), odpowiednie instrukcje znaleźć można w książkach które sprzedają Bennet i Jan.
- dodano więcej obiektów w niektórych miejsach.
- zmieniono niektóre modele.
- kilka ulepszeń i poprawek.

Changelog wersji 0.92
Spoiler
- zmodyfikowano lokacje w Górniczej Dolinie oraz Khorinis.
- zmieniono / dodano kilka modeli.
- dodano modele z Carnage Graphic Patch (by Mark56)
- zmodyfikowano kowalstwo. Teraz by wykuć miecz, trzeba użyć do tego celu kolejno: kowadła, wiadra z wodą, stołu kowalskiego, osełki.
- dodano nową umiejętność - płatnerstwo. Od teraz wiąże się ona z wytwarzaniem pancerzy i ich ulepszaniem. Umiejętnosci tej uczy kowal Carl (kolejne poziomy odblokowują sie przy odpowiednich rozdzialach).
- dodano nową umiejetność - skórnictwo. Uczy jej Bosper po zrobieniu zadania z wilczymi skórami. Skóry sa wykorzystywane w kowalstwie do wytwarzania mieczy/pancerzy.
- dodano nową umiejetność - górnictwo. W Khorinis i Gorniczej Dolinie znajdują się teraz żyły żelaza oraz rudy. Umiejętności tej można nauczyć sie u czeladników Harada oraz Benneta, oraz u Grimesa (kopacza w GD).
- dodano animacje pieczenia miesa (autorstwa Mark56).
- dodano możliwość pieczenia miesa przy ogniskach i kuchenkach.
- ze względu na dużą liczbę doświadczenia do zdobycia, zredukowano początkowe statystyki gracza.
- grając magiem można zakładać/zdejmować kaptur z szaty poprzez modyfikowanie jej na stole kowalskim.
- nowe ekrany ładowania.
- lekkie zmiany menu.
- i inne ...

Changelog wersji 0.91
Spoiler
Zmiany w Khorinis:
- przemodelowano dzielnicę portową, dodano kanał i doki, zmieniono układ niektórych budynków.
- dodano kilka nowych pomieszczeń (magazynów) należących do mistrzów rzemieślniczych.


DOWNLOAD

Link do pobrania patcha 0.9.3a:

Patch naprawia problem z nauką 2 i 3 poziomu płatnerstwa w późniejszych rozdziałach gry. Wymaga uprzedniego zainstalowania wersji pełnej PL 0.9.3 LUB wersji minimalnej PL 0.9.3 + wersji rosyjskiej 0.9.3.

Link do pobrania pełnej wersji PL (0.9.3):

Wersja full spolszczenia zawiera w sobie wersję rosyjską, z którą została scalona i nie trzeba ściągać żadnych dodatkowych plików.

Link do pobrania minimalnej wersji PL (0.9.3):

Wersja mini spolszczenia do prawidłowego działania wymaga uprzedniego zainstalowania wersji rosyjskiej 0.93!

Instalacja moda:
- Przed wypakowaniem utwórz kopię zapasową pliku Gothic.ini znajdującego się w folderze z grą ( ...\Gothic II\System).
- Wypakuj zawartość paczki z modem do folderu Gothic II.

Co zmienia spolszczenie względem oryginalnego moda?
Spoiler
- W modzie dostępne są dwie nowe twarze dla bezimiennego. Zamiast defaultowej użyliśmy twarzy alternatywnej. Gdyby ktoś jednak chciał grać na tej pierwszej wystarczy usunąć plik G2_LH_Edit_PL_v0.9.3_ALTFACE.vdf znajdujący się w folderze Gothic II/Data.
- Dodano opcję pytania o potwierdzenie przy rozpoczęciu nowej gry.

Polska wersja moda została przygotowana przez bgb i GizmoRa. Zastrzegamy, że mimo testów mogliśmy nie wyłapać wszystkich błędów. Prosimy o zgłaszanie ewentualnych problemów - w razie potrzeby ukaże się poprawiona wersja moda.

Link do starego tematu modyfikacji:
http://themodders.org/index.php?topic=21651.0

Screeny:
Spoiler








































































4
Skrypty / Problem z dodaniem potworów
« dnia: 2014-08-21, 15:53 »
Chciałem dodać potwory w lochach zamku w GD (wasteland mod), parę szkieletów i zombiaków - niby banalna sprawa, a napotykam na problem. Mianowicie: dodaję skrypt Wld_InsertNpc w func void Startup_Oldcamp(), waypoint przez spacer i... nic się nie dzieję. Potwora nie ma w grze. Co dziwne ten problem zdaje się występować tylko w starym obozie, bo potworki pojawiły się, gdy umieściłem je (na próbę) np. przy wieży xardasa, czy też w GD zaraz przy wejściu do lokacji. Dodam jeszcze, że nie ma tego problemu z npc-ami. Ci pojawiają się bez problemu na danym waypoincie w lochu, zapewne dzięki skryptowi rutyny. O co tu chodzi? Czyżbym robił jakiś banalny błąd?

5
No więc mam taki problem. Pobrałem sobie ten model miecza z WoGa:
 http://www.worldofgothic.de/?go=moddb&action=view&fileID=277&cat=11&page=4&order=0
Jest on oparty na gothicowych teksturach więc nie powinien robić problemów. Jednak gdy chciałem wstawić miecz jako model statyczny przez spacer w ogóle się nie wyświetlał. W końcu doszedłem do wniosku, że to przez jego nazwę - zmieniłem ä na a, no i tym razem model się wczytał. Wszystko wyglądało ok więc zadowolony zmieniłem mu nazwę na SLEEPERSWORD.3ds i wrzuciłem w skrypty. Od tego czasu minął może miesiąc. No i pewnego dnia przywołuje sobie w gothicu ludka którego zrobiłem (z tym mieczem) i co widzę? Otóż tekstury miecza są jakieś dziwne. Wczytuje model spacerem i rzeczywiście - ma tekstury niby ziemi. Co dziwne, te tekstury zmieniają się zależnie od świata w którym wczytuje miecz. Gdy otworzę go w OLDWORLD - jest cały ziemisty. Gdy w NEWWORLD - rękojeść jest dobra, natomiast same ostrze nie. Tylko w Jarkendarze wczytuje się cały dobrze :| O co tu chodzi?

Edit. wygrzebałem starą paczkę .vdf sprzed miesiąca - z dodanym już mieczem. I o dziwo tam mieczyk działa w porządku. Co ja mogłem zepsuć? :F  :hmmm:

Edit2. wygląda na to, że w starszych wersjach moich zenów, tekstury miecza są wyświetlane poprawnie. Dopiero w nowszych miecz zaczyna wariować. Dalej jednak nie wiem, co może być tego przyczyną.

Edit3. Kolejny update - wydaje mi się, że coś odkryłem. Zauważyłem, że ostatnio dodany vob w newworld.zen także miał jakiś problem z teksturą. Mianowicie, wyświetlała się na nim tekstura mieczy... mimo, że to był całkiem inny przedmiot. Gdy usunąłem ten vob ze świata, sam miecz znowu zaczął wyglądać ok, więc wygląda na to że te dwa modele jakoś ze sobą kolidowały pod względem tekstur (nie wiem czy to w ogóle możliwe?). Natomiast problem dalej pozostał w oldworld.zen , tylko, że tam nie mam tego voba...

6
Czy ktoś tutaj preferuje ten rodzaj gier? Ja swego czasu bardzo lubiłem się wirtualnie pościgać. Teraz jednak, gdy próbuję znaleźć coś co by mnie przyciągnęło na dłużej do ekranu mam z tym spory problem :wstyd: Ostatnio próbowałem świeżutkiego GRID Autosport - dla mnie klapa. Model jazdy toporny, emocje podczas rozgrywki - "meh", a zjebany widok z kokpitu tylko dopełnia wrażenie, że gra jest zrobiona na odwal. Nie rozumiem tego tym bardziej, że pierwszy Dirt, a więc już 7-letnia gra i to od tego samego studia, ma kokpity które wizualnie biją na głowę to co nam zaserwowano teraz. Regres niesamowity.  :antyprops: Znacie jakieś godne polecenia tytuły?

7
Forum / Nowe emotikony
« dnia: 2014-07-04, 21:38 »
Postuluje o uzupełnienie forumowych emotikonek o dodatkowe - niekoniecznie przebajerzone - chociaż można by pójść trochę z duchem czasu. Niemniej, czemu brak takich podstaw jak np. sadface?

edit. hmm... Teraz nic nie wkleję, bo nie miałem na myśli konkretnych emotikonek, a raczej poszerzenie tych obecnych o dodatkowe, ale utrzymane w tym samym stylu graficznym. Sądziłem, że te obecne to tylko część z większego template, bo brak minki :( dziwi. Poszukam czegoś w takim razie.

8
Pytania i problemy / Konwersja .zen do .3ds w 3dsmaxie
« dnia: 2014-06-10, 19:17 »

Witam. Generalnie na start napiszę, że z edytorem grafiki 3d mam do czynienia po raz pierwszy... Także nie wiem bardzo wielu rzeczy i prawdę mówiąc ledwo się orientuję w podstawowych czynnościach :|

Przechodząc jednak do rzeczy, chodzi o odzyskanie mesha świata z moda L'hiver Edition http://themodders.org/index.php?topic=21651.0 i nie, nie chodzi tutaj o wykradanie czyjejś pracy. Sytuacja wygląda tak, że autor moda jakiś czas temu stracił wszystkie swoje materiały. Udało się odzyskać tylko to co zostało uprzednio zuploadowane w wydanej niekompletnej wersji modyfikacji. Czyli skrypty, textury, animacje, i inne pliki z paczki vdf. Największy problem stanowią jednak zmofydikowane światy. Dla kogoś kto nie zna tego moda - Khorinis i GD są powiększone o spore połacie nowych terenów (GD w mniejszym stopniu). No i teraz sprawa wygląda tak, że dostepne są tylko całe scalone już pliki: newworld.zen oraz oldworld.zen. W spacerze można się co prawda pobawić dodając do nich voby, ale jakieś ingerencje w mesh odpadają. Próbowałem skonwertować świat przez spacera podpierając się tym tutkiem:  http://themodders.org/index.php?topic=48.0

Ale nic z tego nie wyszło - po kompilacji świat zmienił się na oryginalny newworld z podstawki:
Spoiler

Pomyślałem więc o użyciu 3dsmaxa. Pierwsze efekty przerosły moje oczekiwania - udało mi się zaimportowac plik .zen i zapisać go jako .3ds. Musiałem co prawda podzielić świat na około 20 elementów jednak w końcu udało się go zapisać (dzieliłem to byle jak). Pierwszy mój problem jest taki, że gdy otwieram ten plik w spacerze, widzę że niektóre tekstury są nieprawidłowe:

Spoiler





Jest tego dosyć sporo... Więc czy może to ja robię coś źle w 3dsmaxie czy jednak tak już bywa? W jaki sposób temu zaradzić? (bez ręcznego ponownego teksturowania oczywiście). Drugie pytanie - czy da się jakoś w miarę prosty sposób podzielić cały mesh na kawałki dokładnie takie jak np. w niemodowanym newworld.zen? (wyłączając dodane tereny oczywiście, one byłyby zapisane jako nowe elementy). Trzecie pytanie - zauważyłem, że tekstury znajdujące się w przejściach (drzwiach) budynków, które normalnie powinny znikać gdy znajdujemy się bliżej nich teraz są widoczne cały czas. No i poznikała woda z jezior/rzek. Czy także da się temu jakoś zaradzić "z automatu" ? Bez potrzeby poprawiania ręcznego każdego z tych elementów z osobna..?

Ok chyba narazie starczy pytań. Dodam tylko, że ten mesh jest świetną potencjalną podstawą do wykorzystania w rozszerzających modyfikacjach do goticzka. Także jeśli ktoś z odpowiednią wiedzą/umiejętnościami chce coś zrobić pro publico bono to zachęcam  :lol:

9
Muzyka / Muzyka z gier / okołogrowa
« dnia: 2014-05-19, 22:54 »
Pomyślałem, że przydałby się osobny temat na muzykę związaną bezpośrednio z grami bo niektóre soundtracki to prawdziwe perełki... No to jedziemy, zacznę wacraftem:P

https://www.youtube.com/watch?v=QzYe5fSpxFo

10
Skrypty / Modyfikacja okna statystyk
« dnia: 2014-04-23, 09:14 »
Witam. Czy w G2NK możliwa jest modyfikacja okna statystyk bohatera by wyświetlana była dodatkowa obrona: np. przed ostrzami i przed obuchami osobno zamiast jednej obrony przed bronią? Z tego co wyczytałem możliwość ingerencji w to menu jest baaardzo ograniczone...

11
Skrypty / Kompilacja menu
« dnia: 2014-04-21, 09:26 »
Na wstępie zaznaczę, że programista ze mnie żaden i robię dopiero pierwsze kroki "w modowaniu", także proszę o wyrozumiałość  :P Na początek zabrałem się za spolszczanie pewnej modyfikacji. Czytałem tutki na forum i do tej pory wszystko ogarniałem, tj. zdekompilowałem skrypty moda Gsourcerem, wprowadziłem własne zmiany w plikach z gothic.dat, skompilowałem spacerem, sprawdzałem w grze - działa. Jedak gdy zabrałem się za menu.dat napotykam problem...

Z tego topiku wynika, że menu kompiluje się w sourcerze: http://themodders.org/index.php?topic=8835.0

No i tak też zrobiłem. Poszło ładnie - 0 błędów, 0 warningów. Mimo to robię paczkę z modem, z podmienionym menu.dat, odpalam grę, naciskam B chcąc otworzyć okno statystyk bohatera to wywala mi taki błąd:

C: zmenu_item.cpp(zCMenuItem::Create)

:MenuItem not known: MENU_ITEM_PASSTAL_HEADING

Myślałem, że to przez moje zmiany, tzn. że gdzieś się jednak machnąłem. No ale gdy kompiluję sourcerem oryginalny menu.dat (bez zmian) wywala w grze mi taki sam błąd. W czym tu tkwi problem?

Czytałem też topik: http://themodders.org/index.php?topic=106.0

I z niego wynika, że menu można kompilować także spacerem, ale gdy próbuję wyskakuje mi dość dużo błędów...



12
Archiwum / [G2] L'HIVER Edition
« dnia: 2014-03-29, 13:06 »
Gothic II - L'HIVER Edition

Typ modyfikacji: Re-Texture, Re-Model, Re-Balance, Re-World
Obecna wersja: 0.9.0 (nie jest jeszcze finalna)
Polska wersja: 0.9.0 (oraz starsza 0.8.7)

Mod został stworzony przez unknown111, wykorzystuje materiały z różnych texture packów i gier takich jak Wiedźmin 2, Skyrim.

Link do topicu na WoP: http://worldofplayers.ru/threads/36390/page-13

Generalnie o modyfikacji:
Główną atrakcją moda jest zmodyfikowana oprawa graficzna, rozszerzone lokacje Khorinis i (w mniejszym stopniu) Górniczej Doliny. Jarkendar został zmodyfikowany prawie, że niezauważalnie. Mod co prawda nie zmienia w jakikolwiek sposób fabuły jednak zmiany w grafice to nie wszystko. Należy wspomnieć, że mod także znacząco wpływa na balans rozgrywki i zwiększa jej poziom trudności. Oto krótka (niepełna) lista zmian:
- Zmodyfikowano szate graficzną (nowe tekstury, obiekty).
- Przemodelowano lokacje.
- Zmodyfikowane oświetlenie.
- Dodano nowe przedmioty (w tym pancerze i bronie)
- Dodano kilku nowych przeciwników.
- Potwory mają zwiększone statystyki oraz zasięg z którego reagują na gracza.
- Obniżono statystyki obrony wielu zbroi.
- Obniżono wartość przedmiotów, przy ich sprzedaży kupcom.
- Usunięto tabliczki dające stałe bonusy do statystyk.
- Dodano nową umiejętność - patroszenie zwierząt - od teraz wymagana do zbierania mięsa z zabitych potworów. Do wyuczenia u: Bospera (tylko po zostaniu jego czeladnikiem), Niclasa, Jacka Alligatora.
- Zmieniono efekty pożywienia (przykładowo: pieczone mięso przywraca teraz sporą wartość życia w procentach).
- Będąc czeladnikiem Harada, możemy nauczyć się wykuwania wielu nowych mieczy.
- Możemy ulepszać na kowadle niektóre zbroje (skórzana zbroja + nowe pancerze).
- Dodano nowy przedmiot: sztaba metalu (używana do ulepszania zbroii).
- Bennet uczy łowców smoków wykuwania nowych ostrzy w 5 rozdziale.
- Po wykonaniu zadania z krwawymi kielichami, jako nagrodę możemy wybrać nowy pancerz.
- Podział obrony i obrażeń na ostrza i obuchy.
- Styl chodzenia bezimiennego zmienia się zależnie od gildii.
- I wiele innych, mniejszych zmian...

Uwaga! Autor moda doradza, by ustawić widoczność na 180%.
W razie problemów z zawieszaniem podczas gry uruchamiać w trybie zgodności z win xp. (thx to podkopek )

Link do downloadu wersji RU (0.9.0):
https://yadi.sk/d/rFk9woSPcWj2c

Link do downloadu wersji PL (0.9.0):

lub
http://chomikuj.pl/lolzekqw12/Gothic/G2_LH_Edit_PL_v0.9.0,4415540634.rar

Link do downloadu starszej wersji PL (0.8.7):

Spolszczenie jest autorstwa mojego i GizmoRa. Chcemy zastrzec, że mimo testów mogliśmy nie wyłapać wszystkich błędów. Dlatego mamy prośbę - jeśli coś zauważycie, piszcie - w razie potrzeby ukaże się poprawiona wersja moda.

Bugi, które zostały z oryginalnego moda (a przynajmniej, te które zauważyliśmy):
- Autocomplete questa z Owenem i Malcolmem - bug naprawiony w wersji 0.9 PL.
- W karcie statystyk bohatera nie wyświetla się obrona przed ostrzami.

Co zmienia spolszczenie względem oryginalnego moda?
Spoiler
- Zmiana tekstury jednego z obrazów (powód: oryginalny uznany za zbyt mało klimatyczny).
- Zmiana tekstury morza w Khorinis (wielu osobom, w tym i nam bardzo nie podobała się oryginalna woda) - nieaktualne w wersji 0.9 PL.
- Zmiana tekstury twarzy bezimiennego (mod zawiera w sobie dwie nowe tekstury twarzy bezia, jednak tylko jedna z nich jest wykorzystywana. Niestety - ta brzydsza. Użyliśmy więc tej drugiej).
- Zmiana tekstur grzybów (powód: mod wykorzystywał stare tekstury gothica, które średnio pasowały do ulepszonej oprawy graficznej)
- Dodano 5 nowych polskich ekranów: menu, Khorinis, Irdorath, Jarkendar, Górnicza Dolina.
- Jako ekranu ładowania gry użyliśmy ekranu, który w modzie służył za screen startowy (powód: ekran utrudniał widoczność przy poruszaniu się po menu).
- Zmieniliśmy pozycję menu. Teraz jest umiejscowione tak jak w podstawowym Gothicu 2NK, czyli na środku ekranu, a nie jak w modyfikacji - po prawej stronie (powód: na niektórych rozdzielczościach, menu umiejscowione po prawej stronie nie było w pełni widoczne).
- Dodano opcję pytania o potwierdzenie przy rozpoczęciu nowej gry - tylko w wersji 0.9 PL.

Gdyby, ktoś chciał przywrócić sobie oryginalne tekstury moda, to wszystkie znajdują się w paczce z modem z dopiskiem _OLD (prócz rosyjskich ekranów ładowania).

Screeny:

Spoiler














































Strony: [1]
Do góry