Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[ ----------------------------------------------------------------------------------------------
- Ïëàòôîðìû: CoP 1.6.2
- Îïèñàíèå : Ñêðèïòîâûé ìåíåäæåð îðóæèÿ äëÿ ÍÏÑ
- Ïîääåðæêà: 2013 © Shoker Mod
- Àâòîðû : Shoker
- Âåðñèÿ : 3.0 (01.01.2014) - ýòà âåðñèÿ èñïîëüçóåò äâèæêîâóþ ïðàâêó òèïà îðóæèÿ, äàáû äâèæêîâûé ìåíåäæåð âûáèðàë åãî â ïîñëåäíèþ î÷åðåäü
- --]] ----------------------------------------------------------------------------------------------
- local DIST_MEMORY_TIME = xr_danger.DANGER_INERTION_TIME or 30000 --> Âðåìÿ ïîñëå ïîòåðè âðàãà, êîòîðîå ÍÏÑ åù¸ íå ïðîáóåò ìåíÿòü îðóæèå
- local NEXT_UPD_TIME = 3000 --> Èíòåðâàë â ì\ñåê, ÷åðåç êîòîðûé ÍÏÑ ïðîáóåò âûáðàòü ñåáå íîâîå îðóæèå
- local NEXT_UPD_TIME_MST = 9000 --> Òîæå ñàìîå, íî âðàã ìîíñòð è îí áëèçêî
- local CLS_DISTANCE = 20 --> Äèñòàíöèÿ, êîòîðàÿ ñ÷èòàåòñÿ áëèçêîé
- local PST_DISTANCE = 9 --> Äèñòàíöèÿ, íà êîòîðîé ÍÏÑ ëó÷øå ïåðåêëþ÷èòñÿ íà ïèñòîëåò åñëè ïàòðîíû êîí÷àòñÿ à ÍÏÑ âèäèò âðàãà
- local SEE_DISTANCE = 6 --> Äèñòàíöèÿ, íà êîòîðîé ñ÷èòàåì ÷òî ÍÏÑ âñåãäà âèäèò âðàãà
- local MST_DISTANCE = 5 --> Åñëè ìîíñòðû áëèæå ýòîé äèñòàíöèè òî ñðàçó âçÿòü ïèñòîëåò, åñëè ó íàñ íåòó secondary
- --[[
- Ñóùåñòâóþùèå òèïû îðóæèÿ: (weapon_type)
- * none - îðóæèå, êîòîðîå ÍÏÑ íå ìîãóò èñïîëüçîâàòü (ïî äåôîëòó) - îäíàêî åñëè äðóãîãî îðóæèÿ ó íåãî íå áóäåò, ìîæåò è âçÿòü â ðóêè <!>
- * pistol - ïèñòîëåòû, èñïîëüçóþòñÿ íà áëèçêîé äèñòàíöèè êîãäà â îñíîâíîì êîí÷èëèñü ïàòðîíû, à âðàã áëèçêî, ìåíÿþòñÿ íà PDW
- * pdw - ïèñòîëåòû-ïóëåì¸òû, èñïîëüçóþòñÿ íà áëèçêîé äèñòàíöèè (åñëè íåò äðîáîâèêà), ïðèîðèòåòíåé àâòîìàòîâ
- * sniper - ñíàéïåðñêèå âèíòîâêè, èñïîëüçóþòñÿ êîãäà âðàã äàëåêî
- * dbarshg - äâóõñòâîëêè, õóæå pdw
- * shotgun - äðîáîâèêè, ïðåäïî÷òèòåëüíåé ÷àì pdw äëÿ áëèçêèõ ðàññòîÿíèé
- * auto - àâòîìàòè÷åñêèå âèíòîâêè è ò.ä è ò.ï, îñíîâíîå îðóæèå ñðåäíèõ äèñòàíöèé.
- * mguns - ïóëåì¸òû
- * explosive - âçðûâîîïàñíîå îðóæèå, êîòîðîå ìîæíî èñïîëüçîâàòü òîëüêî èçäàëåêà
- * special - îðóæèå ýòîãî òèïà âñåãäà ëó÷øåå, è ÍÏÑ åãî íå ñìåíÿåò
- --]]
- local primary_types = { --> Äàëüíèé áîé
- auto = 1,
- sniper = 2,
- mguns = 3,
- explosive = 4,
- }
- local secondary_types = { --> Áëèæíèé áîé
- dbarshg = 1,
- pdw = 2,
- shotgun = 3, --> ÷åì áîëüøå öèôðà, òåì áîëüøå ïðèîðèòåò äàííîãî òèïà
- }
- local current_wpn_tbl = {} --> òàáëèöà ãäå õðàíèòñÿ òåêóùèé âûáîð îðóæèÿ è âðåìÿ ñëåäóþùåé âûáîðêè
- --\\ Ïîëó÷àåì òàáëèöó, ãäå õðàíÿòñÿ ïàðàìåòðû òåêóùåãî âûáîðà ÍÏÑ
- function get_tbl(id)
- if current_wpn_tbl[id] == nil then
- current_wpn_tbl[id] = {}
- current_wpn_tbl[id].locked = false --> çàïðåòèòü ñìåíó îðóæèÿ, åñëè êîí÷èëàñü îáîéìà
- current_wpn_tbl[id].cur_id = nil --> ID òåêóùåãî îðóæèÿ
- current_wpn_tbl[id].upd_time = 0 --> âðåìÿ ñëåäóþùåãî âûáîðà
- end
- return current_wpn_tbl[id]
- end
- function get_wpn(ctbl)
- local wpn_id = ctbl.cur_id
- if wpn_id == nil then return nil end
- local wpn = level.object_by_id(wpn_id)
- if wpn == nil or isWeapon(wpn) == false then
- ctbl.cur_id = nil
- return nil
- else
- return wpn
- end
- end
- local wm_list = {} --> ëèñò âñåõ ìåíåäæåðîâ îðóæèÿ [id] = mgr
- --\\ Àïäåéò ÍÏÑ
- function npc_update(npc)
- local id = npc:id()
- if npc:alive() then
- if wm_list[id] == nil then
- wm_list[id] = weapon_manager(npc) --> Ñîçäà¸ì íîâûé ìåíåäæåð
- end
- wm_list[id]:update()
- else
- if wm_list[id] ~= nil then
- wm_list[id]:kill_wm(1) --> ̸ðòâûì ÍÏÑ åãî óáèðàåì
- end
- end
- end
- --\\ Êîëáåê íà net_destroy êëèåíòñêîãî îáúåêòà
- function on_unregistre_obj(obj, id)
- local wpn_mgr = wm_list[id]
- if wpn_mgr ~= nil then
- wpn_mgr:kill_wm(4)
- end
- end
- --------------------------------------
- class "weapon_manager"
- function weapon_manager:__init(npc)
- self.npc_id = npc:id()
- self.npc = npc
- self.last_enemy_time = 0
- self.last_distance = 0
- self.bKilled = false
- self.wpns_list = {} --> Ñïèñîê îðóæèÿ, ïðèíàäëåæàùåãî ÍÏÑ
- self.ctbl = get_tbl(self.npc_id) --> Òàáëèöà ñ òåêóùèì îðóæèåì ÍÏÑ
- end
- --\\ Îáíîâëåíèå ìåíåäæåðà
- function weapon_manager:update()
- self:fill_wpn_list()
- self:get_current_wpn()
- end
- --\\ Ñàìî-ïðîâåðêà ìåíåäæåðà íà âàëèäíîñòü
- function weapon_manager:self_test()
- local npc = level.object_by_id(self.npc_id)
- local snpc = alife():object(self.npc_id)
- local npc_name
- if snpc == nil then
- npc_name = "<snpc = nil>"
- else
- npc_name = snpc:name()
- end
- if npc == nil or not IsStalker(npc) then
- abort("weapon_manager:npc = nil! bKilled = %s, Owner name = %s ", tostring(self.bKilled), npc_name)
- end
- end
- --\\ Óäàëåíèå ìåíåäæåðà
- function weapon_manager:kill_wm(iType)
- self.bKilled = true --> Ôëàã ÷òî ìåíåäæåð áûë "óáèò"
- self.npc = nil --> Óäàëÿåì ññûëêó íà îáúåêò ÍÏÑ
- wm_list[self.npc_id] = nil --> Ñíîñèì ñàì ìåíåäæåð
- end
- --\\ Ñòðîèì ëèñò îðóæèÿ ó ÍÏÑ, à òàêæå ïðÿ÷åì íå òåêóùåå
- function weapon_manager:fill_wpn_list()
- --* Ñòðîèì ñïèñîê îðóæèÿ ó ÍÏÑ
- local function find_wpn(npc, wpn)
- if isWeapon(wpn) then
- self.wpns_list[wpn:id()] = true
- end
- end
- self.npc:iterate_inventory(find_wpn, self.npc)
- --* Äàëåå ïåðåíîñèì âñ¸ íå àêòèâíîå îðóæèå èç èíâåíòîðÿ ÍÏÑ â ÿùèê
- for id, _ in pairs(self.wpns_list) do
- local wpn = level.object_by_id(id)
- local bIsActive = false
- --> Îðóæèå íå ó íàñ â èíâåíòîðå è íå â ÿùèêå - çíà÷èò ìû åãî ïîòåðÿëè
- local parent = nil
- if wpn ~= nil then
- parent = wpn:parent()
- local cwpn = get_wpn(self.ctbl)
- bIsActive = (cwpn ~= nil and cwpn:id() == wpn:id())
- self.Engine = xray.Get(wpn, "CWeapon", true) --> Äàííûå èç ïàìÿòè äëÿ êëèåíòñêîãî îáúåêòà
- if parent == nil or (parent:id() ~= self.npc_id) then
- self.wpns_list[id] = nil --> ñòâîë ïîòåðÿëè
- else
- if bIsActive == false then --> íå àêòèâíîå îðóæèå íûêàåì â ÿùèê
- -- if parent:id() == self.npc_id then
- --self.npc:transfer_item(wpn, box)
- self.Engine:Set("ef_main_weapon_type", 0)
- self.Engine:Set("ef_weapon_type", 0)
- -- end
- else --> àêòèâíîå ñó¸ì ÍÏÑ
- -- if parent:id() == box:id() then
- --box:transfer_item(wpn, self.npc)
- self.Engine:Set("ef_main_weapon_type", _u.ltx(wpn:section(), "ef_main_weapon_type", "num"))
- self.Engine:Set("ef_weapon_type", _u.ltx(wpn:section(), "ef_weapon_type", "num"))
- -- end
- end
- end
- else
- self.wpns_list[id] = nil --> Ñòâîë ïîõîæå óäàäèëèë
- end
- end
- end
- --\\ Íàõîäèì ëó÷øåå îðóæèå äëÿ ÍÏÑ
- function weapon_manager:get_current_wpn()
- local id = self.npc_id
- local npc = self.npc
- local special_wpn = nil --> ñïåö-îðóæèå, èìååò ïðèîðèòåò íà âûáîð.
- local bIsEmptyMag = false --> ôëàã, ÷òî â òåêóùåì îðóæèè êîí÷èëàñü îáîéìà
- local cur_wpn = get_wpn(self.ctbl) --> ññûëêà íà òåêóùåå îðóæèå
- if cur_wpn ~= nil and cur_wpn:get_ammo_in_magazine() == 0 then
- bIsEmptyMag = true
- end
- if self.ctbl.upd_time < time_global() or (bIsEmptyMag == true and self.ctbl.locked == false) then
- self.ctbl.locked = false
- local weapon_tbl = {} --> òàáëèöà âñåõ ñòâîëîâ ó ÍÏÑ âèäà (ñòâîë = òèï)
- local primary, pcost, ppri = nil, 0, 0 --> îñíîâíîå îðóæèå ÍÏÑ (àâòîìàòû, ñíàéïåðñêîå, îñîáîå)
- local secondary, scost, spri = nil, 0, 0 --> âòîðè÷íîå îðóæèå ÍÏÑ (PDW, Äðîáîâèêè)
- local pistol, pst_cost = nil, 0 --> ïèñòîëåò
- local enemy = npc:best_enemy() --> òåêóùèé âðàã ÍÏÑ
- local dist = 10000 --> ðàññòîÿíèå äî âðàãà
- local bSee = false --> âèäèò ëè ÍÏÑ âðàãà
- local bMob = false --> âðàã - ìîíñòð
- if enemy ~= nil then
- dist = npc:position():distance_to(enemy:position())
- self.last_enemy_time = time_global()
- self.last_distance = dist
- if dist <= SEE_DISTANCE then
- bSee = true
- else
- bSee = npc:see(enemy)
- end
- bMob = IsMonster(enemy)
- else
- --* Åñëè âðàã áûë íî èñ÷åç, òî íåêîòîðîå âðåìÿ èñïîëüçóåì òåêóùåå îðóæèå (ïðè óñëîâèè ÷òî îíî ó íàñ âîîáùå åñòü)
- if cur_wpn ~= nil and (time_global() - self.last_enemy_time <= DIST_MEMORY_TIME) then
- self.ctbl.upd_time = time_global() + NEXT_UPD_TIME/2
- return
- end
- end
- local bExpl = false --> îñíîâíîå îðóæèå âçðûâîîïàñíî
- --* Íàõîäèì ëó÷øåå îñíîâíîå è âòîðè÷íîå îðóæèå äëÿ ÍÏÑ
- for wpn_id, bIsActive in pairs(self.wpns_list) do
- local wpn = level.object_by_id(wpn_id)
- if wpn ~= nil then
- ------------------------------------------
- local sec = wpn:section()
- local wpn_type = _u.ltx(sec, "weapon_type", "str") or "none"
- if wpn_type ~= "none" then
- ---------------------------
- local cost = wpn:cost()
- --* Åñëè åñòü îðóæèå òèïà special, òî ñðàçó âûáèðàåì åãî
- if wpn_type == "special" then
- special_wpn = wpn
- break
- end
- --* Èùåì ëó÷øèé ïèñòîëåò
- if wpn_type == "pistol" then
- if math.abs(cost - pst_cost) > 1000 then
- pistol = wpn
- pst_cost = cost
- end
- end
- local wpn_prior = nil
- --* Èùåì ëó÷øåå îñíîâíîå
- wpn_prior = primary_types[wpn_type]
- if wpn_prior ~= nil then
- if wpn_prior >= ppri then
- if (wpn_prior ~= ppri) or (math.abs(cost - pcost) >= 2000) then
- primary = wpn
- pcost = cost
- if wpn_type == "explosive" then
- bExpl = true
- else
- bExpl = false
- end
- end
- end
- end
- wpn_prior = nil
- --* Èùåì ëó÷øåå âòîðè÷íîå
- wpn_prior = secondary_types[wpn_type]
- if wpn_prior ~= nil then
- if wpn_prior >= spri then
- if (wpn_prior ~= spri) or (math.abs(cost - scost) >= 2000) then
- secondary = wpn
- scost = cost
- end
- end
- end
- ---------------------------
- end
- ------------------------------------------
- end
- end
- --* Ïðîâåðÿåì íàøëè ëè õîòü êàêîå òî îðóæèå
- if special_wpn == nil and primary == nil and secondary == nil and pistol == nil then
- return npc:set_weapon(nil, NEXT_UPD_TIME)
- end
- --* Åñëè ó íàñ âçðûâîîïàñíîå îðóæèå, è íåòó çàïàñíîãî, òî ïðîáóåì þçàòü ïèñòîëåò âáëèçè
- if bExpl and secondary == nil then
- secondary = pistol
- end
- --* Åñëè ó íàñ íåòó âðàãà, òî "çàðÿäèì" âñå ñòâîëû ÍÏÑ, äàáû â ãîðÿ÷êå áîÿ îí íå ïîëåç ïåðåçàðÿæàòüñÿ
- if enemy == nil then
- --! Íå ó÷èòûâàåò ÷òî ðàçìåð ìàãàçèíà ìîæåò èçìåíèòüñÿ ñ àïãðåéäîì, íî ýòî ñëèøêîì çàòðàòíî ñ÷èòàòü
- local function set_ammo(wpn)
- if wpn ~= nil then
- local ammo_max = _u.ltx(wpn:section(), "ammo_mag_size", "num") or nil
- if ammo_max ~= nil and wpn:get_ammo_in_magazine() < ammo_max then
- wpn:set_ammo_elapsed(ammo_max)
- end
- end
- end
- set_ammo(primary)
- set_ammo(secondary)
- set_ammo(pistol)
- end
- if special_wpn == nil then --> Òåïåðü âûáèðàåì êàêîé òèï îðóæèÿ íàì ñåé÷àñ þçàòü
- ------------------------------------------
- --* Åñëè âðàã ìîíñòð, è îí íà êðèòè÷íîì ðàññòîÿíèè, òî áåð¸ì ïèñòîëåò ïðè îòñóòñòâèè âòîðè÷íîãî îðóæèÿ
- if bMob == true and dist <= MST_DISTANCE then
- if secondary == nil and pistol ~= nil then
- return npc:set_weapon(pistol, NEXT_UPD_TIME_MST)
- end
- end
- if bMob == false and dist <= PST_DISTANCE and bSee == true then
- if pistol ~= nil then
- if (secondary == nil or secondary:get_ammo_in_magazine() == 0) then
- return npc:set_weapon(pistol, NEXT_UPD_TIME)
- end
- end
- end
- --* Âðàã óæå áëèçêî, ïåðåêëþ÷àåìñÿ íà âòîðè÷íîå
- if dist <= CLS_DISTANCE then
- if secondary ~= nil then
- return npc:set_weapon(secondary, NEXT_UPD_TIME)
- end
- end
- --* Èíà÷å äà¸ì â ðóêè ïåðâîå, ÷òî åñòü
- if primary ~= nil then
- return npc:set_weapon(primary, NEXT_UPD_TIME)
- end
- if secondary ~= nil then
- return npc:set_weapon(secondary, NEXT_UPD_TIME)
- end
- return npc:set_weapon(pistol, NEXT_UPD_TIME)
- ------------------------------------------
- end
- end
- if special_wpn ~= nil then
- return npc:set_weapon(special_wpn, NEXT_UPD_TIME)
- end
- npc:set_weapon(cur_wpn)
- end
- -----------------------------------------------------------------------
- --\\ Ïðèíóäèòåëüíî óñòàíàâëèâàåì ÍÏÑ äàííóþ ïóøêó êàê îñíîâíóþ íà çàäàííûé ïðîìåæóòîê âðåìåíè â ì\ñåê
- function game_object:set_weapon(wpn, upd_time, bLocked)
- if bLocked == nil then bLocked = false end
- if wpn == nil or not isWeapon(wpn) then
- wpn = nil
- end
- local npc = self
- local id = npc:id()
- local ctbl = get_tbl(id)
- --* Íå ïóùàåì îðóæèå íå èç èíâåíòîðÿ ÍÏÑ
- if wpn ~= nil then
- local parent = wpn:parent()
- if parent == nil or (parent:id() ~= id) then
- return nil
- end
- end
- if wpn == nil then
- ctbl.cur_id = nil
- else
- ctbl.cur_id = wpn:id()
- end
- ctbl.locked = bLocked
- if upd_time ~= nil then
- ctbl.upd_time = time_global() + upd_time
- end
- return wpn
- end
- --\\ Ïîëó÷àåì ëó÷øóþ ïóøêó ÍÏÑ
- function game_object:best_weapon()
- local npc = self
- local id = npc:id()
- local ctbl = get_tbl(id)
- return get_wpn(ctbl)
- end
- -----------------------------------------------------
- -- Íåíóæíûå ôóíêöèè, îñòàâëåííûå äëÿ ñîâìåñòèìîñòè --
- -----------------------------------------------------
- --\\ Êîëáåê íà àïäåéò èãðîêà
- local box_upd_time = 0
- function actor_update()
- end
- --\\ Êîëáåê íà ñîõðàíåíèÿ èãðîêà
- function actor_save()
- end
- --\\ Êîëáåê íà ïåðåõîä ÍÏÑ â îôôëàéí
- function npc_switch_offline(sobj)
- end
- --\\ Êîëáåê íà óäàëåíèå ÍÏÑ èç èãðû
- function npc_on_unregister(sobj)
- end
- function onModInit()
- --> Ïóñòûøêà. Èñïîëüçóåì äëÿ çàãðóçêè ñêðèïòà â ïàìÿòü èãðû. (íå ïîìíþ ïî÷åìó prefetch() íå çàþçàë, ìîæåò è ôóíêöèÿ óæå íå íóæíà)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement