Я тут юзал мобильныйл телепортатор singapur'a22 - хотел выдрать саму функцию, которая телепортирует, но не могу понять, что нужно выдрать.
Вот полный скрипт:
class "list_item" (CUIListItemEx) --\\ отдельный класс для ItemList. Обязательное условие.
function list_item:__init() super()
self:SetWndRect (0,0,150,29)
self.fn = CUIStatic ()
self.fn:SetAutoDelete (true) --включить автоудаление
self:AttachChild (self.fn) --создать виджет
self.fn:SetWndRect (0,0,150,29) --задать координаты и размеры виджета
self.fn:SetText ("level_name") --загрузить текст
self.fn:SetTextY (6) --позиция отображения текста по Y
self.fn:InitTexture("ui\\ui_btn_mm_h") --загрузить текстуру
self.fn:SetOriginalRect(0, 0, 255, 37) --координаты захвата текстуры из указанного файла dds
self.fn:SetStretchTexture(true) --растяжка текстуры по размерам виджета
self.fn:SetTextAlign(2) --центрировать текст
end
--инициализация
function mobile_changer:__init() super()
local index_level = alife():level_id()
self.name_level = alife():level_name(index_level)
self:Init(50,50,900,640)
-----------------------------------------
-- интерфейс
self.xml = CScriptXmlInit()
self.xml:ParseFile("_mobile_changer.xml")
self.xml:InitStatic("background", self)
-- список локаций
local list = self.xml:InitList("list", self)
list:ShowSelectedItem(false)
list:EnableScrollBar(true)
self:Register(list, "list_window")
self:AddCallback("list_window", ui_events.LIST_ITEM_CLICKED, self.OnListItemClicked, self) --клик по итему
for k,v in ipairs(levels) do
local _itm = list_item() --\\ класс "list_item"
local fn = _itm.fn --\\ блок CUIStatic
fn:SetText( v[2] )
if self.name_level == v[1] then
fn:InitTexture("ui\\ui_btn_mm_t")
fn:SetOriginalRect(0, 0, 255, 37)
end
list:AddItem(_itm)
end
-- блок ввода координат
local vectors = CUIStatic ()
vectors:SetAutoDelete (true)
vectors:Init (225,55,620,80)
vectors:InitTexture ("ui\\ui_frame_dialog_back")
vectors:SetStretchTexture(true)
self:AttachChild (vectors)
local vector_x = self.xml:InitStatic("vector_x", vectors)
local vector_y = self.xml:InitStatic("vector_y", vectors)
local vector_z = self.xml:InitStatic("vector_z", vectors)
local vector_lv = self.xml:InitStatic("vector_lv", vectors)
local vector_gv = self.xml:InitStatic("vector_gv", vectors)
local vector_ln = self.xml:InitStatic("vector_ln", vectors)
-- Enter
local enter = self.xml:Init3tButton("enter", vectors)
enter:EnableTextHighlighting(true)
self:Register(enter,"enter_but")
self:AddCallback("enter_but", ui_events.BUTTON_CLICKED, self.Enter, self)
-- зона с изображениями
local zone_pic = CUIStatic ()
zone_pic:SetAutoDelete (true)
zone_pic:Init (225,140,620,440)
zone_pic:ClipperOn(true)
self:AttachChild (zone_pic)
local picX,picY,picW,picH = 30,5,128,96
for i=1, 16 do
local fX,fY = 1,0
if i>4 and i<=8 then
fX,fY = 5,1
elseif i>8 and i<=12 then
fX,fY = 9,2
elseif i>12 then
fX,fY = 13,3
end
local picXs = picX + (picW + 10) * (i-fX)
local picYs = picY + (picH + 10) * fY
local pic = CUIStatic()
pic:SetAutoDelete (true)
pic:SetWindowName ("pic"..i)
pic:Init (picXs,picYs,picW,picH)
local fon = _change_list.jump_to_level(self.name_level, i)
if fon then
pic:InitTexture (fon['pic'])
pic:SetOriginalRect(0, 0, 128, 96)
else
pic:InitTexture ("ui\\ui_frame_dialog_back")
end
pic:SetStretchTexture(true)
zone_pic:AttachChild (pic)
--функция выбора локации
function mobile_changer:OnListItemClicked()
local list = self:GetListWnd("list_window") --\\определить list
if list:GetSize()==0 then return end --\\если лист пуст, то завершить выполнение функции
local index = list:GetSelectedItem() --\\определить индекс нажатого итема
if index == -1 then return end --\\если не один индекс не активен, то завершить выполнение функции
local item = list:GetItem(index) --\\определить CUI итема по индексу
local text = item.fn:GetText() --\\определение текста итема
list:RemoveAll() --\\очистим список
for _,v in ipairs(levels) do
local _itm = list_item() --\\ класс "list_item"
local fn = _itm.fn --\\ блок CUIStatic
fn:SetText(v[2])
if text == v[2] then
fn:InitTexture("ui\\ui_btn_mm_t")
fn:SetOriginalRect(0, 0, 255, 37)
self.name_level = v[1]
end
list:AddItem(_itm)
end
for i=1,16 do
local zone = self:GetStatic("pic"..i)
local fon = _change_list.jump_to_level(self.name_level, i)
if fon then
zone:InitTexture (fon['pic'])
zone:SetOriginalRect(0, 0, 128, 96)
else
zone:InitTexture ("ui\\ui_frame_dialog_back")
end
end
self.vectorLN:SetText(self.name_level)
self:Btn_print(1)
end
--функция старта телепортации (Enter)
function mobile_changer:Enter()
local x = tonumber(self.vectorX:GetText())
local y = tonumber(self.vectorY:GetText())
local z = tonumber(self.vectorZ:GetText())
--вывод ошибки в координатах
if not x then level.start_stop_menu(_mobil_changer.wind_error("Ошибка в координате Х"), true) return
elseif not y then level.start_stop_menu(_mobil_changer.wind_error("Ошибка в координате Y"), true) return
elseif not z then level.start_stop_menu(_mobil_changer.wind_error("Ошибка в координате Z"), true) return
end
if alife():level_name(alife():level_id()) == self.name_level then
self:on_quit()
db.actor:set_actor_position(vector():set(x,y,z))
else
--вывод ошибки в вертексах и имени локации
local lv = tonumber(self.vectorLV:GetText())
local gv = tonumber(self.vectorGV:GetText())
local lev = self.vectorLN:GetText()
if not lv then level.start_stop_menu(_mobil_changer.wind_error("Ошибка в координате LV"), true) return
elseif not gv then level.start_stop_menu(_mobil_changer.wind_error("Ошибка в координате GV"), true) return
elseif not lev then level.start_stop_menu(_mobil_changer.wind_error("Ошибка в имени локации"), true) return
end
self:on_quit()
this.start_level_changer(vector():set(x,y,z), lv, gv, lev)
end
end
--клава
function mobile_changer:OnKeyboard(dik, keyboard_action)
CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
if keyboard_action == ui_events.WINDOW_KEY_PRESSED then
if dik == DIK_keys.DIK_ESCAPE then
self:on_quit()
end
end
return true
end
--выбор секции с координатами
function mobile_changer:Btn_1() self:Btn_print(1) end
function mobile_changer:Btn_2() self:Btn_print(2) end
function mobile_changer:Btn_3() self:Btn_print(3) end
function mobile_changer:Btn_4() self:Btn_print(4) end
function mobile_changer:Btn_5() self:Btn_print(5) end
function mobile_changer:Btn_6() self:Btn_print(6) end
function mobile_changer:Btn_7() self:Btn_print(7) end
function mobile_changer:Btn_8() self:Btn_print(8) end
function mobile_changer:Btn_9() self:Btn_print(9) end
function mobile_changer:Btn_10() self:Btn_print(10) end
function mobile_changer:Btn_11() self:Btn_print(11) end
function mobile_changer:Btn_12() self:Btn_print(12) end
function mobile_changer:Btn_13() self:Btn_print(13) end
function mobile_changer:Btn_14() self:Btn_print(14) end
function mobile_changer:Btn_15() self:Btn_print(15) end
function mobile_changer:Btn_16() self:Btn_print(16) end
function mobile_changer:Btn_print(index)
local data = _change_list.jump_to_level(self.name_level, index)
if data then
self.vectorX:SetText(data["pos_x"])
self.vectorY:SetText(data["pos_y"])
self.vectorZ:SetText(data["pos_z"])
self.vectorLV:SetText(data["lvid"])
self.vectorGV:SetText(data["gvid"])
else
self.vectorX:SetText('')
self.vectorY:SetText('')
self.vectorZ:SetText('')
self.vectorLV:SetText('')
self.vectorGV:SetText('')
end
for i=1,16 do
local btn = self:GetButton("btn"..i)
if index == i then
btn:InitTexture("ui\\ramka")
else
btn:InitTexture("ui\\clear")
end
end
end
--выход
function mobile_changer:on_quit()
self:GetHolder():start_stop_menu (self,true)
end
function start_level_changer(p_dest_pos, p_dest_lv, p_dest_gv, p_dest_level)
local obj = alife():create("level_changer", db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id())
local packet = net_packet()
obj:STATE_Write(packet)
-- свойства cse_alife_object
local game_vertex_id = packet:r_u16()
local distance = packet:r_float()
local direct_control = packet:r_u32()
local level_vertex_id = packet:r_u32()
local object_flags = packet:r_u32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_u32()
local spawn_story_id = packet:r_u32()
-- свойства cse_shape
local shape_count = packet:r_u8()
for i=1,shape_count do
local shape_type = packet:r_u8()
if shape_type == 0 then
-- sphere
local center = packet:r_vec3()
local radius = packet:r_float()
else
-- box
local axis_x = packet:r_vec3()
local axis_y = packet:r_vec3()
local axis_z = packet:r_vec3()
local offset = packet:r_vec3()
end
end
-- свойства cse_alife_space_restrictor
local restrictor_type = packet:r_u8()
-- свойства cse_alife_level_changer
local dest_game_vertex_id = packet:r_u16()
local dest_level_vertex_id = packet:r_u32()
local dest_position = packet:r_vec3()
local dest_direction = packet:r_vec3()
local dest_level_name = packet:r_stringZ()
local dest_graph_point = packet:r_stringZ()
local silent_mode = packet:r_u8()
packet:r_seek(0)
obj:STATE_Read(packet, packet:w_tell())
end
function start_del()
local obj = alife():story_object( 46489 )
if obj then
db.actor:set_fastcall(del_changer, db.actor)
end
end
function del_changer()
local obj = alife():story_object( 46489 )
if obj then
local lv_ch = game_graph():vertex(obj.m_game_vertex_id):level_id() --определяем id локации нахождения временного чейнджера
local lv_ac = alife():level_id() --определяем id текущей локации
if lv_ch ~= lv_ac then --если не равны
alife():release(obj, true) --то удаляем временный чейнджер
end
end
end
start_del()
Вот это, как я понимаю, спавнится левел_чаннжер прям рядом с ГГ:
Код:
function start_level_changer(p_dest_pos, p_dest_lv, p_dest_gv, p_dest_level)
local obj = alife():create("level_changer", db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id())
local packet = net_packet()
obj:STATE_Write(packet)
-- свойства cse_alife_object
local game_vertex_id = packet:r_u16()
local distance = packet:r_float()
local direct_control = packet:r_u32()
local level_vertex_id = packet:r_u32()
local object_flags = packet:r_u32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_u32()
local spawn_story_id = packet:r_u32()
-- свойства cse_shape
local shape_count = packet:r_u8()
for i=1,shape_count do
local shape_type = packet:r_u8()
if shape_type == 0 then
-- sphere
local center = packet:r_vec3()
local radius = packet:r_float()
else
-- box
local axis_x = packet:r_vec3()
local axis_y = packet:r_vec3()
local axis_z = packet:r_vec3()
local offset = packet:r_vec3()
end
end
-- свойства cse_alife_space_restrictor
local restrictor_type = packet:r_u8()
-- свойства cse_alife_level_changer
local dest_game_vertex_id = packet:r_u16()
local dest_level_vertex_id = packet:r_u32()
local dest_position = packet:r_vec3()
local dest_direction = packet:r_vec3()
local dest_level_name = packet:r_stringZ()
local dest_graph_point = packet:r_stringZ()
local silent_mode = packet:r_u8()
ЦитатаПоправка НЕ принимается, т.к. по сути бессмысленна.
Работа гулага там (на той локации), где гулаг! Естественно гулаги могут быть на любой локации и соответственно их работы тоже, но именно на локации соответствующего гулага.
Вспоминаем - работа начинает выполняться по достижении некоторой дистанции до гулага, а значит - соответствующей локации. В теории можно задать рестрикторами работу где-то ... но выполняться она не будет, т.к. флаг достижения гулага будет сбрасываться как только ...
Artos вы заблуждаетесь работа начинает выполнятся не при достижении некоторой дистанции до гулага а при достижении некоторой дистанции до места работы вот цитата всем известной статьи про логику пункт 6 и пункт 7 тоже смотреть
3.11.3. Новые особенности смарттеррейнов
Возможности нового смарттеррейна (СТ):
1) Не держит сталкеров постоянно в онлайне. Работает стандартный онлайн-радиус.
2) Сталкеры идут на ближайшие работы.
3) На места работ сталкеры идут независимо от того, в онлайне они или в оффлайне.
4) СТ в офлайне работает так же, как и в онлайне: выполняет переключение своих состояний, перераспределение работ.
5) Сталкерам можно прописать, при каких условиях в какие СТ они могут идти. (см. ниже) Если сталкер попал в СТ, то онбудет находится в нём, пока не истечёт время и выполняется условие. 6) Работы могут находиться на разных уровнях. 7) Скриптовая зона СТ теперь не используется для захвата персонажей.8) Симуляция заключается в миграции персонажей между разными СТ.
да и если посмотреть файл gulag_general.script (универсальные гулаги) видно что координаты работ данного гулага находяться на разных уровнях правда загружаемых динамически что впрочем не мешает сделать и статически .
Вобще разделение гулагов по уровням только для удобства можно создать один гулаг на всю игру с работами на разных уровнях и для разных неписей
ЦитатаТоже неудачная попытка поправки/пояснения.
Смарт-терейн - а) объект игры, а не некие преустановки! Он имеет и геометрию (cse_shape properties), т.е. позицию и радиус(ы)! Это именно территория, ограниченная некоей границей. Собственно и само название 'smart terrain' - 'умный ландшафт', т.е. область на локации, в пределах которой работает некая логика.
Ну а уж гулаг - это уже логический/организационный объект, т.е. набор предустановок и пр. ... И есть он или нет - свойства смарта!
Смарт-терейн именно предустановки для гулага никакой геометрии он не имеет (верней имеет но это поБочный эфект работы в СДК (Сказанно не мной а IG-2007)
Параметр (cse_shape properties), вобше ни на что не влияет главное чтоб значение было отлично от нуля хоть 0.34556788 хоть 0.000000001 (проверенно впрочем можете проверить сами)
Не нужно мне пояснять о том что 'некое' условие - инфопоршень. Я пишу общим определением! И если для тебя 'некое' только инфопоршень из оригинальных кодов, то мое определение дает 'свободу' и смена Волка на Фаната, к примеру, может поизводится любым подходящим событием, который взбредет в голову модмейкеру. И сними шоры! Фанат в игре изначально заспавнен! Хотя собственно это не столь уж важно для конкретного случая для SkyLoader.
Заставить его проявиться, заставить уйти Волка на Склады иль еще чего - не суть разбираемого вопроса.
Фанат изначально присутствует в алл спавне только спаунится при определенных условиях
Зы. Извените если чем-то обидел или задел но истина дороже
SkyLoader.
нет пакет переписывается только если непись в оф лайне
STALKER 7777 не может открыть секцию identity_immunities = выход, добавить эту секцию ( =скорее всего это в папке креэйчурс, там в твой файл скопируй эту секцию из других файлов)
имя файла.start_level_changer(позиция, левел вертекс, гейм вертекс, скриптовое наименование локации)
все передаваемые параметры являются координатами места назначения.
erlik
Здарова. В том то и дело, что размер как положено, даже меньшим делал, как по пикселам, так и по ёмкости.
Про C#, я уже забыл как он выглядит
У меня щас временная передышка. Занялся ремонтом квартиры. Вот и решил вспомнить Сталкера. Както потянуло по новой.
function test()
this.test22222(vector():set(156.42, 0.17, 71.66), 41158, 1180, l05_bar)
end
test()
function test22222(p_dest_pos, p_dest_lv, p_dest_gv, p_dest_level)
local obj = alife():create("level_changer", db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id())
local packet = net_packet()
obj:STATE_Write(packet)
-- свойства cse_alife_object
local game_vertex_id = packet:r_u16()
local distance = packet:r_float()
local direct_control = packet:r_u32()
local level_vertex_id = packet:r_u32()
local object_flags = packet:r_u32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_u32()
local spawn_story_id = packet:r_u32()
-- свойства cse_shape
local shape_count = packet:r_u8()
for i=1,shape_count do
local shape_type = packet:r_u8()
if shape_type == 0 then
-- sphere
local center = packet:r_vec3()
local radius = packet:r_float()
else
-- box
local axis_x = packet:r_vec3()
local axis_y = packet:r_vec3()
local axis_z = packet:r_vec3()
local offset = packet:r_vec3()
end
end
-- свойства cse_alife_space_restrictor
local restrictor_type = packet:r_u8()
-- свойства cse_alife_level_changer
local dest_game_vertex_id = packet:r_u16()
local dest_level_vertex_id = packet:r_u32()
local dest_position = packet:r_vec3()
local dest_direction = packet:r_vec3()
local dest_level_name = packet:r_stringZ()
local dest_graph_point = packet:r_stringZ()
local silent_mode = packet:r_u8()
packet:r_seek(0)
obj:STATE_Read(packet, packet:w_tell())
end
Пишет ошибку:new_test.script:2:_attempt_to_index_global_'this'_(a_nil_value).Если поменять местоположение функций:
Код:
function test()
this.test22222(vector():set(156.42, 0.17, 71.66), 41158, 1180, l05_bar)
end
function test22222(p_dest_pos, p_dest_lv, p_dest_gv, p_dest_level)
local obj = alife():create("level_changer", db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id())
local packet = net_packet()
obj:STATE_Write(packet)
-- свойства cse_alife_object
local game_vertex_id = packet:r_u16()
local distance = packet:r_float()
local direct_control = packet:r_u32()
local level_vertex_id = packet:r_u32()
local object_flags = packet:r_u32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_u32()
local spawn_story_id = packet:r_u32()
-- свойства cse_shape
local shape_count = packet:r_u8()
for i=1,shape_count do
local shape_type = packet:r_u8()
if shape_type == 0 then
-- sphere
local center = packet:r_vec3()
local radius = packet:r_float()
else
-- box
local axis_x = packet:r_vec3()
local axis_y = packet:r_vec3()
local axis_z = packet:r_vec3()
local offset = packet:r_vec3()
end
end
-- свойства cse_alife_space_restrictor
local restrictor_type = packet:r_u8()
-- свойства cse_alife_level_changer
local dest_game_vertex_id = packet:r_u16()
local dest_level_vertex_id = packet:r_u32()
local dest_position = packet:r_vec3()
local dest_direction = packet:r_vec3()
local dest_level_name = packet:r_stringZ()
local dest_graph_point = packet:r_stringZ()
local silent_mode = packet:r_u8()
Stalk15 Я так понимаю ты активируешь функцию через dofile(...). Если нет. Если вызов производится на момент загрузки, то ничего удивительного.
В первом случае ошибку получил изза того, что чтение стартовой функции производилось раньше загрузки основной функции. Во втором ... уточни на счёт вызова.
singapur22
Да, через dofile(...).Ща попробовал вызвать по обычному - через диалог:
<action>for_chek.test</action>
Файл for_chek:
Код:
function test()
news_manager.send_tip(db.actor, "шшщш.", 0, "trader", 7000)
this.test22222(vector():set(156.42, 0.17, 71.66), 41158, 1180, l05_bar)
end
function test22222(p_dest_pos, p_dest_lv, p_dest_gv, p_dest_level)
local obj = alife():create("level_changer", db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id())
local packet = net_packet()
obj:STATE_Write(packet)
-- свойства cse_alife_object
local game_vertex_id = packet:r_u16()
local distance = packet:r_float()
local direct_control = packet:r_u32()
local level_vertex_id = packet:r_u32()
local object_flags = packet:r_u32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_u32()
local spawn_story_id = packet:r_u32()
-- свойства cse_shape
local shape_count = packet:r_u8()
for i=1,shape_count do
local shape_type = packet:r_u8()
if shape_type == 0 then
-- sphere
local center = packet:r_vec3()
local radius = packet:r_float()
else
-- box
local axis_x = packet:r_vec3()
local axis_y = packet:r_vec3()
local axis_z = packet:r_vec3()
local offset = packet:r_vec3()
end
end
-- свойства cse_alife_space_restrictor
local restrictor_type = packet:r_u8()
-- свойства cse_alife_level_changer
local dest_game_vertex_id = packet:r_u16()
local dest_level_vertex_id = packet:r_u32()
local dest_position = packet:r_vec3()
local dest_direction = packet:r_vec3()
local dest_level_name = packet:r_stringZ()
local dest_graph_point = packet:r_stringZ()
local silent_mode = packet:r_u8()
Люди, здравствуйте.
Итак, вопрос(ы):
В конфигах оружия прописаны различные параметры, и игра их использует. То есть как-то получает значения этих параметров.
А как человеку получить значения этих параметров? А именно: как статичные (скорострельность, макс. объем рожка), так и изменяемые (кол-во патронов, повреждение ствола)...
Должен же быть метод для их получения?
Есть ли функция для отслеживания выстрела? Если ГГ произвел выстрел, возвращает true, а то отслеживать через изменение кол-ва патронов в рожке не всегда возможно.
function line_count(string);
function r_bool(string, string);
function section_exist(string);
function r_float(string, string);
function r_clsid(string, string);
function r_s32(string, string);
function r_line(ini_file*, string, number, string&, string&);
function r_token(string, string, const token_list&);
function r_vector(string, string);
function r_u32(string, string);
function r_string_wq(string, string);
function r_string(string, string);
function line_exist(string, string);
};
Примеров куча, ближе всего - у erlik'а в заметке 'Рандомный хабар для тайников'.
vhodnoylogin
Все параметры можно считать из конфиг файла нужного ствола. Есть специальные методы - описанные в справочнике по функциям и классам.
Простой пример - считываем размер магазина у калаша
local SizeMagazin = system_ini():r_u32("wpn_ak74", "ammo_mag_size")
system_ini() - метод обращения к конфигурационным файлам игры указанных в файле sistem.ltx. К нему и применяются методы чтения.
Так как параметр ammo_mag_size - 32 разрядное целое число, то и метод чтения - r_u32( ) - соответствующий.
Для считывания string - строки - есть другой метод. Также как и для разных типов чисел, векторов, булевых значений и т.д.
Состояние ствола\брони можно узнать через метод condition().
Дефолтной функции от разрабов для отслеживания выстрела не существует - есть только самописные варианты - через изменение кол-ва патронов в рожке например. Или через хит_каллбек в xr_motivator'e.
А вот тебе и Darien Fx список методов чтения привел - разбирайся.
добавлено спустя 26 минут
------------------------------------------------------------------------------------------------------------------------
Кстати недавно баловался с каллбеками и выяснил, что их можно устанавливать точечно(без использования имеющихся биндеров) - на конкретные объекты, если конечно объект поддерживает хоть какой-нибудь каллбек.
Вот так можно на волка поставить каллбек на хит
Код:
function WolfCall()
local obj = level_object_by_sid(6)
obj:set_callback(callback.hit, Callback)
end
После вызова этой функции при наступлении нужного события указанная как аргумент функция Callback(имя задается произвольное) будет вызвана. То бишь например пишем
function Callback()
news_manager.send_tip(db.actor, "Волк получил хит", 0, nil, 5000)
end
И при хите волка получим сообщение.
На NPC\тачках\дверях\ящиках работает каллбек на юз - callback.use_object.
Код:
function BoxCall()
local oSBox = alife():object("level_prefix_inventory_box_0003") -- неуловимый ящик сидора :-)
local oCBox = level.object_by_id(oSBox.id) -- получаем клиентский объект - иначе нельзя.
if oCBox then
oCBox:set_callback(callback.use_object, RandomSpawnItems)
news_manager.send_tip(db.actor, "Каллбек на ящик установлен", 0, nil, 5000)
oCBox:set_tip_text("Руки прочь от чужого добра!!!") -- всплывающая надпись при наведении на предмет.
end
end
Также на NPC можно поставить callback.death.
Отменить\аннулировать каллбек можно так obj:set_callback(callback.use_object, nil) -- вместо имени функции указываем nil - и данный каллбек для этого объекта больше не вызывается - пока заново не установить.
Сообщение было успешно отредактировано erlik (09-08-2010 21:53 GMT3 часа, назад)
Еще пару вопросов:
есть ли различие между предметом в инвентаре и им же, но на земле (помещаясь в инвентарь, предмет получает новое ID)? Или, спрашивая по-другому, существует некое "инвентарное" ID?
На счет ф-ии condition(): что она делает? Может выдать информацию о стволе или изменять этот параметр?
Или это перегрузка: condition() - инфа condition(num) - "лечение" ствола (где num - (float?) от 0.0 до 1.0)
НА счет проверки наличия выстрела. Можно ли проверить выстрел по косвенным признакам: а именно, по анимации выстрела (патикл, кажется так называется)? Или через отслеживание нажатия на кнопку выстрела (но это трудно - возникают многие другие вопросы)...
PS:
Dietrich2009, а где ты такую аватарку нашел? Интересно знать источник.
Сообщение было успешно отредактировано vhodnoylogin (10-08-2010 01:26 GMT3 часа, назад)
Чувак на болоте, лично я знаю такой способ: satiety_v - ;скорость уменьшения сытости со временем satiety_health_v - ;увеличение здоровья при уменьшении сытости
Из этого следует, что ты ставишь большое значение для satiety_health_v и малое для satiety_v.
Сам таким методом пользовался этим способом и не понимал, почему я так быстро лечусь сам.
Раз о конфигах, то: что такое мораль, зачем нужна и что дает?
Сообщение было успешно отредактировано vhodnoylogin (10-08-2010 01:39 GMT3 часа, назад)
vhodnoylogin
condition() возвращает состояние предмета к которому это метод применяется. Аргументов у метода нет.
Ремонт\ломание ствола не condition(num) - а set_condition(num) -аргумент число от 0 до 1 - где 0 будет ствол в хлам, а 1 - как новенький. Оба методы применяются к клиентской юзердате объекта.
Айдишка вроде как не меняется (хотя высказывались мнения что все таки меняется в процессе игры) - но по моему опыту могу сказать что от перемещения объекта с земли в инвентарь и обратно айди не меняется.
Инвентарного айди нет,но есть порядковый номер инвентарного объекта в массиве куда заносятся все объекты инвентаря - при итерации рюкзака\массива объектов рюкзака как раз можно использовать эти порядковые номера через метод object(число)
local cnt = db.actor:object_count() -- возвращает кол-во объектов в инвентаре ГГ
for i=0,cnt-1 do -- итерация номеров
local item = db.actor:object(i) --возвращает объект по его номеру в инвентаре
и номера эти если объект поперемещать туда-сюда как раз меняются.
-----------------------------------------------------------------------------------
Отследить нажатие ЛКМ (как и ПКМ) напрямую нельзя - не предусмотрено(разве что кейлоггером). Только косвенно. Как - уже писалось. ПКМ можно по изменению accuracy() - точности. По анимации выстрела - не представляю как.
Сообщение было успешно отредактировано erlik (10-08-2010 02:13 GMT3 часа, назад)
AAAAKKK
Что-то часто заучат фразы о поправкахи заблуждениях, при чем аргументация ... "а вот прочти там ..."
Начну с конца (так проще):
Цитатанет пакет переписывается только если непись в оф лайне
Абсолютно неверное утверждение. Если объект существует, то изменение (перезапись) нет-пакета объекта возможна условно В ЛЮБОЙ момент времени (главное не попасть в момент 'штатной' перезаписи, чтобы не возникли коллизии). Иное дело, что внесенные изменения могут проявиться не сразу, а по прошествии некоторого времени. Для ускорения этого процесса можно использовать принудительный метод, отравляя объект в офф-лайн и возврат его в он-лайн с уже обновленными параметрами.
Собственно изменения/перезапись нет пакетов происходят для серверных объектов, для которых состояние 'он-лайн' - только некоторое состояние одного из параметров, и неясно чем вызвана такая категоричность процитированной фразы.
Не вижу смысла далее дискутировать на тему смартов/гулагов, т.к. диалог идет на разных языках. Во-первых, мы все тут пишем не научные трактаты, а достаточно сжатые сообщения, в которых порой нет цели максимально правильно и всесторонне формулировать все затронутые понятия. И во-вторых, если уж затрагивается/оспаривается одно, то не перескакивают на следующее ... Если цель - достижение правильного толкования и практического применения, то диалог возможен далее. Если же цель - перебрасывание субъективными аксиомами - не вижу смысла далее продолжать.
Меня поправляешь отказывая смарту в признаке 'территории', называя объект - предустановками, забывая, элементарное: точка - это тоже площадь, хотя и выродившаяся до точки.
Итак, смарт-террейн это объект, имеющий некий центр, радиус , т.е некая территория или же начнем опять приводить крайности и необязательности, нивелируя его до 'предустановки'?
Не стОит мне в качестве аргументов приводить некие статьи, даже написанные кем-либо из разрабов.
а) Никогда всех нюансов кодов не описать в статье для 'остальных'
б) После написания коды были не раз изменены.
... и т.д.
Взгянув не в статью, а в коды (не призываю их анализировать и делать выводи исходя из них), но даже комменты самих разрабов уже опровергают:
Цитата--/ условия достижения персонажем места работы:
--/ а) в офлайне: персонаж пришёл на нужную точку графа
--/ б) в онлайне: персонаж продошёл на расстояние iJobPositionThreshold
Для чего(?) приводить тавтологию типа:
Цитата... работа начинает выполнятся не при достижении некоторой дистанции до гулага а при достижении некоторой дистанции до места работы ...
Есть точка отсчета - гулаг, он же смарт-террейн, от него отсчитывается некая дистанция 'Job.position_threshold', которая считается 'дистанцией/позицией достижения работы'. Что неправильного в первоначальной моей фразе???
Расстояние от города до города можно считать хоть от окраины до окраины, хоть от центра, до цента. Но(!) базовой точкой отсчета будет все равно ЦЕНТР, о не производная от него.
Все далее лень писать ...
erlik
Однозначно, игровой идентификатор объектов в игре (ID) назначается один раз (при первичном спавне) и неизменен на всем протяжении игры или до уничтожения объекта.
Каких либо метаморфоз с идентификатором при перемещении объекта в рюкзак иль еще куда и обратно НЕ происходит.
Те, кто утвердает/высказывает обратное мнение путают банальное - при некоторых операциях с рюкзачными предметами порой объект удаляется и спавнится вновь или нечто аналогичное. Естественно у 'него' будет иной ID, но это у же и не 'тот' же объект!
Определить, находится объект в инвентаре, или на земле достаточно просто. Для этого имеется соответствующий метод obj:parent() для клиентского объекта. Возвращает userdata материнского объекта. Тоесть, при перемещении объекта в какой либо инвентарь, объект становится дочерним. Это и будет различием. Если объект не дочерний, то метод вернёт nil. Вот тут то и существует некоторая неясность. По существу перемещённый, да и просто заспавненый объект в инвентарь не удаляется и не переводится в оффлайн. Он остаётся в онлайне, но при этом не отображается. Смею предположить, что дочерние элементы просто напросто не считываются рендерингом. Но может быть и другая предустановка.
Так же есть и переменная для определения материнства серверного объекта sobj.parent_id. Возвращает айди материнского объекта, тобишь инвентаря.
Как видно из данного списка ничего подобного упомянутого тобой даже близко нету.
Конечно есть колбэк и на взятие предметов из инвентаря и на его туда укладывание. Но как ты понимаешь он не рассматривает колличество взятых или положенных итемов.
Сообщение было успешно отредактировано singapur22 (10-08-2010 12:08 GMT3 часа, назад)
singapur22
Собственно я давал подтверждение по Неизменности игрового ID объекта.
Ну по 'parent_id', я бы не назвал достаточно простым определение нахождения в инчентаре.
1. Само понятие 'в инвентаре' - расплывчато для игроков. Если считать по 'parent_id' (идентификатору владельца), но находясь в руках/слотах/поясе - это вроде как не в инвентаре, т.е. путаница. Есть и более неочевидные моменты. Из вопроса vhodnoylogin онозначно понять что его интересует невозможно.
2. Все же метод 'obj:parent()' и переменная sobj.parent_id - методы определения владельца, коим не обязательно может быть актор или непись. Это могут быть и ящики и пр. , т.е. однозначности в принадлежности к инвентори тут нет.
3. Как ты сам указал, метод obj:parent() для клиентского объекта, т.о. существуют моменты/периоды, когда объест уже/еще НЕ в инвенторе. Задержки изменения признака 'parent' - от 3-4 апдейтов актора. Это следует учитывать.
Artos Это всё понятно. Я лишь обобщённо прояснил ситуацию. Точнее я понял так, что vhodnoylogin понадобилось узнать имеет ли объект хоть какието различия находясь в инвентаре или на воле. Вот я и выдвинул метод определения, который именно за это и отвечает. А то, что объект может быть как в инвентаре актора, или в ящике, сути не меняет. В обоих случаях объект становится дочерним. Всё остальное примочки распределения дочерних объектов. С нпс вообще сложная конструкция. Первая ступень дочерности именно инвентарь, после него уже идёт пояс и всё остальное. Не будем вдаваться в подробности, это уже отдельная тема которая никакого отношения к данному случаю не имеет.
А на счёт тебя, скажу так. Довольно расплывчато написал. Тобишь я не совсем понял. Вот и отметил. Извиняй, если что.
Сообщение было успешно отредактировано singapur22 (10-08-2010 12:48 GMT3 часа, назад)
Stalk15
В bind_stalker есть что то типа каллбека на взятие вещи из ящика:
actor_binder:take_item_from_box(box, item)
функция возвращает юзердату ящика и объекты взятых итемов.
проверка на то что ящик пустой if box:is_inv_box_empty() == true then -- не помню работает ли.
Можешь на ящик (например какой то один конкретный) поставить каллбек на юзание тем способом что я описал, а в функции которая будет вызываться при обыске ящика поставить указанную проверку на пустой ли ящик. И если пустой - то нужное действие.
--------------------------------------------------------------
Проверил - проверка на пуст ли ящик - работает.
Но срабатывает только на вторичный юз ящика - уже после его опустошения.
Так что тут придется видимо ставить на апдейт эту проверку - если ты хочешь чтобы она срабатывала сразу же после того, как из ящика изъяли все вещи. Или ящик на fastcall поставить.
Сообщение было успешно отредактировано erlik (10-08-2010 13:15 GMT3 часа, назад)
erlik
Спасибо, я тоже проверил
Думал, что можно такой колбэk поставить:take_item_from_box, но что-то не сработал.
Значит апдейтом надо.
добавлено спустя 7 минут
Хотел проверить, как работает fastcall - так заглючило.Идет Клиент:Синхроризация, а потом бац - опять идет загрузка сейва, потом пару раз все потухло и вылетело.Если что, вот как я делал:
В actor_binder:net_spawn(data):
Код:
for_chek.test()
Файл for_chek:
Код:
local fast = false
function test()
if not fast then
db.actor:set_fastcall( fastcall, db.actor )
fast = not fast
end
end
function fastcall()
this.fastgeg()
end
function fastgeg()
if db.actor:object("medkit") then
news_manager.send_tip(db.actor, "Апдейт пашет", 0, nil, 5000)
end
end
Может, что не правильно сделал?
Сообщение было успешно отредактировано Stalk15 (10-08-2010 13:38 GMT3 часа, назад)
Stalk15
На net_spawn вызов я не ставил. У меня именно на апдейте фасткал вызывается при каждой загрузке
- для моей гравипушки.
В общем я сейчас замутил такую хитрую штуку
Код:
-- функция установки быстрого обработчика - вызывается каллбеком
function BoxFastcall(oCBox)
if oCBox then
oCBox:set_fastcall( BoxEmpty, oCBox)-- передаем имя функции, которая будет вызываться обработчиком и объект
end
end
-- функция которая вызывается фасткаллом
function BoxEmpty(oCBox)
if oCBox then
if oCBox:is_inv_box_empty() then -- если ящик пустой
news_manager.send_tip(db.actor, "Ящик пустой ", 0, nil, 5000)
oCBox:set_fastcall(nil, nil) -- фаскалл отключаем
end
end
end
-- функция установки каллбека(активируется единожды) на юз ящика
function BoxCall(oCBox)
oCBox:set_callback(callback.use_object, BoxFastcall)
news_manager.send_tip(db.actor, "Каллбек на ящик установлен", 0, nil, 5000)
oCBox:set_tip_text("Руки прочь от чужого добра!!!")
end
function SpawnBoxInBunker() -- функция активации каллбека
local oSBox = alife():object("level_prefix_inventory_box_0003")
if oSBox== nil then
news_manager.send_tip(db.actor, "Серверный объект ящика не существует", 0, nil, 5000)
return end
local oCBox = level.object_by_id(oSBox.id)
if oCBox then
level.map_add_object_spot_ser(oCBox:id(), "user", "Метка на ящик Сидора")
this.BoxCall(oCBox) -- вызов функции установки каллбека
end
end
Теперь как только ящик опустошить - получим сообщение, что он пуст.
-------------------------------------------------------------------- Darien Fx
Об этом я не подумал - хотел передавать объект через скобки в вызове - а раз можно так, то еще лучше
-------------------
Проверил - каллбек также объект передает. Исправил весь код на более компактный вариант.
Спасибо за подсказку.
------------------------------------------------------------------------------------------------- Stalk15
ЦитатаДумал, что можно такой колбэk поставить:take_item_from_box, но что-то не сработал.
Для объектов ящиков этот каллбек действительно не пашет - он только для эктора - то есть ставится на объект эктора и вызывается при взятии им вещи из какого либо инвентарного ящика. И если не пользоваться вызовом из биндера эктора, а установить его вручную
Эта тема закрыта, публикация новых сообщений недоступна.
Продолжая пользоваться сайтом, вы соглашаетесь с использованием файлов cookie. Страницы сайта могут содержать информацию, запрещенную для просмотра посетителям младше 18 лет. Авторское право на серию игр «S.T.A.L.K.E.R» и используемые в ней материалы принадлежит GSC Game World.