diff options
Diffstat (limited to 'doc/old-spell-language')
-rw-r--r-- | doc/old-spell-language | 870 |
1 files changed, 0 insertions, 870 deletions
diff --git a/doc/old-spell-language b/doc/old-spell-language deleted file mode 100644 index 5f70f89..0000000 --- a/doc/old-spell-language +++ /dev/null @@ -1,870 +0,0 @@ --------------------------------------------------------------------------------- -== Spell language - -* Comments: One-line comments using '#' or '//' as prefix -* names vs. invocations: spells and anchors have both names - and invocations. Names are used to refer to spells and - anchors from within scripts without revealing their - invocations. - - -Each spell specification file consists of a sequence of definitions of -globals, anchors, spells, and procedures. - -Types: ------- - These are the primitive types: - * int - * string - * dir (a direction: N, S, SE, NW etc.) - * location (a single spot in the world) - * entity (a PC, NPC, or monster) - * area (a set of locations) - * spell (a spell) - * invocation (a spell instance) - * fail (a separate type that arises implicitly when a function - fails) - - `fail' arises in special circumstances in some functions, e.g. when -trying to divide by zero, or when function parameters fail to -type-check. When a fail value flows into an operation, than that -operation is skipped. When a fail value flows into a function, then -that function evaluates to fail, except for - - * if_then_else (which permits `fail' in its true or false branch) - * failed (which returns true iff the argument is of type fail). - - We will use standard functional type notation: - - `int * string -> entity' denotes the type of a function that accepts -an integer and a string and returns an entity. We use the return `()' -for operations (which return nothing). - -Globals: --------- - A `global' is a global variable, declared and defined in the -same line: - - foo = "this is a string"; - - Expressions can be arbitrary language expressions. Note that globals -can only reference the values of globals defined earlier in the same -program. - - There are two special globals: - - * min_casttime : int - Minimal number of milliseconds of cast delay, no matter what any - given spell may say. Cast delay is the time before the next spell - can be cast. - - * obscure : int - Chance of a character of a given spell to be obscured (masked out - by an asterisk). - - - Globals can also be defined as CONST (though this should not be done -for the special globals listed above or they will not take effect.) -CONST-defined globals cannot be re-defined. - - -Expressions: ------------- - Expressions occur in globals, anchors, spells, and procedures. -Expressions evaluate to values of a given type. Expressions can be -simple literals, area literals, infix expressions, function -applications, or variable refecences. - -- Simple literals: - * 42, 0xff: int literals - * N, S, E, W, NE, NW, SE, SW : dir literals - * "foo bar" : string literals - -- Area literals: - * @("new_3-1.gat", 26, 26) - This area denotes a single field on a map (new_3-1.gat, - co-ordinates (26,26). - * @("new_3-1.gat", 26, 26) @+ (10, 10) - This area is 100 fields, stretching to a field of size 10x10 to - the south and east of (26,26) in new_3-1.gat. - * @("new_3-1.gat", 26, 26) towards S (5, 3) - This area is a rectangular field of depth 3 and width 5 to the - south of (26,26) in new_3-1.gat. `depth 3' here means that it - stretches three fields to the south. `width 5' here means that it - extends five fields to the east and five to the west of the - specified coordinate, for a total width of 11. - The only directions supported here are S, E, N, W. - -- Infix expressions: - Infix expressions are special functions in which the operator is - written between two expressions. Infix expressions largely follow - the C precedence rules. The following infix operators are - supported: - * addition (+) (operates on ints, concatenates strings, and - constructs the union of areas) - * subtraction (- : int * int -> int) - * multiplication (* : int * int -> int) - * division (/ : int * int -> int, may fail) - * modulo (% : int * int -> int, may fail) - * comparison (<, >, >=, <=, =, <> : int * int -> int) - Comparison operators generally work on ints and strings. - (In)equality checks work on all values except for areas. - Note that "==" and "!=" are available as alternatives for "=" and - "<>" (respectively). - * conjunction and disjunction (&&, || : int * int -> int). Note - that these are not short-circuit. - * Bitwise or (| : int * int -> int) - * Bitwise and (& : int * int -> int) - * Bitwise xor (^ : int * int -> int) - * Shift left and right (<<, >> : int * int -> int) - -- Function applications: - Function applications are written as - - f(arg1, ..., argn) - - where each `argi' is an arbitrary expression. - For a complete list of Functions, see `functions' below. - -- Variable references: - The expression (foo + 1) references a variable `foo' which must have - been previously defined. - - -Anchors: --------- - Anchors are teleport anchors; spells can look them up by name. Each -teleport anchor is written as - - TELEPORT-ANCHOR <id> : <invocation-string> = <location> - - For example: - - TELEPORT-ANCHOR tulimshar : "home" = @("new_3-1.gat", 26, 26) @+(10, 10) - - This maps the teleport anchor `tulimshar' to an area in new_3-1.gat -binds it to the name "home". The function `anchor' can look up -teleport anchors (cf. the function library). - - -Spells: -------- - Each spell is written either as - - [spell-modifiers] SPELL <id> : <name> = <spelldef> - - or as - - [spell-modifiers] SPELL <id> (<id> : <sty>) : <name> = <spelldef> - - For example, - - SPELL random_dance : "zxr" = ... - - creates a spell `random_dance' and makes it available under the -invocation "zxr". The string `...' is not a valid <spelldef>; we will -look at proper spelldefs below. An alternative example illustrates -the use of parameters: - - SPELL shout (message : STRING) : "zzx" = ... - - This defines a spell `shout' (bound to invocation "zzx") that takes -a parameter `message' of type STRING. Valid types are STRING and PC: -PC parameters are automatically translated into a player character -entity of that name, or mapped to the caster if the specified name -does not map to a player character or is missing. - - The list of spell modifiers is short: - - * SILENT means that the spell's invocation will never be broadcast, - not even obscured. - * LOCAL means that the spell is bound to the location it was cast at - and will not `travel' with the caster. - * NONMAGIC means that the spell is not affected by the caster's ability - to perform magic. Typically used for special (quest) keywords. - - Modifiers may be given in any order, but only once. - -- Spell bodies - - Spell bodies consist of three parts: LET bindings, spell guards and - effects. LET bindings locally bind names to values. Spell guards - are constraints that must be satisfied for the spell to be - triggered. Effects describes what happens if the spell is - successfully triggered. Spells may have multiple guards and - effects. - - Consider the following example: - - SPELL plugh (message : STRING) : "zzx" = - LET x = "kappa" - y = "sigma" - IN - (MANA 1, CATALYSTS ["Pearl"]) => EFFECT message (caster, "First branch"); - | (MANA 20) => EFFECT message (caster, "Second branch") - - This defines a spell `plugh' with two let bindings (`x' bound to - "kappa" and `y' bound to "sigma") and two `branches' which are - tested in sequence. The first branch tests whether the caster has - one spellpoint and owns a pearl-- if so, the effect of sending a - message "First branch" to the caster is triggered. - - However, if the spell guard is not satisfied, the magic engine - examines the second branch. Now, if the caster has 20 spellpoints, - we INSTEAD trigger the effect of sending the message "Second branch" - to the caster. - -- Spell guards - - Spell guards can be omitted; in that case, just use the effect - itself. Otherwise they can be any of the following: - * MANA x: Require x spellpoints to be present. If this spellguard - is taken, x mana will be consumed implicitly. This requirement is - cumulative. - * CASTTIME x: Require that the caster spend x milliseconds until - the next spell can be cast. This requirement is cumulative. If - the total casttime for a spell is less than the global variable - min_casttime, then the latter supercedes the specified spell cast - delay. - * REQUIRE <expr>: Test that the specified expression evaluates to - nonzero and does not fail. Requirements are cumulative. - * CATALYSTS <items>: Ensure that the caster possesses all specified - items. This effect is cumulative. - * COMPONENTS <items>: Ensure that the caster possesses all specified - items. If the branch suceeeds, all items specified here are - consumed. This effect is cumulative. - - Items can be specified as follows: - * [ 700, 701 ] -- require one item of item ID 700 and one of 701. - * [ 700, 3 * 701 ] -- require 1 item of item ID 700 and 3 of 701. - * [ "Pearl" ] -- require one item named `Pearl' in the item DB. - - Spell guards can be combined as follows: - * `or': disjunction. The first matching path is taken. - * (a, ..., n): conjunction. a, n, and everything in between must be - satisfied. - * a => b: Implication. If `a' is satisfied, try to satisfy `b'. - This operation is useful to combine different branches (see - below.) - - Different branches of spell effects are separated by the vertical - bar `|'. For example, - - SPELL plugh (message : STRING) : "zzx" = - MANA 5 => ( (CATALYSTS ["Pearl"]) => - EFFECT message (caster, "First branch"); - | (MANA 20) => - EFFECT message (caster, "Second branch");) - - will always try to deduct 5 Mana points but then make a choice of - whether to go to the first branch (if the player has `Pearl') or to - the second (if the player does not have `Pear' but has another 20 - spell points, for a total of 25 spell points, all of which will be - consumed in that case.) - - -- Effects - - Effects describe what happens when a spell is triggered. Each - spell has at least one EFFECT specification, which looks as follows: - - EFFECT <effectlist> [ ATTRIGGER <effectlist> ] [ ATEND <effectlist> ] - - The three parts are as follows: - * EFFECT: All effects here are executed as soon as the spell is - triggered. - * ATEND: All steps described here are executed when the spell - finishes. Note that the spell may remain active after all steps - from the EFFECT section have been taken; this happens when the spell - triggers a status change (using the `status_change' operation, - as described in the operations library). In that case the spell - will terminate only after all status changes have finished. - The ATEND section is not called when the spell finishes due to the - caster dying. - * ATTRIGGER: This section is used only for the `override_attack' - operation and described there. - - Before effects are executed, the engine defines the following - variables: - - * The parameter (if any) - * caster : entity (the caster of this spell) - * spellpower : int (the caster's spellpower, normally 6 -- 198) - * location : location (the location the spell is currently at) - * self_spell : spell (the current spell) - * self_invocation : invocation (the current spell instance) - - The engine can then execute the following effects from the effect list: - * SKIP; # a no-op - * ABORT; # Abort the spell, don't run ATEND, don't consume a - # trigger charge (cf. `override_attack') - * END; # Skip to the ATEND block - * WAIT <expr>; # Wait <expr> milliseconds before continuing - * <id> = <expr>; # Set <id> to the result of evaluating <expr> - * (<s1> ... <sn>) # Execute statements <s1> through <sn> in sequence - * IF <c> # Test condition <c>. If nonzero, - THEN <s1> # execute <s1>. Otherwise, - ELSE <s2> # execute <s2>. - # The `ELSE' branch can be omitted. - - * FOREACH <k> <id> IN <expr> DO <s> - # Evaluate <expr> to an area, find all entities in - # the area that match <k>, randomise this list, - # bind <id> to each in turn and execute <s>. - - Example: - - FOREACH ENTITY t IN rbox(location(caster), 20) - DO aggravate(t, 0, caster); - # This aggravates all entities within 20 paces of - # the caster to attack the caster. - - Valid values for <k> are - + ENTITY : PC or mob - + PC - + MOB - + TARGET : mob, PC (but only if we are on a PvP map) - - * FOR <id> = <start> TO <stop> DO <stmt> - # This will iterate from <start> to <stop> (inclusively), bind - # <id> to the current iteration value, and execute <stmt>. - - * BREAK; - # This will break out of the current FOR loop, FOREACH loop, or - # procedure. - - * <id> ( <expr1>, ..., <exprn> ); - # This executes an operation. See `Operations', below, for a - # list. - - * CALL <id> ( <expr1>, ..., <exprn> ); - # This will execute a procedure, after binding the actual - # parameters from <expr1> to <exprn> to the formal procedure - # parameters. - - * { ... } - # This executes arbitrary eAthena script code. The following - # variables script variables are bound implicitly: - # - @caster_name$ is the name of the spellcaster - # - @caster and @target are also bound, to useless values (sorry.) - # - # By default, script popup boxes are sent to the caster. This can - # be overridden by setting the special `script_target' variable. - -Procedures: ------------ - Procedures are defined as - - PROCEDURE <id> ( <id>, ... , <id> ) = <effectlist> - - For example, - - PROCEDURE testproc(x) = message(caster, "foo(" + x + )"); - y = 10; - x = 20; - - defines a procedure `testproc' with one formal parameter `x'. - Procedure execution is nonrecursive and uses dynamic scoping. The - latter means that it can modify variables in the caller's scope. In - the above example, the assignment to `y' will be visible to the - caller. The assignment to `x' however will be not be visible, since - that assignment goes to the parameter and is therefore limited in - scope to `testproc'. More precisely, - - EFFECT x = 0; y = 0; testproc(1); - message(caster, "x=" + x + ", y=" + y); - - would print - - foo(1) - x=0, y=10 - - (note how the update to x is isolated from the caller.) - -Functions: ----------- -This section documents the function API. - -The following functions are available: - - + max : int * int -> int - Pick the greater of two values. - - + min : int * int -> int - Lesser of two values. - - + is_in : location * area -> bool - Test whether a location is within an area. - - + if_then_else : bool * 'a * 'a -> 'a - Test a condition (first parameter). If the contition is nonzero, - return the second parameter, otherwise the third parameter. - - + skill : entity * int -> int - Get the skill level that the `entity' has for the skill id. - - + dex : entity -> int - + agi : entity -> int - + int : entity -> int - + vit : entity -> int - + str : entity -> int - + luk : entity -> int - + hp : entity -> int - + sp : entity -> int - + def : entity -> int - + mdef : entity -> int - + max_hp : entity -> int - + max_sp : entity -> int - + level : entity -> int - Status attributes. - - + dir : entity -> dir - Direction that the entity is currently facing. - - + not : int -> int - Logical negation. (NOT bitwise negation.) - - + neg : int -> int - Bitwise negation. - - + name_of : entity -> string - | spell -> string - Retrieves the name either of an entity or of a spell. - - + location : entity -> location - Determines the location that the specified entity presently - occupies. - - + random : int -> int - random(6) yields a random value from 0 to 5. - - + random_dir : int -> dir - random_dir(0) yields N, S, E, or W. - random_dir(1) yields N, S, E, W, SE, SW, NE, or NW. - - + hash_entity : entity -> int - Retrieve a number idenfying the entity. - - + is_married : entity -> int - Tests whether the entity is married. - - + partner : entity -> entity - Retrieves the entity's partner, if online, or fails otherwise. - - + awayfrom : location * dir * int -> location - awayfrom(loc, dir, distance) returns a location obtained by moving - at most `distance' towards `dir', starting at `loc'. If the move - hits an obstacle, we stop before the obstacle. - - + failed : 'a -> bool - True iff the input was the special failure value. - - + pc : string -> entity - Looks up a player character by name. Fails if there is no match. - - + npc : string -> entity - Looks up an NPC by name. Fails if there is no match. - - + distance : location * location -> int - This is the `fake square distance': The maximum of delta x and - delta y between the two locations. - - + rdistance : location * location -> int - This is the `real' distance (square root of the square of dx, dy) - - + anchor : string -> area - Looks up a teleport anchor by name and returns the associated - area. Fails if the result is not an area. - - + random_location : area -> location - Pick a random location from within an area. - - + script_int : entity * string -> int - Read a player script variable as an integer. - - + rbox : location * int -> area - rbox(l, n) computes rectangular box centered at `l', with a - `radius' of n. The box contains (n*2 + 1)^2 squares. - - + count_item : entity * int -> int - | entity * string -> int - Counts the number of instances of the specified item that the - entity has. Items may be given by ID or by name. - - + line_of_sight : location * location -> int - Determines whether there is a line-of-sight connection between the - two locations. - - + running_status_update : entity * int -> bool - Determines whether the specified status update is still active. - - + element : entity -> int - Determines what element the entity is associated with - - + element_level : entity -> int - Determines what element level the entity has - - + has_shroud : entity -> int - Determines whether the player is presently shrouded (i.e., whether - the player's name is being obscured.) - - + is_equipped : entity * int -> int - : entity * string -> int - Determines whether the player has equipped the specified item - - + spell_index : spell -> int - Determines a unique index assigned to each spell - - + is_exterior : location -> bool - Determines whether the location is under an open sky - - + contains_string : string * string -> bool - contains_string(a, b) determines whether the string `a' contains - the string `b' as a substring. - - + strstr : string * string -> bool - strstr(a, b) returns the offset of the first instance of the - string `b' in the string `a', or fails if there is none. The - offset is reported with a base of zero, i.e., strstr("xyz", "x") = 0. - - + strlen : string -> int - Compute the length of a string, in characters. - - + substr : string * int * int -> string - substr(s, offset, len) extracts a substring of the length `len' at - offset `offset'. The substring is automatically clipped, i.e., the - function will never fail. - - + sqrt : int -> int - Computes the square root of the specified number - - + map_level : location -> int - Determines the map level: 0 for outside, 1 for inside, 2ff for - dungeon levels (going down) - - + map_nr : location -> int - Computes the map number. Map number and map level together uniquely - identify a map. - - + dir_towards : location * location * int -> dir - dir_towards(start, end, flag) computes the direction from `start' to - `end'. If flag is zero, directions are limited to N, S, E, W; - otherwise NE, SE, NW, SW will also be used. The two locations must be - on the same map. - - + is_dead : entity -> bool - Determines whether the specified entity is no longer alive. - - + extract_healer_experience : entity * int -> int - Extracts `healer experience points' from the specified entity. - Non-PCs always have an empty pool of healer exprerience points. - PCs gain such experience points by killing/completing quests, - though this `healer experience point pool' slowly drains itself. - extract_healer_experience(pc, xp) extracts up to `xp' points. - - + is_pc : entity -> bool - Determines whether the target is a player character - -Operations: ------------ -This section documents the operations API. - - + sfx : entity * int * int -> () - | location * int *int -> () - Trigger a special effect (specified by sfx ID) for an entity or a - location. The int specifies a delay until the effect is issued. - - + itemheal : entity * int * int -> () - itemheal(entity, hp, sp) triggers item healing. This will - hopefully be slowed down if an appropriate server patch is - installed. - - + instaheal : entity * int * int -> () - itemheal(entity, hp, sp) heals instantly. - - + shroud : entity * int -> () - shroud(entity, flags) hides the entity's name (only for PCs). - Flags: 0x01: Hide PC'ss name when talking - 0x02: Shroud vanishes when player picks something up - 0x04: Shroud vanishes when player talks - The shroud will not affect players in visible range until the - entity has left and re-entered their field of vision. This can be - enforced by warping. - - + unshroud : entity -> () - Counter a shroud. - - + message : entity * string -> () - Send a message to the entity. - - + messenger_npc : location * int - * string * string * int -> () - messenger_npc(location, image, npc_name, message, duration) - creates a messenger NPC looking like the `image' at `location', - with name `npc_name' and delivering the `message' when clicked - upon. The NPC disappears after the `duration' in ms has expired. - - + move : entity * dir -> () - Move the entity into the specified direction, unless that - direction is blocked. - - + warp : entity * location -> () - Warp entity to specified location. - - + spawn : area * entity * int * int * int * int -> () - spawn(area, owner, mob_id, attitude, count, lifetime) spawns for a - limited `lifetime' (in ms) a total of `count' monsters of kind - `mob_id' in `area'. `attitude' specifies how they behave: - 0 : attack everyone - 1 : be friendly - 2 : attack enemies of `owner' and give XP to `owner' if successful - - + banish : entity -> () - If the entity was spawned by the `spawn' operation, eliminate it. - - - + status_change : entity * int * int - * int * int * int * int -> () - status_change(entity, status, v1, v2, v3, v4, duration) initiates - a status change. The precise status change (and the meaning of - `v1', `v2', `v3', `v4') varies depending on `status'. This - operation may delay spell termination (and the ATEND effect). - ATEND can therefore be used to notify the caster that the status - change has finished. - - + stop_status_change : entity * int - Stops a status change - - + override_attack : entity * int * int - * int * int *int * int -> () - override_attack(entity, charges, delay, range, icon, animation, stop) - overrides the entity's current attack (only for PCs). The entity - will have `charges' attacks that instead result in calling the - ATTRIGGER effect for this spell. When this operation is called, - the spell environment (variables etc.) is cloned into a separate - invocation. This special invocation will be triggered every time - the entity tries to attack, until they have run out of charages (at - which time the previous behaviour is restored.) - `delay' specifies the attack delay. - `range' specifies the attack range as shown in the client GUI. - `icon' is the ID of a status-effect ID that will be displayed - while the spell is in effect. - `animation' is the attack animation ID that should be used. - `stop' decides whether attacking should stop once the spell is out - of charges (1) or continue (0). (Note: this doesn't properly work, - possibly due to client issues. Always use 0.) - - Note that if the ATTRIGGER effect ABORTs, no charge will be - consumed. - - ATTRIGGER can refernece the player's target via the `target' - variable. - - Example: - - SPELL tshuffle : "zvp" = - (MANA 1, CATALYSTS ["Pearl"]) => - EFFECT - override_attack(caster, 3, 500, 10, 700, 31); - ATTRIGGER - IF (not (line_of_sight(location, location(target)))) - THEN (message (caster, "No line of sight!"); ABORT;) - FOR i = 0 TO 10 DO (move(target, random_dir(0));); - - This overrides the caster's attack for three attacks (attack delay - 500, range 10) to instead randomly move around any entity that the - player tries to attack by up to 11 paces. - - + create_item : entity * int * int -> () - | entity * string * int -> () - create_item(entity, item, count) gives the `entity' `count' - instances of `item'. As usual, `item' can be either a string name - or an item ID. - - + aggravate : entity * int * entity -> () - aggravate (victim, mode, target) causes the `victim' to - mode = 0: attack `target' - mode = 1: become universally permanently aggressive - mode = 2: both of the above - - + injure : entity * entity * int * int -> () - injure(attacker, defender, hp, sp) causes damage to the defender - from the attacker (possibly killing, giving XP etc.), unless the - defender is immortal (NPC) or a PC on a non-PvP map. - - + emote : entity * int -> () - Issues the specified emotion to the specified entity. - - + set_script_variable : entity * string * int -> () - Sets a script variable to the specified value - - + set_hair_colour : entity * int -> () - Sets the hair colour of the specified entity to the specified - value (must be a PC). - - + set_hair_style : entity * int -> () - Adjusts the hair style of a PC. - - + drop_item : location * (int | string) * int * int -> () - drop_item(place, "name", count, duration) drops `count' items - (where count may be zero) of name "name" at `place'. The items - vanish again after `duration'. - - + drop_item_for : location * (int | string) - * int * int * entity * int -> () - drop_item_for(place, obj, count, duration, owner, delay) works - like drop_item(place, obj, count, duration), except that the item - can only be picked up by `owner' for the next `delay' - milliseconds, modulo pickup rules (spousal pickup, out-of-range). - - + gain_experience : entity * int * int * int -> () - gain_experience(player, base_xp, job_xp, reason) gives expereince - points to `player'. If reason is 0, they are handed out normally, - but if reason is 1, then those experience points are NOT added to - the pool of experience points that healers can draw from `player'. - - -Script API updates: -------------------- -Two new script API functions are available: - - * getspellinvocation : string -> string - Looks up a spell by spell ID and returns the spell's invocation. - * getanchorinvocation : string -> string - Looks up a teleport anchor by anchor ID and returns the invocation. - - -Syntax Reference: ------------------ - -SPELLCONF ::= (GLOBAL | ANCHOR | SPELL | PROCEDURE | ';')* (* The ';' are only for decorative purposes *) - - VALUE ::= <int> - | <hexint> - | <id> - | <string> - | <dir> (* one of {N, S, E, W, NE, SE, NW, SW} *) - - EXPR ::= (VALUE) - | (AREA) - | (EXPR) '+' (EXPR) - | (EXPR) '*' (EXPR) - | (EXPR) '-' (EXPR) - | (EXPR) '/' (EXPR) - | (EXPR) '%' (EXPR) - | (EXPR) '<' (EXPR) - | (EXPR) '>' (EXPR) - | (EXPR) '<>' (EXPR) - | (EXPR) '=' (EXPR) - | (EXPR) '!=' (EXPR) - | (EXPR) '==' (EXPR) - | (EXPR) '<=' (EXPR) - | (EXPR) '>=' (EXPR) - | (EXPR) '&&' (EXPR) - | (EXPR) '||' (EXPR) - | (EXPR) '|' (EXPR) - | (EXPR) '^' (EXPR) (* XOR *) - | (EXPR) '&' (EXPR) (* binary AND *) - | (EXPR) '<<' (EXPR) - | (EXPR) '>>' (EXPR) - | <id> '(' ((EXPR) /* ',') ')' - | <id> - | '(' (EXPR) ')' - - INVOCATION ::= <string> (* used for convenience *) - - LOCATION ::= '@' '(' (EXPR) ',' (EXPR) ',' (EXPR) ')' (* <map name, x, y> *) - - AREA ::= (LOCATION) - | (LOCATION) '@' '+' '(' (EXPR) ',' (EXPR) ')' (* width and height around location, passable only *) - | (LOCATION) 'towards' (EXPR) ':' '(' (EXPR) ',' (EXPR) ')' (* towards dir: Bar-shaped, width and depth; only NSEW supported *) - - ITEMS ::= '[' (ITEMC) /+ ',' ']' - - ITEMC ::= (ITEM) - | <int> '*' (ITEM) - - ITEM ::= <int> - | <id> - -* global - - GLOBAL ::= 'CONST'? <id> '=' (EXPR) ';' - - Available globals: - - min_casttime : int (* min # of ticks for each spell (BEFORE scaling according to battle.conf) *) - - obscure : int (* obscure percentage *) - -* teleport-anchor - - ANCHOR ::= 'TELEPORT-ANCHOR' <id> ':' (INVOCATION) '=' (EXPR) - - For example, - - TELEPORT-ANCHOR t : "tulimshar" = @("map_3-1.gat", 44, 70) - - creates a teleport anchor with name `t' and invocation `tulimshar' at the speicfied location. - -* spell - - SPELL ::= spellmod 'SPELL' <id> (ARG)? ':' (INVOCATION) '=' (SPELLDEF) - - SPELLMOD ::= ('SILENT' | 'LOCAL')* - - (silent: invocation silently dropped. local: `location' variable doesn't change after spell init.) - - ARG ::= '(' <id> ':' (ARGTYPE) ')" - - ARGTYPE ::= 'PC' (* yields a pc, or self *) - | 'STRING' - - SPELLDEF ::= ((SPELLBODY) /* '|') - | 'LET' (DECL)* 'IN' ((SPELLBODY) /* '|') - - SPELLBODY ::= (SPELLGUARD) '=>' (SPELLBODY) - | 'EFFECT' (EFFECT) ('ATTRIGGER' (EFFECT))? ('ATEND' (EFFECT))? - - (* `ATTRIGGER' is executed as a separate effect if the spell is `triggered'. If the trigger has a target, it is denoted - * in the variable `target'. - * `ATEND' is invoked for normal termination, i.e., after the spell is over or has been dispelled. `ATEND' is NOT used - * for the triggered effect; instead, spawn a separate spell in ATTRIGGER if that is desired. *) - - DECL ::= <id> '=' (EXPR) ';' - - SPELLGUARD ::= (PREREQ) - | (SPELLGUARD) 'or' (SPELLGUARD) - | '(' (SPELLGUARD) /+ ',' ')' - - PREREQ ::= 'REQUIRE' (EXPR) - | 'CATALYSTS' (ITEMS) - | 'COMPONENTS' (ITEMS) - | 'MANA' (EXPR) - | 'CASTTIME' (EXPR) (* # of ticks until the next spell can be cast *0 - - EFFECT ::= EFFECT ';' EFFECT - | '(' (EFFECT) ')' - | 'SKIP' (* no-op *) - | 'ABORT' (* abort spell. If used in a trigger, no charges will be consumed. *) - | 'END' (* skip to atend *) - | 'BREAK' (* break out of loop *) - | <id> '=' (EXPR) (* interpreted in the current context, eval'ds trictly *) - | 'FOREACH' (SELECTION) <id> 'IN' (AREA) 'DO' (EFFECT) (* randomises the subjects first *) - | 'FOR' <id> '=' (EXPR) 'TO' (EXPR) 'DO' (EFFECT) (* bounds are evaluated when the loop begins, no updates are respected *) - | 'IF' (EXPR) 'THEN' (EFFECT) ('ELSE' (EFFECT))? - | 'WAIT' (EXPR) (* amount in ticks before continuing. *) - | <id> '(' (EXPR) /* ',' ')' (* operation *) - | 'CALL' <id> '(' (EXPR) /* ',' ')' (* procedure call *) - | '{' ... '}' (* script *) - - SELECTION ::= 'PC' - | 'MOB' - | 'ENTITY' (* MOB or PC *) - | 'TARGET' (* like ENTITY, but includes PCs only on PvP maps *) - | 'SPELL' - | 'NPC' - -* procedures - - Procedures may be invoked via `CALL'. They use dynamic scoping. - - PROCEDURE ::= 'PROCEDURE' <id> '(' <id> /* ',' ')' '=' (EFFECT) |