SoC. Снятие денег с трупов
Материал из S.T.A.L.K.E.R. Inside Wiki
Версия от 16:33, 8 июля 2010; 91.90.15.46 (обсуждение)
В этой теме я напишу как сделать так что бы можно было снимать деньги с трупов. Нам надо файл 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
теперь создаем файл watcher_act.script и впишем в его
-- 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
--спавним объекты на карту --для спавна неписей смотрим 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
всё заходим в игру и пробуем :-)