- Joined
- Nov 4, 2007
- Messages
- 337
Embasic is a collection of recycling and attachment systems.
It also includes functions like H2I, so it's useful for all maps.
Embasic includes:
TimerUtils
HandleIndexing
GroupUtils
AID
ColorCode functions
H2I stuff
I think, this is very useful.
If this is gonna be a standard, it will be easier for
many mapmakers.
Users decide over the speed of the systems!
Blub.
[x] safe
[x] useful
[x] fast
[x] standard
SUFS
Em stands for 'M' spoken like em.
M stands for map.
So Embasic = Mapbasic.
Maybe someone could create
Emmath [Custom math like logarithm]
Emmetry [Geometry funcs]
Emdebug [Debug maps]
What do you think about this?
It also includes functions like H2I, so it's useful for all maps.
Embasic includes:
TimerUtils
HandleIndexing
GroupUtils
AID
ColorCode functions
H2I stuff
I think, this is very useful.
If this is gonna be a standard, it will be easier for
many mapmakers.
Users decide over the speed of the systems!
JASS:
library Embasic
//*********************************************************************
//* Embasic
//* ----------
//! [Attachment] [Recycling] [Coloring] [H2I] [GameTime]
//*
//*
//* To implement it , create a custom text trigger called Embasic
//* and paste the contents of this script there.
//* If you want to use it, don't forget to call InitEmbasic() at the map start.
//*
//* To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass) More scripts: htt://www.wc3campaigns.net
//*
//! TimerUtils [by Vesxorian]
//! HandleIndexing [by Mr.Malte]
//! AID [by Mr.Malt]
//! GroupUtils [by Rising_Dusk]
//! ColorFunctions [by Mr.Malte]
// ======= What is Embasic ? =======
// Embasic is a collection of useful stuff that should go into any map.
// Embasic inclues mainly HandleAttachment functions.
// There are many attachment systems, but these are the two which I
// recommend.
// ======= Functions of Embasic =======
// NewTimer() : Recycles an old timer, to keep the HandleID size small.
// ReleaseTimer(timer) : Timers created with NewTimer() must be deleten like this.
// SetTimerData(timer,integer) : Attach Data to a timer created with NewTimer()
// GetTimerData(timer) : Get the attached Data
// Index(handle) : Creates a unique integer between 1 and 8190 for a handle.
// ReleaseIndex(integer) : Release the index of a unit. Very important! Call this, when you don't need the Index anymore, like if a unit dies.
// GameTimeString() : Returns in a string the elapsed game time.
// NewGroup() : Simliar to NewTimer(), just with groups. Create a new group with this.
// ReleaseGroup(group) : Use this instead of DestroyGroup(g), but ONLY on groups created with NewGroup()
// GroupRefresh(group) : Removes for example dead units from a group. Destroys 'Shadow References'
// PrintAID() : Prints the number of handles that will probably be created in your game.
// GameTimeString() : Returns the gametime as a string ( when GameTimeWanted is true ). Example: 01:05:36 => 1 hour, 5 minutes, 36 seconds.
// GetElapsedGameTime(string) : Returns the elapsed game time in a device (hours, minutes, seconds)
// ColorPlayer(player) : Returns the name of a player coloured.
// H2I, h2i, i2e, i2u, i2t : Basic returnbug functions. You don't have to create tons of private h2i() functions then.
// ======= Constants of Embasic =======
// Pi : The thing you need to handle with circles. Maybe Useful.
// ColorBlue/Green/Red[PlayerId]: The Color of players in integers between 0 and 255
// ======= What else should I know? =======
// This supports AID. MAX_HANDLE_ID_COUNT is very important for attachment systems.
// If you create more handles than this value is big, attachment systems fail.
// AID stores the number of created handles and the biggest Handle ID.
// Then it calculates this value up to MAX_GAME_DURATION.
// Example: After 10 minutes, 5000 handles were created.
// MAX_GAME_DURATION is 40.
// So it calculates how many handles might be created after 40 minutes.
// This needs performance! To disabled AID, set AID to false
// ======= About the Systems =======
//! [HandleIndexing]
// Fast, save, doesn't need Unit User Data.
// This is not the fastest! But it doesn't use UnitUserData.
//! [TimerUtils]
// Fast, save, recycles timers
//! [AID]
// Slow system. Should be disabled for final games.
//! [GroupUtils]
// Recycles groups in order to keep the Handle ID size small.
// ======= For speed Freaks =======
// To increase the speed of embasic:
// [x] Replace TimerUtils(Red) with TimerUtils(DarkRed)
// [x] Replace HandleIndexing with UnitIndexing
// [x] Disable AID
// [x] Disable GameTimeWanted
//*
//********************************************************************
globals
private constant integer MAX_HANDLE_ID_COUNT = 50000 //: Very important. Tip: Play a whole game with AID enabled and if AID recommends a higher value, increase it.
private constant integer tosub = 0x100000 //: Subtracts this integer from handles. Keep it!
private constant integer QUANTITY = 256 //: The number of timers you can use at the same time created with NewTimer()
private constant integer ARRAY_SIZE = 8191 //: Increase this; Make safer, cripple performance
private constant integer HELD = 0x28829022 //: Use a totally random number. The best: Don't change it.
private boolean GameTimeWanted = true //: Starts a timer that counts the Game Time.
private constant integer MAX_GAME_DURATION = 5 //: What do you think, how long will your game last? In minutes, please
constant boolean AID = false //: Disable AID?
private constant boolean ColorsWanted = true //: Color Codes for players. false will disable 'ColorPlayer' and PlayerColorConstants
constant real Pi = 3.1415926535897
endglobals
function h2i takes handle h returns integer
return h
return 0
endfunction
function H2I takes handle h returns integer
return h
return 0
endfunction
function i2e takes integer i returns effect
return i
return null
endfunction
function i2u takes integer i returns unit
return i
return null
endfunction
function i2t takes integer i returns timer
return i
return null
endfunction
globals
integer BIGGEST = 0
integer SMALLEST = 0
//integer HandlesNeeded = 0
integer seconds = 0
integer hours = 0
integer minutes = 0
integer ElapsedMinutes = 0
integer GameTime = 0
endglobals
function startAID takes handle h returns nothing
local integer i = h2i(h)-tosub
if ( i > BIGGEST ) then
set BIGGEST = i
endif
endfunction
function Gametime takes nothing returns nothing
set seconds = seconds + 1
set GameTime = GameTime + 1
if ( seconds == 60 ) then
set seconds = 0
set minutes = minutes + 1
set ElapsedMinutes = ElapsedMinutes + 1
if ( minutes == 60 ) then
set hours = hours + 1
set minutes = 0
endif
endif
endfunction
function GetElapsedGameTime takes string device returns integer
if ( device == "minutes" ) then
return ElapsedMinutes
elseif ( device == "seconds" ) then
return ElapsedMinutes*60
elseif ( device == "hours" ) then
return R2I(I2R(ElapsedMinutes/60))
endif
return -1
endfunction
function GameTimeString takes nothing returns string
local string toreturn = ""
if ( hours < 10 ) then
set toreturn = toreturn + "0" + I2S(hours)
else
set toreturn = toreturn + I2S(hours)
endif
if ( minutes < 10 ) then
set toreturn = toreturn + ":"+"0"+I2S(minutes)
else
set toreturn = toreturn + ":"+I2S(minutes)
endif
if ( seconds < 10 ) then
set toreturn = toreturn + ":"+"0"+I2S(seconds)
else
set toreturn = toreturn + ":"+I2S(seconds)
endif
return toreturn
endfunction
function PrintAID takes nothing returns nothing
local real HandlesNeeded = GameTime/(BIGGEST-SMALLEST)*(MAX_GAME_DURATION*60)+SMALLEST+5000
call DisplayTextToForce(GetPlayersAll(),I2S(R2I(HandlesNeeded))+" is probably gonna be the biggest handle Index in your map. Now "+I2S(BIGGEST) +" was the biggest Index.")
endfunction
function HAID takes nothing returns nothing
local unit t = CreateUnit(Player(13),'hpea',0.,0.,0.)
call startAID(t)
call RemoveUnit(t)
endfunction
// ***************************************
//! S T A R T O F C O L O R F U N C T I O N S
// ***************************************
globals
integer array ColorRed
integer array ColorGreen
integer array ColorBlue
string array ColorString
endglobals
function ColorPlayer takes player p returns string
if ( ColorsWanted ) then
return ColorString[GetPlayerId(p)]+GetPlayerName(p)+"|r"
endif
return "Embasic: Enable ColorsWanted"
endfunction
function InitColor takes nothing returns nothing
local integer nIndex = 0
set ColorRed[nIndex] = 255
set ColorGreen[nIndex] = 0
set ColorBlue[nIndex] = 0
set ColorString[nIndex] = "|cffff0000" //red
set nIndex = nIndex + 1
set ColorRed[nIndex] = 0
set ColorGreen[nIndex] = 0
set ColorBlue[nIndex] = 255
set ColorString[nIndex] = "|cff0000ff" //blue
set nIndex = nIndex + 1
set ColorRed[nIndex] = 0
set ColorGreen[nIndex] = 245
set ColorBlue[nIndex] = 255
set ColorString[nIndex] = "|cff00f5ff" //Teal
set nIndex = nIndex + 1
set ColorRed[nIndex] = 85
set ColorGreen[nIndex] = 26
set ColorBlue[nIndex] = 139
set ColorString[nIndex] = "|cff551A8B" //Purple
set nIndex = nIndex + 1
set ColorRed[nIndex] = 255
set ColorGreen[nIndex] = 255
set ColorBlue[nIndex] = 0
set ColorString[nIndex] = "|cffffff00" //Yellow
set nIndex = nIndex + 1
set ColorRed[nIndex] = 248
set ColorGreen[nIndex] = 154
set ColorBlue[nIndex] = 0
set ColorString[nIndex] = "|cffEE9A00" //Orange
set nIndex = nIndex + 1
set ColorRed[nIndex] = 0
set ColorGreen[nIndex] = 255
set ColorBlue[nIndex] = 0
set ColorString[nIndex] = "|cff00CD00" //Green
set nIndex = nIndex + 1
set ColorRed[nIndex] = 255
set ColorGreen[nIndex] = 105
set ColorBlue[nIndex] = 180
set ColorString[nIndex] = "|cffFF69B4" //Pink
set nIndex = nIndex + 1
set ColorRed[nIndex] = 192
set ColorGreen[nIndex] = 192
set ColorBlue[nIndex] = 192
set ColorString[nIndex] = "|cffC0C0C0" //Gray
set nIndex = nIndex + 1
set ColorRed[nIndex] = 176
set ColorGreen[nIndex] = 226
set ColorBlue[nIndex] = 255
set ColorString[nIndex] = "|cffB0E2FF" //Light Blue
set nIndex = nIndex + 1
set ColorRed[nIndex] = 0
set ColorGreen[nIndex] = 100
set ColorBlue[nIndex] = 0
set ColorString[nIndex] = "|cff006400" //Dark Green
set nIndex = nIndex + 1
set ColorRed[nIndex] = 139
set ColorGreen[nIndex] = 69
set ColorBlue[nIndex] = 19
set ColorString[nIndex] = "|cff8B4513" //Brown
endfunction
// ***************************************
//! S T A R T O F G R O U P U T I L S
// ***************************************
globals
//* Group for use with all instant enumerations
group ENUM_GROUP = CreateGroup()
//* Temporary references for GroupRefresh
private boolean Flag = false
private group Refr = null
//* Assorted constants
private constant integer MAX_HANDLE_COUNT = MAX_HANDLE_ID_COUNT
private constant integer MIN_HANDLE_ID = tosub
//* Arrays and counter for the group stack
private group array Groups
private integer array Status[MAX_HANDLE_COUNT]
private integer Count = 0
endglobals
private function AddEx takes nothing returns nothing
if Flag then
call GroupClear(Refr)
set Flag = false
endif
call GroupAddUnit(Refr, GetEnumUnit())
endfunction
function GroupRefresh takes group g returns nothing
set Flag = true
set Refr = g
call ForGroup(Refr, function AddEx)
if Flag then
call GroupClear(g)
endif
endfunction
function NewGroup takes nothing returns group
if Count == 0 then
set Groups[0] = CreateGroup()
else
set Count = Count - 1
endif
set Status[H2I(Groups[Count])-MIN_HANDLE_ID] = 1
return Groups[Count]
endfunction
function ReleaseGroup takes group g returns boolean
local integer stat = Status[H2I(g)-MIN_HANDLE_ID]
if g == null then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Null groups cannot be released")
return false
elseif stat == 0 then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Group not part of stack")
return false
elseif stat == 2 then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Groups cannot be multiply released")
return false
elseif Count == 8191 then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Max groups achieved, destroying group")
call DestroyGroup(g)
return false
else
call GroupClear(g)
set Groups[Count] = g
set Count = Count + 1
set Status[H2I(g)-MIN_HANDLE_ID] = 2
endif
return true
endfunction
// ***************************************
//! S T A R T O F T I M E R U T I L S
// ***************************************
globals
private integer array data[ARRAY_SIZE]
private integer OFFSET
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
debug if(H2I(t)-OFFSET<0) then
debug call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
debug endif
set data[H2I(t)-OFFSET]=value
endfunction
function GetTimerData takes timer t returns integer
debug if(H2I(t)-OFFSET<0) then
debug call BJDebugMsg("GetTimerData: Wrong handle id, only use GetTimerData on timers created by NewTimer")
debug endif
return data[H2I(t)-OFFSET]
endfunction
//==========================================================================================
globals
private timer array tT
private integer tN = 0
endglobals
//==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, please increase it for your map, fix your map's timer leaks or switch to blue flavor when applicable")
set tT[0]=CreateTimer()
if (H2I(tT[0])-OFFSET<0) or (H2I(tT[0])-OFFSET>=ARRAY_SIZE) then
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably switch to the blue flavor or fix timer leaks.")
return null
endif
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
endfunction
//==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==8191) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
private function redInit takes nothing returns nothing
local integer i
local integer last
local boolean correct
loop
set tT[0] = CreateTimer()
set OFFSET=H2I(tT[0] )
set i=1
set correct=true
loop
exitwhen (i==QUANTITY)
set tT[i] = CreateTimer()
if(H2I(tT[i])-OFFSET<0) or (H2I(tT[i])-OFFSET>=ARRAY_SIZE) then
debug call BJDebugMsg("TimerUtils_redInit: Failed a initializing attempt")
set correct=false
exitwhen true
endif
set i=i+1
endloop
exitwhen correct
endloop
set tN=QUANTITY
endfunction
// ***************************************
//! S T A R T O F H A N D L E I N D E X I N G
// ***************************************
globals
private integer IDs = 0
private integer array StoredIDs[MAX_HANDLE_ID_COUNT]
private integer gaps = 0
private integer array Gaps
endglobals
function ReleaseIndex takes integer index returns nothing
//! Tell the recycler which gap can be recycled
set gaps = gaps + 1
set Gaps[gaps] = index
set StoredIDs[index] = 0
endfunction
function FixIssue takes nothing returns nothing
local integer i = 0
loop
set i = i + 1
exitwhen i > 8190
if ( i2e(i) == null and i2u(i) == null and i2t(i) == null ) then
call ReleaseIndex(i)
endif
endloop
endfunction
function CreateIndex takes integer num returns integer
//! Recycle Indexes
if ( gaps > 0 ) then
set StoredIDs[num] = Gaps[gaps]
set gaps = gaps - 1
return StoredIDs[num]
else
//! Create new Index
set IDs = IDs + 1
set StoredIDs[num] = IDs
if IDs > 8189 then
debug call BJDebugMsg("Handle Indexes; Created too many Indexes! Don't forget to call ReleaseIndex(handle). Trying to fix Issue. May cause Errors or bugs!"
call FixIssue()
endif
return IDs
endif
endfunction
function Index takes handle h returns integer
local integer hashnum = h2i(h)-tosub
debug if ( hashnum > MAX_HANDLE_ID_COUNT ) then
debug call BJDebugMsg("Handle Indexes; Index of handle too big. Increae 'MAX_HANDLE_ID_COUNT'!")
debug endif
if ( StoredIDs[hashnum] == 0 ) then
return CreateIndex(hashnum)
else
return StoredIDs[hashnum]
endif
endfunction
// ***************************************
//! S T A R T O F I N I T I A L I Z E R
// ***************************************
function InitEmbasic takes nothing returns nothing
local timer t
if ( AID ) then
set GameTimeWanted = true
set t = CreateTimer()
set SMALLEST = h2i(t)-tosub
call TimerStart(CreateTimer(),10.,true,function HAID)
call DestroyTimer(t)
endif
if ( GameTimeWanted ) then
call TimerStart(CreateTimer(),1.,true,function Gametime)
endif
call redInit()
if ( ColorsWanted ) then
call InitColor
endif
endfunction
endlibrary
library EmbasicChild initializer AutoAID requires Embasic
globals
private constant real TIMEOUT = 15.
private constant boolean PERIODIC = true
endglobals
function AutoAID takes nothing returns nothing
if ( AID ) then
call TimerStart(CreateTimer(),TIMEOUT,PERIODIC,function PrintAID)
endif
endfunction
endlibrary
Blub.
[x] safe
[x] useful
[x] fast
[x] standard
SUFS
Em stands for 'M' spoken like em.
M stands for map.
So Embasic = Mapbasic.
Maybe someone could create
Emmath [Custom math like logarithm]
Emmetry [Geometry funcs]
Emdebug [Debug maps]
What do you think about this?
Last edited: