Neverwinter Nights by Tichondrius

Banner-Tichondrius

Toolset > Scripting


Neverwinter Nights Scripting průvodce od Jindragon.

Čtvrtá kapitola scriptování v NWN

4.1 Události (Events)

Pokud chceme aby se script spouštěl za určitých podmínek přiřadíme ho k některému objektu a ke konkrétní události. Když je script události spuštěn, nejdůležitější je určit kdo nebo co ho spustilo.

4.2 Objekty s událostmi
Objektem se rozumí například NPC, placeable jako jsou truhly a podobné. Objekty s událostmi umožňují vzájemné působení a reakci s PC, tím že se na jednotlivé události můžou připojit různé scripty.

Seznam všech objektů s událostmi:
Area (lokace)
Creature (bytost)
Door (dveře)
Encounter (setkání)
Module (modul)
Placeable Object (umístitelný objekt)
Trap (past)
Trigger (spoušť)

4.3 Area (lokace)
Lokace je založena na daném tilesetu, jedná se o jakékoliv místo v tvém modulu, například tajemný hrad nebo temná jeskyně. Lokace může obsahovat mnoho dalších objektů s událostmi.

Lokace obsahuje tyto události:
OnEnter -script se spustí po vstupu do lokace
OnExit - script se spustí po opuštění lokace
OnHeartbeat - script se spouští každých 6 sekund
OnUserDefined - script se spustí podle nastavení v OnSpawn scriptu

4.4 Creature (bytost)
Bytosti nebo také NPC.

Bytost obsahuje tyto události:
OnBlocked -script se spustí pokud bytosti blokují cestu dveře
OnCombatRoundEnd -script se spustí na konec každého kola souboje
OnConversation -script se spustí když dialog s bytostí skončí
OnDamaged - script se spustí když objekt je poškozen
OnDeath -script se spustí pokud je objekt zničen
OnDisturbed -script se spustí pokud je bytost vyrušena
OnHeartbeat - script se spouští každých 6 sekund
OnPerception -script se spustí ve chvíli když bytost spatří jinou bytost
OnPhysicalAttacked -script se spustí při fyzickém útoku na objekt
OnRested -script se spustí, když se bytost pokusí odpočívat
OnSpawn -script se spustí při objevení bytosti v dané lokaci
OnSpellCastAt - script se spustí pokud se objekt stane cílem kouzla
OnUserDefined - script se spustí podle nastavení v OnSpawn scriptu

4.5 Door (dveře)
Dveře slouží k oddělení jednotlivých místností v lokaci, nebo můžou sloužit k přesunu do jiné lokace.

Dveře obsahují tyto události:
OnAreaTransitionClick -script se spustí když PC projde přechodem dvou lokací
OnClose -script se spustí když objekt je zavřen
OnDamaged -script se spustí když objekt je poškozen
OnDeath -script se spustí pokud je objekt zničen
OnFailToOpen -script se spustí když se pokus o otevření dveří nezdaří
OnHeartbeat -script se spouští každých 6 sekund
OnLock -script se spustí když objekt je zamknut
OnOpen -script se spustí když objekt je otevřen
OnPhysicalAttacked -script se spustí pokud je objekt poprvé napaden, neplatí pro boj
OnSpellCastAt -script se spustí pokud se objekt stane cílem kouzla
OnUnlock -script se spustí když objekt je odemknut
OnUserDefined - script se spustí podle nastavení v OnSpawn scriptu

4.6 Setkání (Encounter)
Setkání je spoušť, která automaticky spustí spawn bytostí.

Setkání obsahuje tyto události:
OnEnter - script se spustí po vstupu do lokace
OnExhausted - script se spustí v chvíli když poslední bytost setkání zemře
OnExit - script se spustí po opuštění lokace
OnHeartbeat - script se spouští každých 6 sekund
OnUserDefined - script se spustí podle nastavení v OnSpawn scriptu

4.7 Modul (Module)
Modul může být jedno dobrodružství, které postavíš v toolsetu, nebo jeden velký perzistentní svět.

