SoC. Снятие денег с трупов — различия между версиями — S.T.A.L.K.E.R. Inside Wiki

SoC. Снятие денег с трупов — различия между версиями

Материал из S.T.A.L.K.E.R. Inside Wiki

Перейти к: навигация, поиск
(Подправил орфографию)
м (tags)
 
(не показаны 17 промежуточные версии 11 участников)
Строка 1: Строка 1:
В этой теме я напишу как сделать так что бы можно было снимать деньги с трупов.
+
Нам понадобится файл ''''treasure_manager.script''''.
Нам надо файл treasure_manager.script
+
В этом файле находим такие строки
+
  
<pre>--' Юзание инициатора (возможность выдать тайник)
+
В этом файле находим такие строки:
 +
 
 +
<lua>
 +
--' Юзание инициатора (возможность выдать тайник)
 
function CTreasure:use(npc)
 
function CTreasure:use(npc)
 
printf("TREASURE USE")
 
printf("TREASURE USE")
Строка 11: Строка 12:
 
lootmoney.lootmoney(npc)
 
lootmoney.lootmoney(npc)
 
end
 
end
</pre>
+
</lua>
У нас далжно выйти
+
 
<pre>--' Юзание инициатора (возможность выдать тайник)
+
У нас должно выйти
 +
 
 +
<lua>
 +
--' Юзание инициатора (возможность выдать тайник)
 
function CTreasure:use(npc)
 
function CTreasure:use(npc)
 
printf("TREASURE USE")
 
printf("TREASURE USE")
Строка 20: Строка 24:
 
lootmoney.lootmoney(npc)
 
lootmoney.lootmoney(npc)
 
end
 
end
</pre>
+
</lua>
Теперь создаём файл lootmoney.script
+
и в нём пишем
+
  
<pre>function lootmoney(npc)
+
Теперь создаём файл '''lootmoney.script''' и в нём пишем
 +
 
 +
<lua>
 +
function lootmoney(npc)
 
if npc ~= nil and not string.find(npc:section(),"arena") and npc:character_community()~="arena_enemy" then
 
if npc ~= nil and not string.find(npc:section(),"arena") and npc:character_community()~="arena_enemy" then
 
local money = npc:money()
 
local money = npc:money()
Строка 48: Строка 53:
 
end
 
end
 
end
 
end
</pre>
+
</lua>
теперь создаем файл watcher_act.script и впишем в его
+
 
+
<pre>-- Red75 (c) 2008
+
-- Marauder scheme v 1.1
+
-- Part of AMK MOD
+
 
+
evid_see_stuff=6931
+
evid_near_stuff=evid_see_stuff+1
+
evid_see_body=evid_see_stuff+2
+
evid_position_corrected=evid_see_stuff+3
+
 
+
actid_reach_item=evid_see_stuff
+
actid_grab_item=evid_see_stuff+1
+
actid_grab_body=evid_see_stuff+2
+
actid_correct_position=evid_see_stuff+3
+
 
+
-- Вызывает closure раз в period, obj[var] хранит время следующего срабатывания
+
function timed(obj,var,period,closure)
+
if obj[var] and obj[var]<time_global() then
+
obj[var]=time_global()+period
+
closure()
+
elseif not obj[var] then
+
obj[var]=time_global()+period
+
-- closure()
+
end
+
end
+
 
+
function trigger_timed(obj,var)
+
obj[var]=time_global()
+
end
+
 
+
local disabled_objects={}
+
 
+
local corpse_checked={} -- true - has loot, false - hasn't loot, nil - not checked
+
 
+
function checkCorpse(obj)
+
if (IsStalker(obj) or IsMonster(obj)) and obj:alive()==false then
+
if corpse_checked[obj:id()]~=nil then
+
return corpse_checked[obj:id()]
+
end
+
local cnt=0
+
obj:iterate_inventory(function (dummy, item)
+
        if item:section()~="bolt" then
+
          cnt=cnt+1
+
        end
+
end, nil)
+
corpse_checked[obj:id()]=cnt>0
+
return corpse_checked[obj:id()]
+
end
+
return false
+
end
+
 
+
local valuable_clsid={
+
    [clsid.art_bast_artefact]=true,
+
    [clsid.art_black_drops]=true,
+
    [clsid.art_dummy]=true,
+
    [clsid.art_electric_ball]=true,
+
    [clsid.art_faded_ball]=true,
+
    [clsid.art_galantine]=true,
+
    [clsid.art_gravi]=true,
+
    [clsid.art_gravi_black]=true,
+
    [clsid.art_mercury_ball]=true,
+
    [clsid.art_needles]=true,
+
    [clsid.art_rusty_hair]=true,
+
    [clsid.art_thorn]=true,
+
    [clsid.art_zuda]=true,
+
    [clsid.artefact_s]=true,
+
    [clsid.device_detector_simple]=true,
+
    [clsid.device_pda]=true,
+
    [clsid.device_torch_s]=true,
+
    [clsid.equ_exo]=true,
+
    [clsid.equ_military]=true,
+
    [clsid.equ_scientific]=true,
+
    [clsid.equ_stalker_s]=true,
+
    [clsid.obj_antirad]=true,
+
    [clsid.obj_attachable]=true,
+
    [clsid.obj_bandage]=true,
+
    [clsid.obj_bolt]=true,
+
    [clsid.obj_bottle]=true,
+
    [clsid.obj_food]=true,
+
    [clsid.obj_medkit]=true,
+
    [clsid.wpn_ak74_s]=true,
+
    [clsid.wpn_ammo]=true,
+
    [clsid.wpn_ammo_m209]=true,
+
    [clsid.wpn_ammo_og7b]=true,
+
    [clsid.wpn_ammo_vog25]=true,
+
    [clsid.wpn_binocular_s]=true,
+
    [clsid.wpn_bm16_s]=true,
+
    [clsid.wpn_fn2000]=true,
+
    [clsid.wpn_fort]=true,
+
    [clsid.wpn_groza_s]=true,
+
    [clsid.wpn_hpsa_s]=true,
+
    [clsid.wpn_knife_s]=true,
+
    [clsid.wpn_lr300_s]=true,
+
    [clsid.wpn_pm_s]=true,
+
    [clsid.wpn_rg6_s]=true,
+
    [clsid.wpn_rpg7_s]=true,
+
    [clsid.wpn_scope_s]=true,
+
    [clsid.wpn_shotgun_s]=true,
+
    [clsid.wpn_silencer]=true,
+
    [clsid.wpn_svd_s]=true,
+
    [clsid.wpn_svu_s]=true,
+
    [clsid.wpn_usp45_s]=true,
+
    [clsid.wpn_val_s]=true,
+
    [clsid.wpn_vintorez_s]=true,
+
    [clsid.wpn_walther_s]=true,
+
    [clsid.wpn_wmagaz]=true,
+
    [clsid.wpn_wmaggl]=true
+
}
+
 
+
local obj_owner={}
+
 
+
function bgwith(str,ptr)
+
local ps=string.find(str,ptr)
+
return ps~=nil and ps==1
+
end
+
 
+
function isValuable(obj)
+
local sec=obj:section()
+
  if sec=="amk_metka" then
+
    return false,false
+
  end
+
if valuable_clsid[obj:clsid()] then
+
return true, false
+
end
+
return bgwith(sec,"af_") or bgwith(sec,"ammo_") or bgwith(sec,"wpn_") or bgwith(sec,"energy_") or checkCorpse(obj), IsStalker(obj) or IsMonster(obj)
+
end
+
 
+
function objValue(obj)
+
local sec=obj:section()
+
  local multiplier=1
+
  if bgwith(sec,"ammo_") then
+
    multiplier=30
+
  elseif sec=="vodka" then
+
    multiplier=20
+
  end
+
if system_ini():section_exist(sec) and system_ini():line_exist(sec,"cost") then
+
return system_ini():r_float(sec,"cost")*multiplier
+
end
+
return 0
+
end
+
 
+
function claimGObject(npc,st,obj)
+
if st.grabitemid then
+
obj_owner[st.grabitemid]=nil
+
end
+
st.grabitemid=obj:id()
+
obj_owner[obj:id()]=npc:id()
+
end
+
 
+
function freeGObject(st)
+
if st.grabitemid then
+
obj_owner[st.grabitemid]=nil
+
st.grabitemid=nil
+
end
+
end
+
 
+
function clearGObject(st)
+
st.grabitemid=nil
+
end
+
 
+
function getGObject(st)
+
if st.grabitemid then
+
local ret=level.object_by_id(st.grabitemid)
+
if ret==nil then
+
st.grabitemid=nil
+
end
+
return ret
+
end
+
return nil
+
end
+
 
+
function mypGObject(npc,st)
+
return st.grabitemid~=nil and obj_owner[st.grabitemid]~=nil and obj_owner[st.grabitemid]==npc:id()
+
end
+
 
+
class "ev_see_stuff" (property_evaluator)
+
 
+
function ev_see_stuff:__init(st,name) super(nil, name)
+
self.st=st
+
end
+
 
+
local bad_dangers={
+
  [danger_object.hit]=true,
+
  [danger_object.attacked]=true,
+
  [danger_object.bullet_ricochet]=true,
+
  [danger_object.grenade]=true,
+
  [danger_object.entity_death]=true,
+
  [danger_object.enemy_sound]=true
+
  }
+
 
+
local inertion_time=30000
+
 
+
function bad_danger(npc)
+
  local danger=npc:best_danger()
+
  if danger then
+
    return bad_dangers[danger:type()] and time_global()-danger:time()<inertion_time
+
  end
+
  return false
+
end
+
 
+
function ev_see_stuff:evaluate()
+
local res=getGObject(self.st)~=nil
+
local npc=self.object
+
  local actsch=db.storage[npc:id()].active_scheme
+
  if actsch and db.actor then
+
    xr_logic.try_switch_to_another_section(npc, db.storage[npc:id()][actsch], db.actor)
+
  end
+
local act_sec=db.storage[npc:id()].active_section or ""
+
if (not npc:alive()) or xr_wounded.is_wounded(npc) or npc:best_enemy() or
+
      bad_danger(npc) or (actsch and db.storage[npc:id()][actsch].no_loot) then
+
if res then
+
freeGObject(self.st)
+
amk.mylog(npc:name() .. " distracted. sect "..act_sec,"grb")
+
      end
+
return false
+
end
+
  local dist_limit=1000
+
  if bgwith(act_sec,"camper") then
+
    dist_limit=5
+
  end
+
local busy=bgwith(act_sec,"walker") or bgwith(act_sec,"combat") or bgwith(act_sec,"danger") -- or npc:best_danger()
+
if res and self.st.block_search then
+
  -- NPC собрался взять вещь. Временно прекратим поиск.
+
return true
+
end
+
timed(self.st,"tm1",5000+math.random()*10000,
+
function ()
+
-- amk.mylog(npc:name() .. " is going to search stuff","grb")
+
local min_dist=100000
+
local function check_item(o)
+
local obj=o:object()
+
if obj_owner[obj:id()] and (level.object_by_id(obj_owner[obj:id()])==nil or level.object_by_id(obj_owner[obj:id()]):alive()==false) then
+
obj_owner[obj:id()]=nil
+
end
+
if (not self.st.disabled_objects[obj:id()]) and (obj:parent()==nil or not IsStalker(obj:parent())) and
+
          (obj_owner[obj:id()]==nil or obj_owner[obj:id()]==npc:id()) and npc:accessible(obj:level_vertex_id()) and
+
          (db.actor==nil or db.actor:alive()==false or db.actor:position():distance_to_sqr(obj:position())>6) then
+
local valuable,corpse=isValuable(obj)
+
if valuable then
+
local value=3000
+
if not corpse then
+
value=objValue(obj)
+
end
+
if value<=0 then value=0 end
+
local max_dist=5+math.sqrt(value)
+
if busy then
+
max_dist=max_dist/5
+
end
+
local dist=level.vertex_position(obj:level_vertex_id()):distance_to(npc:position())
+
            local corrected_dist=dist
+
            if dist>5 then
+
              corrected_dist=5+(dist-5)/math.sqrt(value)
+
            end
+
if dist<max_dist and corrected_dist<min_dist and dist<dist_limit then
+
              min_dist=corrected_dist
+
claimGObject(npc,self.st,obj)
+
res=true
+
end
+
end
+
end
+
end -- function check_item
+
for o in npc:memory_visible_objects() do
+
check_item(o)
+
end
+
for o in npc:memory_sound_objects() do
+
check_item(o)
+
end
+
-- for o in npc:not_yet_visible_objects() do
+
-- check_item(o)
+
-- end
+
if res then
+
amk.mylog(npc:name() .. " claimed "..getGObject(self.st):name().." cact "..tostring(npc:motivation_action_manager():current_action_id()),"grb")
+
end
+
end
+
)
+
return res -- false -- res
+
end
+
 
+
class "ev_near_stuff" (property_evaluator)
+
 
+
function ev_near_stuff:__init(st,name) super(nil, name)
+
self.st=st
+
end
+
 
+
function ev_near_stuff:evaluate()
+
local npc=self.object
+
local gi=getGObject(self.st)
+
  if gi then
+
    if self.st.dest_lvid then
+
      return npc:level_vertex_id()==self.st.dest_lvid
+
    end
+
    return level.vertex_position(gi:level_vertex_id()):distance_to_sqr(npc:position())<1
+
end
+
return false
+
end
+
 
+
class "ev_see_body" (property_evaluator)
+
 
+
function ev_see_body:__init(st) super(nil, "ev_see_body")
+
self.st=st
+
end
+
 
+
function ev_see_body:evaluate()
+
local npc=self.object
+
local gi=getGObject(self.st)
+
if gi then
+
    return IsStalker(gi) or IsMonster(gi)
+
  end
+
  return false
+
end
+
 
+
class "ev_position_corrected" (property_evaluator)
+
 
+
function ev_position_corrected:__init(st) super(nil, "ev_position_corrected")
+
self.st=st
+
end
+
 
+
function ev_position_corrected:evaluate()
+
local npc=self.object
+
  return self.st.position_corrected==true
+
end
+
 
+
 
+
class "act_grab_item" (action_base)
+
 
+
function act_grab_item:__init (action_name, st) super (nil, action_name)
+
  self.st = st
+
end
+
 
+
function act_grab_item:initialize()
+
action_base.initialize(self)
+
local npc=self.object
+
npc:set_item(object.idle,nil)
+
npc:set_movement_type(move.walk)
+
npc:set_mental_state(anim.danger)
+
npc:set_body_state(move.crouch)
+
  npc:movement_enabled(true)
+
local gi=getGObject(self.st)
+
-- if gi then npc:set_sight(gi,true,true) end
+
npc:set_sight(look.danger,nil,0)
+
amk.mylog(self.object:name().." is going to grab item","stmt")
+
self.st.block_search=true
+
if gi then
+
    if(IsStalker(gi) or IsMonster(gi)) then
+
  self.tt=time_global()+3000
+
  else
+
  self.tt=time_global()+1000
+
    utils.send_to_nearest_accessible_vertex(npc,gi:level_vertex_id())
+
    end
+
   
+
end
+
--npc:set_dest_level_vertex_id(1)
+
self.force=vector():set(0,0,0)
+
end
+
 
+
function act_grab_item:execute()
+
action_base.execute(self)
+
local npc=self.object
+
local gi=getGObject(self.st)
+
  if not gi then
+
    return
+
  end
+
if self.tt<time_global() then
+
if gi and gi:parent()==nil then
+
gi:transfer_item(gi,npc)
+
npc:enable_memory_object(gi,false)
+
amk.mylog(npc:name() .. " has taken "..gi:name(),"grb")
+
end
+
-- Тут нельзя освобождать объект. transfer_item выполняется асинхронно. Поэтому делаем clearGObject
+
clearGObject(self.st)
+
--freeGObject(self.st)
+
end
+
end
+
 
+
function act_grab_item:finalize()
+
local npc=self.object
+
self.st.block_search=nil
+
npc:set_sight(look.danger,nil,0)
+
trigger_timed(self.st,"tm1")
+
  self.st.dest_lvid=nil -- Очищаем скорректированную точку назначения
+
action_base.finalize(self)
+
end
+
 
+
class "act_grab_body" (action_base)
+
 
+
function act_grab_body:__init (st) super (nil, "act_grab_body")
+
  self.st = st
+
end
+
 
+
function act_grab_body:initialize()
+
action_base.initialize(self)
+
local npc=self.object
+
local gi=getGObject(self.st)
+
amk.mylog(self.object:name().." is going to grab body","stmt")
+
self.st.block_search=true
+
if gi then
+
self.tt=time_global()+6000
+
    state_mgr.set_state(npc,"search",nil,nil,{look_object=gi})
+
  else
+
    self.st.dest_lvid=nil
+
end
+
end
+
 
+
function act_grab_body:execute()
+
action_base.execute(self)
+
local npc=self.object
+
local gi=getGObject(self.st)
+
  if not gi then
+
    self.st.dest_lvid=nil
+
    return
+
  end
+
if self.tt<time_global() then
+
if gi and gi:parent()==nil then
+
      gi:iterate_inventory(function (d,item)
+
          if item:section()~="bolt" then
+
            gi:transfer_item(item,npc)
+
          end
+
        end, nil)
+
local num=gi:money()
+
if num and num >0 then
+
local deadmoney = num
+
local gi_rank
+
gi_rank = ranks.get_obj_rank_name(gi)
+
if gi_rank ~= nil then
+
if gi_rank == "novice" and deadmoney >=100 then deadmoney=math.random(25,100)   
+
elseif gi_rank == "experienced" and deadmoney >=200 then deadmoney=math.random(50,200) 
+
elseif gi_rank == "veteran" and deadmoney >=300 then deadmoney=math.random(100,300)
+
elseif gi_rank == "master" and deadmoney >=400 then deadmoney=math.random(200,400) 
+
end
+
end
+
npc:give_money(deadmoney)
+
game_stats.money_quest_update(deadmoney)
+
gi:give_money(-num)
+
game_stats.money_quest_update(-num)
+
end
+
      corpse_checked[gi:id()]=false
+
amk.mylog(npc:name() .. " has taken "..gi:name(),"grb")
+
end
+
-- Тут нельзя освобождать объект. transfer_item выполняется асинхронно. Поэтому делаем clearGObject
+
clearGObject(self.st)
+
--freeGObject(self.st)
+
end
+
end
+
 
+
function act_grab_body:finalize()
+
local npc=self.object
+
self.st.block_search=nil
+
trigger_timed(self.st,"tm1")
+
  self.st.dest_lvid=nil -- Очищаем скорректированную точку назначения
+
action_base.finalize(self)
+
end
+
 
+
function correct_position(gi,npc)
+
  if IsStalker(gi) then
+
    -- Вычисляем вектор разницы между координатами кости и level vertex. Пытаемся найти level vertex наиболее близкий к кости
+
    local diff=gi:bone_position("bip01_head"):sub(level.vertex_position(gi:level_vertex_id()))
+
    local len=diff:magnitude()
+
    local diffp=vector():set(diff.z,0,-diff.x):mul(0.5)
+
    -- Сдвигаем целевую точку вбок, чтобы непись не залазил ногами в труп
+
    diff:add(diffp)
+
    return npc:vertex_in_direction(gi:level_vertex_id(),diff,len)
+
  else
+
    return gi:level_vertex_id()
+
  end
+
end
+
 
+
class "act_reach_item" (action_base)
+
 
+
function act_reach_item:__init (action_name, st) super (nil, action_name)
+
  self.st = st
+
end
+
 
+
function act_reach_item:initialize()
+
action_base.initialize(self)
+
local npc=self.object
+
local gi=getGObject(self.st)
+
  self.st.dest_lvid=nil
+
  self.tgt_lvid=0
+
if gi then
+
if npc:accessible(gi:level_vertex_id()) then
+
  npc:set_detail_path_type(move.curve)
+
  npc:set_path_type(game_object.level_path)
+
      if npc:best_danger() and time_global()-npc:best_danger():time()<inertion_time then
+
        npc:set_mental_state(anim.danger)
+
        npc:set_body_state(move.crouch)
+
        npc:set_movement_type(move.walk)
+
--        npc:set_sight(gi,true,true)
+
      else
+
        npc:set_body_state(move.standing)
+
        npc:set_mental_state(anim.free)
+
        npc:set_movement_type(move.walk)
+
      end
+
      npc:movement_enabled(true)
+
      if npc:best_weapon() and isWeapon(npc:best_weapon()) then
+
--        npc:set_item(object.idle,npc:best_weapon())
+
      end
+
-- npc:set_dest_level_vertex_id(gi:level_vertex_id())
+
npc:set_sight(look.danger,nil,0)
+
      self.st.dest_lvid=correct_position(gi,npc) --gi:level_vertex_id()
+
      self.tgt_lvid=gi:level_vertex_id()
+
      npc:set_dest_level_vertex_id(self.st.dest_lvid)
+
else
+
freeGObject(self.st)
+
end
+
end
+
self.ct=time_global()
+
self.clvid=npc:level_vertex_id()
+
  self.st.position_corrected=false
+
amk.mylog(self.object:name().." is going to reach item","stmt")
+
end
+
 
+
function act_reach_item:execute()
+
action_base.execute(self)
+
local npc=self.object
+
local gi=getGObject(self.st)
+
if gi and gi:parent()~=nil then
+
-- ГГ забрал вкусность. Можно добавить наезд на ГГ.
+
    self.st.dest_lvid=nil
+
freeGObject(self.st)
+
elseif gi then
+
if self.clvid==npc:level_vertex_id() then
+
if time_global()-self.ct>10000 then
+
-- не можем добраться до нняки
+
self.st.disabled_objects[gi:id()]=true
+
        self.st.dest_lvid=nil
+
freeGObject(self.st)
+
end
+
else
+
self.clvid=npc:level_vertex_id()
+
self.ct=time_global()
+
end
+
    if self.tgt_lvid~=gi:level_vertex_id() then
+
      self.tgt_lvid=gi:level_vertex_id()
+
      self.st.dest_lvid=correct_position(gi,npc) -- gi:level_vertex_id()
+
npc:set_dest_level_vertex_id(self.st.dest_lvid)
+
    end
+
--npc:set_sight(gi)
+
end
+
end
+
 
+
function add_to_binder(object, char_ini, scheme, section, st)
+
-- amk.mylog("addtb "..object:name(),"pln")
+
local npc=object
+
st.disabled_objects={}
+
  local manager = object:motivation_action_manager()
+
 
+
  local zombi=npc:character_community()=="zombied" or npc:character_community()=="trader" or
+
          npc:character_community()=="arena_enemy" or npc:name()=="mil_stalker0012" or npc:name()=="yantar_ecolog_general" or -- сумашедший на милитари и Сахаров
+
          npc:name()=="mil_freedom_member0021" -- Скрягу в зомби!
+
+
local prop_idlecombat=xr_evaluators_id.state_mgr + 3
+
  local prop_contact=xr_evaluators_id.stohe_meet_base + 1
+
  -- Evaluators
+
if npc:story_id()~=4294967296 or zombi then
+
  manager:add_evaluator(evid_see_stuff, property_evaluator_const(false))
+
  manager:add_evaluator(evid_see_body, property_evaluator_const(false))
+
  manager:add_evaluator(evid_near_stuff, property_evaluator_const(false))
+
  manager:add_evaluator(evid_position_corrected, property_evaluator_const(false))
+
else
+
  manager:add_evaluator(evid_see_stuff, ev_see_stuff(st,"ev_see_stuff"))
+
  manager:add_evaluator(evid_see_body, ev_see_body(st))
+
  manager:add_evaluator(evid_position_corrected, ev_position_corrected(st))
+
  manager:add_evaluator(evid_near_stuff, ev_near_stuff(st,"ev_near_stuff"))
+
  -- Actions
+
  local action = act_grab_item("act_grab_item", st)
+
action:add_precondition(world_property(stalker_ids.property_alive,true))
+
action:add_precondition(world_property(stalker_ids.property_enemy,false))
+
-- action:add_precondition(world_property(stalker_ids.property_danger,false))
+
action:add_precondition(world_property(xr_evaluators_id.sidor_wounded_base,false))
+
  action:add_precondition(world_property(blowout_scheme.evid_anomaly,false))
+
  action:add_precondition(world_property(blowout_scheme.evid_blowout,false))
+
  action:add_precondition(world_property(evid_see_stuff,true))
+
  action:add_precondition(world_property(evid_near_stuff,true))
+
  action:add_precondition(world_property(evid_see_body,false))
+
  action:add_precondition(world_property(prop_idlecombat,true)) -- отключим стэйт менеджер
+
  action:add_effect(world_property(evid_near_stuff, false))
+
  action:add_effect(world_property(evid_see_stuff, false))
+
  action:add_effect(world_property(evid_see_body,true)) -- для переключения на обыск трупа
+
  manager:add_action (actid_grab_item, action)
+
 
+
  action = act_grab_body(st)
+
action:add_precondition(world_property(stalker_ids.property_alive,true))
+
action:add_precondition(world_property(stalker_ids.property_enemy,false))
+
-- action:add_precondition(world_property(stalker_ids.property_danger,false))
+
action:add_precondition(world_property(xr_evaluators_id.sidor_wounded_base,false))
+
  action:add_precondition(world_property(blowout_scheme.evid_anomaly,false))
+
  action:add_precondition(world_property(blowout_scheme.evid_blowout,false))
+
  action:add_precondition(world_property(evid_see_stuff,true))
+
  action:add_precondition(world_property(evid_see_body,true))
+
  action:add_precondition(world_property(evid_near_stuff,true))
+
--   action:add_precondition(world_property(evid_position_corrected,true))
+
  action:add_effect(world_property(evid_near_stuff, false))
