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 - Khantor

Strony: [1]
1
Spacer / [G2NK] Niewidzialna ściana i powolne animacje
« dnia: 2024-01-15, 11:48 »
Witam, nie jestem pewny czy to właściwy dział, ale problem pojawił się po skleceniu nowego świata, więc wstawiam tutaj.

Otóż skleciłem nowy świat w blenderze, skompilowałem go w Spacerze i po odpaleniu go w Gothicu dzieje się to co na filmie.

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


Postać biega jak mucha w smole a dodatkowo w jednym czy dwóch miejscach są niewidzialne ściany na środku pomieszczenia. Nie wstawiałem tam nic w spacerze, w blenderze też żadnej ściany tam nie ma, na filmiku widać nawet podgląd samej siatki - nic tam nie ma. Widać też, że portale chyba działają dobrze, więc to raczej nie ich wina. Ma ktoś jakieś pomysły o co chodzi z tym drewnem? Oczywiście ten sam Gothic tylko z oryginalnym światem działa normalnie.

2
Spacer / Modyfikacja świata z innego moda.
« dnia: 2023-07-25, 17:55 »
No dzień dobry. Mam szybkie pytanie - czy istnieje możliwość edytowania (w spacerze) skompilowanego już świata z innego moda? Jak rozpakuję dajmy na to VarusBikera i chcę otworzyć ZEN świata w spacerze to wyskakuje okienko kompilacji i świat się nie otwiera. Pytanie moje brzmi - czy poza otrzymaniem nieskompilowanych plików od autora da się coś z tym zrobić, czy szkoda sobie zawracać w ogóle głowę?

3
No dzień dobry. Chciałem podpiąć banalną funkcję powodującą, że NPC A atakuje NPC B pod środkowy przycisk myszy. Napisałem banalną, przykładową funkcję:
b_attack(sentenza,hero,AR_NONE,0);

I wsadziłem ją do FrameFunction i zainicjowałem co klatkę - działa perfekcyjnie.

Idąc krok dalej dołożyłem na razie nic nie robiący warunek z klawiszem:
if (MEM_KeyState(MOUSE_BUTTONMID) == KEY_UP)
{
b_attack(sentenza,hero,AR_NONE,0);
};

I także działa perfekcyjnie, tzn. tak jak powinno się stać - Sentenza rzuca się od razu na gracza. Ale to by było na tyle, jeśli o działanie przy próbie podpięcia pod klawisz. Jeśli zamienię warunek na cokolwiek innego określającego czy przycisk jest naciśnięty czy nie, nawet na MEM_KeyState(MOUSE_BUTTONMID) != KEY_UP To już się robi problem. Ten przykładowy Sentenza który sobie stoi w miejscu i je, przy wywołaniu przyciskiem funkcji po prostu zamiera w miejscu jakby kija połknął, ale atakuje może raz na 100 prób. Wsadzony do tej funkcji print działa, że więc ten warunek spełniony wg gry jest. Wie ktoś o co chodzi i jak okiełznać to drewno? Dodam tylko, że w ten sam sposób napisałem i podpiąłem pod PPM funkcję podnoszącą itemy z ziemi jak w returningu i działa bez problemu, a tu się dzieją jaja.

4
Skrypty / [G2NK] Quickloot zdejmuje zbroje z NPC
« dnia: 2021-05-22, 18:57 »
Dzień dobry. Napisałem funkcję która ma przeszukiwać ciała pobitych/zabitych NPC.

func void Remove_Focused_Empty_Body()
{
        var int index; index = 0;
var int loopStart; loopStart = MEM_StackPos.position;

if((Hlp_GetInstanceID(trgt))
&& (Hlp_Is_oCNpc(her.focus_vob))
&& ((MEM_KeyState(MOUSE_BUTTONRIGHT) == KEY_PRESSED)
|| (MEM_KeyState(MOUSE_BUTTONRIGHT) == KEY_HOLD))
&& (((Npc_GetBodyState(trgt) == BS_UNCONSCIOUS)
|| (Npc_GetBodyState(trgt) ==  BS_DEAD))
|| (trgt.attribute[ATR_HITPOINTS] < 1))
&& (Npc_GetInvItemBySlot (trgt, 0, index) != 0))
{
var C_Item meelee; meelee = Npc_GetEquippedMeleeWeapon(trgt);
var C_Item rangee; rangee = Npc_GetEquippedRangedWeapon(trgt);

if ((item.mainflag & (ITEM_KAT_ARMOR))
|| (Hlp_GetInstanceId(meelee) == Hlp_GetInstanceId(item))
|| (Hlp_GetInstanceId(rangee) == Hlp_GetInstanceId(item)))
{
index += 1;
MEM_StackPos.position = loopStart;
}
else if (Npc_GetInvItemBySlot (trgt, 0, index) != 0)
{
var int amount2; amount2 = Npc_GetInvItemBySlot (trgt, 0, index);

CreateInvItems (hero, Hlp_GetInstanceID (item), amount2);
NPC_RemoveInvItems (trgt, Hlp_GetInstanceID (item), amount2);

var string concatText;
concatText = concatstrings("Zebrano: ", item.description);
concatText = concatstrings(concatText, " x ");
concatText = concatstrings(concatText, inttostring(amount2));
InfoBox_Create(concatText, TRUE, FONT_ScreenSmall, RGBA(255, 255, 255, 255), InfoBox_DefaultTexture);

index += 1;
MEM_StackPos.position = loopStart;
};
};
};

Podpiąłem ją do FrameFunction

        if (!FF_Active (Remove_Focused_Empty_Body))
{
FF_ApplyOnceExt (Remove_Focused_Empty_Body, 0, -1);
};

 i działa z tym, że czasami przy przeszukiwaniu NPCa, pomimo wstawionego warunku zabiera mu też zbroję. Nie zawsze tak się dzieje i nie zauważyłem nawet żadnej reguły, która pomogłaby mi namierzyć problem. Co może być tego przyczyną i jak temu zaradzić?



Swoją drogą jest jakaś dostępna zwykłemu śmiertelnikowi metoda na zrobienie quickloota dla skrzyń?

5
Witam. Jak chcę sobie powyciągać zmienne namierzonego przedmiotu w ekwipunku no to używam

container = ECX;

const int call = 0;

if (CALL_Begin(call))
{
CALL_PutRetValTo(_@(selectedItemPtr));
CALL__thiscall(_@(container), 7377600);
call = CALL_End();
};

itm = _^(selectedItemPtr);

i hookuje to na

HookEngineF(7370416, 6, nazwa_funkcji);

Działa to na otwartym ekwipunku. A może ktoś powiedzieć takiemu laikowi jak ja co mam zrobić, żeby móc wyciągnąć zmienne namierzonego itemu ale w polu ekwipunku otwartej skrzyni, polu ekwipunku handlarza podczas handlu i polu ekwipunka przeszukiwanego npc? Byłbym wdzięczny i postawiłbym kratę piwa w zamian ale zaraza i nie wolno.

6
Skrypty / [G2NK] Dodatkowe wolne AIVARy.
« dnia: 2020-11-01, 19:31 »
Witam. Często można spotkać opinię, że w Gothicu jest za mało wolnych AIVarów do wykorzystania, ale chyba nie znalazłem nigdzie sposobu, żeby te dodatkowe AIVary sobie zwolnić. Jak wiemy, w G2NK mamy do dyspozycji 11 wolnych AIVarów (89-99 gdzie 89 jest wykorzystywany przez LeGo do tworzenia nowej umiejętności), na upartego 12, bo AIVar 72 "AIV_NPCIsRanger" nie jest w ogóle wykorzystywany w skryptach. Pokażę więc dzisiaj, w jaki sposób zwolnić sobie dodatkowe 52 AIVary. Jak ktoś bardzo potrzebuje i się uprze to może sobie zwolnić ich jeszcze więcej. Z góry uprzedzam, że wymaga to dosyć sporo monotonnej roboty, ale nie ma nic za darmo. Potrzebny Ikarus i LeGo.

Jeśli przyjrzymy się AIVarom które mamy w Gothicu to możemy zauważyć, że duża ich część przyjmuje tylko wartości 0-1, a większość przyjmuje wartości nie większe niż 23. Jeśli mamy do wykorzystania ograniczoną ilość AIVarów, z czego każdy ma wielkość 32 bitów, to zużycie go na zapisanie tylko 1-5 bitów to straszne marnotractwo miejsca. Jako, że chyba żaden, poza "AIV_INVINCIBLE" nie jest w żaden sposób czytany przez silnik, to jedyne co musimy zrobić, to skompresować z góry ograniczone AIVary o długości 1-5 bitów w jeden. Poniżej wyznaczona przeze mnie lista AIVarów do kompresji.

AIVary 0-1; - 1 bit

AIV_NpcStartedTalk
AIV_TalkedToPlayer
AIV_PlayerHasPickedMyPocket
AIV_PursuitEnd
AIV_RANSACKED
AIV_DeathInvGiven
AIV_PASSGATE
AIV_PARTYMEMBER
AIV_VictoryXPGiven
AIV_Gender
AIV_SeenLeftRoom
AIV_ToughGuyNewsOverride
AIV_MM_ThreatenBeforeAttack
AIV_MM_FollowInWater
AIV_MM_PRIORITY
AIV_DuelLost
AIV_MM_Packhunter
AIV_MagicUser
AIV_DropDeadAndKill
AIV_IGNORE_Murder
AIV_IGNORE_Theft
AIV_IGNORE_Sheepkiller
AIV_ToughGuy
AIV_NewsOverride
AIV_EnemyOverride
AIV_LOADGAME
AIV_DefeatedByPlayer
AIV_KilledByPlayer
AIV_IgnoresFakeGuild
AIV_NoFightParker
AIV_NPCIsRanger
AIV_IgnoresArmor
AIV_StoryBandit
AIV_StoryBandit_Esteban


AIVary 0-2; - 2 bity

AIV_Guardpassage_Status
AIV_TAPOSITION


AIVary 0-3; - 2 bity

AIV_LastFightAgainstPlayer
AIV_Food
AIV_ArenaFight


AIVary 0-4; - 3 bity

AIV_NpcSawPlayerCommit


AIVary 0-7; - 3 bity

AIV_ChapterInv


AIVary 0-19; - 5 bitów

AIV_ATTACKREASON
AIV_LastPlayerAR


AIVary 0-23 godziny; - 5 bitów

AIV_MM_SleepStart
AIV_MM_SleepEnd
AIV_MM_RestStart
AIV_MM_RestEnd
AIV_MM_RoamStart
AIV_MM_RoamEnd
AIV_MM_EatGroundStart
AIV_MM_EatGroundEnd
AIV_MM_WuselStart
AIV_MM_WuselEnd
AIV_MM_OrcSitStart
AIV_MM_OrcSitEnd


AIVar 0-14; - 4 bity

AIV_MM_ShrinkState

56 powyższych AIVarów można skompresować do 4. Zaczynamy od napisania funkcji, która nam będzie:
a) Kompresować wiele AIVarów w jeden i w razie potrzeby zmieniać ich wartości w obrębie skompresowanego AIVaru.
b) Odczytywać ze skompresowanego AIVara wartości AIVarów składowych.

Gotowiec:

func int PowerFunction (var int Basic_of_Power, var int Power)
{
var int Powered_Number; Powered_Number = 1;
var int index; index = 0;

if (Power < 0)
{
Power = 0;
};

if (Power == 0)
{
return Powered_Number;
};

var int loopStart; loopStart = MEM_StackPos.position;
if (index < Power)
{
Powered_Number = Powered_Number * Basic_of_Power;

index += 1;
MEM_StackPos.position = loopStart;
};

return Powered_Number;
};

func int Byte_for_AIVars (var C_NPC AIVar_Taker, var int AIVar_Input, var int Value_to_AIVar, var int Write_or_Read) //var int Write_or_Read = 0 - wpisanie w skompresowany AIVar AIVaru składowego AIVar_Input którego wartość wynosi Value_to_AIVar; var int Write_or_Read = 1 - odczytanie ze skompresowanego AIVara wartości AIVara składowego AIVar_Input.
// Value_to_AIVar - AIVary 5 - bitowe określające godziny mogą przyjmować wartość "-1". U nas rolę "-1" będzie pełnić "31".
{
var int Nr_CompressedAIVar; Nr_CompressedAIVar = 0; // Na którym z 4 skompresowanych AIVarów będzie znajował się nam nasz AIVar kompresowany
var int Bit_AIVar_CompressedAIVar; Bit_AIVar_CompressedAIVar = 0; // Od którego bitu w AIVarze skompresowanym zaczyna się nasz AIVar kompresowany
var int Bit_Position_AIVar; Bit_Position_AIVar = 0; // Długość w bitach AIVaru kompresowanego

if (AIVar_Input == AIV_MM_OrcSitEnd) // 41
{
Nr_CompressedAIVar = 1;
Bit_AIVar_CompressedAIVar = 1;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_SleepStart) // 30
{
Nr_CompressedAIVar = 1;
Bit_AIVar_CompressedAIVar = 6;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_SleepEnd) // 31
{
Nr_CompressedAIVar = 1;
Bit_AIVar_CompressedAIVar = 11;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_RestStart) // 32
{
Nr_CompressedAIVar = 1;
Bit_AIVar_CompressedAIVar = 16;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_RestEnd) // 33
{
Nr_CompressedAIVar = 1;
Bit_AIVar_CompressedAIVar = 21;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_RoamStart) // 34
{
Nr_CompressedAIVar = 1;
Bit_AIVar_CompressedAIVar = 26;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_IgnoresFakeGuild) // 70
{
Nr_CompressedAIVar = 1;
Bit_AIVar_CompressedAIVar = 31;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_MM_RoamEnd) // 35
{
Nr_CompressedAIVar = 2;
Bit_AIVar_CompressedAIVar = 1;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_EatGroundStart) // 36
{
Nr_CompressedAIVar = 2;
Bit_AIVar_CompressedAIVar = 6;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_EatGroundEnd) // 37
{
Nr_CompressedAIVar = 2;
Bit_AIVar_CompressedAIVar = 11;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_WuselStart) // 38
{
Nr_CompressedAIVar = 2;
Bit_AIVar_CompressedAIVar = 16;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_WuselEnd) // 39
{
Nr_CompressedAIVar = 2;
Bit_AIVar_CompressedAIVar = 21;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_OrcSitStart) // 40
{
Nr_CompressedAIVar = 2;
Bit_AIVar_CompressedAIVar = 26;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_DeathInvGiven) // 11
{
Nr_CompressedAIVar = 2;
Bit_AIVar_CompressedAIVar = 31;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_NoFightParker) // 71
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 1;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_NPCIsRanger) // 72
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 2;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_IgnoresArmor) // 73
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 3;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_StoryBandit) // 74
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 4;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_StoryBandit_Esteban) // 75
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 5;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_ATTACKREASON) // 9
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 6;
Bit_Position_AIVar = 5;
}
else if (AIVar_Input == AIV_MM_ShrinkState) // 42
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 11;
Bit_Position_AIVar = 4;
}
else if (AIVar_Input == AIV_ChapterInv) // 49
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 15;
Bit_Position_AIVar = 3;
}
else if (AIVar_Input == AIV_NpcSawPlayerCommit) // 1
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 18;
Bit_Position_AIVar = 3;
}
else if (AIVar_Input == AIV_ArenaFight) // 45
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 21;
Bit_Position_AIVar = 2;
}
else if (AIVar_Input == AIV_Guardpassage_Status) // 12
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 23;
Bit_Position_AIVar = 2;
}
else if (AIVar_Input == AIV_TAPOSITION) // 19
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 25;
Bit_Position_AIVar = 2;
}
else if (AIVar_Input == AIV_NpcStartedTalk) // 3
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 27;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_TalkedToPlayer) // 5
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 28;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_PlayerHasPickedMyPocket) // 6
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 29;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_PursuitEnd) // 8
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 30;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_RANSACKED) // 10
{
Nr_CompressedAIVar = 3;
Bit_AIVar_CompressedAIVar = 31;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_PASSGATE) // 14
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 1;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_PARTYMEMBER) // 15
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 2;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_VictoryXPGiven) // 16
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 3;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_Gender) // 17
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 4;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_SeenLeftRoom) // 21
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 5;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_ToughGuyNewsOverride) // 25
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 6;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_MM_ThreatenBeforeAttack) // 26
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 7;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_MM_FollowInWater) // 28
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 8;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_MM_PRIORITY) // 29
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 9;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_DuelLost) // 48
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 10;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_MM_Packhunter) // 50
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 11;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_MagicUser) // 51
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 12;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_DropDeadAndKill) // 52
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 13;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_IGNORE_Murder) // 54
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 14;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_IGNORE_Theft) // 55
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 15;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_IGNORE_Sheepkiller) // 56
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 16;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_ToughGuy) // 57
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 17;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_NewsOverride) // 58
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 18;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_EnemyOverride) // 61
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 19;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_KilledByPlayer) // 67
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 20;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_LOADGAME) // 65
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 21;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_DefeatedByPlayer) // 66
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 22;
Bit_Position_AIVar = 1;
}
else if (AIVar_Input == AIV_Food) // 18
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 23;
Bit_Position_AIVar = 2;
}
else if (AIVar_Input == AIV_LastFightAgainstPlayer) // 0
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 25;
Bit_Position_AIVar = 2;
}
else if (AIVar_Input == AIV_LastPlayerAR) // 47
{
Nr_CompressedAIVar = 4;
Bit_AIVar_CompressedAIVar = 27;
Bit_Position_AIVar = 5;
};

if ((Value_to_AIVar < PowerFunction(2, Bit_Position_AIVar))
&& (Value_to_AIVar >= 0))
{
var int AIVar_Initial_Value; AIVar_Initial_Value = 0;
if (Nr_CompressedAIVar == 1)
{
AIVar_Initial_Value = AIVar_Taker.aivar[AIV_FirstCompressed];
}
else if (Nr_CompressedAIVar == 2)
{
AIVar_Initial_Value = AIVar_Taker.aivar[AIV_SecondCompressed];
}
else if (Nr_CompressedAIVar == 3)
{
AIVar_Initial_Value = AIVar_Taker.aivar[AIV_ThirdCompressed];
}
else if (Nr_CompressedAIVar == 4)
{
AIVar_Initial_Value = AIVar_Taker.aivar[AIV_FourthCompressed];
};

var int AIVar_Value; AIVar_Value = 0;

var int Component1; Component1 = 0;
Component1 = AIVar_Initial_Value%(PowerFunction(2, Bit_AIVar_CompressedAIVar + Bit_Position_AIVar - 1));

var int Component2; Component2 = 0;
Component2 = PowerFunction(2, Bit_AIVar_CompressedAIVar - 1);

if (Write_or_Read == 0)
{
AIVar_Value = AIVar_Initial_Value - Component1 + (Value_to_AIVar * Component2) + Component1%Component2;

if (Nr_CompressedAIVar == 1)
{
AIVar_Taker.aivar[AIV_FirstCompressed] = AIVar_Value;
}
else if (Nr_CompressedAIVar == 2)
{
AIVar_Taker.aivar[AIV_SecondCompressed] = AIVar_Value;
}
else if (Nr_CompressedAIVar == 3)
{
AIVar_Taker.aivar[AIV_ThirdCompressed] = AIVar_Value;
}
else if (Nr_CompressedAIVar == 4)
{
AIVar_Taker.aivar[AIV_FourthCompressed] = AIVar_Value;
};
}
else if (Write_or_Read == 1)
{
AIVar_Value = (Component1 - Component1%Component2) / Component2;

return AIVar_Value;
};
};
};

Teraz czeka nas najbardziej monotonna i mozolna część - zamienianie w plikach wszystkich kompresowanych AIVarów na ich skompresowaną wersję. Tutaj trzeba uważać na jedną rzecz. Część AIVarów, szczególne te 5 bitowe z 1 i 2 skompresowanego oznaczające godziny, występują w 2 miejscach jako argumenty innych funkcji. Tak się składa, że nie możemy jako argumentu funkcji wsadzić innej funkcji bo Gothic głupieje. W takiej sytuacji, musimy jako argument wsadzić wartości AIVarów wyciągnęte ze skompresowanego ręcznie. O co chodzi - przykład pliku "_Work/Data/Scripts/Content/AI/Monster/RTN_Monster/ZS_MM_AllScheduler.d". W orginale funkcja wygląda tak:

func void ZS_MM_AllScheduler()
{
self.aivar[AIV_MM_PRIORITY] = PRIO_EAT;

//ADDON>
if (self.guild == GIL_STONEGUARDIAN)
&& (RavenIsDead == TRUE)
{
B_KillNpc (self);
};
//ADDON<

if (Wld_IsTime (self.aivar[AIV_MM_SleepStart],00,self.aivar[AIV_MM_SleepEnd],00) || (self.aivar[AIV_MM_SleepStart] == OnlyRoutine))
{
AI_StartState (self, ZS_MM_Rtn_Sleep, 1, "");
}
else if (Wld_IsTime (self.aivar[AIV_MM_RestStart],00,self.aivar[AIV_MM_RestEnd],00) || (self.aivar[AIV_MM_RestStart] == OnlyRoutine))
{
AI_StartState (self, ZS_MM_Rtn_Rest, 1, "");
}
else if (Wld_IsTime (self.aivar[AIV_MM_RoamStart],00,self.aivar[AIV_MM_RoamEnd],00) || (self.aivar[AIV_MM_RoamStart] == OnlyRoutine))
{
AI_StartState (self, ZS_MM_Rtn_Roam, 1, "");
}
else if (Wld_IsTime (self.aivar[AIV_MM_EatGroundStart],00,self.aivar[AIV_MM_EatGroundEnd],00) || (self.aivar[AIV_MM_EatGroundStart] == OnlyRoutine))
{
AI_StartState (self, ZS_MM_Rtn_EatGround, 1, "");
}
else if (Wld_IsTime (self.aivar[AIV_MM_WuselStart],00,self.aivar[AIV_MM_WuselEnd],00) || (self.aivar[AIV_MM_WuselStart] == OnlyRoutine))
{
AI_StartState (self, ZS_MM_Rtn_Wusel, 1, "");
}
else if (Wld_IsTime (self.aivar[AIV_MM_OrcSitStart],00,self.aivar[AIV_MM_OrcSitEnd],00) || (self.aivar[AIV_MM_OrcSitStart] == OnlyRoutine))
{
AI_StartState (self, ZS_MM_Rtn_OrcSit, 1, "");
}
else
{
AI_StartState (self, ZS_MM_Rtn_Rest, 1, ""); //Default = Rest
};
};

Jak widać w funkcji "Wld_IsTime" jednymi z argumentów są wartości AIVarów, które po skompresowaniu będziemy wyciągać za pomocą funkcji. Mielibyśmy więc w tym przypadku funkcję "Byte_for_AIVars" jako argument funkcji "Wld_IsTime". Unikamy tego wpisując wartości AIVarów ręcznie:

func void ZS_MM_AllScheduler()
{
Byte_for_AIVars(self, AIV_MM_PRIORITY, PRIO_EAT, 0);

//ADDON>
if (self.guild == GIL_STONEGUARDIAN)
&& (RavenIsDead == TRUE)
{
B_KillNpc (self);
};
//ADDON<

if (Wld_IsTime ((self.aivar[AIV_FirstCompressed]%1024 - (self.aivar[AIV_FirstCompressed]%1024)%32) / 32,00,(self.aivar[AIV_FirstCompressed]%32768 - (self.aivar[AIV_FirstCompressed]%32768)%1024) / 1024,00) || ((self.aivar[AIV_FirstCompressed]%1024 - (self.aivar[AIV_FirstCompressed]%1024)%32) / 32 == 31))
{
AI_StartState (self, ZS_MM_Rtn_Sleep, 1, "");
}
else if (Wld_IsTime ((self.aivar[AIV_FirstCompressed]%1048576 - (self.aivar[AIV_FirstCompressed]%1048576)%32768) / 32768,00,(self.aivar[AIV_FirstCompressed]%33554432 - (self.aivar[AIV_FirstCompressed]%33554432)%1048576) / 1048576,00) || ((self.aivar[AIV_FirstCompressed]%1048576 - (self.aivar[AIV_FirstCompressed]%1048576)%32768) / 32768 == 31))
{
AI_StartState (self, ZS_MM_Rtn_Rest, 1, "");
}
else if (Wld_IsTime ((self.aivar[AIV_FirstCompressed]%1073741824 - (self.aivar[AIV_FirstCompressed]%1073741824)%33554432) / 33554432,00,(self.aivar[AIV_SecondCompressed]%32 - (self.aivar[AIV_SecondCompressed]%32)%1) / 1,00) || ((self.aivar[AIV_FirstCompressed]%1073741824 - (self.aivar[AIV_FirstCompressed]%1073741824)%33554432) / 33554432 == 31))
{
AI_StartState (self, ZS_MM_Rtn_Roam, 1, "");
}
else if (Wld_IsTime ((self.aivar[AIV_SecondCompressed]%1024 - (self.aivar[AIV_SecondCompressed]%1024)%32) / 32,00,(self.aivar[AIV_SecondCompressed]%32768 - (self.aivar[AIV_SecondCompressed]%32768)%1024) / 1024,00) || ((self.aivar[AIV_SecondCompressed]%1024 - (self.aivar[AIV_SecondCompressed]%1024)%32) / 32 == 31))
{
AI_StartState (self, ZS_MM_Rtn_EatGround, 1, "");
}
else if (Wld_IsTime ((self.aivar[AIV_SecondCompressed]%1048576 - (self.aivar[AIV_SecondCompressed]%1048576)%32768) / 32768,00,(self.aivar[AIV_SecondCompressed]%33554432 - (self.aivar[AIV_SecondCompressed]%33554432)%1048576) / 1048576,00) || ((self.aivar[AIV_SecondCompressed]%1048576 - (self.aivar[AIV_SecondCompressed]%1048576)%32768) / 32768 == 31))
{
AI_StartState (self, ZS_MM_Rtn_Wusel, 1, "");
}
else if (Wld_IsTime ((self.aivar[AIV_SecondCompressed]%1073741824 - (self.aivar[AIV_SecondCompressed]%1073741824)%33554432) / 33554432,00,(self.aivar[AIV_FirstCompressed]%32 - (self.aivar[AIV_FirstCompressed]%32)%1) / 1,00) || ((self.aivar[AIV_SecondCompressed]%1073741824 - (self.aivar[AIV_SecondCompressed]%1073741824)%33554432) / 33554432 == 31))
{
AI_StartState (self, ZS_MM_Rtn_OrcSit, 1, "");
}
else
{
AI_StartState (self, ZS_MM_Rtn_Rest, 1, ""); //Default = Rest
};
};

Podane wyżej wartości będą poprawne tylko, jeśli nie zmienicie wartości "Nr_CompressedAIVar", "Bit_AIVar_CompressedAIVar", "Bit_Position_AIVar" podanych przeze mnie. Jak zmienicie to musicie je sobie wyliczyć na nowo i wstawić. Oczywiście stałym "AIV_FirstCompressed", "AIV_SecondCompressed", "AIV_ThirdCompressed" i "AIV_FourthCompressed" nadajemy wartości jakichś wolnych AIVarów. Lista wolnych AIVarów po kompresji:

//const int AIV_TALENT_INDEX                                         = 89; - wykorzystywany przez LeGo do tworzenia nowej umiejętności, ale możemy go sobie zabrać i użyć do własnych celów.

const int AIV_90                         = 90;
const int AIV_91                         = 91;
const int AIV_92                         = 92;

const int AIV_93                 = 93;
const int AIV_94                 = 94;
const int AIV_95                         = 95;

const int AIV_96         = 96;
const int AIV_97                 = 97;
const int AIV_98                 = 98;

const int AIV_99           = 99;

const int AIV_FirstCompressed = 0;
const int AIV_SecondCompressed = 1;
const int AIV_ThirdCompressed = 3;
const int AIV_FourthCompressed = 5;

const int Free_AIVar_01 = 6;
const int Free_AIVar_02 = 8;
const int Free_AIVar_03 = 9;

const int Free_AIVar_04 = 10;
const int Free_AIVar_05 = 11;
const int Free_AIVar_06 = 12;
const int Free_AIVar_07 = 14;
const int Free_AIVar_08 = 15;
const int Free_AIVar_09 = 16;
const int Free_AIVar_10 = 17;

const int Free_AIVar_11 = 18;
const int Free_AIVar_12 = 19;
const int Free_AIVar_13 = 21;
const int Free_AIVar_14 = 25;
const int Free_AIVar_15 = 26;
const int Free_AIVar_16 = 28;
const int Free_AIVar_17 = 29;

const int Free_AIVar_18 = 30;
const int Free_AIVar_19 = 31;
const int Free_AIVar_20 = 32;
const int Free_AIVar_21 = 33;
const int Free_AIVar_22 = 34;
const int Free_AIVar_23 = 35;
const int Free_AIVar_24 = 36;

const int Free_AIVar_25 = 37;
const int Free_AIVar_26 = 38;
const int Free_AIVar_27 = 39;
const int Free_AIVar_28 = 40;
const int Free_AIVar_29 = 41;
const int Free_AIVar_30 = 42;
const int Free_AIVar_31 = 45;

