Executor
I see you
- Reaction score
- 57
TrackMapSystem
- Language = vJass
- System Requirements = Event;
- Usage Requirements = jass abilities
Description:
This System allows the fast creation of rects filled with trackables or as I call them "TrackMaps". The object trackable is able to react to mouse movements aswell as to mouse clicks.
I simply use the model of a transparent square for the trackable to fill a rect without modifying map appearance.
In TrackMaps you will be able to access the cursor position, cursor clicks on the ground and cursor movements over the ground.
Screenshot:
You won't really see the point of my system by looking at this screenshot.
Instruction:
Just insert the whole system code into an empty trigger.
If you have problems look at the Demo Map.
Problems:
TrackMaps cannot be destroyed, as trackables aren't removable. Destroying a TrackMap will lead to the removal of the triggers but nothing more.
Normal clicks on the ground will malfunction because the ground cannot be directly acessed anymore.
You should try it out!
Interface:
JASS:
function SetUpTrackMap takes rect area, player p, boolean veryprecise returns TrackMap
// boolean veryprecise => My system grants the possibilty to use a smaller or a bigger quadrat as a model for the TrackMap
// true means you want the small model and more trackables while false means that the big model will be used aswell as less trackables
// In general : more trackables => more lag, more precision.. less trackables => less lag, less precision
function SetUpTrackMapEx takes rect area, player p, real precision, boolean timed returns TrackMap
// real precision means you can choose the distance between the trackables.. but I would say you should use one of the two constants
// given in the globals section.. you also can see how they are used in the system code on the bottom.
// boolean timed => generates TrackMap dynamically while the game is running.. means that the TrackMap will take a few moments to initialize but it
// shouldn't lag
// Any TrackMap reacts:
function TriggerRegisterAnyMouseEvent takes trigger t returns nothing
// Any TrackMap reacts to a Click or a Track Event
function TriggerRegisterAnyClickEvent takes trigger t returns nothing
// Any TrackMap reacts to a Click Event
function TriggerRegisterAnyTrackEvent takes trigger t returns nothing
// Any TrackMap reacts to a Track Event
// A specific TrackMap reacts
function TriggerRegisterMouseEvent takes trigger t, TrackMap tm returns nothing
// A specific TrackMap reacts to a Click or a Track Event
function TriggerRegisterClickEvent takes trigger t, TrackMap tm returns nothing
// A specific TrackMap reacts to a ClickEvent
function TriggerRegisterTrackEvent takes trigger t, TrackMap tm returns nothing
// A specific TrackMap reacts to a Track Event
// Track = Cursor touches a trackable
// Click = User clicked on a trackable
// Mouse = Track or Click
function Clicked takes nothing returns boolean
function Tracked takes nothing returns boolean
function GetMousePosX takes integer p returns real
function GetMousePosY takes integer p returns real
function GetTriggerMousePosX takes nothing returns real
function GetTriggerMousePosY takes nothing returns real
function GetTriggerTrackMap takes nothing returns TrackMap
function GetMouseUsingPlayer takes nothing returns player
function GetMouseUsingPlayerId takes nothing returns integer
Code:
Requirement Event
System Code:
JASS:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~ Event ~~ By Jesus4Lyf ~~ Version 1.03 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is Event?
// - Event simulates Warcraft III events. They can be created,
// registered for, fired and also destroyed.
// - Event, therefore, can also be used like a trigger "group".
// - This was created when there was an influx of event style systems
// emerging that could really benefit from a standardised custom
// events snippet. Many users were trying to achieve the same thing
// and making the same kind of errors. This snippet aims to solve that.
//
// Functions:
// - Event.create() --> Creates a new Event.
// - .chainDestroy() --> Destroys an Event.
// DO NOT use .destroy().
// - .fire() --> Fires all triggers which have been
// registered on this Event.
// - .register(trigger) --> Registers another trigger on this Event.
//
// Details:
// - Event is extremely efficient and lightweight.
// - It is safe to use with dynamic triggers.
// - Internally, it is just a singularly linked list. Very simple.
//
// How to import:
// - Create a trigger named Event.
// - Convert it to custom text and replace the whole trigger text with this.
//
// Thanks:
// - Builder Bob for the trigger destroy detection method.
// - Azlier for inspiring this by ripping off my dodgier code.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library Event
///////////////
// EventRegs //
////////////////////////////////////////////////////////////////////////////
// For reading this far, you can learn one thing more.
// Unlike normal Warcraft III events, you can attach to Event registries.
//
// Event Registries are registrations of one trigger on one event.
// These cannot be created or destroyed, just attached to.
//
// It is VERY efficient for loading and saving data.
//
// Functions:
// - set eventReg.data = someStruct --> Store data.
// - eventReg.data --> Retreive data.
// - Event.getTriggeringEventReg() --> Get the triggering EventReg.
//
struct EventReg
integer data
method clear takes nothing returns nothing
set this.data=0
endmethod
endstruct
struct Event
private trigger trig
private Event next
static method create takes nothing returns Event
local Event this=Event.allocate()
set this.next=0
return this
endmethod
private static Event current
static method getTriggeringEventReg takes nothing returns EventReg
return .current
endmethod
private static trigger t
method fire takes nothing returns nothing
local Event curr
// this = last.
loop
set curr=this.next
exitwhen curr==0
set .t=curr.trig
if IsTriggerEnabled(.t) then
set .current=curr
if TriggerEvaluate(.t) then
call TriggerExecute(.t)
endif
set this=curr
else
call EnableTrigger(.t) // Was trigger destroyed?
if IsTriggerEnabled(.t) then
call DisableTrigger(.t)
set this=curr
else // If trigger destroyed...
set .current.trig=null
set this.next=curr.next
call curr.destroy()
endif
endif
endloop
endmethod
method register takes trigger t returns EventReg
local Event new=Event.allocate()
set new.next=this.next
set new.trig=t
set this.next=new
call EventReg(new).clear()
return new
endmethod
method chainDestroy takes nothing returns nothing
loop
call this.destroy()
set this=this.next
exitwhen this==0
set this.trig=null
endloop
endmethod
endstruct
/////////////////////////////////////////////////////
// Demonstration Functions & Alternative Interface //
////////////////////////////////////////////////////////////////////////////
// What this would look like in normal WC3 style JASS (should all inline).
//
function CreateEvent takes nothing returns Event
return Event.create()
endfunction
function DestroyEvent takes Event whichEvent returns nothing
call whichEvent.chainDestroy()
endfunction
function FireEvent takes Event whichEvent returns nothing
call whichEvent.fire()
endfunction
function TriggerRegisterEvent takes trigger whichTrigger, Event whichEvent returns EventReg
return whichEvent.register(whichTrigger)
endfunction
// And for EventRegs...
function SetEventRegData takes EventReg whichEventReg, integer data returns nothing
set whichEventReg.data=data
endfunction
function GetEventRegData takes EventReg whichEventReg returns integer
return whichEventReg.data
endfunction
function GetTriggeringEventReg takes nothing returns integer
return Event.getTriggeringEventReg()
endfunction
endlibrary
System Code:
JASS:
library TrackMapSystem initializer InitSystem uses Event
//=====================================================================================
// ||
// TrackMapSystem ||
// ||
// created by Lord_Executor alias Executor alias Executor1 ||
// ||
// Credits ||
// ||
// Vexorian [JNGP,Dummy.mdx] ||
// tamisrah [Advice] ||
// Azelier [Ideas] ||
// Jesus4Lyf [Event] ||
// ||
//=====================================================================================
//=====================================================================================
// ||
// This system allows you the fast and effective set up of TrackMaps which means ||
// filling an area with trackable objects which will callback to cursor actions. ||
// ||
// I create those trackables without a visible model, which allows them to be ||
// invisible ingame but still able to determine move and click of the cursor. ||
// ||
// There are several problems with this system because normal orders on TrackMapped ||
// ground won't be handled normal anymore. But you should try for yourself. ||
// ||
//=====================================================================================
globals
//May be modified:
private constant real TIMER_INTERVAL = 0.05
private constant integer LOOP_BREAK_VALUE = 2500
// You should know what you do if you want to modify these:
private constant string MODEL_SMALL = "Doodads\\Terrain\\InvisiblePlatformSmall\\InvisiblePlatformSmall.mdl"
private constant string MODEL_NORMAL = "Doodads\\Terrain\\InvisiblePlatform\\InvisiblePlatform.mdl"
private constant real RADIUS_NORMAL = 73.59
// Usuable Constants
constant real MOUSEPOSITION_HIGH_PRECISION = RADIUS_NORMAL
constant real MOUSEPOSITION_LESS_PRECISION = RADIUS_NORMAL * 2
//System Vars (do not modify)
private hashtable Hash = null
private constant key SLOT_TRACKDATA
private constant key SLOT_STRUCT
private real array TMpx
private real array TMpy
private boolean clicked = false
private integer TMlasttm = 0
private integer TMlastplayer = -1
endglobals
private function InitSystem takes nothing returns nothing
set Hash = InitHashtable()
endfunction
private function SetTriggerData takes trigger t, integer i returns nothing
loop
exitwhen i <= 0
call TriggerExecute(t)
set i = i - 1
endloop
endfunction
private function DestroyTriggerDelayed takes trigger t returns nothing
call TriggerSleepAction(3.0)
call DestroyTrigger(t)
endfunction
private struct trackdata
readonly real x
readonly real y
static method create takes real x, real y returns thistype
local thistype this = thistype.allocate()
set .x = x
set .y = y
return this
endmethod
endstruct
private struct cache
public real res
public string mod
public boolean timed
public real x_MIN
public real y_MIN
public real x_MAX
public real y_MAX
static method create takes nothing returns thistype
return thistype.allocate()
endmethod
endstruct
struct TrackMap
readonly trigger TrigTrack
readonly trigger TrigClick
readonly integer p
readonly rect r
readonly boolean active
private static boolexpr TrackHandle
private static boolexpr ClickHandle
private static Event anyClick
private static Event anyTrack
private Event onClick
private Event onTrack
static method registerAnyClick takes trigger t returns nothing
call .anyClick.register(t)
endmethod
static method registerAnyTrack takes trigger t returns nothing
call .anyTrack.register(t)
endmethod
static method registerAnyChange takes trigger t returns nothing
call .anyClick.register(t)
call .anyTrack.register(t)
endmethod
method registerClick takes trigger t returns nothing
call .onClick.register(t)
endmethod
method registerTrack takes trigger t returns nothing
call .onTrack.register(t)
endmethod
method registerChange takes trigger t returns nothing
call .onClick.register(t)
call .onTrack.register(t)
endmethod
private static method TrackHandleEx takes nothing returns boolean
local thistype map = GetTriggerExecCount(GetTriggeringTrigger())
local trackdata d = LoadInteger(Hash,GetHandleId(GetTriggeringTrackable()),SLOT_TRACKDATA)
set TMlasttm = map
set TMpx[map.p] = d.x
set TMpy[map.p] = d.y
set TMlastplayer = map.p
set clicked = false
call map.onTrack.fire()
call .anyTrack.fire()
return false
endmethod
private static method ClickHandleEx takes nothing returns boolean
local thistype map = GetTriggerExecCount(GetTriggeringTrigger())
local trackdata d = LoadInteger(Hash,GetHandleId(GetTriggeringTrackable()),SLOT_TRACKDATA)
set TMlasttm = map
set TMpx[map.p] = d.x
set TMpy[map.p] = d.y
set TMlastplayer = map.p
set clicked = true
call map.onClick.fire()
call .anyClick.fire()
return false
endmethod
static method create takes rect r,integer p, real resolution, boolean timed returns thistype
local thistype this = thistype.allocate()
local string mod = ""
local cache c = cache.create()
if resolution <= RADIUS_NORMAL then
set mod = MODEL_SMALL
else
set mod = MODEL_NORMAL
endif
set .p = p
set .r = r
set c.res = resolution
set c.mod = mod
set c.x_MIN = GetRectMinX(.r)
set c.y_MIN = GetRectMinY(.r)
set c.x_MAX = GetRectMaxX(.r)
set c.y_MAX = GetRectMaxY(.r)
set c.timed = timed
set .onClick = Event.create()
set .onTrack = Event.create()
set .TrigTrack = CreateTrigger()
set .TrigClick = CreateTrigger()
call SetTriggerData.execute(.TrigTrack,this)
call SetTriggerData.execute(.TrigClick,this)
call TriggerAddCondition(.TrigTrack,thistype.TrackHandle)
call TriggerAddCondition(.TrigClick,thistype.ClickHandle)
if timed then
call DynamicTrackMapGenerator.create(this,c)
else
call .generatefield(c,0)
endif
return this
endmethod
method generatefield takes cache c, integer i returns boolean
local integer j = 0
local trackable track = null
local real x = 0.
local real y = 0.
local string mod = c.mod
if GetPlayerId(GetLocalPlayer()) != .p then
set mod = ""
endif
loop
set j = 0
set x = c.x_MIN + i * c.res
loop
set y = c.y_MIN + j * c.res
set track = CreateTrackable(mod,x,y,0.)
call SaveInteger(Hash,GetHandleId(track),SLOT_TRACKDATA,trackdata.create(x,y))
call TriggerRegisterTrackableTrackEvent(.TrigTrack, track)
call TriggerRegisterTrackableHitEvent(.TrigClick, track)
set j = j + 1
exitwhen y >= c.y_MAX
endloop
set i = i + 1
if x >= c.x_MAX then
// completely done.
call c.destroy()
return true
endif
// wait for next interval to proceed
exitwhen c.timed
if (i * j >= LOOP_BREAK_VALUE) then
// recall the function in another thread to avoid a loop break.
call .generatefield.execute(c,i)
return false
endif
endloop
return false
endmethod
method onDestroy takes nothing returns nothing
call TriggerClearActions(.TrigTrack)
call TriggerClearActions(.TrigClick)
call DisableTrigger(.TrigTrack)
call DisableTrigger(.TrigClick)
call DestroyTriggerDelayed.execute(.TrigTrack)
call DestroyTriggerDelayed.execute(.TrigClick)
set .TrigTrack = null
set .TrigClick = null
endmethod
private static method onInit takes nothing returns nothing
set .anyClick = Event.create()
set .anyTrack = Event.create()
set .ClickHandle = Condition( function thistype.ClickHandleEx)
set .TrackHandle = Condition( function thistype.TrackHandleEx)
endmethod
method stop takes nothing returns nothing
if not .active then
return
endif
set .active = false
if .TrigTrack != null then
call DisableTrigger(.TrigTrack)
endif
if .TrigClick != null then
call DisableTrigger(.TrigClick)
endif
endmethod
method resume takes nothing returns nothing
if .active then
return
endif
set .active = true
if .TrigTrack != null then
call EnableTrigger(.TrigTrack)
endif
if .TrigClick != null then
call EnableTrigger(.TrigClick)
endif
endmethod
endstruct
struct DynamicTrackMapGenerator
private integer i = -1
private TrackMap m
private cache c
static method create takes TrackMap m, cache c returns thistype
local thistype this = thistype.allocate()
local timer t = CreateTimer()
set .m = m
set .c = c
call SaveInteger(Hash, GetHandleId(t),SLOT_STRUCT,this)
call TimerStart(t,TIMER_INTERVAL,true, function thistype.callback)
return this
endmethod
static method callback takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = LoadInteger(Hash,GetHandleId(t),SLOT_STRUCT)
set .i = .i + 1
if .m.generatefield(.c,.i) then
call RemoveSavedInteger(Hash,GetHandleId(t),SLOT_STRUCT)
call DestroyTimer(t)
call .destroy()
endif
endmethod
endstruct
// Usuable Functions
function SetUpTrackMap takes rect area, player p, boolean veryprecise returns TrackMap
if veryprecise then
return TrackMap.create(area ,GetPlayerId(p),MOUSEPOSITION_HIGH_PRECISION,true)
else
return TrackMap.create(area ,GetPlayerId(p),MOUSEPOSITION_LESS_PRECISION,true)
endif
endfunction
function SetUpTrackMapEx takes rect area, player p, real precision, boolean timed returns TrackMap
return TrackMap.create(area,GetPlayerId(p),precision,timed)
endfunction
function TriggerRegisterAnyMouseEvent takes trigger t returns nothing
call TrackMap.registerAnyChange(t)
endfunction
function TriggerRegisterAnyClickEvent takes trigger t returns nothing
call TrackMap.registerAnyClick(t)
endfunction
function TriggerRegisterAnyTrackEvent takes trigger t returns nothing
call TrackMap.registerAnyTrack(t)
endfunction
function TriggerRegisterMouseEvent takes trigger t, TrackMap tm returns nothing
call tm.registerChange(t)
endfunction
function TriggerRegisterClickEvent takes trigger t, TrackMap tm returns nothing
call tm.registerClick(t)
endfunction
function TriggerRegisterTrackEvent takes trigger t, TrackMap tm returns nothing
call tm.registerTrack(t)
endfunction
function Clicked takes nothing returns boolean
return clicked
endfunction
function Tracked takes nothing returns boolean
return not clicked
endfunction
function GetMousePosX takes integer p returns real
return TMpx[p]
endfunction
function GetMousePosY takes integer p returns real
return TMpy[p]
endfunction
function GetTriggerMousePosX takes nothing returns real
return TMpx[TMlastplayer]
endfunction
function GetTriggerMousePosY takes nothing returns real
return TMpy[TMlastplayer]
endfunction
function GetTriggerTrackMap takes nothing returns TrackMap
return TMlasttm
endfunction
function GetMouseUsingPlayer takes nothing returns player
return Player(TMlastplayer)
endfunction
function GetMouseUsingPlayerId takes nothing returns integer
return TMlastplayer
endfunction
endlibrary
Changelog:
v1.1a:
Fixed 2 Problems
v1.1:
Added Event
Code Optimization
v1.0:
first Release
Fixed 2 Problems
v1.1:
Added Event
Code Optimization
v1.0:
first Release
Credits:
- Vexorian [JNGP]
- tamisrah [Advice]
- Azlier [Ideas]
- Jesus4Lyf [Event]
Hint:
The code in this post is more actual then the map.
Greetings.