diff --git a/artifacts/scripting/arrays.md b/artifacts/scripting/arrays.md index c098e90f..6d660107 100644 --- a/artifacts/scripting/arrays.md +++ b/artifacts/scripting/arrays.md @@ -164,23 +164,23 @@ ___ _*mixed means any type_ #### `int create_array(int size, int flags)` -- creates permanent array (but not "saved") -- if `size >= 0`, creates list with given size -- if `size == -1`, creates map (associative array) +- creates a permanent array (but not "saved") +- if `size >= 0`, creates a list with the given size +- if `size == -1`, creates a map (associative array) - if `size == -1` and `flags == 2`, creates a "lookup" map (associative array) in which the values of existing keys are read-only and can't be updated. This type of array allows you to store a zero (0) key value * NOTE: in earlier versions (up to 4.1.3/3.8.13) the second argument is not used, just use 0 - returns array ID (valid until array is deleted) #### `int temp_array(int size, int flags)` -- works exactly like `create_array`, only created array becomes "temporary" +- works exactly like `create_array`, only the created array becomes "temporary" #### `void fix_array(int arrayID)` -- changes "temporary" array into "permanent" ("permanent" arrays are not automatically saved into savegames) +- changes a "temporary" array into "permanent" ("permanent" arrays are not automatically saved into savegames) #### `void set_array(int arrayID, mixed key, mixed value)` - sets array value -- if used on list, "key" must be numeric and within valid index range (0..size-1) -- if used on map, key can be of any type +- if used on lists, "key" must be numeric and within valid index range (0..size-1) +- if used on maps, "key" can be of any type - to "unset" a value from map, just set it to zero (0) * NOTE: to add a value of 0 for the key, use the float value of 0.0 - this works exactly like statement: `arrayID[key] := value;` @@ -200,17 +200,17 @@ _*mixed means any type_ - if array was "saved", it will be removed from a savegame #### `mixed scan_array(int arrayID, mixed value)` -- searches for a first occurrence of given value inside given array +- searches for the first occurrence of the given value inside the given array - if value is found, returns its index (for lists) or key (for maps) - if value is not found, returns -1 (be careful, as -1 can be a valid key for a map) #### `int len_array(int arrayID)` -- returns number of elements or key=>value pairs in a given array -- if array is not found, returns -1 (can be used to check if given array exist) +- returns number of elements or key=>value pairs in the given array +- if array is not found, returns -1 (can be used to check if the given array exist) #### `void save_array(mixed key, int arrayID)` - makes the array saveable; it will be saved in **sfallgv.sav** file when saving the game -- array ID is associated with given "key" +- array ID is associated with the given "key" - array becomes permanent (if it was temporary) and "saved" - key can be of any type (int, float or string) - if you specify 0 as the key for the array ID, it will make the array "unsaved" @@ -223,11 +223,11 @@ _*mixed means any type_ - don't use it directly; it is generated by the compiler in foreach loops - for lists, returns index back (no change) - for maps, returns a key at the specified numeric index (don't rely on the order in which keys are stored though) -- can be checked if given array is associative or not, by using index (-1): 0 - array is list, 1 - array is map +- can be checked if the given array is associative or not, by using index (-1): 0 - array is a list, 1 - array is a map #### `int arrayexpr(mixed key, mixed value)` - don't use it directly; it is used by compiler to create array expressions -- assigns value to a given key in an array, created by last `create_array` or `temp_array` call +- assigns value to the given key in an array, created by last `create_array` or `temp_array` call - always returns 0 diff --git a/artifacts/scripting/functions.yml b/artifacts/scripting/functions.yml index 38d89cac..8d23b860 100644 --- a/artifacts/scripting/functions.yml +++ b/artifacts/scripting/functions.yml @@ -794,12 +794,14 @@ doc: Should work like `art_change_fid_num` but in `reg_anim` sequence. opcode: 0x825e - name: reg_anim_take_out - detail: void reg_anim_take_out(ObjectPtr, holdFrameID, delay) - doc: Plays "take out weapon" animation for given `holdFrameID`. It is not required to have such weapon in critter's inventory. + detail: void reg_anim_take_out(ObjectPtr, int weaponCode, int delay) + doc: | + Plays "take out weapon" animation for the given `weaponCode` (see `WPN_ANIM_*` constants in **define_extra.h**). + - It is not required for the critter to have this type of weapon in its inventory. opcode: 0x825f - name: reg_anim_turn_towards detail: void reg_anim_turn_towards(ObjectPtr, int tile/target, delay) - doc: Makes object change its direction to face given tile number or target object. + doc: Makes object change its direction to face the given tile number or target object. opcode: 0x8260 - name: reg_anim_callback detail: void reg_anim_callback(procedure proc) @@ -816,7 +818,9 @@ items: - name: art_exists detail: int art_exists(int artFID) - doc: 'checks if given artFID exists in the game. Useful when you want to check if critter can use specific weapon: `art_exists((artFid bwand 0xffff0fff) bwor (weaponAnim * 0x1000))`.' + doc: | + Checks if the given `artFID` exists in the game. + - Useful when you want to check if critter can use specific weapon: `art_exists((artFid bwand 0xffff0fff) bwor (weaponAnim * 0x1000))`. opcode: 0x8274 - name: refresh_pc_art detail: void refresh_pc_art @@ -852,14 +856,16 @@ opcode: 0x826d - name: tile_get_objs detail: array tile_get_objs(int tileNum, int elevation) - doc: Returns an array of all objects at given tile. It will include any hidden, dead or system objects (like cursor), so make sure to check properly when iterating. + doc: | + Returns an array of all objects at the given tile. + - It will include any hidden, dead or system objects (like cursor), so make sure to check properly when iterating. opcode: 0x8270 - name: tile_refresh_display detail: void tile_refresh_display doc: Redraws the game scene (tiles, walls, objects, etc.). - name: obj_blocking_tile detail: ObjectPtr obj_blocking_tile(int tileNum, int elevation, int blockingType) - doc: Returns first object blocking given tile using given blocking function or 0 if tile is clear. + doc: Returns the first object blocking the given tile using the given blocking function, or 0 if the tile is clear. opcode: 0x826f - name: tile_by_position @@ -870,20 +876,26 @@ macro: sfall.h - name: get_tile_ground_fid detail: int get_tile_ground_fid(int tileNum, int elevation) - doc: Returns FID of a ground tile at given tile number and elevation. + doc: Returns FID of a ground tile at the given tile number and elevation. macro: sfall.h - name: get_tile_roof_fid detail: int get_tile_roof_fid(int tileNum, int elevation) - doc: Returns FID of a roof tile at given tile number and elevation. Note that FID of 1 is used when there is no actual roof. + doc: Returns FID of a roof tile at the given tile number and elevation. Note that FID of 1 is used when there is no actual roof. macro: sfall.h - name: obj_blocking_line detail: ObjectPtr obj_blocking_line(ObjectPtr objFrom, int tileTo, int blockingType) - doc: Returns first object which blocks direct linear path from `objFrom` to `tileTo` using selected blocking function (see `BLOCKING_TYPE_*` constants in **sfall.h**). If path is clear (no blocker was encountered by selected function) - returns 0. `objFrom` is always excluded from calculations, but is required to be a valid object. + doc: | + Returns the first object which blocks direct linear path from `objFrom` to `tileTo` using selected blocking function (see `BLOCKING_TYPE_*` constants in **sfall.h**). + - If path is clear (no blocker was encountered by selected function) - returns 0. + - `objFrom` is always excluded from calculations, but is required to be a valid object. opcode: 0x826e - name: path_find_to detail: array path_find_to(ObjectPtr objFrom, int tileTo, int blockingType) - doc: Returns the shortest path to a given tile using given blocking function as an array of tile directions (0..5) to move on each step. Array length equals to a number of steps. Empty array means that specified target cannot be reached. + doc: | + Returns the shortest path to a given tile using the given blocking function as an array of tile directions (0..5) to move on each step. + - Array length equals to a number of steps. + - Empty array means that specified target cannot be reached. opcode: 0x8272 - name: Other @@ -1062,7 +1074,7 @@ - name: create_spatial detail: ObjectPtr create_spatial(int scriptID, int tile, int elevation, int radius) - doc: Creates new spatial script with given SID, at given tile, and radius. + doc: Creates new spatial script with the given scriptID at the given tile and radius. opcode: 0x8273 - name: unwield_slot @@ -1095,8 +1107,8 @@ - name: sprintf detail: string sprintf(string format, any value) doc: | - Formats given value using standart syntax of C `printf` function (google "printf" for format details). However, it is limited to formatting only 1 value. - - Can be used to get character by ASCII code ("%c"). + Formats the given value using standard syntax of C `printf` function (google "printf" for format details). However, it is limited to formatting only 1 value. + - Can be used to get character by ASCII code (`%c`). opcode: 0x8250 - name: typeof detail: int typeof(any value) @@ -1130,7 +1142,7 @@ opcode: 0x824f - name: charcode detail: int charcode(string text) - doc: Returns ASCII code for the first character in given string. + doc: Returns ASCII code for the first character in the given string. opcode: 0x8251 - name: get_string_pointer detail: int get_string_pointer(string text) @@ -1427,7 +1439,7 @@ - name: spatial_radius detail: int spatial_radius(ObjectPtr obj) - doc: Returns radius of spatial script, associated with given dummy-object (returned by `create_spatial`). + doc: Returns radius of spatial script, associated with the given dummy object (returned by `create_spatial`). macro: sfall.h - name: set_rest_heal_time detail: void set_rest_heal_time(int time) @@ -2010,12 +2022,16 @@ - name: set_script detail: void set_script(ObjectPtr obj, int scriptID) opcode: 0x81f4 - doc: Accepts a pointer to an object and scriptID, and applies the given script to an object (scriptID accept the same values as `create_object_sid `from sfall 3.6). If used on an object that is already scripted, it will remove the existing script first; you cannot have multiple scripts attached to a single object. Calling `set_script` on `self_obj` will have all sorts of wacky side effects, and should be avoided. If you add 0x80000000 to the sid when calling `set_script`, `map_enter_p_proc` will be SKIPPED. The `start` proc will always be run. + doc: | + Accepts a pointer to an object and scriptID, and applies the given script to an object (scriptID accept the same values as `create_object_sid` from sfall 3.6). + - If used on an object that is already scripted, it will remove the existing script first; you cannot have multiple scripts attached to a single object. + - Calling `set_script` on `self_obj` will have all sorts of wacky side effects, and should be avoided. + - If you add 0x80000000 to the scriptID when calling `set_script`, `map_enter_p_proc` will be SKIPPED. The `start` proc will always be run. - name: get_script detail: int get_script(ObjectPtr obj) opcode: 0x81f5 doc: | - - accepts a pointer to an object and returns its scriptID (line number in `scripts.lst`), or 0 if the object is unscripted. + Accepts a pointer to an object and returns its `scriptID` (line number in `scripts.lst`), or 0 if the object is unscripted. - returns -1 on argument error. - name: obj_is_carrying_obj @@ -2058,7 +2074,9 @@ macro: sfall.h - name: set_flags detail: void set_flags(ObjectPtr obj, int flags) - doc: Sets the current flags of an object. All flags are rewritten with given integer, so first get current flags with `get_flags` and use `bwor/bwand` to set/remove specific flag. + doc: | + Sets the current flags of an object. + - All flags are rewritten with the given `flags` integer, so first get the current flags with `get_flags` and use `bwor`/`bwand` to set/remove specific flags. macro: sfall.h - name: set_unique_id diff --git a/artifacts/scripting/sfall function notes.md b/artifacts/scripting/sfall function notes.md index c8c0dcd7..559bfe48 100644 --- a/artifacts/scripting/sfall function notes.md +++ b/artifacts/scripting/sfall function notes.md @@ -182,19 +182,20 @@ FUNCTION REFERENCE - This function works in addition to the **WorldMapTimeMod** setting in **ddraw.ini** and the Pathfinder perk, rather than overriding it, so calling `set_map_time_multi(0.5)` when the player has 2 levels of pathfinder would result in time passing at 25% the normal speed on the world map. ----- -#### `void remove_script(object obj)` -- Accepts a pointer to an object and will remove the script from that object. +#### `int get_script(object obj)` +- Accepts a pointer to an object and returns its `scriptID` (line number in **scripts.lst**), or 0 if the object is unscripted. +- Returns -1 on argument error. ----- #### `void set_script(object obj, int scriptID)` -- Accepts a pointer to an object and **scriptID**, and applies the given script to an object (scriptID accepts the same values as `create_object_sid`) -- If used on an object that is already scripted, it will remove the existing script first; you cannot have multiple scripts attached to a single object. Calling `set_script` on `self_obj` will have all sorts of wacky side effects, and should be avoided. -- If you add `0x80000000` to the SID when calling `set_script`, `map_enter_p_proc` will be SKIPPED. The `start` proc will always be run. +- Accepts a pointer to an object and **scriptID**, and applies the given script to an object (**scriptID** accepts the same values as `create_object_sid`) +- If used on an object that is already scripted, it will remove the existing script first; you cannot have multiple scripts attached to a single object. +- Calling `set_script` on `self_obj` will have all sorts of wacky side effects, and should be avoided. +- If you add `0x80000000` to the **scriptID** when calling `set_script`, `map_enter_p_proc` will be SKIPPED. The `start` proc will always be run. ----- -#### `int get_script(object obj)` -- Accepts a pointer to an object and returns its scriptID (line number in **scripts.lst**), or 0 if the object is unscripted. -- Returns -1 on argument error. +#### `void remove_script(object obj)` +- Accepts a pointer to an object and will remove the script from that object. ----- #### `void set_self(object setObj)` @@ -246,11 +247,11 @@ FUNCTION REFERENCE ----- #### `int get_tile_ground_fid(int tileNum, int elevation)` -- Returns FID of a ground tile at given tile number and elevation. +- Returns FID of a ground tile at the given tile number and elevation. ----- #### `int get_tile_roof_fid(int tileNum, int elevation)` -- Returns FID of a roof tile at given tile number and elevation. Note that FID of 1 is used when there is no actual roof. +- Returns FID of a roof tile at the given tile number and elevation. Note that FID of 1 is used when there is no actual roof. ----- #### `void reg_anim_combat_check(int enable)` @@ -275,12 +276,13 @@ FUNCTION REFERENCE - Should work like `art_change_fid_num` but in `reg_anim` sequence. ----- -#### `void reg_anim_take_out(object obj, holdFrameID, int delay)` -- Plays "take out weapon" animation for given **holdFrameID**. It is not required to have such weapon in critter's inventory. +#### `void reg_anim_take_out(object obj, int weaponCode, int delay)` +- Plays "take out weapon" animation for the given `weaponCode` (see `WPN_ANIM_*` constants in **define_extra.h**). +- It is not required for the critter to have this type of weapon in its inventory. ----- #### `void reg_anim_turn_towards(object obj, int/object tile/target, int delay)` -- Makes object change its direction to face given tile number or target object. +- Makes object change its direction to face the given tile number or target object. ----- #### `void reg_anim_callback(procedure proc)` @@ -349,7 +351,7 @@ FUNCTION REFERENCE ----- #### `string sprintf(string format, any value)` -- Formats given value using standard syntax of C `printf` function (google "printf" for format details). However, it is limited to formatting only 1 value. +- Formats the given value using standard syntax of C `printf` function (google "printf" for format details). However, it is limited to formatting only 1 value. - Can be used to get character by ASCII code (`%c`). ----- @@ -358,7 +360,7 @@ FUNCTION REFERENCE ----- #### `int charcode(string text)` -- Returns ASCII code for the first character in given string. +- Returns ASCII code for the first character in the given string. ----- #### `div` operator (unsigned integer division) @@ -415,7 +417,7 @@ FUNCTION REFERENCE ----- #### `void register_hook_proc(int hookID, procedure proc)` -- Works just like `register_hook`, but allows to specify which procedure to use for given hook script (instead of `start`). +- Works just like `register_hook`, but allows to specify which procedure to use for the given hook script (instead of `start`). - Use zero (0) as second argument to unregister hook script from current global script. - Only use in global scripts. - Second argument should be passed just like you pass procedures to functions like `gsay_option`, `giq_option`, etc. (name without quotes). @@ -444,17 +446,17 @@ FUNCTION REFERENCE ----- #### `object obj_blocking_line(object objFrom, int tileTo, int blockingType)` -- Returns first object which blocks direct linear path from objFrom to tileTo using selected blocking function (see `BLOCKING_TYPE_*` constants in **sfall.h**). +- Returns the first object which blocks direct linear path from `objFrom` to `tileTo` using selected blocking function (see `BLOCKING_TYPE_*` constants in **sfall.h**). - If path is clear (no blocker was encountered by selected function) - returns 0. - `objFrom` is always excluded from calculations, but is required to be a valid object. ----- #### `object obj_blocking_tile(int tileNum, int elevation, int blockingType)` -- Returns first object blocking given tile using given blocking function or 0 if tile is clear. +- Returns the first object blocking the given tile using the given blocking function, or 0 if the tile is clear. ----- #### `array tile_get_objs(int tileNum, int elevation)` -- Returns an array of all objects at given tile. +- Returns an array of all objects at the given tile. - It will include any hidden, dead or system objects (like cursor), so make sure to check properly when iterating. ----- @@ -463,17 +465,17 @@ FUNCTION REFERENCE ----- #### `array path_find_to(object objFrom, int tileTo, int blockingType)` -- Returns the shortest path to a given tile using given blocking function as an array of tile directions (0..5) to move on each step. +- Returns the shortest path to a given tile using the given blocking function as an array of tile directions (0..5) to move on each step. - Array length equals to a number of steps. - Empty array means that specified target cannot be reached. ----- #### `object create_spatial(int scriptID, int tile, int elevation, int radius)` -- Creates new spatial script with given SID, at given tile, and radius. +- Creates new spatial script with the given scriptID at the given tile and radius. ----- #### `int art_exists(int artFID)` -- Checks if given **artFID** exists in the game. +- Checks if the given `artFID` exists in the game. - Useful when you want to check if critter can use specific weapon: `art_exists((artFid bwand 0xFFFF0FFF) bwor (weaponAnim * 0x1000))` ----- @@ -505,7 +507,7 @@ sfall_funcX metarule functions ---- #### spatial_radius `int sfall_func1("spatial_radius", object obj)` -- Returns radius of spatial script, associated with given dummy-object (returned by `create_spatial`) +- Returns radius of spatial script, associated with the given dummy object (returned by `create_spatial`) ---- #### critter_inven_obj2 @@ -580,7 +582,7 @@ sfall_funcX metarule functions #### set_flags `void sfall_func2("set_flags", object obj, int flags)` - Sets the current flags of an object -- All flags are rewritten with given integer, so first get current flags with `get_flags` and use `bwor`/`bwand` to set/remove specific flag +- All flags are rewritten with the given `flags` integer, so first get the current flags with `get_flags` and use `bwor`/`bwand` to set/remove specific flags ---- #### tile_refresh_display diff --git a/docs/arrays.md b/docs/arrays.md index da145561..5e0ce76c 100644 --- a/docs/arrays.md +++ b/docs/arrays.md @@ -168,23 +168,23 @@ end _*mixed means any type_ * `int create_array(int size, int flags)`: - - creates permanent array (but not "saved") - - if `size >= 0`, creates list with given size - - if `size == -1`, creates map (associative array) + - creates a permanent array (but not "saved") + - if `size >= 0`, creates a list with the given size + - if `size == -1`, creates a map (associative array) - if `size == -1` and `flags == 2`, creates a "lookup" map (associative array) in which the values of existing keys are read-only and can't be updated. This type of array allows you to store a zero (0) key value * NOTE: in earlier versions (up to 4.1.3/3.8.13) the second argument is not used, just use 0 - returns arrayID (valid until array is deleted) * `int temp_array(int size, int flags)`: - - works exactly like `create_array`, only created array becomes "temporary" + - works exactly like `create_array`, only the created array becomes "temporary" * `void fix_array(int arrayID)`: - - changes "temporary" array into "permanent" ("permanent" arrays are not automatically saved into savegames) + - changes a "temporary" array into "permanent" ("permanent" arrays are not automatically saved into savegames) * `void set_array(int arrayID, mixed key, mixed value)`: - sets array value - - if used on list, "key" must be numeric and within valid index range (0..size-1) - - if used on map, key can be of any type + - if used on lists, "key" must be numeric and within valid index range (0..size-1) + - if used on maps, "key" can be of any type - to "unset" a value from map, just set it to zero (0) * NOTE: to add a value of 0 for the key, use the float value of 0.0 - this works exactly like statement: `arrayID[key] := value;` @@ -204,17 +204,17 @@ _*mixed means any type_ - if array was "saved", it will be removed from a savegame * `mixed scan_array(int arrayID, mixed value)`: - - searches for a first occurrence of given value inside given array - - if value is found, returns it's index (for lists) or key (for maps) + - searches for the first occurrence of the given value inside the given array + - if value is found, returns its index (for lists) or key (for maps) - if value is not found, returns -1 (be careful, as -1 can be a valid key for a map) * `int len_array(int arrayID)`: - - returns number of elements or key=>value pairs in a given array - - if array is not found, returns -1 (can be used to check if given array exist) + - returns number of elements or key=>value pairs in the given array + - if array is not found, returns -1 (can be used to check if the given array exist) * `void save_array(mixed key, int arrayID)`: - makes the array saveable; it will be saved in **sfallgv.sav** file when saving the game - - arrayID is associated with given "key" + - arrayID is associated with the given "key" - array becomes permanent (if it was temporary) and "saved" - key can be of any type (int, float or string) - if you specify 0 as the key for the array ID, it will make the array "unsaved" @@ -227,11 +227,11 @@ _*mixed means any type_ - don't use it directly; it is generated by the compiler in foreach loops - for lists, returns index back (no change) - for maps, returns a key at the specified numeric index (don't rely on the order in which keys are stored though) - - can be checked if given array is associative or not, by using index (-1): 0 - array is list, 1 - array is map + - can be checked if the given array is associative or not, by using index (-1): 0 - array is a list, 1 - array is a map * `int arrayexpr(mixed key, mixed value)`: - don't use it directly; it is used by compiler to create array expressions - - assigns value to a given key in an array, created by last `create_array` or `temp_array` call + - assigns value to the given key in an array, created by last `create_array` or `temp_array` call - always returns 0 ## Backward compatibility notes diff --git a/sfall/Modules/Scripting/Handlers/Objects.cpp b/sfall/Modules/Scripting/Handlers/Objects.cpp index 0c4a1104..8819a8a9 100644 --- a/sfall/Modules/Scripting/Handlers/Objects.cpp +++ b/sfall/Modules/Scripting/Handlers/Objects.cpp @@ -130,9 +130,10 @@ void op_get_npc_level(OpcodeContext& ctx) { void op_remove_script(OpcodeContext& ctx) { auto object = ctx.arg(0).object(); - if (object->scriptId != 0xFFFFFFFF) { + if (object->scriptId != -1) { fo::func::scr_remove(object->scriptId); - object->scriptId = 0xFFFFFFFF; + object->scriptId = -1; + object->scriptIndex = -1; } } @@ -151,22 +152,29 @@ void op_set_script(OpcodeContext& ctx) { unsigned long valArg = ctx.arg(1).rawValue(); long scriptIndex = valArg & ~0xF0000000; - if (scriptIndex == 0 || valArg > 0x8FFFFFFF) { // negative values are not allowed - ctx.printOpcodeError("%s() - invalid script index number.", ctx.getOpcodeName()); + if (scriptIndex == 0 || scriptIndex > fo::var::maxScriptNum) { // negative values are not allowed + ctx.printOpcodeError("%s() - invalid script index number: %d", ctx.getOpcodeName(), scriptIndex); return; } scriptIndex--; - if (object->scriptId != 0xFFFFFFFF) { + if (object->scriptId != -1) { fo::func::scr_remove(object->scriptId); - object->scriptId = 0xFFFFFFFF; + object->scriptId = -1; + object->scriptIndex = -1; } if (object->IsCritter()) { scriptType = fo::Scripts::ScriptTypes::SCRIPT_CRITTER; } else { scriptType = fo::Scripts::ScriptTypes::SCRIPT_ITEM; } - fo::func::obj_new_sid_inst(object, scriptType, scriptIndex); + if (fo::func::obj_new_sid_inst(object, scriptType, scriptIndex) == -1) { + // if sid assignment failed, revert to the "removed" state + object->scriptId = -1; + object->scriptIndex = -1; + return; + } + object->scriptIndex = scriptIndex; long scriptId = object->scriptId; exec_script_proc(scriptId, start); @@ -588,7 +596,7 @@ void mf_set_unique_id(OpcodeContext& ctx) { void mf_objects_in_radius(OpcodeContext& ctx) { long radius = ctx.arg(1).rawValue(); - if (radius <= 0) radius = 1; else if (radius > 50) radius = 50; + if (radius < 0) radius = 0; else if (radius > 50) radius = 50; long elev = ctx.arg(2).rawValue(); if (elev < 0) elev = 0; else if (elev > 2) elev = 2; long type = (ctx.numArgs() > 3) ? ctx.arg(3).rawValue() : -1;