Перейти к контенту

Скриптование


Svoboда

Рекомендуемые сообщения

Эксперементировал со скриптами мода "Скриптовая эмуляция невидимых слотов". Вместо ПДА взял слот для детектора. Если убрать детектор в рюкзак все нормально, а когда поместить его обратно в слот, то возникает безлоговый вылет. Что делать?

 


local debug = false --true -- система размещения кнопок ( true - вкл.\ false - выкл.)
local rec_wnd = nil
local initial = false
local TBtn = {}

-- нож бинокль болт ПДА фонарик -- координаты кнопок {x,y}
local slots = { {80,50},{220,50},{4000,50},{730,50},{880,50}}
----------------------------------------------------------------------------------

class "BkgrWnd" (CUIScriptWnd)

function BkgrWnd:__init(owner) super()
self.owner = owner
self:Init(0, 0, 1024, 768)

self.ClickBtn={}

self.ClickBtn[1] = function()
local item = db.actor:item_in_slot(0)
if item then spawn_item_in_inv("fake_"..item:section()) del_item(item:id()) end TBtn["check_button_1"]:Show(false)
end

self.ClickBtn[2]=function()
local item = db.actor:item_in_slot(4)
if item then spawn_item_in_inv("fake_"..item:section()) del_item(item:id()) end TBtn["check_button_2"]:Show(false)
end

self.ClickBtn[3]=function()
news_manager.send_tip(db.actor, "руки прочь от болта!" )
end

self.ClickBtn[4]=function()
local item = db.actor:item_in_slot(8)
if item then spawn_item_in_inv(item:section()) del_item(item:id()) end TBtn["check_button_4"]:Show(false)
end

self.ClickBtn[5]=function()
local item = db.actor:object("device_torch")
if item then spawn_item_in_inv("fake_device_torch") del_item(item:id()) end TBtn["check_button_5"]:Show(false)
end

self:InitControls()
end

function BkgrWnd:__finalize() end

function BkgrWnd:InitControls()

clear_table(TBtn)

self.bkgr_static=CUIStatic()
self.bkgr_static:Init("ui\\ui_inv_quick_slots",10, 0, 1024, 100)
self.bkgr_static:ClipperOn()

self.stat = CUIStatic()

self.stat:AttachChild(self.bkgr_static)

self.stat:Init(0, 0, 1024, 768)
self.owner:AttachChild(self.stat)

for k,v in pairs (slots) do

local name="check_button_"..k
self.btn = CUIButton()
self.btn:SetAutoDelete(false)
self.btn:SetWindowName(name)
self:Register(self.btn)
self.stat:AttachChild(self.btn)
TBtn[name]= self.btn

init_btn(k)

self:AddCallback(name,ui_events.WINDOW_LBUTTON_DB_CLICK, self.ClickBtn[k], self)

end

initial = true
end

function BkgrWnd:ClickBtnStepUp()
self.step=self.step*2
if self.step>200 then self.step=128 end
--news_manager.send_tip(db.actor,"шаг= "..self.step)
self.btn:SetText("кнопка "..self.num_btn.." шаг "..self.step)
end

function BkgrWnd:ClickBtnStepDn()
self.step=self.step/2
if self.step==1 then self.step=2 end
--news_manager.send_tip(db.actor,"шаг= "..self.step)
self.btn:SetText("кнопка "..self.num_btn.." шаг "..self.step)
end

function BkgrWnd:ClickNxtBtn()
self.num_btn=self.num_btn+1
if self.num_btn>#slots then self.num_btn=1 end
self.btn:SetText("кнопка "..self.num_btn.." шаг "..self.step)
--news_manager.send_tip(db.actor,"скорректируем положение кнопки "..self.num_btn)
end

function BkgrWnd:ClickBtnUp()
slots[self.num_btn][2]=slots[self.num_btn][2]-self.step
if slots[self.num_btn][2]<0 then slots[self.num_btn][2]=768+slots[self.num_btn][2] end
init_btn(self.num_btn)
end

function BkgrWnd:ClickBtnDwn()
slots[self.num_btn][2]=slots[self.num_btn][2]+self.step
if slots[self.num_btn][2]>768 then slots[self.num_btn][2]=-768+slots[self.num_btn][2] end
init_btn(self.num_btn)
end

function BkgrWnd:ClickBtnLft()
slots[self.num_btn][1]=slots[self.num_btn][1]-self.step
if slots[self.num_btn][1]<0 then slots[self.num_btn][1]=1024+slots[self.num_btn][1] end
init_btn(self.num_btn)
end