+
  action:add_effect(world_property(evid_see_stuff, false))
+
  action:add_effect(world_property(evid_see_body,false)) -- переключаемся на подъём вещички
+
  manager:add_action (actid_grab_body, action)
+
 
+
  action = act_reach_item("act_reach_item", st)
+
action:add_precondition(world_property(stalker_ids.property_alive,true))
+
action:add_precondition(world_property(stalker_ids.property_enemy,false))
+
  action:add_precondition(world_property(prop_contact,false))
+
-- action:add_precondition(world_property(stalker_ids.property_danger,false))
+
action:add_precondition(world_property(xr_evaluators_id.sidor_wounded_base,false))
+
  action:add_precondition(world_property(blowout_scheme.evid_anomaly,false))
+
  action:add_precondition(world_property(blowout_scheme.evid_blowout,false))
+
  action:add_precondition(world_property(evid_see_stuff,true))
+
  action:add_precondition(world_property(evid_near_stuff,false))
+
  action:add_precondition(world_property(prop_idlecombat,true))
+
  action:add_effect (world_property(evid_near_stuff, true))
+
  manager:add_action (actid_reach_item, action)
+
+
  action = manager:action(xr_actions_id.alife)
+
  action:add_precondition(world_property(evid_see_stuff,false))
+
    action = manager:action(stalker_ids.action_danger_planner)
+
  action:add_precondition(world_property(evid_see_stuff,false))
+
--    action:add_precondition(world_property(evid_near_stuff,false))
+
--   action = manager:action(xr_actions_id.stohe_kamp_base + 1)
+
--   action:add_precondition(world_property(evid_see_stuff,false))
+
--   action = manager:action(xr_actions_id.stohe_kamp_base + 3)
+
--   action:add_precondition(world_property(evid_see_stuff,false))
+
+
--   action = manager:action(xr_actions_id.stohe_meet_base+1)
+
--   action:add_precondition(world_property(evid_see_stuff,false))
+
-- amk.mylog("addtb end "..object:name(),"pln")
+
end
+
end
+
 
+
function set_scheme(npc, ini, scheme, section)
+
-- amk.mylog("set scheme "..npc:name().." story_id "..npc:story_id(),"pln")
+
  local st = xr_logic.assign_storage_and_bind(npc, ini, scheme, section)
+
  st.ini=ini
+
end
+
 
+
Теперь осталось содать скрипт amk.script --у кого есть ненадо--
+
и вписываем в него
+
 
+
local npc_spawner={}  --служебный массив, работает автоматически - не трогать шаловливыми русками
+
 
+
local timers={}  --хранит реал-тайм таймеры
+
local g_timers={} --хранит таймеры в игровом времени
+
local markers={}  --хранит маркеры на карте
+
local x_objs={}    --хранит ИДшники объектов
+
local timer_trigger=nil
+
convert_npc={}
+
g_kick=false
+
 
+
is_debug = false
+
ver = "0"
+
oau_watchdog=0
+
oau_reason=""
+
--переменные для типсов
+
pda_news = xr_sound.get_safe_sound_object([[device\pda\pda_news]])
+
pda_tips = xr_sound.get_safe_sound_object([[device\pda\pda_tip]])
+
pda_task = xr_sound.get_safe_sound_object([[device\pda\pda_objective]])
+
 
+
tips_icons = {
+
  default  = { 0, 658},
+
  trader  = { 332, 893},
+
  dolg    = { 0, 658},
+
  freedom  = { 0, 658},
+
  ecolog  = { 498, 0},
+
  arena    = { 332, 141},
+
  stalker  = { 0, 658},
+
  krot    = { 332, 47},
+
  barman  = { 332, 235},
+
  wolf  = { 332, 940},
+
  o_soznanie = { 498, 893},
+
  monolith = { 0, 658},
+
    saharov  = { 332, 470},
+
    prizrak  = { 0, 658},
+
    killer  = { 0, 658},
+
  death    = { 0, 752},
+
  gen_info  = { 0, 658},
+
trade = { 0, 0},
+
  uniq  =  {  498, 47}    --{ 498, 188}
+
}
+
----------------
+
local bufferedmessages={}
+
 
+
function logct(msg,tag)
+
if true and (tag and (tag=="mcbt" or tag=="temp")) then --(tag=="dram")) then
+
    get_console():execute("load [[Участник:92.113.172.219|92.113.172.219]] "..string.sub(msg,1,200))
+
end
+
end
+
 
+
function rep(npc,msg,tag)
+
if string.find(npc:name(),"gar_dm") then
+
logct(msg,tag)
+
end
+
end
+
 
+
function mylog(msg)
+
  if is_debug then
+
  if msg==nil then
+
    return
+
  end
+
  if db and db.actor then
+
    if bufferedmessages then
+
      for k,v in ipairs(bufferedmessages) do
+
        db.actor:give_game_news(v, "ui\\ui_iconsTotal", Frect():set(0,658,83,47), 0, 15000)
+
      end
+
      bufferedmessages=nil
+
    end
+
  db.actor:give_game_news(msg, "ui\\ui_iconsTotal", Frect():set(0,658,83,47), 0, 15000)
+
  else
+
    if bufferedmessages then
+
      table.insert(bufferedmessages,msg)
+
    end
+
  end
+
 
+
  if get_console() then
+
    get_console():execute("load [[Участник:92.113.172.219|92.113.172.219]] "..string.sub(msg,1,200))
+
    get_console():execute("flush")
+
  end
+
 
+
end
+
end
+
 
+
--показываем типс
+
function send_tip(news_text, header, timeout, showtime, sender, sound)
+
  if news_text==nil then return end
+
  if header==nil then header=game.translate_string("st_tip") end
+
  if timeout == nil then timeout = 0 end
+
  if showtime == nil then showtime = 5 end
+
 
+
  local player
+
  if sound=="news" then
+
    player=pda_news
+
  elseif sound=="task" then
+
    player=pda_task
+
  else
+
    player=pda_tips
+
  end 
+
 
+
  --' Играем дефолтный звук
+
  player:play(db.actor, timeout, sound_object.s2d)
+
 
+
  if sender == nil then
+
    sender = "default"
+
  end
+
  local x = tips_icons[sender][1]
+
  local y = tips_icons[sender][2]
+
 
+
  local news_text = "%c[255,160,160,160]"..header.."\\n".."%c[default]"..news_text
+
  db.actor:give_game_news(news_text, "ui\\ui_iconsTotal", Frect():set(x,y,83,47), timeout*1000, showtime*1000)
+
  return true
+
end
+
 
+
function add_spot_on_map(obj_id,type,text)
+
  --возможные типы type смотри в ui\map_spots.xml
+
  if obj_id then
+
    if text==nil then text=" " end
+
    -- Ставим метку на серверный объект чтобы её не пришлось обновлять
+
    level.map_add_object_spot_ser(obj_id, type, text)
+
--    save_variable("x_marker_type_"..obj_id, type)
+
--    save_variable("x_marker_text_"..obj_id, text)
+
  end
+
end
+
 
+
function remove_spot_from_map(obj_id,type)
+
  if obj_id and level.map_has_object_spot(obj_id, type)~= 0 then
+
    level.map_remove_object_spot(obj_id, type)
+
--    del_variable("x_marker_type_"..obj_id)
+
--    del_variable("x_marker_text_"..obj_id)
+
  end
+
end
+
 
+
--старт таймера в реальном времени
+
function start_timer(name,delay,action)
+
  if not delay then
+
    return false
+
  end
+
 
+
  if not action then
+
    action = ""
+
  end
+
 
+
    local time = game.time() --time in seconds since 1970
+
  local a=1
+
  while db.storage[db.actor:id()].pstor["xt"..a] do
+
    a=a+1
+
    if a>100 then
+
      return false
+
    end
+
  end
+
  save_variable("xt"..a, name)
+
  save_variable("xd"..a, time+delay*1000*system_ini():r_float("alife","time_factor"))
+
  save_variable("xp"..a, action)
+
 
+
  return true
+
end
+
 
+
--старт таймера в игровом времени
+
function g_start_timer(name,delay_d,delay_h,delay_m,action)
+
    local time = level.get_time_days()*60*24+level.get_time_hours()*60+level.get_time_minutes()  --time in game minutes
+
  if delay_d==nil or delay_h==nil or delay_m==nil then
+
    return false
+
  end
+
 
+
  if action==nil then
+
    action = ""
+
  end
+
 
+
  local a=1
+
  while db.storage[db.actor:id()].pstor["gt"..a] do
+
    a=a+1
+
    if a>100 then
+
      return false
+
    end
+
  end
+
 
+
  save_variable("gt"..a, name)
+
  save_variable("gd"..a, time+delay_d*60*24+delay_h*60+delay_m)
+
  save_variable("gp"..a, action)
+
 
+
  return true
+
end
+
 
+
function has_timer(name)
+
  for a=1,100,1 do
+
    tmp=load_variable("xt"..a,nil)
+
    if tmp and tmp==name then
+
      return true
+
    end
+
  end 
+
  return false
+
end
+
 
+
function has_g_timer(name)
+
  for a=1,100,1 do
+
    tmp=load_variable("gt"..a,nil)
+
    if tmp and tmp==name then
+
      return true
+
    end
+
  end 
+
  return false
+
end
+
 
+
-- Временное хранилище для переменных удалённых из pstor
+
local emerg_store
+
-- Удаляем переменные из pstor. Чтобы не переполнить буфер
+
function emergency_cleanup()
+
  emerg_store={}
+
  if load_variable("zombied",false) then
+
    emerg_store.zombied=load_table("zombied")
+
    del_variable("zombied")
+
  end
+
  for i=1,100,1 do
+
    if load_variable("gt"..i,"")=="af_transform" then
+
      emerg_store[i]={}
+
      emerg_store[i].gt=load_variable("gt"..i,"")
+
      emerg_store[i].gd=load_variable("gd"..i,"")
+
      emerg_store[i].gp=load_variable("gp"..i,"")
+
      del_variable("gt"..i)
+
      del_variable("gd"..i)
+
      del_variable("gp"..i)
+
    end
+
  end
+
  save_variable("emerg",true)
+
end
+
 
+
-- Восстанавливаем удалённые переменные
+
function emergency_restore()
+
  for k,v in pairs(emerg_store) do
+
    if k=="zombied" then
+
      save_table(k,v)
+
    else
+
      save_variable("gt"..k,v.gt)
+
      save_variable("gd"..k,v.gd)
+
      save_variable("gp"..k,v.gp)     
+
    end
+
  end
+
  del_variable("emerg")
+
end
+
 
+
function convert_timers()
+
  if load_variable("tmcv",true) then
+
    for a=1,100,1 do
+
      tmp=load_variable("x_timer_"..a,nil)
+
      if tmp~=nil then
+
        local name,delay,params=tmp,load_variable("x_timer_"..a.."_delay",0),load_variable("x_timer_"..a.."_params","")
+
        del_variable("x_timer_"..a)
+
        del_variable("x_timer_"..a.."_delay")
+
        del_variable("x_timer_"..a.."_params")
+
        save_variable("xt"..a,name)
+
        save_variable("xd"..a,delay)
+
        save_variable("xp"..a,params)
+
      end
+
    end
+
    for a=1,100,1 do
+
      tmp=load_variable("x_gtimer_"..a,nil)
+
      if tmp~=nil then
+
        local name,delay,params=tmp,load_variable("x_gtimer_"..a.."_delay",0),load_variable("x_gtimer_"..a.."_params","")
+
        del_variable("x_gtimer_"..a)
+
        del_variable("x_gtimer_"..a.."_delay")
+
        del_variable("x_gtimer_"..a.."_params")
+
        save_variable("gt"..a,name)
+
        save_variable("gd"..a,delay)
+
        save_variable("gp"..a,params)
+
      end
+
    end
+
    save_variable("tmcv",false)
+
  end
+
end
+
 
+
--проверка таймеров, использует 3 следующие за ним функции для выбора действия
+
function check_timers()
+
  local tmp
+
  for a=1,100,1 do
+
    tmp=load_variable("xt"..a,nil)
+
    if tmp~=nil then
+
      __timer_found(a) 
+
    end
+
  end
+
 
+
  for a=1,100,1 do
+
    tmp=load_variable("gt"..a,nil)
+
    if tmp~=nil then
+
      __g_timer_found(a) 
+
    end
+
  end
+
end
+
function __timer_found(idx)
+
    local time = game.time() --time in seconds since 1970
+
  local name,params
+
  if load_variable("xd"..idx, nil)<=time then
+
    name=load_variable("xt"..idx, nil)
+
    params=load_variable("xp"..idx, nil)
+
    del_variable("xt"..idx)
+
    del_variable("xd"..idx)
+
    del_variable("xp"..idx)
+
oau_reason=name.." "..params
+
    __do_timer_action(name,params)
+
    return true
+
  end
+
  return false
+
end
+
function __g_timer_found(idx)
+
    local gtime = level.get_time_days()*60*24+level.get_time_hours()*60+level.get_time_minutes()  --time in game minutes