const int Free_AIVar_32 = 47;
const int Free_AIVar_33 = 48;
const int Free_AIVar_34 = 49;
const int Free_AIVar_35 = 50;
const int Free_AIVar_36 = 51;
const int Free_AIVar_37 = 52;
const int Free_AIVar_38 = 54;

const int Free_AIVar_39 = 55;
const int Free_AIVar_40 = 56;
const int Free_AIVar_41 = 57;
const int Free_AIVar_42 = 58;
const int Free_AIVar_43 = 61;
const int Free_AIVar_44 = 65;
const int Free_AIVar_45 = 66;

const int Free_AIVar_46 = 67;
const int Free_AIVar_47 = 70;
const int Free_AIVar_48 = 71;
const int Free_AIVar_49 = 72;
const int Free_AIVar_50 = 73;
const int Free_AIVar_51 = 74;
const int Free_AIVar_52 = 75;

Po skończonej kompresji mamy łącznie 63 wolne AIVary, czyli więcej niż zajętych. Jak ktoś bardzo chce i potrzebuje, to może np. przyjąć, że AIVary określające poziom władania bronią nigdy nie przekroczy nam 127 ( 8 bitów) i 3 z nich skompresować w 1 zwalniając 2, itp.

Rozwiązanie to ma jedną wadę. Nie pamiętam dokładnie jak to było, ale zaraz po włączeniu Gothica, chyba LeGo i Ikarus (?) nie inicjują się do pierwszego wczytania gry. Oznacza to, że żeby wszystko działało, to po włączeniu nowej gry musimy dać nową grę jeszcze raz - odpalić nową grę z już załadowanej gry a nie z menu głównego, inaczej nie będzie działać, AIVary NPCtom się nie ustawią i będzie burdel kompletny. Wydaje mi się, że Siemekk kiedyś napisał jak sobie z tym poradzić, żeby Ikarus był zainicjowany od razu po włączeniu gry, ale nie zapisałem tego nigdzie a teraz znaleźć nie mogę. Może jak go ładnie poprosicie to to wrzuci.

7
Skrypty / [G2NK] Focus na voby podczas kroku w bok.
« dnia: 2020-06-24, 11:45 »
Witam. Mam problem, którego nie wiem nawet z której strony musiałbym ugryźć, bo nic mi nie przychodzi do głowy. Otóż jak wiadomo, w Gothicu podczas kroku w bok nie możemy namierzać itemów na ziemi ani npc, dlatego np. Można łatwo zbugować wszelkiej maści strażników przy bramach. Pytanie moje brzmi, jak ustawić, żeby podczas chodzenia na boki mieć focus na itemy i NPC tak, jak przy biegnięciu przed siebie tak, jak to było np. W Returningu 2.0?

8
Skrypty / [G2NK] Zmiana stringa na instancję.
« dnia: 2020-06-22, 11:13 »
Witam. Od dawna nurtuje mnie jedna rzecz. Załóżmy, że złożyłem sobie z jakichś części jednego stringa i brzmi on np. "ITSC_FIREBOLT". Tak się składa, że istnieje w grze instancja "ITSC_FIREBOLT". Tutaj moje pytanie: czy da się z tego otrzymanego przeze mnie stringa zrobić jakoś tą instancję? Chodzi mi o to, że mam stringa a ja chcę z tego stringa dostać inta, którego będę mógł wykorzystać np. Do spawnowania tego itemu?

9
Witam. Mam pytanie jak w temacie posta. Jak mogę sprawdzić, która opcja dialogowa w czasie rozmowy (czy monologu) jest aktualnie zaznaczona? Chodzi mi o to, że prowadząc rozmowę, po najechaniu np. na opcję "Koniec" coś się dzieje.

10
Skrypty / [G2NK] Zmiania rozmiaru komórek w ekwipunku
« dnia: 2020-04-04, 03:59 »
Witam ponownie. Chciałem zmniejszyć rozmiary komórek w ekwipunku (żeby więcej wierszy się zmieściło i szerokość całej kolumny się zmniejszyła). Znalazłem w SystemPack.ini linijkę "InventoryCellSize" i próbowałem zmieniać tam wartości, ale nic się nie dzieje. Zgaduję, że ten parametr działa tylko w G1. W jaki sposób mogę zatem zmienić wielkość tych komórek? I czy dałoby się ewentualnie tym samym sposobem zmienić wielkość i położenie innych elementów ekwipunku, np. pola na środku na dole ekranu z opisem przedmiotu, statystykami i jego renderem, czy pola z ilością złota?

11
Skrypty / [G2NK] Funkcje renderujące z LeGo
« dnia: 2020-03-06, 03:22 »
Witam.
Chciałem skorzystać z funkcji do renderowania przedmiotów (oCItem_Render, Render_AddItem) ale nie mam zielonego pojęcia jak się za to zabrać. Nie ważne co próbowałem do nich wstawiać, nic się nie renderowało. Przeszukałem TheModders, WorlfOfGothic i niczego na temat tych funkcji nie znalazłem (albo jestem ślepy). Na wiki LeGo też nie ma żadnego wyjaśnienia ani przykładu ich użycia. Jeśli ktoś miałby chwilę czasu to mógłby mi wytłumaczyć jak laikowi jak się tych funkcji używa? Skąd należy brać argumenty tej funkcji? Te funkcje można tak po prostu wywołać, czy trzeba je wywołać razem z innymi funkcjami, żeby w ogóle działały? Byłbym bardzo wdzięczny za naprowadzenie.

12
Witam. Problem pewnie banalny, ale krew mnie już zalewa. Chciałem dodać u siebie goblina na ścierwojadzie. Wsadziłem animacje i MDS, przywołuje goblina w grze i ten cały czas jakby poruszał się po płaskiej powierzchni, tj. jak idzie pod górę to lekko zapada się pod ziemię aż ta go nie wypchnie a jak idzie w dół to cały czas "spada". Wygląda to tak samo jak w przypadku zbroi jak skompiluje się je 1 raz. Normalnie na takie coś pomagało wpisanie ciała do MDSa i włączenie Gothica 2 raz - ciało jest wpisane i za każdym razem jest to samo. Próbowałem wrzucać już skompilowane pliki, zmieniać pozycję bazowego ciała w Gmaxie, nawet przepisałem od nowa MDSa i nic. Co mogę jeszcze z tym zrobic?