function BkgrWnd:ClickBtnRt()
slots[self.num_btn][1]=slots[self.num_btn][1]+self.step
if slots[self.num_btn][1]>1024 then slots[self.num_btn][1]=-1024+slots[self.num_btn][1] end
init_btn(self.num_btn)
end

-- инициализация с учетом размеров иконки статика
function init_btn(num,sec)

local function sections(num)
if num==1 then
local item=db.actor:item_in_slot(0)
if item then return item:section() else return end
elseif num==2 then
local item=db.actor:item_in_slot(4)
if item then return item:section() else return end
elseif num==3 then

elseif num==4 then
local item=db.actor:item_in_slot(8)
if item then return item:section() else return end

elseif num==5 then
local item=db.actor:item_in_slot(9)
if item then return "device_torch" else return end
end
end

local btn=TBtn["check_button_"..num]
if not btn then rec_wnd = BkgrWnd(level.main_input_receiver()) end
btn=TBtn["check_button_"..num]
local sect = sec or sections(num)
if sect then
local ini=system_ini()
local x=ini:r_u32(sect, "inv_grid_x")*50
local y=ini:r_u32(sect, "inv_grid_y")*50
local width=ini:r_u32(sect, "inv_grid_width")*50
local height=ini:r_u32(sect, "inv_grid_height")*50
btn:InitTexture("ui\\ui_icon_equipment")
btn:SetOriginalRect(x,y,width,height)
btn:SetStretchTexture(true)
local h=50 -- высота кнопки 50 пикселов
local w=h*width/height -- ширина пропорциональна соотношению высоты и ширины инвентарной иконки.
btn:Init(slots[num][1]-w/2,slots[num][2]-h/2,w,h)
btn:Show(true)

else
btn:Init(slots[num][1],slots[num][2],0,0)
end

end

function BkgrWnd:ShowWnd()
if initial and rec_wnd.stat~= nil then
rec_wnd.stat:Show(true)
end
end


function BkgrWnd:HideWnd()
if initial and rec_wnd.stat~= nil then
rec_wnd.stat:Show(false)
end
end

function BkgrWnd:DetachWnd()
self.owner:DetachChild(self.stat)
-- self:AttachChild(self.stat)
initial = false
end

--------------------------------------------------------------------------

function on_eat(sect)

local items_for_0_slot={ -- кулаки,ножи,перчатки...
["fake_wpn_knife"]=true,
["fake_wpn_fist"]=true,
["fake_wpn_fist_m"]=true
}
if items_for_0_slot[sect] then
reinit_button_1(string.sub(sect,6,-1)) return
end

local items_for_4_slot={ -- бинокли...
["fake_wpn_binoc"]=true,
["fake_wpn_binoc1"]=true
}
if items_for_4_slot[sect] then
reinit_button_2(string.sub(sect,6,-1)) return
end

if sect=="fake_device_torch" then
if db.actor:object("device_torch") then
spawn_item_in_inv("fake_device_torch")
else
spawn_item_in_inv("device_torch") init_btn(5,"device_torch")
end
end
end

function reinit_button_1(sect)
local item=db.actor:item_in_slot(0)
if item then
db.actor:drop_item(item) spawn_item_in_inv("fake_"..item:section())
del_item(item:id())
end
spawn_item_in_inv(sect)
init_btn(1,sect)
end

function reinit_button_2(sect)
local item=db.actor:item_in_slot(4)
if item then
db.actor:drop_item(item) spawn_item_in_inv("fake_"..item:section())
del_item(item:id())
end
spawn_item_in_inv(sect)
init_btn(2,sect)
end

function spawn_item_in_inv( sect )
alife():create(sect,db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
end

function del_item(id)
if id then
local sobj=alife():object(id)
if sobj then alife():release(sobj,true) end
end
end

---------------------------------------------------------------------------------------------

function on_info(info_id)
if info_id == "ui_inventory" then
if not initial then
rec_wnd = BkgrWnd(level.main_input_receiver())
end
if not rec_wnd.stat:IsShown() then
rec_wnd:ShowWnd()
end

elseif info_id == "ui_inventory_hide" then

if rec_wnd then
rec_wnd:DetachWnd()
end
end
end

 

Поделиться этим сообщением


Ссылка на сообщение
(изменено)

С вопросом ошибся темой.

ColR_iT

Изменено пользователем ColR_iT

Поделиться этим сообщением


Ссылка на сообщение
(изменено)

Всем привет.
Хотел добавить зависимость выпадения вещей после смерти НПС от ранга. Но поскольку я в скриптинге не очень опытный, то возникают баги.


--' Ключем является группировка персонажа. Значением является таблица, содержашая имена секций предметов.
local item_by_community = {}

--' Зависимости в спауне предметов. Предмет спауниться только если есть хотя бы один из зависимых.
local item_dependence = {}

--' Множители и минимаксы для выпадения вещей в зависимости от уровня
local mul_by_level = {}
local count_by_level = {}

--' Множители и минимаксы для выпадения вещей в зависимости от ранга
local mul_by_rank = {}
local count_by_rank = {}

--' Предметы, которые нельзя удалять (квестовые например)
local always_keep_item = {}

--' Предметы, относящиеся к патронам. Их надо спаунить другим методом.
local ammo_sections = {}

local death_ini = ini_file("misc\\death_generic.ltx")


function init_drop_settings()
local community_list = { "stalker", "dolg", "freedom", "bandit", "military", "zombied", "ecolog", "killer", "monolith", "arena_enemy", "actor_dolg" }

for k,v in pairs(community_list) do
--' Необходимо заполнить таблицу
item_by_community[v] = {}
if death_ini:section_exist(v) then
local n = death_ini:line_count(v)
local id, value = "", ""
for i=0,n-1 do
result, id, value = death_ini:r_line(v,i,"","")
item_by_community[v][id] = 100*tonumber(value)
end
end
end

--' Заполняем таблицу зависимостей
local n = death_ini:line_count("item_dependence")
local id, value = "", ""
for i=0,n-1 do
result, id, value = death_ini:r_line("item_dependence",i,"","")
item_dependence[id] = {}
local vvv = parse_names(value)
for k,v in pairs(vvv) do
item_dependence[id][v] = true
end
end

--' Множители и минимаксы для выпадения вещей в зависимости от уровня
local level_name = level.name()

if not death_ini:section_exist(level_name) then
level_name = "default"
end

local n = death_ini:line_count(level_name)
local id, value = "", ""
for i=0,n-1 do
result, id, value = death_ini:r_line(level_name,i,"","")
mul_by_level[id] = tonumber(value)
end

--' Множители и минимаксы для выпадения вещей в зависимости от ранга
local character_rank = db.actor:rank()

if not death_ini:section_exist(character_rank) then
character_rank = "novice"
end

local n = death_ini:line_count(character_rank)
local id, value = "", ""
for i=0,n-1 do
result, id, value = death_ini:r_line(character_rank,i,"","")
mul_by_rank[id] = tonumber(value)
end

local item_count_section = "item_count_" .. level.get_game_difficulty()
local n = death_ini:line_count(item_count_section)
for i=0,n-1 do
result, id, value = death_ini:r_line(item_count_section,i,"","")
--' Нужно распарсить value в два значения
local t = parse_nums(value)
if t[1] == nil then
abort("Error on [death_ini] declaration. Section [%s], line [%s]", item_count_section, tostring(id))
end
local min = t[1]
local max = t[2]
if max == nil then
max = min
end

if mul_by_level[id] == nil then
mul_by_level[id] = 0
end

if mul_by_rank[id] == nil then
mul_by_rank[id] = 0
end

min = tonumber(min) * (mul_by_level[id] + mul_by_rank[id])
max = tonumber(max) * (mul_by_level[id] + mul_by_rank[id])

count_by_level[id] = {min = min, max = max}
count_by_rank[id] = {min = min, max = max}
end

--' Предметы, которые нельзя удалять (квестовые например)
local n = death_ini:line_count("keep_items")
for i=0,n-1 do
result, id, value = death_ini:r_line("keep_items",i,"","")
if value == "true" then
always_keep_item[id] = true
end
end

--' Предметы, относящиеся к патронам. Их надо спаунить другим методом.
ammo_sections = {}
local n = death_ini:line_count("ammo_sections")
local id, value = "", ""
for i=0,n-1 do
result, id, value = death_ini:r_line("ammo_sections",i,"","")
ammo_sections[id] = true
end
end



class "drop_manager"
function drop_manager:__init(npc)
self.npc = npc
end
function drop_manager:create_release_item()
--' Спрашиваем у серверного объекта генерились ли предметы
local se_obj = alife():object(self.npc:id())
if se_obj.death_droped == true then
return
end
se_obj.death_droped = true

--' Запускаем итератор на удаление предметов
self.npc:iterate_inventory(keep_item, self.npc)

--' Проверка на отсутствие спауна лута
local ini = self.npc:spawn_ini()

if ini and ini:section_exist("dont_spawn_loot") then
return
end

--' Доспавниваем необходимое количество итемов:
--' Необходимо составить список объектов которые могут быть заспавнены для персонажа

local spawn_items = item_by_community[self.npc:character_community()]
for k,v,t in pairs(spawn_items) do
--' По каждому объекту необходимо получить зависимости
if check_item_dependence(self.npc, k) == true then
--' По каждому объекту необходимо получить количество
local number = math.ceil(math.random(count_by_level[k].min, count_by_level[k].max))
--' Необходимо заспавнить нужное количество.
create_items(self.npc, k, number, v)
end
end
end

--' Функция вызывается для каждого предмета, если вернет false то предмет удалится.
function keep_item(npc, item)
if item==nil or alife():object(item:id())==nil then return end
local section = item:section()

if section == "bolt" then
return false
end

if always_keep_item[section] == true then
return true
end

local item_id = item:id()
local item_in_slot = npc:item_in_slot(1)
if item_in_slot ~= nil and
item_in_slot:id() == item_id
then
--' Тут надо уменьшить кондишн оружия
item:set_condition((math.random(15)+75)*item:condition()/100)
return true
end
item_in_slot = npc:item_in_slot(2)
if item_in_slot ~= nil and
item_in_slot:id() == item_id
then
--' Тут надо уменьшить кондишн оружия
item:set_condition((math.random(15)+75)*item:condition()/100)
return true
end
alife():release(alife():object(item:id()), true)
end
function set_weapon_drop_condition(item)
local condition = (math.random(15)+75)/100
--printf("condition [%s]", tostring(condition))
item:set_condition(condition)
end

--' Функция спавнит необходимое число предметов
function create_items(npc, section, number, rnd)
--'printf("create %s of %s", tostring(number), tostring(section))
if ammo_sections[section] == true then
if number > 0 then
se_respawn.create_ammo(section,
npc:position(),
npc:level_vertex_id(),
npc:game_vertex_id(),
npc:id(),
number)
end
else
for i=1,number do
--' Проверяем вероятность появить каждый объект в отдельности
if math.random(100) <= rnd then
alife():create(section,
npc:position(),
npc:level_vertex_id(),
npc:game_vertex_id(),
npc:id())
end
end
end
end


--' Функция проверяет есть ли хоть один из зависимых объектов у персонажа
function check_item_dependence(npc, section)
if item_dependence[section] == nil then
return true
end

local d_flag = true
for k,v in pairs(item_dependence[section]) do
local obj = npc:object(k)
if obj ~= nil and npc:marked_dropped(obj) ~= true then
return true
end
d_flag = false
end

return d_flag
end

Функця работает, но дело в том, что учитывается ранг Актора, а не НПС. А вот как сделать, чтобы учитывался ранг НПС, я не знаю.

Изменено пользователем Gaz24

Поделиться этим сообщением


Ссылка на сообщение
(изменено)

Всем привет. Пытался переадаптировать схему боя НПС с ножом из ЗП в ТЧ. В итоге НПС достает нож, смотрит на ГГ и больше ничего не делает. Возникли вопросы:
1. Кто-нибудь разбирал этот скрипт?
2. Возможно подправить это баг?
Вот еще файл скрипта

---- Rulix aka Bak --- 8.3.2010

function printf(s, ...)
-- rx_ai.printf("kn:"..s,...)
-- get_console():execute("flush")
end

local kn_ini = ini_file("misc\\rx_knife.ltx")
local knife_sets = {forbiddens = {weapons = {},factions = {},npcs = {}},
communities = {},
ranks = {},
check_prd = rx_utils.read_from_ini(kn_ini,"main","check_period",1001),
fire_dist = rx_utils.read_from_ini(kn_ini,"main","fire_dist",1.5),
enabled = rx_utils.read_from_ini(kn_ini,"main","enabled",false,0)}

function init()
if not knife_sets.enabled then
kn_ini = nil
return
end
local ranks = {"novice","experienced","veteran","master"}
for k,v in ipairs(ranks) do
if kn_ini:section_exist(v) then
knife_sets.ranks[v] = {rate = rx_utils.read_from_ini(kn_ini,v,"rate",1)}
end
end
local communities = { "stalker", "dolg", "freedom", "bandit", "military", "ecolog", "killer", "monolith" }
for k,v in ipairs(communities) do
knife_sets.communities[v] = {rate_add = rx_utils.read_from_ini(kn_ini,v,"rate_add",0),
courage = rx_utils.read_from_ini(kn_ini,v,"courage",1),
attack_wounded = rx_utils.read_from_ini(kn_ini,v,"attack_wounded",0),
mutant_hunt = rx_utils.read_from_ini(kn_ini,v,"mutant_hunt",true,0) or nil}
end
knife_sets.forbiddens.weapons = rx_utils.parse_list(kn_ini,"main","forbidden_weapons",true)
knife_sets.forbiddens.factions = rx_utils.parse_list(kn_ini,"main","forbidden_factions",true)
knife_sets.forbiddens.npcs = rx_utils.parse_list(kn_ini,"main","forbidden_npcs",true)
kn_ini = nil
knife_sets.inited = true
end

local kill_wounded = 0
local sneak_attack = 1
local close_attack = 2
local mutant_hunt = 3
local mutant_defend = 4

local mutant_hunt_clsids = {
[clsid.bloodsucker_s] = true,
[clsid.boar_s] = true,
-- [clsid.dog_s] = true,
[clsid.flesh_s] = true,
-- [clsid.pseudodog_s] = true,
-- [clsid.burer_s] = true,
-- [clsid.cat_s] = true,
-- [clsid.chimera_s] = true,
[clsid.controller_s] = true,
-- [clsid.fracture_s] = true,
-- [clsid.poltergeist_s] = true,
-- [clsid.gigant_s] = true,
-- [clsid.zombie_s] = true,
-- [clsid.snork_s] = true,
-- [clsid.tushkano_s] = true,
[clsid.psy_dog_s] = true,
-- [clsid.psy_dog_phantom_s] = true}
}
local mutant_defend_clsids = {
-- [clsid.bloodsucker_s] = true,
[clsid.boar_s] = true,
-- [clsid.dog_s] = true,
[clsid.flesh_s] = true,
[clsid.pseudodog_s] = true,
-- [clsid.burer_s] = true,
[clsid.cat_s] = true,
-- [clsid.chimera_s] = true,
-- [clsid.controller_s] = true,
[clsid.fracture_s] = true,
-- [clsid.poltergeist_s] = true,
-- [clsid.gigant_s] = true,
-- [clsid.zombie_s] = true,
-- [clsid.snork_s] = true,
[clsid.tushkano_s] = true,
[clsid.psy_dog_s] = true,
-- [clsid.psy_dog_phantom_s] = true}
}

targets = {}

local function remove_target(npc_id,st)
if st.target and targets[st.target] == npc_id then
targets[st.target] = nil
end
st.target = nil
end

class "evaluator_knife_attack" (property_evaluator)
function evaluator_knife_attack:__init(npc,name,storage) super (nil,name)
self.st = storage
self.st.delay = 0
self.st.timer = 0
self.check_timer = 0
local comm = npc:character_community()
if self.attack_wounded == nil then
self.attack_wounded = math.random() < knife_sets.communities[comm].attack_wounded
end
if not self.courage then
self.courage = math.random(25,npc:character_rank()/4+51)
end
self.courage = self.courage*knife_sets.communities[comm].courage
self.cmhunt = knife_sets.communities[comm].mutant_hunt
-- rx_ai.printf("knife_init[%s]:kn_aw %s, courage %s, rank %s",npc:character_name(),tostring(self.attack_wounded),self.courage,npc:character_rank())
rx_ai.subscribe_for_events(npc,self)
end

function evaluator_knife_attack:evaluate()
local npc = self.object
if rx_utils.IsTrader(npc) then
return false
end
local wm = rx_wmgr and rx_wmgr.get_wm(npc)
local knife = npc:object("wpn_knife")
if not knife or npc:animation_count() ~= 0 then
-- printf("evaluator_knife_attack[%s]:not knife or anims",npc:character_name())
remove_target(npc_id,self.st)
return false
end
local npc_id,tg = npc:id(),time_global()
if self.st.delay > tg then
remove_target(npc_id,self.st)
-- printf("evaluator_knife_attack[%s]:delay",npc:character_name())
return false
end
local be = npc:best_enemy()
if not be then
remove_target(npc_id,self.st)
return false
end
local be_id = be:id()
local target = self.st.target and level.object_by_id(self.st.target)
if not (target and target:alive()) then
-- printf("evaluator_knife_attack[%s]:not target",npc:character_name())
remove_target(npc_id,self.st)
end
local npc_pos = npc:position()
if target then
-- printf("evaluator_knife_attack[%s]:target",npc:character_name())
local target_pos = be:position()
local dist = target_pos:distance_to(npc_pos)
if targets[self.st.target] then
if targets[self.st.target] ~= npc_id then
printf("evaluator_knife_attack[%s]:target gette",npc:character_name())
remove_target(npc_id,self.st)
elseif self.st.target ~= be_id and dist > 3 or not npc:accessible(target_pos) then
printf("evaluator_knife_attack[%s]:target not access",npc:character_name())
remove_target(npc_id,self.st)
else
if self.st.type == kill_wounded and dist > 5 then
remove_target(npc_id,self.st)
self.st.delay = tg+15000
return false
elseif self.st.type == sneak_attack and target:see(npc) and dist > self.courage/20 then
self.st.type = close_attack
return true
elseif self.st.type == close_attack and dist > self.courage/10 then
remove_target(npc_id,self.st)
self.st.delay = tg+15000
return false
elseif self.st.type == mutant_hunt and dist > 15 then
remove_target(npc_id,self.st)
self.st.delay = tg+12000
return false
elseif self.st.type == mutant_defend and dist > 12 or npc.health < 0.2 then -- or not (target:get_enemy() and target:get_enemy():id() == npc_id)
remove_target(npc_id,self.st)
self.st.delay = tg+12000
return false
end
return true
end
else
if dist > 12 then
printf("evaluator_knife_attack[%s]:target dist > 12",npc:character_name())
self.st.target = nil
end
end
end
if self.check_timer > tg then
return target ~= nil
end
self.check_timer = tg+knife_sets.check_prd
local be_pos = be:position()
local dist = npc_pos:distance_to(be_pos)
if targets[be_id] or (xr_wounded.is_wounded(be) and not self.attack_wounded) or dist > 10 or not npc:accessible(be_pos) then
-- printf("evaluator_knife_attack[%s]:not access %s %s %s %s",npc:character_name(),tostring(targets[be_id]),tostring((xr_wounded.is_wounded(be) and not self.attack_wounded)),tostring(dist > 15),tostring(not npc:accessible(be_pos)))
return false
end
local be_see_me,me_see_be = be:see(npc),npc:see(be)
if IsStalker(be) then
if xr_wounded.is_wounded(be) then
if self.attack_wounded and me_see_be and dist < 3.5 then
self.st.target = be_id
self.st.type = kill_wounded
return true
end
return false
end
if me_see_be and not be_see_me and self.courage > 40 and npc:body_state() == move.crouch and dist < 5 and npc.health > 0.5 then
-- printf("sneak_attack[%s]:return true",npc:character_name())
self.st.target = be_id
self.st.type = sneak_attack
return true
end
if self.courage > 33+5*dist and me_see_be then
local npc_wpn,be_wpn = npc:active_item(),be:active_item()
if not (be_wpn and rx_utils.item_is_fa(be_wpn) and npc_wpn and npc_wpn:section() ~= "wpn_knife" and npc_wpn:get_ammo_in_magazine() ~= 0 and be_wpn:get_ammo_in_magazine() ~= 0) then
-- printf("close_attack[%s]:return true",npc:character_name())
self.st.target = be_id
self.st.type = close_attack
self.st.timer = self.st.timer+6000
return true
end
end
else
local bee = be:get_enemy()
-- printf("monster[%s]: %s %s",npc:character_name(),tostring(not (be_see_me and be:get_enemy() and be:get_enemy():id() == npc_id)),tostring(npc.health > 0.8))
if self.cmhunt and mutant_hunt_clsids[be:clsid()] and self.courage > 35+5*dist and not (be_see_me and bee and bee:id() == npc_id) and npc.health > 0.8 then
-- printf("mutant_hunt[%s]:return true",npc:character_name())
self.st.target = be_id
self.st.type = mutant_hunt
self.st.timer = self.st.timer+6000
return true
elseif mutant_defend_clsids[be:clsid()] and dist < 6 and self.courage > 40+dist and (be_see_me and bee and bee:id() == npc_id) and npc.health > 0.2 then
-- printf("mutant_defend[%s]:return true",npc:character_name())
self.st.target = be_id
self.st.type = mutant_defend
self.st.timer = self.st.timer+4000
return true
end
end
return false
end
function evaluator_knife_attack:death_callback(who)
if self.object then
remove_target(self.object:id(),self.st)
end
end