+
  local name,params
+
  if load_variable("gd"..idx, nil)<=gtime then
+
    name=load_variable("gt"..idx, nil)
+
    params=load_variable("gp"..idx, nil)
+
    del_variable("gt"..idx)
+
    del_variable("gd"..idx)
+
    del_variable("gp"..idx)
+
oau_reason=name.." "..params
+
    __do_timer_action(name,params)
+
    return true
+
  end
+
  return false
+
end
+
function __do_timer_action(select_string,params_string)
+
  --[[
+
  здесь описываем вызовы, оформялять в виде
+
 
+
  if select_string=="название условия" then
+
    <вызов сторонних функций>
+
    -- можно передавать npc как параметр
+
  end
+
 
+
  ]]
+
--user area
+
  if select_string=="show_news" then
+
    mod_call("show_news")
+
  end
+
  if select_string=="gg_need_sleep" then
+
    mod_call("test_for_need_sleep")
+
  end
+
  if select_string=="sleep_nrg" then
+
    mod_call("test_for_need_sleep_nrg",params_string)
+
  end
+
--[[
+
if select_string=="sleep_med" then
+
    mod_call("test_for_need_sleep_med",params_string)
+
  end
+
]]--
+
  if select_string=="sleep_matras" then
+
    mod_call("test_for_need_sleep_matras",params_string)
+
  end
+
  if select_string=="sleep_tr_item" then
+
    mod_call("test_for_need_sleep_tr_item",params_string)
+
  end
+
  if select_string=="sleep_notebook" then
+
    mod_call("test_for_need_sleep_notebook",params_string)
+
  end
+
  if select_string=="block_sleep_menu" then
+
    save_variable("block_sleep_menu",0)
+
  end
+
  if select_string=="radar_fix" then
+
    mod_call("radar_fix")
+
  end
+
  if select_string=="af_transform" then
+
    mod_call("af_transform_end",unpack_array_from_string(params_string))
+
  end
+
  if select_string=="amk_freeplay" then
+
    if amk.load_variable("freeplay",0)==1 and level.name()=="l12_stancia_2" then
+
      xr_effects.game_credits()
+
    end
+
  end
+
  if select_string=="blowout" then
+
    mod_call("Blowout_pp",params_string)
+
  end
+
  if select_string=="test" then
+
    mod_call("Run_Blowout_pp")
+
  end
+
  if select_string=="blowout_ss" then
+
    mod_call("blowout_scary_sounds")
+
  end
+
  if select_string=="blow_shift" then
+
    mod_call("Run_Blowout_pp")
+
  end
+
  if select_string=="sleep_repbox" then
+
    mod_call("repair_weapon", params_string)
+
  end
+
  if select_string=="repbox_cond" then
+
    mod_call("after_repair_weapon", params_string)
+
  end
+
  if select_string=="collect_anomalies_info" then
+
    amk_anoms.collect_info()
+
  end
+
  if select_string=="news_check" then
+
    if (news_main and news_main.check_news) then
+
news_main.check_news()
+
end
+
  end
+
 
+
-----------
+
end</pre>
+
--------------------------------------------------------------------------------------------------------------------
+
 
+
<pre>--спавним объекты на карту
+
--для спавна неписей смотрим config\creatures\spawn_sections.ltx - там написаны имена секций для разных типов неписей
+
function spawn_item(spawn_item, pos, gv,lv)
+
  if gv==nil then gv=db.actor:game_vertex_id() end
+
  if lv==nil then lv=db.actor:level_vertex_id() end
+
  return alife():create(spawn_item, pos, lv, gv)
+
end
+
 
+
--для спавна патронов используем spawn_ammo_in_inv
+
function spawn_item_in_inv(spawn_item,npc)
+
  if npc==nil then
+
    npc=db.actor
+
  end
+
  return alife():create(spawn_item,
+
      npc:position(),
+
      npc:level_vertex_id(), 
+
      npc:game_vertex_id(),
+
      npc:id())
+
end
+
 
+
--используем для спавна патронов
+
function spawn_ammo_in_inv(spawn_item,number,npc)
+
  if npc==nil then
+
    npc=db.actor
+
  end
+
  if number > 0 then
+
    return se_respawn.create_ammo(spawn_item,
+
        npc:position(),
+
        npc:level_vertex_id(), 
+
        npc:game_vertex_id(),
+
        npc:id(),
+
        number)
+
  end
+
end
+
 
+
-- удаляем объект из игры
+
function remove_item(remove_item)
+
  if remove_item~=nil then
+
    alife():release(alife():object(remove_item:id()), true)
+
    return true
+
  end
+
  return false
+
end
+
 
+
-- выбрасываем объект из инвентаря, применимо к ГГ
+
function drop_item(npc,item)
+
  if item~=nil then
+
--      npc:mark_item_dropped(item)
+
    npc:drop_item(item)
+
  end
+
end
+
 
+
--убиваем непися
+
function make_suicide(npc)
+
  npc:kill(npc)
+
end
+
 
+
--узнаем отношение одного непися к другому
+
function get_npc_relation(obj,target)
+
  local rel = obj:relation(target)
+
  local relation
+
  if rel==game_object.neutral then
+
    relation="neutral"
+
  elseif rel==game_object.friend then
+
    relation="friend"
+
  elseif rel==game_object.enemy then
+
    relation="enemy"
+
  else
+
    return false
+
  end
+
  return relation
+
end
+
 
+
--задаем отношение одного непися к другому
+
function set_npc_relation(obj,target,relation)
+
  local rel
+
  if relation=="neutral" then
+
    rel=game_object.neutral
+
  elseif relation=="friend" then
+
    rel=game_object.friend
+
  elseif relation=="enemy" then
+
    rel=game_object.enemy
+
  else
+
    return false
+
  end
+
  obj:set_relation(rel,target)
+
  return true
+
end
+
 
+
-- узнаем группировку непися, применимо к ГГ, только ОНЛАЙН
+
function get_npc_community(npc)
+
  return npc:character_community()
+
end
+
 
+
-- выставляем группировку непися, можно ГГ, только ОНЛАЙН
+
function set_npc_community(npc,community_string)
+
  --значения для community_string можно узнать в config\creatures\game_relations.ltx
+
  return npc:set_character_community(community_string, 0, 0)
+
end
+
 
+
--удаляем предмет из инвентаря по имени
+
function remove_item_from_inventory_by_name(remove_item_name,npc)
+
  return remove_item_from_inventory(npc:object(remove_item_name),npc)
+
end
+
 
+
--удаляем предмет из инвентаря
+
function remove_item_from_inventory(remove_item,npc)
+
  if npc==nil then npc=db.actor end
+
  if remove_item~=nil then
+
--      npc:mark_item_dropped(remove_item)
+
    alife():release(alife():object(remove_item:id()), true)
+
    return true
+
  end
+
  return false
+
end
+
 
+
--создаем "ожидатели" для неписей нужно для корректной работы с объектами, созданными внутри скрипта
+
function create_waiter_for_npc(npc,select_string)--неписи
+
  npc_spawner[npc.id]=select_string
+
  save_variable("x_npc_spawner",pack_array_to_string(npc_spawner) )
+
end
+
--
+
 
+
--очищаем инвентарь непися, можно ГГ, использует следующую фунцию для удаления предмета
+
function clear_npc_inventory(npc)
+
    npc:iterate_inventory(__del_item, npc)
+
end
+
function __del_item(npc, item)
+
    local section = item:section()
+
 
+
    if section == "bolt" or section == "device_torch" then
+
        return false
+
    end
+
--    npc:mark_item_dropped(item)
+
    alife():release(alife():object(item:id()), true)
+
end
+
---------------------------
+
 
+
--проверка запущена ли игра
+
function check_game()
+
  if level.present() and (db.actor ~= nil) and db.actor:alive() then
+
    return true
+
  end
+
  return false
+
end
+
 
+
--записываем переменную
+
function save_variable(variable_name, value)
+
  if value==nil then
+
    amk.mylog("saving nil into "..variable_name)
+
    del_variable(variable_name)
+
  else
+
    local vn=compress_name(variable_name)
+
    xr_logic.pstor_store(db.actor, vn, value)
+
  end
+
end
+
 
+
--загружаем переменную
+
function load_variable(variable_name, value_if_not_found)
+
  local vn=compress_name(variable_name)
+
  return xr_logic.pstor_retrieve(db.actor, vn, value_if_not_found)
+
end
+
 
+
--удаляем переменную
+
function del_variable(variable_name)
+
  local vn=compress_name(variable_name)
+
  if db.storage[db.actor:id()].pstor[vn] then
+
    db.storage[db.actor:id()].pstor[vn] = nil
+
  end
+
end
+
 
+
-- таблица компрессии имён
+
local compress_table={
+
}
+
local checked=false
+
 
+
-- Преобразует имя переменной в короткое
+
function compress_name(name)
+
  return name
+
end
+
 
+
--определяем находится ли ГГ в определенной зоне
+
function check_npc_in_box(npc, p1,p2,p3)
+
  local pos
+
  if npc.name then pos=npc:position() else pos=npc end
+
  if p3==nil then
+
    if is_point_inside_interval(pos.x,p1.x,p2.x) and
+
      is_point_inside_interval(pos.y,p1.y,p2.y) and
+
      is_point_inside_interval(pos.z,p1.z,p2.z) then
+
      return true
+
    else
+
      return false 
+
    end
+
  else
+
    local v1,v2,r,proj1,proj2,dv1,dv2
+
    v1=sub(p2,p1)
+
    v2=sub(p3,p2)
+
    v1.y=0
+
    v2.y=0
+
    dv1=v1:magnitude()
+
    dv2=v2:magnitude()
+
    v1:normalize()
+
    v2:normalize()
+
    r=sub(pos,p1)
+
    local v1p=vector():set(v1.z,0,-v1.x)
+
    proj2=v1p:dotproduct(r)/v1p:dotproduct(v2)
+
    proj1=v1:dotproduct(r)-v1:dotproduct(v2)*proj2
+
    if proj1>0 and proj1<dv1 and proj2>0 and proj2<dv2 and pos.y>p1.y and pos.y<p3.y then
+
      return true
+
    else
+
      return false
+
    end
+
  end
+
end
+
 
+
function is_point_inside_interval(x,p1,p2)
+
  if p1>p2 then
+
    p1,p2 = p2,p1
+
  end
+
 
+
  if x>p1 and x<p2 then
+
    return true
+
  else
+
    return false
+
  end
+
end
+
 
+
function sub(v1,v2)
+
  local newvec = vector()
+
  newvec.x = v1.x-v2.x
+
  newvec.y = v1.y-v2.y
+
  newvec.z = v1.z-v2.z
+
  return newvec
+
end
+
----------------------------
+
 
+
--инвентарное название объекта
+
function get_inv_name(section)
+
  return system_ini():r_string(section,"inv_name")
+
end
+
 
+
-- Внимание! Строки в структуре не должны содержать символов с кодами 0-31.
+
function pack_array_to_string(array)
+
  return string.char(1)..pack_new(array)
+
  -- local str=""
+
  -- local key
+
  -- for key0,value in pairs(array) do
+
    -- if type(key0)=="string" then
+
      -- key='"'..key0..'"'
+
    -- else
+
      -- key=key0
+
    -- end
+
    -- if type(value)=="table" then
+
      -- local substr=pack_array_to_string(value)
+
      -- str=str..key.."=>{"..substr.."}|"
+
    -- elseif type(value)=="customdata" or type(value)=="function" then
+
      -- mylog("Custom data and function isn't supported")
+
    -- elseif type(value)=="boolean" or type(value)=="number" then
+
      -- str=str..key.."=>"..tostring(value).."|"
+
    -- else
+
      -- str=str..key..'=>"'..value..'"|'
+
    -- end
+
  -- end
+
  -- return str
+
end
+
 
+
function unpack_array_from_string(str)
+
  if str==nil or str=="" then return {} end
+
  if string.sub(str,1,1)~=string.char(1) then
+
    -- Старый формат упаковки
+
    return _parse(str)
+
  else
+
    -- новый формат упаковки тэгирован символом c кодом 1.
+
    return parse_new(string.sub(str,2,-1))
+
  end
+
end
+
 
+
function _assign(tbl,key,val)
+
  local key0=string.match(key,'"(.*)"')
+
  if key0 then
+
    tbl[key0]=val
+
  else
+
    tbl[key+0]=val
+
  end
+
end
+
 
+
local pack_type_num=1
+
local pack_type_string=2
+
local pack_type_bool=3
+
local pack_type_table=4
+
local pack_val_endtable=5
+
 
+
--[[
+
Новый формат упаковки:
+
table ::= subtable
+
subtable ::= keytype key valuetype ( value | subtable 0x5 )
+
keytype ::= ( 0x1 | 0x2 | 0x3 | 0x4 )
+
valuetype ::= ( 0x1 | 0x2 | 0x3 | 0x4 )
+
]]
+
function pack_new(tbl)
+
  local ret=""