13
Witam. Napisałem funkcję, która zmienia wartość zmiennej odpowiadającej za obrażenia danej broni w zależności od jakichś tam parametrów, plik z funkcją wpisałem do Gothic.src i samą funkcję wywołałem w startupie.

FF_ApplyExt (B_DamageChange, 1000, -1);

Funkcja działa i obrażenia broni się zmieniają ale dopiero po zdjęciu i założeniu nowej broni lub wczytaniu gry. Co zrobić, żeby obrażenia aktualizowały się na bieżąco? I czy da się to zrobić w miarę prosty sposób, bo żadnym znawcą Ikarusa nie jestem. Jak się okaże, że przerasta to mój mały mózg to dam sobie spokój  :P

14
Witam,
Dodałem do Gothica hełmy i wszystko jest w porządku, hełm zachowuje się tak jak należy, także przy wykonywaniu oryginalnie-gothicowych animacji (przede wszystkim postawa bojowa i walka). Problem pojawił się, kiedy dodałem do gry także tarcze i animacje do nich (połączone animacje z L'Hivera i USWT), mając włączone animacje dla tarczy z hełmem na głowie, zaczynają dziać się cuda i przestaje on ładnie leżeć na głowie.


(Góra - zwykłe - gothicowe animacje (np. postawa bojowa gothicowa). Dół - dodane animacje tarczy i fruwający hełm.)

Ponieważ problemu tego nie ma w przypadku zbroi z wbudowanym hełmem (np. pancerz paladyna) to stwierdziłem, że problem leży w braku sił trzymających model hełmu z kością głowy. Chciałem dodać hełm jako ASC z przypisaną siłą do gości głowy - niestety jak można się domyślić nic z tego nie wyszło, bo Gothic jako hełmy widzi tylko meshe. Dodanie podmiany ASC w skryptach po założeniu hełmu też nic nie daje, bo ASC podmienia całe ciało, wliczając w to założoną zbroję. Idąc dalej tokiem rozumowania, że winnym takiego stanu rzeczy jest brak sił, rozpakowałem ASC. głowy, nałożyłem na niego w programie 3D hełm, scaliłem je w 1 model i w skryptach ustawiłem przy zakładaniu hełmu zmianę głowy z oryginalnej na głowę z wbudowanym w nią hełmem.
I na tym etapie się zatrzymałem. Teraz niby działa i hełm razem z głową trzymają się kości głowy tak jak ma być, ale jak widać na 1 rzut oka takie rozwiązanie ma masę wad - przede wszystkim głowa staje się statycznym obiektem pozbawionym animacji (robienie ręcznie kompletu animacji dla każdej głowy - hełmu z osobną mija się z celem bo roboty więcej niż to jest warte). Ponadto traktując hełm jako pancerz
mainflag = ITEM_KAT_ARMOR;
wear = WEAR_HEAD;
i tak na głowę zakładany jest dodatkowo model 3D, bez linijki "wear" hełmu nie można w ogóle użyć.

I tutaj moja prośba i pytanie - czy można te hełmy naprawić w jakiś prostszy sposób tylko ja kombinuję jak koń pod górę?
A jeśli nie i jestem skazany na głowę bez animacji - jak mogę wyłączyć nakładanie modelu 3D na głowę przy nakładaniu hełmu? Próbowałem np. zrobić 2 model hełmu z przezroczystą teksturą i dodać linijkę
visual_change = "TRANSPARENT.3ds";ale Gothic ma chyba wywalone na "visual_change" w hełmach.
Ostatecznie zmieniłem hełmowi mainflagę z "ITEM_KAT_ARMOR" na "ITEM_KAT_MAGIC" a flagę na "ITEM_THROW", co po dodaniu warunków w skryptach powinno działać (żeby nie zakładało 107 hełmów naraz), ale czy można to zrobić w jakiś prostszy sposób? Zależy mi także na pewnej estetyce a to spowoduje bajzel w kolejności ułożenia itemów w ekwipunku. Flagę "ITEM_THROW" chciałem wykorzystać do pierścieni (a wtedy hełmy z pierścieniami pewnie w ogóle się wymieszają). Robienie ręcznie wszystkich możliwych kombinacji hełmów i zbroi też sensu nie ma. :P

Także po wyczerpaniu chyba wszystkich pomysłów proszę o pomoc starszych i mądrzejszych.  ;( Tym bardziej mnie to zastanawia, bo w takim Returningu hełmy działają dobrze, a w skryptach nie widzę tam żadnych udziwnień w tym kierunku.

15
Witam,
Męczę się z tym już nie wiem nawet ile i zaczynam powoli głupieć i nie wiem już co ja k***a robię źle.
Dodałem do gry pewną zbroję (nie pierwszą więc wydaje mi się, że wiem jak się to robi), dodałem jej ASC, zarejestrowałem w HumanS, dodałem model 3D, oteksturowałem, tekstura o dziwo też się skompilowała. Wchodzę do gry, przywołuję zbroję, zakładam na siebie, wszystko ładnie. Przywołuję postać z innymi zbrojami i c**j model 3D dodanej zbroi ma już inną teksturę (ASC jest ok). Wychodzę z gry i widzę, że z niewiadomych mi przyczyn Gothic za nic nie chce skompilować modelu 3D zbroi do MRM. Zacząłem sprawdzać w programie 3D czy tekstury w modelu tej zbroi (i tych zbroi których tekstury się na nią nakładają) są ok i czy nazwy materiałów nie są takie same. Skończyło się na tym, że po zmianie nazw materiałów ASC zbroi, Gothic ich też już nie chce skompilować. (skompilowane pliki rzecz jasna za każdym razem usuwałem) Nie wiem już co ja do cholery robię źle i czemu Gothic odmawia mi teraz posłuszeństwa, skoro niejeden model już do gry dodałem. Byłbym wdzięczny za pomoc.

16
Witam.
Dodałem do gry kilkanaście nowych pancerzy i o ile z plikami .asc wszystko jest w porządku, to z plikami .3ds męczę się już 2 miesiące. Wszystko robiłem zgodnie z instrukcjami Czip'a:
https://www.youtube.com/playlist?list=PL6F0BF678B9BA50BFTutaj pojawia się mój problem: Po wejściu do gry i przywołaniu pancerzy, tekstura na modelu 3d (zbroi w ekwipunku, na ziemi) jakby nadpisuje się. Tzn. Przywołuję pierwszy pancerz, jest ok. Przywołuję drugi pancerz, 1 i 2 mają teksturę drugiego pancerza. Przywołuję trzeci pancerz to samo. itd. itd. Po wczytaniu gry, przywołaniu itemhoshiego zamiast każdego z pancerzy pojedynczo, wszystkie modele 3d które były przeze mnie edytowane mają teksturę jakiejś losowej zbroi.


Problem tyczy się tylko zbroi których pliki .3ds edytowałem (edytowałem tylko przez podmienienie tekstury, nie ważne czy na nową teksturę czy na już istniejącą w grze).
Teksturę podmieniałem w programie Gmax (z kerraxem), próbowałem też na żywca podmieniać teksturę w notepadzie++, efekt jest ten sam. Po każdej zmianie usuwałem pliki zbroi .MRM z folderu "_compiled". Wszystkie tekstury w formatach ".tga" i ".TEX" są w odpowiednich folderach.

Czy ktoś miał kiedyś podobny problem albo po prostu wie co robię źle? Z góry dzięki za pomoc.

17
Witam.
Mam dość niepokojący mnie problem. Wprowadziłem do Gothica kilka nowych zbroi (w tym kilka "nowych" modeli powstałych z przerobienia już obecnych w grze) zgodnie z instrukcjami Czipa 17:
https://www.youtube.com/playlist?list=PLM9vkMnYZSkicEBAEroTOfM7iquIfKVxRKiedy wchodzę do gry i kodami przywołuję sobie te nowe zbroje i je zakładam, NPC (z tego co zauważyłem to tylko ci, których nie zdążyłem jeszcze ani raz spotkać) wyglądają np tak:

Wygląda to tak, jakby pancerz był na nich nałożony (nałożenie pancerza na ciało a nie zamiana ciała jak normalnie jest), mimo, że mają na sobie inne zbroje. Tyczy się to tylko (z tego co zauważyłem) właśnie nowych, wprowadzonych przeze mnie zbroi.

Może mi ktoś doradzić o co chodzi, jaki jest powód, jak mogę temu zaradzić? Może zapomniałem/nie wiedziałem że trzeba czegoś zrobić?

18
Witam.
Znalazłem na WOG kilka świetnych tekstur, jednak stworzone one są do niektórych modelów zbroi bez hełmów, z nimi zwyczajnie słabo wyglądają, dlatego chciałem w Gmaxie pousuwać hełmy z z tych modeli i problem z głowy. Z czapką w ubraniu kapitana (Greg) się udało, jednak jeśli chcę importować plik z modelem np. Średni pancerz łowcy smoków (i nie tylko) pojawia się sajgon.

Może mi ktoś doradzić co zrobić żeby model normalnie się zachowywał?
Jest to spowodowane tym, że ten pancerz składa się z 2 części? (z tego co mi się zdaje to pancerz osobno, hełm osobno) Jeśli tak to jak mogę sobie z tym poradzić? Może jest jakiś prostszy sposób na szybkie i łatwe usunięcie hełmu bez potrzeby użycia programu 3D w sytuacji gdy właśnie hełm i pancerz są osobno?

19
Witam.

Chciałem zbalansować nieco czary w Gothicu i wprowadzić opcję, że po użyciu czarów magii ognia (jeśli przeciwnik ma odpowiednio niską obronę przed magią) jest on podpalany i np. przez 5 sekund podpalenie zadaje mu "x" pkt obrażeń (te już niezależnie od obrony).
W tym celu przez pare dni kombinowałem, na początek chciałem po prostu zmienić typ obrażeń tych czarów z "DAM_MAGIC" na "DAM_FIRE", ale z tego co widzę to obrażenia od ognia są niejako "przypisane" do smoków i ognistych jaszczurów i takie płonięcie zadaje stałe 50 pkt obrażeń. Nie mam pojęcia jak to zmienić ani w ogole czy się da to tak prosto zrobić więc zacząłem kombinować inaczej.
Przerobiłem plik ZS_MagicFreeze tak, żeby zadawać obrażenia po użyciu np. ognistej strzały (dodałem oczywiście odpowiednie stałe (obrażenia na sekundę i czas trwania) w pliku odpowiadającym za wspomnianą ognistą strzałę, dodałem też efekt dla ognistej strzały w pliku "B_AssesMagic"), innym razem "aktywowałem" gotowy już plik "ZS_MagicBurn" i wszystko nawet działa, obrażenia od podpalenia są naliczane przez te 5 sekund, z tym, że podczas podpalenia i naliczania obrażeń przeciwnik zamiera w miejscu.

To jest problem którego przeskoczyć nijak nie mogę, w jaki sposób mogę wprowadzić to nieszczęsne podpalenie w taki sposób, żeby przeciwnik nie zamierał w miejscu (coś na kształt podpalenia przez ognistego jaszczura tylko najlepiej od magii a nie od ognia)? Może pliki ZS_ po prostu mają "wbudowane" w sobie zamieranie w miejscu? Mam coś poprawić w plikach ZS_, czy sposobu należy szukać zupełnie gdzie indziej? A może da się edytować to gotowe podpalenie (np. ogniste jaszczury) zmieniając jego obrażenia, typ obrażeń i czas trwania w zależności od użycia czaru?

Pozdrawiam i proszę o pomoc...  ;(

Strony: [1]
Do góry