class "evaluator_knife_defend" (property_evaluator)
function evaluator_knife_defend:__init(npc,name,storage) super (nil,name)
self.st = storage
end

function evaluator_knife_defend:evaluate()
return false
end


class "action_knife_attack" (action_base)
function action_knife_attack:__init(npc,action_name,storage) super (nil,action_name)
self.st = storage
self.rank = ranks.get_obj_rank_name(npc)
self.comm = npc:character_community()
self.rate = 1000/(knife_sets.ranks[self.rank].rate+knife_sets.communities[self.comm].rate_add)
end
function action_knife_attack:initialize()
action_base.initialize(self)
local npc = self.object
printf("knife_attack[%s]:init",npc:character_name())
self.st.timer = time_global()+30000
self.start_time = time_global()
self.fire_time = 0
self.mental_time = 0
if rx_wmgr then
local wm = rx_wmgr.get_wm(npc)
-- local knife = wm:get_best_weapon(1)
-- wm:return_items(knife and knife:id() or 0)
wm:disable(self.st.timer)
end
npc:set_desired_position()
npc:set_desired_direction()
npc:set_mental_state(anim.danger)
npc:set_movement_type(move.run)
-- state_mgr.set_state(npc,"assault")
state_mgr.set_state(npc,"idle")
targets[self.st.target] = npc:id()
if self.st.type == kill_wounded then
--xr_sound.set_sound_play(targets[self.st.target],"kill_wounded")
end
self.ddr = math.random() > 0.5
end