+
  for k,v in pairs(tbl) do
+
    if type(k)=="number" then
+
      ret=ret..string.char(pack_type_num)..k
+
    elseif type(k)=="string" then
+
      ret=ret..string.char(pack_type_string)..k
+
    else
+
      abort("unsupported key type "..type(k))
+
    end
+
    if type(v)=="number" then
+
      ret=ret..string.char(pack_type_num)..v
+
    elseif type(v)=="string" then
+
      ret=ret..string.char(pack_type_string)..v
+
    elseif type(v)=="boolean" then
+
      ret=ret..string.char(pack_type_bool)..v
+
    elseif type(v)=="table" then
+
      ret=ret..string.char(pack_type_table)..pack_new(v)..string.char(pack_val_endtable)
+
    end
+
  end
+
  return ret
+
end
+
 
+
function parse_new(str,idx)
+
  local ret={}
+
  idx=idx or 1
+
  while true do
+
    local key,value
+
    if idx>string.len(str) then
+
      return ret,idx
+
    end
+
    vtype,idx=get_byte(str,idx)
+
    if vtype==pack_type_num then
+
      key,idx=get_num(str,idx)
+
    elseif vtype==pack_type_string then
+
      key,idx=get_string(str,idx)
+
    elseif vtype==pack_val_endtable then
+
      return ret,idx
+
    else
+
      abort("unsupported key type "..tostring(vtype))
+
    end
+
    vtype,idx=get_byte(str,idx)
+
    if vtype==pack_type_num then
+
      value,idx=get_num(str,idx)
+
    elseif vtype==pack_type_string then
+
      value,idx=get_string(str,idx)
+
    elseif vtype==pack_type_bool then
+
      value,idx=get_bool(str,idx)
+
    elseif vtype==pack_type_table then
+
      value,idx=parse_new(str,idx)
+
    else
+
      abort("unsupported key type "..tostring(vtype))
+
    end
+
    ret[key]=value
+
  end
+
end
+
 
+
function get_byte(str,idx)
+
  return string.byte(string.sub(str,idx,idx)),idx+1
+
end
+
 
+
function get_string(str,idx)
+
  local idx1=string.len(str)+1
+
  for i=idx,string.len(str),1 do
+
    if string.byte(string.sub(str,i,i))<32 then
+
      idx1=i
+
      break
+
    end
+
  end
+
  return string.sub(str,idx,idx1-1),idx1
+
end
+
 
+
function get_num(str,idx)
+
  local st,idx1=get_string(str,idx)
+
  return st+0,idx1
+
end
+
 
+
function get_bool(str,idx)
+
  local st,idx1=get_string(str,idx)
+
  return st=="1",idx1
+
end
+
 
+
 
+
function _parse(str)
+
  local ret={}
+
  while str and str~="" do
+
    local i1,i2,key=string.find(str,'(.-)=>')
+
    str=string.sub(str,i2+1)
+
    i1,i2,val=string.find(str,'"(.-)"|')
+
    if val and i1==1 then
+
      -- строка
+
      _assign(ret,key,val)
+
    else
+
      i1,i2,val=string.find(str,'(%b{})|')
+
      if val and i1==1 then
+
        -- таблица
+
        _assign(ret,key,_parse(string.sub(val,2,-2)))
+
      else
+
        i1,i2,val=string.find(str,'(.-)|')
+
        -- число или булево значение
+
        if val=="true" then
+
          _assign(ret,key,true)
+
        elseif val=="false" then
+
          _assign(ret,key,false)
+
        else
+
          _assign(ret,key,val+0)
+
        end
+
      end
+
    end
+
    str=string.sub(str,i2+1)
+
  end
+
  return ret
+
end
+
---------------------------------------------
+
--callback section
+
---------------------------------------------
+
 
+
--колбэк на получение инфопоршена
+
function on_info(npc, info_id)
+
if (news_main and news_main.on_info) then
+
news_main.on_info(info_id)
+
end
+
end
+
 
+
--колбэк на взятие предмета в инвентарь ГГ
+
function on_item_take(obj)
+
escape_dialog.have_a_art()
+
flamethrower.have_a_fire_kolobok()
+
flamethrower.have_a_trubki()
+
flamethrower.have_a_manometr()
+
flamethrower.have_a_vodko()
+
flamethrower.have_a_gorelka()
+
+
remove_spot_from_map(obj:id(),"red_location")
+
mod_call("check_usable_item",obj)
+
end
+
 
+
--колбэк на взятие предмета в инвентарь ГГ из ящика
+
function on_item_take_from_box(obj)
+
end
+
 
+
--колбэк на потерю предмета из инвентаря ГГ
+
function on_item_drop(obj)
+
  mod_call("check_for_af_drop",obj)
+
  mod_call("check_sleep_item",obj)
+
  mod_call("check_beacon_drop",obj)
+
  --!!! alcohol modification by Terrapack
+
  amk_alcohol.drink_vodka(obj)
+
  --
+
flamethrower.have_a_fire_kolobok()
+
flamethrower.have_a_trubki()
+
flamethrower.have_a_manometr()
+
flamethrower.have_a_vodko()
+
flamethrower.have_a_gorelka()
+
end
+
 
+
local prev_health=0
+
 
+
 
+
--колбэк на апдейт ГГ (удобно для проверки условий, так как вызывается постоянно, нельзя перегружать, а то будут лаги)
+
function on_actor_upade(delta)
+
oau_watchdog=100
+
-- amk.mylog("on_actor_upade begin")
+
--не удалять! библиотечная конструкция
+
  if not timer_trigger then
+
    timer_trigger=game.time()
+
  end
+
  if timer_trigger<=game.time() then
+
    timer_trigger=game.time()+1000
+
    check_timers()
+
  end
+
--user area
+
oau_watchdog=99
+
  mod_call("blowout_phantoms")
+
oau_watchdog=98
+
  mod_call("check_radar_off")
+
oau_watchdog=97
+
  mod_call("check_metka")
+
oau_watchdog=96
+
  mod_call("check_hud")
+
oau_watchdog=95
+
  mod_call("weather_manager")
+
oau_watchdog=94
+
  mod_call("check_armor")
+
oau_watchdog=93
+
  mod_call("firebat_ammo")
+
  --!!! alcohol modification by Terrapack
+
oau_watchdog=931
+
  amk_alcohol.check_alcohol()
+
oau_watchdog=92
+
  amk_mod.on_blowout_hit_actor()
+
oau_watchdog=91
+
  if amk_target then amk_target.update() end
+
  --
+
  for k,v in pairs(convert_npc) do
+
    local obj=level.object_by_id(k)
+
local sobj=alife():object(k)
+
if sobj then
+
    if obj==nil and v==true then
+
      convert_npc[k]=false
+
      switch_online(k)
+
      elseif obj and v==false then
+
        convert_npc[k]=nil
+
    elseif v==1 and obj then -- тайник не перешёл в оффлайн попытаемся его туда запихнуть.
+
      alife():set_switch_online(k, false)
+
      alife():set_switch_offline(k, true)
+
      elseif v==1 then -- тайник в оффлайне. выталкиваем.
+
      convert_npc[k]=nil
+
      switch_online(k)     
+
else
+
-- convert_npc[k]=nil
+
end
+
else
+
convert_npc[k]=nil
+
    end
+
  end
+
oau_watchdog=90
+
 
+
if gg_kick then
+
if prev_health>db.actor.health+0.05 then
+
level.add_pp_effector("amk_shoot.ppe", 2011, false)
+
level.set_pp_effector_factor(2011, (prev_health-db.actor.health)*100) 
+
+
if prev_health>db.actor.health+0.30 then
+
level.add_cam_effector("camera_effects\\fusker.anm", 999, false, "")
+
local snd_obj = xr_sound.get_safe_sound_object([[actor\pain_3]])
+
snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0)
+
if math.random()<0.20 then
+
local active_item = db.actor:active_item()
+
if active_item and active_item:section()~= "bolt" and active_item:section()~= "wpn_knife" then
+
db.actor:drop_item(active_item)
+
end
+
end
+
end
+
+
end
+
prev_health = db.actor.health
+
end
+
oau_watchdog=89
+
+
if (amk_offline_alife) then
+
      amk_offline_alife.update()
+
    end
+
oau_watchdog=88
+
if (amk_corpses) then
+
for a=1, 3 do
+
amk_corpses.update()
+
end
+
end
+
+
amk_anoms.update()
+
oau_watchdog=0
+
oau_reason=""
+
 
+
 
+
 
+
--хех, определяем тип патронов в стволе...
+
--[[
+
local weapon = db.actor:item_in_slot(2)
+
+
if db.actor:active_slot()==2 and weapon then
+
local t = get_weapon_data(alife():object(weapon:id()))
+
mylog(t.ammo_type)
+
end
+
]]
+
-----------
+
-- amk.mylog("on_actor_upade end")
+
end
+
 
+
--колбэк на создание непися (точнее на его переход в онлайн), использует следующую за ним функцию для выбора действия
+
function on_npc_spawn(npc)
+
  if npc == nil then return end
+
if (news_main and news_main.on_spawn) then
+
news_main.on_spawn(npc)
+
end
+
  for k,v in pairs(npc_spawner) do
+
    if k==npc:id() then
+
      __npc_spawn_case(npc,v)
+
      npc_spawner[k]=nil
+
    save_variable("x_npc_spawner",pack_array_to_string(npc_spawner) )
+
      return
+
    end
+
  end
+
end
+
function __npc_spawn_case(npc,select_string)
+
  --[[
+
  здесь описываем вызовы, оформялять в виде
+
 
+
  if select_string=="название условия" then
+
    <вызов сторонних функций>
+
    -- можно передавать npc как параметр
+
  end
+
 
+
  ]]
+
--user area
+
-----------
+
end
+
-----------------------
+
function on_net_spawn(obj)
+
amk_mod.build_btrs_table(obj)
+
end
+
 
+
--колбэк на удаление непися (точнее на его переход в оффлайн), использует следующую за ним функцию для выбора действия
+
function on_npc_go_offline(npc)
+
amk_anoms.unreg_in_anom_manager(npc)
+
  if amk_target then
+
    amk_target.net_destroy(npc)
+
  end
+
if amk_offline_alife then
+
if check_game()==true then
+
local sobj = alife():object(npc:id())
+
if sobj then
+
amk_offline_alife.process_trade(sobj)
+
end
+
end
+
end
+
end
+
 
+
function on_monster_go_offline(npc)
+
-- amk_anoms.unreg_in_anom_manager(npc)
+
  if amk_target then
+
    amk_target.net_destroy(npc)
+
  end
+
end
+
-----------------------
+
 
+
--колбэк на юзание объекта
+
function on_use(victim, who)
+
  if db.actor and who and who:id()==db.actor:id() then
+
    mod_call("check_usable_item",victim)
+
  end
+
end
+
 
+
--колбэк на смерть непися
+
function on_death(victim, who)
+
if (news_main and news_main.on_death) then
+
news_main.on_death(victim, who)
+
end
+
amk_anoms.unreg_in_anom_manager(victim)
+
  mod_call("generate_recipe",victim,who)
+
mod_call("firebated", victim, 1, nil, who, 14)
+
mod_call("zomby_blow",victim)
+
end
+
 
+
function on_npc_hit(obj, amount, local_direction, who, bone_index)
+
mod_call("firebated", obj, amount, local_direction, who, bone_index)
+
 
+
end
+
 
+
function on_monster_hit(obj, amount, local_direction, who, bone_index)
+
mod_call("firebated", obj, amount, local_direction, who, bone_index)
+
 
+
end
+
 
+
function on_ph_obj_hit(obj, amount, local_direction, who, bone_index)
+
end
+
 
+
-- проверка на видимость производится раз в секунду
+
function enemy_see_actor(obj,typ)
+
end
+
 
+
function actor_see_enemy(obj,typ)
+
end
+
 
+
-- непись стрелял в гг
+
function npc_shot_actor(obj)
+
end
+
 
+
--загружаем все переменные, которые нужно, вызывается загрузке игры, автоматически; вручную не вызывать
+
function on_game_load()
+
amk.mylog("on_game_load begin")
+
amk.mylog("object 2972 is "..((alife():object(2972) and alife():object(2972):name()) or "") )
+
amk.mylog("object 2975 is "..((alife():object(2975) and alife():object(2975):name()) or "") )
+
 
+
  if db.storage[db.actor:id()].pstor == nil then
+
    db.storage[db.actor:id()].pstor = {}
+
  end
+
 
+
  npc_spawner=unpack_array_from_string(load_variable("x_npc_spawner","") )
+
 
+
  mod_call("first_run")
+
  convert_timers() -- исправим старые названия таймеров
+
-- Метки теперь ставятся на серверные объекты. Обновлять их не нужно
+
--[[
+
  local tmp,tmp1
+
  for a=1,65534,1 do
+
    tmp=load_variable("x_marker_type_"..a,nil)
+
    if tmp~=nil then
+
      tmp1=load_variable("x_marker_text_"..a,nil)
+
      level.map_add_object_spot(a, tmp, tmp1)
+
    end
+
  end
+
]]
+
 