Modul obsahuje tyto události:
OnAcquireItem - script se spustí když PC získá nějakou věc
OnActivateItem - script se spustí když PC aktivuje nějakou věc
OnClientEnter - script se spustí po vstupu do modulu
OnClientLeave - script se spustí po opuštění modulu
OnCutsceneAbort- script se spustí pokud se PC pokusí ukončit cutscene
OnHeartbeat - script se spouští každých 6 sekund
OnModuleLoad - script se spustí po nahrání modulu
OnPlayerDeath - script se spustí pokud životy PC klesnou pod -10 životů
OnPlayerDying - script se spustí pokud životy PC klesnou na 0 životů
OnPlayerLevelUp - script se spustí když PC získá novou úroveň
OnPlayerRespawn - script se spustí po respawnu PC
OnPlayerRest - script se spustí při pokusu PC odpočívat
OnUnAcquireItem - script se spustí když je věc odebrána z inventáře PC
OnUserDefined - script se spustí podle nastavení v OnSpawn scriptu

4.8 Umístitelný Objekt (Placeable Object)
Jedná se o speciální objekty jako jsou stromy, truhly nebo vizuální efekty. Můžou obsahovat vlastní inventář s věcmi.

Umístitelný Objekt obsahuje tyto události:
OnClose - script se spustí když objekt je zavřen
OnDamaged - script se spustí když objekt je poškozen
OnDeath - script se spustí pokud je objekt zničen
OnDisturbed- script se spustí pokud je bytost vyrušena
OnHeartbeat - script se spouští každých 6 sekund
OnLock - script se spustí když objekt je zamknut
OnOpen - script se spustí když objekt je otevřen
OnPhysicalAttacked - script se spustí pokud je objekt poprvé napaden, neplatí pro boj
OnSpellCastAt -script se spustí pokud se objekt stane cílem kouzla
OnUnlock -script se spustí když objekt je odemknut
OnUsed - script se spustí když objekt je použit
OnUserDefined - script se spustí podle nastavení v OnSpawn scriptu

4.9 Past (Trap)
Past je druh spouště, který po spuštění zraní toho kdo ji spustil. Past může být detekována a následně deaktivována.

Past obsahuje tyto události:
OnDisarm - script se spustí po odstranění pasti
OnTrapTriggered - script se spustí když past je spuštěna

4.10 Spoušť (Trigger)
Jsou tu tři druhy spouští: area transitions, generic triggers a traps. Area transitions neboli přesun do jiné lokace, slouží ke spojení dvou lokací. Generic trigger neboli obecná spoušť může mít vlastní scriptovanou událost, například upozornění PC na nějakou skrytou věc. Past je vymezená sekce na zemi, která způsobí zranění PC nebo NPC jestliže ji spustí.

Spoušť obsahuje tyto události:
OnClick - script se spustí jakmile PC klikne na přesun do jiné lokace
OnEnter - script se spustí při kontaktu se spouští
OnExit - script se spustí po opuštění spouště
OnHeartbeat - script se spouští každých 6 sekund
OnUserDefined - script se spustí podle nastavení v OnSpawn scriptu

V dalších odstavcích podrobněj popíšu jednotlivé události a uvedu pár příkladů.

4.11 OnAcquireItem
Script připojený k této události se spustí, když objekt získá nějakou věc. Daná věc může být porovnaná oproti seznamu věcí, jestliže je daná věc v seznamu můžou se kolem postavy znenadání objevit nebezpečné potvory.


Funkce:
GetModuleItemAcquired() – vrátí věc která právě byla získaná (a spustí tuto událost).
GetModuleItemAcquiredFrom() – vrátí objekt z kterého byla daná věc získaná
GetItemPossessor(object oItem) – vrátí objekt který vlastní danou věc

Známé chyby:
Událost se nespustí pokud PC sebere zlato, nebo když je věc přidaná do existujícího hromádky v inventáři.

Příklad:

//Pokud je tento script připojen na událost OnAcquireItem,
//zapíše záznam do log souboru, kdykoliv PC získá věc.
//Záznam bude obsahovat jméno PC, které získalo danou věc, věc,
//a objekt z kterého byla věc získaná
void main()
{
    object oItem = GetModuleItemAcquired();
    object oPC = GetItemPossessor(oItem);
     object oLostBy = GetModuleItemAcquiredFrom(); string sLog = GetName(oPC) + " získal " + GetName(oItem) + " od " + GetName(oLostBy);
    PrintString(sLog);
}

4.12 OnActivateItem
Script připojený k této události se spustí, když daná věc je aktivovaná. Jedná se většinou o speciální věc, kterou PC aktivuje ve svém inventáři.

Funkce:
GetItemActivated() - vrátí věc která byla aktivovaná
GetItemActivatedTarget() – pokud cílem kouzla "Unique Power (Vlastní jedinečná moc)" je objekt vrátí cíl tohoto kouzla
GetItemActivatedTargetLocation() – pokud cílem kouzla "Unique Power" je bod vrátí lokaci cíle tohoto kouzla
GetItemActivator() – vrátí vlastníka věci, která byla aktivovaná

Poznámka:
Událost vlastní modul. To znamená například, pokud PC zabije NPC pomocí věci, která vlastní jedinečnou moc tak zkušenost nedostane PC, ale modul.

Příklad:
// Alicia stone of return
//Pokud PC aktivuje věc “Alicia stone of return“
//spustí se následující script, který způsobí
//přesun PC do lokace, kde se nachází kontrolní bod "port_alicia".
object oItemToTake;
oItemToTake = GetItemPossessedBy(oActivator, "ALICIA_RECALL");
if (sItemTag=="ALICIA_RECALL")
{
    string sPCLoc=GetTag(GetArea(oActivator));
    if (!(sPCLoc=="Ocistec"))
    {
        ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(VFX_FNF_WAIL_O_BANSHEES),oActivator, 1.0);
         DelayCommand(4.0,AssignCommand(oActivator, JumpToLocation(GetLocation(GetObjectByTag ("port_alicia")))));
         if(GetIsObjectValid(oItemToTake) != 0)
         DestroyObject(oItemToTake);
     }
}

4.13 OnAreaTransitionClick
Script připojený k této události se spustí, když PC vstoupí na přechod dvou lokací. Jestliže script je připojen k této události, tak se musí nastavit přechod mezi lokacemi manuálně, protože standardní přechod nebude fungovat.

Funkce:
GetClickingObject()- vrátí poslední objekt který kliknul na dveře

Poznámka:
OnAreaTransitionClick se používá jen pro dveře.

4.14 OnBlocked
Script připojený k této události se spustí, když bytosti stojí v cestě dveře. Tato událost může být například použita proto, aby daná potvora zanechala sledováni pronásledované oběti pokud bude mít v cestě dveře. Script se nespustí pokud bytost blokuje jiný objekt.

Funkce:
GetBlockingDoor() – vrátí dveře, které zablokovali pohyb bytosti.

Příklad:

//::///////////////////////////////////////////////
//:: Default On Blocked
//:: NW_C2_DEFAULTE
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Pokud bytost budou blokovat dveře, podle inteligence se rozhodne je otevřít nebo rozbít.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Nov 23, 2001
//::////////////////////////////////////////////// void main()
{
    object oDoor = GetBlockingDoor();
     if (GetObjectType(oDoor) == OBJECT_TYPE_CREATURE)
    {
        // * Increment number of times blocked
         /*SetLocalInt(OBJECT_SELF, "X2_NUMTIMES_BLOCKED", GetLocalInt(OBJECT_SELF, "X2_NUMTIMES_BLOCKED") + 1);
         if (GetLocalInt(OBJECT_SELF, "X2_NUMTIMES_BLOCKED") > 3)
         {
             SpeakString("Blocked by creature");
             SetLocalInt(OBJECT_SELF, "X2_NUMTIMES_BLOCKED",0);
             ClearAllActions();
             object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);
             if (GetIsObjectValid(oEnemy) == TRUE)
              {
                  ActionEquipMostDamagingRanged(oEnemy);
                 ActionAttack(oEnemy);
              }
             return;
         } */
         return;
     }
    if(GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 5)
    {
        if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_OPEN) && GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 7 )
        {
            DoDoorAction(oDoor, DOOR_ACTION_OPEN);
        }
    else if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_BASH))
         {
        DoDoorAction(oDoor, DOOR_ACTION_BASH);
        }
    }
}

4.15 OnClick
Script připojený k této události se spustí, když PC klikne na přechod mezi lokacemi.

Funkce:
GetClickingObject() – vrátí PC které kliklo na přechod mezi lokacemi.

4.16 OnClientEnter
Script připojený k této události se spustí, když klient vstoupí do modulu. Tato událost se především používá k nastavení inicializačních proměnných konkrétního PC.

Funkce:
GetEnteringObject() - vrátí PC, které vstoupilo do lokace

Příklad:

// zapíše jméno a IP adresu
// hráče který právě vstoupil do modulu
void main()
{
     object oPC = GetEnteringObject();
    if (GetIsPC(oPC))
    {
         PrintString(GetPCPlayerName(oPC) + " (" + GetPCIPAddress(oPC) + ")");
    }
}

4.17 OnClientLeave
Script připojený k této události se spustí, když klient opustí modulu. Například může být použito pro zrušení spawnu bytostí.

Funkce:
GetExitingObject() – vrátí PC které opustilo modul.

Poznámka:
Tato událost se nedá použít k nastavení proměnných PC při odchodu z modulu. Tedy nedá se například použít pro zjištění a uložení aktuálního stavu životů PC, které opustilo modul.

4.18 OnClose
Script připojený k této události se spustí, když objekt je zavřen a může být použit k analýze obsahu nebo k otevření blízkých dvěrí.

Funkce:
GetLastClosedBy() – vrátí objekt, který zavřel OBJECT_SELF.

Příklad:

// připojit k truhle (samozřejmě že to nebude pracovat na dveřích)
// jestliže truhla je prázdná, vygeneruje 100 kusů zlata
void main()
{
     // podíváme se jestli je uvnitř nějaká věc
    object oItem = GetFirstItemInInventory();
     if (!GetIsObjectValid(oItem))
     {
        CreateItemOnObject("NW_IT_GOLD001", OBJECT_SELF, 100);
     }
}

4.19 OnCombatRoundEnd
Script připojený k této události se spustí na konci každého kola souboje (každou šestou vteřinu v NWN).

Funkce: DetermineCombatRound(object, int) pro standardní bojovou akci za kolo.

Příklad:
Tato úprava standardního scriptu OnCombatRoundEnd opravuje inteligenci NPC, výměnu zbraně během souboje.
Script kontroluje vzdálenost NPC s nejbližším nepřítelem a jestli je nepřítel platný cíl. Pokud NPC používá střelnou nebo vrhací zbraň a jeho nepřítel je vzdálen méně než 4 metry, vytasí svou sečnou zbraň. Pokud NPC drží v ruce sečnou zbraň a v okolí 4 metrů není žádný nebezpečný nepřítel, vrátí se ke své střelné zbrani. Výsledkem je že NPC používá střelnou zbraň dokud je to bezpečné.

//::///////////////////////////////////////////////
//:: Modified Associate: End of Combat Round
//:: NW_CH_AC3
//:: Original Code Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Calls the end of combat script every round
*/
//:://////////////////////////////////////////////
//:: Original Code Created By: Preston Watamaniuk
//:: Original Code Created On: Oct 16, 2001
//:: Modified Code Created By: Eric Konizer (Layrinn)
//:: Modified Code Created On: July 22, 2002
//:://////////////////////////////////////////////
#include "NW_I0_GENERIC"
void main()
{
     if(!GetSpawnInCondition(NW_FLAG_SET_WARNINGS))
     {
          DetermineCombatRound();
     }
     if(GetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT))
     {
          SignalEvent(OBJECT_SELF, EventUserDefined(1003));
     }
     // Zacatek upravy kodu
     object oNearestEnemy = GetNearestSeenOrHeardEnemy();
     if ( (GetIsObjectValid(oNearestEnemy)) && (GetDistanceBetween(OBJECT_SELF, oNearestEnemy) < 4.0))
     {
          if (!GetLocalInt(OBJECT_SELF, "nTempMelee") && GetAssociateState(NW_ASC_USE_RANGED_WEAPON))
          {
               SpeakString("Bastardi! Pozor jsou moc blizko! Taste sve mece!");
               SetAssociateState(NW_ASC_USE_RANGED_WEAPON, FALSE);
               SetLocalInt(OBJECT_SELF, "nTempMelee", TRUE);
               ClearAllActions();
               ActionDoCommand(EquipAppropriateWeapons(GetMaster()));
               ActionDoCommand(DetermineCombatRound());
          }
     }
     else
     {
          if (GetLocalInt(OBJECT_SELF, "nTempMelee"))
          {
               SpeakString("Dobry, pouzijte sve strelne zbrane!");
               SetAssociateState(NW_ASC_USE_RANGED_WEAPON, TRUE);
               SetLocalInt(OBJECT_SELF, "nTempMelee", FALSE);
               ClearAllActions();
               EquipAppropriateWeapons(GetMaster());
               ActionDoCommand(DetermineCombatRound());
          }
     }
     // Konec upravy kodu
}

4.20 OnConversation

Script připojený k této události se spustí jakmile dialog s bytostí skončí, nebo také když je slyšet křik. Pokud PC mluví, může se tento script spustit, je to dobrá cesta jak dostat speciální odpověď (hádanka, heslo).

Funkce:

GetLastSpeaker() vrátí objekt, kdo kliknul na OBJECT_SELF nebo kdo poslední mluvil.

GetListenPatternNumber() vrátí číslo modelu (jestliže byl nastaven, obvykle v OnSpawn události)

GetMatchedSubstring(int nString) vrátí řetězec, který byl slyšen, nebo část řetězce, který spustil tuto událost.

Příklad:

// Když slyšíme křik 100, slyšíme všechno(SetListeningPattern),
// a můžem zkontrolovat jestli řekl správné heslo.

void main()
{
    // Najdi kdo mluví, a
    int nMatch = GetListenPatternNumber();
    // vezmi řetězec který byl řečen (Nastavení přes // SetListenPattern(OBJECT_SELF, "**", 100); )
    //řetězec bude složen z velkých písmen (tedy nebude závislý na velikosti písmen).
    string sSpoken = GetStringUpperCase(GetMatchedSubstring( 100));
    // Heslo je "Ahoj". if(FindSubString(sSpoken, "Ahoj") >= 0)
    {
        SpeakString( "Spravné heslo!");
    }
}

4.21 OnCutsceneAbort

Událost se spustí, když se PC pokusí ukončit cutscene. Může být použit pro vyhození PC z cutscene módu, zrušení jeho cutscene neviditelnosti, vymazání všech cutscene objektů a jejich aktivních front, a nastavení hry tak jako by skončila normálně.

Funkce:

GetLastPCToCancelCutscene() – hráč který stlačí tlačítko escape

Poznámka:

Jednoduché stlačením tlačítka escape v cutsceně se nestane nic.Všechny události se musí scriptovat.

4.22 OnDamaged

Script připojený k této události se spustí, když je objekt poškozen.

Funkce:

GetLastDamager() – vrátí objekt, který poslední způsobil poškození OBJECT_SELF, způsobuje spuštění této události.

GetTotalDamageDealt() – vrátí velikost poškozeni způsobené bytostí

GetDamageDealtByType(int nDamageType) – vrátí velikost poškození způsobené konkrétním útokem.

GetCurrentHitPoints(object oObject = OBJECT_SELF) – může být použit pro zjištění aktuálních životů

GetMaxHitPoints(object oObject = OBJECT_SELF) – může být použit pro zjištění maximálního počtu životů.

Příklad:

// vložit do události bytosti - OnDamaged
// když bytost ztratí víc jak půlku životů
// ustoupí k waypointu označeným tagem "CAVE_EXIT" a ztratí se
void main()
{
    int nEvent = GetUserDefinedEventNumber();
    if (nEvent = 1006) // OnDamaged událost
     {
        int nMaxHP = GetMaxHitPoints(); // OBJECT_SELF (volající) je nastaven
        int nCurHP = GetCurrentHitPoints(); // OBJECT_SELF (volající) je nastaven
         // míň jak půlka životů z maxima
         if (nCurHP < (nMaxHP / 2))
        {
             // zastav všechno co bytost dělá
             ClearAllActions();
             // řve strachem
             ActionSpeakString( "Pomóc zabíjej mě!");
             // rychle utéct
             ActionMoveToObject(GetObjectByTag( "CAVE_EXIT"), TRUE);
             // zničit sebe ActionDoCommand(DestroyObject( OBJECT_SELF));
             // neakceptovat žádné další AI příkazy (zničen!)
             SetCommandable( FALSE);
         }
     }
}

4.23 OnDeath

Script připojený k této události se spustí, když objekt umře z jakéhokoliv důvodu. Může být použit na objekt, který má něco upustit na zem, objevit se v nové lokaci, nebo způsobit reinkarnaci objektu. DestroyObject nezpůsobí spuštění této události, ale DM kill ano.

Funkce:

GetLastKiller() – vrátí objekt, který zabil OBJECT_SELF

Příklad:

//Vytvoří nad bytostí efekt smrti “ implosion visual“
void main()
{
    location lSelf = GetLocation( OBJECT_SELF);
    effect eVis = EffectVisualEffect(VFX_FNF_IMPLOSION);
     ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lSelf);
}

4.24 OnDisarm

Script připojený k této události se spustí, když je past úspěšně deaktivována. Může být použito jako odměna (XP) za deaktivaci pasti.

Funkce:

GetLastDisarmed() – vrátí bytost nebo PC objekt, který deaktivoval past.

Příklad:

// odměna 1000 XP pro bytost, která úspěšně deaktivuje past
// tento script vložte na OnDisarm událost
void main()
{
     object oPC = GetLastDisarmed();
    if (GetIsPC(oPC))
    {
        GiveXPToCreature(oPC, 1000);
    }
}

4.25 OnDisturbed

Script připojený k této události se spustí, když dojde v inventáři objektu ke změně. Inventář může být narušen pokusem okradením objektu (pickpoket), nebo odebrání věci z umístitelného objektu  (placeable) inventáře.

Funkce:

GetLastDisturbed() – vrátí objekt, který poslední vyrušil OBJECT_SELF

GetInventoryDisturbType() – vrátí jednu konstantu z INVENTORY_DISTURB_TYPE_* pro určení události.

GetInventoryDisturbItem() – vrátí věc které byla z inventáře odebrána, nebo přidána OBJECT_SELF.

Příklad:

// vložte tento script na událost OnDisturbed bedny.
// Kdykoliv vezme věc z truhly, bude mu účtována
// hodnota dané věci.
void main()
{
    object oItem=GetInventoryDisturbItem();
    object oPC=GetLastDisturbed();
    int nType=GetInventoryDisturbType();
    switch (nType)
    {
    case INVENTORY_DISTURB_TYPE_REMOVED:
    case INVENTORY_DISTURB_TYPE_STOLEN:
        int nAmount=GetGoldPieceValue(oItem);
        AssignCommand(oPC, TakeGoldFromCreature(nAmount, oPC, TRUE));
        SendMessageToPC(oPC, "Krást se nemá. Dej mi tvoje zlato!");
        break;
    }
}

4.26 OnEnter

Script připojený k této události se spustí, když bytost vstoupí do lokace, spoušti nebo setkání.

Funkce:

GetEnteringObject() – vrátí objekt který vstoupil do lokace, spoušti nebo setkání.

Příklad:

void main()
{
    //Po vstupu PC do lokace se zobrazí text.
    object oPC = GetEnteringObject();
    string sMessage ="Obklopil te hnusný zápach spáleného lidského masa.";
    SendMessageToPC (oPC, sMessage);
}


Jindragon


 
 

Toolset


Toolset Tutorial

Or-Horo Tutorial

První Kapitola Scriptování

Druhá Kapitola Scriptování

Třetí Kapitola Scriptování

Čtvrtá Kapitola Scriptování