function action_knife_attack:execute()
action_base.execute(self)
local npc,tg = self.object,time_global()
local npc_id = npc:id()
if self.st.timer < tg then
remove_target(npc_id,self.st)
self.st.delay = tg+10000
printf("knife_attack[%s]:timer < tg",npc:character_name())
return
end
local target = level.object_by_id(self.st.target)
local dist = npc:position():distance_to(target:position())
local knife = npc:object("wpn_knife")
local dir = target:position()
dir:sub(npc:position())
npc:set_sight(look.direction,dir)
local acti = npc:active_item()
acti = acti and acti:section() == "wpn_knife"
if acti and (dist < knife_sets.fire_dist or self.st.type == mutant_defend and dist < knife_sets.fire_dist*1.5) then
-- printf("attack[%s]:set fire",npc:character_name())
npc:set_sight(look.fire_point,target:bone_position("bip01_neck"))
if self.fire_time < tg then
npc:set_item(object.fire1,knife,1,self.rate)
self.fire_time = tg+self.rate
end
if self.st.type == kill_wounded then
-- npc:set_dest_level_vertex_id(npc:level_vertex_id())
npc:set_movement_type(move.stand)
npc:set_body_state(move.crouch)
end
else
if not (self.st.type == kill_wounded or self.st.type == sneak_attack or IsMonster(target)) then
--xr_sound.set_sound_play(npc_id,"knife_attack")
end
if self.st.type ~= mutant_defend then
npc:set_movement_type(move.run)
end
npc:set_item(object.aim1,knife)
end
if not acti then
if self.start_time+4000 < tg then
remove_target(npc_id,self.st)
self.st.delay = tg+15000
printf("knife_attack[%s]:timer < tg",npc:character_name())
return
end
npc:set_mental_state(anim.danger)
elseif self.st.type == sneak_attack then
npc:set_body_state(move.crouch)
npc:set_mental_state(anim.danger)
if dist > 6 and target:see(npc) then
printf("sneak_attack[%s]:abort",npc:character_name())
remove_target(npc_id,self.st)
return
end
elseif self.st.type == mutant_hunt then
npc:set_body_state(move.standing)
if self.mental_time < tg then
if dist < 3 and self.mental ~= anim.danger then
self.mental_time = tg+900
self.mental = anim.danger
elseif self.mental ~= anim.panic then
self.mental_time = tg+1500
self.mental = anim.panic
end
npc:set_mental_state(self.mental)
end
-- printf("mutant_hunt[%s]:send",npc:character_name())
elseif self.st.type == close_attack then
npc:set_body_state(move.standing)
npc:set_mental_state(anim.danger)
-- printf("close_attack[%s]:send",npc:character_name())
elseif self.st.type == mutant_defend then
npc:set_body_state(move.standing)
npc:set_mental_state(anim.danger)
if dist < 3.5 then
npc:set_movement_type(move.run)
else
npc:set_movement_type(move.walk)
end
-- printf("mutant_defend[%s]:send",npc:character_name())
end
local vertex = self.st.type == mutant_defend and get_dodge_vertex(npc,target,self.ddr) or target:level_vertex_id()
utils.send_to_nearest_accessible_vertex(npc,vertex)
end

function action_knife_attack:finalize()
local npc = self.object
printf("knife_attack[%s]:fin",npc:character_name())
if rx_wmgr then
rx_wmgr.get_wm(npc):enable()
end
if not npc:best_enemy() then
npc:set_item(object.idle,npc:object("wpn_knife"))
state_mgr.set_state(npc,"guard")
end
npc:set_sight(look.direction,npc:direction())
remove_target(npc:id(),self.st)
self.mental = nil
self.ddr = nil
action_base.finalize(self)
end

class "action_knife_defend" (action_base)
function action_knife_defend:__init (npc,action_name,storage) super (nil,action_name)
self.st = storage
end
function action_knife_defend:initialize()
action_base.initialize(self)
self.wm = db.storage[npc:id()].wm
self.wm:set_weapon(npc:object("wpn_knife"))
self.wm.disabled_temp = true
end
function action_knife_defend:execute()
action_base.execute(self)
end
function action_knife_defend:finalize()
action_base.finalize(self)
end

function get_dodge_vertex(s,o,d)
local dir = o:position():sub(s:position())
dir = vector_rotate_y(dir,d and 50 or 310)
return s:vertex_in_direction(s:level_vertex_id(),dir,3)
end

function npc_update(npc)
if knife_sets.enabled then
local knife = npc:object("wpn_knife")
if not knife then
alife():create("wpn_knife",npc:position(),npc:level_vertex_id(),npc:game_vertex_id(),npc:id())
end
end
end

evid_knife_attack=rx_ai.base_id+35
--evid_knife_defend=evid_knife_attack+1
actid_knife_attack=evid_knife_attack
--actid_knife_defend=actid_knife_attack+1

function add_to_binder(npc,ini,scheme,section,storage)
if not knife_sets.inited then
init()
end
local manager = npc:motivation_action_manager()
if not (knife_sets.enabled and not knife_sets.forbiddens.factions[npc:character_community()] and knife_sets.ranks[ranks.get_obj_rank_name(npc)] and not knife_sets.forbiddens.npcs[npc:name()]) then
manager:add_evaluator(evid_knife_attack,property_evaluator_const(false))
return
end
manager:add_evaluator(evid_knife_attack,evaluator_knife_attack(npc,"evaluator_knife_attack",storage))
local action = action_knife_attack(npc,"knife_attack",storage)
action:add_precondition(world_property(stalker_ids.property_alive,true))
action:add_precondition(world_property(xr_evaluators_id.sidor_wounded_base,false))
-- action:add_precondition(world_property(xr_evaluators_id.state_mgr+1,true))
if rx_gl then
action:add_precondition(world_property(rx_gl.evid_gl_fire,false))
end
if rx_bandage then
action:add_precondition(world_property(rx_bandage.evid_bandage,false))
end
action:add_precondition(world_property(evid_knife_attack,true))
action:add_effect(world_property(evid_knife_attack,false))
manager:add_action(actid_knife_attack,action)
for i,id in ipairs({stalker_ids.action_combat_planner,stalker_ids.action_danger_planner,xr_actions_id.stohe_meet_base+1}) do
action = manager:action(id)
action:add_precondition(world_property(evid_knife_attack,false))
end
end

function set_scheme(npc,ini,scheme,section)
local st = xr_logic.assign_storage_and_bind(npc,ini,scheme,section)
end

function disable_scheme(npc,scheme)
local st = db.storage[npc:id()][scheme]
if st then
st.enabled = false
end
end

ltx-фаил

;--------------------------------------

; Модуль knife
; Rulix aka Bak
;--------------------------------------

[main]
enabled = true
check_period = 1001 ;мс ; время между проверками
forbidden_weapons = none ; запрещенное к использованию оружие
forbidden_factions = zombied
forbidden_npcs = none
fire_dist = 1.5

[novice]
rate = 0.6 ; ударов в секунду

[experienced]
rate = 1.1

[veteran]
rate = 1.3

[master]
rate = 2

;---------------------------------------
[stalker]
rate_add = 0
courage = 0.9
attack_wounded = 0.1
mutant_hunt = true

[bandit]
rate_add = 0.1
courage = 0.7
attack_wounded = 0.2
mutant_hunt = false

[freedom]
rate_add = 0.3
courage = 1.4
attack_wounded = 0.2
mutant_hunt = true

[dolg]
rate_add = 0
courage = 1
attack_wounded = 0
mutant_hunt = true

[killer]
rate_add = 0.2
courage = 0.8
attack_wounded = 0
mutant_hunt = true

[military]
rate_add = 0
courage = 0.6
attack_wounded = 0
mutant_hunt = false

[ecolog]
rate_add = 0
courage = 0.1
attack_wounded = 0
mutant_hunt = false

[monolith]
rate_add = 0
courage = 1.5
attack_wounded = 0.05
mutant_hunt = false

Скрин

post-23395-0-56300200-1445767417_thumb.jpg

Изменено пользователем Gaz24

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   1 пользователь

AMK-Team.ru

×
×
  • Создать...