Divergent/mods/AI Combat Pack/gamedata/scripts/rx_utils.script

875 lines
21 KiB
Plaintext
Raw Normal View History

2024-03-17 20:18:03 -04:00
function init()
rank_unit = 1/ranks.get_rank_interval(get_rank_list()[#get_rank_list()])[1]
init_clsid()
end
--------------------------------------ini---------------------------------------
local sys_ini = system_ini()
function read_from_ini(ini,sec,lin,def,typ)
if not (sec and lin) then
ABORT("read_from_ini: ini [%s] sec [%s] lin [%s] def [%s] typ [%s]",ini~=nil,sec,lin,def,typ)
end
if not ini then
ini = sys_ini
end
if ini:line_exist(sec,lin) then
if typ == 1 then
return ini:r_string(sec,lin) or def
elseif typ == nil then
return ini:r_float(sec,lin) or def
elseif typ == 0 then
local r = ini:r_bool(sec,lin)
return r == nil and def or r
elseif typ == 2 then
return ini:r_string_wq(sec,lin) or def
elseif typ == 3 then
return ini:r_s32(sec,lin) or def
elseif typ == 4 then
return ini:r_vector(sec,lin) or def
end
end
return def
end
function collect_sections(ini,sections,vfunc,dval,convert)
if vfunc == true then
vfunc = tonumber
end
local r,p,c = {},{},{}
for k,v in ipairs(sections) do
if ini:section_exist(v) then
local n = ini:line_count(v)
if n > 0 then
for i = 0,n-1 do
local res,id,val = ini:r_line(v,i,"","")
if r[id] == nil then
r[id] = dval or vfunc and vfunc(val) or val
if convert ~= nil then
table.insert(c,convert == false and r[id] or id)
end
end
end
end
p[k] = n
else
p[k] = 0
end
end
if convert ~= nil then
return c,r
end
return r,p
end
function parse_list(ini,sec,val,convert,vfunc)
local tmp = str_explode(",",read_from_ini(ini,sec,val,"",1))
if vfunc then
if vfunc == true then
vfunc = tonumber
end
for i,v in ipairs(tmp) do
local res = vfunc(v)
if res ~= nil then
tmp[i] = res
end
end
end
if convert then
local swap,func = convert == -1,type(convert) == "function"
local t = {}
for i,v in ipairs(tmp) do
t[v] = swap and i or func and convert(v,i) or convert
end
return t,tmp
end
return tmp
end
local ranksl
function get_rank_list()
if ranksl then
return ranksl
end
local tmp = parse_list(nil,"game_relations","rating")
ranksl = {}
for i,rn in ipairs(tmp) do
if not tonumber(rn) then
table.insert(ranksl,rn)
end
end
return ranksl
end
local communitiesl
function get_communities_list()
if communitiesl then
return communitiesl
end
local tmp = parse_list(nil,"game_relations","communities")
communitiesl = {}
for i,cn in ipairs(tmp) do
if not tonumber(cn) then
table.insert(communitiesl,cn)
end
end
return communitiesl
end
rank_unit = 0.01
--------------------------------------str---------------------------------------
function trim(s)
return (string.gsub(s,"^%s*(.-)%s*$","%1"))
end
function str_explode(div,str)
local t = {}
for sect in str:gmatch('[^%s*%'..div..']+') do
if sect and sect ~= "" then
table.insert(t, sect)
end
end
return t
end
function vec_to_str(vec)
if vec == nil then return "<nil>" end
return string.format("[%s:%s:%s]",vec.x,vec.y,vec.z)
end
local function format_safe(str,...)
local i,args = 0,{...}
local f = function()
i = i + 1
local a = args[i]
if a == nil then
return "<nil>"
elseif type(a) == "userdata" then
if a.setHP then
return vec_to_str(a)
elseif a.name then
return "<obj>:"..a:name()
end
return "<userdata>"
end
return tostring(a)
end
return string.gsub(str,"%%s",f)
end
----------------------------------------------------------------------------------
function count_table(t)
local cnt = 0
for k,v in pairs(t) do
cnt = cnt+1
end
return cnt
end
function transform_tiny(m,v)
local res = vector()
res.x = m.i.x * v.x + m.k.x * v.z + m.j.x * v.y + m.c.x;
res.y = m.k.y * v.z + m.j.y * v.y + m.i.y * v.x + m.c.y;
res.z = m.k.z * v.z + m.j.z * v.y + m.i.z * v.x + m.c.z;
return res
end
function random_choice(...)
local args = {...}
if #args == 1 then
return args[1][math.random(#args[1])]
end
return args[math.random(#args)]
end
--------------------------------------class---------------------------------------
actor_clsid = clsid.script_actor
creatures_clslist = {
actor = actor_clsid,
stalker = clsid.script_stalker,
dog = clsid.dog_s,
boar = clsid.boar_s,
flesh = clsid.flesh_s,
pseudodog = clsid.pseudodog_s,
bloodsucker = clsid.bloodsucker_s,
snork = clsid.snork_s,
tushkano = clsid.tushkano_s,
zombie = clsid.zombie_s,
giant = clsid.gigant_s,
chimera = clsid.chimera_s,
burer = clsid.burer_s,
controller = clsid.controller_s,
poltergeist = clsid.poltergeist_s,
fracture = clsid.fracture_s,
cat = clsid.cat_s,
psy_dog = clsid.psy_dog_s,
psy_dog_phantom = clsid.psy_dog_phantom_s
}
local firearm_clst
function item_is_fa(o,c)
if not c then
c = o and o:clsid()
end
if c and firearm_clst[c] then
return true
end
return false
end
local knife_cls
function item_is_knife(o,c)
if not c then
c = o and o:clsid()
end
return c == knife_cls
end
local grenade_clst
function item_is_grenade(o,c)
if not c then
c = o and o:clsid()
end
if c and grenade_clst[c] then
return true
end
return false
end
local blaster_clst
function item_is_blaster(o,c)
if not c then
c = o and o:clsid()
end
if c and blaster_clst[c] then
return true
end
return false
end
local ammo_clst
function item_is_ammo(o,c)
if not c then
c = o and o:clsid()
end
if c and ammo_clst[c] then
return true
end
return false
end
function is_actor(o,c)
if not c then
c = o and o:clsid()
end
return c == actor_clsid
end
local anom_clst
function is_anomaly(o,c)
if not c then
c = o and o:clsid()
end
if c and anom_clst[c] then
return true
end
return false
end
function is_story_object(game_obj)
return game_obj:story_id() < 4294967296
end
function init_clsid()
firearm_clst = {
[clsid.wpn_pm_s] = true,
[clsid.wpn_walther_s] = true,
[clsid.wpn_usp45_s] = true,
[clsid.wpn_hpsa_s] = true,
[clsid.wpn_bm16_s] = true,
[clsid.wpn_shotgun_s] = true,
[clsid.wpn_ak74_s] = true,
[clsid.wpn_lr300_s] = true,
[clsid.wpn_groza_s] = true,
[clsid.wpn_val_s] = true,
[clsid.wpn_vintorez_s] = true,
[clsid.wpn_svu_s] = true,
[clsid.wpn_svd_s] = true,
[clsid.wpn_rg6_s] = true,
[clsid.wpn_rpg7_s] = true,
-- [clsid.wpn_knife_s] = true,
}
blaster_clst = {
[clsid.wpn_rg6_s] = true,
[clsid.wpn_rpg7_s] = true
}
grenade_clst = {
[clsid.wpn_grenade_f1] = true,
[clsid.wpn_grenade_rgd5] = true
}
ammo_clst = {
[clsid.wpn_ammo] = true,
[clsid.wpn_ammo_vog25] = true,
[clsid.wpn_ammo_m209] = true,
[clsid.wpn_ammo_og7b] = true
}
anom_clst = {
-- [clsid.ameba_zone] = true,
[clsid.torrid_zone] = true,
[clsid.zone_acid_fog] = true,
[clsid.zone_bfuzz] = true,
[clsid.zone_bfuzz_s] = true,
[clsid.zone_dead] = true,
[clsid.zone_galant_s] = true,
[clsid.zone_galantine] = true,
[clsid.zone_mbald_s] = true,
[clsid.zone_mincer] = true,
[clsid.zone_mincer_s] = true,
[clsid.zone_mosquito_bald] = true,
-- [clsid.zone_radioactive] = true,
[clsid.zone_rusty_hair] = true,
-- [clsid.zone_torrid_s] = true
}
knife_cls = clsid.wpn_knife_s
end
--------------------------------------sch---------------------------------------
function add_anim(npc,anim,hand_usage,use_movement_controller)
if anim then
npc:add_animation(anim,hand_usage==true,use_movement_controller==true)
end
end
function get_sound(snd)
if snd then
return sound_object(snd)
end
end
--------------------------------------net------------------------------------------
local stpk = net_packet()
local nph,npt -- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
function get_weapon_data(sobj)
if not sobj then
return {}
end
if time_global() == npt then
if nph[sobj] then
return nph[sobj]
end
else
nph = {}
npt = time_global()
end
stpk:w_begin(0)
sobj:STATE_Write(stpk)
local size = stpk:w_tell()
stpk:r_seek(2)
local t = {}
parse_object_packet(t,stpk)
parse_visual_packet(t,stpk)
parse_item_packet(t,stpk)
parse_item_weapon_packet(t,stpk)
nph[sobj] = t
return t
end
function parse_object_packet(ret,stpk)
ret.gvid = stpk:r_u16()
ret.obf32u1 = stpk:r_float()
ret.obs32u2 = stpk:r_s32()
ret.lvid = stpk:r_s32()
ret.oflags = stpk:r_s32()
ret.custom = stpk:r_stringZ()
ret.sid = stpk:r_s32()
ret.obs32u3 = stpk:r_s32()
return ret
end
function parse_visual_packet(ret,stpk)
ret.visual = stpk:r_stringZ()
ret.vsu8u1 = stpk:r_u8()
return ret
end
function parse_item_packet(ret,stpk)
ret.condition = stpk:r_float()
ret.upgrades = readvu32stringZ(stpk)
return ret
end
function parse_item_weapon_packet(ret,stpk)
ret.ammo_current = stpk:r_u16()
ret.ammo_elapsed = stpk:r_u16()
ret.weapon_state = stpk:r_u8()
ret.addon_flags = stpk:r_u8()
ret.ammo_type = stpk:r_u8()
ret.xz1 = stpk:r_u8()
return ret
end
function readvu8uN(packet,n)
local v = {}
for i=1,n,1 do
table.insert(v,packet:r_u8())
end
return v
end
function set_weapon_data(t,sobj)
if sobj then
stpk:w_begin(0)
fill_object_packet(t,stpk)
fill_visual_packet(t,stpk)
fill_item_packet(t,stpk)
fill_item_weapon_packet(t,stpk)
local size = stpk:w_tell()
stpk:r_seek(2)
sobj:STATE_Read(stpk,size)
end
end
function fill_object_packet(ret,stpk)
stpk:w_u16(ret.gvid)
stpk:w_float(ret.obf32u1)
stpk:w_s32(ret.obs32u2)
stpk:w_s32(ret.lvid)
stpk:w_s32(ret.oflags)
stpk:w_stringZ(ret.custom)
stpk:w_s32(ret.sid)
stpk:w_s32(ret.obs32u3)
end
function fill_visual_packet(ret,stpk)
stpk:w_stringZ(ret.visual)
stpk:w_u8(ret.vsu8u1)
end
function fill_item_packet(ret,stpk)
stpk:w_float(ret.condition)
writevu32stringZ(stpk,ret.upgrades)
return ret
end
function fill_item_weapon_packet(ret,stpk)
stpk:w_u16(ret.ammo_current)
stpk:w_u16(ret.ammo_elapsed)
stpk:w_u8(ret.weapon_state)
stpk:w_u8(ret.addon_flags)
stpk:w_u8(ret.ammo_type)
stpk:w_u8(ret.xz1)
return ret
end
function writevu8uN(pk,v)
local len = table.getn(v)
for i=1,len,1 do
pk:w_u8(v[i])
end
end
function readvu32stringZ(packet)
local v = {}
local len = packet:r_s32()
for i=1,len,1 do
table.insert(v,packet:r_stringZ())
end
return v
end
function writevu32stringZ(pk,v)
if v == nil then
v = {}
end
local len = #v
pk:w_s32(len)
for i=1,len,1 do
pk:w_stringZ(v[i])
end
end
--------------------------------------weapon---------------------------------------
game_object.get_wm = function (npc,enabled_only)
local wm = rx_ai.get_storage(npc:id()).wm
if wm and not (enabled_only and wm.disabled) then
return wm
end
end
function get_weapon(npc)
local wm = rx_ai.get_storage(npc:id()).wm
return wm and wm:get_weapon() or npc:best_weapon()
end
function get_ammo_type(wpn,id)
return get_weapon_data(alife():object(id or wpn:id())).ammo_type or 0
end
--[[
function in_grenade_mode(wpn)
local pak = get_weapon_w_gl_full_data(alife():object(wpn:id()))
if bit_and(pak.addon_flags,2) == 2 then
return pak.updgrenade_mode ~= 0
end
return false
end]]
EWeaponStates = {
eFire = 5,
eFire2 = 6,
eReload = 7,
eMisfire = 8,
eMagEmpty = 9,
eSwitch = 10
}
function get_weapon_state(wpn,id)
return get_weapon_data(alife():object(id or wpn:id())).weapon_state
end
function get_mag_size(section)
return (rx_wmgr and not rx_wmgr.wm_modes.forbiddens[section] and rx_wmgr.read_wpn_params(section).mag) or read_from_ini(nil,section,"ammo_mag_size",1,3)
end
function get_wpn_type(section)
return (rx_wmgr and not rx_wmgr.wm_modes.forbiddens[section] and rx_wmgr.read_wpn_params(section).typ) or read_from_ini(nil,section,"ef_weapon_type",0,3)
end
--------------------------------------addons---------------------------------------
function get_addon_status(wpn,addon)
if addon == "sc" then
return wpn:weapon_scope_status()
elseif addon == "sl" then
return wpn:weapon_silencer_status()
elseif addon == "gl" then
return wpn:weapon_grenadelauncher_status()
end
return 0
end
function get_addon_flag(wpn,with_int)
local flag = 0
if wpn:weapon_is_scope() then
if with_int or get_addon_status(wpn,"sc") == 2 then
flag = 1
end
end
if wpn:weapon_is_silencer() then
if with_int or get_addon_status(wpn,"sl") == 2 then
flag = flag+4
end
end
if wpn:weapon_is_grenadelauncher() then
if with_int or get_addon_status(wpn,"gl") == 2 then
flag = flag+2
end
end
return flag
end
local ft = {sc = 1,sl = 4,gl = 2}
function addon_attached(wpn,addon,flag)
if ft[addon] then
return bit_and(flag or get_addon_flag(wpn,true),ft[addon]) == ft[addon]
end
end
--------------------------------------ai-----------------------------------------
function cover_in_direction(lvid,dir,bs)
if bs == move.crouch then
return level.low_cover_in_direction(lvid,dir)
else
return level.high_cover_in_direction(lvid,dir)
end
end
function npc_in_cover(npc,stand)
local st = rx_ai.get_storage(npc:id(),"in_cover")
local be,de = npc:best_enemy(),db.storage[npc:id()].danger_flag
if (be and not xr_wounded.is_wounded(be) or de) then
if stand and not npc:path_completed() then
st.evn = false
return false
end
else
return true
end
local tg = time_global()
if (st.wait or 0) > tg then
return st.evn
end
local enemies,tt = {},{}
if be and not xr_wounded.is_wounded(be) then
enemies[1] = be
tt[be:id()] = true
else -- <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if not be and de and npc:best_danger() then
local bd = npc:best_danger()
local dir = bd:position():sub(npc:position())
if dir:magnitude() < (bd:type() == danger_object.grenade and 20 or 8) or 1-cover_in_direction(npc:level_vertex_id(),dir,npc:body_state()) < 0.3 then
st.evn = false
st.wait = tg+3000
return false
end
end
st.evn = true
st.wait = tg+2000
return true
end
for o in npc:memory_visible_objects() do
local obj = o:object()
if obj then
local id = obj:id()
if not tt[id] and obj:alive() and npc:relation(obj) == game_object.enemy and (IsStalker(obj) and not xr_wounded.is_wounded(obj) or IsMonster(obj)) then
table.insert(enemies,obj)
tt[id] = true
end
end
end
for o in npc:memory_sound_objects() do
local obj = o:object()
if obj and obj:alive() and not tt[obj:id()] and npc:relation(obj) == game_object.enemy and (IsStalker(obj) and not xr_wounded.is_wounded(obj) or IsMonster(obj)) then
table.insert(enemies,obj)
end
end
local npc_lvid,npc_id,bs = npc:level_vertex_id(),npc:id(),npc:body_state()
local f = 28
for i,enemy in ipairs(enemies) do
if IsMonster(enemy) then
local dist = enemy:position():distance_to_sqr(npc:position())
local ebe = enemy:get_enemy()
if (dist < 12*12 and enemy:see(npc)) or (dist < 50*50 and ebe and ebe:id() == npc_id) then
st.evn = false
st.wait = tg+5000
return false
end
else
local dir = enemy:position():sub(npc:position())
local dist = dir:magnitude()
local seez = npc:see(enemy) and enemy:see(npc) -- <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
local cover = cover_in_direction(npc_lvid,dir,bs)
if seez or dist < 7 or cover > 0.8 or dist*cover > dist-f*cover then -- <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
st.evn = false
st.wait = tg+2500
return false
end
end
end
st.evn = true
st.wait = tg+400
return true
end
function actor_aiming_at_me(npc,df)
local aim_dir = device().cam_dir
local my_dir = npc:center():sub(device().cam_pos)
local aH,aP = aim_dir:getH(),aim_dir:getP()
local fH,fP = my_dir:getH(),my_dir:getP()
local f = 0.03+(df or 0.5)/my_dir:magnitude()
if (aH > fH and aH-fH or fH-aH) < f and (aP > fP and aP-fP or fP-aP) < f*2 then
return true
end
end
function eat_medkit(npc,medkit)
local health = read_from_ini(nil,medkit:section(),'npc_eat_health')
if health then
npc.health = health
end
npc:eat(medkit)
end
function IsTrader(npc)
local st = rx_ai.get_storage(npc:id())
if st.is_trader == nil then
local dbst = db.storage[npc:id()]
local trader = false
if npc:character_community() == "trader" or npc:clsid() == clsid.script_trader then
trader = true
elseif string.find(npc:section(),"trader") or string.find(npc:name(),"trader") then
trader = true
elseif dbst.ini and dbst.section_logic and dbst.ini:section_exist(dbst.section_logic) and dbst.ini:line_exist(dbst.section_logic,"trade") then
trader = true
end
if dbst.stype then -- <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
st.is_trader = trader
else
return trader
end
end
return st.is_trader == true
end
function safe_bone_pos(npc,bone)
local cls = npc:clsid()
if cls == clsid.burer_s then
return npc:center()
elseif cls == clsid.gigant_s then
return npc:center()
elseif cls == clsid.chimera_s then
return npc:bone_position("neck_r")
else
return npc:bone_position(bone or get_fire_bone(npc:section(),"torso"))
end
end
local gfb_torso,gfb_head,gfb_fire = {},{},{}
function get_fire_bone(sec,part)
if part == "head" then
if not gfb_head[sec] then
gfb_head[sec] = read_from_ini(nil,sec,"bone_head","bip01_head",1)
end
return gfb_head[sec]
elseif part == "torso" then
if not gfb_torso[sec] then
gfb_torso[sec] = read_from_ini(nil,sec,"bone_torso",nil,1) or read_from_ini(nil,sec,"bone_spin","bip01_spine",1)
end
return gfb_torso[sec]
end
if not gfb_fire[sec] then
gfb_fire[sec] = read_from_ini(nil,sec,"bone_fire","bip01_head",1)
end
return gfb_fire[sec]
end
--------------------------------------switch---------------------------------------
function switch_online(id)
if id == -1 then return end
local sim = alife()
if sim then
sim:set_switch_online(id,true)
sim:set_switch_offline(id,false)
end
end
function switch_offline(id)
local sim = alife()
if sim then
sim:set_switch_online(id,false)
sim:set_switch_offline(id,true)
end
end
--------------------------------------output---------------------------------------
function printf(str,...)
get_console():execute("load ~#I#:"..format_safe(str,...))
-- log(format_safe(str,...))
-- get_console():execute("flush")
end
function prints(str)
get_console():execute("load ~#I#:"..str)
-- log(str)
end
function give_game_news(str,time,...)
if db.actor then
db.actor:give_game_news("",format_safe(str,...),"ui_iconsTotal_grouping",0,time,0)
end
end
function ABORT(s,...)
printf("rx_utils.abort: "..s,...)
sys_ini:r_bool("___aborting","a")
end
_G['ABORTX'] = ABORT
function ASSERT(o,s,...)
if not o then
ABORT(s,...)
end
end
_G['ASSERTX'] = ASSERT
function print_table(t,name)
local print_r_cache={}
local function sub_print_r(t,indent)
if (type(t)~="userdata" and print_r_cache[tostring(t)]) then
prints(indent.."*"..tostring(t))
else
if type(t)~="userdata" then
print_r_cache[tostring(t)]=true
end
if (type(t)=="table") then
for pos,val in pairs(t) do
if (type(val)=="table") then
prints(indent.."["..pos.."] => "..tostring(t).." {")
sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
prints(indent..string.rep(" ",string.len(pos)+6).."}")
elseif (type(val)=="string") then
prints(indent.."["..pos..'] => "'..val..'"')
elseif(type(val)=="userdata") then
prints(indent.."["..pos..'] => "userdata"')
else
prints(indent.."["..pos.."] => "..tostring(val))
end
end
elseif(type(t)=="userdata") then
prints(indent.."userdata")
else
prints(indent..tostring(t))
end
end
end
if (type(t)=="table") then
printf("print_table %s: %s {",(name or 'unnamed'),tostring(t))
sub_print_r(t," ")
prints("}")
else
printf("print_table %s: %s(%s) is not table!",(name or 'unnamed'),type(t),t)
end
end
--------------------------------------spy------------------------------------------
class "prof_spy"
function prof_spy:__init()
self.store = {}
self.global_timer = time_global()
end
function prof_spy:__finalize()
end
function prof_spy:start(name)
if not self.store[name] then
self.store[name] = {timer = profile_timer(),count = 0,time = 0,min_time = 0,max_time = 0,prev_ptime = 0}
end
local st = self.store[name]
st.timer:start()
end
function prof_spy:finish(name)
local st = self.store[name]
ASSERTX(st,"spy finish %s",name)
st.timer:stop()
local ptime = st.timer:time()
local rtime = ptime-st.prev_ptime
if rtime == 0 then
return
end
st.prev_ptime = ptime
st.time = st.time+rtime
st.count = st.count+1
st.min_time = (st.min_time == 0 or rtime < st.min_time) and rtime or st.min_time
st.max_time = rtime > st.max_time and rtime or st.max_time
end
function prof_spy:get_stat(name)
if name then
local st = self.store[name]
if not st then
return "nil"
end
local global_time = time_global()-self.global_timer
local exec_ms_in_sec = st.time/global_time
local str = string.format("\n[%s]: cnt=[%s] time=[%s] min=[%s] max=[%s] prd=[%s] ret=[%s] insec=[%s]",name,st.count,st.time,st.min_time,st.max_time,global_time/st.count,st.time/st.count,exec_ms_in_sec)
return str
else
local tt = {}
for name,st in pairs(self.store) do
local global_time = time_global()-self.global_timer
local exec_ms_in_sec = st.time/global_time
local str = string.format("\n[%s]: cnt=[%s] time=[%s] min=[%s] max=[%s] prd=[%s] ret=[%s] insec=[%s]",name,st.count,st.time,st.min_time,st.max_time,global_time/st.count,st.time/st.count,exec_ms_in_sec)
table.insert(tt,str)
end
return tt
end
end