--[[ Utility Functions ]] --------------------------------------------------------------------------- -- Bitwise and -------------------------------------------------------------------------- function bitand(a, b) local result = 0 local bitval = 1 while a > 0 and b > 0 do if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits result = result + bitval -- set the current bit end bitval = bitval * 2 -- shift left a = math.floor(a/2) -- shift right b = math.floor(b/2) end return result end --------------------------------------------------------------------------- function Lerp(t, a, b) return a + t * (b - a) end --------------------------------------------------------------------------- function LerpClamp(t, a, b) if t < 0 then t = 0 elseif t > 1 then t = 1 end return Lerp( t, a, b ) end --------------------------------------------------------------------------- -- Broadcast messages to screen --------------------------------------------------------------------------- function printf(...) print(string.format(...)) end --------------------------------------------------------------------------- -- Broadcast messages to screen --------------------------------------------------------------------------- function BroadcastMessage( sMessage, fDuration ) local centerMessage = { message = sMessage, duration = fDuration } FireGameEvent( "show_center_message", centerMessage ) end --------------------------------------------------------------------------- -- GetRandomElement --------------------------------------------------------------------------- function GetRandomElement( table ) local nRandomIndex = RandomInt( 1, #table ) local randomElement = table[ nRandomIndex ] return randomElement end --------------------------------------------------------------------------- -- ShuffledList --------------------------------------------------------------------------- function ShuffledList( orig_list ) local list = shallowcopy( orig_list ) local result = {} local count = #list for i = 1, count do local pick = RandomInt( 1, #list ) result[ #result + 1 ] = list[ pick ] table.remove( list, pick ) end return result end --------------------------------------------------------------------------- -- ShuffleListInPlace --------------------------------------------------------------------------- function ShuffleListInPlace( list, hRandomStream ) local count = #list for i = 1, count do local j = 0 if hRandomStream == nil then j = RandomInt( 1, #list ) else j = hRandomStream:RandomInt( 1, #list ) end list[i] , list[j] = list[j] , list[i] end end --------------------------------------------------------------------------- -- string.starts --------------------------------------------------------------------------- function string.starts( string, start ) return string.sub( string, 1, string.len( start ) ) == start end function string.ends( String, End ) return End=='' or string.sub(String,-string.len(End))==End end --------------------------------------------------------------------------- -- string.split --------------------------------------------------------------------------- function string.split( str, sep ) local sep, fields = sep or ":", {} local pattern = string.format("([^%s]+)", sep) str:gsub(pattern, function(c) fields[#fields+1] = c end) return fields end --------------------------------------------------------------------------- -- shallowcopy --------------------------------------------------------------------------- function shallowcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in pairs(orig) do copy[orig_key] = orig_value end else -- number, string, boolean, etc copy = orig end return copy end --------------------------------------------------------------------------- -- deepcopy --------------------------------------------------------------------------- function deepcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, orig, nil do copy[deepcopy(orig_key)] = deepcopy(orig_value) end setmetatable(copy, deepcopy(getmetatable(orig))) else -- number, string, boolean, etc copy = orig end return copy end --------------------------------------------------------------------------- -- Table functions --------------------------------------------------------------------------- function PrintTable( t, indent ) --print( "PrintTable( t, indent ): " ) if type(t) ~= "table" then return end if indent == nil then indent = " " end for k,v in pairs( t ) do if type( v ) == "table" then if ( v ~= t ) then print( indent .. tostring( k ) .. ":\n" .. indent .. "{" ) PrintTable( v, indent .. " " ) print( indent .. "}" ) end else print( indent .. tostring( k ) .. ":" .. tostring(v) ) end end end function table.ToStringShallow(t) if t == nil then return "nil" end local s = "{" for k,v in pairs(t) do s = string.format(" %s %s=%s, ", s, k, v) end s = s .. "}" return s end function TableFindKey( table, val ) if table == nil then print( "nil" ) return nil end for k, v in pairs( table ) do if v == val then return k end end return nil end function TableLength( t ) local nCount = 0 for _ in pairs( t ) do nCount = nCount + 1 end return nCount end function tablefirstkey( t ) for k, _ in pairs( t ) do return k end return nil end function tablehaselements( t ) return tablefirstkey( t ) ~= nil end --------------------------------------------------------------------------- function TableContainsValue( t, value ) for _, v in pairs( t ) do if v == value then return true end end return false end function TableContainsSubstring( t, substr ) for _, v in pairs( t ) do if v and string.match(v,substr) then return true end end return false end --------------------------------------------------------------------------- function ConvertToTime( value ) local value = tonumber( value ) if value <= 0 then return "00:00:00"; else hours = string.format( "%02.f", math.floor( value / 3600 ) ); mins = string.format( "%02.f", math.floor( value / 60 - ( hours * 60 ) ) ); secs = string.format( "%02.f", math.floor( value - hours * 3600 - mins * 60 ) ); if math.floor( value / 3600 ) == 0 then return mins .. ":" .. secs end return hours .. ":" .. mins .. ":" .. secs end end --------------------------------------------------------------------------- function SimpleSpline( value ) local valueSquared = value * value; return ( 3 * valueSquared ) - ( 2 * valueSquared * value ) end --------------------------------------------------------------------------- function IsGlobalAscensionCaster( hUnit ) if hUnit == nil then return false end return hUnit:GetName() == "ascension_global_caster" end --------------------------------------------------------------------------- -- AI functions --------------------------------------------------------------------------- function SetAggroRange( hUnit, fRange ) --print( string.format( "Set search radius and acquisition range (%.2f) for unit %s", fRange, hUnit:GetUnitName() ) ) hUnit.fSearchRadius = fRange hUnit:SetAcquisitionRange( fRange ) hUnit.bAcqRangeModified = true end -------------------------------------------------------------------------------- function GetRandomPathablePositionWithin( vPos, nRadius, nMinRadius ) if IsServer() then -- Try to find a good position, be willing to fail and return a nil value local nMaxAttempts = 10 local nAttempts = 0 local vTryPos = nil if nMinRadius == nil then nMinRadius = nRadius end repeat vTryPos = vPos + RandomVector( RandomFloat( nMinRadius, nRadius ) ) nAttempts = nAttempts + 1 if nAttempts >= nMaxAttempts then break end until ( GridNav:CanFindPath( vPos, vTryPos ) ) return vTryPos end end --------------------------------------------------------------------------------