e4s-sdk/gamedata/scripts/utils.script
2026-06-17 23:06:51 +03:00

823 lines
No EOL
22 KiB
Text

--[[
ÎÏÈÑÀÍÈÅ ÔÓÍÊÖÈÉ
-- Âûâîäèò îòëàäî÷íîå ñîîáùåíèå â ëîã, åñëè ñêðèïò àêòèâåí (àêòèâíûé ñêðèïò âûáèðàåòñÿ ñ ïîìîùüþ
-- ïåðåìåííîé debug_info.trace_script).
function trace(script_name, fmt, ...)
-- Ïåðåâîäèò ïåðåìåííóþ ëþáîãî òèïà (âêëþ÷àÿ nil) â ñòðîêó. Èñïîëüçóåòñÿ äëÿ îòëàäî÷íîãî âûâîäà èíôîðìàöèè.
function to_str(what)
-- Ñîçäàåò è âîçâðàùàåò êîïèþ âåêòîðà
function vector_copy_by_val(vec)
-- Íàñòðîéêà ïàðàìåòðîâ èãðîâûõ îáúåêòîâ:
function cfg_get_bool(char_ini, section, field, object, mandatory, default_val)
function cfg_get_string(char_ini, section, field, object, mandatory, gulag_name, default_val)
function cfg_get_number(char_ini, section, field, object, mandatory, default_val)
-- Ïðîâåðÿåò, íàõîäèòñÿ ëè stalker ðÿäîì ñ òî÷êîé path_point ïóòè patrol_path
function stalker_at_waypoint(stalker, patrol_path, path_point)
-- Ïîñëàòü stalker â çàäàííóþ òî÷êó patrol_path(path_point)
function stalker_go_to_waypoint(stalker, patrol_path, path_point)
--]]
----------------------------------------------------------------------------------------------------
-- Âûâîäèò îòëàäî÷íîå ñîîáùåíèå â ëîã, åñëè ñêðèïò àêòèâåí (àêòèâíûé ñêðèïò âûáèðàåòñÿ ñ ïîìîùüþ
-- ïåðåìåííîé debug_info.trace_script).
--function trace(script_name, fmt, ...)
-- if debug_info.trace_script == script_name then
-- log(string.format("[TRACE] " .. script_name .. ".script: " .. fmt, unpack(arg)))
-- end
--end
-- Ïåðåâîäèò ïåðåìåííóþ ëþáîãî òèïà (âêëþ÷àÿ nil) â ñòðîêó. Èñïîëüçóåòñÿ äëÿ îòëàäî÷íîãî âûâîäà èíôîðìàöèè.
function to_str(what)
if what == nil then
return "<nil>"
else
return tostring(what)
end
end
--'Êîïèðîâàíèå òàáëèöû ïî çíà÷åíèþ
function copy_table(dest, src)
for k,v in pairs(src) do
if type(v) == "table" then
--' ðåêóðñèâíûé âûçîâ ñåáÿ æå äëÿ ïîäòàáëèö
dest[k] = {}
copy_table(dest[k], v)
else
dest[k] = v
end
end
end
function print_table()
local sub
if subs ~= nil then
sub = subs
else
sub = ""
end
for k,v in pairs(table) do
if type(v) == "table" then
printf(sub.."%s:", tostring(k))
print_table(v, sub.." ")
elseif type(v) == "function" then
printf(sub.."%s:function", tostring(k))
elseif type(v) == "userdata" then
printf(sub.."%s:userdata", tostring(k))
elseif type(v) == "boolean" then
if v == true then
printf(sub.."%s:true", tostring(k))
else
printf(sub.."%s:false", tostring(k))
end
else
if v ~= nil then
printf(sub.."%s:%s", tostring(k),v)
else
printf(sub.."%s:nil", tostring(k),v)
end
end
end
end
--' Âîçâðàùàåò ðàññòîÿíèå ìåæäó äâóìÿ òî÷êàìè ãðàôà ñ ó÷åòîì ðàçíîñòè óðîâíåé
function graph_distance(vid1, vid2)
local p1 = game_graph():vertex(vid1):game_point()
local p2 = game_graph():vertex(vid2):game_point()
--printf("GRAPH DISTANCE [%s][%s][%s] : [%s][%s][%s]", p1.x, p1.y, p1.z, p2.x, p2.y, p2.z)
return game_graph():vertex(vid1):game_point():distance_to(game_graph():vertex(vid2):game_point())
end
--' Ñðàâíèâàåò äâà âåêòîðà
function vector_cmp(a, b)
return a.x == b.x and a.y == b.y and a.z == b.z
end
--' Ñðàâíèâàåò äâà âåêòîðà ñ çàäàííîé ïîãðåøíîñòüþ
function vector_cmp_prec(a, b, d)
return math.abs(a.x - b.x) <= d and
math.abs(a.y - b.y) <= d and
math.abs(a.z - b.z) <= d
end
-- Ñîçäàåò è âîçâðàùàåò êîïèþ âåêòîðà
function vector_copy_by_val(vec)
return vector():set(vec)
end
-- Íàñòðîéêà ïàðàìåòðà òèïà bool ó èãðîâîãî îáúåêòà.
--
-- char_ini - óêàçàòåëü íà customdata (îáû÷íî object:spawn_ini())
-- section - èìÿ ñåêöèè â customdata
-- field - èìÿ ïîëÿ â customdata
-- object - èãðîâîé îáúåêò, îò êîòîðîãî áóäåò âçÿòî èìÿ äëÿ ñîîáùåíèÿ îá îøèáêå
-- mandatory - ïîëå îáÿçàòåëüíî äîëæíî áûòü çàäàíî
--
-- Âîçâðàùàåò true èëè false
function cfg_get_bool(char_ini, section, field, object, mandatory, default_val)
if mandatory == nil then
abort("section '%s': wrong arguments order in call to cfg_get_bool", section)
end
--printf("DEBUG: conf_get_bool: section='%s', field='%s'", section, field)
if section and char_ini:section_exist(section) and char_ini:line_exist(section, field) then
local ret = char_ini:r_bool(section, field)
return ret
end
if not mandatory then
if default_val then
if default_val ~= false and default_val ~= true then
abort("object '%s': section '%s': field '%s': default value is " ..
"not boolean", object:name(), section, field)
end
return default_val
end
return false
end
abort("object '%s': attempt to read a non-existant boolean field '%s' in " ..
"section '%s'", object:name(), field, section)
end
function cfg_get_string(char_ini, section, field, object, mandatory, gulag_name, default_val)
if mandatory == nil or gulag_name == nil then
abort("section '%s': wrong arguments order in call to cfg_get_string", section)
end
--printf("DEBUG: conf_get_string: section='%s', field='%s'", section, field)
if section and char_ini:section_exist(section) and char_ini:line_exist(section, field) then
if gulag_name and gulag_name ~= "" then
return gulag_name .. "_" .. char_ini:r_string(section, field)
else
return char_ini:r_string(section, field)
end
end
if not mandatory then
return default_val
end
local err = "'Attempt to read a non-existant string field '" ..
field .. "' in section '" .. section .. "'";
abort("%s", err)
end
function cfg_get_number(char_ini, section, field, object, mandatory, default_val)
if mandatory == nil then
abort("section '%s': wrong arguments order in call to cfg_get_number", section)
end
--printf("DEBUG: conf_get_number: section='%s', field='%s'", section, field)
if section and char_ini:section_exist(section) and char_ini:line_exist(section, field) then
return char_ini:r_float(section, field)
end
if not mandatory then
return default_val
end
-- local err = "object name '" .. object:name() .. "': attempt to read a non-existant numeric field '" ..
-- field .. "' in section '" .. section .. "'";
-- abort("%s", err)
end
function mob_get_string(char_ini, section, field, override, object, mandatory, default_val)
if override ~= nil then
return override
end
return cfg_get_string(char_ini, section, field, object, mandatory, "", default_val)
end
function mob_get_number(char_ini, section, field, override, object, mandatory, default_val)
if override ~= nil then
return override
end
return cfg_get_number(char_ini, section, field, object, mandatory, default_val)
end
function mob_get_bool(char_ini, section, field, override, object, mandatory, default_val)
if override ~= nil then
return override ~= false
end
return cfg_get_bool(char_ini, section, field, object, mandatory, default_val)
end
-- Ïðîâåðÿåò, íàõîäèòñÿ ëè stalker ðÿäîì ñ òî÷êîé path_point ïóòè patrol_path
function stalker_at_waypoint(stalker, patrol_path, path_point)
-- return stalker:level_vertex_id() == patrol_path:level_vertex_id(path_point)
local stalker_pos = stalker:position()
local distance = stalker_pos:distance_to_sqr(patrol_path:point(path_point))
if distance <= 0.13 then
return true
end
return false
end
-- Ïîñëàòü stalker â çàäàííóþ òî÷êó patrol_path(path_point)
--[[
function stalker_go_to_waypoint(stalker, patrol_path, path_point)
if stalker:animation_count() > 0 then
stalker:clear_animations()
end
if stalker:level_vertex_id() == patrol_path:level_vertex_id(path_point) then
return
end
stalker:set_dest_level_vertex_id(patrol_path:level_vertex_id(path_point))
stalker:set_movement_type(move.run)
stalker:set_body_state(move.standing)
stalker:set_sight(look.path_dir, nil, 0)
stalker:set_path_type(game_object.level_path)
stalker:set_mental_state(anim.danger)
stalker:set_detail_path_type(move.line)
end
--]]
function stalker_stop(stalker)
stalker:set_movement_type(move.stand)
end
--[[
function stalker_look_at_waypoint(stalker, patrol_path, path_point)
local look_pt = this.vector_copy_by_val(patrol_path:point(path_point)):sub(stalker:position())
stalker:set_sight(look.direction, look_pt, 0)
end
--]]
--[[
function stalker_look_at_stalker(stalker, whom)
local look_pt = this.vector_copy_by_val(whom:position()):sub(stalker:position())
stalker:set_sight(look.direction, look_pt, 0)
end
--]]
--[[
function stalker_look_at_stalker_angle(stalker, whom, angle)
--stalker - killer
--whom - killed :)
local look_pt = this.vector_copy_by_val(whom:position()):sub(stalker:position())
stalker:set_sight (look.direction, vector_rotate_y (look_pt, angle), 0)
end
--]]
--[[
function stalker_look_firepoint_angle(stalker, whom, angle)
--stalker - killer
--whom - killed :)
local look_pt = this.vector_copy_by_val(whom:position()):sub(stalker:position())
stalker:set_sight (look.fire_point, vector_rotate_y (look_pt, angle), 0)
end
--]]
local function door_default_callback(door, actor)
local ph_shell = door:get_physics_shell()
local joint = ph_shell:get_joint_by_bone_name("door")
local low_limit = 0
local hi_limit = 0
low_limit, hi_limit = joint:get_limits(low_limit, hi_limit, 0)
local angle = joint:get_axis_angle(0)
if angle-low_limit > hi_limit - angle
then
joint:set_max_force_and_velocity(100, -1.5, 0)
else
joint:set_max_force_and_velocity(100, 1.5, 0)
end
end
function door_init(door)
door:set_use_callback(door_default_callback)
end
-- Äâåðü door èìïóëüñîì çàõëîïíåòñÿ è çàëî÷èòñÿ, ïðè þçå áóäåò âûçûâàòüñÿ callback_fn
function door_close_then_lock(door, callback_fn)
local ph_shell = door:get_physics_shell()
local joint = ph_shell:get_joint_by_bone_name("door")
local low_limit = 0
local hi_limit = 0
low_limit, hi_limit = joint:get_limits(low_limit, hi_limit, 0)
local angle = joint:get_axis_angle(0)
if angle-low_limit > hi_limit - angle
then
joint:set_max_force_and_velocity(1000000, 0, 0)
else
joint:set_max_force_and_velocity(1000000, 0, 0)
end
end
--unlock_then_open(door) -- äâåðü ðàçëî÷èòñÿ è èìïóëüñîì îòêðîåòñÿ
--locked(door) -- true, åñëè äâåðü çàêðûòà è çàëî÷åíà
--Ïðè ïîïûòêå ïîþçàòü íåçàïåðòóþ äâåðü îíà ïðîñòî ñèëîé îòêðûâàåòñÿ äî ìàêñèìàëüíî äîïóñòèìîãî ñîñòîÿíèÿ.
function parse_waypoint_data(pathname, wpflags, wpname)
local rslt = {}
rslt.flags = wpflags
local at
if string.find(wpname, "|", at, true) == nil then
return rslt
end
local par_num
local fld
local val
par_num = 1
for param in string.gfind(wpname, "([%w%+~_\\%=%{%}%s%!%-%,%*]+)|*") do
if par_num == 1 then
-- continue
else
if param == "" then
abort("path '%s': waypoint '%s': syntax error in waypoint name", pathname, wpname)
end
local t_pos = string.find(param, "=", 1, true)
if t_pos == nil then
printf("Path_param: %s", param)
abort("path '%s': waypoint '%s': syntax error in waypoint name", pathname, wpname)
end
fld = string.sub(param, 1,t_pos - 1)
val = string.sub(param, t_pos + 1)
if not fld or fld == "" then
abort("path '%s': waypoint '%s': syntax error while parsing the param '%s': no field specified",
pathname, wpname, param)
end
if not val or val == "" then
val = "true"
end
if fld == "a" then
rslt[fld] = xr_logic.parse_condlist(db.actor, "waypoint_data", "anim_state", val)
else
rslt[fld] = val
end
end
par_num = par_num + 1
end
return rslt
end
function path_parse_waypoints(pathname)
if not pathname then
return nil
end
--printf("_bp: path_parse_waypoints: pathname='%s'", pathname)
local ptr = patrol(pathname)
local cnt = ptr:count()
local rslt = {}
for pt = 0, cnt - 1 do
--printf("_bp: %s", ptr:name(pt))
rslt[pt] = parse_waypoint_data(pathname, ptr:flags(pt), ptr:name(pt))
if not rslt[pt] then
abort("error while parsing point %d of path '%s'", pt, pathname)
end
end
return rslt
end
function path_parse_waypoints_from_arglist(pathname, num_points, ...)
local arg = {...}
if not pathname then
return nil
end
local ptr = patrol(pathname)
local cnt = ptr:count()
if cnt ~= num_points then
abort("path '%s' has %d points, but %d points were expected", pathname, cnt, num_points)
end
local rslt = {}
local cur_arg
local fl
for pt = 0, cnt-1 do
cur_arg = arg[pt + 1]
if not cur_arg then
abort("script error [1] while processing point %d of path '%s'", pt, pathname)
end
fl = flags32()
fl:assign(cur_arg[1])
rslt[pt] = parse_waypoint_data(pathname, fl, cur_arg[2])
if not rslt[pt] then
abort("script error [2] while processing point %d of path '%s'", pt, pathname)
end
end
return rslt
end
function action2(obj,...)
local act = entity_action()
local i = 1
while true do
if (arg[i] ~= nil) then
act:set_action(arg[i])
else
break
end
i = i + 1
end
if (obj ~= nil) then
obj:command(act,false)
end
return entity_action(act)
end
function wpn_info_get(npc)
local rslt = {}
local active_item = npc:active_item()
local has_weapon = active_item and isWeapon(active_item)
if has_weapon then
rslt["id"] = active_item:id()
rslt["ammo"] = active_item:get_ammo_in_magazine()
end
return rslt
end
function wpn_info_equal(wpn_info1, wpn_info2)
return wpn_info1["id"] == wpn_info2["id"] and wpn_info1["ammo"] == wpn_info2["ammo"]
end
function get_scheme_by_section(section)
local scheme = string.gsub(section, "%d", "")
local at, to = string.find(scheme, "@", 1, true)
if at and to then
scheme = string.sub(scheme, 1, at - 1)
end
return scheme
end
-- a | b | c ==> { 1 = "a", 2 = "b", 3 = "c" }
function parse_params(params)
--printf("_bp: parse_params: params=%s", params)
local rslt = {}
local n = 1
for fld in string.gfind(params, "%s*([^|]+)%s*") do
--printf("_bp: parse_params iter=%d, fld=%s", n, fld)
rslt[n] = fld
n = n + 1
end
return rslt
end
function is_day()
return level.get_time_hours() >= 5 and level.get_time_hours() < 22
end
function electro_art_enabled ()
return level.get_time_hours() >= 0 and level.get_time_hours() < 5
end
function no_need_to_rotate(npc, target_pos)
local y = yaw(npc:direction(), utils.vector_copy_by_val(target_pos):sub(npc:position()))
return y < 0.3
end
function no_need_to_rotate_xz(npc, target_pos)
local dir1 = npc:direction()
dir1.y = 0
local dir2 = utils.vector_copy_by_val(target_pos):sub(npc:position())
dir2.y = 0
local y = yaw(dir1, dir2)
return y < 0.3
end
-- Ïåðåâîä óãëà èç ðàäèàíîâ â ãðàäóñû
function rad2deg(r)
return r * 180.0 / math.pi
end
-- Ïåðåâîä óãëà èç ãðàäóñîâ â ðàäèàíû
function deg2rad(d)
return d * math.pi / 180.0
end
-- óãîë ìåæäó äâóìÿ âåêòîðàìè â ãðàäóñàõ.
function angle_diff(a1, a2)
local b1 = a1:normalize()
local b2 = a2:normalize()
local dotp = b1:dotproduct(b2)
return rad2deg(math.acos(math.abs(dotp)))
end
-- true, åñëè íóæíî ïîâîðà÷èâàòü âëåâî
function angle_left(dir1, dir2)
local dir_res = vector()
dir_res:crossproduct(dir1, dir2)
return dir_res.y <= 0
end
function angle_left_xz(dir1, dir2)
local dir_res = vector()
dir1.y = 0
dir2.y = 0
dir_res:crossproduct(dir1, dir2)
return dir_res.y <= 0
end
function get_nearest_waypoint(obj, pathname, ptr, cnt)
local pt_chosen = nil
local min_dist = nil
local dist
for i = 0, cnt - 1 do
dist = obj:position():distance_to(ptr:point(i))
if not min_dist or dist < min_dist then
min_dist = dist
pt_chosen = i
end
end
if not pt_chosen then
abort("object '%s': path '%s': get_nearest_waypoint: unable to choose a nearest waypoint (path has no waypoints?)",
obj:name(), pathname)
end
return pt_chosen
end
function npc_in_zone(npc, zone)
return npc ~= nil and zone ~= nil and zone:inside(npc:position())
end
------------------------- çàïèñü/çàãðóçêà CTime ---------------------------
local CTime_0
if not editor() then
CTime_0 = game.CTime()
end
-- çàïèñü CTime â ïàêåò. åñëè t=nil, òî çàïèøåò îäèí íóëåâîé áàéò
function w_CTime( p, t )
--set_save_marker(p, "save", false, "CTIME")
if t == nil then
p:w_u8(-1)
--set_save_marker(p, "save", true, "CTIME")
return
end
if (CTime == nil) or (t ~= CTime_0) then
local Y, M, D, h, m, s, ms = 0, 0, 0, 0, 0, 0, 0
Y, M, D, h, m, s, ms = t:get( Y, M, D, h, m, s, ms )
p:w_u8 ( Y - 2000 )
p:w_u8 ( M )
p:w_u8 ( D )
p:w_u8 ( h )
p:w_u8 ( m )
p:w_u8 ( s )
p:w_u16( ms )
else
p:w_u8 ( 0 )
end
--set_save_marker(p, "save", true, "CTIME")
end
-- ÷òåíèå CTime èç ïàêåòà
function r_CTime( p )
--set_save_marker(p, "load", false, "CTIME")
local Y = p:r_u8()
if Y == 255 then
--set_save_marker(p, "load", true, "CTIME")
return nil
end
if Y ~= 0 then
local t = game.CTime()
local M, D, h, m, s, ms = p:r_u8(), p:r_u8(), p:r_u8(), p:r_u8(), p:r_u8(), p:r_u16()
t:set( Y + 2000, M, D, h, m, s, ms)
--set_save_marker(p, "load", true, "CTIME")
return t
else
--set_save_marker(p, "load", true, "CTIME")
return 0
end
end
---------------------------------------------------------------------------
-- îòîñëàòü â áëèæàéøóþ ðàçðåø¸ííóþ íîäó ïî íàïðàâëåíèþ ê çàäàííîé.
-- âîçâðàùàåò vertex_id, â êîòîðîå îòïðàâèë ïåðñîíàæà
function send_to_nearest_accessible_vertex( npc, v_id )
if not npc:accessible( v_id ) then
local vtemp = vector()
--printf("vertex_position")
v_id, vtemp = npc:accessible_nearest( level.vertex_position( v_id ), vtemp )
end
npc:set_dest_level_vertex_id( v_id )
return v_id
end
-- ïðîèñõîäèò ëè â äàííûé ìîìåíò ñìåíà óðîâíÿ?
-- íóæíî äëÿ òîãî, ÷òîáû îáúåêòû çíàëè, êàêóþ èíôîðìàöèþ çàïèñûâàòü ïðè ñîõðàíåíèè, à êàêóþ íåò
function level_changing()
local sim = alife()
if not sim then
return false
end
local actor_gv = game_graph():vertex( sim:actor().m_game_vertex_id )
return actor_gv:level_id() ~= sim:level_id()
end
function parse_data_1v(npc,s)
local t = {}
if s then
for name in string.gfind( s, "(%|*%d+%|[^%|]+)%p*" ) do
-- printf("[%s]", utils.to_str(name))
local dat = { dist = nil,
state = nil}
local t_pos = string.find( name, "|", 1, true )
local dist = string.sub( name, 1, t_pos - 1 )
local state = string.sub( name, t_pos + 1)
-- printf(" [%s]=[%s][%s]", utils.to_str(dist), utils.to_str(state), utils.to_str(sound))
dat.dist = tonumber(dist)
if state then
dat.state = xr_logic.parse_condlist(npc, dist, state, state)
end
t[tonumber(dist)] = dat
end
end
return t
end
--' Âû÷èòêà ñâîéñòâ äëÿ ñïàóíà îáúåêòîâ.
function parse_names(s)
local t = {}
for name in string.gfind( s, "([%w_%-.\\]+)%p*" ) do
table.insert( t, name )
end
return t
end
function parse_spawns(str)
--' åñëè default-îâ áîëüøå, ÷åì çíà÷åíèé â ini, òî çàáèòü íåäîñòàþùèå ïîñëåäíèì çíà÷åíèåì èç ini
local t = utils.parse_names(str)
local n = #t
local ret_table = {}
local k = 1
while k <= n do
local spawn = {}
spawn.section = t[k]
--' Ïðîâåðÿåì ÷òî ýòî íå ïîñëåäíÿÿ çàïèñü
if t[k+1] ~= nil then
local p = tonumber(t[k+1])
--' ïðîâåðÿåì ÷òî âòîðûì ÷èñëîì çàäàíà âåðîÿòíîñòü, à íå äðóãàÿ ñåêöèÿ ñïàâíó
if p then
--' çàáèâàåì ÷èñëî
spawn.prob = p
k = k + 2
else
--' çàáèâàåì äåôîëò 1
spawn.prob = 1
k = k + 1
end
else
spawn.prob = 1
k = k + 1
end
table.insert(ret_table, spawn)
end
return ret_table
end
function r_2nums( spawn_ini, section, line, def1, def2 )
if spawn_ini:line_exist( section, line ) then
-- åñëè default-îâ áîëüøå, ÷åì çíà÷åíèé â ini, òî çàáèòü íåäîñòàþùèå ïîñëåäíèì çíà÷åíèåì èç ini
local t = utils.parse_names( spawn_ini:r_string( section, line ) )
local n = #t
if n == 0 then
return def1, def2
elseif n == 1 then
return t[1], def2
else
return t[1], t[2]
end
else
return def1, def2
end
end
function parse_target(target)
local pos = string.find(target, ",")
if pos then
return string.sub(target, 1, pos - 1), string.sub(target, pos + 1)
else
return target, nil
end
end
function parse_data(npc,s)
local t = {}
if s then
for name in string.gfind( s, "(%|*%d+%|[^%|]+)%p*" ) do
-- printf("[%s]", utils.to_str(name))
local dat = { dist = nil,
state = nil,
sound = nil}
local t_pos = string.find( name, "|", 1, true )
local s_pos = string.find( name, "@", 1, true )
local dist = string.sub( name, 1, t_pos - 1 )
local state
local sound
if s_pos then
state = string.sub( name, t_pos + 1,
s_pos - 1 )
sound = string.sub( name, s_pos + 1)
else
state = string.sub( name, t_pos + 1)
end
-- printf(" [%s]=[%s][%s]", utils.to_str(dist), utils.to_str(state), utils.to_str(sound))
dat.dist = tonumber(dist)
if state then
dat.state = xr_logic.parse_condlist(npc, dist, state, state)
end
if sound then
dat.sound = xr_logic.parse_condlist(npc, dist, sound, sound)
end
table.insert(t, dat)
end
end
return t
end
function parse_syn_data(npc,s)
-- printf("parse_syn_data [%s]", utils.to_str(s))
local t = {}
if s then
for name in string.gfind( s, "(%|*[^%|]+%|*)%p*" ) do
local dat = { zone = nil,
state = nil,
sound = nil}
-- printf("[%s]", utils.to_str(name))
local t_pos = string.find( name, "@", 1, true )
local s_pos = string.find( name, "|", 1, true )
local state = string.sub( name, 1, t_pos - 1 )
local sound
if s_pos then
sound = string.sub( name, t_pos + 1, s_pos -1)
else
sound = string.sub( name, t_pos + 1)
end
dat.state = state
dat.sound = sound
table.insert(t, dat)
end
end
return t
end
function is_widescreen()
return (device().width/device().height>1024/768+0.01)
end