Name | Type | is_array | initial_value |
//TESH.scrollpos=15
//TESH.alwaysfold=0
library ArrowKeySequence /* v3.0.1 By IcemanBo
*/ requires /*
*/ SequenceT /* hiveworkshop.com/forums/submissions-414/sequencet-274244/#post2772894
*/ ArrowKeyEvent /* hiveworkshop.com/forums/jass-resources-412/system-arrowkeyevent-205650/
*/
/* What is this?
This code allows you to create an ArrowKeySequence which can be solved by a user.
An ArrowKeySequence is for example: "ArrowUp, ArrowDown, ArrowLeft".
Now, when the user puhses these arrow keys in correct order, it can be seen as solved.
It can be used as kind of a puzzle, or it can also act as
opening mechanism for treasure chests like in the RPG Gothic.
*/
//! novjass
//API
/* At first you need to create at least one
ArrowKeySequence that a user can try to solve.
You need knowledge of the Vector library to create a vector.
You can look in Sequence Demo for an example.
You also have to register a boolexpr as code,
that will run, whenever a user tries to solve a sequence.*/
// struct ArrowKeySequence - constructor
static method create takes IntegerVector vector, boolexpr bx returns thistype
// struct ArrowKeySequence - destructor
For safety the destructor is wrapped into the API function DestroySequence. (see later)
// The registered code will fire whenever a user presses a key while he is about to
// solve a sequence. Within the code function you have access to:
boolean IsSequenceSolved // Is sequence completed
boolean IsKeyCorrect // If current input was correct
integer CurrentSequenceVectorPosition // Current position in sequence
integer ArrowKeyInteger // Read ArrowKeyEvent for info which key it is.
player ArrowKeyUser // User who pressed the arrow key
function EndSequence takes nothing returns nothing
// The current running sequence will end for the user.
function EndSequenceAll takes ArrowKeySequence keySequence, player p returns nothing
// Will end ALL sequences of a type for the user "p".
function DestroySequence takes ArrowKeySequence keySequence returns nothing
// Will end ALL sequences of the type for all players.
// Will completly destroy the sequence so it can't be used anymore. (deallocate)
// Use follwing function to start.
function StartPlayerSequence takes player p, ArrowKeySequence id, integer pos returns nothing
// whichPlayer
// whichSequence
// startPosition (All vectors start with "0". So "0" is the common start value.
// But in case you want, you can manipulate it to your needs.
// It is recommended to read the demo examples.
// That was it. Have fun!
//! endnovjass
// Data of all default sequences (added by user)
struct ArrowKeySequence extends array
implement Alloc
readonly trigger handler
readonly IntegerSequenceType sequence
static method create takes IntegerVector vec, boolexpr bx returns thistype
local thistype this = allocate()
set this.sequence = IntegerSequenceType.create(vec)
set this.handler = CreateTrigger()
call TriggerAddCondition(handler, bx)
return this
endmethod
method destroy takes nothing returns nothing
call this.sequence.destroy()
call DestroyTrigger(this.handler)
set this.handler = null
call this.deallocate()
endmethod
endstruct
//! runtextmacro DEFINE_STRUCT_VECTOR("", "SequenceVector", "IntegerSequence")
//! runtextmacro DEFINE_STRUCT_VECTOR("", "ArrowKeySequenceVector", "ArrowKeySequence")
globals
player ArrowKeyUser
integer ArrowKeyInteger
boolean IsKeyCorrect
private boolean endSequence
private ArrowKeySequence currentArrowKeySequence
private integer max
endglobals
// This handles the sequences of all players.
struct PlayerSequence extends array
private boolean inGame
readonly ArrowKeySequenceVector arrowKeySequence
private SequenceVector sequence
readonly integer sequenceAmount
// Will remove the sequence from given position.
method end takes integer pos returns nothing
call this.arrowKeySequence.erase(pos, 1)
call this.sequence[pos].destroy()
call this.sequence.erase(pos, 1)
set this.sequenceAmount = this.sequenceAmount - 1
endmethod
// Will start a new sequence from vectorPosition[startPos]
method start takes ArrowKeySequence that, integer startPos returns nothing
call this.arrowKeySequence.push(that)
call this.sequence.push(IntegerSequence.create(that, startPos))
set this.sequenceAmount = this.sequenceAmount + 1
endmethod
private method onArrowKeyEvent takes integer arrow, boolean pressed returns nothing
local integer i
local integer currentSequencePosition
if (pressed) then
// Responses
set ArrowKeyUser = Player(this)
set ArrowKeyInteger = arrow
// We need an independant integer as max, to have more control.
// The sequenceAmount is dynamic and can be changed which may lead to bugs.
set max = this.sequenceAmount
set currentSequencePosition = 0
loop
exitwhen currentSequencePosition >= max
set currentArrowKeySequence = this.arrowKeySequence[currentSequencePosition]
call this.sequence[currentSequencePosition].onSequenceEvent(arrow)
set IsKeyCorrect = IsSequenceInputCorrect
if (IsSequenceSolved) then
set i = this.sequenceAmount - 1
loop
exitwhen(i < 0)
if (this.arrowKeySequence[i] == currentArrowKeySequence) then
call this.end(i)
set max = max - 1
endif
set i = i - 1
endloop
endif
set endSequence = false
// Interact with user
call TriggerEvaluate(currentArrowKeySequence.handler)
if (endSequence) then
call this.end(currentSequencePosition)
set max = max - 1
else
set currentSequencePosition = currentSequencePosition + 1
endif
endloop
endif
endmethod
implement ArrowKey
// If a player leaves he doesn't need the vectors anymore
private static method onLeave takes nothing returns boolean
local integer i = GetPlayerId(GetTriggerPlayer())
if (thistype(i).inGame) then
call thistype(i).arrowKeySequence.destroy()
call thistype(i).sequence.destroy()
set thistype(i).sequenceAmount = 0
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local integer i = 0
local trigger t = CreateTrigger()
call TriggerAddCondition(t, function thistype.onLeave)
loop
exitwhen (i > 11)
set thistype(i).sequenceAmount = 0
if (GetPlayerController(Player(i)) == MAP_CONTROL_USER) then
set thistype(i).arrowKeySequence = ArrowKeySequenceVector.create()
set thistype(i).sequence = SequenceVector.create()
set thistype(i).inGame = true
call TriggerRegisterPlayerEvent(t, Player(i), EVENT_PLAYER_LEAVE)
endif
set i = i + 1
endloop
endmethod
endstruct
// API
// Remove all sequences of a type for a player.
function EndSequenceAll takes ArrowKeySequence currentKeySequence, player p returns nothing
local PlayerSequence this = PlayerSequence(GetPlayerId(p))
local integer i = this.sequenceAmount - 1
loop
exitwhen(i < 0)
if (this.arrowKeySequence[i] == currentKeySequence) then
call this.end(i)
set max = max - 1
endif
set i = i - 1
endloop
endfunction
// When a sequence per pe gets destroyed then
// we to run though all player sequences and
// remove the destroyed sequence type.
function DestroySequence takes ArrowKeySequence keySequence returns nothing
local integer i = 0
loop
exitwhen (i > 11)
call EndSequenceAll(keySequence, Player(i))
set i = i + 1
endloop
call keySequence.destroy()
endfunction
function EndSequence takes nothing returns nothing
set endSequence = true
endfunction
function StartPlayerSequence takes player p, ArrowKeySequence id, integer pos returns nothing
call PlayerSequence(GetPlayerId(p)).start(id, pos)
endfunction
endlibrary
//TESH.scrollpos=34
//TESH.alwaysfold=0
struct SequenceDemoOne extends array
/*
Info
Here we want to create a sequence: LEFT - RIGHT - DOWN - UP
- We (re-)start the sequence when user presses 'Esc'.
- We destroy the sequence if user presses a wrong key.
- We destroy the sequence when it's solved and disable the 'Esc' trigger.
(so it can be solved only once)
*/
private static ArrowKeySequence mySequence
private static trigger t = CreateTrigger()
private static IntegerVector myVector
private static method onESC takes nothing returns nothing
// With pressing 'ESC' user can start the puzzle sequence.
call ClearTextMessages()
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("First demonstration: puzzle")
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("Press correct order of arrow keys.")
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("-------------------------------------------------")
call StartPlayerSequence(GetTriggerPlayer(), mySequence, 0)
endmethod
private static method onTry takes nothing returns boolean
if (IsKeyCorrect) then
call PlaySoundBJ( gg_snd_MouseClick1 )
call BJDebugMsg("correct key: (" + ArrowKey(ArrowKeyInteger).getKeyName(ArrowKeyInteger) + ")")
if(IsSequenceSolved) then
// Remember if a player solves a sequence EndSequenceAll() is
// automatically called for the player and the matching sequence.
// When solved we disable the start trigger.
call PlaySoundBJ( gg_snd_GoodJob )
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("Puzzle was solved!")
call BJDebugMsg("Demonstration 1 over.")
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("-------------------------------------------------")
call DisableTrigger(t)
// We don't want that someone can solve this sequence anymore.
call DestroySequence(mySequence)
// We start demo two
call SequenceDemoTwo.SequenceDemoTwoInit()
endif
else
// If pressed wrong, we simply destroy the sequence.
call ClearTextMessages()
call PlaySoundBJ( gg_snd_Error )
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("wrong key: (" + ArrowKey(ArrowKeyInteger).getKeyName(ArrowKeyInteger) + ")")
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("Press 'Esc' to retry the puzzle.")
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("-------------------------------------------------")
call EndSequence()
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local player p = GetLocalPlayer()
// We wanna create a sequence: Left, Left, Right
// Create new vector
set myVector = IntegerVector.create()
call myVector.push(ARROW_KEY_LEFT).push(ARROW_KEY_RIGHT).push(ARROW_KEY_DOWN).push(ARROW_KEY_UP)
// Create new sequence and bind a code
set mySequence = ArrowKeySequence.create(myVector, Condition(function thistype.onTry))
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("Press 'Esc' start first demonstration.")
call BJDebugMsg("-------------------------------------------------")
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_END_CINEMATIC)
call TriggerAddAction(t, function thistype.onESC)
endmethod
endstruct
//TESH.scrollpos=34
//TESH.alwaysfold=0
library DemoTwo uses ArrowKeySequence
/*
Info
Here we want to create a sequence: LEFT - LEFT - RIGHT - LEFT - RIGHT
- We start the sequence when user attcks the treasure chest.
- If user presses wrong key we give him 50/50 chance to retry at same position.
- If the user fails, the sequence will automatically restart. (no new attack needed)
- Once solved, the chestAttak trigger gets deactivated, so it can't get solved anymore.
*/
struct SequenceDemoTwo extends array
private static ArrowKeySequence mySequence
private static trigger t = CreateTrigger()
private static unit chest
private static unit hero
private static method onAttack takes nothing returns nothing
call ClearTextMessages()
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("Second demonstration: treasure chest")
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("Only use ArrowRight and ArrowLeft.")
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("-------------------------------------------------")
call IssueImmediateOrder(hero, "stop")
call CameraSetupApplyForPlayer( true, gg_cam_Cam_Chest, GetLocalPlayer(), 1.00 )
call PauseUnit(hero, true)
// Start sequence onAttack
call StartPlayerSequence(GetLocalPlayer(), mySequence, 0)
endmethod
private static method onTry takes nothing returns boolean
call CameraSetupApplyForPlayer( true, gg_cam_Cam_Chest, ArrowKeyUser, 0.1 )
// We only want to use LEFT or RIGHT
if ArrowKeyInteger == ARROW_KEY_LEFT or ArrowKeyInteger == ARROW_KEY_RIGHT then
if (IsKeyCorrect) then
call PlaySoundBJ( gg_snd_MouseClick1 )
call BJDebugMsg("correct key: (" + ArrowKey(ArrowKeyInteger).getKeyName(ArrowKeyInteger) + ")")
if(IsSequenceSolved) then
// Remember if a player solves a sequence EndSequenceAll() is
// automatically called for the player and the matching sequence.
// Sequence was solved and we deactivate the trigger for the chest attack.
call PlaySoundBJ( gg_snd_GoodJob )
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("Treasure Chest was opened!")
call BJDebugMsg("Demonstration is completed.")
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("-------------------------------------------------")
call SetUnitAnimation(chest, "Birth")
call ResetToGameCamera(1)
call DisableTrigger(t)
call PauseUnit(hero, false)
// We don't want that someone can solve this sequence anymore.
call DestroySequence(mySequence)
endif
else
call ClearTextMessages()
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("wrong key: (" + ArrowKey(ArrowKeyInteger).getKeyName(ArrowKeyInteger) + ")")
call PlaySoundBJ( gg_snd_Error )
// If wrong key was pressed, we give a 50/50 chance to try again.
if GetRandomInt(1, 2) == 1 then
call EndSequence()
call StartPlayerSequence(ArrowKeyUser, mySequence, 0)
call BJDebugMsg("key has broken.")
else
call BJDebugMsg("you have a new try.")
endif
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("-------------------------------------------------")
endif
endif
return false
endmethod
// We only activate it when Demo one was solved.
private static method onInit takes nothing returns nothing
call DisableTrigger(t)
endmethod
static method SequenceDemoTwoInit takes nothing returns nothing
local IntegerVector myVector = IntegerVector.create()
local player p = GetLocalPlayer()
set chest = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'h000', 400, -200, 225)
set hero = CreateUnit(p, 'hfoo', 0, -1200, 90)
call SetCameraTargetController(hero, 0, 0, true)
// Create vector
call myVector.push(ARROW_KEY_LEFT).push(ARROW_KEY_LEFT).push(ARROW_KEY_RIGHT).push(ARROW_KEY_LEFT).push(ARROW_KEY_RIGHT)
// Create sequence
set mySequence = ArrowKeySequence.create(myVector, Condition(function thistype.onTry))
call ClearTextMessages()
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("Now search the treasure chest and attack it.")
call BJDebugMsg("-------------------------------------------------")
call TriggerRegisterUnitEvent(t, chest, EVENT_UNIT_ATTACKED )
call TriggerAddAction(t, function thistype.onAttack)
call EnableTrigger(t)
endmethod
endstruct
endlibrary
//TESH.scrollpos=54
//TESH.alwaysfold=0
library DemoThree uses ArrowKeySequence
struct SequenceDemoThree extends array
/*
Info
Here we want to create a sequence: UP - LEFT - UP - RIGHT - UP
- The seqeunce is initialy activated for the user.
- When solving the sequence the user gets 1000 gold.
- It can be solved as many times you want.
The tricky part in this demo is that the user can try to solve
multiple Sequences at same time of the very same sequence type.
It creates a new sequence for the player in an intuitive way.
Read comments for better understanding.
*/
private static ArrowKeySequence mySequence
private static integer array SequenceCount // We count active sequences. Explained later why.
private static constant integer FIRST_KEY = ARROW_KEY_UP // Will use to run parallel sequences
private static method onTry takes nothing returns boolean
local integer id = GetPlayerId(ArrowKeyUser)
// Here we start new parallel sequence if the user presses UP_KEY,
// but is not at position[0]. The new sequence will start at position [1].
if (not IsSequenceSolved) and (ArrowKeyInteger == FIRST_KEY and CurrentSequenceVectorPosition > 0) then
call StartPlayerSequence(ArrowKeyUser, mySequence, 1)
set SequenceCount[id] = SequenceCount[id] + 1
endif
if (IsKeyCorrect) then
if(IsSequenceSolved) then
// Remember if a player solves a sequence EndSequenceAll() is
// automatically called for the player and the matching sequence.
// If solved we give 1000 gold
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("Secret Sequence 1 was solved!")
call BJDebugMsg("Gold +1000")
call BJDebugMsg("-------------------------------------------------")
call AdjustPlayerStateBJ( 1000, ArrowKeyUser, PLAYER_STATE_RESOURCE_GOLD )
call PlaySoundBJ( gg_snd_SecretFound )
// We give opportunity to solve this sequence again again.
call StartPlayerSequence(ArrowKeyUser, mySequence, 0)
set SequenceCount[id] = 1
endif
else
set SequenceCount[id] = SequenceCount[id] - 1
call EndSequence()
// We want achieve that the user ALWAYS has the opporunity to solve this sequence.
// So if ALL sequences are destroyed there would be no chance anymore.
// That's why we check if the SequenceCount would equal 0;
// if yes - we simply start a new one.
if SequenceCount[id] == 0 then
call StartPlayerSequence(ArrowKeyUser, mySequence, 0)
set SequenceCount[id] = SequenceCount[id] + 1
endif
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local IntegerVector myVector = IntegerVector.create()
local player p = GetLocalPlayer()
// Create vector
call myVector.push(ARROW_KEY_UP).push(ARROW_KEY_LEFT).push(ARROW_KEY_UP).push(ARROW_KEY_RIGHT).push(ARROW_KEY_UP)
// Create sequence
set mySequence = ArrowKeySequence.create(myVector, Condition(function thistype.onTry))
// Start sequence
call StartPlayerSequence(p, mySequence, 0)
set SequenceCount[GetPlayerId(p)] = 1
endmethod
endstruct
endlibrary
//TESH.scrollpos=2
//TESH.alwaysfold=0
library DemoFour uses ArrowKeySequence
globals
private hashtable hash = InitHashtable()
private constant real TIMEOUT = 0.3
private timer array tim
endglobals
struct SequenceDemoFour extends array
/*
Info
Here we want to create a sequence: DOWN - DOWN - DOWN - DOWN - DOWN - DOWN
- The seqeunce is initialy activated for the user.
- When solving the sequence, the user gets 1000 lumber.
- When something is false, user restarts.
- When starting to solve, the user has "TIMEOUT" seconds to press the next correct key,
else it automaticaly gets destroyed and the user has to restart the whole sequence.
- When the sequence is solved it gets destroyed and cant be solved anymore. BY NOONE.
*/
private static ArrowKeySequence mySequence
// Timerout has expired. User was too slow, so we restart the sequence.
private static method callback takes nothing returns nothing
local player p = LoadPlayerHandle(hash, GetHandleId(GetExpiredTimer()), 0)
call EndSequenceAll(mySequence, p)
call StartPlayerSequence(p, mySequence, 0)
endmethod
private static method onTry takes nothing returns boolean
local integer i
if (IsKeyCorrect) then
if(IsSequenceSolved) then
// Remember if a player solves a sequence EndSequenceAll() is
// automatically called for the player and the matching sequence.
call BJDebugMsg("-------------------------------------------------")
call BJDebugMsg("Secret Sequence 2 was solved!")
call BJDebugMsg("Lumber +1000")
call BJDebugMsg("-------------------------------------------------")
call AdjustPlayerStateBJ( 1000, ArrowKeyUser, PLAYER_STATE_RESOURCE_LUMBER )
call PlaySoundBJ( gg_snd_SecretFound )
// We don't want that someone can solve this sequence anymore.
call DestroySequence(mySequence)
call DestroyTimer(tim[GetPlayerId(ArrowKeyUser)])
else
// Give an other 0.5 seconds to press next key.
call TimerStart(tim[GetPlayerId(ArrowKeyUser)], TIMEOUT, false, function thistype.callback)
endif
else
// Destroy and start again
call EndSequence()
call StartPlayerSequence(ArrowKeyUser, mySequence, 0)
call PauseTimer(tim[GetPlayerId(ArrowKeyUser)])
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local IntegerVector myVector = IntegerVector.create()
local player p = GetLocalPlayer()
set tim[GetPlayerId(p)] = CreateTimer()
// Create vector
call myVector.push(ARROW_KEY_DOWN).push(ARROW_KEY_DOWN).push(ARROW_KEY_DOWN).push(ARROW_KEY_DOWN).push(ARROW_KEY_DOWN).push(ARROW_KEY_DOWN)
// Create sequence
set mySequence = ArrowKeySequence.create(myVector, Condition(function thistype.onTry))
// Start sequence
call StartPlayerSequence(p, mySequence, 0)
// Attach player to the timer. If you want you also can go with TimerUtils and just attach the PlayerId.
call SaveInteger(hash, GetHandleId(tim[GetPlayerId(p)]), 0, GetPlayerId(p))
endmethod
endstruct
endlibrary
//TESH.scrollpos=81
//TESH.alwaysfold=0
/*****************************************************************************
*
* Vector<T> v1.1.6.6
* by Bannar aka Spinnaker
*
* Dynamic contiguous array.
*
******************************************************************************
*
* Requirements:
*
* Table by Bribe
* hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*
* Alloc - choose whatever you like
*
******************************************************************************
*
* Implementation:
*
* macro DEFINE_STRUCT_VECTOR takes ACCESS, NAME, TYPE
*
* macro DEFINE_VECTOR takes ACCESS, NAME, TYPE
*
* ACCESS - encapsulation, choose retriction access
* NAME - name of vector type
* TYPE - type of values stored
*
******************************************************************************
*
* struct API:
*
* General:
*
* | static method create takes nothing returns thistype
* | default ctor
* |
* | static method operator [] takes thistype vec returns thistype
* | copy ctor
* |
* | method destroy takes nothing returns nothing
* | default dctor
* |
* | method empty takes nothing returns boolean
* | checks whether the vector is empty
* |
* | method size takes nothing returns integer
* | returns size of a vector
*
*
* Access:
*
* | method operator [] takes integer index returns $TYPE$
* | returns item at position index
* |
* | method operator []= takes integer index, $TYPE$ value returns nothing
* | sets item at index to value
* |
* | method front takes nothing returns $TYPE$
* | retrieves first element
* |
* | method back takes nothing returns $TYPE$
* | retrieves last element
* |
* | method data takes nothing returns Table
* | returns the underlying Table object
*
*
* Modifiers:
*
* | method clear takes nothing returns nothing
* | performs a flush operation on data table
* |
* | method push takes $TYPE$ value returns thistype
* | adds elements to the end
* |
* | method pop takes nothing returns thistype
* | removes the last element
* |
* | method assign takes integer count, $TYPE$ value returns thistype
* | assigns count elements replacing current data
* |
* | method insert takes integer pos, integer count, $TYPE$ value returns thistype
* | inserts count elements before position pos
* |
* | method erase takes integer pos, integer count returns thistype
* | erase count elements starting at position pos
*
*
*****************************************************************************/
library VectorT requires Table, Alloc
// Run here any global vector types you want to be defined.
//! runtextmacro DEFINE_VECTOR("", "IntegerVector", "integer")
//! runtextmacro DEFINE_VECTOR("", "StringVector", "string")
//! textmacro_once DEFINE_STRUCT_VECTOR takes ACCESS, NAME, TYPE
$ACCESS$ struct $NAME$ extends array
private delegate IntegerVector parent
method operator[] takes integer index returns $TYPE$
return parent[index]
endmethod
method front takes nothing returns $TYPE$
return parent.front()
endmethod
method back takes nothing returns $TYPE$
return parent.back()
endmethod
static method create takes nothing returns thistype
local thistype this = IntegerVector.create()
set parent = this
return this
endmethod
endstruct
//! endtextmacro
//! textmacro_once DEFINE_VECTOR takes ACCESS, NAME, TYPE
$ACCESS$ struct $NAME$ extends array
private Table table
private integer length
implement Alloc
private method seT takes integer index, $TYPE$ value returns nothing
set table.$TYPE$[index] = value
endmethod
private method get takes integer index returns $TYPE$
return table.$TYPE$[index]
endmethod
private method assert_pos takes integer pos, string f returns boolean
debug if ( pos < 0 and pos >= length ) then
debug call DisplayTimedTextFromPlayer(GetLocalPlayer(),0,0,60,"$NAME$::assert_pos failed at "+f+" for instance "+I2S(this)+". Invalid index at position: "+I2S(pos)+".")
debug endif
return ( pos >= 0 and pos < length )
endmethod
private method assert_range takes integer pos, string f returns boolean
debug if ( pos < 0 or pos > length ) then
debug call DisplayTimedTextFromPlayer(GetLocalPlayer(),0,0,60,"$NAME$::assert_range failed at "+f+" for instance "+I2S(this)+". Invalid iterator at position: "+I2S(pos)+".")
debug endif
return ( pos >= 0 and pos <= length )
endmethod
method operator [] takes integer index returns $TYPE$
debug if not assert_pos(index, "operator []") then
debug return get(-1)
debug endif
return get(index)
endmethod
method operator []= takes integer index, $TYPE$ value returns nothing
debug if not assert_pos(index, "operator []=") then
debug return
debug endif
call seT(index, value)
endmethod
static method create takes nothing returns thistype
local thistype this = allocate()
set table = Table.create()
set length = 0
return this
endmethod
method empty takes nothing returns boolean
return length == 0
endmethod
method size takes nothing returns integer
return length
endmethod
static method operator [] takes thistype vec returns thistype
local thistype this = create()
loop
exitwhen length >= vec.size()
call seT(length, vec[length])
set length = length + 1
endloop
return this
endmethod
method clear takes nothing returns nothing
set length = 0
call table.flush()
endmethod
method destroy takes nothing returns nothing
call clear()
call table.destroy()
set table = 0
call deallocate()
endmethod
method front takes nothing returns $TYPE$
return this[0]
endmethod
method back takes nothing returns $TYPE$
return this[length-1]
endmethod
method data takes nothing returns Table
return this
endmethod
method push takes $TYPE$ value returns thistype
call seT(length, value)
set length = length + 1
return this
endmethod
method pop takes nothing returns thistype
if ( length > 0 ) then
set length = length - 1
call table.$TYPE$.remove(length)
call table.real.remove(0)
endif
return this
endmethod
method assign takes integer count, $TYPE$ value returns thistype
if ( count > 0 ) then
call clear()
loop
exitwhen length >= count
call push(value)
endloop
endif
return this
endmethod
method insert takes integer pos, integer count, $TYPE$ value returns thistype
local integer i
if assert_range(pos, "insert") then
if ( count > 0 ) then
set length = length + count
set i = length - 1
loop
exitwhen i < (pos + count)
call seT(i, get(i-count))
set i = i - 1
endloop
set i = 0
loop
exitwhen i >= count
call seT(pos+i, value)
set i = i + 1
endloop
endif
endif
return this
endmethod
method erase takes integer pos, integer count returns thistype
if assert_pos(pos, "erase") then
if ( count > 0 ) then
if ( pos + count > length ) then
set count = length - pos
endif
set pos = pos + count
loop
exitwhen pos >= length
call seT(pos-count, get(pos))
set pos = pos + 1
endloop
loop
exitwhen count <= 0
call pop()
set count = count - 1
endloop
endif
endif
return this
endmethod
endstruct
//! endtextmacro
endlibrary
//TESH.scrollpos=279
//TESH.alwaysfold=0
library Table /* made by Bribe, special thanks to Vexorian & Nestharus, version 4.1.0.1.
One map, one hashtable. Welcome to NewTable 4.1.0.1
This newest iteration of Table introduces the new HashTable struct.
You can now instantiate HashTables which enables the use of large
parent and large child keys, just like a standard hashtable. Previously,
the user would have to instantiate a Table to do this on their own which -
while doable - is something the user should not have to do if I can add it
to this resource myself (especially if they are inexperienced).
This library was originally called NewTable so it didn't conflict with
the API of Table by Vexorian. However, the damage is done and it's too
late to change the library name now. To help with damage control, I
have provided an extension library called TableBC, which bridges all
the functionality of Vexorian's Table except for 2-D string arrays &
the ".flush(integer)" method. I use ".flush()" to flush a child hash-
table, because I wanted the API in NewTable to reflect the API of real
hashtables (I thought this would be more intuitive).
API
------------
struct Table
| static method create takes nothing returns Table
| create a new Table
|
| method destroy takes nothing returns nothing
| destroy it
|
| method flush takes nothing returns nothing
| flush all stored values inside of it
|
| method remove takes integer key returns nothing
| remove the value at index "key"
|
| method operator []= takes integer key, $TYPE$ value returns nothing
| assign "value" to index "key"
|
| method operator [] takes integer key returns $TYPE$
| load the value at index "key"
|
| method has takes integer key returns boolean
| whether or not the key was assigned
|
----------------
struct TableArray
| static method operator [] takes integer array_size returns TableArray
| create a new array of Tables of size "array_size"
|
| method destroy takes nothing returns nothing
| destroy it
|
| method flush takes nothing returns nothing
| flush and destroy it
|
| method operator size takes nothing returns integer
| returns the size of the TableArray
|
| method operator [] takes integer key returns Table
| returns a Table accessible exclusively to index "key"
*/
globals
private integer less = 0 //Index generation for TableArrays (below 0).
private integer more = 8190 //Index generation for Tables.
//Configure it if you use more than 8190 "key" variables in your map (this will never happen though).
private hashtable ht = InitHashtable()
private key sizeK
private key listK
endglobals
private struct dex extends array
static method operator size takes nothing returns Table
return sizeK
endmethod
static method operator list takes nothing returns Table
return listK
endmethod
endstruct
private struct handles extends array
method has takes integer key returns boolean
return HaveSavedHandle(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSavedHandle(ht, this, key)
endmethod
endstruct
private struct agents extends array
method operator []= takes integer key, agent value returns nothing
call SaveAgentHandle(ht, this, key, value)
endmethod
endstruct
//! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE
private struct $TYPE$s extends array
method operator [] takes integer key returns $TYPE$
return Load$FUNC$(ht, this, key)
endmethod
method operator []= takes integer key, $TYPE$ value returns nothing
call Save$FUNC$(ht, this, key, value)
endmethod
method has takes integer key returns boolean
return HaveSaved$SUPER$(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSaved$SUPER$(ht, this, key)
endmethod
endstruct
private module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//! textmacro NEW_ARRAY takes FUNC, TYPE
private struct $TYPE$s extends array
method operator [] takes integer key returns $TYPE$
return Load$FUNC$Handle(ht, this, key)
endmethod
method operator []= takes integer key, $TYPE$ value returns nothing
call Save$FUNC$Handle(ht, this, key, value)
endmethod
method has takes integer key returns boolean
return HaveSavedHandle(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSavedHandle(ht, this, key)
endmethod
endstruct
private module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//Run these textmacros to include the entire hashtable API as wrappers.
//Don't be intimidated by the number of macros - Vexorian's map optimizer is
//supposed to kill functions which inline (all of these functions inline).
//! runtextmacro NEW_ARRAY_BASIC("Real", "Real", "real")
//! runtextmacro NEW_ARRAY_BASIC("Boolean", "Boolean", "boolean")
//! runtextmacro NEW_ARRAY_BASIC("String", "Str", "string")
//New textmacro to allow table.integer[] syntax for compatibility with textmacros that might desire it.
//! runtextmacro NEW_ARRAY_BASIC("Integer", "Integer", "integer")
//! runtextmacro NEW_ARRAY("Player", "player")
//! runtextmacro NEW_ARRAY("Widget", "widget")
//! runtextmacro NEW_ARRAY("Destructable", "destructable")
//! runtextmacro NEW_ARRAY("Item", "item")
//! runtextmacro NEW_ARRAY("Unit", "unit")
//! runtextmacro NEW_ARRAY("Ability", "ability")
//! runtextmacro NEW_ARRAY("Timer", "timer")
//! runtextmacro NEW_ARRAY("Trigger", "trigger")
//! runtextmacro NEW_ARRAY("TriggerCondition", "triggercondition")
//! runtextmacro NEW_ARRAY("TriggerAction", "triggeraction")
//! runtextmacro NEW_ARRAY("TriggerEvent", "event")
//! runtextmacro NEW_ARRAY("Force", "force")
//! runtextmacro NEW_ARRAY("Group", "group")
//! runtextmacro NEW_ARRAY("Location", "location")
//! runtextmacro NEW_ARRAY("Rect", "rect")
//! runtextmacro NEW_ARRAY("BooleanExpr", "boolexpr")
//! runtextmacro NEW_ARRAY("Sound", "sound")
//! runtextmacro NEW_ARRAY("Effect", "effect")
//! runtextmacro NEW_ARRAY("UnitPool", "unitpool")
//! runtextmacro NEW_ARRAY("ItemPool", "itempool")
//! runtextmacro NEW_ARRAY("Quest", "quest")
//! runtextmacro NEW_ARRAY("QuestItem", "questitem")
//! runtextmacro NEW_ARRAY("DefeatCondition", "defeatcondition")
//! runtextmacro NEW_ARRAY("TimerDialog", "timerdialog")
//! runtextmacro NEW_ARRAY("Leaderboard", "leaderboard")
//! runtextmacro NEW_ARRAY("Multiboard", "multiboard")
//! runtextmacro NEW_ARRAY("MultiboardItem", "multiboarditem")
//! runtextmacro NEW_ARRAY("Trackable", "trackable")
//! runtextmacro NEW_ARRAY("Dialog", "dialog")
//! runtextmacro NEW_ARRAY("Button", "button")
//! runtextmacro NEW_ARRAY("TextTag", "texttag")
//! runtextmacro NEW_ARRAY("Lightning", "lightning")
//! runtextmacro NEW_ARRAY("Image", "image")
//! runtextmacro NEW_ARRAY("Ubersplat", "ubersplat")
//! runtextmacro NEW_ARRAY("Region", "region")
//! runtextmacro NEW_ARRAY("FogState", "fogstate")
//! runtextmacro NEW_ARRAY("FogModifier", "fogmodifier")
//! runtextmacro NEW_ARRAY("Hashtable", "hashtable")
struct Table extends array
// Implement modules for intuitive syntax (tb.handle; tb.unit; etc.)
implement realm
implement integerm
implement booleanm
implement stringm
implement playerm
implement widgetm
implement destructablem
implement itemm
implement unitm
implement abilitym
implement timerm
implement triggerm
implement triggerconditionm
implement triggeractionm
implement eventm
implement forcem
implement groupm
implement locationm
implement rectm
implement boolexprm
implement soundm
implement effectm
implement unitpoolm
implement itempoolm
implement questm
implement questitemm
implement defeatconditionm
implement timerdialogm
implement leaderboardm
implement multiboardm
implement multiboarditemm
implement trackablem
implement dialogm
implement buttonm
implement texttagm
implement lightningm
implement imagem
implement ubersplatm
implement regionm
implement fogstatem
implement fogmodifierm
implement hashtablem
method operator handle takes nothing returns handles
return this
endmethod
method operator agent takes nothing returns agents
return this
endmethod
//set this = tb[GetSpellAbilityId()]
method operator [] takes integer key returns Table
return LoadInteger(ht, this, key) //return this.integer[key]
endmethod
//set tb[389034] = 8192
method operator []= takes integer key, Table tb returns nothing
call SaveInteger(ht, this, key, tb) //set this.integer[key] = tb
endmethod
//set b = tb.has(2493223)
method has takes integer key returns boolean
return HaveSavedInteger(ht, this, key) //return this.integer.has(key)
endmethod
//call tb.remove(294080)
method remove takes integer key returns nothing
call RemoveSavedInteger(ht, this, key) //call this.integer.remove(key)
endmethod
//Remove all data from a Table instance
method flush takes nothing returns nothing
call FlushChildHashtable(ht, this)
endmethod
//local Table tb = Table.create()
static method create takes nothing returns Table
local Table this = dex.list[0]
if this == 0 then
set this = more + 1
set more = this
else
set dex.list[0] = dex.list[this]
call dex.list.remove(this) //Clear hashed memory
endif
debug set dex.list[this] = -1
return this
endmethod
// Removes all data from a Table instance and recycles its index.
//
// call tb.destroy()
//
method destroy takes nothing returns nothing
debug if dex.list[this] != -1 then
debug call BJDebugMsg("Table Error: Tried to double-free instance: " + I2S(this))
debug return
debug endif
call this.flush()
set dex.list[this] = dex.list[0]
set dex.list[0] = this
endmethod
//! runtextmacro optional TABLE_BC_METHODS()
endstruct
//! runtextmacro optional TABLE_BC_STRUCTS()
struct TableArray extends array
//Returns a new TableArray to do your bidding. Simply use:
//
// local TableArray ta = TableArray[array_size]
//
static method operator [] takes integer array_size returns TableArray
local Table tb = dex.size[array_size] //Get the unique recycle list for this array size
local TableArray this = tb[0] //The last-destroyed TableArray that had this array size
debug if array_size <= 0 then
debug call BJDebugMsg("TypeError: Invalid specified TableArray size: " + I2S(array_size))
debug return 0
debug endif
if this == 0 then
set this = less - array_size
set less = this
else
set tb[0] = tb[this] //Set the last destroyed to the last-last destroyed
call tb.remove(this) //Clear hashed memory
endif
set dex.size[this] = array_size //This remembers the array size
return this
endmethod
//Returns the size of the TableArray
method operator size takes nothing returns integer
return dex.size[this]
endmethod
//This magic method enables two-dimensional[array][syntax] for Tables,
//similar to the two-dimensional utility provided by hashtables them-
//selves.
//
//ta[integer a].unit[integer b] = unit u
//ta[integer a][integer c] = integer d
//
//Inline-friendly when not running in debug mode
//
method operator [] takes integer key returns Table
static if DEBUG_MODE then
local integer i = this.size
if i == 0 then
call BJDebugMsg("IndexError: Tried to get key from invalid TableArray instance: " + I2S(this))
return 0
elseif key < 0 or key >= i then
call BJDebugMsg("IndexError: Tried to get key [" + I2S(key) + "] from outside TableArray bounds: " + I2S(i))
return 0
endif
endif
return this + key
endmethod
//Destroys a TableArray without flushing it; I assume you call .flush()
//if you want it flushed too. This is a public method so that you don't
//have to loop through all TableArray indices to flush them if you don't
//need to (ie. if you were flushing all child-keys as you used them).
//
method destroy takes nothing returns nothing
local Table tb = dex.size[this.size]
debug if this.size == 0 then
debug call BJDebugMsg("TypeError: Tried to destroy an invalid TableArray: " + I2S(this))
debug return
debug endif
if tb == 0 then
//Create a Table to index recycled instances with their array size
set tb = Table.create()
set dex.size[this.size] = tb
endif
call dex.size.remove(this) //Clear the array size from hash memory
set tb[this] = tb[0]
set tb[0] = this
endmethod
private static Table tempTable
private static integer tempEnd
//Avoids hitting the op limit
private static method clean takes nothing returns nothing
local Table tb = .tempTable
local integer end = tb + 0x1000
if end < .tempEnd then
set .tempTable = end
call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
else
set end = .tempEnd
endif
loop
call tb.flush()
set tb = tb + 1
exitwhen tb == end
endloop
endmethod
//Flushes the TableArray and also destroys it. Doesn't get any more
//similar to the FlushParentHashtable native than this.
//
method flush takes nothing returns nothing
debug if this.size == 0 then
debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
debug return
debug endif
set .tempTable = this
set .tempEnd = this + this.size
call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
call this.destroy()
endmethod
endstruct
//NEW: Added in Table 4.0. A fairly simple struct but allows you to do more
//than that which was previously possible.
struct HashTable extends array
//Enables myHash[parentKey][childKey] syntax.
//Basically, it creates a Table in the place of the parent key if
//it didn't already get created earlier.
method operator [] takes integer index returns Table
local Table t = Table(this)[index]
if t == 0 then
set t = Table.create()
set Table(this)[index] = t //whoops! Forgot that line. I'm out of practice!
endif
return t
endmethod
//You need to call this on each parent key that you used if you
//intend to destroy the HashTable or simply no longer need that key.
method remove takes integer index returns nothing
local Table t = Table(this)[index]
if t != 0 then
call t.destroy()
call Table(this).remove(index)
endif
endmethod
//Added in version 4.1
method has takes integer index returns boolean
return Table(this).has(index)
endmethod
//HashTables are just fancy Table indices.
method destroy takes nothing returns nothing
call Table(this).destroy()
endmethod
//Like I said above...
static method create takes nothing returns thistype
return Table.create()
endmethod
endstruct
endlibrary
function Trig_Unbezeichneter_Ausl__ser_001_Actions takes nothing returns nothing
endfunction
//===========================================================================
function InitTrig_Table takes nothing returns nothing
set gg_trg_Table = CreateTrigger( )
call TriggerAddAction( gg_trg_Table, function Trig_Unbezeichneter_Ausl__ser_001_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
library ArrowKeyEvent /*
=========================================================================
ArrowKeyEvent version 1.0.0.1
=========================================================================
Credits:
-------------------------------------------------------------------------
- Written by Bribe.
- Earth-Fury for providing a lot of inspiration for the development of
this system (especially documentation) via his KeyAction resource.
- tooltiperror & Sgqvur for providing very helpful, constructive advice.
=========================================================================
Introduction:
-------------------------------------------------------------------------
Easy to use, efficient system for handling all arrow key events. It uses
arrays and GetHandleId lookups to avoid the trap of many cloned functions
that so many arrow key systems suffer from.
=========================================================================
API Guide:
-------------------------------------------------------------------------
To help centralize and make everything understandable, I originally used
the constants appointed by Blizzard (bj_KEYEVENTKEY_LEFT/RIGHT/etc). But
there was a lot of criticism over their ugliness so I made the following
constants to correspond accordingly. They have the same values as the BJ
constants, so you can use whichever is more appealing for you.
Their purpose is to be passed as arguments so you are able to query such
things as "is this key pressed" or simply to help make sense of what key
was pressed from an event response and interpret it as an integer.
constant integer ARROW_KEY_LEFT = 0
constant integer ARROW_KEY_RIGHT = 1
constant integer ARROW_KEY_DOWN = 2
constant integer ARROW_KEY_UP = 3
-------------------------------------------------------------------------
As I was developing this resource, is was mostly written in vanilla JASS.
I had since converted it to OOP syntax but it has been requested to bring
it back. I have made it available once again.
function IsArrowKeyPressed
takes player whichPlayer, integer arrowKey
returns boolean
To find out if the arrow key was pressed, you need to first ask which
player is holding down the key, and then pass an ARROW_KEY constant
to represent the key you are querying for.
function RegisterArrowKeyEvent
takes code onEvent
returns nothing
Instead of making up to 8 different functions for 8 different events,
you can use this instead. Just specify a function that you want to be
called whenever any key is pressed. For event responses, reference 1
of the following 3 functions:
function GetEventArrowKeyPlayerId
takes nothing
returns integer
This is more of an optimization benefit than not. GetTriggerPlayer()
will get you the player who pressed the key, but most of the time you
just need to know the player ID of that person.
function GetEventArrowKey
takes nothing
returns integer
Call this function to find out which key was pressed. It will return
one of the four ARROW_KEY constants, of course.
function IsEventArrowKeyPressed
takes nothing
returns boolean
This is also here more for optimization's benefit. You can certainly
use "IsArrowKeyPressed(GetEventArrowKey(GetEventArrowKeyPlayerId()))"
but this is much more convenient I must say.
-------------------------------------------------------------------------
"implement ArrowKey"
ArrowKey API is accessible as if it were part of the implementing struct
itself. As a bonus, you can create a method "onArrowKeyEvent" that gets
called automatically when any key is pressed. The method musn't be static,
because the member "this" is a player ID (to mirror the ArrowKey struct's
own API). It must take an integer as its first argument to represent the
pressed or released key. As a final argument, it must take a boolean to
determine if the key was pressed (true) or released (false).
The member "this" taken by the method is a player ID.
*/
//=======================================================================
//
// System Code
//
//=======================================================================
globals
//-------------------------------------------------------------------
// Yo dawg, I herd you like constant variables so I gave you some new
// constant variables so you can have some constant variables to go
// with Blizzard's constant variables.
//
constant integer ARROW_KEY_LEFT = bj_KEYEVENTKEY_LEFT
constant integer ARROW_KEY_RIGHT = bj_KEYEVENTKEY_RIGHT
constant integer ARROW_KEY_DOWN = bj_KEYEVENTKEY_DOWN
constant integer ARROW_KEY_UP = bj_KEYEVENTKEY_UP
endglobals
//=======================================================================
// Ugly modules are needed to prevent initialization bugs.
//
private module Init
private static method onInit takes nothing returns nothing
local player p
local integer i = 12
local trigger t = .trig
loop
set i = i - 1
set p = Player(i)
if GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(p) == MAP_CONTROL_USER then
//Register arrow key events for playing players
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_ARROW_LEFT_DOWN)
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_ARROW_LEFT_UP)
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_ARROW_RIGHT_DOWN)
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_ARROW_RIGHT_UP)
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_ARROW_DOWN_DOWN)
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_ARROW_DOWN_UP)
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_ARROW_UP_DOWN)
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_ARROW_UP_UP)
//Run if library ArrowKey is found in the map.
//! runtextmacro optional INIT_ARROW_KEY_AA()
endif
exitwhen i == 0
endloop
//Run if library ArrowKey is found in the map.
//! runtextmacro optional INIT_ARROW_KEY_CALL_LINK()
call .registerEvent(function ArrowKey.actions)
set p = null
set t = null
endmethod
endmodule
//=======================================================================
// A central struct to handle all ArrowKey mechanics. This has its uses,
// giving you slightly more control over the inner system functionality.
//
struct ArrowKey extends array
//-------------------------------------------------------------------
// Event responses
//
readonly static integer eventKey = 0 //Arrow key that triggered the event.
readonly static boolean eventKeyPressed = false //Was the arrow key pressed?
readonly static ArrowKey eventPlayerId = 0 //The id of the player who pressed the key.
//Run if library ArrowKey is found in the map.
//! runtextmacro optional ARROW_KEY_DECLARE_ARRAYS()
//-------------------------------------------------------------------
// System variables
//
private static trigger trig = CreateTrigger() //Handles all events.
private static boolean array press //Is key pressed?
//===================================================================
// User-friendly typecasting.
//
static method operator [] takes player who returns ArrowKey
return GetPlayerId(who)
endmethod
//===================================================================
// Great for simplifying arrow key events - this function runs when
// any player presses or releases an arrow key. The code passed is
// expected to "return false".
//
static method registerEvent takes code onEvent returns nothing
call TriggerAddCondition(.trig, Filter(onEvent))
return
endmethod
//===================================================================
// Returns true if the key is pressed, false if it is released.
//
method isPressed takes integer arrow returns boolean
return press[this + arrow * 12]
endmethod
//Run if library ArrowKey is found in the map.
//! runtextmacro optional ARROW_KEY_AXIS_METHODS()
//===================================================================
// If you are running debug tests, this might come in handy.
//
static if DEBUG_MODE then
static method getKeyName takes integer arrow returns string
if arrow == ARROW_KEY_LEFT then
return "LEFT"
elseif arrow == ARROW_KEY_RIGHT then
return "RIGHT"
elseif arrow == ARROW_KEY_DOWN then
return "DOWN"
elseif arrow == ARROW_KEY_UP then
return "UP"
endif
return "--"
endmethod
endif
//===================================================================
//
// Private Components
//
//===================================================================
//===================================================================
// Key event handler.
//
private static method actions takes nothing returns nothing
local integer id = GetHandleId(GetTriggerEventId()) - 261
set .eventPlayerId = GetPlayerId(GetTriggerPlayer())
//If id is an even number, the key was pressed.
set .eventKey = id / 2
set .eventKeyPressed = .eventKey * 2 == id
set .press[.eventPlayerId + .eventKey * 12] = .eventKeyPressed
//Run if library ArrowKey is found in the map.
//! runtextmacro optional ARROW_KEY_SETUP()
endmethod
//Run if library ArrowKey is found in the map.
//! runtextmacro optional INIT_ARROW_KEY_LINK()
//Initialize the system via module
implement Init
endstruct
//=======================================================================
//
// Event Responses
//
//=======================================================================
//=======================================================================
function IsArrowKeyPressed takes player whichPlayer, integer arrowKey returns boolean
return ArrowKey[whichPlayer].isPressed(arrowKey)
endfunction
//=======================================================================
function RegisterArrowKeyEvent takes code onEvent returns nothing
call ArrowKey.registerEvent(onEvent)
endfunction
//=======================================================================
function GetEventArrowKeyPlayerId takes nothing returns integer
return ArrowKey.eventPlayerId
endfunction
//=======================================================================
function GetEventArrowKey takes nothing returns integer
return ArrowKey.eventKey
endfunction
//=======================================================================
function IsEventArrowKeyPressed takes nothing returns boolean
return ArrowKey.eventKeyPressed
endfunction
//=======================================================================
// Implementation of this module allows you to make your struct "extend"
// the ArrowKey struct. As a bonus feature, you can create a method named
// "onArrowKeyEvent" that is called whenever a key is pressed or released.
// The method needs "takes integer arrow, boolean pressed", and must be
// positioned *above* the "implement ArrowKey" statement (this way it is
// detected by the static if and doesn't compile to a function interface).
//
module ArrowKey
//Delegates are fun, you should try them out.
private delegate ArrowKey AK
//===================================================================
// Please call this method from *below the module implement statement
// if you know what's good for you.
//
static method operator [] takes player who returns thistype
return GetPlayerId(who)
endmethod
static if thistype.onArrowKeyEvent.exists then
private static method eventProxy takes nothing returns nothing
call thistype(.eventPlayerId).onArrowKeyEvent(.eventKey, .eventKeyPressed)
endmethod
endif
private static method onInit takes nothing returns nothing
local thistype i = 12
loop
set i = i - 1
set i.AK = i //Delegates require some delegation of course.
exitwhen i == 0
endloop
static if thistype.onArrowKeyEvent.exists then
call ArrowKey.registerEvent(function thistype.eventProxy)
endif
endmethod
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Alloc /* v1.3.1.1
*************************************************************************************
*
* */ uses /*
*
* */ optional ErrorMessage /* github.com/nestharus/JASS/tree/master/jass/Systems/ErrorMessage
* */ optional MemoryAnalysis /*
*
*************************************************************************************
*
* Minimizes code generation and global variables while maintaining
* excellent performance.
*
* local thistype this = recycler[0]
*
* if (recycler[this] == 0) then
* set recycler[0] = this + 1
* else
* set recycler[0] = recycler[this]
* endif
*
************************************************************************************
*
* module Alloc
*
* static method allocate takes nothing returns thistype
* method deallocate takes nothing returns nothing
*
* The Following Require Error Message To Be In The Map
* --------------------------------------------------------
*
* debug readonly boolean allocated
*
* The Following Require Memory Analysis To Be In The Map
* --------------------------------------------------------
*
* debug readonly integer monitorCount
* - the amount of global memory being monitored by this
* debug readonly integer monitorString
* - gets a string representation of all global memory being monitored by this
* debug readonly integer address
* - global memory address for debugging
* - used with monitor and stopMonitor
*
* debug static method calculateMemoryUsage takes nothing returns integer
* debug static method getAllocatedMemoryAsString takes nothing returns string
*
* debug method monitor takes string label, integer address returns nothing
* - monitor a global memory address with a label
* - used to identify memory leaks
* - should be memory that ought to be destroyed by the time this is destroyed
* debug method stopMonitor takes integer address returns nothing
* - stops monitoring global memory
* debug method stopMonitorValue takes handle monitoredHandle returns nothing
* - stops monitoring handle values
*
* The Following Are Used To Monitor Handle Values
*
* debug method monitor_widget takes string label, widget handleToTrack returns nothing
* debug method monitor_destructable takes string label, destructable handleToTrack returns nothing
* debug method monitor_item takes string label, item handleToTrack returns nothing
* debug method monitor_unit takes string label, unit handleToTrack returns nothing
* debug method monitor_timer takes string label, timer handleToTrack returns nothing
* debug method monitor_trigger takes string label, trigger handleToTrack returns nothing
* debug method monitor_triggercondition takes string label, triggercondition handleToTrack returns nothing
* debug method monitor_triggeraction takes string label, triggeraction handleToTrack returns nothing
* debug method monitor_force takes string label, force handleToTrack returns nothing
* debug method monitor_group takes string label, group handleToTrack returns nothing
* debug method monitor_location takes string label, location handleToTrack returns nothing
* debug method monitor_rect takes string label, rect handleToTrack returns nothing
* debug method monitor_boolexpr takes string label, boolexpr handleToTrack returns nothing
* debug method monitor_effect takes string label, effect handleToTrack returns nothing
* debug method monitor_unitpool takes string label, unitpool handleToTrack returns nothing
* debug method monitor_itempool takes string label, itempool handleToTrack returns nothing
* debug method monitor_quest takes string label, quest handleToTrack returns nothing
* debug method monitor_defeatcondition takes string label, defeatcondition handleToTrack returns nothing
* debug method monitor_timerdialog takes string label, timerdialog handleToTrack returns nothing
* debug method monitor_leaderboard takes string label, leaderboard handleToTrack returns nothing
* debug method monitor_multiboard takes string label, multiboard handleToTrack returns nothing
* debug method monitor_multiboarditem takes string label, multiboarditem handleToTrack returns nothing
* debug method monitor_dialog takes string label, dialog handleToTrack returns nothing
* debug method monitor_button takes string label, button handleToTrack returns nothing
* debug method monitor_texttag takes string label, texttag handleToTrack returns nothing
* debug method monitor_lightning takes string label, lightning handleToTrack returns nothing
* debug method monitor_image takes string label, image handleToTrack returns nothing
* debug method monitor_ubersplat takes string label, ubersplat handleToTrack returns nothing
* debug method monitor_region takes string label, region handleToTrack returns nothing
* debug method monitor_fogmodifier takes string label, fogmodifier handleToTrack returns nothing
* debug method monitor_hashtable takes string label, hashtable handleToTrack returns nothing
*
************************************************************************************/
module Alloc
/*
* stack
*/
private static integer array recycler
static if LIBRARY_MemoryAnalysis then
debug private MemoryMonitor globalAddress
debug method operator address takes nothing returns integer
debug call ThrowError(recycler[this] != -1, "Alloc", "address", "thistype", this, "Attempted To Access Null Instance.")
debug return globalAddress
debug endmethod
endif
/*
* allocation
*/
static method allocate takes nothing returns thistype
local thistype this = recycler[0]
static if LIBRARY_ErrorMessage then
debug call ThrowError(this == 8192, "Alloc", "allocate", "thistype", 0, "Overflow.")
endif
if (recycler[this] == 0) then
set recycler[0] = this + 1
else
set recycler[0] = recycler[this]
endif
static if LIBRARY_ErrorMessage then
debug set recycler[this] = -1
endif
static if LIBRARY_MemoryAnalysis then
debug set globalAddress = MemoryMonitor.allocate("thistype")
endif
return this
endmethod
method deallocate takes nothing returns nothing
static if LIBRARY_ErrorMessage then
debug call ThrowError(recycler[this] != -1, "Alloc", "deallocate", "thistype", this, "Attempted To Deallocate Null Instance.")
endif
static if LIBRARY_MemoryAnalysis then
debug call globalAddress.deallocate()
debug set globalAddress = 0
endif
set recycler[this] = recycler[0]
set recycler[0] = this
endmethod
static if LIBRARY_MemoryAnalysis then
debug method monitor takes string label, integer address returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor(label, address)
debug endmethod
debug method stopMonitor takes integer address returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "stopMonitor", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.stopMonitor(address)
debug endmethod
debug method stopMonitorValue takes handle monitoredHandle returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "stopMonitorValue", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.stopMonitorValue(monitoredHandle)
debug endmethod
debug method operator monitorCount takes nothing returns integer
debug call ThrowError(recycler[this] != -1, "Alloc", "monitorCount", "thistype", this, "Attempted To Access Null Instance.")
debug return globalAddress.monitorCount
debug endmethod
debug method operator monitorString takes nothing returns string
debug call ThrowError(recycler[this] != -1, "Alloc", "monitorString", "thistype", this, "Attempted To Access Null Instance.")
debug return globalAddress.monitorString
debug endmethod
debug method monitor_widget takes string label, widget handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_widget", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_widget(label, handleToTrack)
debug endmethod
debug method monitor_destructable takes string label, destructable handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_destructable", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_destructable(label, handleToTrack)
debug endmethod
debug method monitor_item takes string label, item handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_item", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_item(label, handleToTrack)
debug endmethod
debug method monitor_unit takes string label, unit handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_unit", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_unit(label, handleToTrack)
debug endmethod
debug method monitor_timer takes string label, timer handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_timer", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_timer(label, handleToTrack)
debug endmethod
debug method monitor_trigger takes string label, trigger handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_trigger", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_trigger(label, handleToTrack)
debug endmethod
debug method monitor_triggercondition takes string label, triggercondition handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_triggercondition", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_triggercondition(label, handleToTrack)
debug endmethod
debug method monitor_triggeraction takes string label, triggeraction handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_triggeraction", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_triggeraction(label, handleToTrack)
debug endmethod
debug method monitor_force takes string label, force handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_force", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_force(label, handleToTrack)
debug endmethod
debug method monitor_group takes string label, group handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_group", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_group(label, handleToTrack)
debug endmethod
debug method monitor_location takes string label, location handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_location", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_location(label, handleToTrack)
debug endmethod
debug method monitor_rect takes string label, rect handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_rect", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_rect(label, handleToTrack)
debug endmethod
debug method monitor_boolexpr takes string label, boolexpr handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_boolexpr", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_boolexpr(label, handleToTrack)
debug endmethod
debug method monitor_effect takes string label, effect handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_effect", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_effect(label, handleToTrack)
debug endmethod
debug method monitor_unitpool takes string label, unitpool handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_unitpool", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_unitpool(label, handleToTrack)
debug endmethod
debug method monitor_itempool takes string label, itempool handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_itempool", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_itempool(label, handleToTrack)
debug endmethod
debug method monitor_quest takes string label, quest handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_quest", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_quest(label, handleToTrack)
debug endmethod
debug method monitor_defeatcondition takes string label, defeatcondition handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_defeatcondition", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_defeatcondition(label, handleToTrack)
debug endmethod
debug method monitor_timerdialog takes string label, timerdialog handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_timerdialog", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_timerdialog(label, handleToTrack)
debug endmethod
debug method monitor_leaderboard takes string label, leaderboard handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_leaderboard", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_leaderboard(label, handleToTrack)
debug endmethod
debug method monitor_multiboard takes string label, multiboard handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_multiboard", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_multiboard(label, handleToTrack)
debug endmethod
debug method monitor_multiboarditem takes string label, multiboarditem handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_multiboarditem", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_multiboarditem(label, handleToTrack)
debug endmethod
debug method monitor_dialog takes string label, dialog handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_dialog", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_dialog(label, handleToTrack)
debug endmethod
debug method monitor_button takes string label, button handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_button", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_button(label, handleToTrack)
debug endmethod
debug method monitor_texttag takes string label, texttag handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_texttag", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_texttag(label, handleToTrack)
debug endmethod
debug method monitor_lightning takes string label, lightning handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_lightning", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_lightning(label, handleToTrack)
debug endmethod
debug method monitor_image takes string label, image handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_image", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_image(label, handleToTrack)
debug endmethod
debug method monitor_ubersplat takes string label, ubersplat handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_ubersplat", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_ubersplat(label, handleToTrack)
debug endmethod
debug method monitor_region takes string label, region handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_region", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_region(label, handleToTrack)
debug endmethod
debug method monitor_fogmodifier takes string label, fogmodifier handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_fogmodifier", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_fogmodifier(label, handleToTrack)
debug endmethod
debug method monitor_hashtable takes string label, hashtable handleToTrack returns nothing
debug call ThrowError(recycler[this] != -1, "Alloc", "monitor_hashtable", "thistype", this, "Attempted To Access Null Instance.")
debug call globalAddress.monitor_hashtable(label, handleToTrack)
debug endmethod
static if DEBUG_MODE then
//! runtextmacro optional MEMORY_ANALYSIS_STATIC_FIELD_NEW("recycler")
static method calculateMemoryUsage takes nothing returns integer
return calculateAllocatedMemory__recycler()
endmethod
static method getAllocatedMemoryAsString takes nothing returns string
return allocatedMemoryString__recycler()
endmethod
endif
endif
/*
* analysis
*/
static if LIBRARY_ErrorMessage then
debug method operator allocated takes nothing returns boolean
debug return recycler[this] == -1
debug endmethod
endif
/*
* initialization
*/
private static method onInit takes nothing returns nothing
set recycler[0] = 1
endmethod
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SequenceT /* v1.1 By IcemanBo
*/ requires /*
*/ VectorT /* hiveworkshop.com/forums/submissions-414/containers-vector-t-248942/
*/ Alloc /* any alloc.
A sequence is a special order of any data type.
Input is given through the API and the user can
react based on the provided input responses.
integer and string sequences are already supported.
See config.
Attention.
Sequences work with vectors from VectorT library.
If you want create a sequence of a new type, you
also have to create the VECTOR_TYPE respectivly.
*/
// Config
//! novjass
textmacro SEQUENCE_TYPE takes SEQUENCE_TYPE_NAME, VECTOR_TYPE
textmacro SEQUENCE takes SEQUENCE_TYPE_NAME, SEQUENCE_NAME, TYPE
//! endnovjass
// For integer sequences
//! runtextmacro SEQUENCE_TYPE("IntegerSequenceType", "IntegerVector")
//! runtextmacro SEQUENCE("IntegerSequenceType", "IntegerSequence", "integer")
// For string sequences
//! runtextmacro SEQUENCE_TYPE("StringSequenceType", "StringVector")
//! runtextmacro SEQUENCE("StringSequenceType", "StringSequence", "string")
// Read the readme for the system's API
// ================ End Config =================== //
//! textmacro SEQUENCE_TYPE takes TYPE_NAME, VECTOR_TYPE
struct $TYPE_NAME$ extends array
implement Alloc
readonly $VECTOR_TYPE$ vector
readonly integer size
static method create takes $VECTOR_TYPE$ vec returns thistype
local thistype this = allocate()
set this.vector = vec
set this.size = vec.size()
return this
endmethod
method destroy takes nothing returns nothing
call this.vector.destroy()
call this.deallocate()
endmethod
endstruct
//! endtextmacro
globals
boolean IsSequenceSolved
boolean IsSequenceInputCorrect
integer CurrentSequenceVectorPosition
endglobals
//! textmacro SEQUENCE takes TYPE_NAME NAME, TYPE
struct $NAME$ extends array
implement Alloc
readonly $TYPE_NAME$ sequence
readonly integer currentPosition
method onSequenceEvent takes $TYPE$ input returns nothing
set CurrentSequenceVectorPosition = this.currentPosition
set IsSequenceInputCorrect = (input == this.sequence.vector[CurrentSequenceVectorPosition])
if (IsSequenceInputCorrect) then
set this.currentPosition = this.currentPosition + 1
set IsSequenceSolved = this.currentPosition >= this.sequence.size
else
set IsSequenceSolved = false
endif
endmethod
method destroy takes nothing returns nothing
call deallocate()
endmethod
static method create takes $TYPE_NAME$ sequ, integer startPos returns thistype
local thistype this = allocate()
set this.currentPosition = startPos
set this.sequence = sequ
return this
endmethod
endstruct
//! endtextmacro
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
// In case you want to create your own sequence types you need to run the textmacros in the Sequence config at first.
// There is already a IntegerSequenceType and a StringSequenceType by default.
// When done with the config have a look at the API:
// Attention:
// The $ NAME $ place holders are respectivly to the parameters that are used in config.
/* You now need to create a default sequence that can be used: */
// struct SEQUENCE_TYPE_NAME - constructor
static method create takes $VECTOR_TYPE$ vec returns thistype
// struct SEQUENCE_TYPE_NAME - destructor
method destroy takes nothing returns nothing
// struct SEQUENCE_TYPE_NAME - readonly members
readonly $VECTOR_TYPE$ vector
readonly integer size
/* To start now a new sequence use: */
// struct SEQUENCE_NAME - constructor
static method create takes SEQUENCE_TYPE_NAME sequ, integer startPos returns thistype
// startPos is the position where you want to start. Usually it should be 0.
// struct SEQUENCE_NAME - destructor
method destroy takes nothing returns nothing
// struct SEQUENCE_NAME - readonly members
readonly SEQUENCE_TYPE_NAME sequence
readonly integer currentPosition
/* To give input to the sequence interact with using this method */
method onSequenceEvent takes $TYPE$ input returns nothing
// After onSequenceEvent is called you have access to following variables:
boolean IsSequenceSolved // Is sequence completed
boolean IsSequenceInputCorrect // If current input was correct
integer CurrentSequenceVectorPosition // Current position in sequence