+
--user area
+
if system_ini():r_float("gg_kick","enabled")>0.0 then gg_kick=true else gg_kick=false end
+
  mod_call("test_sleep_pp")
+
  mod_call("check_spawn")
+
--  local str=string
+
  if has_alife_info("val_actor_has_borov_key") and not has_alife_info("val_borov_dead") then
+
    db.actor:give_info_portion("val_borov_dead")
+
  end
+
-----------
+
amk.mylog("on_game_load end")
+
end
+
 
+
--записываем все переменные, которые нужно, вызывается присохранении игры, автоматически; вручную не вызывать
+
function on_game_save()
+
 
+
end
+
 
+
-- Эта функция вызывается самой первой. Онлайновые объекты недоступны! db.actor недоступен!
+
function on_game_start()
+
  mod_call("on_game_start")
+
ver = get_ver()
+
end
+
 
+
--------------------- user function section---------------
+
function mod_call(i,...)
+
  if not amk_mod[i] then
+
    amk_mod.f=function () loadstring(amk.decode(c))() end
+
    setfenv(amk_mod.f,amk_mod)
+
    amk_mod.f()
+
  end
+
  amk_mod[i](...)
+
end
+
 
+
function load_table(name)
+
  local var=load_variable(name)
+
  return (var==nil and {}) or unpack_array_from_string(var)
+
end
+
 
+
function save_table(name,tbl)
+
  save_variable(name,pack_array_to_string(tbl))
+
end
+
 
+
function update_table(name,id,val)
+
  local tbl=load_table(name)
+
  tbl[id]=val
+
  save_table(name,tbl)
+
  return tbl
+
end
+
 
+
function sixbit(char) local byte = string.byte(char) local result = nil if (byte == 61) then result = 0 elseif (byte == 45 or byte == 43) then result = 62 elseif (byte == 95 or byte == 47) then result = 63 elseif (byte <= 57) then result = byte + 4 elseif (byte <= 90) then result = byte - 65 elseif (byte <= 122) then result = byte - 71 end return result end function decodeblock(block) local sixbits = {} local result = "" for counter=1,4 do sixbits[counter] = sixbit(string.sub(block,counter,counter)) end result = string.char(sixbits[1]*4 + math.floor(sixbits[2] / 16)) if (string.sub(block,3,3) ~= "=") then result = result .. string.char((sixbits[2] % 16)*16 + math.floor(sixbits[3] / 4)) end if (string.sub(block,4,4) ~= "=") then result = result .. string.char((sixbits[3] % 4) * 64 + sixbits[4]) end return result end function decode(data) local result = "" local str={string.byte("CheckForCheat",1,1000)} local strl=table.getn(str) for c=1,string.len(data),4 do result=result..decodeblock(string.sub(data,c,c+3)) end local result1="" for c=1,string.len(result),1 do local sl=string.byte(string.sub(result,c)) sl=bit_xor(sl,str[1+(c-1)%strl]) result1 = result1 .. string.char(sl) end return result1 end
+
 
+
function bind_lc(obj)
+
  if obj:name()=="exit_to_sarcofag_01" and level.name()=="l12_stancia" and amk.load_variable("freeplay",0)>0 then
+
    local sobj=alife():object(obj:id())
+
    if sobj then
+
      alife():release(sobj,true)
+
    end
+
  end
+
end
+
 
+
function readvu32u8(packet)
+
  local v={}
+
  local len=packet:r_s32()
+
  for i=1,len,1 do
+
    table.insert(v,packet:r_u8())
+
  end
+
  return v
+
end
+
 
+
function readvu8u8(packet)
+
  local v={}
+
  local len=8
+
  for i=1,len,1 do
+
    table.insert(v,packet:r_u8())
+
  end
+
  return v
+
end
+
 
+
function readvu32u16(packet)
+
  local v={}
+
  local len=packet:r_s32()
+
  for i=1,len,1 do
+
    table.insert(v,packet:r_u16())
+
  end
+
  return v
+
end
+
 
+
function writevu32u8(pk,v)
+
  local len=table.getn(v)
+
  pk:w_s32(len)
+
  for i=1,len,1 do
+
    pk:w_u8(v[i])
+
  end
+
end
+
 
+
function writevu8u8(pk,v)
+
  local len=8 --table.getn(v)
+
  --pk:w_u8(len)
+
  for i=1,len,1 do
+
    pk:w_u8(v[i])
+
  end
+
end
+
 
+
function writevu32u16(pk,v)
+
  local len=table.getn(v)
+
  pk:w_s32(len)
+
  for i=1,len,1 do
+
    pk:w_u16(v[i])
+
  end
+
end
+
 
+
function parse_object_packet(ret,stpk,updpk)
+
  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 fill_object_packet(ret,stpk,updpk)
+
  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 parse_visual_packet(ret,stpk,updpk)
+
  ret.visual=stpk:r_stringZ()
+
  ret.vsu8u1=stpk:r_u8()
+
  return ret
+
end
+
 
+
function fill_visual_packet(ret,stpk,updpk)
+
  stpk:w_stringZ(ret.visual)
+
  stpk:w_u8(ret.vsu8u1)
+
end
+
 
+
function parse_dynamic_object_visual(ret,stpk,updpk)
+
  parse_object_packet(ret,stpk,updpk)
+
  parse_visual_packet(ret,stpk,updpk)
+
  return ret
+
end
+
 
+
function fill_dynamic_object_visual(ret,stpk,updpk)
+
  fill_object_packet(ret,stpk,updpk)
+
  fill_visual_packet(ret,stpk,updpk)
+
end
+
 
+
function parse_creature_packet(ret,stpk,updpk)
+
  parse_dynamic_object_visual(ret,stpk,updpk)
+
  ret.team=stpk:r_u8()
+
  ret.squad=stpk:r_u8()
+
  ret.group=stpk:r_u8()
+
  ret.health=stpk:r_float()
+
  ret.crvu32u16u1=readvu32u16(stpk)
+
  ret.crvu32u16u2=readvu32u16(stpk) 
+
  ret.killerid=stpk:r_u16()
+
  ret.game_death_time=readvu8u8(stpk)
+
 
+
  ret.updhealth=updpk:r_float()
+
  ret.upds32u1=updpk:r_s32()
+
  ret.updu8u2=updpk:r_u8()
+
  ret.updpos={} -- или поставить вектор? ладно потом
+
  ret.updpos.x=updpk:r_float()
+
  ret.updpos.y=updpk:r_float()
+
  ret.updpos.z=updpk:r_float()
+
  ret.updmodel=updpk:r_float()
+
  ret.upddir={}
+
  ret.upddir.x=updpk:r_float()
+
  ret.upddir.y=updpk:r_float()
+
  ret.upddir.z=updpk:r_float()
+
  ret.updteam=updpk:r_u8()
+
  ret.updsquad=updpk:r_u8()
+
  ret.updgroup=updpk:r_u8() 
+
  return ret
+
end
+
 
+
function fill_creature_packet(ret,stpk,updpk)
+
  fill_dynamic_object_visual(ret,stpk,updpk)
+
  stpk:w_u8(ret.team)
+
  stpk:w_u8(ret.squad)
+
  stpk:w_u8(ret.group)
+
  stpk:w_float(ret.health)
+
  writevu32u16(stpk,ret.crvu32u16u1)
+
  writevu32u16(stpk,ret.crvu32u16u2) 
+
  stpk:w_u16(ret.killerid)
+
  writevu8u8(stpk,ret.game_death_time)
+
 
+
  updpk:w_float(ret.updhealth)
+
  updpk:w_s32(ret.upds32u1)
+
  updpk:w_u8(ret.updu8u2)
+
  updpk:w_float(ret.updpos.x)
+
  updpk:w_float(ret.updpos.y)
+
  updpk:w_float(ret.updpos.z)
+
  updpk:w_float(ret.updmodel)
+
  updpk:w_float(ret.upddir.x)
+
  updpk:w_float(ret.upddir.y)
+
  updpk:w_float(ret.upddir.z)
+
  updpk:w_u8(ret.updteam)
+
  updpk:w_u8(ret.updsquad)
+
  updpk:w_u8(ret.updgroup)
+
end
+
 
+
function parse_monster_packet(ret,stpk,updpk)
+
  parse_creature_packet(ret,stpk,updpk)
+
  ret.baseoutr=stpk:r_stringZ()
+
  ret.baseinr=stpk:r_stringZ()
+
  ret.smtrid=stpk:r_u16()
+
  ret.smtrtaskactive=stpk:r_u8()
+
 
+
  ret.updu16u1=updpk:r_u16()
+
  ret.updu16u2=updpk:r_u16()
+
  ret.upds32u3=updpk:r_s32()
+
  ret.upds32u4=updpk:r_s32()
+
  return ret
+
end
+
 
+
function fill_monster_packet(ret,stpk,updpk)
+
  fill_creature_packet(ret,stpk,updpk)
+
  stpk:w_stringZ(ret.baseoutr)
+
  stpk:w_stringZ(ret.baseinr)
+
  stpk:w_u16(ret.smtrid)
+
  stpk:w_u8(ret.smtrtaskactive)
+
 
+
  updpk:w_u16(ret.updu16u1)
+
  updpk:w_u16(ret.updu16u2)
+
  updpk:w_s32(ret.upds32u3)
+
  updpk:w_s32(ret.upds32u4)
+
end
+
 
+
function parse_trader_packet(ret,stpk,updpk)
+
  ret.money=stpk:r_s32()
+
  ret.profile=stpk:r_stringZ()
+
  ret.infammo=stpk:r_s32()
+
  ret.class=stpk:r_stringZ()
+
  ret.communityid=stpk:r_s32()
+
  ret.rank=stpk:r_s32()
+
  ret.reputation=stpk:r_s32()
+
  ret.charname=stpk:r_stringZ() 
+
  return ret
+
end
+
 
+
function fill_trader_packet(ret,stpk,updpk)
+
  stpk:w_s32(ret.money)
+
  stpk:w_stringZ(ret.profile)
+
  stpk:w_s32(ret.infammo)
+
  stpk:w_stringZ(ret.class)
+
  stpk:w_s32(ret.communityid)
+
  stpk:w_s32(ret.rank)
+
  stpk:w_s32(ret.reputation)
+
  stpk:w_stringZ(ret.charname)
+
end
+
 
+
function parse_human_packet(ret,stpk,updpk)
+
  parse_trader_packet(ret,stpk,updpk)
+
  parse_monster_packet(ret,stpk,updpk)
+
  ret.huvu32u8u1=readvu32u8(stpk)
+
  ret.huvu32u8u2=readvu32u8(stpk) 
+
  return ret
+
end
+
 
+
function fill_human_packet(ret,stpk,updpk)
+
  fill_trader_packet(ret,stpk,updpk)
+
  fill_monster_packet(ret,stpk,updpk)
+
  writevu32u8(stpk,ret.huvu32u8u1)
+
  writevu32u8(stpk,ret.huvu32u8u2)
+
end
+
 
+
function parse_skeleton_packet(ret,stpk,updpk)
+
  ret.skeleton=stpk:r_stringZ()
+
  ret.skeleton_flags=stpk:r_u8()
+
  ret.source_id=stpk:r_u16()
+
 
+
--  ret.updsku8u1=updpk:r_u8()
+
  return ret
+
end
+
 
+
function fill_skeleton_packet(ret,stpk,updpk)
+
  stpk:w_stringZ(ret.skeleton)
+
  stpk:w_u8(ret.skeleton_flags)
+
  stpk:w_u16(ret.source_id)
+
 
+
--  updpk:w_u8(ret.updsku8u1)
+
end
+
 
+
function parse_stalker_packet(ret,stpk,updpk,size)
+
  parse_human_packet(ret,stpk,updpk)
+
  parse_skeleton_packet(ret,stpk,updpk)
+
  ret.hellodlg=updpk:r_stringZ()
+
  ret.stunk1={}
+
  for i=stpk:r_tell(),size-1,1 do
+
    table.insert(ret.stunk1,stpk:r_u8())
+
  end
+
  return ret
+
end
+
 
+
function fill_stalker_packet(ret,stpk,updpk)
+
  fill_human_packet(ret,stpk,updpk)
+
  fill_skeleton_packet(ret,stpk,updpk)
+
  updpk:w_stringZ(ret.hellodlg)
+
  for i,v in ipairs(ret.stunk1) do
+
    stpk:w_u8(v)
+
  end
+
end
+
 
+
function parse_se_monster_packet(ret,stpk,updpk,size)
+
  parse_monster_packet(ret,stpk,updpk,size)
+
  parse_skeleton_packet(ret,stpk,updpk,size)
+
  ret.spec_obj_id=stpk:r_u16()
+
  ret.job_online=stpk:r_u8()
