- Joined
- Apr 29, 2007
- Messages
- 826
Additionally, the IsPlaying initializer should be placed inside a module so you can also use your IsPlaying stuff inside a struct initializer.
function IsFirstLetterOfRawcodeAnUpperCase takes integer rawcode returns boolean
return IsHeroUnitId(rawcode)
endfunction
UnitId2String(unitid) != null
but the library itself is only useful if the game was loaded.PurgeAndFire's cinematic scripts have been linked in the first thread. Still pondering Troll-Brain's script as I like the findUnitId2String(unitid) != null
but the library itself is only useful if the game was loaded.
library IsUnitTypeId requires Table
/* The point of this library is to bypass a nasty bug, but it's only present
with loaded game, if you don't care about them then you would just inline
UnitId2String(yourUnitTypeId) != null instead of using this library */
private keyword s_dummy
private function GameLoaded takes nothing returns boolean
set s_dummy.is_game_loaded = true
call DestroyBoolExpr(Condition(function GameLoaded))
call DestroyTrigger(GetTriggeringTrigger())
return false
endfunction
// coz of vJass madness initializer module priority, even if i hardly see the usefulness of registring a such event on a module initializer ...
// but in some case this kind of initializer can be "handy", here we avoid an unecessary init
private module onInit
static method onInit takes nothing returns nothing
local trigger trig = CreateTrigger()
call TriggerRegisterGameEvent(trig,EVENT_GAME_LOADED)
call TriggerAddCondition(trig,Condition(function GameLoaded))
set trig = null
set s_dummy.tab = Table.create()
endmethod
endmodule
private struct s_dummy extends array // the extends array avoid some unneeded stuff
static Table tab
static boolean is_game_loaded = false
implement onInit
endstruct
function IsGameLoaded takes nothing returns boolean
return s_dummy.is_game_loaded
endfunction
function IsUnitTypeId takes integer unitid returns boolean
local unit u
if IsGameLoaded() then
if s_dummy.tab.exists(unitid) then
return s_dummy.tab[unitid] != 0
endif
// IsUnitIdType is not enough , IsUnitHeroId only check if the first letter of the id is an uppercase and not if the id is a valid hero id
// so i've figured only this way, or you can use a third party tool instead, like GMSI, but imho it's overskilled here
set u = CreateUnit(Player(13),unitid,0.,0.,0.)
if u != null then
call RemoveUnit(u)
set u = null
set s_dummy.tab[unitid] = 1
return true
else
set s_dummy.tab[unitid] = 0
return false
endif
endif
return UnitId2String(unitid) != null // always returns null when the game was saved and loaded, and yes it's a bug
endfunction
endlibrary
It's missing an endif..
library StopOrder
globals
constant integer ORDER_STUN = 851973
/*
Special "stun" order, in case the unit had a previous no target order, like holdposition, it will keep it.
Plus you can filter it easily, since this order can be given only with a trigger action and have no string equivalent.
But be aware that this order also occurs when an unit is being paused or stunned.
In case of pause it will be a (not null) point order event, and for stun it will be a target event, where the target is the widget which has stunned the unit.
*/
endglobals
private function interface func takes unit u returns nothing
globals
private unit U = null
private func array F
endglobals
function StopOrder takes unit u, func f returns nothing
call DisableTrigger(GetTriggeringTrigger()) // just in case you have a point order event registered
call PauseUnit(u,true) // it will generate a point order event if the unit is not already stunned or paused (851973, no string equivalent)
call IssueImmediateOrderById(u,ORDER_STUN)
call PauseUnit(u,false)
call EnableTrigger(GetTriggeringTrigger())
set F[GetUnitId(u)] = f
set u = null
endfunction
private function Act takes nothing returns boolean
local unit u
local integer i
if GetIssuedOrderId() == ORDER_STUN then
set u = GetOrderedUnit()
set i = GetUnitId(u)
call F[i].evaluate(u)
set F[i] = 0
set u = null
endif
return false
endfunction
private function init takes nothing returns nothing
local trigger trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_ISSUED_ORDER)
call TriggerAddCondition(trig,function Act)
endfunction
endlibrary
library Example initializer init requires StopOrder
private function DisplayUnitName takes unit u returns nothing
call BJDebugMsg(GetUnitName(u) +" has been stopped")
endfunction
private function Act takes nothing returns boolean
// All no target orders will be stopped.
if GetIssuedOrderId() != ORDER_STUN then
call StopOrder(GetTriggerUnit(),DisplayUnitName)
endif
return false
endfunction
private function init takes nothing returns nothing
local trigger trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_ISSUED_ORDER)
call TriggerAddCondition(trig,function Act)
endfunction
endlibrary
library RectData requires optional Typecasting
// Credits to MasterofSickness for this technique.
// This assigns all the rects to a unique index of a specified array.
// Just use it upon initialization. Example:
/* //! runtextmacro SetRectData( gg_rct_Region_000 , udg_RectArray )
*/ // "FIRST_RECT" is the first rect listed in the "Region Palette". The sorting doesn't matter.
// "ARRAY" is the array you want to assign data to. It doesn't have to start with udg_ or anything.
globals
private hashtable hash = InitHashtable()
public integer COUNT = 0
endglobals
static if (not LIBRARY_Typecasting) then
function Int2Rect takes integer id returns rect
call SaveFogStateHandle(hash,0,0,ConvertFogState(id))
return LoadRectHandle(hash,0,0)
endfunction
endif
//! textmacro SetRectData takes FIRST_RECT, ARRAY
local integer i = GetHandleId($FIRST_RECT$)
loop
set $ARRAY$[RectData_COUNT] = Int2Rect(i)
exitwhen $ARRAY$[RectData_COUNT]==null
set RectData_COUNT = RectData_COUNT + 1
set i = i + 1
endloop
//! endtextmacro
endlibrary
scope Example initializer Init
globals
rect array RECTS
endglobals
private function Init takes nothing returns nothing
//! runtextmacro SetRectData( "gg_rct_Region_000" , "RECTS" )
endfunction
endscope
library RectData requires optional Typecasting
// Credits to MasterofSickness for this technique.
// This assigns all the rects in the "Region Palette" to a unique index of a specified array.
// Just use it upon initialization. Example:
/* //! runtextmacro SetRectData( gg_rct_Lulu_lala , udg_RectArray )
*/ // "ANY_RECT" is any rect defined in the "Region Palette".
// "ARRAY" is the array you want to assign data to. It doesn't have to start with udg_ or anything.
globals
private hashtable hash = InitHashtable()
public integer COUNT = 0
endglobals
static if (not LIBRARY_Typecasting) then
function Int2Rect takes integer id returns rect
call SaveFogStateHandle(hash,0,0,ConvertFogState(id))
return LoadRectHandle(hash,0,0)
endfunction
endif
//! textmacro SetRectData takes ANY_RECT, ARRAY
local integer i = GetHandleId($ANY_RECT$)
loop
set $ARRAY$[RectData_COUNT] = Int2Rect(i)
exitwhen $ARRAY$[RectData_COUNT]==null
set RectData_COUNT = RectData_COUNT + 1
set i = i - 1
endloop
set i = GetHandleId($ANY_RECT$)+1
loop
set $ARRAY$[RectData_COUNT] = Int2Rect(i)
exitwhen $ARRAY$[RectData_COUNT]==null
set RectData_COUNT = RectData_COUNT + 1
set i = i + 1
endloop
//! endtextmacro
endlibrary
library CheckHandles
globals
private hashtable HashT = InitHashtable()
endglobals
function IsAgentValid takes agent whichAgent returns boolean
return SaveAgentHandle(HashT,0,0,whichAgent)
endfunction
//! textmacro t_CheckHandles takes TYPE_NAME , TYPE
function Is$TYPE_NAME$Valid takes $TYPE$ which$TYPE_NAME$ returns boolean
return Save$TYPE_NAME$Handle(HashT,0,0,which$TYPE_NAME$)
endfunction
//! endtextmacro
// example of textmacro usage
//! runtextmacro t_CheckHandles("Group","group")
endlibrary
if not IsAgentValid(bj_lastCreatedGroup) then
set bj_lastCreatedGroup = CreateGroup()
endif
library UnitList requires AutoIndex
globals
group GROUP = CreateGroup()
endglobals
struct UnitList
readonly integer Count
readonly thistype First
readonly thistype Last
readonly thistype Prev
readonly thistype Next
readonly unit me
method clear takes nothing returns nothing
local thistype s = this.First
local integer i
loop
exitwhen s == 0
// evil trick in order to avoid a loop, see comments at the end of the struct if you want understand (or at least try xD, i'm quite confusing)
set i = GetUnitId(s.me)
set s.Next.Prev = s.Prev
set s.Prev.Next = s.Next
set thistype(i).instancesNumber = thistype(i).instancesNumber-1
call SaveInteger(thistype.hashT,-i, LoadInteger(thistype.hashT,-i,-s) , LoadInteger(thistype.hashT,-i,thistype(i).instancesNumber) )
call RemoveSavedInteger(thistype.hashT,-i,thistype(i).instancesNumber)
call RemoveSavedInteger(thistype.hashT,-i,-s)
call RemoveSavedInteger(thistype.hashT,this,s)
set s.me = null
call s.deallocate()
set s = s.Next
endloop
set this.Count = 0
set this.First = 0
set this.Last = 0
call FlushChildHashtable(thistype.hashT,this)
endmethod
method destroy takes nothing returns nothing
call this.clear()
call this.deallocate()
endmethod
method addUnit takes unit u returns boolean
local integer index = GetUnitId(u)
if index == 0 or LoadInteger(thistype.hashT,this,index) != 0 then // the unit is not valid or already inside the UnitList
return false
endif
if this.Count == 0 then // the UnitList was empty
set this.First = thistype.allocate()
set this.Last = this.First
set this.First.Prev = 0
else // the UnitList contains one unit or more
set this.Last.Next = thistype.allocate()
set this.Last.Next.Prev = this.Last
set this.Last = this.Last.Next
endif
set this.Last.Next = 0 // for recycled instances
set this.Last.me = u // link the unit to the new member
set this.Last.whichList = this // used internally
call SaveInteger(thistype.hashT,this,index,integer(this.Last)) // link the UnitList and the unit
set this.Count = this.Count+1
// For each unit we need to store all their instances, in order to remove them when the unit is removed
// I use "-" in order to use only one hashtable without conflicts and still keep it efficient
call SaveInteger(thistype.hashT,-index,thistype(index).instancesNumber,this.Last)
call SaveInteger(thistype.hashT,-index,-this.Last,thistype(index).instancesNumber) // avoid a loop when the instance is destroyed
set thistype(index).instancesNumber = thistype(index).instancesNumber +1
return true
endmethod
method removeUnit takes unit u returns boolean
local integer i = GetUnitId(u)
local thistype x = thistype(LoadInteger(thistype.hashT,this,i))
if x == 0 then // the unit wasn't inside the group
return false
endif
set this.Count = this.Count-1
if x == this.First then
set this.First = this.First.Next
endif
if x == this.Last then
set this.Last = this.Last.Prev
endif
set x.Next.Prev = x.Prev
set x.Prev.Next = x.Next
set thistype(i).instancesNumber = thistype(i).instancesNumber-1
call RemoveSavedInteger(thistype.hashT,this,i)
call SaveInteger(thistype.hashT,-i, LoadInteger(thistype.hashT,-i,-x) , LoadInteger(thistype.hashT,-i,thistype(i).instancesNumber) )
call RemoveSavedInteger(thistype.hashT,-i,thistype(i).instancesNumber)
call RemoveSavedInteger(thistype.hashT,-i,-x)
set x.me = null
call x.deallocate()
return true
endmethod
method isUnitInList takes unit u returns boolean
return LoadInteger(thistype.hashT,this,GetUnitId(u)) != 0
endmethod
method addUnitList takes UnitList whichUnitList returns nothing
set whichUnitList = whichUnitList.First
loop
exitwhen whichUnitList == 0
call .addUnit(whichUnitList.me)
set whichUnitList = whichUnitList.Next
endloop
endmethod
static method wrap takes group g returns UnitList
if not SaveGroupHandle(thistype.hashT,0,0,g) then // group invalid
return 0
endif
set thistype.wrapList = thistype.allocate()
call ForGroup(g,function thistype.WrapList)
return thistype.wrapList
endmethod
private static method WrapList takes nothing returns nothing
call thistype.wrapList.addUnit(GetEnumUnit())
endmethod
private static method OnRemove takes unit u returns nothing
local integer index = GetUnitId(u)
local integer i = thistype(index).instancesNumber
local thistype x
loop
exitwhen i == 0
set i = i-1
set x = thistype(LoadInteger(thistype.hashT,-index,i))
set x.me = null
if x == x.whichList.First then
set x.whichList.First = x.whichList.First.Next
endif
if x == x.whichList.Last then
set x.whichList.Last = x.whichList.Last.Prev
endif
set x.Next.Prev = x.Prev
set x.Prev.Next = x.Next
set x.whichList.Count = x.whichList.Count-1
call RemoveSavedInteger(thistype.hashT,x.whichList,index)
call x.deallocate()
endloop
call FlushChildHashtable(thistype.hashT,index)
set thistype(-index).instancesNumber = 0
endmethod
private thistype whichList = 0
private static hashtable hashT
private static thistype wrapList = 0
private integer instancesNumber
private static method onInit takes nothing returns nothing
set thistype.hashT = InitHashtable()
call OnUnitDeindexed(OnRemove)
endmethod
endstruct
// for hashtable (used internally)
// UnitList,GetUnitId(<unit>) -> which instance of UnitList
// -GetUnitId(<unit>),GetUnitId(<unit>).instancesNumber -> which instance of UnitList
// -GetUnitId(<unit>),-which instance of UnitList -> GetUnitId(<unit>).instancesNumber
endlibrary
library ColorString
globals
// define the hexadecimal colors you want
constant string LOWER_CASE = "FF0000FF"
constant string CAPITAL_LETTER = "FF00FF00"
constant string NUMBER = "FFFF0000"
constant string OTHER = "FFFFFF00"
endglobals
function ColorString takes string source returns string
local integer i= StringLength(source)
local string dest= null
local string min
local string maj
local string s
loop
exitwhen i== 0
set i=i-1
set s= SubString(source,i,i+1)
set min= StringCase(s,false)
set maj= StringCase(s,true)
if s== min and s!= maj then
set dest = "|c"+LOWER_CASE+s+"|r" + dest
elseif s== maj and s!= min then
set dest = "|c"+CAPITAL_LETTER+s+"|r" + dest
elseif s== "0" or S2I(s) != 0 then
set dest = "|c"+NUMBER+s+"|r" + dest
else
set dest = "|c"+OTHER+s+"|r" + dest
endif
endloop
return dest
endfunction
endlibrary
You should be passing the strings into the function rather than having them as globals.
set b = eb[de[this]]
set i.base = b
set h = SPACE_COUNT
loop
set i = i.previous
exitwhen i.end
set c = b.char(i.digit)
if (h == 0) then
set h = SPACE_COUNT
set s = s + SPACE + ct[Char2Ascii(c)] + c
else
set s = s + ct[Char2Ascii(c)] + c
endif
set h = h - 1
endloop
if s == min and s == max then //special or number
if (s == "0" or S2I(s) != 0) then //number
else //special
endif
elseif s == min then //lower
else //upper
endif
//colorize
set b = eb[de[this]]
set i.base = b
set h = SPACE_COUNT
loop
set i = i.previous
exitwhen i.end
set c = b.char(i.digit)
if (h == 0) then
set h = SPACE_COUNT
set s = s + SPACE
endif
set l = StringCase(c, false) == c
if (c == StringCase(c, true) and l) then
if (c == "0" or S2I(c) != 0) then
//number
set s = s + NUM_COLOR + c
else
//special
set s = s + SPEC_COLOR + c
endif
elseif (l) then
//lower
set s = s + LOWER_COLOR + c
else
//upper
set s = s + UPPER_COLOR + c
endif
set h = h - 1
endloop
instance.destroy()
.library EffectLoop requires TimerUtils
/* call EffectLoop.create( string modelName, widget target, string attachmentPoint, real interval, real duration ) */
// modelName = The model of the effect to create.
// target = The widget to attach the effect to.
// attachmentPoint = The attachment point of the widget to attach the effect to.
// interval = How long it will take before the next effect is created for the loop.
// duration = The total time length that the effect looping will last.
struct EffectLoop extends array
private static integer iC = 0
private static thistype recycle = 0
private thistype recycleNext
private string mn
private widget tw
private string apn
private real dur
private real int
private timer tt
private effect fx
method destroy takes nothing returns nothing //incase the user wants to destroy it early
call DestroyEffect(this.fx)
call ReleaseTimer(this.tt)
set this.recycleNext = thistype.recycle
set thistype.recycle = this
endmethod
private static method effectLoop takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
set this.dur = this.dur - this.int
if this.dur < 0 then
call this.destroy()
else
call DestroyEffect(this.fx)
set this.fx = AddSpecialEffectTarget(this.mn,this.tw,this.apn)
endif
endmethod
static method create takes string modelName, widget targetWidget, string attachPointName, real interval, real duration returns thistype
local thistype this
if thistype.recycle==0 then
set thistype.iC = thistype.iC + 1
set this = thistype.iC
else
set this = thistype.recycle
set thistype.recycle = thistype.recycle.recycleNext
endif
set this.mn = modelName
set this.tw = targetWidget
set this.apn = attachPointName
set this.dur = duration
set this.int = interval
set this.fx = AddSpecialEffectTarget(modelName,targetWidget,attachPointName)
set this.tt = NewTimer()
call SetTimerData(this.tt,this)
call TimerStart(this.tt,interval,true,function thistype.effectLoop)
return this
endmethod
endstruct
endlibrary
library AddCommas
function AddCommas takes integer n returns string
local integer m = 0
local string s = ""
local boolean b = false
if (n == 0) then
return "0"
elseif (n < 0) then
set n = -n
set b = true
endif
loop
set m = n
set n = n/1000
set m = m-n*1000
if (n > 0) then
if (m < 10) then
set s = ",00" + I2S(m) + s
elseif (m < 100) then
set s = ",0" + I2S(m) + s
else
set s = "," + I2S(m) + s
endif
elseif (b) then
return "-" + I2S(m) + s
else
return I2S(m) + s
endif
endloop
return ""
endfunction
endlibrary
struct tester extends array
private static method onInit takes nothing returns nothing
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, AddCommas(-30000000))
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, AddCommas(-3000000))
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, AddCommas(-300000))
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, AddCommas(-30000))
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, AddCommas(-3000))
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, AddCommas(-300))
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, AddCommas(-30))
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, AddCommas(-3))
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, AddCommas(0))
endmethod
endstruct
library IsIssuedOrderInterrupting
globals
private constant boolean SAFE_CHECK = true
endglobals
function IsIssuedOrderInterrupting takes nothing returns boolean
static if SAFE_CHECK then
local eventid evd = GetTriggerEventId()
if evd==EVENT_UNIT_ISSUED_ORDER or evd==EVENT_UNIT_ISSUED_POINT_ORDER /*
*/ or evd==EVENT_UNIT_ISSUED_TARGET_ORDER or evd==EVENT_PLAYER_UNIT_ISSUED_ORDER /*
*/ or evd==EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER or evd==EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER then
return GetIssuedOrderId() == GetUnitCurrentOrder(GetOrderedUnit())
else
debug call BJDebugMsg("IsIssuedOrderInterrupting : use this function with an order event only")
return false
endif
else
return GetIssuedOrderId() == GetUnitCurrentOrder(GetOrderedUnit())
endif
endfunction
What does the 0-second timer actually do?
library Tester
function Print takes string msg returns nothing
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 240, msg)
endfunction
module Test
private static method runs takes nothing returns nothing
call DestroyTimer(GetExpiredTimer())
call thistype.run()
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(), 0, false, function thistype.runs)
endmethod
endmodule
endlibrary
struct tester extends array
private static method run takes nothing returns nothing
call Print("Hello World")
endmethod
implement Test
endstruct
library StringSize /* v2.0.0.0
********************************************************************
*
* This library can calculate the width of a string in pixels.
* Useful for word wrapping in multiboards and texttags.
*
* The sizes might not be 100% accurate but are far more reliable
* than using just StringLength().
*
* Note that actual sizes may very depending on resolution.
*
*********************************************************************
*
* */uses/*
*
* */ Ascii /* [url]http://www.hiveworkshop.com/forums/jass-functions-413/snippet-ascii-190746/[/url]
*
*********************************************************************
*
* function MeasureString takes string source returns real
*
* - Measures the string and returns the calculated width.
*
* function MeasureCharacter takes string char returns real
*
* - Returns the width of an individual character.
*
*********************************************************************
*
* struct StringSize
*
* static method measure takes string source returns real
*
* static method measureChar takes string char returns real
*
*********************************************************************
*
* Credits
*
* - Bob666 aka N-a-z-g-u-l for the character widths.
* - Tukki for pointing out an error in the system.
*
*********************************************************************/
globals
private real array size
private string src
endglobals
private module StringSizeModule
static method onInit takes nothing returns nothing
set size[124] = 3
set size[39] = 4
set size[58] = 4
set size[59] = 4
set size[46] = 4
set size[44] = 4
set size[49] = 5
set size[105] = 5
set size[33] = 5
set size[108] = 6
set size[73] = 6
set size[106] = 6
set size[40] = 6
set size[91] = 6
set size[93] = 6
set size[123] = 6
set size[125] = 6
set size[32] = 7
set size[34] = 7
set size[41] = 7
set size[74] = 7
set size[114] = 8
set size[102] = 8
set size[96] = 8
set size[116] = 9
set size[45] = 9
set size[92] = 9
set size[42] = 9
set size[70] = 10
set size[115] = 11
set size[47] = 11
set size[63] = 11
set size[69] = 12
set size[76] = 12
set size[55] = 12
set size[43] = 12
set size[61] = 12
set size[60] = 12
set size[62] = 12
set size[36] = 12
set size[97] = 12
set size[107] = 13
set size[84] = 13
set size[99] = 13
set size[83] = 13
set size[110] = 13
set size[122] = 13
set size[80] = 13
set size[51] = 13
set size[53] = 13
set size[95] = 13
set size[126] = 13
set size[94] = 13
set size[98] = 14
set size[66] = 14
set size[54] = 14
set size[118] = 14
set size[101] = 14
set size[120] = 14
set size[121] = 14
set size[50] = 14
set size[57] = 14
set size[104] = 14
set size[117] = 14
set size[111] = 15
set size[100] = 15
set size[48] = 15
set size[103] = 15
set size[56] = 15
set size[52] = 15
set size[113] = 15
set size[112] = 15
set size[115] = 15
set size[67] = 16
set size[82] = 16
set size[90] = 16
set size[86] = 16
set size[89] = 16
set size[68] = 16
set size[75] = 16
set size[85] = 16
set size[35] = 16
set size[78] = 17
set size[72] = 17
set size[37] = 17
set size[71] = 18
set size[88] = 18
set size[64] = 18
set size[65] = 19
set size[119] = 20
set size[79] = 20
set size[109] = 21
set size[81] = 21
set size[38] = 21
set size[77] = 25
set size[87] = 26
endmethod
endmodule
private function IsColorCode takes string s returns boolean
/* checks if the string has hexadecimal color coding */
local integer l = StringLength(s)
local integer a
if l == 8 then
loop
exitwhen l == 0
set a = Char2Ascii(SubString(s, l-1, l))
if (a > 64 and a < 71) or (a > 96 and a < 103) or (a > 47 and a < 58) then
set l = l - 1
else
return false
endif
endloop
return true
endif
return false
endfunction
private function RemoveTextFormatting takes nothing returns nothing
/* removes the formatting on a text */
local integer l = StringLength(src)
local integer i = 0
local string sub
loop
exitwhen i >= l
set sub = SubString(src, i, i+1)
if sub == "|" then
set sub = SubString(src, i+1, i+2)
if sub == "c" then
if IsColorCode(SubString(src, i+2, i+10)) then
set src = SubString(src, 0, i) + SubString(src, i+10, l)
set l = l - 10
set i = i - 1
endif
elseif sub == "r" then
set src = SubString(src, 0, i) + SubString(src, i+2, l)
set l = l - 2
set i = i - 1
endif
endif
set i = i + 1
endloop
endfunction
private function ConvertToPlainText takes string source returns string
set src = source
call ForForce(bj_FORCE_PLAYER[0], function RemoveTextFormatting)
return src
endfunction
struct StringSize extends array
static method measureChar takes string char returns real
return size[Char2Ascii(char)]
endmethod
static method measure takes string s returns real
local integer i = StringLength(s)
local real result = 0
if i == 0 then
return 0
elseif i == 1 then
return size[Char2Ascii(s)]
endif
set s = ConvertToPlainText(s)
set i = StringLength(s)
loop
exitwhen i == 0
set result = result + size[Char2Ascii(SubString(s, i-1, i))]
set i = i - 1
endloop
return result
endmethod
implement StringSizeModule
endstruct
function MeasureString takes string s returns real
return StringSize.measure(s)
endfunction
function MeasureCharacter takes string s returns real
return StringSize.measureChar(s)
endfunction
endlibrary
library LineBreak requires StringSize
//~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
//
// Line Break v. 1 . 0 . 1 . 0
// ���������� ����������������
//
// What is it?
// �����������
// - This library can separate strings into several lines, based on each line's width.
// - It is not line wrapping, but rather word wrapping. [url]http://en.wikipedia.org/wiki/Word_wrapping[/url]
// - Supports color codes.
// - Useful for multiboards, centering strings, and anything alike.
//
// Requirements:
// �������������
// - Ascii [url]http://www.hiveworkshop.com/forums/jass-functions-413/snippet-ascii-190746/[/url]
// - StringSize [url]http://www.hiveworkshop.com/forums/1886277-post379.html[/url]
//
// Usage:
// ������
/* LineBreak.create( string source , real size, boolean preserveColors) */
//
// Divides the "source" string into several lines. Each line has a maximum width of the "size" provided.
// "Preserve Colors" will activate a feature to make sure that colors transfer to the next line as well
// if they are supposed to.
//
/* string array LineBreak.Line[] */
/* integer LineBreak.Count */
//
// LineBreak.Count returns how many lines were created.
// LineBreak.Line[n] returns the nth line of the line breaks.
//
// Credits:
// ��������
// - cleeezzz & tooltiperror for the idea.
//
// Bugs:
// �����
// - If there is a single word that is longer than the "size" input, this system will fail. I might add support
// for that later, but it may add a few more function calls and checks to the code.
//
//~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
private module LBInit
static method onInit takes nothing returns nothing
call TriggerAddAction(preserveExec,function thistype.preserveColor)
endmethod
endmodule
struct LineBreak extends array
static trigger preserveExec = CreateTrigger()
static string array Line
static integer Count = 0
private static method refresh takes nothing returns nothing
loop
exitwhen thistype.Count == 0
set thistype.Count = thistype.Count - 1
set thistype.Line[thistype.Count] = ""
endloop
endmethod
private static method preserveColor takes nothing returns nothing
local integer i = 0
local integer i2 = 0
local integer l = 0
local string temp = ""
local string hex = ""
local boolean carryOn = false
loop
exitwhen i == thistype.Count
set carryOn = false
set hex = ""
set i2 = 0
set l = StringLength(thistype.Line[i])
loop
exitwhen i2 == l
set temp = SubString(thistype.Line[i],i2,i2+1)
if temp == "|" then
set temp = SubString(thistype.Line[i],i2+1,i2+2)
if temp == "c" then
if IsStringHexCC(SubString(thistype.Line[i],i2+2,i2+10)) then
set hex = SubString(thistype.Line[i],i2,i2+10)
set carryOn = true
endif
elseif temp == "r" then
set carryOn = false
endif
endif
set i2 = i2 + 1
endloop
set i = i + 1
if carryOn then
set thistype.Line[i] = hex+thistype.Line[i]
endif
endloop
endmethod
static method create takes string source, real size, boolean preserveColors returns thistype
local integer l = StringLength(source)
local integer i = 0
local integer i2 = 0
local string s = ""
local string word
local real result = 0
local real ssize = 0
call thistype.refresh()
loop
exitwhen i == l
set s = SubString(source,i,i+1)
if s == " " or i == (l-1) then
set word = SubString(source,i2,i)+s
set ssize = StringSize.measure(word)
set result = result + ssize
if result <= size then
set thistype.Line[thistype.Count] = thistype.Line[thistype.Count]+word
else
set thistype.Count = thistype.Count + 1
set thistype.Line[thistype.Count] = word
set result = ssize
endif
set i2 = i + 1
endif
set i = i + 1
endloop
set thistype.Count = thistype.Count + 1
if preserveColors then
call TriggerExecute(preserveExec)
endif
return 0
endmethod
implement LBInit
endstruct
endlibrary
scope Testing initializer Init
private function esc takes nothing returns nothing
local string text = "Hello, my name is Joe. I work in a button factory. One day, my boss said to me, \"Hiya Joe! Are you busy?\" "+/*
*/" I said, \"No\"." //our original text
local integer i = 0
call LineBreak.create(text,450,true) //We will break it into lines, 450 maximum pixels per line
loop
exitwhen i == LineBreak.Count //This is how many lines there are
call BJDebugMsg(LineBreak.Line[i]) //This is how you read a line
set i = i + 1
endloop
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterPlayerEvent(t,Player(0),EVENT_PLAYER_END_CINEMATIC)
call TriggerAddAction(t,function esc)
endfunction
endscope
"|r|cff00aabbsomeshit|r"
set i = i - 1
PurgeandFire111, try using this in your StringSize library:"|r|cff00aabbsomeshit|r"
It should result in an incorrect measuring, since you're skipping the next char when you detect those |'s.
It's easy to fix, just addset i = i - 1
library IsGameOnline initializer init
// IT SEEMS TO WORK, AT LEAST FOR THE PATCH 1.26
// lan games are considered to be "on line"
// ofc you can't use the function IsGameOnline on map initialisation, at least after a time (0.), (0.01) would be better
globals
private trigger Trig = CreateTrigger()
private boolean IS_GAME_ONLINE = false
//TRUE = Game is online, no cheats possible.
//FALSE = Game is offline, cheats possible.
//If your map have some sort of secrets, you can cover them in offline games
endglobals
function IsGameOnline takes nothing returns boolean
return IS_GAME_ONLINE
endfunction
private function Clean takes nothing returns nothing
set IS_GAME_ONLINE = GetTriggerEvalCount(Trig) == 0
call DestroyTrigger(Trig)
set Trig = null
call DestroyTimer(GetExpiredTimer())
endfunction
private function init takes nothing returns nothing
local unit u = CreateUnit(Player(13),'hpea',0.,0.,0.)
call TriggerRegisterUnitEvent(Trig,u,EVENT_UNIT_SELECTED)
call SelectUnit(u,true)
call RemoveUnit(u) // if the game is online (network local or battle.net) the unit won't have the time to be selected, it takes about 0.1 s
call TimerStart(CreateTimer(),0.,false,function Clean)
set u = null
endfunction
endlibrary
I think ReloadGamecache or w/e is the best method hands down, and it doesn't need any timer or anything.
Replays are only useful for watching pro games from Moon or Axslav. Sometimes Grubby.
Aren't there good utilities people have built to detect if a game is a replay?
I should run some tests, but something so substantial as a replay has to be in some way detectable.
Wouldn't GetPlayerName(GetLocalPlayer()) return the replay-viewer's name and not the name of the actual players? If so, you could just make a unique name that you ONLY use for viewing replays and, if GetPlayerName(GetLocalPlayer()) returns that string, you know you're watching a replay.
But if you try to select an unit with GetLocalPlayer() == Player(1), the select event will fire in replay, even if the first player slot was Player(0).
Nes:
I think ReloadGamecache or w/e is the best method hands down, and it doesn't need any timer or anything.
Troll:
Only if you don't care about replays (always returns "on line").
Else i'm totally agree that is the most elegant solution.
That's under the condition that Player(0) was not a human player?
library IsGameOnline initializer init
globals
private trigger t
private boolean replay = not ReloadGameCachesFromDisk()
private boolean online = false
//If your map have some sort of secrets, you can cover them in offline games
endglobals
function IsGameOnline takes nothing returns boolean
return online
endfunction
function IsGameReplay takes nothing returns boolean
return replay
endfunction
private function Clean takes nothing returns nothing
if GetTriggerEvalCount(t) == 0 then
set online = true
set replay = false
endif
call DestroyTimer(GetExpiredTimer())
call DestroyTrigger(t)
set t = null
endfunction
private function Init takes nothing returns nothing
local unit u
if replay then
set u = CreateUnit(Player(13),'hpea',0.,0.,0.)
set t = CreateTrigger()
call TriggerRegisterUnitEvent(t, u, EVENT_UNIT_SELECTED)
call SelectUnit(u, true)
call RemoveUnit(u) // if the game is online (network local or battle.net) the unit won't have the time to be selected, it takes about 0.1 s
call TimerStart(CreateTimer(), 0, false, function Clean)
set u = null
endif
endfunction
endlibrary
Nah, that was i said ReloadGameCachesFromDisk() will return false with a real-not-replay multiplayer game also, so it's a no-no.
You're saying the selection-event won't work for a replay? It will still have the 0.1 second delay?