Item Manipulation Triggers
Z Moriawiki
Item Manipulation Triggers jsou triggery, které se spouští při manipulaci s itemy. Aktuální (a brzy minulý) stav těchto triggerů je založen na zpětné kompatibilitě se sphereserverem. Když jsem je dělal, tak mi na kompatibilitě záleželo víc než teď :) To mě ale mezitím přešlo, takže přišel čas udělat to po svém, kompletně a lépe.
Ve sphere jsou to všelijaké ty @equip, @pickup a @dropon triggery. Nic proti nim, ale jsou lehce nekonzistentní - například @pickup se volá, jen když je item zvednut přímo klientem, zatimco @equip se spouští i při equipnutí itemu ze skriptu... Špatně se tedy rozlišuje, jestli je akce přímo provedena klientem, nebo až "druhotně" nějakým skriptem. Proto jsem se rozhodl udělat dvě množiny triggerů - jedny volané při (resp. těsně před) každém pokusu klienta něco zvednout/položit/stacknout (a ty budou vesměs Cancellable a budou mít jasně daného původce, tj. hráče) a druhou, která se bude volat při každé změně lokace/stavu itemu (a ty vesměs Cancellable nebudou, nýbrž budou spis "oznamovací" s tím, že původce může být nejasný). Tyto dvě skupiny se pochopitelně budou částečně překrývat, resp. doplňovat, a to znamená spustu volání triggerů při každé manipulaci s itemem... ale dokud se neukáže opak, tak si myslím, že si to můzeme dovolit.
Pořadí parametrů zde popsané budiž závazné, tj. platí i pro LScript. V některých případech mohou být parametry "obalené" do potomka ScriptArgs, pak budou parametry vypsány jako NazevTridyPotomkaScriptArgs(A param1, B param2, C param3, ...) a znamená to, že v C# lze trigger v Triggergroupe/pluginu deklarovat buď s dvěma parametry - z toho druhý bude NazevTridyPotomkaScriptArgs - nebo s vypsáním jednotlivých A param1, B param2, C param3, ...
Vykřičníkem označené triggery jsou Cancellable (tedy return 1/true z nich způsobí zastavení akce/sekvence triggeru).
Obsah |
Lowlevel triggery
Tyto triggery budiž volány při každé změně vlastnosti Cont nebo P. Při každém volání triggeru platí, že musí být dodržovány všechny běžné invarianty, tj. nikdy není item někde "ve vzduchu", ale je přesně definováno, jestli oznamovaná akce (změna stavu) už proběhla nebo právě proběhne.
Fakt, že tyto triggery jsou "oznamovací", podtrhuje i to, že pokud je trigger někam přemístí, budou opět vráceny na sve místo (už vidím ten opruz tohle programovat, co jsem si to na sebe vymyslel :)
Ohledne nazvu tech triggeru plati ze se na samotnem manipulovanem itemu vola trigger s tou casti nazvu ve druhe zavorce (napr. @EnterItem), a na cilovem objektu se vola ten s casti nazvu v prvni zavorce (@ItemEnter). Parametry jsou nicmene stejne.
Název triggeru | Parametry | Stav při volání a popis |
---|---|---|
@Create | Volán po vytvoření (ne při loadu!), těsně po umístění do světa. Tento trigger sem až tak úplně nezapadá, píšu ho sem spíše pro úplnost... Potom je zavolán i trigger oznamující toto umístění. | |
@Dupe | Thing model | Volán při duplikaci itemu (i charu) na zkopirovanem objektu... Je volan po zavolani odpovidajicich @Enter triggeru.
Pokud je item implementací tohoto triggeru přesunut jinam, bude po skončeni opět vrácen a bude zobrazen Warning (protože použití Dupe() musí garantovat očekávaný výsledek) |
@(Item)Enter(Item) | ItemInItemArgs( Item manipulatedItem, Container cont ) | Volán po vložení itemu do kontejneru. V názvu je "Item", nikoli "Cont" nebo "Container", aby to nebylo zavádějící (protože Cont můze být i Character...)
Pokud je item implementací tohoto triggeru přesunut jinam, bude po skončeni opět vrácen a bude zobrazen Warning (protože použití Cont= musí garantovat očekávaný výsledek) |
@(Item)Enter(Char) / (Item)Equip | ItemInCharArgs( Item manipulatedItem, Character cont, byte layer ) | Volán po equipnutí.
Pokud je item implementací tohoto triggeru přesunut jinam, bude po skončeni opět vrácen a bude zobrazen Warning (protože použití Cont= musí garantovat očekaváný výsledek) Pokud je item equippable, a je vkladan do sveho layeru, tak se misto @enter(char) vola @equip |
@(Item)Enter(Region) | ItemOnGroundArgs( Item manipulatedItem, Region region, Point4D point ) | Volán po položení na zem.
Pokud je item implementací tohoto triggeru přesunut jinam, bude po skončeni opět vrácen a bude zobrazen Warning (protože použití P(...) musí garantovat očekaváný výsledek) |
@(Item)Leave(Item) | ItemInItemArgs( Item manipulatedItem, Container cont ) | Volán těsně před opuštěním kontejneru (tedy platí, že cont == manipulatedItem.Cont).
Pokud je item implementací tohoto triggeru přesunut jinam, je tato sekvence volání triggeru přerušena a spuštěna znovu a bude zobrazen Warning. Nicméně přesunu tím zabráněno nebude. |
@(Item)Leave(Char) / (Item)UnEquip | ItemInCharArgs( Item manipulatedItem, Character cont, byte layer ) | Volán těsně před unequipnutím. Pozor - za unequipnutí (a znovuequipnutí) se považuje i "jen" změna layeru.
Pokud je item implementací tohoto triggeru přesunut jinam, bude po skončení opět vrácen a bude zobrazen Warning (protože použití Cont= musí garantovat očekávaný výsledek) Pokud je item equippable, a je vyndavan ze sveho layeru, tak se misto @leave(char) vola @unequip |
@(Item)Leave(Region) | ItemOnGroundArgs( Item manipulatedItem, Region region, Point4D point ) | Volán před opuštěním pozice na mapě. Pozor - za opuštění se považuje i přesunutí ze země na zem.
Pokud je item implementací tohoto triggeru přesunut jinam, bude po skončení opět vrácen a bude zobrazen Warning (protože použití Cont= musí garantovat očekávaný výsledek) |
! @(Item)StackOn(Item) | ItemStackArgs( Item manipulatedItem, Item waitingStack ) | Volán těsně před stacknutím dvou itemů na obou z nich. V okamžiku volání byl manipulatedItem právě položen na stejné místo jako waitingStack (ať už v kontejneru nebo na zemi), a čeká se na to, jestli tento trigger povolí jejich stacknutí. V případě že ano, bude manipulatedItem smazán a amount waitingstacku zvětšen. Jádro se pokouší o stacknutí pouze v případě, že oba itemy mají stejný ItemDef, Model, Color a jsou Stackable.
Pokud je item implementací tohoto triggeru přesunut jinam, bude po skončení opět vrácen, případně rovnou smazán a bude zobrazen Warning (protože použití Cont= musí garantovat očekávaný výsledek) |
Highlevel triggery
Pokud projde @Pickup, je výsledkem equipnuti itemu do dragging layeru.
Pokud projde @Dropon, je výsledkem unequipnutí itemu z dragging layeru.
"Deny" triggery budiz takove ktere jsou urceny pro zakazani urcite cinnosti. Jsou to cancellable triggery, ale jejich cancelnuti (tj. return 1/true) neznamena zakazani te cinnosti, znamena to pouze ukonceni prubehu dotycne sekvence triggeru. Jestli bude cinnost zakazana nebo povolena zalezi na hodnote "DenyResult result" ktera je bud Allow nebo Deny_neco, kde "neco" reprezentuje nejakou zpravu ktera bude zobrazena, pripadne NoMessage.
Typicky by implementace mela bud neudelat nic (tedy dovolit cinnost), nebo nastavit result na Deny a zastavit sekvenci (return 1).
Název triggeru | Parametry | Stav při volání a popis |
---|---|---|
! @DenyPickup(Item)(From) | DenyPickupArgs(DenyResult result, Character pickingChar, Item manipulatedItem, ushort amount | Trigger urcen pro zakazani zvednuti itemu (ze zeme, kontejneru, nebo characteru). Volan jadrem pri pokusu klienta neco zvednout. Pokud neni cancelnuto/zakazano, vola se pro nastaveni DenyResult hodnoty metoda CanReach(). Na kontejneru/charu/regionu ze kteryho je item zvedan se vola !@DenyPickupItemFrom |
! @DenyPut(Item)On(Ground) | DenyPutOnGroundArgs( DenyResult result, Character puttingChar, Item manipulatedItem, Point4D point ) | Trigger urcen pro zakazani polozeni itemu na zem. |
! @Put(Item)On(Item) | ItemOnItemArgs( Character puttingChar, Item manipulatedItem, Item waitingItem ) | Toto neni @deny trigger. Vyvolava se v pripade ze klient polozi jeden item na druhy, a tyto dva nelze stacknout ani druhy neni kontejner. Nutno dodat ze toto se deje jen kdyz si klient "mysli" ze dotycne dva itemy pujde stacknout nebo ten lezici je kontejner. V tomto triggeru tedy lze implementovat nejakou funkcionalitu podobnou stacknuti/vlozeni do kontejneru... Cancellable je jen proto ze se predpoklada ze po probehnuti nejake smysluplne akce bude sekvence prerusena. Tento trigger se nevola na droppingCharu, jen na dotycnych 2 itemech (tedy !@PutItemOn a !@PutOnItem) |
! @Put(Item)On(Char) | ItemOnCharArgs( Character puttingChar, Item manipulatedItem, Character cont ) | Toto neni @deny trigger. Vyvolava se v pripade ze klient polozi item na jiniou nez vlastni postavu. V tomto triggeru tedy lze implementovat nejakou funkcionalitu ktera by nahradila standartni akci, tj. vlozeni itemu dotycnemu do backpacku (na coz se ale kazdopadne vyvola standartni @PutItemInItem sekvence). Neplest s @equip ! Toto bude pouzito spis na veci jako krmeni zvere apod. |
! @DenyPut(Item)In(Item) | DenyPutInItemArgs( DenyResult result, Character pickingChar, Item manipulatedItem, Item container) | Volano kdyz klient poklada item do kontejneru. |
! @DenyEquip(OnChar) | DenyEquipArgs( DenyResult result, Character puttingChar, Item manipulatedItem, Character cont, byte layer ) | Trigger urcen pro zakazani requipnuti itemu na postavu. Na puttingChar a se vola @DenyEquipOnChar, na cont a manipulatedItem se vola @DenyEquip. |
Character manipulation
Sice to sem jakoby nezapada ale tak nejak vyplynulo pri tech upravach u Itemu ze je zahodno udelat jiste upravy i u charu. Character nema zadnej cont, je vzdy na nejakych souradnicich na mape, takze o to je to jednodussi.
(toto zatim neni hotovo)
Lowlevel triggery
Dupe ChangeLocation (Char)Enter(Region) (Char)Leave(Region)
Highlevel triggery
Step(In/Out) TeleportStep?