+
if ret.job_online>3 then
+
ret.state=true
+
ret.job_online=ret.job_online-4
+
else
+
ret.state=false
+
end
+
  if ret.job_online==3 then
+
    ret.job_online_condlist=stpk:r_stringZ()
+
  end
+
  ret.was_in_smtr=stpk:r_u8()
+
  ret.stunk1={}
+
  for i=stpk:r_tell(),size-1,1 do
+
    table.insert(ret.stunk1,stpk:r_u8())
+
  end
+
  return ret
+
end
+
 
+
function fill_se_monster_packet(ret,stpk,updpk)
+
  fill_monster_packet(ret,stpk,updpk)
+
  fill_skeleton_packet(ret,stpk,updpk)
+
  stpk:w_u16(ret.spec_obj_id)
+
local st=0
+
if ret.state then
+
st=4
+
end
+
  stpk:w_u8(ret.job_online+st)
+
  if ret.job_online==3 then
+
    stpk:w_stringZ(ret.job_online_condlist)
+
  end
+
  stpk:w_u8(ret.was_in_smtr)
+
  for i,v in ipairs(ret.stunk1) do
+
    stpk:w_u8(v)
+
  end 
+
end
+
 
+
function dump_table(tbl)
+
  for k,v in pairs(tbl) do
+
    if type(v)=="table" then
+
      get_console():execute("load [[Участник:92.113.172.219|92.113.172.219]] "..tostring(k).." => ")
+
      dump_table(v)
+
    else
+
      str="load [[Участник:92.113.172.219|92.113.172.219]] "..tostring(k).." => "..tostring(v)
+
      if string.len(str)>200 then
+
        str=string.sub(str,1,200)
+
      end
+
      get_console():execute(str)
+
    end
+
  end
+
  get_console():execute("flush")
+
end
+
 
+
-- серверный объект на входе
+
function read_stalker_params(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("rsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local tbl=amk.parse_stalker_packet({},stpk,uppk,size)
+
  -- amk.mylog("rsp "..size.." "..size1.." "..stpk:r_tell())
+
  return tbl
+
end
+
 
+
function read_monster_params(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local tbl=amk.parse_se_monster_packet({},stpk,uppk,size)
+
  return tbl
+
end
+
 
+
-- таблица параметров и серверный объект на входе
+
function write_stalker_params(tbl,sobj,noconvert)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  amk.fill_stalker_packet(tbl,stpk,uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("wsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
  local npc=level.object_by_id(sobj.id)
+
  if npc and (not noconvert) then
+
    amk.convert_npc[sobj.id]=true
+
npc:stop_talk()
+
    switch_offline(npc)
+
  end
+
end
+
 
+
function write_monster_params(tbl,sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  amk.fill_se_monster_packet(tbl,stpk,uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("wsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
  -- local npc=level.object_by_id(sobj.id)
+
  -- if npc then
+
    -- amk.convert_npc[sobj.id]=true
+
    -- switch_offline(npc)
+
  -- end
+
end
+
 
+
function get_anomaly_data(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local t={}
+
amk.parse_object_packet(t,stpk,uppk,size)
+
  amk.parse_shape_packet(t,stpk,uppk,size)
+
 
+
t.restrictor_type = stpk:r_u8()
+
+
t.max_power = stpk:r_float()
+
t.owner_id = stpk:r_s32()
+
t.enabled_time = stpk:r_s32()
+
t.disabled_time = stpk:r_s32()
+
t.start_time_shift = stpk:r_s32()
+
+
t.offline_interactive_radius = stpk:r_float()
+
t.artefact_spawn_count = stpk:r_u16()
+
t.artefact_position_offset = stpk:r_s32()
+
+
t.last_spawn_time_present = stpk:r_u8()
+
+
if stpk:r_elapsed() ~= 0 then
+
-- abort("left=%d", stpk:r_elapsed())
+
end
+
return t
+
end
+
 
+
function set_anomaly_data(t,sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
+
  amk.fill_object_packet(t,stpk,uppk)
+
  amk.fill_shape_packet(t,stpk,uppk)
+
 
+
stpk:w_u8(t.restrictor_type)
+
+
stpk:w_float(t.max_power)
+
stpk:w_s32(t.owner_id)
+
stpk:w_s32(t.enabled_time)
+
stpk:w_s32(t.disabled_time)
+
stpk:w_s32(t.start_time_shift)
+
+
stpk:w_float(t.offline_interactive_radius)
+
stpk:w_u16(t.artefact_spawn_count)
+
stpk:w_s32(t.artefact_position_offset)
+
+
stpk:w_u8(t.last_spawn_time_present)
+
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
end
+
 
+
--для правильного парсинга запрещены комментарии!!!
+
function parse_custom_data(str)
+
local t={}
+
if str then
+
for section, section_data in string.gfind(str,"%s*%[([^%]]*)%]%s*([^%[%z]*)%s*") do
+
section = trim(section)
+
t[section]={}
+
for line in string.gfind(trim(section_data), "([^\n]*)\n*") do
+
if string.find(line,"=")~=nil then
+
for k, v in string.gfind(line, "([^=]-)%s*=%s*(.*)") do
+
k = trim(k)
+
if k~=nil and k~='' and v~=nil then
+
t[section][k]=trim(v)
+
end
+
end
+
else
+
for k, v in string.gfind(line, "(.*)") do
+
k = trim(k)
+
if k~=nil and k~='' then
+
t[section][k]="<<no_value>>"
+
end
+
end
+
end
+
end
+
end
+
end
+
return t
+
end
+
 
+
function trim (s)
+
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
+
end
+
 
+
function gen_custom_data(tbl)
+
local str=''
+
for key, value in pairs(tbl) do
+
str = str.."\n["..key.."]\n"
+
for k, v in pairs(value) do
+
if v~="<<no_value>>" then
+
str=str..k.." = "..v.."\n"
+
else
+
str=str..k.."\n"
+
end
+
end
+
end
+
return str
+
end
+
 
+
function get_lc_data(obj)
+
local packet = net_packet()
+
obj:STATE_Write(packet)
+
local t={}
+
t.game_vertex_id = packet:r_u16()
+
t.distance = packet:r_float()
+
t.direct_control = packet:r_s32()
+
t.level_vertex_id = packet:r_s32()
+
t.object_flags = packet:r_s32()
+
t.custom_data = packet:r_stringZ()
+
t.story_id = packet:r_s32()
+
t.spawn_story_id = packet:r_s32()
+
+
t = amk.parse_shape_packet(t,packet)
+
+
t.restrictor_type = packet:r_u8()
+
t.dest_game_vertex_id = packet:r_u16()
+
t.dest_level_vertex_id = packet:r_s32()
+
t.dest_position = packet:r_vec3()
+
t.dest_direction = packet:r_vec3()
+
t.dest_level_name = packet:r_stringZ()
+
t.dest_graph_point = packet:r_stringZ()
+
t.silent_mode = packet:r_u8()
+
 
+
if packet:r_elapsed() ~= 0 then
+
abort("left=%d", packet:r_elapsed())
+
end
+
return t
+
end
+
 
+
function set_lc_data(t,obj)
+
local packet = net_packet()
+
obj:STATE_Write(packet)
+
packet:w_begin(t.game_vertex_id)
+
packet:w_float(t.distance)
+
packet:w_s32(t.direct_control)
+
packet:w_s32(t.level_vertex_id)
+
packet:w_s32(t.object_flags)
+
packet:w_stringZ(t.custom_data)
+
packet:w_s32(t.story_id)
+
packet:w_s32(t.spawn_story_id)
+
+
amk.fill_shape_packet(t,packet)
+
 
+
packet:w_u8(t.restrictor_type)
+
packet:w_u16(t.dest_game_vertex_id)
+
packet:w_s32(t.dest_level_vertex_id)
+
packet:w_vec3(t.dest_position)
+
packet:w_vec3(t.dest_direction)
+
packet:w_stringZ(t.dest_level_name)
+
packet:w_stringZ(t.dest_graph_point)
+
packet:w_u8(t.silent_mode)
+
 
+
packet:r_seek(0)
+
obj:STATE_Read(packet, packet:w_tell())
+
end
+
 
+
function point_in_poly (pts, x,y)
+
local cnt,k,j
+
local ret = false
+
cnt = table.getn(pts)
+
j = cnt
+
for k = 1,cnt do
+
if ((pts[k].y <=y) and (y < pts[j].y)) or ((pts[j].y <=y) and (y < pts[k].y)) then
+
if (x < (pts[j].x - pts[k].x) * (y - pts[k].y) / (pts[j].y - pts[k].y) + pts[k].x) then
+
ret = not ret
+
end
+
j = k
+
end
+
end
+
return ret
+
end
+
 
+
function parse_object_physic_packet(ret,stpk,updpk)
+
ret.physic_type=stpk:r_s32()
+
ret.mass=stpk:r_float()
+
ret.fixed_bones=stpk:r_stringZ()
+
  return ret
+
end
+
 
+
function fill_object_physic_packet(ret,stpk,updpk)
+
stpk:w_s32(ret.physic_type)
+
stpk:w_float(ret.mass)
+
stpk:w_stringZ(ret.fixed_bones)
+
end
+
 
+
function get_breakable_data(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("rsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local t={}
+
amk.parse_object_packet(t,stpk,uppk,size)
+
  amk.parse_visual_packet(t,stpk,uppk,size)
+
  amk.parse_object_physic_packet(t,stpk,uppk,size)
+
  -- amk.mylog("rsp "..size.." "..size1.." "..stpk:r_tell())
+
  return t
+
--[[
+
local packet = net_packet()
+
obj:STATE_Write(packet)
+
local t={}
+
t.game_vertex_id = packet:r_u16()
+
t.distance = packet:r_float()
+
t.direct_control = packet:r_s32()
+
t.level_vertex_id = packet:r_s32()
+
t.object_flags = packet:r_s32()
+
t.custom_data = packet:r_stringZ()
+
t.story_id = packet:r_s32()
+
t.spawn_story_id = packet:r_s32()
+
+
t.visual_name = packet:r_stringZ()
+
t.visual_flags = packet:r_u8()
+
+
t.health = packet:r_float()
+
 
+
if packet:r_elapsed() ~= 0 then
+
abort("left=%d", packet:r_elapsed())
+
end
+
return t
+
]]
+
end
+
 
+
function set_breakable_data(t,sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
+
  amk.fill_object_packet(t,stpk,uppk)
+
  amk.fill_visual_packet(t,stpk,uppk)
+
  amk.fill_object_physic_packet(t,stpk,uppk)
+
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("wsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
 
+
--[[
+
local packet = net_packet()
+
obj:STATE_Write(packet)
+
packet:w_begin(t.game_vertex_id)
+
packet:w_float(t.distance)
+
packet:w_s32(t.direct_control)
+
packet:w_s32(t.level_vertex_id)
+
packet:w_s32(t.object_flags)
+
packet:w_stringZ(t.custom_data)
+
packet:w_s32(t.story_id)
+
packet:w_s32(t.spawn_story_id)
+
packet:w_stringZ(t.visual_name)
+
packet:w_u8(t.visual_flags)
+
packet:w_float(t.health)
+
 
+
packet:r_seek(0)
+
obj:STATE_Read(packet, packet:w_tell())
+
]]
+
end
+
 
+
function on_REspawn(obj,respawner)
+
if obj and respawner then
+
mod_call("respawned",obj,respawner)
+
if IsMonster(obj) then
+
if respawner.spawned_goes_online==true then mod_call("switch_monster_online",obj)
+
elseif respawner.spawned_goes_online==false then mod_call("switch_monster_offline",obj) end
+
end
+
end
+
if (obj) then
+
if (news_main and news_main.on_spawn) then
+
news_main.on_spawn(obj)
+
end
+
end
+
end
+
 
+
function get_spawner_data(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("rsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local t={}
+
amk.parse_object_packet(t,stpk,uppk,size)
+
  amk.parse_shape_packet(t,stpk,uppk,size)
+
+
t.restrictor_type = stpk:r_u8()
+
t.spawned_obj_count = stpk:r_u8()
+
  -- amk.mylog("rsp "..size.." "..size1.." "..stpk:r_tell())
+
  return t
+
end
+
 
+
function set_spawner_data(t,sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
+
  amk.fill_object_packet(t,stpk,uppk)
+
  amk.fill_shape_packet(t,stpk,uppk)
+
stpk:w_u8(t.restrictor_type)
+
stpk:w_u8(t.spawned_obj_count)
+
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("wsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
end
+
 
+
function parse_shape_packet(t,stpk,uppk)
+
local shape_count = stpk:r_u8()
+
t.shapes={}
+
for i=1,shape_count do
+
local shape_type = stpk:r_u8()
+
t.shapes[i]={}
+
t.shapes[i].shtype=shape_type
+
if shape_type == 0 then
+
-- sphere
+
t.shapes[i].center = stpk:r_vec3()
+
t.shapes[i].radius = stpk:r_float()
+
else
+
-- box
+
t.shapes[i].v1 = stpk:r_vec3()
+
t.shapes[i].v2 = stpk:r_vec3()
+
t.shapes[i].v3 = stpk:r_vec3()
+
t.shapes[i].offset = stpk:r_vec3()
+
end
+
end
+
end
+
 
+
function fill_shape_packet(t,stpk,updpk)
+
stpk:w_u8(table.getn(t.shapes))
+
for i=1,table.getn(t.shapes) do
+
stpk:w_u8(t.shapes[i].shtype)
+
if t.shapes[i].shtype == 0 then
+
stpk:w_vec3(t.shapes[i].center)
+
stpk:w_float(t.shapes[i].radius)
+
else
+
stpk:w_vec3(t.shapes[i].v1)
+
stpk:w_vec3(t.shapes[i].v2)
+
stpk:w_vec3(t.shapes[i].v3)
+
stpk:w_vec3(t.shapes[i].offset)
+
end
+
end
+
end
+
 
+
function parse_ini_section_to_array(ini,section)
+
local tmp={}
+
if ini:section_exist(section) then
+
local result, id, value = nil, nil, nil
+
for a=0,ini:line_count(section)-1 do
+
result, id, value = ini:r_line(section,a,"","")
+
if id~=nil and trim(id)~="" and trim(id)~=nil then
+
tmp[trim(id)]=trim(value)
+
end
+
end
+
end
+
return tmp
+
end
+
 
+
function str_explode(div,str,clear)
+
local t={}
+
local cpt = string.find (str, div, 1, true)
+
if cpt then
+
repeat
+
if clear then
+
table.insert( t, trim(string.sub(str, 1, cpt-1)) )
+
else
+
table.insert( t, string.sub(str, 1, cpt-1) )
+
end
+
str = string.sub( str, cpt+string.len(div) )
+
cpt = string.find (str, div, 1, true)
+
until cpt==nil
+
end
+
if clear then
+
table.insert(t, trim(str))
+
else
+
table.insert(t, str)
+
end
+
return t
+
end
+
 
+
function quotemeta(str)
+
return (string.gsub(s, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%1"))
+
end
+
 
+
 
+
function add(v1,v2)
+
local nv=vector()
+
nv.x=v1.x+v2.x
+
nv.y=v1.y+v2.y
+
nv.z=v1.z+v2.z
+
return nv
+
end
+
 
+
function set_len(v,num)
+
local cl = math.sqrt(v.x*v.x+v.y*v.y+v.z*v.z)
+
cl = num/cl
+
v.x= v.x*cl
+
v.y= v.y*cl
+
v.z= v.z*cl
+
return v
+
end
+
 
+
function get_restrictor_data(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("rsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local t={}
+
amk.parse_object_packet(t,stpk,uppk,size)
+
  amk.parse_shape_packet(t,stpk,uppk,size)
+
+
t.restrictor_type = stpk:r_u8()
+
  -- amk.mylog("rsp "..size.." "..size1.." "..stpk:r_tell())
+
  return t
+
end
+
 
+
function set_restrictor_data(t,sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
+
  amk.fill_object_packet(t,stpk,uppk)
+
  amk.fill_shape_packet(t,stpk,uppk)
+
stpk:w_u8(t.restrictor_type)
+
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("wsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
end
+
 
+
function get_trader_data(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("rsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local t={}
+
amk.parse_object_packet(t,stpk,uppk,size)
+
  amk.parse_visual_packet(t,stpk,uppk,size)
+
  amk.parse_trader_packet(t,stpk,uppk,size)
+
  -- amk.mylog("rsp "..size.." "..size1.." "..stpk:r_tell())
+
  return t
+
end
+
 
+
function set_trader_data(t,sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
+
  amk.fill_object_packet(t,stpk,uppk)
+
  amk.fill_visual_packet(t,stpk,uppk)
+
  amk.fill_trader_packet(t,stpk,uppk)
+
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("wsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
end
+
 
+
function get_invbox_data(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("rsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local t={}
+
amk.parse_object_packet(t,stpk,uppk,size)
+
  amk.parse_visual_packet(t,stpk,uppk,size)
+
  -- amk.mylog("rsp "..size.." "..size1.." "..stpk:r_tell())
+
  return t
+
end
+
 
+
function set_invbox_data(t,sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
+
  amk.fill_object_packet(t,stpk,uppk)
+
  amk.fill_visual_packet(t,stpk,uppk)
+
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("wsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
end
+
 
+
function readvu8uN(packet,n)
+
  local v={}
+
  for i=1,n,1 do
+
    table.insert(v,packet:r_u8())
+
  end
+
  return v
+
end
+
 
+
function writevu8uN(pk,v)
+
  local len=table.getn(v)
+
  --pk:w_u8(len)
+
  for i=1,len,1 do
+
    pk:w_u8(v[i])
+
  end
+
end
+
 
+
function parse_item_packet(ret,stpk,updpk)
+
ret.condition=stpk:r_float()
+
ret.updnum_items=updpk:r_u8()
+
  ret.updpos={} -- или поставить вектор? ладно потом
+
  ret.updpos.x=updpk:r_float()
+
  ret.updpos.y=updpk:r_float()
+
  ret.updpos.z=updpk:r_float()
+
ret.updcse_alife_item__unk1_q8v4=readvu8uN(updpk,4)
+
ret.updcse_alife_item__unk2_q8v3=readvu8uN(updpk,3)
+
ret.updcse_alife_item__unk3_q8v3=readvu8uN(updpk,3)
+
  return ret
+
end
+
 
+
function fill_item_packet(ret,stpk,updpk)
+
stpk:w_float(ret.condition)
+
updpk:w_u8(ret.updnum_items)
+
  updpk:w_float(ret.updpos.x)
+
  updpk:w_float(ret.updpos.y)
+
  updpk:w_float(ret.updpos.z)
+
readvu8uN(updpk,ret.updcse_alife_item__unk1_q8v4)
+
readvu8uN(updpk,ret.updcse_alife_item__unk2_q8v3)
+
readvu8uN(updpk,ret.updcse_alife_item__unk3_q8v3)
+
  return ret
+
end
+
 
+
function parse_item_ammo_packet(ret,stpk,updpk)
+
ret.ammo_left=stpk:r_u16()
+
ret.updammo_left=updpk:r_u16()
+
  return ret
+
end
+
 
+
function fill_item_ammo_packet(ret,stpk,updpk)
+
stpk:w_u16(ret.ammo_left)
+
updpk:w_u16(ret.updammo_left)
+
  return ret
+
end
+
 
+
function get_ammo_params(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local t={}
+
amk.parse_object_packet(t,stpk,uppk,size)
+
  amk.parse_visual_packet(t,stpk,uppk,size)
+
  amk.parse_item_packet(t,stpk,uppk,size)
+
  amk.parse_item_ammo_packet(t,stpk,uppk,size)
+
  return t
+
end
+
 
+
function set_ammo_data(t,sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
+
  amk.fill_object_packet(t,stpk,uppk)
+
  amk.fill_visual_packet(t,stpk,uppk)
+
  amk.fill_item_packet(t,stpk,uppk)
+
  amk.fill_item_ammo_packet(t,stpk,uppk)
+
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
end
+
 
+
function cfg_get_string(ini,sect,name,def)
+
if ini and ini:line_exist(sect,name) then
+
return ini:r_string(sect,name)
+
end
+
return def
+
end
+
 
+
function get_destroyable_data(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("rsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local t={}
+
amk.parse_object_packet(t,stpk,uppk,size)
+
  amk.parse_visual_packet(t,stpk,uppk,size)
+
  amk.parse_skeleton_packet(t,stpk,uppk,size)
+
  amk.parse_object_physic_packet(t,stpk,uppk,size)
+
  -- amk.mylog("rsp "..size.." "..size1.." "..stpk:r_tell())
+
  return t
+
end
+
 
+
function set_destroyable_data(t,sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
+
  amk.fill_object_packet(t,stpk,uppk)
+
  amk.fill_visual_packet(t,stpk,uppk)
+
  amk.fill_skeleton_packet(t,stpk,uppk)
+
  amk.fill_object_physic_packet(t,stpk,uppk)
+
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("wsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
 
+
end
+
 
+
function get_weapon_data(sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
  sobj:STATE_Write(stpk)
+
  sobj:UPDATE_Write(uppk)
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("rsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  local t={}
+
  amk.parse_object_packet(t,stpk,uppk,size)
+
  amk.parse_visual_packet(t,stpk,uppk,size)
+
  amk.parse_item_packet(t,stpk,uppk,size)
+
  amk.parse_item_weapon_packet(t,stpk,uppk,size)
+
  -- amk.mylog("rsp "..size.." "..size1.." "..stpk:r_tell())
+
  return t
+
end
+
 
+
function set_weapon_data(t,sobj)
+
  local stpk=net_packet()
+
  local uppk=net_packet()
+
+
  amk.fill_object_packet(t,stpk,uppk)
+
  amk.fill_visual_packet(t,stpk,uppk)
+
  amk.fill_item_packet(t,stpk,uppk)
+
  amk.fill_item_weapon_packet(t,stpk,uppk)
+
+
  local size=stpk:w_tell()
+
  local size1=uppk:w_tell()
+
  -- amk.mylog("wsp "..size.." "..size1)
+
  stpk:r_seek(0)
+
  uppk:r_seek(0)
+
  sobj:STATE_Read(stpk,size)
+
  sobj:UPDATE_Read(uppk)
+
 
+
end
+
 
+
function parse_item_weapon_packet(ret,stpk,updpk)
+
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.updcondition = updpk:r_u8()
+
ret.updweapon_flags = updpk:r_u8()
+
ret.updammo_elapsed = updpk:r_u16()
+
ret.updaddon_flags = updpk:r_u8()
+
ret.updammo_type = updpk:r_u8()
+
ret.updweapon_state = updpk:r_u8()
+
ret.updweapon_zoom = updpk:r_u8()
+
ret.updcurrent_fire_mode = updpk:r_u8()
+
  return ret
+
end
+
 
+
function fill_item_weapon_packet(ret,stpk,updpk)
+
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)
+
+
updpk:w_u8(ret.updcondition)
+
updpk:w_u8(ret.updweapon_flags)
+
updpk:w_u16(ret.updammo_elapsed)
+
updpk:w_u8(ret.updaddon_flags)
+
updpk:w_u8(ret.updammo_type)
+
updpk:w_u8(ret.updweapon_state)
+
updpk:w_u8(ret.updweapon_zoom)
+
updpk:w_u8(ret.updcurrent_fire_mode)
+
  return ret
+
end
+
 
+
function get_ver()
+
local ver = "0"
+
local mm = _G.main_menu.get_main_menu()
+
if mm then ver = mm:GetGSVer() end
+
return ver
+
end
+
</pre>
+
всё заходим в игру и пробуем :-)
+
  
 
[[Категория:Скрипты]]
 
[[Категория:Скрипты]]

Текущая версия на 07:09, 2 апреля 2011

Нам понадобится файл 'treasure_manager.script'.

В этом файле находим такие строки:

 
--' Юзание инициатора (возможность выдать тайник)
function CTreasure:use(npc)
	printf("TREASURE USE")
После строки --printf("TREASURE USE")-- пишем
 
	if (npc and db.actor) then
		lootmoney.lootmoney(npc)
	end
 

У нас должно выйти

 
--' Юзание инициатора (возможность выдать тайник)
function CTreasure:use(npc)
	printf("TREASURE USE")
 
	if (npc and db.actor) then
		lootmoney.lootmoney(npc)
	end
 

Теперь создаём файл lootmoney.script и в нём пишем

 
function lootmoney(npc)
	if npc ~= nil and not string.find(npc:section(),"arena") and npc:character_community()~="arena_enemy" then
		local money = npc:money()
		if money ~= nil and money ~=0 then
				local deadmoney = money
 
                                local npc_rank
		npc_rank = ranks.get_obj_rank_name(npc)
		if npc_rank ~= nil then
			if npc_rank == "novice" and deadmoney >=400 then deadmoney=math.random(25,400)    
			elseif npc_rank == "experienced" and deadmoney >=500 then deadmoney=math.random(50,500)  
			elseif npc_rank == "veteran" and deadmoney >=600 then deadmoney=math.random(100,600) 
			elseif npc_rank == "master" and deadmoney >=700 then deadmoney=math.random(200,700)  
                          end
						  end
				local news_texti = "\\n%c[255,255,0,0]Мёртвый сталкер: %c[default]"..npc:character_name().."\\n%c[255,255,0,0]Обнаружено денег: %c[default]"..game.translate_string(tostring(deadmoney).."руб.")
				db.actor:give_game_news(news_texti, "ui\\ui_iconsTotal", Frect():set(0,0,83,47), 1, 4000)
				db.actor:give_money(deadmoney)
				game_stats.money_quest_update(deadmoney) 
				npc:give_money(-money)
				game_stats.money_quest_update(-money)
			end
		end
	end
 
Другие места
LANGUAGE