diff --git a/res/gamedata/configs/ui/ui_console.xml b/res/gamedata/configs/ui/ui_console.xml
new file mode 100644
index 00000000000..ed5f3861fe0
--- /dev/null
+++ b/res/gamedata/configs/ui/ui_console.xml
@@ -0,0 +1,52 @@
+
+
+ ui\ui_console
+
+
+
+ ui_inGame2_edit_box_1
+
+
+
+
+
+ ui_inGame2_Mp_bigbuttone
+ X
+
+
+
+
+ ui_inGame2_Mp_bigbuttone
+ Execute
+
+
+
+
+ ui_inGame2_Mp_bigbuttone
+ R
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/gamedata/scripts/_console.script b/res/gamedata/scripts/_console.script
new file mode 100644
index 00000000000..caa903b6e66
--- /dev/null
+++ b/res/gamedata/scripts/_console.script
@@ -0,0 +1,501 @@
+--[[ ----------------------------------------------------------------------------------------------
+ Платформы: CoP v1.6.02
+ Описание : Скриптовая консоль
+ Поддержка: 2013 © Shoker Mod
+ Версия : 1.0 (12.09.2013)
+ Автор : Shoker
+ Отдельное спасибо за метод отлова нажатия клавиш: Charsi, Shadows и ColR_iT
+--]] ----------------------------------------------------------------------------------------------
+
+--[[
+ Подключение:
+ * Функция actor_update() на апдейт игрока или любой другой постоянно выполняющийся код
+ * Если нужен вызов из меню, то вставить туда код для вызова консоли
+ * Все изменения в ориг. скриптах игры помечены знаком --#SM+#--
+ * XML-файлы с интерфейсом, сделаны под ЗП но там закоментированы текстуры под ЧН\ТЧ (правда не тестировал)
+--]]
+
+-- Команды из мод-консоли можно также вводить через обычную игровую консоль через команду CONSOLE_COMMAND_NAME
+-- Однако команда выполнится только если игра не на паузе\в меню, а если в меню, то только если мод-консоль открыта
+
+LOG_FILE_NAME = "gamedata\\"..user_name().."_console.log_dump" --> Файл, куда сохраняется весь текст из консоли
+VAL_FILE_NAME = "gamedata\\"..user_name().."_console.values" --> Файл, куда сохраняются значения консольных переменных
+MENU_KEY = DIK_keys.DIK_U --> Клавиша для открытия консоли из меню
+GAME_KEY = "kU" --> Клавиша для открытия консоли из игры
+
+local CONSOLE_COMMAND_NAME = "mm_net_srv_name" --> Название консольной команды для ввода команд из ориг. консоли
+local FUNC_SCRIPT = "_console_func" --> Скрипт, где хранятся все функции
+local SAVE_TO_FILE = true --> Нужно ли сохранять текст
+local LOAD_FROM_FILE = true --> Нужно ли загружать текст
+local DIV = string.char(1) --> Символ-разделитель для файла лога, строки с ним не сохраняются в файл
+
+--\\ Возможные типы: "bol", "num", nil (строка)
+VALUES_TBL = { --> Консольные переменные (Получать методами Get\SetValue)
+ ["flush_log"] = {value_and_def = true, types = "bol", descr_1 = "true\\false", descr_2 = "Сохранять лог на диск"},
+-- ["num_test"] = {value_and_def = 1.23, types = "num", descr_1 = "number", descr_2 = "Тест числа"},
+-- ["str_test"] = {value_and_def = "Hello Zep", types = nil, descr_1 = "string", descr_2 = "Тест строки"},
+}
+
+
+local uiConsole = nil
+local registred_commands = {}
+local bBindKey = false
+
+--\\ Показать консоль
+function Show()
+ InitUI()
+
+ if not uiConsole:IsShown() then
+ uiConsole:ShowDialog(false)
+ end
+end
+
+--\\ Скрыть консоль
+function Hide()
+ if uiConsole then
+ if uiConsole:IsShown() then
+ uiConsole:HideDialog()
+ end
+ end
+end
+
+--\\ Получить ссылку на консоль
+function Get()
+ InitUI()
+ return uiConsole
+end
+
+--\\ Выполнить консольную команду
+function Execute(sCommand, bNoLog)
+ Get():OnButtonExecute(sCommand, (bNoLog or true))
+end
+
+local bNeedLoad = true
+
+--\\ Получить консольное значение
+function GetVal(name)
+ if bNeedLoad == true then
+ fill_values_tbl()
+ bNeedLoad = false
+ end
+
+ return VALUES_TBL[name].value_and_def
+end
+
+--\\ Сохранить консольное значение
+function SetVal(name, val)
+ if bNeedLoad == true then
+ fill_values_tbl()
+ bNeedLoad = false
+ end
+
+ local tbl = VALUES_TBL[name]
+
+ if tbl then
+ local set_value = _G[FUNC_SCRIPT].cast(val, tbl.types)
+
+ if set_value == nil then
+ set_value = tbl.value_and_def
+ end
+
+ if tbl.value_and_def ~= set_value then
+ tbl.value_and_def = set_value
+
+ -----------------------
+ local file = io.open( VAL_FILE_NAME, "w" )
+ for cmnd, ctbl in pairs(VALUES_TBL) do
+ if file ~= nil then
+ file:write( cmnd..DIV..tostring(ctbl.value_and_def), "\n" )
+ else
+ Get():AddString("Can't find or create values file: "..VAL_FILE_NAME, "Red")
+ end
+ end
+ file:close()
+ -----------------------
+ end
+ else
+ Get():AddString("Can't finde console value with name ["..name.."]", "Red")
+ end
+end
+
+--\\ Инициализировать консоль
+function InitUI()
+ InitCommands()
+ if (uiConsole==nil) then
+ uiConsole = console_dialog()
+ end
+end
+
+--\\ Инициализировать только команды
+local bNeedInit = true
+function InitCommands()
+ if bNeedInit == true then
+ for idx,cmnd in ipairs(_G[FUNC_SCRIPT].COMMANDS_LIST) do
+ registred_commands[cmnd[1]] = cmnd[2]
+ end
+ get_console():execute(CONSOLE_COMMAND_NAME.." nil")
+ bNeedInit = false
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+--------------------------------------------------------------------------------------------
+
+--\\ Апдейт игрока
+function actor_update()
+ InitCommands()
+ UpdateConsole()
+end
+
+--\\ Апдейт консоли (как от игрока так и от интерфейса)
+function UpdateConsole()
+ if bBindKey == false then
+ get_console():execute("bind_console mm_net_srv_name con.show "..GAME_KEY)
+ bBindKey = true
+ end
+
+ local text = get_console():get_string(CONSOLE_COMMAND_NAME)
+ if text ~= "nil" then
+ Execute(text)
+ get_console():execute(CONSOLE_COMMAND_NAME.." nil")
+ end
+end
+
+--\\ Вызвать консольную функцию из файла FUNC_SCRIPT
+function ExecuteFunc(reg_func, parsed_string)
+ if _G[FUNC_SCRIPT][reg_func] then
+ _G[FUNC_SCRIPT][reg_func](parsed_string)
+ else
+ Get():AddString("Can't find registred function: "..reg_func.." ", "Red")
+ end
+end
+
+--\\ Вызвать консольную функцию из файла FUNC_SCRIPT
+function ExecuteValue(reg_value, value, bMsg)
+ if VALUES_TBL[reg_value] then
+ if value ~= nil then
+ SetVal(reg_value, value)
+
+ if bMsg == true then
+ Get():AddString("Set value for "..reg_value.." ["..tostring(value).."]", "Green")
+ end
+ else
+ if bMsg == true then
+ Get():AddString(reg_value.." = "..tostring(GetVal(reg_value)).." ", "Green")
+ end
+ end
+ end
+end
+
+--\\ Загрузить таблицу консольных переменных из файла
+function fill_values_tbl()
+ local file = io.open( VAL_FILE_NAME, "r" )
+ if file ~= nil then
+ for line in file:lines() do
+ if line then
+ local tbl = _u.string_expl(line, DIV)
+
+ if tbl[1] ~= nil and tbl[1] ~= "" then
+ local tbl_val = VALUES_TBL[tbl[1]]
+ if tbl_val then
+ local last_value = tbl_val.value_and_def
+ tbl_val.value_and_def = _G[FUNC_SCRIPT].cast(tbl[2], tbl_val.types)
+
+ if tbl_val.value_and_def == nil then
+ tbl_val.value_and_def = last_value
+ end
+ else
+ -- Заблокировано из за применения функции GetValue в коде консоли
+ -- т.к там идёт вызов функции GetVal в процессе создания консоли, которая
+ -- вызывает эту функцию fill_values_tbl и если код доходит до этих строчек
+ -- то функция Get() обращается к ещё не созданной до конца консоли и создаёт вторую (3-ю, 4-ю...)
+ -- консоль и так всё циклится пока игра не вылетит.
+ --Get():AddString("Can't finde console value with name ["..tbl[1].."]", "Red")
+ end
+ end
+ end
+ end
+ file:close()
+ else
+ --Get():AddString("Can't find values file: "..VAL_FILE_NAME, "Red")
+ end
+end
+
+---------------------------------------------------------------------------------------------------------------
+
+
+class "console_dialog" (CUIScriptWnd)
+function console_dialog:__init() super()
+
+ local xml = CScriptXmlInit()
+ xml:ParseFile("ui_console.xml")
+
+ self:SetWndRect(Frect():set(0,0,1024,768))
+ self.form = xml:InitStatic("console", self)
+
+
+ self.editbox = xml:InitEditBox("console:edit_box", self.form)
+ self:Register (self.editbox, "command_box")
+
+ self.btn_x = xml:Init3tButton("console:btn_x", self.form)
+ self:Register(self.btn_x, "btn_x")
+
+ self.btn_exec = xml:Init3tButton("console:btn_execute", self.form)
+ self:Register(self.btn_exec, "btn_execute")
+
+ self.btn_r = xml:Init3tButton("console:btn_r", self.form)
+ self:Register(self.btn_r, "btn_r")
+
+ ctrl = CUIWindow()
+ xml:InitWindow ("file_item:main",0,ctrl)
+
+ self.file_item_main_sz = vector2():set(ctrl:GetWidth(),ctrl:GetHeight())
+
+ xml:InitWindow ("file_item:fn",0,ctrl)
+ self.file_item_fn_sz = vector2():set(ctrl:GetWidth(),ctrl:GetHeight())
+
+ self.list_box = xml:InitListBox("console:list",self.form)
+
+ self.list_box:ShowSelectedItem (true)
+ self:Register (self.list_box, "list_window")
+
+ self:Clear()
+
+ if LOAD_FROM_FILE then
+ self:LoadLog()
+ end
+
+ self:ReInit()
+ InitCommands()
+
+ --------------------------------------------------------------------------------
+ self:AddCallback("btn_execute", ui_events.BUTTON_CLICKED, self.OnButtonExecute, self)
+ self:AddCallback("btn_x", ui_events.BUTTON_CLICKED, self.OnButtonX, self)
+ self:AddCallback("btn_r", ui_events.BUTTON_CLICKED, self.OnButtonR, self)
+ self:AddCallback("list_window", ui_events.WINDOW_LBUTTON_DB_CLICK, self.OnListItemDbClicked, self)
+end
+
+function console_dialog:ReInit()
+ self:AddString("")
+ self:AddString("<<>>")
+ self:AddString("_______________________________")
+end
+
+function console_dialog:Clear()
+ self.list_box:Clear()
+end
+
+function console_dialog:Update()
+ CUIScriptWnd.Update(self)
+ UpdateConsole() --> Для обновления из меню
+end
+
+class "console_item" (CUIListBoxItem)
+
+function console_item:__init() super()
+ self:SetTextColor(GetARGB(255, 170, 170, 170))
+
+ self.fn = self:GetTextItem()
+ self.fn:SetFont(GetFontLetterica18Russian())
+ self.fn:SetEllipsis(true)
+end
+
+function console_dialog:AddString(sStr, sColor, bNoFlush)
+ if sStr ~= nil then
+ if string.match(sStr, DIV) then
+ bNoFlush = true
+ end
+
+ local _itm = console_item(self.file_item_main_sz.y)
+
+ if sColor == nil then sColor = "White" end
+ _itm:SetTextColor(GetARGB(_G[FUNC_SCRIPT].ColorTbl[sColor].a, _G[FUNC_SCRIPT].ColorTbl[sColor].r, _G[FUNC_SCRIPT].ColorTbl[sColor].g, _G[FUNC_SCRIPT].ColorTbl[sColor].b))
+
+ _itm:SetWndSize (self.file_item_main_sz)
+
+ _itm.fn:SetWndPos (vector2():set(0,0))
+ _itm.fn:SetWndSize (self.file_item_fn_sz)
+ _itm.fn:SetText (sStr)
+
+ self.list_box:AddExistingItem(_itm)
+
+ if bNoFlush ~= true then
+ if SAVE_TO_FILE and GetVal("flush_log") == true then
+ self:Flush(sStr, sColor)
+ end
+ end
+ end
+end
+
+function console_dialog:Log(text)
+ self:AddString(text, "Log")
+end
+
+function console_dialog:Flush(sStr, sColor)
+ local sStr = tostring(sStr)
+ local file = io.open( LOG_FILE_NAME, "a" )
+ if file ~= nil then
+ file:write( sColor..DIV..sStr, "\n" )
+ file:close()
+ end
+end
+
+function console_dialog:LoadLog(file_name, bAsText)
+ if file_name == nil then
+ file_name = LOG_FILE_NAME
+ end
+
+ local file = io.open( file_name, "r" )
+ if file ~= nil then
+ for line in file:lines() do
+ if line then
+ local tbl = {}
+
+ if bAsText == true then
+ tbl[1] = "Yelow"
+ tbl[2] = line
+ else
+ tbl = _u.string_expl(line, DIV)
+ if tbl[2] == "" or tbl[2] == nil or tbl[2] == "nil" then
+ tbl[2] = " "
+ end
+ end
+
+ if bAsText == true or tbl[1] == nil or _G[FUNC_SCRIPT].ColorTbl[tbl[1]] == nil then
+ tbl[1] = "Yelow"
+ end
+
+
+ self:AddString(tbl[2], tbl[1], true)
+ end
+ end
+ file:close()
+ else
+ self:AddString("Can't find file: "..file_name, "Red")
+ end
+end
+
+-------------------------------------------------------------------------------
+
+function console_dialog:OnListItemDbClicked()
+ if self.list_box:GetSize()==0 then return end
+
+ self:OnButtonX()
+
+ local item = self.list_box:GetSelectedItem()
+
+ if item then
+ local item_text = item.fn:GetText()
+ self.editbox:SetText(item_text)
+ end
+end
+
+function console_dialog:OnButtonX()
+ self.editbox:SetText("")
+end
+
+function console_dialog:OnButtonR()
+ if self.list_box:GetSize()==0 then return end
+
+ local item = self.list_box:GetSelectedItem()
+
+ if item then
+ local index = self.list_box:GetSelectedIndex()
+
+ if index == -1 or index == nil then return end
+
+ item = self.list_box:GetItemByIndex(index)
+ self.list_box:RemoveItem(item)
+ end
+end
+
+
+function console_dialog:OnButtonExecute(manual_text, bSilent)
+ local text = manual_text or self.editbox:GetText()
+
+ if bSilent == nil then bSilent = false end
+
+ if bSilent ~= true then
+ self:AddString(text, "Alpha")
+ end
+
+ if text ~= "" then
+ ------------------------------------
+ local parsed_string = _u.string_expl(text, " ")
+ local command_name = parsed_string[1]
+ local reg_func = registred_commands[command_name]
+ local bIsValue = VALUES_TBL[command_name] ~= nil
+
+ parsed_string[1] = nil
+ if text ~= command_name and text ~= command_name.." " then
+ local params = string.gsub (text, command_name.." ", "")
+ local spaces = string.gsub (params, " ", "")
+
+ if spaces ~= "" then
+ parsed_string[1] = tostring(string.gsub (text, command_name.." ", ""))
+ end
+ end
+
+ --* Это зарегистрированная команда
+ if reg_func ~= nil then
+ if bSilent ~= true then
+ self:AddString("Execute command: "..command_name.." ("..reg_func..")", "Green")
+ end
+
+ ExecuteFunc(reg_func, parsed_string)
+ end
+
+ --* Это консольная переменная
+ if bIsValue then
+ ExecuteValue(command_name, parsed_string[1], not bSilent)
+ end
+ ------------------------------------
+ end
+end
+
+function console_dialog:OnButtonClose()
+ Hide()
+end
+
+function console_dialog:OnKeyboard(dik, keyboard_action)
+ CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
+ local bNeedFocus = true
+
+ if (dik == DIK_keys.DIK_ESCAPE) and keyboard_action == ui_events.WINDOW_KEY_PRESSED then
+ self:OnButtonClose()
+ bNeedFocus = false
+ end
+
+ if dik == DIK_keys.DIK_RETURN and keyboard_action == ui_events.WINDOW_KEY_PRESSED then
+ self:OnButtonExecute()
+ bNeedFocus = false
+ end
+
+ if dik == DIK_keys.DIK_LMENU and keyboard_action == ui_events.WINDOW_KEY_PRESSED then
+ self:OnButtonX()
+ bNeedFocus = false
+ end
+
+ if bNeedFocus then
+ self.editbox:CaptureFocus(true)
+ end
+
+ return true
+end
+
diff --git a/res/gamedata/scripts/_console_func.script b/res/gamedata/scripts/_console_func.script
new file mode 100644
index 00000000000..5c6750d3c6f
--- /dev/null
+++ b/res/gamedata/scripts/_console_func.script
@@ -0,0 +1,480 @@
+--[[ ----------------------------------------------------------------------------------------------
+ Платформы: CoP v1.6.02
+ Описание : Скриптовая консоль (Функции)
+ Поддержка: 2013 © Shoker Mod
+ Версия : 1.0 (12.09.2013)
+ Авторы : Shoker, ...
+--]] ----------------------------------------------------------------------------------------------
+
+local FSys = getFS()
+
+--\\ Получить ссылку на консоль
+function Get()
+ return _console.Get()
+end
+
+--\\ Таблица цветов, поддерживаемых консолью
+ColorTbl = {
+ White = {r = 255, g = 255, b = 255, a = 255},
+ Red = {r = 255, g = 0, b = 0, a = 255},
+ Green = {r = 0, g = 255, b = 0, a = 255},
+ Blue = {r = 0, g = 0, b = 255, a = 255},
+ Yelow = {r = 255, g = 216, b = 0, a = 255},
+ Log = {r = 0, g = 200, b = 255, a = 255},
+ Alpha = {r = 255, g = 255, b = 255, a = 120},
+}
+
+--\\ Все доступные команды
+COMMANDS_LIST = {
+ {"help", "ShowHelp", "", "Все доступные команды"},
+ {"list", "ShowList", "", "Все консольные переменные"},
+ {"cls", "ClearList", "", "Очищает список введённых команд"},
+ ---------------------[CON]---------------------------
+ {"con.show", "Con_Show", "", "Открыть консоль (нужна для открытия консоли из стандартной консоли)"},
+ {"con.colors", "Con_Colors", "", "Показывает все доступные цвета текста в консоли"},
+ {"con.send", "Con_Send", "<текст>, <цвет*>", "Послать в консоль текст заданного цвета"},
+ {"con.clean", "Con_Clean", "string*", "Очистить дамп лога\\указанный файл в папке с игрокй"},
+ {"con.load", "Con_Load", "string", "Загрузить в консоль лог из указанного файла в папке gamedata (поддерживает цветное форматирование строк)"},
+ {"con.load_text", "Con_LoadText", "string", "Загрузить в консоль текст из указанного файла (грузит как есть)"},
+ ---------------------[LUA]---------------------------
+ {"lua.do", "Lua_Execute", "string", "Выполняет lua-код, переданный в виде строки и выводит результат, если он есть."},
+ {"lua.dor", "Lua_ExecuteR", "string", "Выполняет lua-код, переданный в виде строки и всегда выводит результат (добавляет return в начало кода)"},
+ {"lua.dof", "Lua_ExecuteF", "string", "Загружает скриптовый файл из папки scripts и выполняет код из него"},
+ {"lua.crash", "Lua_Crash", "string*", "Заставить игру вылететь с указанным текстом как причиной"},
+ {"lua.exit", "Lua_Exit", "", "Закрыть игру"},
+ ---------------------[FS]----------------------------
+ {"fs.list", "FS_List", "string*", "Вывести список файлов по указанной маске относительно папки gamedata"},
+ ---------------------[C]-----------------------------
+ {"c.tlp", "C_Tlp", "", "Телепортировать игрока к камере"},
+ {"c.ui", "C_UI", "", "Скрыть\\Показать интерфейс и сделать игрока бессмертным (при скрытом)"},
+ ---------------------[CAM]---------------------------
+ {"cam.eff", "Cam_Eff", "string", "Проиграть эффект камеры (путь от папки anims)"},
+ {"cam.anm", "Cam_Anm", "string", "Проиграть анимацию камеры (путь от папки anims)"},
+ {"cam.anm_fix", "Cam_Anm_Fix", "string", "Проиграть анимацию камеры от некой начальной точки, зашитой в anm-файле (путь от папки anims)"},
+ ---------------------[G]-----------------------------
+ {"g.info", "G_Info", "radius* = float", "Выводит информацию о ближайших объектах вокруг камеры в заданном радиусе (5 по умолчанию)"},
+ {"g.spawn", "G_Spawn", "sec = string, x* = float, y* = float, z* = float", "Заспавнить объект на локацию с игроком в указанные координаты или перед камерой"},
+ {"g.spawn_inv", "G_Spawn_Inv", "sec = string, id* = int", "Заспавнить предмет в инвентарь объекта с указанным id (если не указать id - спавн к игроку)"},
+}
+
+---------------------------------------------------------------------------------------------------------------
+
+--[[
+ * Функция cast служит для преобразования строкового значения в заданный тип, по умолчанию типов всего два - num число и bol логическое
+ * Каждой функции здесь передаётся параметр tbl, таблица введённых параметров, в tbl[1] хранится ВСЯ строка без учёта команды, а
+ в остальных каждый параметр по отдельности в порядке их ввода в консоле
+--]]
+
+function cast(value, to_type)
+ if value == nil or value == "nil" then
+ return nil
+ end
+
+ if to_type == nil then return tostring(value) end
+
+ if to_type == "num" then
+ return tonumber(value)
+ end
+
+ if to_type == "bol" then
+ if value == "1" then
+ return true
+ end
+
+ if value == "0" then
+ return false
+ end
+
+ return not (string.match(value, "false") ~= nil)
+ end
+end
+
+
+--\\ Проверка что такая секция существует
+function sec_exist(sec)
+ local ini = system_ini()
+ if sec == nil then return false end
+ if not ini:section_exist(sec) then return false end
+ return true
+end
+
+--\\ Проверка что такой файл существует
+function exist(path)
+ if path ~= nil then
+ return (FSys:exist("$game_data$", path) ~= nil)
+ else
+ Get():AddString(" File name is empty", "Red")
+ return false
+ end
+end
+
+--**************************************************************--
+
+function ShowHelp()
+ Get():AddString("Кнопка Esc - закрыть консоль", "White")
+ Get():AddString("Кнопка Enter - ввести команду", "White")
+ Get():AddString("Кнопка Left Alt - очистить текстовое поле", "White")
+
+ Get():AddString("", "White")
+
+ Get():AddString("Вызов команды из стандартной консоли: mm_net_srv_name <команда> <параметры...>", "White")
+ Get():AddString("Параметры команд указаны в скобках, если параметр имеет знак *, значит его можно не писать\\заменить на nil", "White")
+
+ Get():AddString("", "White")
+
+ for idx,cmnd in ipairs(COMMANDS_LIST) do
+ local type_info = ""
+
+ if cmnd[3] ~= "" then
+ type_info = " ("..cmnd[3]..")"
+ end
+
+ Get():AddString(idx..") "..cmnd[1]..type_info, "Log")
+ Get():AddString(cmnd[4], "White")
+ end
+end
+
+function ShowList()
+ for name, tbl in pairs(_console.VALUES_TBL) do
+ Get():AddString(name.." ("..tbl.descr_1..") = "..tostring(tbl.value_and_def), "Log")
+ Get():AddString(tbl.descr_2, "White")
+ end
+end
+
+function ClearList()
+ Get():Clear()
+end
+
+
+function Con_Show()
+ _console.Show()
+end
+
+function Con_Colors()
+ Get():AddString("-------------------------", "Log")
+ Get():AddString("Print colors:", "Log")
+
+ for color, rgba in pairs(ColorTbl) do
+ Get():AddString(">>> "..color.." = ["..rgba.r..","..rgba.g..","..rgba.b..","..rgba.a.."]", color)
+ end
+
+ Get():AddString("-------------------------", "Log")
+end
+
+function Con_Send(tbl)
+ local size = #tbl
+ local color = "White"
+ local bHaveColor = false
+
+ if tbl[size] and ColorTbl[tbl[size]] then
+ color = tbl[size]
+ bHaveColor = true
+ end
+
+ if bHaveColor then
+ size = size - 1
+ end
+
+ if size >= 2 then
+ for i=2, size do
+ Get():AddString(tbl[i], color)
+ end
+ end
+end
+
+function Con_Clean(tbl)
+ local file_name = tbl[1] or _console.LOG_FILE_NAME
+ local file = io.open( file_name, "w" )
+ file:close()
+end
+
+function Con_Load(tbl)
+ if tbl[1] == nil or tbl[1] == "" then
+ Get():AddString(" File name is empty", "Red")
+ else
+ local con = Get()
+ con:Clear()
+ con:LoadLog("gamedata\\"..tbl[1])
+ end
+end
+
+function Con_LoadText(tbl)
+ if tbl[1] == nil or tbl[1] == "" then
+ Get():AddString(" File name is empty", "Red")
+ else
+ local con = Get()
+ con:Clear()
+ con:LoadLog("gamedata\\"..tbl[1], true)
+ end
+end
+
+function Lua_Crash(tbl)
+ if tbl[1] == "" or tbl[1] == nil then
+ tbl[1] = "nil"
+ end
+
+ get_console():execute(tbl[1])
+ a = nil + nil
+end
+
+function Lua_Exit()
+ get_console():execute("quit")
+end
+
+function Lua_Execute(tbl)
+ if tbl[1] ~= nil then
+ local func, msg = loadstring(tbl[1])
+ if func ~= nil then
+ local bWork, result = pcall(func)
+ if bWork then
+ if result ~= nil then
+ if type(result) ~= "userdata" then
+ Get():AddString("Result: "..tostring(result), "Log")
+ else
+ Get():AddString("Result: UserData", "Log")
+ end
+ end
+ else
+ Get():AddString(" Bad code: "..result, "Red")
+ end
+ else
+ Get():AddString(" Can't compile code = "..tostring(msg), "Red")
+ end
+ else
+ Get():AddString(" There is no code to compile", "Red")
+ end
+end
+
+function Lua_ExecuteR(tbl)
+ if tbl[1] ~= nil then
+ local func, msg = loadstring("return "..tbl[1])
+
+ if func ~= nil then
+ local bWork, result = pcall(func)
+ if bWork then
+ if result ~= nil then
+ if type(result) ~= "userdata" then
+ Get():AddString("Result: "..tostring(result), "Log")
+ else
+ Get():AddString("Result: UserData", "Log")
+ end
+ end
+ else
+ Get():AddString(" Bad code: "..result, "Red")
+ end
+ else
+ Get():AddString(" Can't compile code = "..tostring(msg), "Red")
+ end
+ else
+ Get():AddString(" There is no code to compile", "Red")
+ end
+end
+
+function Lua_ExecuteF(tbl)
+ if tbl[1] ~= nil then
+ local bWork, result = pcall(dofile, "gamedata\\scripts\\"..tbl[1]..".script")
+
+ if bWork then
+ if result ~= nil then
+ if type(result) ~= "userdata" then
+ Get():AddString("Result: "..tostring(result), "Log")
+ else
+ Get():AddString("Result: UserData", "Log")
+ end
+ end
+ else
+ Get():AddString(" Bad file: "..result, "Red")
+ end
+ else
+ Get():AddString(" There is no file to open", "Red")
+ end
+end
+
+function FS_List(tbl)
+ local mask = tbl[1] or "*"
+ local flist = FSys:file_list_open_ex("$game_data$", FS.FS_ListFiles, mask)
+ local f_cnt = flist:Size()
+
+ Get():AddString("-------------------------", "Log")
+ Get():AddString("List of files:", "Log")
+
+ for it=0, f_cnt-1 do
+ local file = flist:GetAt(it)
+ local file_name = file:NameFull()
+
+ Get():AddString(file_name, "Log")
+ end
+
+
+ Get():AddString("Total: "..tostring(f_cnt), "Log")
+ Get():AddString("-------------------------", "Log")
+end
+
+function C_Tlp()
+ if db.actor then
+ db.actor:set_actor_position(device().cam_pos)
+ else
+ Get():AddString(" Game not started yet", "Red")
+ end
+end
+
+local bHideUi = false
+function C_UI(tbl)
+ if db.actor then
+ local bHide = not bHideUi
+
+ if bHide then
+ level.hide_indicators_safe()
+ else
+ level.show_indicators()
+ end
+
+ bHideUi = bHide
+ else
+ Get():AddString(" Game not started yet", "Red")
+ end
+end
+
+function Cam_Eff(tbl)
+ if db.actor then
+ if tbl[1] == nil or tbl[1] == "" then
+ Get():AddString(" File path is empty", "Red")
+ else
+ if exist("anims\\"..tbl[1]) then
+ level.add_pp_effector(tbl[1], 123321, false)
+ else
+ Get():AddString(" Can't find file anims\\"..tbl[1], "Red")
+ end
+ end
+ else
+ Get():AddString(" Game not started yet", "Red")
+ end
+end
+
+function Cam_Anm(tbl)
+ if db.actor then
+ if tbl[1] == nil or tbl[1] == "" then
+ Get():AddString(" File path is empty", "Red")
+ else
+ if exist("anims\\"..tbl[1]) then
+ level.add_cam_effector(tbl[1], 123321, false, "")
+ else
+ Get():AddString(" Can't find file anims\\"..tbl[1], "Red")
+ end
+ end
+ else
+ Get():AddString(" Game not started yet", "Red")
+ end
+end
+
+function Cam_Anm_Fix(tbl)
+ if db.actor then
+ if tbl[1] == nil or tbl[1] == "" then
+ Get():AddString(" File path is empty", "Red")
+ else
+ if exist("anims\\"..tbl[1]) then
+ level.add_cam_effector2(tbl[1], 123321, false, "")
+ else
+ Get():AddString(" Can't find file anims\\"..tbl[1], "Red")
+ end
+ end
+ else
+ Get():AddString(" Game not started yet", "Red")
+ end
+end
+
+function G_Info(tbl)
+ local distance = cast(tbl[2], "num") or 5
+
+ if db.actor then
+ Get():AddString("-------------------------", "Log")
+ Get():AddString("Search objects in radius "..tostring(distance).." ...", "Log")
+ local cnt = 0
+ for id = 1, 65534 do
+ local sobj = alife():object(id)
+ if sobj ~= nil and sobj.parent_id == 65535 then
+ -----------------------------
+ local lvert = game_graph():vertex(sobj.m_game_vertex_id)
+ local lid = lvert:level_id()
+ local lvl = alife():level_name(lid)
+
+ if lvl == level.name() then
+ local dis = device().cam_pos:distance_to(sobj.position)
+ if dis <= distance then
+ Get():AddString(id.." = "..sobj:name().." ("..sobj:section_name()..") Distance = "..tostring(dis), "Log")
+ cnt = cnt + 1
+ end
+ end
+ -----------------------------
+ end
+ end
+ Get():AddString("Total: "..tostring(cnt), "Log")
+ Get():AddString("-------------------------", "Log")
+ else
+ Get():AddString(" Game not started yet", "Red")
+ end
+end
+
+function G_Spawn(tbl, id)
+ if db.actor ~= nil then
+ local sec = tbl[2]
+
+ if sec ~= nil then
+ if sec_exist(sec) then
+ local x = cast(tbl[3], "num")
+ local y = cast(tbl[4], "num")
+ local z = cast(tbl[5], "num")
+
+
+ local bToActorPos = false
+
+ if x == nil and y == nil and z == nil then
+ bToActorPos = true
+ end
+
+ if x == nil then x = device().cam_pos.x end
+ if y == nil then y = device().cam_pos.y end
+ if z == nil then z = device().cam_pos.z end
+
+ local vec = vector():set(x,y,z)
+
+ if bToActorPos then
+ vec = vec:add(device().cam_dir:mul(3))
+ end
+
+ if id ~= nil then
+ local sobj = alife():object(id)
+
+ if sobj then
+ alife():create(sec, sobj.position, sobj.m_level_vertex_id, sobj.m_game_vertex_id, id)
+ else
+ Get():AddString(" There is now object with id "..tostring(id), "Red")
+ end
+ else
+ alife():create(sec, vec, db.actor:level_vertex_id(), db.actor:game_vertex_id())
+ end
+ else
+ Get():AddString(" There is now section ["..tostring(sec).."] in system.ltx", "Red")
+ end
+ else
+ Get():AddString(" Section is nil", "Red")
+ end
+ else
+ Get():AddString(" Game not started yet", "Red")
+ end
+end
+
+function G_Spawn_Inv(tbl)
+ local id = cast(tbl[3], "num")
+
+ if id == nil then
+ if db.actor then
+ id = db.actor:id()
+ end
+ end
+
+ tbl[3] = 0
+ tbl[4] = 0
+ tbl[5] = 0
+ G_Spawn(tbl, id)
+end
diff --git a/res/gamedata/scripts/_u.script b/res/gamedata/scripts/_u.script
new file mode 100644
index 00000000000..26a2b7c3e09
--- /dev/null
+++ b/res/gamedata/scripts/_u.script
@@ -0,0 +1,288 @@
+--[[ ----------------------------------------------------------------------------------------------
+ Платформы: CS 1.5.10, CoP 1.6.02
+ Описание : Различные утилиты для работы с данными
+ Поддержка: 2013 © Shoker Weapon Mod
+ Авторы : Shoker, <...>
+--]] ----------------------------------------------------------------------------------------------
+
+--[[
+ TODO:
+ * При чтении через ltx() из ini-файла может совпасть имя секции и строка для чтения с похожей
+ секцией из system_ini() или любого другого ini, из за чего она буферизируется и перебьёт значения из них
+--]]
+
+--************************************************************--
+--***********************[Ядро скрипта]***********************--
+--************************************************************--
+local _SN = script_name()
+
+--**************************************************************--
+--********************[Функциональная часть]********************--
+--**************************************************************--
+
+--********************** Операции с векторами - Начало **********************--
+--\\ Из вектора "вперёд" возвращает вектор "вправо" и вектор "вверх" (Roll не учитывается)
+--\\ Спасибо malandrinus за формулы
+function get_all_direction(dir)
+ --* "Вправо"
+ local dir_right = vector()
+ dir_right:crossproduct(dir, vector():set(0,1,0))
+ dir_right = dir_right:normalize()
+
+ --* "Вверх"
+ local dir_up = vector()
+ dir_up:crossproduct(dir_right, dir)
+ dir_up = dir_up:normalize()
+
+ return dir_right:invert(), dir_up
+end
+
+--\\ Принимает координаты на земле и превращает их в координаты для экрана
+--\\ Можно использовать в целеуказателях (malandrinus)
+function point_to_hud(point)
+ local dev = device()
+ local scr_w = dev.width
+ local scr_h = dev.height
+
+ local fov2 = (dev.fov/2) * (math.pi/180)
+ local scr_dist = 0.5 * scr_h / math.tan(fov2)
+
+ local ppp = vector():sub(point, dev.cam_pos)
+ local dp = dev.cam_dir:dotproduct(ppp)
+
+ local x = 512 + dev.cam_right:dotproduct(ppp) * scr_dist / dp * (1024/scr_w)
+ local y = 384 - dev.cam_top:dotproduct(ppp) * scr_dist / dp * (768/scr_h)
+ return x, y
+end
+
+--\\ Вектор X,Y в углах переводит в дирекцию
+function angle_to_direction(oangle)
+ local yaw = oangle.y
+ local pitch = oangle.x
+ return vector():setHP(yaw,pitch):normalize()
+end
+--********************** Операции с векторами - Конец **********************--
+
+
+--********************** Работа с конфигами - Начало **********************--
+local ltxBuffer = {} --> Хранит уже загруженные данные из конфигов
+
+--\\ Возвращает значение из секции в конфигах
+-- sec - секция
+-- line - строка
+-- *mode - режим чтения, по умолчанию читает число с точкой ("str", "tbl1", "bol", "num", "numf")
+-- *ini_file - ini-конфиг откуда надо читать, по умолчанию читает из system.ltx и подкл. к нему файлах
+-- Внимание: в случае отсутствия секции\строки в конфиге - вылета не будет, так что все такие места
+-- проверять соотв. функциями самим. Сделано для упрощения кода.
+function ltx(sec, line, mode, ini_file)
+ if sec == nil then
+ _abort(_SN, "ltx", "sec (%s)(%s)", tostring(line), tostring(mode))
+ end
+
+ if not ltxBuffer[sec] then
+ ltxBuffer[sec] = {}
+ end
+
+ local result = ltxBuffer[sec][line]
+ if result then return result end --> Нет смысла каждый раз читать из конфигов, когда достаточно 1 раз записать в таблицу
+
+ local ini = ini_file or system_ini()
+
+ if ltxExist(sec, line, ini) then
+ if mode==nil or mode=="numf" then --> число с запятой
+ ltxBuffer[sec][line] = ini:r_float(sec, line)
+ return ltxBuffer[sec][line]
+ end
+
+ if mode=="bol" then --> true\false
+ ltxBuffer[sec][line] = ini:r_bool(sec, line)
+ return ltxBuffer[sec][line]
+ end
+
+ if mode=="num" then --> целое число
+ ltxBuffer[sec][line] = ini:r_u32(sec, line)
+ return ltxBuffer[sec][line]
+ end
+
+ if mode=="str" then --> строка
+ ltxBuffer[sec][line] = ini:r_string(sec, line)
+ return ltxBuffer[sec][line]
+ end
+
+ if mode=="vec" then --> вектор
+ local vec = ini:r_vector(sec, line)
+ ltxBuffer[sec][line] = vec
+ return ltxBuffer[sec][line]
+ end
+
+ if mode=="tbl1" then --> таблица из строки с запятыми (1 = ..., 2 = ....)
+ local temp = ini:r_string(sec, line)
+ ltxBuffer[sec][line] = string_expl(temp, ",")
+ return ltxBuffer[sec][line]
+ end
+ end
+
+ -- mDbg(_SN, "ltx - no section: "..sec.." || "..line)
+ return nil
+end
+function test1()
+ return "yes Yes!"
+end
+
+
+--\\ Позволяет выставить значение какого либо из загруженных параметров конфига
+function ltxBufferW(sec, line, value)
+ if not ltxBuffer[sec] then
+ ltxBuffer[sec] = {}
+ end
+
+ ltxBuffer[sec][line] = value
+end
+
+--\\ Возвращает имя и описание предмета
+-- sec - секция предмета в конфигах
+function ltxItem(sec)
+ local name = ltx(sec, "inv_name", "str") or ""
+ local descr = ltx(sec, "description", "str") or ""
+
+ return xml(name), xml(descr)
+end
+
+--\\ Проверяет, что такая комбинация секции-*строки существует в конфиге
+-- sec - секция
+-- *line - строка
+-- *ini_file - ini-конфиг откуда надо читать, по умолчанию читает из system.ltx и подкл. к нему файлах
+function ltxExist(sec, line, ini_file)
+ local ini = ini_file or system_ini()
+ if sec == nil then _abort(_SN, "ltxExist", "sec") end
+ if not ini:section_exist(sec) then return false end
+ if line and not ini:line_exist(sec, line) then return false end
+ return true
+end
+
+--\\ Возвращает из текстового xml-файла
+-- xml_id - идентификатор текста
+function xml(xml_id)
+ return game.translate_string(xml_id)
+end
+
+--\\ Преобразует таблицу в отформатированную строку для записи в custom data
+--[[
+ local value = 123
+ local cd = {}
+ cd["test"] = {}
+ cd["test"]["line"] = value
+ cd["test"]["simple_table"] = {2,4,6,8}
+ cd["test"]["extended_table"] = {val1 = 1, val2 = 2, val3 = 3}
+
+ [test]
+ line = 123
+ simple_table = 2468
+ extended_table = val1, 1, val2, 2, val3, 3
+]]
+function tocdata(tTbl)
+ local result = ""
+ for sec, tData in pairs(tTbl) do
+ result = result.."\n["..sec.."]\n"
+ if type(tData) ~= "table" then
+ _abort(_SN, "tocdata", "tData is not table! result = %s, tData = %s", result, tostring(tData))
+ else
+ for line, t_Param in pairs(tData) do
+ result = result..tostring(line).." = "
+ if type(t_Param) == "table" then
+ if table_size(t_Param) > 0 and #t_Param > 0 then
+ --* Скорее всего это нумерованная таблица, пакуем её без ключа
+ for _,p1 in pairs(t_Param) do
+ local first = true
+ if first then
+ result = result..tostring(p1)
+ first = false
+ else
+ result = result..", "..tostring(p1)
+ end
+ end
+ else
+ --* Хэш-таблица, её пишем вместе с ключами
+ local first = true
+ for p1,p2 in pairs(t_Param) do
+ if first then
+ result = result..tostring(p1)..", "..tostring(p2)
+ first = false
+ else
+ result = result..", "..tostring(p1)..", "..tostring(p2)
+ end
+ end
+ end
+ result = result.."\n"
+ else
+ result = result..tostring(t_Param).."\n"
+ end
+ end
+ end
+ end
+
+ return result
+end
+--********************** Работа с конфигами - Конец **********************--
+
+--\\ Крэшнуть игру с выводом в лог
+function _abort(script_name, function_name, error_string, ...)
+ if script_name == nil then
+ script_name = ""
+ end
+
+ if function_name == nil then
+ function_name = ""
+ end
+
+ abort("%s.%s - "..error_string, script_name, function_name, ...)
+end
+
+--\\ Вывод в лог
+function log(text)
+ get_console():execute("load ~~ " .. tostring(text))
+end
+
+--\\ Подсчёт кол-ва элементов в таблице (под-таблицы считает за 1 элемент)
+function table_size(tTbl)
+ local count = 0
+ for _,_ in pairs(tTbl) do
+ count = count + 1
+ end
+
+ return count
+end
+
+--! Внимание: стандартный шаблон плохо работает с "особыми" символами (например #) и разбивает строку криво
+function string_expl(sStr, sDiv, Mode, bNoClear)
+ sStr = tostring(sStr)
+ if not (sStr ~= "nil" and sStr ~= '') then return {} end --> нечего разделять
+ local tRet = {}
+ local sPattern = '[%w%_]+' --> дефолтный патерн (разделение по 'словам')
+ if type(sDiv) == "string" then --> если задан сепаратор: разделяем по нему
+ if bNoClear then --> если НЕ указано 'чистить пробелы'
+ sPattern = '([^'..sDiv..']+)'
+ else --> иначе с чисткой пробелов
+ sPattern = '%s*([^'..sDiv..']+)%s*'
+ end
+ end
+ --* разделяем строку по патерну
+ if Mode == nil then --> обычный массив
+ for sValue in sStr:gmatch(sPattern) do
+ table.insert(tRet, sValue)
+ end
+ else
+ local sTypeMode = type(Mode)
+ if sTypeMode == "boolean" then --> таблица '[значение] = true или false'
+ for sValue in sStr:gmatch(sPattern) do
+ tRet[sValue] = Mode
+ end
+ elseif sTypeMode == "number" then --> таблица '[idx] = число или стринг'
+ for sValue in sStr:gmatch(sPattern) do
+ tRet[#tRet+1] = tonumber(sValue) or sValue
+ end
+ end
+ end
+ return tRet --> возвращаем таблицу
+end
+
diff --git a/res/gamedata/scripts/ui_main_menu.script b/res/gamedata/scripts/ui_main_menu.script
index db6b0443923..dd17a226751 100644
--- a/res/gamedata/scripts/ui_main_menu.script
+++ b/res/gamedata/scripts/ui_main_menu.script
@@ -344,6 +344,10 @@ function main_menu:OnKeyboard(dik, keyboard_action) --virtual function
end
end
+ if dik == _console.MENU_KEY then --#SM+#--
+ _console.Show()
+ end
+
-- if dik == DIK_keys.DIK_S then
-- self:OnButton_load_spawn()
-- return true
diff --git a/src/xrCore/NET_utils.cpp b/src/xrCore/NET_utils.cpp
index 8d63bb23ed5..d3fb9b3dd74 100644
--- a/src/xrCore/NET_utils.cpp
+++ b/src/xrCore/NET_utils.cpp
@@ -137,7 +137,9 @@ void NET_Packet::w_seek(u32 pos, const void* p, u32 count)
void NET_Packet::r_seek(u32 pos)
{
INI_ASSERT(r_seek)
- VERIFY(pos < B.count);
+ //AVO: changed changed condition to <= as all net packet script utils are using r_seek(0) to read the entire packet.
+ VERIFY(pos <= B.count);
+ //VERIFY(pos < B.count);
r_pos = pos;
}
diff --git a/src/xrEngine/xrTheora_Stream.cpp b/src/xrEngine/xrTheora_Stream.cpp
index fdb8c898d4e..acadabc7781 100644
--- a/src/xrEngine/xrTheora_Stream.cpp
+++ b/src/xrEngine/xrTheora_Stream.cpp
@@ -201,12 +201,14 @@ bool CTheoraStream::Decode(u32 in_tm_play)
if (d_frame < k_frame)
{
//. dbg_log ((stderr,"%04d: preroll\n",d_frame));
- VERIFY((0 != d_frame % key_rate) ||
- (0 == d_frame % key_rate) && theora_packet_iskeyframe(&o_packet));
+ //AVO: commented out VERIFY to get COC start in Debug - something is wrong with video stream
+ //VERIFY((0 != d_frame % key_rate) ||
+ // (0 == d_frame % key_rate) && theora_packet_iskeyframe(&o_packet));
continue;
}
- [[maybe_unused]] bool is_key = theora_packet_iskeyframe(&o_packet);
- VERIFY((d_frame != k_frame) || ((d_frame == k_frame) && is_key));
+ //AVO: commented out VERIFY to get COC start in Debug - something is wrong with video stream
+ //[[maybe_unused]] bool is_key = theora_packet_iskeyframe(&o_packet);
+ //VERIFY((d_frame != k_frame) || ((d_frame == k_frame) && is_key));
// real decode
//. dbg_log ((stderr,"%04d: decode\n",d_frame));
[[maybe_unused]] int res = theora_decode_packetin(&t_state, &o_packet);
diff --git a/src/xrGame/Actor.cpp b/src/xrGame/Actor.cpp
index 1573ff6df54..e959b910a2e 100644
--- a/src/xrGame/Actor.cpp
+++ b/src/xrGame/Actor.cpp
@@ -77,6 +77,10 @@
#include "xrEngine/Rain.h"
+//Alundaio
+#include "script_hit.h"
+//-Alundaio
+
//const u32 patch_frames = 50;
//const float respawn_delay = 1.f;
//const float respawn_auto = 7.f;
@@ -100,7 +104,8 @@ Flags32 psActorFlags =
AF_AUTOPICKUP |
AF_RUN_BACKWARD |
AF_IMPORTANT_SAVE |
- AF_MULTI_ITEM_PICKUP
+ AF_MULTI_ITEM_PICKUP |
+ AF_USE_TRACERS
};
int psActorSleepTime = 1;
@@ -653,13 +658,35 @@ void CActor::Hit(SHit* pHDS)
{
HDS.power = 0.0f;
inherited::Hit(&HDS);
+ return;
}
- float hit_power = HitArtefactsOnBelt(HDS.damage(), HDS.hit_type);
- HDS.power = hit_power;
+ HDS.power = HitArtefactsOnBelt(HDS.damage(), HDS.hit_type);
HDS.add_wound = true;
if (g_Alive())
{
+ CScriptHit tLuaHit;
+
+ tLuaHit.m_fPower = HDS.power;
+ tLuaHit.m_fImpulse = HDS.impulse;
+ tLuaHit.m_tDirection = HDS.direction();
+ tLuaHit.m_tHitType = HDS.hit_type;
+ tLuaHit.m_tpDraftsman = smart_cast(HDS.who)->lua_game_object();
+
+ luabind::functor funct;
+ if (GEnv.ScriptEngine->functor("_G.CActor__BeforeHitCallback", funct))
+ {
+ if (!funct(smart_cast(this->lua_game_object()), &tLuaHit, HDS.boneID))
+ return;
+ }
+
+ HDS.power = tLuaHit.m_fPower;
+ HDS.impulse = tLuaHit.m_fImpulse;
+ HDS.dir = tLuaHit.m_tDirection;
+ HDS.hit_type = (ALife::EHitType)(tLuaHit.m_tHitType);
+ //HDS.who = smart_cast(tLuaHit.m_tpDraftsman->object());
+ //HDS.whoID = tLuaHit.m_tpDraftsman->ID();
+
/* AVO: send script callback*/
callback(GameObject::eHit)(
this->lua_game_object(),
@@ -780,13 +807,13 @@ void CActor::HitMark(float P, Fvector dir, IGameObject* who_object, s16 element,
void CActor::HitSignal(float perc, Fvector& vLocalDir, IGameObject* who, s16 element)
{
+ //AVO: get bone names from IDs
+ //cpcstr bone_name = smart_cast(this->Visual())->LL_BoneName_dbg(element);
+ //Msg("Bone [%d]->[%s]", element, bone_name);
+ //-AVO
+
if (g_Alive())
{
- /* AVO: to get bone names from IDs*/
- /*Log("hit info");
- Log("bone ID = %s", element);
- Log("bone Name = %s", smart_cast(this->Visual())->LL_BoneName_dbg(element));
- Log("hit info END");*/
// check damage bone
Fvector D;
XFORM().transform_dir(D, vLocalDir);
@@ -1541,7 +1568,7 @@ void CActor::shedule_Update(u32 DT)
}
else if (m_pVehicleWeLookingAt)
{
- m_sDefaultObjAction = m_sCarCharacterUseAction;
+ m_sDefaultObjAction = m_pVehicleWeLookingAt->m_sUseAction != nullptr ? m_pVehicleWeLookingAt->m_sUseAction : m_sCarCharacterUseAction;
}
else if (m_pObjectWeLookingAt && m_pObjectWeLookingAt->cast_inventory_item() &&
m_pObjectWeLookingAt->cast_inventory_item()->CanTake())
@@ -1928,18 +1955,19 @@ void CActor::UpdateArtefactsOnBeltAndOutfit()
const auto artefact = smart_cast(it);
if (artefact)
{
- conditions().ChangeBleeding(artefact->m_fBleedingRestoreSpeed * f_update_time);
- conditions().ChangeHealth(artefact->m_fHealthRestoreSpeed * f_update_time);
- conditions().ChangePower(artefact->m_fPowerRestoreSpeed * f_update_time);
- conditions().ChangeSatiety(artefact->m_fSatietyRestoreSpeed * f_update_time);
- if (artefact->m_fRadiationRestoreSpeed > 0.0f)
+ const float art_cond = artefact->GetCondition();
+ conditions().ChangeBleeding((artefact->m_fBleedingRestoreSpeed * art_cond) * f_update_time);
+ conditions().ChangeHealth((artefact->m_fHealthRestoreSpeed * art_cond) * f_update_time);
+ conditions().ChangePower((artefact->m_fPowerRestoreSpeed * art_cond) * f_update_time);
+ conditions().ChangeSatiety((artefact->m_fSatietyRestoreSpeed * art_cond) * f_update_time);
+ if (artefact->m_fRadiationRestoreSpeed * art_cond > 0.0f)
{
- float val = artefact->m_fRadiationRestoreSpeed - conditions().GetBoostRadiationImmunity();
+ float val = (artefact->m_fRadiationRestoreSpeed * art_cond) - conditions().GetBoostRadiationImmunity();
clamp(val, 0.0f, val);
conditions().ChangeRadiation(val * f_update_time);
}
else
- conditions().ChangeRadiation(artefact->m_fRadiationRestoreSpeed * f_update_time);
+ conditions().ChangeRadiation((artefact->m_fRadiationRestoreSpeed * art_cond) * f_update_time);
}
}
@@ -1986,7 +2014,7 @@ float CActor::GetProtection_ArtefactsOnBelt(ALife::EHitType hit_type)
{
const auto artefact = smart_cast(it);
if (artefact)
- sum += artefact->m_ArtefactHitImmunities.AffectHit(1.0f, hit_type);
+ sum += artefact->m_ArtefactHitImmunities.AffectHit(1.0f, hit_type) * artefact->GetCondition();
}
return sum;
}
@@ -2141,7 +2169,7 @@ float CActor::GetRestoreSpeed(ALife::EConditionRestoreType const& type)
{
const auto artefact = smart_cast(it);
if (artefact)
- res += artefact->m_fHealthRestoreSpeed;
+ res += artefact->m_fHealthRestoreSpeed * artefact->GetCondition();
}
const auto outfit = GetOutfit();
@@ -2156,7 +2184,7 @@ float CActor::GetRestoreSpeed(ALife::EConditionRestoreType const& type)
{
const auto artefact = smart_cast(it);
if (artefact)
- res += artefact->m_fRadiationRestoreSpeed;
+ res += artefact->m_fRadiationRestoreSpeed * artefact->GetCondition();
}
const auto outfit = GetOutfit();
@@ -2173,7 +2201,7 @@ float CActor::GetRestoreSpeed(ALife::EConditionRestoreType const& type)
{
const auto artefact = smart_cast(it);
if (artefact)
- res += artefact->m_fSatietyRestoreSpeed;
+ res += artefact->m_fSatietyRestoreSpeed * artefact->GetCondition();
}
const auto outfit = GetOutfit();
@@ -2190,7 +2218,7 @@ float CActor::GetRestoreSpeed(ALife::EConditionRestoreType const& type)
{
const auto artefact = smart_cast(it);
if (artefact)
- res += artefact->m_fPowerRestoreSpeed;
+ res += artefact->m_fPowerRestoreSpeed * artefact->GetCondition();
}
auto outfit = GetOutfit();
if (outfit)
@@ -2212,7 +2240,7 @@ float CActor::GetRestoreSpeed(ALife::EConditionRestoreType const& type)
{
const auto artefact = smart_cast(it);
if (artefact)
- res += artefact->m_fBleedingRestoreSpeed;
+ res += artefact->m_fBleedingRestoreSpeed * artefact->GetCondition();
}
const auto outfit = GetOutfit();
diff --git a/src/xrGame/Actor.h b/src/xrGame/Actor.h
index 627e7d9f8a5..7b972f46bbe 100644
--- a/src/xrGame/Actor.h
+++ b/src/xrGame/Actor.h
@@ -254,7 +254,7 @@ class CActor : public CEntityAlive,
void detach_Vehicle();
void steer_Vehicle(float angle);
void attach_Vehicle(CHolderCustom* vehicle);
- bool use_MountedWeapon(CHolderCustom* object);
+ bool use_HolderEx(CHolderCustom* object, bool bForce);
virtual bool can_attach(const CInventoryItem* inventory_item) const;
protected:
diff --git a/src/xrGame/ActorInput.cpp b/src/xrGame/ActorInput.cpp
index a303d52ad87..8046c32085d 100644
--- a/src/xrGame/ActorInput.cpp
+++ b/src/xrGame/ActorInput.cpp
@@ -575,8 +575,8 @@ bool CActor::use_Holder(CHolderCustom* holder)
if (smart_cast(holderGO))
b = use_Vehicle(0);
- else if (holderGO->CLS_ID == CLSID_OBJECT_W_STATMGUN)
- b = use_MountedWeapon(0);
+ else if (holderGO->CLS_ID == CLSID_OBJECT_W_STATMGUN || holderGO->CLS_ID==CLSID_OBJECT_HOLDER_ENT)
+ b = use_HolderEx(0, false);
if (inventory().ActiveItem())
{
@@ -594,8 +594,8 @@ bool CActor::use_Holder(CHolderCustom* holder)
if (smart_cast(holder))
b = use_Vehicle(holder);
- if (holderGO->CLS_ID == CLSID_OBJECT_W_STATMGUN)
- b = use_MountedWeapon(holder);
+ if (holderGO->CLS_ID == CLSID_OBJECT_W_STATMGUN || holderGO->CLS_ID==CLSID_OBJECT_HOLDER_ENT)
+ b = use_HolderEx(holder, false);
if (b)
{ // used succesfully
diff --git a/src/xrGame/ActorMountedWeapon.cpp b/src/xrGame/ActorMountedWeapon.cpp
index a5da649ef44..32445018df8 100644
--- a/src/xrGame/ActorMountedWeapon.cpp
+++ b/src/xrGame/ActorMountedWeapon.cpp
@@ -5,36 +5,61 @@
#include "xrEngine/CameraBase.h"
#include "ActorEffector.h"
#include "CharacterPhysicsSupport.h"
+#include "holder_custom.h"
+#include "Car.h"
-bool CActor::use_MountedWeapon(CHolderCustom* object)
+bool CActor::use_HolderEx(CHolderCustom* object, bool bForce)
{
- /*
- CHolderCustom* wpn =object;
- if(m_holder){
- if(!wpn||(m_holder==wpn)){
+ if (m_holder)
+ {
+ if (smart_cast(m_holder))
+ {
+ detach_Vehicle();
+ return true;
+ }
+ if (!m_holder->ExitLocked())
+ {
+ if (!object || (m_holder == object))
+ {
m_holder->detach_Actor();
+
+ if (const CGameObject* go = smart_cast(m_holder))
+ callback(GameObject::eDetachVehicle)(go->lua_game_object());
+
character_physics_support()->movement()->CreateCharacter();
- m_holder=NULL;
+ m_holder = nullptr;
}
- return true;
- }else{
- if(wpn){
- Fvector center; Center(center);
- if(wpn->Use(Device.vCameraPosition, Device.vCameraDirection,center)){
- if(wpn->attach_Actor(this)){
- // destroy actor character
- character_physics_support()->movement()->DestroyCharacter();
- PickupModeOff();
- m_holder=wpn;
- if (pCamBobbing){
- Cameras().RemoveCamEffector(eCEBobbing);
- pCamBobbing = NULL;
- }
- return true;
- }
+ }
+ return true;
+ }
+ if (smart_cast(m_holder))
+ {
+ attach_Vehicle(object);
+ return true;
+ }
+ if (object && !object->EnterLocked())
+ {
+ Fvector center;
+ Center(center);
+ if (object->Use(Device.vCameraPosition, Device.vCameraDirection, center))
+ {
+ if (object->attach_Actor(this))
+ {
+ // destroy actor character
+ character_physics_support()->movement()->DestroyCharacter();
+
+ m_holder = object;
+ if (pCamBobbing)
+ {
+ Cameras().RemoveCamEffector(eCEBobbing);
+ pCamBobbing = nullptr;
}
+
+ if (const CGameObject* go = smart_cast(m_holder))
+ callback(GameObject::eAttachVehicle)(go->lua_game_object());
+ return true;
}
}
- */
+ }
return false;
}
diff --git a/src/xrGame/ActorVehicle.cpp b/src/xrGame/ActorVehicle.cpp
index c01994a313d..ee3074f275f 100644
--- a/src/xrGame/ActorVehicle.cpp
+++ b/src/xrGame/ActorVehicle.cpp
@@ -29,6 +29,10 @@ void CActor::attach_Vehicle(CHolderCustom* vehicle)
if(!vehicle || m_holder)
return;
+ CCar* car = smart_cast(vehicle);
+ if (!car)
+ return;
+
//PickupModeOff();
m_holder=vehicle;
@@ -44,7 +48,6 @@ void CActor::attach_Vehicle(CHolderCustom* vehicle)
}
// temp play animation
- CCar* car = smart_cast(m_holder);
u16 anim_type = car->DriverAnimationType();
SVehicleAnimCollection& anims = m_vehicle_anims->m_vehicles_type_collections[anim_type];
V->PlayCycle(anims.idles[0], false);
diff --git a/src/xrGame/Actor_Flags.h b/src/xrGame/Actor_Flags.h
index 58f44fa36b6..e91f7678587 100644
--- a/src/xrGame/Actor_Flags.h
+++ b/src/xrGame/Actor_Flags.h
@@ -15,6 +15,7 @@ enum
AF_MULTI_ITEM_PICKUP = (1 << 11),
AF_LOADING_STAGES = (1 << 12),
AF_ALWAYS_USE_ATTITUDE_SENSORS = (1 << 13), // or only when zooming if false
+ AF_USE_TRACERS = (1 << 14)
};
extern Flags32 psActorFlags;
diff --git a/src/xrGame/Actor_Movement.cpp b/src/xrGame/Actor_Movement.cpp
index 2beec1b8db5..bce9faeded0 100644
--- a/src/xrGame/Actor_Movement.cpp
+++ b/src/xrGame/Actor_Movement.cpp
@@ -679,7 +679,7 @@ float CActor::get_additional_weight() const
{
CArtefact* artefact = smart_cast(*it);
if (artefact)
- res += artefact->AdditionalInventoryWeight();
+ res += artefact->AdditionalInventoryWeight() * artefact->GetCondition();
}
return res;
diff --git a/src/xrGame/AmebaZone.cpp b/src/xrGame/AmebaZone.cpp
index f7960f2737f..399c587a7f6 100644
--- a/src/xrGame/AmebaZone.cpp
+++ b/src/xrGame/AmebaZone.cpp
@@ -10,7 +10,6 @@
#include "CharacterPhysicsSupport.h"
#include "entity_alive.h"
-
CAmebaZone::CAmebaZone() : m_fVelocityLimit(1.f) {}
CAmebaZone::~CAmebaZone() {}
diff --git a/src/xrGame/Artefact.cpp b/src/xrGame/Artefact.cpp
index 738432662b5..e879c581c29 100644
--- a/src/xrGame/Artefact.cpp
+++ b/src/xrGame/Artefact.cpp
@@ -90,7 +90,7 @@ bool CArtefact::net_Spawn(CSE_Abstract* DC)
StartLights();
m_CarringBoneID = u16(-1);
IKinematicsAnimated* K = smart_cast(Visual());
- if (K)
+ if (K && K->ID_Cycle_Safe("idle"))
K->PlayCycle("idle");
o_fastmode = FALSE; // start initially with fast-mode enabled
diff --git a/src/xrGame/CMakeLists.txt b/src/xrGame/CMakeLists.txt
index 4f7d4dcdee0..611dea1f8d8 100644
--- a/src/xrGame/CMakeLists.txt
+++ b/src/xrGame/CMakeLists.txt
@@ -671,6 +671,8 @@ target_sources(xrGame PRIVATE
hits_store.cpp
hits_store.h
hits_store_inline.h
+ HolderEntityObject.cpp
+ HolderEntityObject.h
holder_custom.cpp
holder_custom.h
holder_custom_script.cpp
@@ -1615,8 +1617,6 @@ target_sources(xrGame PRIVATE
weaponBM16.cpp
weaponBM16.h
Weapon.cpp
- WeaponCustomPistolAuto.cpp
- WeaponCustomPistolAuto.h
WeaponCustomPistol.cpp
WeaponCustomPistol.h
WeaponDispersion.cpp
@@ -2426,6 +2426,8 @@ target_sources(xrGame PRIVATE
ui/UIRankFaction.h
ui/UIRankIndicator.cpp
ui/UIRankIndicator.h
+ ui/UIRankingsCoC.cpp
+ ui/UIRankingsCoC.h
ui/UIRankingWnd.cpp
ui/UIRankingWnd.h
ui/UIScriptWnd.cpp
diff --git a/src/xrGame/Car.cpp b/src/xrGame/Car.cpp
index 23ffb85c1aa..31c02f0773e 100644
--- a/src/xrGame/Car.cpp
+++ b/src/xrGame/Car.cpp
@@ -464,7 +464,7 @@ void CCar::VisualUpdate(float fov)
// OwnerActor()->Cameras().ApplyDevice();
// }
//
- /* if(CurrentGameUI())//
+ /* if(CurrentGameUI())
{
CurrentGameUI()->UIMainIngameWnd->CarPanel().Show(true);
CurrentGameUI()->UIMainIngameWnd->CarPanel().SetCarHealth(GetfHealth());
diff --git a/src/xrGame/Car.h b/src/xrGame/Car.h
index b52a7b00028..b99fadd080f 100644
--- a/src/xrGame/Car.h
+++ b/src/xrGame/Car.h
@@ -534,6 +534,9 @@ class CCar : public CEntity,
}
bool isActiveEngine ();
+
+ float GetRPM() const { return m_current_rpm; }
+ void SetRPM(float val) { m_current_rpm = val; }
/***** added by Ray Twitty (aka Shadows) END *****/
diff --git a/src/xrGame/CarDamageParticles.h b/src/xrGame/CarDamageParticles.h
index 3727dcd159a..47c9f192f31 100644
--- a/src/xrGame/CarDamageParticles.h
+++ b/src/xrGame/CarDamageParticles.h
@@ -19,8 +19,8 @@ struct CCarDamageParticles
void Play2(CCar* car);
/***** added by Ray Twitty (aka Shadows) START *****/
// функции для выключения партиклов дыма
- void Stop1(CCar* car);
- void Stop2(CCar* car);
+ void Stop1(CCar* car);
+ void Stop2(CCar* car);
/***** added by Ray Twitty (aka Shadows) END *****/
void PlayWheel1(CCar* car, u16 bone_id) const;
diff --git a/src/xrGame/CarScript.cpp b/src/xrGame/CarScript.cpp
index b8a6f8ff997..9ee40f84919 100644
--- a/src/xrGame/CarScript.cpp
+++ b/src/xrGame/CarScript.cpp
@@ -35,19 +35,23 @@ SCRIPT_EXPORT(CCar, (CGameObject, CHolderCustom),
.def("ExplodeTime", &CCar::ExplodeTime)
.def("CarExplode", &CCar::CarExplode)
/***** added by Ray Twitty (aka Shadows) START *****/
- .def("GetfFuel", &CCar::GetfFuel)
- .def("SetfFuel", &CCar::SetfFuel)
- .def("GetfFuelTank", &CCar::GetfFuelTank)
- .def("SetfFuelTank", &CCar::SetfFuelTank)
- .def("GetfFuelConsumption", &CCar::GetfFuelConsumption)
- .def("SetfFuelConsumption", &CCar::SetfFuelConsumption)
- .def("ChangefFuel", &CCar::ChangefFuel)
- .def("ChangefHealth", &CCar::ChangefHealth)
- .def("PlayDamageParticles", &CCar::PlayDamageParticles)
- .def("StopDamageParticles", &CCar::StopDamageParticles)
- .def("StartEngine", &CCar::StartEngine)
- .def("StopEngine", &CCar::StopEngine)
- .def("IsActiveEngine", &CCar::isActiveEngine)
+ .def("GetfFuel", &CCar::GetfFuel)
+ .def("SetfFuel", &CCar::SetfFuel)
+ .def("GetfFuelTank", &CCar::GetfFuelTank)
+ .def("SetfFuelTank", &CCar::SetfFuelTank)
+ .def("GetfFuelConsumption", &CCar::GetfFuelConsumption)
+ .def("SetfFuelConsumption", &CCar::SetfFuelConsumption)
+ .def("ChangefFuel", &CCar::ChangefFuel)
+ .def("ChangefHealth", &CCar::ChangefHealth)
+ .def("PlayDamageParticles", &CCar::PlayDamageParticles)
+ .def("StopDamageParticles", &CCar::StopDamageParticles)
+ .def("StartEngine", &CCar::StartEngine)
+ .def("StopEngine", &CCar::StopEngine)
+ .def("IsActiveEngine", &CCar::isActiveEngine)
+ .def("HandBreak", &CCar::HandBreak)
+ .def("ReleaseHandBreak", &CCar::ReleaseHandBreak)
+ .def("GetRPM", &CCar::GetRPM)
+ .def("SetRPM", &CCar::SetRPM)
/***** added by Ray Twitty (aka Shadows) END *****/
.def(constructor<>())
];
diff --git a/src/xrGame/CarWeapon.cpp b/src/xrGame/CarWeapon.cpp
index ee9fc75aed3..b8142373f8b 100644
--- a/src/xrGame/CarWeapon.cpp
+++ b/src/xrGame/CarWeapon.cpp
@@ -212,8 +212,8 @@ void CCarWeapon::FireEnd()
void CCarWeapon::OnShot()
{
- FireBullet(
- m_fire_pos, m_fire_dir, fireDispersionBase, *m_Ammo, m_object->ID(), m_object->ID(), SendHitAllowed(m_object));
+ FireBullet(m_fire_pos, m_fire_dir, fireDispersionBase,
+ *m_Ammo, m_object->ID(), m_object->ID(), SendHitAllowed(m_object), ::Random.randI(0,30));
StartShotParticles();
diff --git a/src/xrGame/Entity.cpp b/src/xrGame/Entity.cpp
index ff52793bb46..5c90db4acbb 100644
--- a/src/xrGame/Entity.cpp
+++ b/src/xrGame/Entity.cpp
@@ -253,21 +253,20 @@ void CEntity::net_Destroy()
void CEntity::KillEntity(u16 whoID, bool bypass_actor_check)
{
- if (GameID() == eGameIDSingle && this->ID() == Actor()->ID())
+ if (IsGameTypeSingle() && this->ID() == Actor()->ID())
{
- //AVO: allow scripts to process actor condition and prevent actor's death or kill him if desired.
- //IMPORTANT: if you wish to kill actor you need to call db.actor:kill(level:object_by_id(whoID), true) in actor_before_death callback, to ensure all objects are properly destroyed
- // this will bypass below if block and go to normal KillEntity routine.
+ Actor()->use_HolderEx(nullptr, true);
#ifdef ACTOR_BEFORE_DEATH_CALLBACK
+ //AVO: allow scripts to process actor condition and prevent actor's death or kill him if desired.
+ //IMPORTANT: if you wish to kill actor you need to call db.actor:kill(level:object_by_id(whoID), true) in actor_before_death callback, to ensure all objects are properly destroyed
+ // this will bypass below if block and go to normal KillEntity routine.
if (bypass_actor_check == false)
{
Actor()->callback(GameObject::eActorBeforeDeath)(whoID);
return;
}
+ //-AVO
#endif
- //-AVO
- Actor()->detach_Vehicle();
- Actor()->use_MountedWeapon(nullptr);
}
if (whoID != ID())
{
diff --git a/src/xrGame/GameObject.cpp b/src/xrGame/GameObject.cpp
index 60aece96f3a..ee438186e98 100644
--- a/src/xrGame/GameObject.cpp
+++ b/src/xrGame/GameObject.cpp
@@ -273,7 +273,11 @@ void CGameObject::reinit()
it->second.clear();
}
-void CGameObject::reload(LPCSTR section) { m_script_clsid = object_factory().script_clsid(CLS_ID); }
+void CGameObject::reload(LPCSTR section)
+{
+ m_script_clsid = object_factory().script_clsid(CLS_ID);
+}
+
void CGameObject::net_Destroy()
{
#ifdef DEBUG
@@ -287,7 +291,6 @@ void CGameObject::net_Destroy()
xr_delete(m_ini_file);
- m_script_clsid = -1;
if (Visual() && smart_cast(Visual()))
smart_cast(Visual())->Callback(0, 0);
//
@@ -325,6 +328,7 @@ void CGameObject::net_Destroy()
//. Parent = 0;
scriptBinder.net_Destroy();
+ m_script_clsid = -1;
xr_delete(m_lua_game_object);
m_spawned = false;
@@ -450,6 +454,7 @@ bool CGameObject::net_Spawn(CSE_Abstract* DC)
cNameSect_set(E->s_name);
if (E->name_replace()[0])
cName_set(E->name_replace());
+
bool demo_spectator = false;
if (Level().IsDemoPlayStarted() && E->ID == u16(-1))
@@ -461,11 +466,12 @@ bool CGameObject::net_Spawn(CSE_Abstract* DC)
{
//Alundaio:
//R_ASSERT(Level().Objects.net_Find(E->ID) == nullptr);
- if (Level().Objects.net_Find(E->ID) != nullptr)
+ if (const auto obj = Level().Objects.net_Find(E->ID))
{
- GEnv.ScriptEngine->script_log(LuaMessageType::Error, "CGameObject:net_Spawn() | Level().Objects.net_Find(E->ID) != nullptr (This mean object already exist on level by this ID) ID=%s s_name=%s", E->ID, E->s_name.c_str());
+ Msg("! ERROR: CGameObject:net_spawn() Object with ID[%u] already exists! self=%s other=%s", E->ID, cName().c_str(), obj->cName().c_str());
return false;
}
+ //-Alundaio
}
setID(E->ID);
@@ -713,57 +719,57 @@ void CGameObject::spawn_supplies()
for (u32 k = 0, j; spawn_ini()->r_line("spawn", k, &N, &V); k++)
{
VERIFY(xr_strlen(N));
- if (pSettings->section_exist(N)) //Alundaio: Validate section exists
- {
- j = 1;
- p = 1.f;
+ if (!pSettings->section_exist(N)) //Alundaio: Validate section exists
+ continue;
- float f_cond = 1.0f;
- if (V && xr_strlen(V))
- {
- int n = _GetItemCount(V);
- string16 temp;
- if (n > 0)
- j = atoi(_GetItem(V, 0, temp)); // count
-
- if (NULL != strstr(V, "prob="))
- p = (float)atof(strstr(V, "prob=") + 5);
- if (fis_zero(p))
- p = 1.f;
- if (!j)
- j = 1;
- if (NULL != strstr(V, "cond="))
- f_cond = (float)atof(strstr(V, "cond=") + 5);
- bScope = (NULL != strstr(V, "scope"));
- bSilencer = (NULL != strstr(V, "silencer"));
- bLauncher = (NULL != strstr(V, "launcher"));
- }
- for (u32 i = 0; i < j; ++i)
- {
- if (::Random.randF(1.f) < p)
- {
- CSE_Abstract* A = Level().spawn_item(N, Position(), ai_location().level_vertex_id(), ID(), true);
+ j = 1;
+ p = 1.f;
- CSE_ALifeInventoryItem* pSE_InventoryItem = smart_cast(A);
- if (pSE_InventoryItem)
- pSE_InventoryItem->m_fCondition = f_cond;
+ float f_cond = 1.0f;
+ if (V && xr_strlen(V))
+ {
+ int n = _GetItemCount(V);
+ string16 temp;
+ if (n > 0)
+ j = atoi(_GetItem(V, 0, temp)); // count
+
+ if (NULL != strstr(V, "prob="))
+ p = (float)atof(strstr(V, "prob=") + 5);
+ if (fis_zero(p))
+ p = 1.f;
+ if (!j)
+ j = 1;
+ if (NULL != strstr(V, "cond="))
+ f_cond = (float)atof(strstr(V, "cond=") + 5);
+ bScope = (NULL != strstr(V, "scope"));
+ bSilencer = (NULL != strstr(V, "silencer"));
+ bLauncher = (NULL != strstr(V, "launcher"));
+ }
+ for (u32 i = 0; i < j; ++i)
+ {
+ if (::Random.randF(1.f) < p)
+ {
+ CSE_Abstract* A = Level().spawn_item(N, Position(), ai_location().level_vertex_id(), ID(), true);
- CSE_ALifeItemWeapon* W = smart_cast(A);
- if (W)
- {
- if (W->m_scope_status == ALife::eAddonAttachable)
- W->m_addon_flags.set(CSE_ALifeItemWeapon::eWeaponAddonScope, bScope);
- if (W->m_silencer_status == ALife::eAddonAttachable)
- W->m_addon_flags.set(CSE_ALifeItemWeapon::eWeaponAddonSilencer, bSilencer);
- if (W->m_grenade_launcher_status == ALife::eAddonAttachable)
- W->m_addon_flags.set(CSE_ALifeItemWeapon::eWeaponAddonGrenadeLauncher, bLauncher);
- }
+ CSE_ALifeInventoryItem* pSE_InventoryItem = smart_cast(A);
+ if (pSE_InventoryItem)
+ pSE_InventoryItem->m_fCondition = f_cond;
- NET_Packet P;
- A->Spawn_Write(P, TRUE);
- Level().Send(P, net_flags(TRUE));
- F_entity_Destroy(A);
+ CSE_ALifeItemWeapon* W = smart_cast(A);
+ if (W)
+ {
+ if (W->m_scope_status == ALife::eAddonAttachable)
+ W->m_addon_flags.set(CSE_ALifeItemWeapon::eWeaponAddonScope, bScope);
+ if (W->m_silencer_status == ALife::eAddonAttachable)
+ W->m_addon_flags.set(CSE_ALifeItemWeapon::eWeaponAddonSilencer, bSilencer);
+ if (W->m_grenade_launcher_status == ALife::eAddonAttachable)
+ W->m_addon_flags.set(CSE_ALifeItemWeapon::eWeaponAddonGrenadeLauncher, bLauncher);
}
+
+ NET_Packet P;
+ A->Spawn_Write(P, TRUE);
+ Level().Send(P, net_flags(TRUE));
+ F_entity_Destroy(A);
}
}
}
diff --git a/src/xrGame/GameObject.h b/src/xrGame/GameObject.h
index 8a620e23ae6..d22ad1a801b 100644
--- a/src/xrGame/GameObject.h
+++ b/src/xrGame/GameObject.h
@@ -320,7 +320,7 @@ class CGameObject : public IGameObject,
virtual CScriptGameObject* lua_game_object() const override;
virtual int clsid() const override
{
- THROW(m_script_clsid >= 0);
+ VERIFY(m_script_clsid >= 0);
return m_script_clsid;
}
virtual CInifile* spawn_ini() override { return m_ini_file; }
diff --git a/src/xrGame/GameTask.h b/src/xrGame/GameTask.h
index 223e56d7dc8..930005bf45d 100644
--- a/src/xrGame/GameTask.h
+++ b/src/xrGame/GameTask.h
@@ -110,11 +110,11 @@ class SGameTaskObjective : public ISerializable
protected:
virtual void ChangeStateCallback();
- void CreateMapLocation(bool on_load);
public:
void RemoveMapLocations(bool notify);
void ChangeMapLocation(pcstr new_map_location, u16 new_map_object_id);
+ void CreateMapLocation(bool on_load); // Made public only for Lua export
// for scripting access
auto GetType_script() const { return m_task_type; }
diff --git a/src/xrGame/GameTask_script.cpp b/src/xrGame/GameTask_script.cpp
index ab01da239b7..5bd95580e8b 100644
--- a/src/xrGame/GameTask_script.cpp
+++ b/src/xrGame/GameTask_script.cpp
@@ -58,6 +58,8 @@ SCRIPT_EXPORT(CGameTask, (),
.def("get_type", &SGameTaskObjective::GetType_script)
.def("set_type", &SGameTaskObjective::SetType_script)
+ .def("get_map_location", +[](const SGameTaskObjective* self) -> pcstr { return self->m_map_location.c_str(); })
+ .def("get_map_object_id", +[](const SGameTaskObjective* self) -> u16 { return self->m_map_object_id; })
.def("set_map_hint", &SGameTaskObjective::SetMapHint_script)
.def("set_map_location", &SGameTaskObjective::SetMapLocation_script)
.def("set_map_object_id", &SGameTaskObjective::SetMapObjectID_script)
@@ -66,6 +68,7 @@ SCRIPT_EXPORT(CGameTask, (),
.def("remove_map_locations", &SGameTaskObjective::RemoveMapLocations)
.def("change_map_location", &SGameTaskObjective::ChangeMapLocation)
+ .def("create_map_location", &SGameTaskObjective::CreateMapLocation)
.def("add_complete_info", &SGameTaskObjective::AddCompleteInfo_script)
.def("add_complete_func", &SGameTaskObjective::AddCompleteFunc_script)
diff --git a/src/xrGame/HelicopterWeapon.cpp b/src/xrGame/HelicopterWeapon.cpp
index 917578c6f32..40ecdbd35fb 100644
--- a/src/xrGame/HelicopterWeapon.cpp
+++ b/src/xrGame/HelicopterWeapon.cpp
@@ -143,7 +143,7 @@ void CHelicopter::OnShot()
fire_dir.sub(enemy_pos, fire_pos).normalize_safe();
};
- FireBullet(fire_pos, fire_dir, fireDispersionBase, m_CurrentAmmo, ID(), ID(), OnServer());
+ FireBullet(fire_pos, fire_dir, fireDispersionBase, m_CurrentAmmo, ID(), ID(), OnServer(), ::Random.randI(0,30));
StartShotParticles();
if (m_bLightShotEnabled)
diff --git a/src/xrGame/HolderEntityObject.cpp b/src/xrGame/HolderEntityObject.cpp
new file mode 100644
index 00000000000..ae494550132
--- /dev/null
+++ b/src/xrGame/HolderEntityObject.cpp
@@ -0,0 +1,234 @@
+#include "StdAfx.h"
+
+#include "HolderEntityObject.h"
+
+#include "Actor.h"
+#include "ActorEffector.h"
+#include "CameraFirstEye.h"
+#include "Level.h"
+
+#include "Include/xrRender/Kinematics.h"
+
+#include "xrPhysics/PhysicsShell.h"
+
+void CHolderEntityObject::BoneCallbackX(CBoneInstance* B)
+{
+}
+
+void CHolderEntityObject::BoneCallbackY(CBoneInstance* B)
+{
+}
+
+CHolderEntityObject::CHolderEntityObject()
+ : camera(xr_new(this, CCameraBase::flRelativeLink | CCameraBase::flPositionRigid | CCameraBase::flDirectionRigid))
+{
+ camera->Load("holder_entity_object_cam");
+}
+
+CHolderEntityObject::~CHolderEntityObject()
+{
+ xr_delete(camera);
+}
+
+void CHolderEntityObject::SetBoneCallbacks()
+{
+ m_pPhysicsShell->EnabledCallbacks(false);
+}
+
+void CHolderEntityObject::ResetBoneCallbacks()
+{
+ m_pPhysicsShell->EnabledCallbacks(true);
+}
+
+void CHolderEntityObject::Load(LPCSTR section)
+{
+ inheritedPH::Load(section);
+ m_bAllowWeapon = pSettings->r_bool(section, "allow_weapon");
+ m_bExitLocked = pSettings->r_bool(section, "lock_exit");
+ m_bEnterLocked = pSettings->r_bool(section, "lock_enter");
+
+ m_exit_position = READ_IF_EXISTS(pSettings, r_fvector3, section, "exit_pos", Fvector().set(0.0f, 0.0f, 0.0f));
+ m_camera_position = READ_IF_EXISTS(pSettings, r_fvector3, section, "camera_pos", Fvector().set(0.0f, 0.0f, 0.0f));
+ m_camera_angle = READ_IF_EXISTS(pSettings, r_fvector3, section, "camera_angle", Fvector().set(0.0f, 0.0f, 0.0f));
+ m_sUseAction = READ_IF_EXISTS(pSettings, r_string, section, "use_action_hint", nullptr);
+}
+
+bool CHolderEntityObject::net_Spawn(CSE_Abstract* DC)
+{
+ if (!inheritedPH::net_Spawn(DC))
+ return false;
+
+ IKinematics* K = smart_cast(Visual());
+ xr_vector fixed_bones;
+ fixed_bones.push_back(K->LL_GetBoneRoot());
+ PPhysicsShell() = P_build_Shell(this, false, fixed_bones);
+
+ processing_activate();
+ setVisible(true);
+ setEnabled(true);
+ return true;
+}
+
+void CHolderEntityObject::net_Destroy()
+{
+ inheritedPH::net_Destroy();
+ processing_deactivate();
+}
+
+void CHolderEntityObject::net_Export(NET_Packet& P) // export to server
+{
+ inheritedPH::net_Export(P);
+}
+
+void CHolderEntityObject::net_Import(NET_Packet& P) // import from server
+{
+ inheritedPH::net_Import(P);
+}
+
+void CHolderEntityObject::attach_actor_script(bool bForce)
+{
+ Actor()->use_HolderEx(this, bForce);
+}
+
+void CHolderEntityObject::detach_actor_script(bool bForce)
+{
+ Actor()->use_HolderEx(nullptr, bForce);
+}
+
+void CHolderEntityObject::UpdateCL()
+{
+ inheritedPH::UpdateCL();
+
+ if (OwnerActor() && OwnerActor()->IsMyCamera())
+ {
+ cam_Update(Device.fTimeDelta, g_fov);
+ OwnerActor()->Cameras().UpdateFromCamera(Camera());
+ OwnerActor()->Cameras().ApplyDevice();
+ }
+}
+
+void CHolderEntityObject::Hit(SHit* pHDS)
+{
+ if (!Owner())
+ inheritedPH::Hit(pHDS);
+}
+
+void CHolderEntityObject::cam_Update(float dt, float fov)
+{
+ Fvector P;
+
+ XFORM().transform_tiny(P, m_camera_position);
+
+ if (OwnerActor())
+ {
+ // rotate head
+ OwnerActor()->Orientation().yaw = -Camera()->yaw;
+ OwnerActor()->Orientation().pitch = -Camera()->pitch;
+ }
+
+ Camera()->f_fov = fov;
+ Camera()->Update(P, m_camera_angle);
+ Level().Cameras().UpdateFromCamera(Camera());
+}
+
+void CHolderEntityObject::renderable_Render(u32 context_id, IRenderable* root)
+{
+ inheritedPH::renderable_Render(context_id, root);
+}
+
+void CHolderEntityObject::Action(u16 id, u32 flags)
+{
+ inheritedHolder::Action(id, flags);
+ /*
+ switch (id)
+ {
+ case kWPN_FIRE:
+ {
+ if (flags == CMD_START)
+ FireStart();
+ else
+ FireEnd();
+ break;
+ }
+ }
+ */
+}
+
+void CHolderEntityObject::SetParam(int id, Fvector2 val)
+{
+ inheritedHolder::SetParam(id, val);
+}
+
+bool CHolderEntityObject::attach_Actor(CGameObject* actor)
+{
+ inheritedHolder::attach_Actor(actor);
+ SetBoneCallbacks();
+ return true;
+}
+
+void CHolderEntityObject::detach_Actor()
+{
+ inheritedHolder::detach_Actor();
+ ResetBoneCallbacks();
+}
+
+void CHolderEntityObject::OnMouseMove(int dx, int dy)
+{
+ if (Remote())
+ return;
+ CCameraBase* C = camera;
+ float scale = (C->f_fov / g_fov) * psMouseSens * psMouseSensScale / 50.f;
+ if (dx)
+ {
+ const float d = float(dx) * scale;
+ C->Move((d < 0) ? kLEFT : kRIGHT, _abs(d));
+ }
+ if (dy)
+ {
+ const float d = ((psMouseInvert.test(1)) ? -1 : 1) * float(dy) * scale * 3.f / 4.f;
+ C->Move((d > 0) ? kUP : kDOWN, _abs(d));
+ }
+}
+
+void CHolderEntityObject::OnKeyboardPress(int dik)
+{
+ if (Remote())
+ return;
+
+ switch (dik)
+ {
+ case kWPN_FIRE:
+ break;
+ }
+}
+
+void CHolderEntityObject::OnKeyboardRelease(int dik)
+{
+ if (Remote())
+ return;
+ switch (dik)
+ {
+ case kWPN_FIRE:
+ break;
+ }
+}
+
+void CHolderEntityObject::OnKeyboardHold(int dik)
+{
+}
+
+void CHolderEntityObject::OnControllerPress(int cmd, float x, float y)
+{
+}
+
+void CHolderEntityObject::OnControllerRelease(int cmd, float x, float y)
+{
+}
+
+void CHolderEntityObject::OnControllerHold(int cmd, float x, float y)
+{
+}
+
+void CHolderEntityObject::OnControllerAttitudeChange(Fvector change)
+{
+}
diff --git a/src/xrGame/HolderEntityObject.h b/src/xrGame/HolderEntityObject.h
new file mode 100644
index 00000000000..f1f7b2a7153
--- /dev/null
+++ b/src/xrGame/HolderEntityObject.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include "holder_custom.h"
+#include "PhysicsShellHolder.h"
+
+class CCameraBase;
+
+class CHolderEntityObject final : public CPhysicsShellHolder, public CHolderCustom
+{
+ typedef CPhysicsShellHolder inheritedPH;
+ typedef CHolderCustom inheritedHolder;
+
+private:
+ CCameraBase* camera;
+
+ static void BoneCallbackX(CBoneInstance* B);
+ static void BoneCallbackY(CBoneInstance* B);
+ void SetBoneCallbacks();
+ void ResetBoneCallbacks();
+
+public:
+ //casts
+ CHolderCustom* cast_holder_custom() override { return this; }
+
+public:
+ //general
+ CHolderEntityObject();
+ ~CHolderEntityObject() override;
+
+ void Load(pcstr section) override;
+
+ bool net_Spawn(CSE_Abstract* DC) override;
+ void net_Destroy() override;
+ void net_Export(NET_Packet& P) override; // export to server
+ void net_Import(NET_Packet& P) override; // import from server
+
+ void UpdateCL() override;
+
+ void Hit(SHit* pHDS) override;
+
+private:
+ //shooting
+ Fvector3 m_camera_position{};
+ Fvector3 m_exit_position{};
+ Fvector3 m_camera_angle{};
+
+ Fvector2 m_lim_x_rot{}, m_lim_y_rot{}; //in bone space
+ bool m_bAllowWeapon;
+
+public:
+ //HolderCustom
+ bool Use(const Fvector& pos, const Fvector& dir, const Fvector& foot_pos) override { return !Owner(); };
+ void OnMouseMove(int x, int y) override;
+ void OnKeyboardPress(int dik) override;
+ void OnKeyboardRelease(int dik) override;
+ void OnKeyboardHold(int dik) override;
+ void OnControllerPress(int cmd, float x, float y) override;
+ void OnControllerRelease(int cmd, float x, float y) override;
+ void OnControllerHold(int cmd, float x, float y) override;
+ void OnControllerAttitudeChange(Fvector change) override;
+ CInventory* GetInventory() override { return nullptr; };
+ void cam_Update(float dt, float fov = 90.0f) override;
+
+ void renderable_Render(u32 context_id, IRenderable* root) override;
+
+ void attach_actor_script(bool bForce = false);
+ void detach_actor_script(bool bForce = false);
+
+ bool attach_Actor(CGameObject* actor) override;
+ void detach_Actor() override;
+ bool allowWeapon() const override { return m_bAllowWeapon; };
+ bool HUDView() const override { return true; };
+ Fvector ExitPosition() override { return m_exit_position; };
+
+ CCameraBase* Camera() override { return camera; };
+
+ void Action(u16 id, u32 flags) override;
+ void SetParam(int id, Fvector2 val) override;
+};
diff --git a/src/xrGame/HudItem.cpp b/src/xrGame/HudItem.cpp
index 0cecb3cf54e..57af3628972 100644
--- a/src/xrGame/HudItem.cpp
+++ b/src/xrGame/HudItem.cpp
@@ -143,6 +143,12 @@ void CHudItem::OnStateSwitch(u32 S, u32 oldState)
void CHudItem::OnAnimationEnd(u32 state)
{
+ if (const auto actor = smart_cast(object().H_Parent()))
+ {
+ actor->callback(GameObject::eActorHudAnimationEnd)(
+ smart_cast(this)->lua_game_object(),
+ hud_sect.c_str(), m_current_motion.c_str(), state, animation_slot());
+ }
switch (state)
{
case eBore: { SwitchState(eIdle);
diff --git a/src/xrGame/HudSound.cpp b/src/xrGame/HudSound.cpp
index a8a14a4189d..a3656c11e21 100644
--- a/src/xrGame/HudSound.cpp
+++ b/src/xrGame/HudSound.cpp
@@ -99,9 +99,17 @@ void HUD_SOUND_ITEM::PlaySound(
hud_snd.m_activeSnd = &hud_snd.sounds[index];
- hud_snd.m_activeSnd->snd.play_at_pos(const_cast(parent),
- flags & sm_2D ? Fvector().set(0, 0, 0) : position, flags, hud_snd.m_activeSnd->delay);
-
+ if (hud_snd.m_b_exclusive)
+ {
+ hud_snd.m_activeSnd->snd.play_at_pos(const_cast(parent),
+ flags & sm_2D ? Fvector().set(0, 0, 0) : position, flags, hud_snd.m_activeSnd->delay);
+ }
+ else
+ {
+ Fvector pos = flags & sm_2D ? Fvector{} : position;
+ hud_snd.m_activeSnd->snd.play_no_feedback(const_cast(parent),
+ flags, hud_snd.m_activeSnd->delay, &pos, nullptr, nullptr, nullptr);
+ }
hud_snd.m_activeSnd->snd.set_volume(hud_snd.m_activeSnd->volume * (b_hud_mode ? psHUDSoundVolume : 1.0f));
}
@@ -145,8 +153,8 @@ void HUD_SOUND_COLLECTION::PlaySound(
if (sound_item.m_b_exclusive)
HUD_SOUND_ITEM::StopSound(sound_item);
- HUD_SOUND_ITEM* snd_item = FindSoundItem(alias, true);
- HUD_SOUND_ITEM::PlaySound(*snd_item, position, parent, hud_mode, looped, index);
+ if (const auto snd_item = FindSoundItem(alias, false))
+ HUD_SOUND_ITEM::PlaySound(*snd_item, position, parent, hud_mode, looped, index);
}
void HUD_SOUND_COLLECTION::StopSound(LPCSTR alias)
@@ -157,8 +165,8 @@ void HUD_SOUND_COLLECTION::StopSound(LPCSTR alias)
void HUD_SOUND_COLLECTION::SetPosition(LPCSTR alias, const Fvector& pos)
{
- HUD_SOUND_ITEM* snd_item = FindSoundItem(alias, true);
- if (snd_item->playing())
+ HUD_SOUND_ITEM* snd_item = FindSoundItem(alias, false);
+ if (snd_item && snd_item->playing())
snd_item->set_position(pos);
}
diff --git a/src/xrGame/Inventory.cpp b/src/xrGame/Inventory.cpp
index 7d4888ec2bb..032041f9b7f 100644
--- a/src/xrGame/Inventory.cpp
+++ b/src/xrGame/Inventory.cpp
@@ -1083,6 +1083,12 @@ bool CInventory::Eat(PIItem pIItem)
pItemToEat->object().cNameSect().c_str());
#endif // MP_LOGGING
+ luabind::functor funct;
+ if (GEnv.ScriptEngine->functor("_G.CInventory__eat", funct))
+ {
+ if (!funct(smart_cast(pItemToEat->object().H_Parent())->lua_game_object(), smart_cast(pIItem)->lua_game_object()))
+ return false;
+ }
CActor* pActor = smart_cast(Level().CurrentControlEntity());
if (pActor && pActor->m_inventory == this)
@@ -1096,7 +1102,6 @@ bool CInventory::Eat(PIItem pIItem)
CurrentGameUI()->GetActorMenu().SetCurrentItem(nullptr);
}
-
if (pItemToEat->Empty())
{
if (!pItemToEat->CanDelete())
@@ -1283,13 +1288,24 @@ u32 CInventory::BeltMaxWidth() const
return m_iMaxBelt;
}
-void CInventory::AddAvailableItems(TIItemContainer& items_container, bool for_trade) const
+void CInventory::AddAvailableItems(TIItemContainer& items_container, bool for_trade, bool bOverride /*= false*/) const
{
for (TIItemContainer::const_iterator it = m_ruck.begin(); m_ruck.end() != it; ++it)
{
PIItem pIItem = *it;
if (!for_trade || pIItem->CanTrade())
+ {
+ if (bOverride)
+ {
+ luabind::functor funct;
+ if (GEnv.ScriptEngine->functor("actor_menu_inventory.CInventory_ItemAvailableToTrade", funct))
+ {
+ if (!funct(m_pOwner->cast_game_object()->lua_game_object(), pIItem->cast_game_object()->lua_game_object()))
+ continue;
+ }
+ }
items_container.push_back(pIItem);
+ }
}
if (m_bBeltUseful)
@@ -1298,7 +1314,18 @@ void CInventory::AddAvailableItems(TIItemContainer& items_container, bool for_tr
{
PIItem pIItem = *it;
if (!for_trade || pIItem->CanTrade())
+ {
+ if (bOverride)
+ {
+ luabind::functor funct;
+ if (GEnv.ScriptEngine->functor("actor_menu_inventory.CInventory_ItemAvailableToTrade", funct))
+ {
+ if (!funct(m_pOwner->cast_game_object()->lua_game_object(), pIItem->cast_game_object()->lua_game_object()))
+ continue;
+ }
+ }
items_container.push_back(pIItem);
+ }
}
}
@@ -1312,7 +1339,18 @@ void CInventory::AddAvailableItems(TIItemContainer& items_container, bool for_tr
if (item && (!for_trade || item->CanTrade()))
{
if (!SlotIsPersistent(I) || item->BaseSlot() == GRENADE_SLOT)
+ {
+ if (bOverride)
+ {
+ luabind::functor funct;
+ if (GEnv.ScriptEngine->functor("actor_menu_inventory.CInventory_ItemAvailableToTrade", funct))
+ {
+ if (!funct(m_pOwner->cast_game_object()->lua_game_object(), item->cast_game_object()->lua_game_object()))
+ continue;
+ }
+ }
items_container.push_back(item);
+ }
}
}
}
diff --git a/src/xrGame/Inventory.h b/src/xrGame/Inventory.h
index e14c354b5ad..4d3ce630826 100644
--- a/src/xrGame/Inventory.h
+++ b/src/xrGame/Inventory.h
@@ -132,7 +132,7 @@ class CInventory
public:
//возвращает все кроме PDA в слоте и болта
- void AddAvailableItems(TIItemContainer& items_container, bool for_trade) const;
+ void AddAvailableItems(TIItemContainer& items_container, bool for_trade, bool bOverride = false) const;
float GetMaxWeight() const { return m_fMaxWeight; }
void SetMaxWeight(float weight) { m_fMaxWeight = weight; }
diff --git a/src/xrGame/Level_Bullet_Manager.cpp b/src/xrGame/Level_Bullet_Manager.cpp
index 29872c6fd09..f94eec1fb00 100644
--- a/src/xrGame/Level_Bullet_Manager.cpp
+++ b/src/xrGame/Level_Bullet_Manager.cpp
@@ -35,7 +35,7 @@ float g_bullet_time_factor = 1.f;
SBullet::SBullet(const Fvector& position, const Fvector& direction, float starting_speed, float power,
/*float power_critical,*/ float impulse, u16 sender_id, u16 sendersweapon_id, ALife::EHitType e_hit_type,
- float maximum_distance, const CCartridge& cartridge, float const air_resistance_factor, bool SendHit)
+ float maximum_distance, const CCartridge& cartridge, float const air_resistance_factor, bool SendHit, int iShotNum /*= 0*/)
{
bullet_pos = position;
speed = max_speed = starting_speed;
@@ -67,6 +67,11 @@ SBullet::SBullet(const Fvector& position, const Fvector& direction, float starti
bullet_material_idx = cartridge.bullet_material_idx;
VERIFY(u16(-1) != bullet_material_idx);
+ //Alundaio: Tracer for every 5th bullet
+ if (flags.allow_tracer && cartridge.m_4to1_tracer && iShotNum % 5 != 0)
+ flags.allow_tracer = false;
+ //-Alundaio
+
flags.allow_tracer = !!cartridge.m_flags.test(CCartridge::cfTracer);
flags.allow_ricochet = !!cartridge.m_flags.test(CCartridge::cfRicochet);
flags.explosive = !!cartridge.m_flags.test(CCartridge::cfExplosive);
@@ -176,7 +181,7 @@ void CBulletManager::Clear()
void CBulletManager::AddBullet(const Fvector& position, const Fvector& direction, float starting_speed, float power,
//. float power_critical,
float impulse, u16 sender_id, u16 sendersweapon_id, ALife::EHitType e_hit_type, float maximum_distance,
- const CCartridge& cartridge, float const air_resistance_factor, bool SendHit, bool AimBullet)
+ const CCartridge& cartridge, float const air_resistance_factor, bool SendHit, bool AimBullet, int iShotNum /*= 0*/)
{
// Always called in Primary thread
// Uncomment below if you will change the behaviour
@@ -189,7 +194,7 @@ void CBulletManager::AddBullet(const Fvector& position, const Fvector& direction
// u32 CurID = Level().CurrentControlEntity()->ID();
// u32 OwnerID = sender_id;
SBullet& bullet = m_Bullets.emplace_back(position, direction, starting_speed, power, /*power_critical,*/ impulse, sender_id,
- sendersweapon_id, e_hit_type, maximum_distance, cartridge, air_resistance_factor, SendHit);
+ sendersweapon_id, e_hit_type, maximum_distance, cartridge, air_resistance_factor, SendHit, iShotNum);
// bullet.frame_num = Device.dwFrame;
bullet.flags.aim_bullet = AimBullet;
if (!IsGameTypeSingle())
@@ -853,6 +858,8 @@ void CBulletManager::Render()
SBullet* bullet = &sbullet;
if (!bullet->flags.allow_tracer)
continue;
+ if (!psActorFlags.test(AF_USE_TRACERS))
+ continue;
if (!bullet->CanBeRenderedNow())
continue;
diff --git a/src/xrGame/Level_Bullet_Manager.h b/src/xrGame/Level_Bullet_Manager.h
index df2d72f57c9..67c9fe8a213 100644
--- a/src/xrGame/Level_Bullet_Manager.h
+++ b/src/xrGame/Level_Bullet_Manager.h
@@ -83,7 +83,7 @@ struct SBullet
public:
SBullet(const Fvector& position, const Fvector& direction, float start_speed, float power,
/*float power_critical,*/ float impulse, u16 sender_id, u16 sendersweapon_id, ALife::EHitType e_hit_type,
- float maximum_distance, const CCartridge& cartridge, float const air_resistance_factor, bool SendHit);
+ float maximum_distance, const CCartridge& cartridge, float const air_resistance_factor, bool SendHit, int iShotNum = 0);
bool CanBeRenderedNow() const { return (Device.dwFrame > init_frame_num); }
};
@@ -207,7 +207,7 @@ class CBulletManager
void AddBullet(const Fvector& position, const Fvector& direction, float starting_speed, float power,
/*float power_critical,*/ float impulse, u16 sender_id, u16 sendersweapon_id, ALife::EHitType e_hit_type,
float maximum_distance, const CCartridge& cartridge, float const air_resistance_factor, bool SendHit,
- bool AimBullet = false);
+ bool AimBullet = false, int iShotNum = 0);
void CommitEvents(); // @ the start of frame
void CommitRenderSet(); // @ the end of frame
diff --git a/src/xrGame/Level_input.cpp b/src/xrGame/Level_input.cpp
index 051199fc076..afa0ac05c41 100644
--- a/src/xrGame/Level_input.cpp
+++ b/src/xrGame/Level_input.cpp
@@ -111,8 +111,10 @@ void CLevel::IR_OnMouseMove(int dx, int dy)
extern bool g_block_pause;
// Lain: added TEMP!!!
+#ifdef DEBUG
extern float g_separate_factor;
extern float g_separate_radius;
+#endif
#include "xrScriptEngine/script_engine.hpp"
#include "ai_space.h"
@@ -214,6 +216,13 @@ void CLevel::IR_OnKeyboardPress(int key)
if (game && game->OnKeyboardPress(GetBindedAction(key)))
return;
+ luabind::functor funct;
+ if (GEnv.ScriptEngine->functor("level_input.on_key_press", funct))
+ {
+ if (funct(key, _curr))
+ return;
+ }
+
if (_curr == kQUICK_SAVE && IsGameTypeSingle())
{
Console->Execute("save");
diff --git a/src/xrGame/ScriptXMLInit.cpp b/src/xrGame/ScriptXMLInit.cpp
index 46911dba27a..d7646ed0089 100644
--- a/src/xrGame/ScriptXMLInit.cpp
+++ b/src/xrGame/ScriptXMLInit.cpp
@@ -8,6 +8,7 @@
#include "xrUICore/ComboBox/UIComboBox.h"
#include "xrUICore/TabControl/UITabControl.h"
#include "xrUICore/Windows/UIFrameWindow.h"
+#include "xrUICore/Hint/UIHint.h"
#include "ui/UILabel.h"
#include "ui/ServerList.h"
#include "ui/UIMapList.h"
@@ -49,6 +50,14 @@ void CScriptXmlInit::InitWindow(LPCSTR path, int index, CUIWindow* pWnd)
CUIXmlInit::InitWindow(m_xml, path, index, pWnd);
}
+UIHint* CScriptXmlInit::InitHint(pcstr path, CUIWindow* parent)
+{
+ UIHint* pWnd = xr_new();
+ pWnd->init_from_xml(m_xml, path);
+ _attach_child(pWnd, parent);
+ return pWnd;
+}
+
CUIFrameWindow* CScriptXmlInit::InitFrame(LPCSTR path, CUIWindow* parent)
{
CUIFrameWindow* pWnd = xr_new(path);
@@ -271,6 +280,7 @@ SCRIPT_EXPORT(CScriptXmlInit, (),
.def("ParseFile", &CScriptXmlInit::ParseFile)
.def("ParseShTexInfo", &CScriptXmlInit::ParseShTexInfo)
.def("InitWindow", &CScriptXmlInit::InitWindow)
+ .def("InitHint", &CScriptXmlInit::InitHint)
.def("InitFrame", &CScriptXmlInit::InitFrame)
.def("InitFrameLine", &CScriptXmlInit::InitFrameLine)
.def("InitEditBox", &CScriptXmlInit::InitEditBox)
diff --git a/src/xrGame/ScriptXMLInit.h b/src/xrGame/ScriptXMLInit.h
index 737816abe4d..7db15ebc382 100644
--- a/src/xrGame/ScriptXMLInit.h
+++ b/src/xrGame/ScriptXMLInit.h
@@ -28,6 +28,7 @@ class CUIScrollView;
class CUIListWnd;
class CUIListBox;
class CUIProgressBar;
+class UIHint;
class CScriptXmlInit
{
@@ -35,6 +36,7 @@ class CScriptXmlInit
void ParseFile(LPCSTR xml_file);
void ParseShTexInfo(pcstr xml_file);
void InitWindow(LPCSTR path, int index, CUIWindow* pWnd);
+ UIHint* InitHint(pcstr path, CUIWindow* parent);
CUIFrameWindow* InitFrame(LPCSTR path, CUIWindow* parent);
CUIFrameLineWnd* InitFrameLine(LPCSTR path, CUIWindow* parent);
CUIEditBox* InitEditBox(LPCSTR path, CUIWindow* parent);
@@ -63,6 +65,8 @@ class CScriptXmlInit
CUIListBox* InitListBox(LPCSTR path, CUIWindow* parent);
CUIProgressBar* InitProgressBar(LPCSTR path, CUIWindow* parent);
+ CUIXml& GetXml() { return m_xml; }
+
protected:
CUIXml m_xml;
};
diff --git a/src/xrGame/ShootingObject.cpp b/src/xrGame/ShootingObject.cpp
index 59fd266e501..0693acfd559 100644
--- a/src/xrGame/ShootingObject.cpp
+++ b/src/xrGame/ShootingObject.cpp
@@ -40,18 +40,19 @@ void CShootingObject::Load(LPCSTR section)
//время затрачиваемое на выстрел
fOneShotTime = pSettings->r_float(section, "rpm");
+
//Alundaio: Two-shot burst rpm; used for Abakan/AN-94
- modeShotTime = READ_IF_EXISTS(pSettings, r_float, section, "rpm_mode_2", fOneShotTime);
+ fModeShotTime = READ_IF_EXISTS(pSettings, r_float, section, "rpm_mode_2", fOneShotTime);
VERIFY(fOneShotTime > 0.f);
fOneShotTime = 60.f / fOneShotTime;
- modeShotTime = 60.f / modeShotTime;
+ fModeShotTime = 60.f / fModeShotTime;
//Cycle down RPM after first 2 shots; used for Abakan/AN-94
if (pSettings->line_exist(section, "cycle_down"))
- cycleDown = pSettings->r_bool(section, "cycle_down") ? true : false;
+ bCycleDown = pSettings->r_bool(section, "cycle_down") ? true : false;
else
- cycleDown = false;
+ bCycleDown = false;
//Alundaio: END
LoadFireParams(section);
@@ -444,7 +445,7 @@ bool CShootingObject::SendHitAllowed(IGameObject* pUser)
extern void random_dir(Fvector& tgt_dir, const Fvector& src_dir, float dispersion);
void CShootingObject::FireBullet(const Fvector& pos, const Fvector& shot_dir, float fire_disp,
- const CCartridge& cartridge, u16 parent_id, u16 weapon_id, bool send_hit)
+ const CCartridge& cartridge, u16 parent_id, u16 weapon_id, bool send_hit, int iShotNum /*= 0*/)
{
Fvector dir;
random_dir(dir, shot_dir, fire_disp);
@@ -504,7 +505,7 @@ void CShootingObject::FireBullet(const Fvector& pos, const Fvector& shot_dir, fl
Level().BulletManager().AddBullet(pos, dir, m_fStartBulletSpeed * cur_silencer_koef.bullet_speed,
l_fHitPower * cur_silencer_koef.hit_power, fHitImpulse * cur_silencer_koef.hit_impulse, parent_id, weapon_id,
- ALife::eHitTypeFireWound, fireDistance, cartridge, m_air_resistance_factor, send_hit, aim_bullet);
+ ALife::eHitTypeFireWound, fireDistance, cartridge, m_air_resistance_factor, send_hit, aim_bullet, iShotNum);
}
void CShootingObject::FireStart() { bWorking = true; }
void CShootingObject::FireEnd() { bWorking = false; }
diff --git a/src/xrGame/ShootingObject.h b/src/xrGame/ShootingObject.h
index ec9762b133c..36c508592fb 100644
--- a/src/xrGame/ShootingObject.h
+++ b/src/xrGame/ShootingObject.h
@@ -46,7 +46,7 @@ class CShootingObject : public IAnticheatDumpable
virtual void LoadFireParams(LPCSTR section); //сила выстрела
virtual bool SendHitAllowed(IGameObject* pUser);
virtual void FireBullet(const Fvector& pos, const Fvector& dir, float fire_disp, const CCartridge& cartridge,
- u16 parent_id, u16 weapon_id, bool send_hit);
+ u16 parent_id, u16 weapon_id, bool send_hit, int iShotNum = 0);
void SetBulletSpeed(float new_speed) { m_fStartBulletSpeed = new_speed; }
float GetBulletSpeed() { return m_fStartBulletSpeed; }
virtual void FireStart();
@@ -61,8 +61,8 @@ class CShootingObject : public IAnticheatDumpable
bool bWorking{};
float fOneShotTime{};
- float modeShotTime;
- bool cycleDown;
+ float fModeShotTime;
+ bool bCycleDown;
Fvector4 fvHitPower{};
Fvector4 fvHitPowerCritical{};
float fHitImpulse;
diff --git a/src/xrGame/UIDialogHolder.cpp b/src/xrGame/UIDialogHolder.cpp
index 9732c081fe7..4838bef9be1 100644
--- a/src/xrGame/UIDialogHolder.cpp
+++ b/src/xrGame/UIDialogHolder.cpp
@@ -41,7 +41,7 @@ void CDialogHolder::StartMenu(CUIDialogWnd* pDialog, bool bDoHideIndicators)
AddDialogToRender(pDialog);
SetMainInputReceiver(pDialog, false);
- if (UseIndicators())
+ if (UseIndicators() && !m_input_receivers.empty()) //Alundaio
{
bool b = !!psHUD_Flags.test(HUD_CROSSHAIR_RT);
m_input_receivers.back().m_flags.set(recvItem::eCrosshair, b);
@@ -82,7 +82,7 @@ void CDialogHolder::StopMenu(CUIDialogWnd* pDialog)
if (TopInputReceiver() == pDialog)
{
- if (UseIndicators())
+ if (UseIndicators() && !m_input_receivers.empty()) //Alundaio
{
bool b = !!m_input_receivers.back().m_flags.test(recvItem::eCrosshair);
psHUD_Flags.set(HUD_CROSSHAIR_RT, b);
diff --git a/src/xrGame/UIGameCustom.cpp b/src/xrGame/UIGameCustom.cpp
index 6ecbbb3b687..6b3106cdba3 100644
--- a/src/xrGame/UIGameCustom.cpp
+++ b/src/xrGame/UIGameCustom.cpp
@@ -227,8 +227,12 @@ void CUIGameCustom::ShowMessagesWindow()
bool CUIGameCustom::ShowPdaMenu()
{
HideActorMenu();
- PdaMenu->ShowDialog(true);
- return true;
+ if (!PdaMenu->IsShown())
+ {
+ PdaMenu->ShowDialog(true);
+ return true;
+ }
+ return false;
}
void CUIGameCustom::HidePdaMenu()
diff --git a/src/xrGame/Weapon.cpp b/src/xrGame/Weapon.cpp
index c556cb13eba..391adfab3e8 100644
--- a/src/xrGame/Weapon.cpp
+++ b/src/xrGame/Weapon.cpp
@@ -1703,6 +1703,14 @@ const CInventoryItem* CWeapon::can_kill(const xr_vector& ite
bool CWeapon::ready_to_kill() const
{
+ //Alundaio
+ const auto io = smart_cast(H_Parent());
+ if (!io)
+ return false;
+
+ if (!io->inventory().ActiveItem() || io->inventory().ActiveItem()->object().ID() != ID())
+ return false;
+ //-Alundaio
return (
!IsMisfire() && ((GetState() == eIdle) || (GetState() == eFire) || (GetState() == eFire2)) && GetAmmoElapsed());
}
diff --git a/src/xrGame/WeaponAmmo.cpp b/src/xrGame/WeaponAmmo.cpp
index dd07aaef61e..70d4ec4da8d 100644
--- a/src/xrGame/WeaponAmmo.cpp
+++ b/src/xrGame/WeaponAmmo.cpp
@@ -56,6 +56,9 @@ void CCartridge::Load(LPCSTR section, u8 LocalAmmoType)
m_flags.set(cfMagneticBeam, TRUE);
}
+ if (pSettings->line_exist(section, "4to1_tracer"))
+ m_4to1_tracer = pSettings->r_bool(section, "4to1_tracer");;
+
if (pSettings->line_exist(section, "can_be_unlimited"))
m_flags.set(cfCanBeUnlimited, pSettings->r_bool(section, "can_be_unlimited"));
@@ -104,6 +107,10 @@ void CWeaponAmmo::Load(LPCSTR section)
else
cartridge_param.kAirRes = pSettings->r_float(BULLET_MANAGER_SECTION, "air_resistance_k");
m_tracer = !!pSettings->r_bool(section, "tracer");
+
+ if (pSettings->line_exist(section, "4to1_tracer"))
+ m_4to1_tracer = pSettings->r_bool(section, "4to1_tracer");;
+
cartridge_param.buckShot = pSettings->r_s32(section, "buck_shot");
cartridge_param.impair = pSettings->r_float(section, "impair");
cartridge_param.fWallmarkSize = pSettings->r_float(section, "wm_size");
@@ -167,6 +174,7 @@ bool CWeaponAmmo::Get(CCartridge& cartridge)
cartridge.param_s = cartridge_param;
cartridge.m_flags.set(CCartridge::cfTracer, m_tracer);
+ cartridge.m_4to1_tracer = m_4to1_tracer;
cartridge.bullet_material_idx = GMLib.GetMaterialIdx(WEAPON_MATERIAL_NAME);
cartridge.m_InvShortName = NameShort();
--m_boxCurr;
diff --git a/src/xrGame/WeaponAmmo.h b/src/xrGame/WeaponAmmo.h
index d2df35b84f4..b6f732367c0 100644
--- a/src/xrGame/WeaponAmmo.h
+++ b/src/xrGame/WeaponAmmo.h
@@ -42,6 +42,7 @@ class CCartridge : public IAnticheatDumpable
SCartridgeParam param_s;
u8 m_LocalAmmoType;
+ bool m_4to1_tracer{};
u16 bullet_material_idx;
Flags8 m_flags;
@@ -81,6 +82,7 @@ class CWeaponAmmo : public CInventoryItemObject
u16 m_boxSize;
u16 m_boxCurr;
bool m_tracer;
+ bool m_4to1_tracer{};
public:
virtual CInventoryItem* can_make_killing(const CInventory* inventory) const;
diff --git a/src/xrGame/WeaponAutomaticShotgun.h b/src/xrGame/WeaponAutomaticShotgun.h
index f477b6ccd32..f280930cb8b 100644
--- a/src/xrGame/WeaponAutomaticShotgun.h
+++ b/src/xrGame/WeaponAutomaticShotgun.h
@@ -25,7 +25,7 @@ class CWeaponAutomaticShotgun : public CWeaponMagazined
void PlayAnimCloseWeapon();
virtual bool Action(u16 cmd, u32 flags);
- //virtual int GetCurrentFireMode() { return m_aFireModes[m_iCurFireMode]; } //AVO: this is already implemented in parent class (CWeaponMagazined)
+
protected:
virtual void OnAnimationEnd(u32 state);
void TriStateReload();
diff --git a/src/xrGame/WeaponCustomPistolAuto.cpp b/src/xrGame/WeaponCustomPistolAuto.cpp
deleted file mode 100644
index 59de9453a63..00000000000
--- a/src/xrGame/WeaponCustomPistolAuto.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "StdAfx.h"
-#include "WeaponCustomPistolAuto.h"
-
-CWeaponCustomPistolAuto::CWeaponCustomPistolAuto() : CWeaponMagazined(SOUND_TYPE_WEAPON_PISTOL) {}
-
-CWeaponCustomPistolAuto::~CWeaponCustomPistolAuto() {}
-
-void CWeaponCustomPistolAuto::switch2_Fire()
-{
- m_bFireSingleShot = true;
- //bWorking = false;
- m_iShotNum = 0;
- m_bStopedAfterQueueFired = false;
-}
-
-void CWeaponCustomPistolAuto::FireEnd()
-{
- //if (fShotTimeCounter <= 0)
- {
- //SetPending(false);
- inherited::FireEnd();
- }
-}
-
-void CWeaponCustomPistolAuto::PlayAnimReload()
-{
- inherited::PlayAnimReload();
-}
diff --git a/src/xrGame/WeaponCustomPistolAuto.h b/src/xrGame/WeaponCustomPistolAuto.h
deleted file mode 100644
index eae1fc6ab99..00000000000
--- a/src/xrGame/WeaponCustomPistolAuto.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include "WeaponMagazined.h"
-
-class CWeaponCustomPistolAuto: public CWeaponMagazined
-{
- using inherited = CWeaponMagazined;
-
-public:
- CWeaponCustomPistolAuto();
- virtual ~CWeaponCustomPistolAuto();
- //int GetCurrentFireMode() override { return 1; };
-
-protected:
- void FireEnd() override;
- void switch2_Fire() override;
- void PlayAnimReload() override;
-};
diff --git a/src/xrGame/WeaponFire.cpp b/src/xrGame/WeaponFire.cpp
index fbbe67b9104..c977be39918 100644
--- a/src/xrGame/WeaponFire.cpp
+++ b/src/xrGame/WeaponFire.cpp
@@ -111,7 +111,7 @@ void CWeapon::FireTrace(const Fvector& P, const Fvector& D)
//выстерлить пулю (с учетом возможной стрельбы дробью)
for (int i = 0; i < l_cartridge.param_s.buckShot; ++i)
{
- FireBullet(P, D, fire_disp, l_cartridge, H_Parent()->ID(), ID(), SendHit);
+ FireBullet(P, D, fire_disp, l_cartridge, H_Parent()->ID(), ID(), SendHit, iAmmoElapsed);
}
StartShotParticles();
diff --git a/src/xrGame/WeaponMagazined.cpp b/src/xrGame/WeaponMagazined.cpp
index a6bad977fab..8686e63552e 100644
--- a/src/xrGame/WeaponMagazined.cpp
+++ b/src/xrGame/WeaponMagazined.cpp
@@ -56,8 +56,7 @@ void CWeaponMagazined::net_Destroy() { inherited::net_Destroy(); }
bool CWeaponMagazined::WeaponSoundExist(pcstr section, pcstr sound_name) const
{
pcstr str;
- bool sec_exist = process_if_exists_set(section, sound_name, &CInifile::r_string, str, true);
- if (sec_exist)
+ if (process_if_exists_set(section, sound_name, &CInifile::r_string, str, true))
return true;
#ifdef DEBUG
Msg("~ [WARNING] ------ Sound [%s] does not exist in [%s]", sound_name, section);
@@ -72,14 +71,14 @@ void CWeaponMagazined::Load(LPCSTR section)
inherited::Load(section);
// Sounds
- m_sounds.LoadSound(section, "snd_draw", "sndShow", false, m_eSoundShow);
- m_sounds.LoadSound(section, "snd_holster", "sndHide", false, m_eSoundHide);
+ m_sounds.LoadSound(section, "snd_draw", "sndShow", true, m_eSoundShow);
+ m_sounds.LoadSound(section, "snd_holster", "sndHide", true, m_eSoundHide);
//Alundaio: LAYERED_SND_SHOOT
m_layered_sounds.LoadSound(section, "snd_shoot", "sndShot", false, m_eSoundShot);
//-Alundaio
- m_sounds.LoadSound(section, "snd_empty", "sndEmptyClick", false, m_eSoundEmptyClick);
+ m_sounds.LoadSound(section, "snd_empty", "sndEmptyClick", true, m_eSoundEmptyClick);
m_sounds.LoadSound(section, "snd_reload", "sndReload", true, m_eSoundReload);
if (WeaponSoundExist(section, "snd_reload_empty"))
@@ -87,7 +86,7 @@ void CWeaponMagazined::Load(LPCSTR section)
if (WeaponSoundExist(section, "snd_reload_misfire"))
m_sounds.LoadSound(section, "snd_reload_misfire", "sndReloadMisfire", true, m_eSoundReloadMisfire);
- m_sSndShotCurrent = "sndShot";
+ m_sSndShotCurrent = IsSilencerAttached() ? "sndSilencerShot" : "sndShot";
//звуки и партиклы глушителя, если такой есть
if (m_eSilencerStatus == ALife::eAddonAttachable || m_eSilencerStatus == ALife::eAddonPermanent)
@@ -99,8 +98,6 @@ void CWeaponMagazined::Load(LPCSTR section)
//Alundaio: LAYERED_SND_SHOOT Silencer
m_layered_sounds.LoadSound(section, "snd_silncer_shot", "sndSilencerShot", false, m_eSoundShot);
- if (WeaponSoundExist(section, "snd_silncer_shot_actor"))
- m_layered_sounds.LoadSound(section, "snd_silncer_shot_actor", "sndSilencerShotActor", false, m_eSoundShot);
//-Alundaio
}
@@ -169,12 +166,9 @@ void CWeaponMagazined::FireStart()
else // misfire
{
// Alundaio
- CGameObject* object = smart_cast(H_Parent());
- if (object)
+ if (const auto object = smart_cast(H_Parent()))
{
- auto& cb = object->callback(GameObject::eOnWeaponJammed);
- if (cb)
- cb(object->lua_game_object(), this->lua_game_object());
+ object->callback(GameObject::eOnWeaponJammed)(object->lua_game_object(), this->lua_game_object());
}
if (smart_cast(this->H_Parent()) && (Level().CurrentViewEntity() == H_Parent()))
@@ -258,6 +252,12 @@ bool CWeaponMagazined::IsAmmoAvailable()
void CWeaponMagazined::OnMagazineEmpty()
{
+ if (IsGameTypeSingle() && ParentIsActor())
+ {
+ int AC = GetSuitableAmmoTotal();
+ Actor()->callback(GameObject::eOnWeaponMagazineEmpty)(lua_game_object(), AC);
+ }
+
if (GetState() == eIdle)
{
OnEmptyClick();
@@ -297,6 +297,12 @@ void CWeaponMagazined::UnloadMagazine(bool spawn_ammo)
VERIFY((u32)iAmmoElapsed == m_magazine.size());
+ if (IsGameTypeSingle() && ParentIsActor())
+ {
+ int AC = GetSuitableAmmoTotal();
+ Actor()->callback(GameObject::eOnWeaponMagazineEmpty)(lua_game_object(), AC);
+ }
+
if (!spawn_ammo)
return;
@@ -550,8 +556,8 @@ void CWeaponMagazined::state_Fire(float dt)
//Alundaio: Use fModeShotTime instead of fOneShotTime if current fire mode is 2-shot burst
//Alundaio: Cycle down RPM after two shots; used for Abakan/AN-94
- if (GetCurrentFireMode() == 2 || (cycleDown == true && m_iShotNum <= 1))
- fShotTimeCounter = modeShotTime;
+ if (GetCurrentFireMode() == 2 || (bCycleDown == true && m_iShotNum <= 1))
+ fShotTimeCounter = fModeShotTime;
else
fShotTimeCounter = fOneShotTime;
//Alundaio: END
@@ -677,43 +683,34 @@ void CWeaponMagazined::switch2_Idle()
void CWeaponMagazined::switch2_Fire()
{
CInventoryOwner* io = smart_cast(H_Parent());
-
-#ifdef DEBUG
if (!io)
return;
- // VERIFY2(io, make_string("no inventory owner, item %s", *cName()));
CInventoryItem* ii = smart_cast(this);
+ if (ii != io->inventory().ActiveItem())
+ {
+ Msg("~ WARNING: Not an active item, item %s, owner %s, active item %s",
+ cName().c_str(), H_Parent()->cName().c_str(),
+ io->inventory().ActiveItem() ? io->inventory().ActiveItem()->object().cName().c_str() : "no_active_item");
+ return;
+ }
+#ifdef DEBUG
if (ii != io->inventory().ActiveItem())
Msg("! not an active item, item %s, owner %s, active item %s", *cName(), *H_Parent()->cName(),
io->inventory().ActiveItem() ? *io->inventory().ActiveItem()->object().cName() : "no_active_item");
if (!(io && (ii == io->inventory().ActiveItem())))
{
- CAI_Stalker* stalker = smart_cast(H_Parent());
- if (stalker)
+ if (const auto stalker = smart_cast(H_Parent()))
{
stalker->planner().show();
stalker->planner().show_current_world_state();
stalker->planner().show_target_world_state();
}
}
-#else
- if (!io)
- return;
#endif // DEBUG
- //
- // VERIFY2(
- // io && (ii == io->inventory().ActiveItem()),
- // make_string(
- // "item[%s], parent[%s]",
- // *cName(),
- // H_Parent() ? *H_Parent()->cName() : "no_parent"
- // )
- // );
-
m_bStopedAfterQueueFired = false;
m_bFireSingleShot = true;
m_iShotNum = 0;
@@ -750,10 +747,12 @@ void CWeaponMagazined::PlayReloadSound()
else
{
if (iAmmoElapsed == 0)
+ {
if (m_sounds.FindSoundItem("sndReloadEmpty", false))
PlaySound("sndReloadEmpty", get_LastFP());
else
PlaySound("sndReload", get_LastFP());
+ }
else
PlaySound("sndReload", get_LastFP());
}
@@ -1171,16 +1170,12 @@ void CWeaponMagazined::OnZoomIn()
PlayAnimIdle();
// Alundaio
- CGameObject* object = smart_cast(H_Parent());
- if (object)
+ if (const auto object = smart_cast(H_Parent()))
{
- auto& cb = object->callback(GameObject::eOnWeaponZoomIn);
- if (cb)
- cb(object->lua_game_object(), this->lua_game_object());
+ object->callback(GameObject::eOnWeaponZoomIn)(object->lua_game_object(), this->lua_game_object());
}
- CActor* pActor = smart_cast(H_Parent());
- if (pActor)
+ if (CActor* pActor = smart_cast(H_Parent()))
{
CEffectorZoomInertion* S = smart_cast(pActor->Cameras().GetCamEffector(eCEZoom));
if (!S)
@@ -1203,17 +1198,12 @@ void CWeaponMagazined::OnZoomOut()
PlayAnimIdle();
//Alundaio
- CGameObject* object = smart_cast(H_Parent());
- if (object)
+ if (const auto object = smart_cast(H_Parent()))
{
- auto& cb = object->callback(GameObject::eOnWeaponZoomOut);
- if (cb)
- cb(object->lua_game_object(), this->lua_game_object());
+ object->callback(GameObject::eOnWeaponZoomOut)(object->lua_game_object(), this->lua_game_object());
}
- CActor* pActor = smart_cast(H_Parent());
-
- if (pActor)
+ if (CActor* pActor = smart_cast(H_Parent()))
pActor->Cameras().RemoveCamEffector(eCEZoom);
}
@@ -1537,5 +1527,5 @@ void CWeaponMagazined::FireBullet(const Fvector& pos, const Fvector& shot_dir, f
SetBulletSpeed(m_fOldBulletSpeed);
}
}
- inherited::FireBullet(pos, shot_dir, fire_disp, cartridge, parent_id, weapon_id, send_hit);
+ inherited::FireBullet(pos, shot_dir, fire_disp, cartridge, parent_id, weapon_id, send_hit, GetAmmoElapsed());
}
diff --git a/src/xrGame/WeaponMagazinedWGrenade.cpp b/src/xrGame/WeaponMagazinedWGrenade.cpp
index 4c646432fd5..8382acb95e5 100644
--- a/src/xrGame/WeaponMagazinedWGrenade.cpp
+++ b/src/xrGame/WeaponMagazinedWGrenade.cpp
@@ -30,7 +30,7 @@ void CWeaponMagazinedWGrenade::Load(LPCSTR section)
CRocketLauncher::Load(section);
//// Sounds
- m_sounds.LoadSound(section, "snd_shoot_grenade", "sndShotG", false, m_eSoundShot);
+ m_sounds.LoadSound(section, "snd_shoot_grenade", "sndShotG", true, m_eSoundShot);
m_sounds.LoadSound(section, "snd_reload_grenade", "sndReloadG", true, m_eSoundReload);
m_sounds.LoadSound(section, "snd_switch", "sndSwitch", true, m_eSoundReload);
@@ -658,12 +658,12 @@ void CWeaponMagazinedWGrenade::PlayAnimIdle()
{
case state::idle:
{
- PlayHUDMotion("anm_idle_g", "anim_idle_g", TRUE, nullptr, GetState());
+ PlayHUDMotion("anm_idle_g", "anim_idle_g", true, nullptr, GetState());
break;
}
case state::sprint:
{
- PlayHUDMotion("anm_idle_sprint_g", "anim_idle_g", TRUE, nullptr, GetState());
+ PlayHUDMotion("anm_idle_sprint_g", "anim_idle_g", true, nullptr, GetState());
break;
}
case state::crouch:
@@ -677,7 +677,7 @@ void CWeaponMagazinedWGrenade::PlayAnimIdle()
}
case state::moving:
{
- PlayHUDMotion("anm_idle_moving_g", "anim_idle_g", TRUE, nullptr, GetState());
+ PlayHUDMotion("anm_idle_moving_g", "anim_idle_g", true, nullptr, GetState());
break;
}
} // switch (act_state)
@@ -688,12 +688,12 @@ void CWeaponMagazinedWGrenade::PlayAnimIdle()
{
case state::idle:
{
- PlayHUDMotion("anm_idle_w_gl", "anim_idle_gl", TRUE, nullptr, GetState());
+ PlayHUDMotion("anm_idle_w_gl", "anim_idle_gl", true, nullptr, GetState());
break;
}
case state::sprint:
{
- PlayHUDMotion("anm_idle_sprint_w_gl", "anim_idle_sprint", TRUE, nullptr, GetState());
+ PlayHUDMotion("anm_idle_sprint_w_gl", "anim_idle_sprint", true, nullptr, GetState());
break;
}
case state::crouch:
@@ -707,7 +707,7 @@ void CWeaponMagazinedWGrenade::PlayAnimIdle()
}
case state::moving:
{
- PlayHUDMotion("anm_idle_moving_w_gl", "anim_idle_gl", TRUE, nullptr, GetState());
+ PlayHUDMotion("anm_idle_moving_w_gl", "anim_idle_gl", true, nullptr, GetState());
break;
}
} // switch (act_state)
@@ -925,7 +925,7 @@ bool CWeaponMagazinedWGrenade::GetBriefInfo(II_BriefInfo& info)
return false;
*/
string32 int_str;
- int ae = GetAmmoElapsed();
+ const int ae = GetAmmoElapsed();
xr_sprintf(int_str, "%d", ae);
info.cur_ammo._set(int_str);
if (HasFireModes())
@@ -941,9 +941,7 @@ bool CWeaponMagazinedWGrenade::GetBriefInfo(II_BriefInfo& info)
if (m_pInventory->ModifyFrame() <= m_BriefInfo_CalcFrame)
return false;
- GetSuitableAmmoTotal();
-
- const u32 at_size = m_bGrenadeMode ? m_ammoTypes2.size() : m_ammoTypes.size();
+ const size_t at_size = m_bGrenadeMode ? m_ammoTypes2.size() : m_ammoTypes.size();
if (unlimited_ammo() || at_size == 0)
{
info.fmj_ammo._set("--");
@@ -958,30 +956,27 @@ bool CWeaponMagazinedWGrenade::GetBriefInfo(II_BriefInfo& info)
info.ap_ammo._set("");
info.third_ammo._set("");
- int total = 0;
if (at_size >= 1)
{
const int fmj = m_bGrenadeMode ? GetAmmoCount2(0) : GetAmmoCount(0);
xr_sprintf(int_str, "%d", fmj);
info.fmj_ammo._set(int_str);
- total += fmj;
}
if (at_size >= 2)
{
const int ap = m_bGrenadeMode ? GetAmmoCount2(1) : GetAmmoCount(1);
xr_sprintf(int_str, "%d", ap);
info.ap_ammo._set(int_str);
- total += ap;
}
if (at_size >= 3)
{
const int third = m_bGrenadeMode ? GetAmmoCount2(2) : GetAmmoCount(2);
xr_sprintf(int_str, "%d", third);
info.third_ammo._set(int_str);
- total += third;
}
- xr_sprintf(int_str, "%d", total);
+ const int ac = GetSuitableAmmoTotal();
+ xr_sprintf(int_str, "%d", ac - ae);
info.total_ammo = int_str;
//-Alundaio
}
diff --git a/src/xrGame/WeaponPistol.cpp b/src/xrGame/WeaponPistol.cpp
index a41cc4de262..c0e9ab1817a 100644
--- a/src/xrGame/WeaponPistol.cpp
+++ b/src/xrGame/WeaponPistol.cpp
@@ -84,11 +84,6 @@ void CWeaponPistol::PlayAnimAim()
inherited::PlayAnimAim();
}
-void CWeaponPistol::PlayAnimReload()
-{
- inherited::PlayAnimReload(); //AVO: refactored to use grand-parent (CWeaponMagazined) function
-}
-
void CWeaponPistol::PlayAnimHide()
{
VERIFY(GetState() == eHiding);
@@ -116,10 +111,6 @@ void CWeaponPistol::PlayAnimShoot()
void CWeaponPistol::switch2_Reload() { inherited::switch2_Reload(); }
void CWeaponPistol::OnAnimationEnd(u32 state) { inherited::OnAnimationEnd(state); }
-void CWeaponPistol::OnShot()
-{
- inherited::OnShot(); //Alundaio: not changed from inherited, so instead of copying changes from weaponmagazined, we just do this
-}
void CWeaponPistol::UpdateSounds()
{
diff --git a/src/xrGame/WeaponPistol.h b/src/xrGame/WeaponPistol.h
index e3f81f13200..82eba06b6bf 100644
--- a/src/xrGame/WeaponPistol.h
+++ b/src/xrGame/WeaponPistol.h
@@ -13,7 +13,6 @@ class CWeaponPistol : public CWeaponCustomPistol
virtual void switch2_Reload();
- virtual void OnShot();
virtual void OnAnimationEnd(u32 state);
virtual void net_Destroy();
virtual void OnH_B_Chield();
@@ -24,7 +23,6 @@ class CWeaponPistol : public CWeaponCustomPistol
virtual void PlayAnimIdleMoving();
virtual void PlayAnimIdleSprint();
virtual void PlayAnimHide();
- virtual void PlayAnimReload();
virtual void PlayAnimShoot();
virtual void PlayAnimBore();
virtual void PlayAnimAim();
diff --git a/src/xrGame/WeaponRevolver.cpp b/src/xrGame/WeaponRevolver.cpp
index 18d43e6c2cb..62f5ff4c9fe 100644
--- a/src/xrGame/WeaponRevolver.cpp
+++ b/src/xrGame/WeaponRevolver.cpp
@@ -98,7 +98,6 @@ void CWeaponRevolver::PlayAnimReload()
PlayHUDMotion("anm_reload_5", true, this, state);
else
PlayHUDMotion("anm_reload", true, this, state);
-
}
diff --git a/src/xrGame/WeaponStatMgun.cpp b/src/xrGame/WeaponStatMgun.cpp
index e8d90c7c80d..d3f3adc6fb2 100644
--- a/src/xrGame/WeaponStatMgun.cpp
+++ b/src/xrGame/WeaponStatMgun.cpp
@@ -62,7 +62,7 @@ void CWeaponStatMgun::ResetBoneCallbacks()
m_pPhysicsShell->EnabledCallbacks(TRUE);
}
-void CWeaponStatMgun::Load(LPCSTR section)
+void CWeaponStatMgun::Load(cpcstr section)
{
inheritedPH::Load(section);
inheritedShooting::Load(section);
@@ -74,6 +74,15 @@ void CWeaponStatMgun::Load(LPCSTR section)
camRelaxSpeed = pSettings->r_float(section, "cam_relax_speed");
camRelaxSpeed = _abs(deg2rad(camRelaxSpeed));
+ m_overheat_enabled = pSettings->read_if_exists(section, "overheat_enabled", false);
+ m_overheat_time_quant = pSettings->read_if_exists(section, "overheat_time_quant", 0.025f);
+ m_overheat_decr_quant = pSettings->read_if_exists(section, "overheat_decr_quant", 0.002f);
+ m_overheat_threshold = pSettings->read_if_exists(section, "overheat_threshold", 110.f);
+ m_overheat_particles = pSettings->read_if_exists(section, "overheat_particles", "damage_fx\\burn_creatures00");
+
+ m_bEnterLocked = pSettings->read_if_exists(section, "lock_enter", false);
+ m_bExitLocked = pSettings->read_if_exists(section, "lock_exit", false);
+
VERIFY(!fis_zero(camMaxAngle));
VERIFY(!fis_zero(camRelaxSpeed));
}
@@ -129,6 +138,12 @@ bool CWeaponStatMgun::net_Spawn(CSE_Abstract* DC)
void CWeaponStatMgun::net_Destroy()
{
+ if (p_overheat)
+ {
+ if (p_overheat->IsPlaying())
+ p_overheat->Stop(false);
+ CParticlesObject::Destroy(p_overheat);
+ }
inheritedPH::net_Destroy();
processing_deactivate();
}
diff --git a/src/xrGame/WeaponStatMgun.h b/src/xrGame/WeaponStatMgun.h
index e2cb598f77e..6ceaa4336ad 100644
--- a/src/xrGame/WeaponStatMgun.h
+++ b/src/xrGame/WeaponStatMgun.h
@@ -62,6 +62,15 @@ class CWeaponStatMgun : public CPhysicsShellHolder, public CHolderCustom, public
float camRelaxSpeed;
float camMaxAngle;
+ bool m_firing_disabled{};
+ bool m_overheat_enabled{};
+ float m_overheat_value{};
+ float m_overheat_time_quant{};
+ float m_overheat_decr_quant{};
+ float m_overheat_threshold{};
+ shared_str m_overheat_particles;
+ CParticlesObject* p_overheat{};
+
protected:
void UpdateBarrelDir();
virtual const Fvector& get_CurrentFirePoint();
diff --git a/src/xrGame/WeaponStatMgunFire.cpp b/src/xrGame/WeaponStatMgunFire.cpp
index 52b57f74d40..afc7bbb90e7 100644
--- a/src/xrGame/WeaponStatMgunFire.cpp
+++ b/src/xrGame/WeaponStatMgunFire.cpp
@@ -12,6 +12,9 @@ const Fvector& CWeaponStatMgun::get_CurrentFirePoint() { return m_fire_pos; }
const Fmatrix& CWeaponStatMgun::get_ParticlesXFORM() { return m_fire_bone_xform; }
void CWeaponStatMgun::FireStart()
{
+ if (m_firing_disabled)
+ return;
+
m_dAngle.set(0.0f, 0.0f);
inheritedShooting::FireStart();
}
@@ -31,12 +34,64 @@ void CWeaponStatMgun::UpdateFire()
inheritedShooting::UpdateFlameParticles();
inheritedShooting::UpdateLight();
+ if (m_overheat_enabled)
+ {
+ m_overheat_value -= m_overheat_decr_quant;
+ if (m_overheat_value < 100.f)
+ {
+ if (p_overheat)
+ {
+ if (p_overheat->IsPlaying())
+ p_overheat->Stop(false);
+ CParticlesObject::Destroy(p_overheat);
+ }
+ if (m_firing_disabled)
+ m_firing_disabled = false;
+ }
+ else {
+ if (p_overheat)
+ {
+ Fmatrix pos;
+ pos.set(get_ParticlesXFORM());
+ pos.c.set(get_CurrentFirePoint());
+ p_overheat->SetXFORM(pos);
+ }
+ }
+ }
+
if (!IsWorking())
{
clamp(fShotTimeCounter, 0.0f, flt_max);
+ clamp(m_overheat_value, 0.0f, m_overheat_threshold);
return;
}
+ if (m_overheat_enabled)
+ {
+ m_overheat_value += m_overheat_time_quant;
+ clamp(m_overheat_value, 0.0f, m_overheat_threshold);
+
+ if (m_overheat_value >= 100.f)
+ {
+ if (!p_overheat)
+ {
+ p_overheat = CParticlesObject::Create(m_overheat_particles.c_str(),FALSE);
+ Fmatrix pos;
+ pos.set(get_ParticlesXFORM());
+ pos.c.set(get_CurrentFirePoint());
+ p_overheat->SetXFORM(pos);
+ p_overheat->Play(false);
+ }
+
+ if (m_overheat_value >= m_overheat_threshold)
+ {
+ m_firing_disabled = true;
+ FireEnd();
+ return;
+ }
+ }
+ }
+
if (fShotTimeCounter <= 0)
{
OnShot();
@@ -53,7 +108,7 @@ void CWeaponStatMgun::OnShot()
{
VERIFY(Owner());
- FireBullet(m_fire_pos, m_fire_dir, fireDispersionBase, *m_Ammo, Owner()->ID(), ID(), SendHitAllowed(Owner()));
+ FireBullet(m_fire_pos, m_fire_dir, fireDispersionBase, *m_Ammo, Owner()->ID(), ID(), SendHitAllowed(Owner()), ::Random.randI(0,30));
StartShotParticles();
diff --git a/src/xrGame/accumulative_states.h b/src/xrGame/accumulative_states.h
index 55f7ac28636..34b7994fd7e 100644
--- a/src/xrGame/accumulative_states.h
+++ b/src/xrGame/accumulative_states.h
@@ -1,6 +1,8 @@
#ifndef ACCUMULATIVE_STATES_INCLUDED
#define ACCUMULATIVE_STATES_INCLUDED
+#include
+
namespace award_system
{
enum enum_accumulative_player_values
diff --git a/src/xrGame/action_base.h b/src/xrGame/action_base.h
index 6a81559729d..319e9227061 100644
--- a/src/xrGame/action_base.h
+++ b/src/xrGame/action_base.h
@@ -47,9 +47,9 @@ class CActionBase : public GraphEngineSpace::CWorldOperator
mutable edge_value_type m_weight;
bool m_first_time;
-#ifdef LOG_ACTION
public:
- LPCSTR m_action_name;
+ pcstr m_action_name{};
+#ifdef LOG_ACTION
bool m_use_log;
bool m_switched;
diff --git a/src/xrGame/action_base_inline.h b/src/xrGame/action_base_inline.h
index 8c51701068a..04974c82ac3 100644
--- a/src/xrGame/action_base_inline.h
+++ b/src/xrGame/action_base_inline.h
@@ -25,9 +25,9 @@ void CBaseAction::init(_object_type* object, LPCSTR action_name)
m_object = object;
m_weight = edge_value_type(1);
+ m_action_name = action_name;
#ifdef LOG_ACTION
m_use_log = false;
- m_action_name = action_name;
m_switched = false;
// if (xr_strlen(m_action_name))
// debug_log (eActionStateConstructed);
diff --git a/src/xrGame/action_base_script.cpp b/src/xrGame/action_base_script.cpp
index 6bc1e2f0a20..89a28f015ac 100644
--- a/src/xrGame/action_base_script.cpp
+++ b/src/xrGame/action_base_script.cpp
@@ -18,7 +18,7 @@ IC static void CScriptActionBase_Export(lua_State* luaState)
module(luaState)
[
class_("action_base")
- .def_readonly("object", &CScriptActionBase::m_object)
+ .def_readwrite("object", &CScriptActionBase::m_object)
.def_readonly("storage", &CScriptActionBase::m_storage)
.def(constructor<>())
.def(constructor())
diff --git a/src/xrGame/action_planner_inline.h b/src/xrGame/action_planner_inline.h
index 3a98aa02040..247d551acb6 100644
--- a/src/xrGame/action_planner_inline.h
+++ b/src/xrGame/action_planner_inline.h
@@ -69,26 +69,29 @@ void CPlanner::update()
}
}
#endif
+ //Alundaio: debug action
+ static bool bDbgAct = strstr(Core.Params, "-dbgact") != NULL;
#ifdef LOG_ACTION
if (this->m_failed)
{
// printing current world state
show();
-
- Msg("! ERROR : there is no action sequence, which can transfer current world state to the target one");
- Msg("Time : %6d", Device.dwTimeGlobal);
- Msg("Object : %s", object_name());
-
+ Msg("! ERROR: there is no action sequence, which can transfer current world state to the target one: action[%s] object[%s], time[%6d]",
+ object_name(), current_action().m_action_name, Device.dwTimeGlobal);
show_current_world_state();
show_target_world_state();
- // VERIFY2 (!this->m_failed,"Problem solver couldn't build a valid path - verify your
- //conditions,
- // effects and goals!");
}
+#else
+ if (bDbgAct && this->m_failed && current_action().m_action_name)
+ Msg("! ERROR: there is no action sequence, which can transfer current world state to the target one: action[%s]", current_action().m_action_name);
#endif
THROW(!this->solution().empty());
+ //Alundaio:
+ if (this->solution().empty())
+ return;
+ //-Alundaio
if (initialized())
{
@@ -96,6 +99,9 @@ void CPlanner::update()
{
current_action().finalize();
m_current_action_id = this->solution().front();
+ //Alundaio: More detailed logging for initializing action
+ if (bDbgAct)
+ Msg("DEBUG: Action [%s] initializing", current_action().m_action_name);
current_action().initialize();
}
}
@@ -103,9 +109,17 @@ void CPlanner::update()
{
m_initialized = true;
m_current_action_id = this->solution().front();
+ //Alundaio: More detailed logging for initializing action
+ if (bDbgAct)
+ Msg("DEBUG: Action [%s] initializing", current_action().m_action_name);
current_action().initialize();
}
+ //Alundaio: More detailed logging for executing action; Knowing the last executing action before a crash can be very useful for debugging
+ if (bDbgAct)
+ Msg("DEBUG: Action [%s] executing", current_action().m_action_name);
+ //-Alundaio: Debug Action
+
current_action().execute();
}
diff --git a/src/xrGame/action_planner_script.cpp b/src/xrGame/action_planner_script.cpp
index c7f51ac1430..faa9e4d2614 100644
--- a/src/xrGame/action_planner_script.cpp
+++ b/src/xrGame/action_planner_script.cpp
@@ -29,7 +29,7 @@ IC static void CScriptActionPlanner_Export(lua_State* luaState)
module(luaState)
[
class_("action_planner")
- .def_readonly("object", &CScriptActionPlanner::m_object)
+ .def_readwrite("object", &CScriptActionPlanner::m_object)
.def_readonly("storage", &CScriptActionPlanner::m_storage)
.def(constructor<>())
.def("actual", &get_actual)
diff --git a/src/xrGame/ai/monsters/monster_sound_memory.h b/src/xrGame/ai/monsters/monster_sound_memory.h
index 310a1d5b3c8..23f82c0f270 100644
--- a/src/xrGame/ai/monsters/monster_sound_memory.h
+++ b/src/xrGame/ai/monsters/monster_sound_memory.h
@@ -65,7 +65,7 @@ typedef struct tagSoundElement
}
TSoundDangerValue ConvertSoundType(ESoundTypes stype);
- void CalcValue(TTime cur_time, Fvector cur_pos)
+ void CalcValue(TTime cur_time, const Fvector& cur_pos)
{
value = FACTOR_SOUND_TYPE * u32(NONE_DANGEROUS_SOUND - WEAPON_SHOOTING) -
iFloor(FACTOR_DISTANCE * cur_pos.distance_to(position)) -
diff --git a/src/xrGame/ai/phantom/phantom.cpp b/src/xrGame/ai/phantom/phantom.cpp
index ef7fe6eb50b..e171b5c2028 100644
--- a/src/xrGame/ai/phantom/phantom.cpp
+++ b/src/xrGame/ai/phantom/phantom.cpp
@@ -76,12 +76,12 @@ bool CPhantom::net_Spawn(CSE_Abstract* DC)
SwitchToState(stBirth); // initial state (changed on load method in inherited::)
+ OBJ->set_killer_id(u16(-1)); // Alundaio: Hack to prevent strange crash with dynamic phantoms
+
// inherited
if (!inherited::net_Spawn(DC))
return FALSE;
- OBJ->set_killer_id(u16(-1)); // Alundaio: Hack to prevent strange crash with dynamic phantoms
-
m_enemy = Level().CurrentEntity();
VERIFY(m_enemy);
@@ -294,7 +294,7 @@ void CPhantom::Hit(SHit* pHDS)
SwitchToState(stShoot);
if (g_Alive())
{
- SetfHealth(-1.f);
+ //SetfHealth(-1.f);
// inherited::Hit (P,dir,who,element,p_in_object_space,impulse/100.f, hit_type);
inherited::Hit(pHDS);
}
@@ -354,8 +354,14 @@ void CPhantom::PsyHit(const IGameObject* object, float value)
//---------------------------------------------------------------------
// Core events
-void CPhantom::save(NET_Packet& output_packet) { output_packet.w_s32(s32(m_CurState)); }
-void CPhantom::load(IReader& input_packet) { SwitchToState(EState(input_packet.r_s32())); }
+void CPhantom::save(NET_Packet& output_packet)
+{
+ //output_packet.w_s32(s32(m_CurState));
+}
+void CPhantom::load(IReader& input_packet)
+{
+ //SwitchToState(EState(input_packet.r_s32()));
+}
void CPhantom::net_Export(NET_Packet& P) // export to server
{
// export
diff --git a/src/xrGame/ai/stalker/ai_stalker_fire.cpp b/src/xrGame/ai/stalker/ai_stalker_fire.cpp
index 5cdd52ee4bb..0d3778f7ae7 100644
--- a/src/xrGame/ai/stalker/ai_stalker_fire.cpp
+++ b/src/xrGame/ai/stalker/ai_stalker_fire.cpp
@@ -49,6 +49,7 @@
#include "stalker_planner.h"
#include "stalker_decision_space.h"
#include "script_game_object.h"
+#include "script_game_object_impl.h"
#include "Inventory.h"
#include "trajectories.h"
@@ -229,6 +230,14 @@ void CAI_Stalker::Hit(SHit* pHDS)
SHit HDS = *pHDS;
HDS.add_wound = true;
+ //AVO: get bone names from IDs
+ //if (HDS.whoID == 0) // if shot by actor
+ //{
+ // pcstr bone_name = smart_cast(Visual())->LL_BoneName_dbg(HDS.boneID);
+ // Msg("Bone [%d]->[%s]", HDS.boneID, bone_name);
+ //}
+ //-AVO
+
float hit_power = HDS.power * m_fRankImmunity;
if (m_boneHitProtection && HDS.hit_type == ALife::eHitTypeFireWound)
@@ -405,7 +414,22 @@ void CAI_Stalker::update_best_item_info()
void CAI_Stalker::update_best_item_info_impl()
{
+ luabind::functor funct;
+ if (GEnv.ScriptEngine->functor("ai_stalker.update_best_weapon", funct))
+ {
+ CGameObject* cur_itm = smart_cast(m_best_item_to_kill);
+ CScriptGameObject* GO = funct(lua_game_object(),cur_itm ? cur_itm->lua_game_object() : nullptr);
+ CInventoryItem* bw = GO ? smart_cast(&GO->object()): nullptr;
+ if (bw)
+ {
+ m_best_item_to_kill = bw;
+ m_best_ammo = bw;
+ return;
+ }
+ }
+
ai().ef_storage().alife_evaluation(false);
+ /* Alundaio: This is what causes stalkers to switch weapons during combat; It's stupid
if (m_item_actuality && m_best_item_to_kill && m_best_item_to_kill->can_kill())
{
if (!memory().enemy().selected())
@@ -419,6 +443,7 @@ void CAI_Stalker::update_best_item_info_impl()
if (fsimilar(value, m_best_item_value))
return;
}
+ */
// initialize parameters
m_item_actuality = true;
diff --git a/src/xrGame/ai_debug.h b/src/xrGame/ai_debug.h
index 5e29378f905..6d76a14e1ca 100644
--- a/src/xrGame/ai_debug.h
+++ b/src/xrGame/ai_debug.h
@@ -14,7 +14,6 @@
#define aiMotion (1 << 2)
#define aiFrustum (1 << 3)
#define aiFuncs (1 << 4)
-#define aiALife (1 << 5)
#define aiGOAP (1 << 7)
#define aiCover (1 << 8)
#define aiAnimation (1 << 9)
@@ -40,6 +39,7 @@
#endif // DEBUG
#if defined(DEBUG) || !defined(MASTER_GOLD)
+#define aiALife (1 << 5)
#define aiIgnoreActor (1 << 24)
#define aiObstaclesAvoiding (1 << 28)
#define aiObstaclesAvoidingStatic (1 << 29)
diff --git a/src/xrGame/alife_dynamic_object.cpp b/src/xrGame/alife_dynamic_object.cpp
index 01e4bdea3d4..24ee197fba0 100644
--- a/src/xrGame/alife_dynamic_object.cpp
+++ b/src/xrGame/alife_dynamic_object.cpp
@@ -41,7 +41,14 @@ void CSE_ALifeDynamicObject::on_before_register() {}
#include "Level.h"
#include "map_manager.h"
-void CSE_ALifeDynamicObject::on_unregister() { Level().MapManager().OnObjectDestroyNotify(ID); }
+void CSE_ALifeDynamicObject::on_unregister()
+{
+ luabind::functor funct;
+ if (GEnv.ScriptEngine->functor("_G.CSE_ALifeDynamicObject_on_unregister", funct))
+ funct(ID);
+ Level().MapManager().OnObjectDestroyNotify(ID);
+}
+
void CSE_ALifeDynamicObject::switch_online()
{
R_ASSERT(!m_bOnline);
diff --git a/src/xrGame/alife_object.cpp b/src/xrGame/alife_object.cpp
index d16dd09c8f5..080ce80d135 100644
--- a/src/xrGame/alife_object.cpp
+++ b/src/xrGame/alife_object.cpp
@@ -32,14 +32,15 @@ void CSE_ALifeObject::spawn_supplies(LPCSTR ini_string)
// No need to spawn ammo, this will automatically spawn 1 box for weapon and if ammo_type is specified it will spawn that type
// count is used only for ammo boxes (ie wpn_pm = 3) will spawn 3 boxes, not 3 wpn_pm
// Usage: to create random weapon loadouts
- if (ini.section_exist("spawn_loadout"))
+ static constexpr cpcstr LOADOUT_SECTION = "spawn_loadout";
+ if (ini.section_exist(LOADOUT_SECTION))
{
pcstr itmSection, V;
xr_vector OnlyOne;
- pcstr lname = *ai().game_graph().header().level(ai().game_graph().vertex(m_tGraphID)->level_id()).name();
+ pcstr lname = ai().game_graph().header().level(ai().game_graph().vertex(m_tGraphID)->level_id()).name().c_str();
- for (u32 k = 0; ini.r_line("spawn_loadout", k, &itmSection, &V); k++)
+ for (u32 k = 0; ini.r_line(LOADOUT_SECTION, k, &itmSection, &V); k++)
{
// If level= then only spawn items if object on that level
if (strstr(V, "level=") != nullptr)
@@ -56,7 +57,7 @@ void CSE_ALifeObject::spawn_supplies(LPCSTR ini_string)
if (!OnlyOne.empty())
{
s32 sel = Random.randI(0, OnlyOne.size());
- if (ini.r_line("spawn_loadout", OnlyOne.at(sel), &itmSection, &V))
+ if (ini.r_line(LOADOUT_SECTION, OnlyOne.at(sel), &itmSection, &V))
{
VERIFY(xr_strlen(itmSection));
if (pSettings->section_exist(itmSection))
@@ -116,8 +117,7 @@ void CSE_ALifeObject::spawn_supplies(LPCSTR ini_string)
alife().spawn_item(ammoSec, o_Position, m_tNodeID, m_tGraphID, ID);
}
}
- CSE_ALifeInventoryItem* IItem = smart_cast(E);
- if (IItem)
+ if (const auto IItem = smart_cast(E))
IItem->m_fCondition = f_cond;
}
}
diff --git a/src/xrGame/alife_simulator_script.cpp b/src/xrGame/alife_simulator_script.cpp
index 2fdb5de572d..4076474e732 100644
--- a/src/xrGame/alife_simulator_script.cpp
+++ b/src/xrGame/alife_simulator_script.cpp
@@ -30,16 +30,22 @@ STORY_PAIRS story_ids;
SPAWN_STORY_PAIRS spawn_story_ids;
CALifeSimulator* alife() { return (const_cast(ai().get_alife())); }
-CSE_ALifeDynamicObject* alife_object(const CALifeSimulator* self, ALife::_OBJECT_ID object_id)
+
+bool valid_object_id(const CALifeSimulator* self, ALife::_OBJECT_ID object_id)
{
VERIFY(self);
- return (self->objects().object(object_id, true));
+ return (object_id != 0xffff);
}
-bool valid_object_id(const CALifeSimulator* self, ALife::_OBJECT_ID object_id)
+CSE_ALifeDynamicObject* alife_object(const CALifeSimulator* self, ALife::_OBJECT_ID object_id)
{
VERIFY(self);
- return (object_id != 0xffff);
+ if (!valid_object_id(self, object_id))
+ {
+ Log("! alife():object(id): invalid id specified");
+ return nullptr;
+ }
+ return (self->objects().object(object_id, true));
}
CSE_ALifeDynamicObject* alife_object(const CALifeSimulator* self, pcstr name)
@@ -184,6 +190,32 @@ CSE_Abstract* CALifeSimulator__spawn_item2(CALifeSimulator* self, LPCSTR section
return (self->server().Process_spawn(packet, clientID));
}
+//Alundaio: Allows to call alife():register(se_obj) manually afterward so that packet editing can be done safely when spawning object with a parent
+CSE_Abstract* CALifeSimulator__spawn_item3(CALifeSimulator* self, pcstr section, const Fvector& position,
+ u32 level_vertex_id, GameGraph::_GRAPH_ID game_vertex_id,
+ ALife::_OBJECT_ID id_parent, bool reg = true)
+{
+ if (reg)
+ return CALifeSimulator__spawn_item2(self, section, position, level_vertex_id, game_vertex_id, id_parent);
+
+ if (id_parent == ALife::_OBJECT_ID(-1))
+ return (self->spawn_item(section, position, level_vertex_id, game_vertex_id, id_parent));
+
+ const auto object = ai().alife().objects().object(id_parent, true);
+ if (!object)
+ {
+ Msg("! invalid parent id [%d] specified", id_parent);
+ return nullptr;
+ }
+
+ if (!object->m_bOnline)
+ return (self->spawn_item(section, position, level_vertex_id, game_vertex_id, id_parent));
+
+ CSE_Abstract* item = self->spawn_item(section, position, level_vertex_id, game_vertex_id, id_parent, false);
+
+ return item;
+}
+
CSE_Abstract* CALifeSimulator__spawn_ammo(CALifeSimulator* self, LPCSTR section, const Fvector& position,
u32 level_vertex_id, GameGraph::_GRAPH_ID game_vertex_id, ALife::_OBJECT_ID id_parent, int ammo_to_spawn)
{
@@ -309,17 +341,15 @@ void teleport_object(CALifeSimulator* alife, ALife::_OBJECT_ID id, GameGraph::_G
{
alife->teleport_object(id, game_vertex_id, level_vertex_id, position);
}
-//-Alundaio
-void iterate_objects(const CALifeSimulator* self, luabind::functor functor)
+void IterateInfo(const CALifeSimulator* alife, const ALife::_OBJECT_ID& id, const luabind::functor& functor)
{
- THROW(self);
- for (const auto& it : self->objects().objects())
- {
- CSE_ALifeDynamicObject* obj = it.second;
- if (functor(obj))
- return;
- }
+ const auto known_info = registry(alife, id);
+ if (!known_info)
+ return;
+
+ for (const auto& it : *known_info)
+ functor(id, it.info_id);
}
CSE_Abstract* reprocess_spawn(CALifeSimulator* self, CSE_Abstract* object)
@@ -340,6 +370,7 @@ CSE_Abstract* reprocess_spawn(CALifeSimulator* self, CSE_Abstract* object)
return self->server().Process_spawn(packet, clientID);
}
+
CSE_Abstract* try_to_clone_object(CALifeSimulator* self, CSE_Abstract* object, pcstr section, const Fvector& position,
u32 level_vertex_id, GameGraph::_GRAPH_ID game_vertex_id, ALife::_OBJECT_ID id_parent,
bool bRegister = true)
@@ -387,15 +418,17 @@ xr_vector& get_children(const CALifeSimulator* self, CSE_Abstract* object)
VERIFY(self);
return object->children;
}
+//-Alundaio
-void IterateInfo(const CALifeSimulator* alife, const ALife::_OBJECT_ID& id, const luabind::functor& functor)
+void iterate_objects(const CALifeSimulator* self, luabind::functor functor)
{
- const auto known_info = registry(alife, id);
- if (!known_info)
- return;
-
- for (const auto& it : *known_info)
- functor(id, it.info_id);
+ THROW(self);
+ for (const auto& it : self->objects().objects())
+ {
+ CSE_ALifeDynamicObject* obj = it.second;
+ if (functor(obj))
+ return;
+ }
}
void set_start_position(Fvector& pos)
@@ -443,6 +476,7 @@ SCRIPT_EXPORT(CALifeSimulator, (),
.def("create", &CALifeSimulator__create)
.def("create", &CALifeSimulator__spawn_item2)
.def("create", &CALifeSimulator__spawn_item)
+ .def("create", &CALifeSimulator__spawn_item3)
.def("create_ammo", &CALifeSimulator__spawn_ammo)
.def("release", &CALifeSimulator__release)
.def("spawn_id", &CALifeSimulator__spawn_id)
@@ -456,7 +490,6 @@ SCRIPT_EXPORT(CALifeSimulator, (),
(&CALifeSimulator::set_switch_distance)) //Alundaio: renamed to set_switch_distance from switch_distance
//Alundaio: extend alife simulator exports
.def("teleport_object", &teleport_object)
- //Alundaio: END
.def("iterate_objects", &iterate_objects)
.def("iterate_info", &IterateInfo)
.def("clone_weapon", (CSE_Abstract* (*)(CALifeSimulator*, CSE_Abstract*, pcstr, const Fvector&, u32,
@@ -467,6 +500,7 @@ SCRIPT_EXPORT(CALifeSimulator, (),
.def("set_objects_per_update", &set_objects_per_update)
.def("set_process_time", &set_process_time)
.def("get_children", &get_children, return_stl_iterator()),
+ //Alundaio: END
def("alife", &alife),
def("set_start_position", &set_start_position),
diff --git a/src/xrGame/alife_storage_manager.cpp b/src/xrGame/alife_storage_manager.cpp
index 0c10232c4ef..a04a41d5083 100644
--- a/src/xrGame/alife_storage_manager.cpp
+++ b/src/xrGame/alife_storage_manager.cpp
@@ -55,6 +55,12 @@ void CALifeStorageManager::save(LPCSTR save_name_no_check, bool update_name)
}
}
+ //Alundaio: To get the savegame fname to make our own custom save states
+ luabind::functor funct1;
+ if (GEnv.ScriptEngine->functor("alife_storage_manager.CALifeStorageManager_before_save", funct1))
+ funct1((pcstr)m_save_name);
+ //-Alundaio
+
u32 source_count;
u32 dest_count;
void* dest_data;
@@ -90,12 +96,24 @@ void CALifeStorageManager::save(LPCSTR save_name_no_check, bool update_name)
Msg("* Game %s is successfully saved to file '%s'", m_save_name, temp);
#endif // DEBUG
+ //Alundaio: To get the savegame fname to make our own custom save states
+ luabind::functor funct2;
+ if (GEnv.ScriptEngine->functor("alife_storage_manager.CALifeStorageManager_save", funct2))
+ funct2((pcstr)m_save_name);
+ //-Alundaio
+
if (!update_name)
xr_strcpy(m_save_name, saveBackup);
}
void CALifeStorageManager::load(void* buffer, const u32& buffer_size, LPCSTR file_name)
{
+ //Alundaio: So we can get the fname to make our own custom save states
+ luabind::functor funct;
+ if (GEnv.ScriptEngine->functor("alife_storage_manager.CALifeStorageManager_load", funct))
+ funct(file_name);
+ //-Alundaio
+
IReader source(buffer, buffer_size);
header().load(source);
time_manager().load(source);
diff --git a/src/xrGame/alife_switch_manager.cpp b/src/xrGame/alife_switch_manager.cpp
index 1a24ecfb295..6837e602eb5 100644
--- a/src/xrGame/alife_switch_manager.cpp
+++ b/src/xrGame/alife_switch_manager.cpp
@@ -61,10 +61,11 @@ void CALifeSwitchManager::add_online(CSE_ALifeDynamicObject* object, bool update
server().Process_spawn(tNetPacket, clientID, FALSE, l_tpAbstract);
object->s_flags._and (u16(-1) ^ M_SPAWN_UPDATE);
- R_ASSERT3(!object->used_ai_locations() || ai().level_graph().valid_vertex_id(object->m_tNodeID),
- "Invalid vertex for object ", object->name_replace());
+ //Alundaio: Workaround for crash with corpses that end up outside AI map
+ //R_ASSERT3(!object->used_ai_locations() || ai().level_graph().valid_vertex_id(object->m_tNodeID),
+ // "Invalid vertex for object ", object->name_replace());
-#ifdef DEBUG
+#ifndef MASTER_GOLD
if (psAI_Flags.test(aiALife))
Msg("[LSS] Spawning object [%s][%s][%d]", object->name_replace(), *object->s_name, object->ID);
#endif
diff --git a/src/xrGame/alife_update_manager.cpp b/src/xrGame/alife_update_manager.cpp
index 339bbfeb8f8..a4552ae2be2 100644
--- a/src/xrGame/alife_update_manager.cpp
+++ b/src/xrGame/alife_update_manager.cpp
@@ -136,6 +136,10 @@ bool CALifeUpdateManager::change_level(NET_Packet& net_packet)
if (m_changing_level)
return (false);
+ luabind::functor funct;
+ if (GEnv.ScriptEngine->functor("_G.CALifeUpdateManager__on_before_change_level", funct))
+ funct(&net_packet);
+
// prepare_objects_for_save ();
// we couldn't use prepare_objects_for_save since we need
// get updates from client
diff --git a/src/xrGame/console_commands.cpp b/src/xrGame/console_commands.cpp
index 680dd543bbe..44570706fad 100644
--- a/src/xrGame/console_commands.cpp
+++ b/src/xrGame/console_commands.cpp
@@ -2205,6 +2205,7 @@ void CCC_RegisterCommands()
CMD3(CCC_Mask, "g_important_save", &psActorFlags, AF_IMPORTANT_SAVE);
CMD3(CCC_Mask, "g_loading_stages", &psActorFlags, AF_LOADING_STAGES);
CMD3(CCC_Mask, "g_always_use_attitude_sensors", &psActorFlags, AF_ALWAYS_USE_ATTITUDE_SENSORS);
+ CMD3(CCC_Mask, "g_use_tracers", &psActorFlags, AF_USE_TRACERS);
CMD4(CCC_Integer, "g_inv_highlight_equipped", &g_inv_highlight_equipped, 0, 1);
CMD4(CCC_Integer, "g_first_person_death", &g_first_person_death, 0, 1);
diff --git a/src/xrGame/encyclopedia_article.cpp b/src/xrGame/encyclopedia_article.cpp
index 46cd73907e9..c631216ce51 100644
--- a/src/xrGame/encyclopedia_article.cpp
+++ b/src/xrGame/encyclopedia_article.cpp
@@ -145,5 +145,5 @@ void CEncyclopediaArticle::InitXmlIdToIndex()
if (!id_to_index::tag_name)
id_to_index::tag_name = "article";
if (!id_to_index::file_str)
- id_to_index::file_str = pSettings->r_string("encyclopedia", "files");
+ id_to_index::file_str = pSettings->read_if_exists("encyclopedia", "files", "");
}
diff --git a/src/xrGame/game_object_space.h b/src/xrGame/game_object_space.h
index 7e31cd11226..0419aee13d0 100644
--- a/src/xrGame/game_object_space.h
+++ b/src/xrGame/game_object_space.h
@@ -54,6 +54,9 @@ enum ECallbackType : u32
eInvBoxItemTake,
eWeaponNoAmmoAvailable,
+ //Alundaio: added defines
+ eActorHudAnimationEnd,
+
//AVO: custom callbacks
// Input
eKeyPress,
@@ -69,19 +72,18 @@ enum ECallbackType : u32
eItemToBelt,
eItemToSlot,
eItemToRuck,
+ // weapon
+ eOnWeaponZoomIn,
+ eOnWeaponZoomOut,
+ eOnWeaponJammed,
+ eOnWeaponMagazineEmpty,
// Actor
eActorBeforeDeath,
- //-AVO
-
// vehicle
eAttachVehicle,
eDetachVehicle,
eUseVehicle,
-
- // weapon
- eOnWeaponZoomIn,
- eOnWeaponZoomOut,
- eOnWeaponJammed,
+ //-AVO
eDummy = u32(-1),
};
diff --git a/src/xrGame/holder_custom.h b/src/xrGame/holder_custom.h
index 01ee9449ee4..17022f62873 100644
--- a/src/xrGame/holder_custom.h
+++ b/src/xrGame/holder_custom.h
@@ -14,6 +14,14 @@ class CHolderCustom
protected:
CGameObject* Owner() { return m_owner; }
CActor* OwnerActor() { return m_ownerActor; }
+
+protected:
+ bool m_bEnterLocked{};
+ bool m_bExitLocked{};
+
+public:
+ shared_str m_sUseAction;
+
public:
CHolderCustom()
{
@@ -42,6 +50,10 @@ class CHolderCustom
virtual void cam_Update(float dt, float fov = 90.0f) = 0;
+ bool EnterLocked() const { return m_bEnterLocked; }
+ bool ExitLocked() const { return m_bExitLocked; }
+ void SetEnterLocked(bool v) { m_bEnterLocked = v; }
+ void SetExitLocked(bool v) { m_bExitLocked = v; }
virtual bool Use(const Fvector& pos, const Fvector& dir, const Fvector& foot_pos) = 0;
virtual bool attach_Actor(CGameObject* actor);
virtual void detach_Actor();
diff --git a/src/xrGame/holder_custom_script.cpp b/src/xrGame/holder_custom_script.cpp
index 7f4908289a0..b76564cfcac 100644
--- a/src/xrGame/holder_custom_script.cpp
+++ b/src/xrGame/holder_custom_script.cpp
@@ -11,8 +11,9 @@ SCRIPT_EXPORT(CHolderCustom, (),
class_("holder")
.def("engaged", &CHolderCustom::Engaged)
.def("Action", &CHolderCustom::Action)
- // .def("SetParam", (void (CHolderCustom::*)(int,Fvector2))
- //&CHolderCustom::SetParam)
+ // .def("SetParam", (void (CHolderCustom::*)(int,Fvector2))&CHolderCustom::SetParam)
.def("SetParam", (void (CHolderCustom::*)(int, Fvector)) & CHolderCustom::SetParam)
+ .def("SetEnterLocked", &CHolderCustom::SetEnterLocked)
+ .def("SetExitLocked", &CHolderCustom::SetExitLocked)
];
});
diff --git a/src/xrGame/inventory_item.cpp b/src/xrGame/inventory_item.cpp
index b8548a4ac83..a2ebae0de28 100644
--- a/src/xrGame/inventory_item.cpp
+++ b/src/xrGame/inventory_item.cpp
@@ -119,6 +119,8 @@ void CInventoryItem::Load(LPCSTR section)
// Added by Axel, to enable optional condition use on any item
m_flags.set(FUsingCondition, READ_IF_EXISTS(pSettings, r_bool, section, "use_condition", false));
+ m_highlight_equipped = READ_IF_EXISTS(pSettings, r_bool, section, "highlight_equipped", false);
+
if (BaseSlot() != NO_ACTIVE_SLOT || Belt())
{
m_flags.set(FRuckDefault, pSettings->read_if_exists(section, "default_to_ruck", true));
diff --git a/src/xrGame/inventory_item.h b/src/xrGame/inventory_item.h
index 496a810a482..be5a755b0eb 100644
--- a/src/xrGame/inventory_item.h
+++ b/src/xrGame/inventory_item.h
@@ -154,6 +154,7 @@ class CInventoryItem : public CAttachableItem,
shared_str m_name;
shared_str m_nameShort;
shared_str m_nameComplex;
+ bool m_highlight_equipped;
SInvItemPlace m_ItemCurrPlace;
@@ -288,9 +289,7 @@ class CInventoryItem : public CAttachableItem,
bool has_upgrade_group_by_upgrade_id(const shared_str& upgrade_id);
void add_upgrade(const shared_str& upgrade_id, bool loading);
bool get_upgrades_str(string2048& res) const;
-#ifdef GAME_OBJECT_EXTENDED_EXPORTS
Upgrades_type get_upgrades() { return m_upgrades; } //Alundaio
-#endif
bool equal_upgrades(Upgrades_type const& other_upgrades) const;
diff --git a/src/xrGame/inventory_upgrade.h b/src/xrGame/inventory_upgrade.h
index d47a730702b..2b0a3316988 100644
--- a/src/xrGame/inventory_upgrade.h
+++ b/src/xrGame/inventory_upgrade.h
@@ -74,7 +74,7 @@ struct functor3 : public functor2
enum EMaxProps
{
- max_properties_count = 3,
+ max_properties_count = 4,
};
class Upgrade : public UpgradeBase
diff --git a/src/xrGame/level_script.cpp b/src/xrGame/level_script.cpp
index bda80dcc7cc..62711bf91e8 100644
--- a/src/xrGame/level_script.cpp
+++ b/src/xrGame/level_script.cpp
@@ -739,14 +739,13 @@ IC static void CLevel_Export(lua_State* luaState)
[
//Alundaio: Extend level namespace exports
def("send", &g_send) , //allow the ability to send netpacket to level
- //def("ray_pick",g_ray_pick),
def("get_target_obj", &g_get_target_obj), //intentionally named to what is in xray extensions
def("get_target_dist", &g_get_target_dist),
def("get_target_element", &g_get_target_element), //Can get bone cursor is targeting
def("spawn_item", &spawn_section),
def("get_active_cam", &get_active_cam),
def("set_active_cam", &set_active_cam),
- def("get_start_time", +[]() { return xrTime(Level().GetStartGameTime()); }),
+ def("get_start_time", +[]() -> xrTime { return xrTime(Level().GetStartGameTime()); }),
def("valid_vertex", +[](u32 level_vertex_id)
{
return ai().level_graph().valid_vertex_id(level_vertex_id);
@@ -863,34 +862,34 @@ IC static void CLevel_Export(lua_State* luaState)
module(luaState)
[
class_("ray_pick")
- .def(constructor<>())
- .def(constructor())
- .def("set_position", &CRayPick::set_position)
- .def("set_direction", &CRayPick::set_direction)
- .def("set_range", &CRayPick::set_range)
- .def("set_flags", &CRayPick::set_flags)
- .def("set_ignore_object", &CRayPick::set_ignore_object)
- .def("query", &CRayPick::query)
- .def("get_result", &CRayPick::get_result)
- .def("get_object", &CRayPick::get_object)
- .def("get_distance", &CRayPick::get_distance)
- .def("get_element", &CRayPick::get_element),
+ .def(constructor<>())
+ .def(constructor())
+ .def("set_position", &CRayPick::set_position)
+ .def("set_direction", &CRayPick::set_direction)
+ .def("set_range", &CRayPick::set_range)
+ .def("set_flags", &CRayPick::set_flags)
+ .def("set_ignore_object", &CRayPick::set_ignore_object)
+ .def("query", &CRayPick::query)
+ .def("get_result", &CRayPick::get_result)
+ .def("get_object", &CRayPick::get_object)
+ .def("get_distance", &CRayPick::get_distance)
+ .def("get_element", &CRayPick::get_element),
class_("rq_result")
- .def_readonly("object", &script_rq_result::O)
- .def_readonly("range", &script_rq_result::range)
- .def_readonly("element", &script_rq_result::element)
- .def(constructor<>()),
+ .def_readonly("object", &script_rq_result::O)
+ .def_readonly("range", &script_rq_result::range)
+ .def_readonly("element", &script_rq_result::element)
+ .def(constructor<>()),
class_>("rq_target")
- .enum_("targets")
- [
- value("rqtNone", int(collide::rqtNone)),
- value("rqtObject", int(collide::rqtObject)),
- value("rqtStatic", int(collide::rqtStatic)),
- value("rqtShape", int(collide::rqtShape)),
- value("rqtObstacle", int(collide::rqtObstacle)),
- value("rqtBoth", int(collide::rqtBoth)),
- value("rqtDyn", int(collide::rqtDyn))
- ]
+ .enum_("targets")
+ [
+ value("rqtNone", int(collide::rqtNone)),
+ value("rqtObject", int(collide::rqtObject)),
+ value("rqtStatic", int(collide::rqtStatic)),
+ value("rqtShape", int(collide::rqtShape)),
+ value("rqtObstacle", int(collide::rqtObstacle)),
+ value("rqtBoth", int(collide::rqtBoth)),
+ value("rqtDyn", int(collide::rqtDyn))
+ ]
];
module(luaState)
diff --git a/src/xrGame/property_evaluator.h b/src/xrGame/property_evaluator.h
index 314c9474a3a..d69f2d25304 100644
--- a/src/xrGame/property_evaluator.h
+++ b/src/xrGame/property_evaluator.h
@@ -24,7 +24,7 @@ class CPropertyEvaluator
_object_type* m_object;
CPropertyStorage* m_storage;
#if 1//def LOG_ACTION //Alundaio: m_evaluator_name
- LPCSTR m_evaluator_name;
+ pcstr m_evaluator_name;
#endif
public:
diff --git a/src/xrGame/property_evaluator_script.cpp b/src/xrGame/property_evaluator_script.cpp
index bf031b83274..19a0d862d8a 100644
--- a/src/xrGame/property_evaluator_script.cpp
+++ b/src/xrGame/property_evaluator_script.cpp
@@ -21,7 +21,7 @@ SCRIPT_EXPORT(CScriptPropertyEvaluator, (),
class_("property_evaluator")
- .def_readonly("object", &CScriptPropertyEvaluator::m_object)
+ .def_readwrite("object", &CScriptPropertyEvaluator::m_object)
.def_readonly("storage", &CScriptPropertyEvaluator::m_storage)
.def(constructor<>())
.def(constructor())
diff --git a/src/xrGame/purchase_list.cpp b/src/xrGame/purchase_list.cpp
index 93630048020..cce4ab77cd0 100644
--- a/src/xrGame/purchase_list.cpp
+++ b/src/xrGame/purchase_list.cpp
@@ -27,12 +27,21 @@ void CPurchaseList::process(CInifile& ini_file, LPCSTR section, CInventoryOwner&
auto E = S.Data.cend();
for (; I != E; ++I)
{
- VERIFY3((*I).second.size(), "PurchaseList : cannot handle lines in section without values", section);
+ if (I->second.empty())
+ continue;
+
+ if (!pSettings->section_exist(I->first))
+ continue;
+
+ //VERIFY3(I->second.size(), "PurchaseList : cannot handle lines in section without values", section);
string256 temp0, temp1;
- THROW3(_GetItemCount(*(*I).second) == 2, "Invalid parameters in section", section);
- process(game_object, (*I).first, atoi(_GetItem(*(*I).second, 0, temp0)),
- (float)atof(_GetItem(*(*I).second, 1, temp1)));
+ //THROW3(_GetItemCount(I->second.c_str()) == 2, "Invalid parameters in section", section);
+
+ cpcstr count = _GetItem(I->second.c_str(), 0, temp0);
+ cpcstr prob = _GetItemCount(I->second.c_str()) >= 2 ? _GetItem(I->second.c_str(), 1, temp1) : "1.0f";
+
+ process(game_object, I->first, atoi(count), (float)atof(prob));
}
}
diff --git a/src/xrGame/script_binder_object_script.cpp b/src/xrGame/script_binder_object_script.cpp
index 5dd2ef3568d..d2970edfc8c 100644
--- a/src/xrGame/script_binder_object_script.cpp
+++ b/src/xrGame/script_binder_object_script.cpp
@@ -19,7 +19,7 @@ SCRIPT_EXPORT(CScriptBinderObject, (),
module(luaState)
[
class_("object_binder")
- .def_readonly("object", &CScriptBinderObject::m_object)
+ .def_readwrite("object", &CScriptBinderObject::m_object)
.def(constructor())
.def("reinit", &CScriptBinderObject::reinit, &CScriptBinderObjectWrapper::reinit_static)
.def("reload", &CScriptBinderObject::reload, &CScriptBinderObjectWrapper::reload_static)
diff --git a/src/xrGame/script_game_object.cpp b/src/xrGame/script_game_object.cpp
index 4a667c27c02..b687cbd0073 100644
--- a/src/xrGame/script_game_object.cpp
+++ b/src/xrGame/script_game_object.cpp
@@ -348,7 +348,8 @@ void CScriptGameObject::SetAmmoElapsed(int ammo_elapsed)
int CScriptGameObject::GetAmmoCount(u8 type)
{
CWeapon* weapon = smart_cast(&object());
- if (!weapon) return 0;
+ if (!weapon)
+ return 0;
if (type < weapon->m_ammoTypes.size())
return weapon->GetAmmoCount_forType(weapon->m_ammoTypes[type]);
@@ -359,7 +360,8 @@ int CScriptGameObject::GetAmmoCount(u8 type)
void CScriptGameObject::SetAmmoType(u8 type)
{
CWeapon* weapon = smart_cast(&object());
- if (!weapon) return;
+ if (!weapon)
+ return;
weapon->SetAmmoType(type);
}
@@ -367,7 +369,8 @@ void CScriptGameObject::SetAmmoType(u8 type)
u8 CScriptGameObject::GetAmmoType()
{
CWeapon* weapon = smart_cast(&object());
- if (!weapon) return 255;
+ if (!weapon)
+ return 255;
return weapon->GetAmmoType();
}
@@ -375,7 +378,8 @@ u8 CScriptGameObject::GetAmmoType()
void CScriptGameObject::SetMainWeaponType(u32 type)
{
CWeapon* weapon = smart_cast(&object());
- if (!weapon) return;
+ if (!weapon)
+ return;
weapon->set_ef_main_weapon_type(type);
}
@@ -383,7 +387,8 @@ void CScriptGameObject::SetMainWeaponType(u32 type)
void CScriptGameObject::SetWeaponType(u32 type)
{
CWeapon* weapon = smart_cast(&object());
- if (!weapon) return;
+ if (!weapon)
+ return;
weapon->set_ef_weapon_type(type);
}
@@ -391,7 +396,8 @@ void CScriptGameObject::SetWeaponType(u32 type)
u32 CScriptGameObject::GetMainWeaponType()
{
CWeapon* weapon = smart_cast(&object());
- if (!weapon) return 255;
+ if (!weapon)
+ return 255;
return weapon->ef_main_weapon_type();
}
@@ -399,7 +405,8 @@ u32 CScriptGameObject::GetMainWeaponType()
u32 CScriptGameObject::GetWeaponType()
{
CWeapon* weapon = smart_cast(&object());
- if (!weapon) return 255;
+ if (!weapon)
+ return 255;
return weapon->ef_weapon_type();
}
@@ -407,7 +414,8 @@ u32 CScriptGameObject::GetWeaponType()
bool CScriptGameObject::HasAmmoType(u8 type)
{
CWeapon* weapon = smart_cast(&object());
- if (!weapon) return false;
+ if (!weapon)
+ return false;
return type < weapon->m_ammoTypes.size();
}
@@ -415,7 +423,8 @@ bool CScriptGameObject::HasAmmoType(u8 type)
u8 CScriptGameObject::GetWeaponSubstate()
{
CWeapon* weapon = smart_cast(&object());
- if (!weapon) return 255;
+ if (!weapon)
+ return 255;
return weapon->m_sub_state;
}
@@ -676,9 +685,6 @@ pcstr CScriptGameObject::get_smart_cover_description() const
return smart_cover_object->get_cover().get_description()->table_id().c_str();
}
-void CScriptGameObject::set_visual_name(LPCSTR visual) { object().cNameVisual_set(visual); }
-LPCSTR CScriptGameObject::get_visual_name() const { return object().cNameVisual().c_str(); }
-
void CScriptGameObject::PhantomSetEnemy(CScriptGameObject* enemy)
{
CPhantom* phant = smart_cast(&object());
@@ -688,7 +694,7 @@ void CScriptGameObject::PhantomSetEnemy(CScriptGameObject* enemy)
phant->SetEnemy(&enemy->object());
}
-//Allows to force use an object if passed obj is the actor
+// Allows to force use an object if passed obj is the actor
bool CScriptGameObject::Use(CScriptGameObject* obj)
{
bool ret = object().use(&obj->object());
@@ -697,30 +703,24 @@ bool CScriptGameObject::Use(CScriptGameObject* obj)
if (!actor)
return ret;
- CInventoryOwner* pActorInv = smart_cast(actor);
- if (!pActorInv)
- return ret;
-
CUIActorMenu& ActorMenu = CurrentGameUI()->GetActorMenu();
- CInventoryBox* pBox = smart_cast(&object());
- if (pBox)
+ if (const auto box = smart_cast(&object()))
{
- ActorMenu.SetActor(pActorInv);
- ActorMenu.SetInvBox(pBox);
+ ActorMenu.SetActor(actor);
+ ActorMenu.SetInvBox(box);
ActorMenu.SetMenuMode(mmDeadBodySearch);
ActorMenu.ShowDialog(true);
return true;
}
- else
- {
- CInventoryOwner* pOtherOwner = smart_cast(&object());
- if (!pOtherOwner)
- return ret;
- /*
+ CInventoryOwner* pOtherOwner = smart_cast(&object());
+ if (!pOtherOwner)
+ return ret;
+
+ /*
CEntityAlive* e = smart_cast(pOtherOwner);
if (e && e->g_Alive())
{
@@ -729,16 +729,13 @@ bool CScriptGameObject::Use(CScriptGameObject* obj)
}
*/
- ActorMenu.SetActor(pActorInv);
- ActorMenu.SetPartner(pOtherOwner);
-
- ActorMenu.SetMenuMode(mmDeadBodySearch);
- ActorMenu.ShowDialog(true);
+ ActorMenu.SetActor(actor);
+ ActorMenu.SetPartner(pOtherOwner);
- return true;
- }
+ ActorMenu.SetMenuMode(mmDeadBodySearch);
+ ActorMenu.ShowDialog(true);
- return false;
+ return true;
}
void CScriptGameObject::StartTrade(CScriptGameObject* obj)
@@ -747,17 +744,13 @@ void CScriptGameObject::StartTrade(CScriptGameObject* obj)
if (!actor)
return;
- CInventoryOwner* pActorInv = smart_cast(actor);
- if (!pActorInv)
- return;
-
CInventoryOwner* pOtherOwner = smart_cast(&object());
if (!pOtherOwner)
return;
CUIActorMenu& ActorMenu = CurrentGameUI()->GetActorMenu();
- ActorMenu.SetActor(pActorInv);
+ ActorMenu.SetActor(actor);
ActorMenu.SetPartner(pOtherOwner);
ActorMenu.SetMenuMode(mmTrade);
@@ -770,17 +763,13 @@ void CScriptGameObject::StartUpgrade(CScriptGameObject* obj)
if (!actor)
return;
- CInventoryOwner* pActorInv = smart_cast(actor);
- if (!pActorInv)
- return;
-
CInventoryOwner* pOtherOwner = smart_cast(&object());
if (!pOtherOwner)
return;
CUIActorMenu& ActorMenu = CurrentGameUI()->GetActorMenu();
- ActorMenu.SetActor(pActorInv);
+ ActorMenu.SetActor(actor);
ActorMenu.SetPartner(pOtherOwner);
ActorMenu.SetMenuMode(mmUpgrade);
diff --git a/src/xrGame/script_game_object.h b/src/xrGame/script_game_object.h
index eb9da6b8eb5..761a9af6cc4 100644
--- a/src/xrGame/script_game_object.h
+++ b/src/xrGame/script_game_object.h
@@ -191,11 +191,7 @@ class CScriptGameObject
_DECLARE_FUNCTION10(Squad, int);
_DECLARE_FUNCTION10(Group, int);
- // XXX: this is a workaround, since luabind can't determine default function arguments...
- // There is more places, not only this one
- // Look here: https://github.com/qweasdd136963/OXR_CoC/commit/c37d8f4e49c92fe226a5958954cc9a6a1ab18c93
- void Kill(CScriptGameObject* who) { Kill(who, false); }
- void Kill(CScriptGameObject* who, bool bypass_actor_check /*= false*/ /*AVO: added for actor before death callback*/);
+ void Kill(CScriptGameObject* who, bool bypass_actor_check = false);
// CEntityAlive
_DECLARE_FUNCTION10(GetFOV, float);
@@ -359,8 +355,8 @@ class CScriptGameObject
bool IsInvUpgradeEnabled();
void ActorLookAtPoint(Fvector point);
- void IterateInventory(luabind::functor functor, luabind::adl::object object);
- void IterateInventoryBox(luabind::functor functor, luabind::adl::object object);
+ void IterateInventory(luabind::functor functor, luabind::adl::object object);
+ void IterateInventoryBox(luabind::functor functor, luabind::adl::object object);
void MarkItemDropped(CScriptGameObject* item);
bool MarkedDropped(CScriptGameObject* item);
void UnloadMagazine();
@@ -421,6 +417,7 @@ class CScriptGameObject
void SetCharacterRank(int);
void ChangeCharacterRank(int);
void ChangeCharacterReputation(int);
+ void SetCharacterReputation(int);
void SetCharacterCommunity(LPCSTR, int, int);
u32 GetInventoryObjectCount() const;
@@ -794,7 +791,45 @@ class CScriptGameObject
bool is_door_blocked_by_npc() const;
bool is_weapon_going_to_be_strapped(CScriptGameObject const* object) const;
-#ifdef GAME_OBJECT_EXTENDED_EXPORTS
+ //AVO: functions for object testing
+ //_DECLARE_FUNCTION10(IsGameObject, bool);
+ //_DECLARE_FUNCTION10(IsCar, bool);
+ //_DECLARE_FUNCTION10(IsHeli, bool);
+ //_DECLARE_FUNCTION10(IsHolderCustom, bool);
+ _DECLARE_FUNCTION10(IsEntityAlive, bool);
+ _DECLARE_FUNCTION10(IsInventoryItem, bool);
+ _DECLARE_FUNCTION10(IsInventoryOwner, bool);
+ _DECLARE_FUNCTION10(IsActor, bool);
+ _DECLARE_FUNCTION10(IsCustomMonster, bool);
+ _DECLARE_FUNCTION10(IsWeapon, bool);
+ //_DECLARE_FUNCTION10(IsMedkit, bool);
+ //_DECLARE_FUNCTION10(IsEatableItem, bool);
+ //_DECLARE_FUNCTION10(IsAntirad, bool);
+ _DECLARE_FUNCTION10(IsCustomOutfit, bool);
+ _DECLARE_FUNCTION10(IsScope, bool);
+ _DECLARE_FUNCTION10(IsSilencer, bool);
+ _DECLARE_FUNCTION10(IsGrenadeLauncher, bool);
+ _DECLARE_FUNCTION10(IsWeaponMagazined, bool);
+ _DECLARE_FUNCTION10(IsSpaceRestrictor, bool);
+ _DECLARE_FUNCTION10(IsStalker, bool);
+ _DECLARE_FUNCTION10(IsAnomaly, bool);
+ _DECLARE_FUNCTION10(IsMonster, bool);
+ //_DECLARE_FUNCTION10(IsExplosive, bool);
+ //_DECLARE_FUNCTION10(IsScriptZone, bool);
+ //_DECLARE_FUNCTION10(IsProjector, bool);
+ _DECLARE_FUNCTION10(IsTrader, bool);
+ _DECLARE_FUNCTION10(IsHudItem, bool);
+ //_DECLARE_FUNCTION10(IsFoodItem, bool);
+ _DECLARE_FUNCTION10(IsArtefact, bool);
+ _DECLARE_FUNCTION10(IsAmmo, bool);
+ //_DECLARE_FUNCTION10(IsMissile, bool);
+ //_DECLARE_FUNCTION10(IsPhysicsShellHolder, bool);
+ //_DECLARE_FUNCTION10(IsGrenade, bool);
+ //_DECLARE_FUNCTION10(IsBottleItem, bool);
+ //_DECLARE_FUNCTION10(IsTorch, bool);
+ _DECLARE_FUNCTION10(IsWeaponGL, bool);
+ _DECLARE_FUNCTION10(IsInventoryBox, bool);
+
// Alundaio
void inactualize_level_path();
void inactualize_game_path();
@@ -812,12 +847,13 @@ class CScriptGameObject
u8 GetRestrictionType();
void SetRestrictionType(u8 type);
- //CWeaponAmmo
- u16 AmmoGetCount();
- void AmmoSetCount(u16 count);
- u16 AmmoBoxSize();
+ void RemoveDanger(const CDangerObject& dobject);
+
+ void RemoveMemorySoundObject(const MemorySpace::CSoundObject& memory_object);
+ void RemoveMemoryHitObject(const MemorySpace::CHitObject& memory_object);
+ void RemoveMemoryVisibleObject(const MemorySpace::CVisibleObject& memory_object);
- //Weapon
+ // Weapon
void Weapon_AddonAttach(CScriptGameObject* item);
void Weapon_AddonDetach(pcstr item_section);
bool HasAmmoType(u8 type);
@@ -830,7 +866,12 @@ class CScriptGameObject
u8 GetWeaponSubstate();
u8 GetAmmoType();
- //Weapon & Outfit
+ // CWeaponAmmo
+ u16 AmmoGetCount();
+ void AmmoSetCount(u16 count);
+ u16 AmmoBoxSize();
+
+ // Weapon & Outfit
bool AddUpgrade(pcstr upgrade);
bool InstallUpgrade(pcstr upgrade);
bool HasUpgrade(pcstr upgrade) const;
@@ -839,11 +880,12 @@ class CScriptGameObject
bool CanAddUpgrade(pcstr upgrade) const;
bool CanInstallUpgrade(pcstr upgrade) const;
void IterateInstalledUpgrades(luabind::functor functor);
+ bool WeaponInGrenadeMode();
//Car
CScriptGameObject* GetAttachedVehicle();
- void AttachVehicle(CScriptGameObject* veh);
- void DetachVehicle();
+ void AttachVehicle(CScriptGameObject* veh, bool bForce = false);
+ void DetachVehicle(bool bForce = false);
//Any class that is derived from CHudItem
u32 PlayHudMotion(pcstr M, bool mixIn, u32 state);
@@ -854,9 +896,12 @@ class CScriptGameObject
bool IsBoneVisible(pcstr bone_name);
void SetBoneVisible(pcstr bone_name, bool bVisibility, bool bRecursive = true);
- //Anything with PPhysicShell (ie. car, actor, stalker, monster, heli)
+ // CAI_Stalker
+ void ResetBoneProtections(pcstr imm_sect, pcstr bone_sect);
+ // Anything with PPhysicShell (ie. car, actor, stalker, monster, heli)
void ForceSetPosition(Fvector pos, bool bActivate = false);
+ // Artefacts
float GetArtefactHealthRestoreSpeed();
float GetArtefactRadiationRestoreSpeed();
float GetArtefactSatietyRestoreSpeed();
@@ -869,53 +914,38 @@ class CScriptGameObject
void SetArtefactPowerRestoreSpeed(float value);
void SetArtefactBleedingRestoreSpeed(float value);
- void RemoveDanger(const CDangerObject& dobject);
-
- void RemoveMemorySoundObject(const MemorySpace::CSoundObject& memory_object);
- void RemoveMemoryHitObject(const MemorySpace::CHitObject& memory_object);
- void RemoveMemoryVisibleObject(const MemorySpace::CVisibleObject& memory_object);
-
- //CAI_Stalker
- void ResetBoneProtections(pcstr imm_sect, pcstr bone_sect);
-
- //Eatable items
+ // Eatable items
void SetRemainingUses(u8 value);
u8 GetRemainingUses();
u8 GetMaxUses();
- //Phantom
+ // Phantom
void PhantomSetEnemy(CScriptGameObject*);
- //Actor
+
+ // Actor
float GetActorMaxWeight() const;
void SetActorMaxWeight(float max_weight);
-
float GetActorMaxWalkWeight() const;
void SetActorMaxWalkWeight(float max_walk_weight);
-
float GetAdditionalMaxWeight() const;
void SetAdditionalMaxWeight(float add_max_weight);
-
float GetAdditionalMaxWalkWeight() const;
void SetAdditionalMaxWalkWeight(float add_max_walk_weight);
-
float GetTotalWeight() const;
float Weight() const;
float GetActorJumpSpeed() const;
void SetActorJumpSpeed(float jump_speed);
-
float GetActorSprintKoef() const;
void SetActorSprintKoef(float sprint_koef);
-
float GetActorRunCoef() const;
void SetActorRunCoef(float run_coef);
-
float GetActorRunBackCoef() const;
void SetActorRunBackCoef(float run_back_coef);
void SetCharacterIcon(pcstr iconName);
//-Alundaio
-#endif // GAME_OBJECT_EXTENDED_EXPORTS
+
doors::door* m_door;
};
diff --git a/src/xrGame/script_game_object2.cpp b/src/xrGame/script_game_object2.cpp
index 5d5dbdf6f0d..e667aa544aa 100644
--- a/src/xrGame/script_game_object2.cpp
+++ b/src/xrGame/script_game_object2.cpp
@@ -81,8 +81,15 @@ CScriptGameObject* CScriptGameObject::best_weapon()
}
else
{
- CGameObject* game_object = object_handler->best_weapon() ? &object_handler->best_weapon()->object() : 0;
- return (game_object ? game_object->lua_game_object() : 0);
+ //Alundaio: extra security
+ CGameObject* game_object = object_handler->best_weapon() ? &object_handler->best_weapon()->object() : nullptr;
+ if (!game_object)
+ return nullptr;
+
+ if (!game_object->H_Parent() || game_object->H_Parent()->ID() != object().ID())
+ return nullptr;
+ //-Alundaio
+ return game_object->lua_game_object();
}
}
@@ -610,3 +617,6 @@ void CScriptGameObject::ResetBoneProtections(pcstr imm_sect, pcstr bone_sect)
stalker->ResetBoneProtections(imm_sect, bone_sect);
}
+
+void CScriptGameObject::set_visual_name(pcstr visual) { object().cNameVisual_set(visual); }
+pcstr CScriptGameObject::get_visual_name() const { return object().cNameVisual().c_str(); }
diff --git a/src/xrGame/script_game_object3.cpp b/src/xrGame/script_game_object3.cpp
index e7d7a72b1e5..6f7c7904f26 100644
--- a/src/xrGame/script_game_object3.cpp
+++ b/src/xrGame/script_game_object3.cpp
@@ -39,7 +39,6 @@
#include "stalker_decision_space.h"
#include "space_restriction_manager.h"
//Alundaio
-#ifdef GAME_OBJECT_EXTENDED_EXPORTS
#include "Artefact.h"
#include "holder_custom.h"
#include "Actor.h"
@@ -48,9 +47,10 @@
#include "eatable_item.h"
#include "xrScriptEngine/script_callback_ex.h"
#include "xrEngine/Feel_Touch.h"
+#include "WeaponAmmo.h"
+#include "WeaponMagazinedWGrenade.h"
#include "level_path_manager.h"
#include "game_path_manager.h"
-#endif
//-Alundaio
namespace MemorySpace
@@ -1263,7 +1263,6 @@ bool CScriptGameObject::is_weapon_going_to_be_strapped(CScriptGameObject const*
}
//Alundaio: Taken from Radium
-#ifdef GAME_OBJECT_EXTENDED_EXPORTS
u16 CScriptGameObject::AmmoGetCount()
{
CWeaponAmmo* ammo = smart_cast(&object());
@@ -1383,22 +1382,21 @@ void CScriptGameObject::SetArtefactBleedingRestoreSpeed(float value)
artefact->SetBleedingPower(value);
}
-void CScriptGameObject::AttachVehicle(CScriptGameObject* veh)
+void CScriptGameObject::AttachVehicle(CScriptGameObject* veh, bool bForce)
{
- CActor* actor = smart_cast(&object());
- if (actor)
+ if (CActor* actor = smart_cast(&object()))
{
- CHolderCustom* vehicle = veh->object().cast_holder_custom();//smart_cast(veh->object());
- if (vehicle)
- actor->attach_Vehicle(vehicle);
+ if (CHolderCustom* vehicle = veh->object().cast_holder_custom())
+ actor->use_HolderEx(vehicle, bForce);
}
}
-void CScriptGameObject::DetachVehicle()
+void CScriptGameObject::DetachVehicle(bool bForce)
{
- CActor* actor = smart_cast(&object());
- if (actor)
- actor->detach_Vehicle();
+ if (CActor* actor = smart_cast(&object()))
+ {
+ actor->use_HolderEx(nullptr, bForce);
+ }
}
CScriptGameObject* CScriptGameObject::GetAttachedVehicle()
@@ -1420,13 +1418,12 @@ CScriptGameObject* CScriptGameObject::GetAttachedVehicle()
u32 CScriptGameObject::PlayHudMotion(pcstr M, bool mixIn, u32 state)
{
- CWeapon* Weapon = object().cast_weapon();
- if (Weapon)
+ if (CWeapon* weapon = object().cast_weapon())
{
- if (!Weapon->isHUDAnimationExist(M))
+ if (!weapon->isHUDAnimationExist(M))
return 0;
- return Weapon->PlayHUDMotion(M, mixIn, Weapon, state);
+ return weapon->PlayHUDMotion(M, mixIn, weapon, state);
}
CHudItem* itm = object().cast_inventory_item()->cast_hud_item();
@@ -1448,32 +1445,34 @@ void CScriptGameObject::SwitchState(u32 state)
return;
}
- CInventoryItem* IItem = object().cast_inventory_item();
- if (IItem)
+ if (CInventoryItem* IItem = object().cast_inventory_item())
{
- CHudItem* itm = IItem->cast_hud_item();
- if (itm)
+ if (CHudItem* itm = IItem->cast_hud_item())
itm->SwitchState(state);
}
}
u32 CScriptGameObject::GetState()
{
- CWeapon* Weapon = object().cast_weapon();
- if (Weapon)
- return Weapon->GetState();
+ if (const auto weapon = object().cast_weapon())
+ return weapon->GetState();
- CInventoryItem* IItem = object().cast_inventory_item();
- if (IItem)
+ if (CInventoryItem* IItem = object().cast_inventory_item())
{
- CHudItem* itm = IItem->cast_hud_item();
- if (itm)
+ if (const auto itm = IItem->cast_hud_item())
return itm->GetState();
}
return 65535;
}
+bool CScriptGameObject::WeaponInGrenadeMode()
+{
+ if (const auto wpn = smart_cast(&object()))
+ return wpn->m_bGrenadeMode;
+ return false;
+}
+
void CScriptGameObject::SetBoneVisible(pcstr bone_name, bool bVisibility, bool bRecursive)
{
IKinematics* k = object().Visual()->dcast_PKinematics();
@@ -1505,7 +1504,7 @@ bool CScriptGameObject::IsBoneVisible(pcstr bone_name)
float CScriptGameObject::GetLuminocityHemi()
{
- CGameObject* e = smart_cast(&object());
+ CGameObject* e = &object();
if (!e || !e->renderable_ROS())
return 0;
return e->renderable_ROS()->get_luminocity_hemi();
@@ -1513,7 +1512,7 @@ float CScriptGameObject::GetLuminocityHemi()
float CScriptGameObject::GetLuminocity()
{
- CGameObject* e = smart_cast(&object());
+ CGameObject* e = &object();
if (!e || !e->renderable_ROS())
return 0;
return e->renderable_ROS()->get_luminocity();
@@ -1525,8 +1524,7 @@ void CScriptGameObject::ForceSetPosition(Fvector pos, bool bActivate)
if (!sh)
return;
- CPhysicsShell* shell = sh->PPhysicsShell();
- if (shell)
+ if (CPhysicsShell* shell = sh->PPhysicsShell())
{
if (bActivate)
sh->activate_physic_shell();
@@ -1540,8 +1538,10 @@ void CScriptGameObject::ForceSetPosition(Fvector pos, bool bActivate)
sh->character_physics_support()->ForceTransform(M);
}
else
- GEnv.ScriptEngine->script_log(LuaMessageType::Error, "force_set_position: object %s has no physics shell!",
- *object().cName());
+ {
+ GEnv.ScriptEngine->script_log(LuaMessageType::Error,
+ "force_set_position: object %s has no physics shell!", object().cName().c_str());
+ }
}
void CScriptGameObject::SetRemainingUses(u8 value)
@@ -1585,15 +1585,11 @@ u8 CScriptGameObject::GetMaxUses()
void CScriptGameObject::IterateFeelTouch(luabind::functor functor)
{
- Feel::Touch* touch = smart_cast(&object());
- if (touch)
+ if (Feel::Touch* touch = smart_cast(&object()))
{
for (const auto& game_object : touch->feel_touch)
{
- // XXX Xottab_DUTY: Do we need this cast from IGameObject* to IGameObject* ?
- IGameObject* o = smart_cast(game_object);
- if (o)
- functor(game_object->ID());
+ functor(game_object->ID());
}
}
}
@@ -1610,8 +1606,7 @@ u32 CScriptGameObject::GetSpatialType()
u8 CScriptGameObject::GetRestrictionType()
{
- CSpaceRestrictor* restr = smart_cast(&object());
- if (restr)
+ if (const auto restr = smart_cast(&object()))
return restr->m_space_restrictor_type;
return -1;
@@ -1619,13 +1614,11 @@ u8 CScriptGameObject::GetRestrictionType()
void CScriptGameObject::SetRestrictionType(u8 type)
{
- CSpaceRestrictor* restr = smart_cast(&object());
- if (restr)
+ if (const auto restr = smart_cast(&object()))
{
restr->m_space_restrictor_type = type;
if (type != RestrictionSpace::eRestrictorTypeNone)
Level().space_restriction_manager().register_restrictor(restr, RestrictionSpace::ERestrictorTypes(type));
}
}
-#endif
//-Alundaio
diff --git a/src/xrGame/script_game_object4.cpp b/src/xrGame/script_game_object4.cpp
index 5805bd1963b..f41416176ae 100644
--- a/src/xrGame/script_game_object4.cpp
+++ b/src/xrGame/script_game_object4.cpp
@@ -24,6 +24,26 @@
#include "Artefact.h"
#include "stalker_sound_data.h"
+// AVO: for functions for testing object class
+//#include "car.h"
+//#include "helicopter.h"
+#include "Actor.h"
+#include "CustomOutfit.h"
+//#include "CustomZone.h"
+#include "ai/monsters/basemonster/base_monster.h"
+//#include "Artifact.h"
+//#include "medkit.h"
+//#include "antirad.h"
+#include "Scope.h"
+#include "Silencer.h"
+#include "Torch.h"
+#include "GrenadeLauncher.h"
+#include "searchlight.h"
+//#include "WeaponAmmo.h"
+//#include "Grenade.h"
+//#include "BottleItem.h"
+#include "WeaponMagazinedWGrenade.h"
+
class CWeapon;
//////////////////////////////////////////////////////////////////////////
@@ -317,7 +337,7 @@ void CScriptGameObject::start_particles(LPCSTR pname, LPCSTR bone)
return;
IKinematics* K = smart_cast(object().Visual());
- R_ASSERT(K);
+ R_ASSERT1_CURE(K, true, { return; });
u16 play_bone = K->LL_BoneID(bone);
R_ASSERT(play_bone != BI_NONE);
@@ -335,7 +355,7 @@ void CScriptGameObject::stop_particles(LPCSTR pname, LPCSTR bone)
return;
IKinematics* K = smart_cast(object().Visual());
- R_ASSERT(K);
+ R_ASSERT1_CURE(K, true, { return; });
u16 play_bone = K->LL_BoneID(bone);
R_ASSERT(play_bone != BI_NONE);
@@ -347,7 +367,6 @@ void CScriptGameObject::stop_particles(LPCSTR pname, LPCSTR bone)
LuaMessageType::Error, "Cant stop particles, bone [%s] is not visible now", bone);
}
-#ifdef GAME_OBJECT_EXTENDED_EXPORTS
//AVO: directly set entity health instead of going through normal health property which operates on delta
void CScriptGameObject::SetHealthEx(float hp)
{
@@ -357,4 +376,51 @@ void CScriptGameObject::SetHealthEx(float hp)
obj->SetfHealth(hp);
}
//-AVO
-#endif
+
+// AVO: functions for testing object class
+// Credits: KD
+#define TEST_OBJECT_CLASS(funcname, classname)\
+ bool funcname() const\
+ {\
+ if (smart_cast(&object()))\
+ return true;\
+ return false;\
+ }
+
+//TEST_OBJECT_CLASS(CScriptGameObject::IsGameObject, CGameObject)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsCar, CCar)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsHeli, CHelicopter)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsHolderCustom, CHolderCustom)
+TEST_OBJECT_CLASS(CScriptGameObject::IsEntityAlive, CEntityAlive)
+TEST_OBJECT_CLASS(CScriptGameObject::IsInventoryItem, CInventoryItem)
+TEST_OBJECT_CLASS(CScriptGameObject::IsInventoryOwner, CInventoryOwner)
+TEST_OBJECT_CLASS(CScriptGameObject::IsActor, CActor)
+TEST_OBJECT_CLASS(CScriptGameObject::IsCustomMonster, CCustomMonster)
+TEST_OBJECT_CLASS(CScriptGameObject::IsWeapon, CWeapon)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsMedkit, CMedkit)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsEatableItem, CEatableItem)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsAntirad, CAntirad)
+TEST_OBJECT_CLASS(CScriptGameObject::IsCustomOutfit, CCustomOutfit)
+TEST_OBJECT_CLASS(CScriptGameObject::IsScope, CScope)
+TEST_OBJECT_CLASS(CScriptGameObject::IsSilencer, CSilencer)
+TEST_OBJECT_CLASS(CScriptGameObject::IsGrenadeLauncher, CGrenadeLauncher)
+TEST_OBJECT_CLASS(CScriptGameObject::IsWeaponMagazined, CWeaponMagazined)
+TEST_OBJECT_CLASS(CScriptGameObject::IsSpaceRestrictor, CSpaceRestrictor)
+TEST_OBJECT_CLASS(CScriptGameObject::IsStalker, CAI_Stalker)
+TEST_OBJECT_CLASS(CScriptGameObject::IsAnomaly, CCustomZone)
+TEST_OBJECT_CLASS(CScriptGameObject::IsMonster, CBaseMonster)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsExplosive, CExplosive)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsScriptZone, CScriptZone)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsProjector, CProjector)
+TEST_OBJECT_CLASS(CScriptGameObject::IsTrader, CAI_Trader)
+TEST_OBJECT_CLASS(CScriptGameObject::IsHudItem, CHudItem)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsFoodItem, CFoodItem)
+TEST_OBJECT_CLASS(CScriptGameObject::IsArtefact, CArtefact)
+TEST_OBJECT_CLASS(CScriptGameObject::IsAmmo, CWeaponAmmo)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsMissile, CMissile)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsPhysicsShellHolder, CPhysicsShellHolder)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsGrenade, CGrenade)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsBottleItem, CBottleItem)
+//TEST_OBJECT_CLASS(CScriptGameObject::IsTorch, CTorch)
+TEST_OBJECT_CLASS(CScriptGameObject::IsWeaponGL, CWeaponMagazinedWGrenade)
+TEST_OBJECT_CLASS(CScriptGameObject::IsInventoryBox, CInventoryBox)
diff --git a/src/xrGame/script_game_object_inventory_owner.cpp b/src/xrGame/script_game_object_inventory_owner.cpp
index b36b6d54899..f5e699ce6bd 100644
--- a/src/xrGame/script_game_object_inventory_owner.cpp
+++ b/src/xrGame/script_game_object_inventory_owner.cpp
@@ -53,7 +53,6 @@
#include "CustomOutfit.h"
#include "ActorBackpack.h"
#include "inventory_item_impl.h"
-#include "Inventory.h"
#include "xrServer_Objects_ALife_Items.h"
#include "xrServerEntities/inventory_space.h"
//-Alundaio
@@ -289,7 +288,7 @@ void CScriptGameObject::ForEachInventoryItems(const luabind::functor& func
}
// 1
-void CScriptGameObject::IterateInventory(luabind::functor functor, luabind::object object)
+void CScriptGameObject::IterateInventory(luabind::functor functor, luabind::object object)
{
CInventoryOwner* inventory_owner = smart_cast(&this->object());
if (!inventory_owner)
@@ -299,14 +298,15 @@ void CScriptGameObject::IterateInventory(luabind::functor functor, luabind
return;
}
- TIItemContainer::iterator I = inventory_owner->inventory().m_all.begin();
- TIItemContainer::iterator E = inventory_owner->inventory().m_all.end();
+ TIItemContainer::iterator I = inventory_owner->inventory().m_all.begin();
+ TIItemContainer::iterator E = inventory_owner->inventory().m_all.end();
for (; I != E; ++I)
- functor(object, (*I)->object().lua_game_object());
+ if (functor(object, (*I)->object().lua_game_object()) == true)
+ return;
}
#include "InventoryBox.h"
-void CScriptGameObject::IterateInventoryBox(luabind::functor functor, luabind::object object)
+void CScriptGameObject::IterateInventoryBox(luabind::functor functor, luabind::object object)
{
CInventoryBox* inventory_box = smart_cast(&this->object());
if (!inventory_box)
@@ -320,9 +320,9 @@ void CScriptGameObject::IterateInventoryBox(luabind::functor functor, luab
xr_vector::const_iterator E = inventory_box->m_items.end();
for (; I != E; ++I)
{
- CGameObject* GO = smart_cast(Level().Objects.net_Find(*I));
- if (GO)
- functor(object, GO->lua_game_object());
+ if (const auto GO = smart_cast(Level().Objects.net_Find(*I)))
+ if (functor(object, GO->lua_game_object()) == true)
+ return;
}
}
@@ -755,6 +755,18 @@ void CScriptGameObject::ChangeCharacterReputation(int char_rep)
pInventoryOwner->ChangeReputation(char_rep);
}
+void CScriptGameObject::SetCharacterReputation(int char_rep)
+{
+ CInventoryOwner* pInventoryOwner = smart_cast(&object());
+
+ if (!pInventoryOwner)
+ {
+ GEnv.ScriptEngine->script_log(LuaMessageType::Error, "SetCharacterReputation available only for InventoryOwner");
+ return;
+ }
+ pInventoryOwner->SetReputation(char_rep);
+}
+
LPCSTR CScriptGameObject::CharacterCommunity()
{
CInventoryOwner* pInventoryOwner = smart_cast(&object());
@@ -1755,7 +1767,6 @@ bool CScriptGameObject::is_door_blocked_by_npc() const
//Alundaio: Methods for exporting the ability to detach/attach addons for magazined weapons
-#ifdef GAME_OBJECT_EXTENDED_EXPORTS
void CScriptGameObject::Weapon_AddonAttach(CScriptGameObject* item)
{
auto weapon = smart_cast(&object());
@@ -2227,5 +2238,4 @@ void CScriptGameObject::SetCharacterIcon(pcstr iconName)
}
return pInventoryOwner->SetIcon(iconName);
}
-#endif
//-Alundaio
diff --git a/src/xrGame/script_game_object_script.cpp b/src/xrGame/script_game_object_script.cpp
index de392ee1d56..640131fdf5e 100644
--- a/src/xrGame/script_game_object_script.cpp
+++ b/src/xrGame/script_game_object_script.cpp
@@ -92,6 +92,8 @@ SCRIPT_EXPORT(CScriptGameObject, (),
value("take_item_from_box", int(GameObject::eInvBoxItemTake)),
value("weapon_no_ammo", int(GameObject::eWeaponNoAmmoAvailable)),
+ //Alundaio:
+ value("hud_animation_end", int(GameObject::eActorHudAnimationEnd)),
//AVO: custom callbacks
// Input
value("key_press", int(GameObject::eKeyPress)),
@@ -102,23 +104,22 @@ SCRIPT_EXPORT(CScriptGameObject, (),
value("controller_press", int(GameObject::eControllerPress)),
value("controller_release", int(GameObject::eControllerRelease)),
value("controller_hold", int(GameObject::eControllerHold)),
- // Inventory
- value("item_to_belt", int(GameObject::eItemToBelt)),
- value("item_to_slot", int(GameObject::eItemToSlot)),
- value("item_to_ruck", int(GameObject::eItemToRuck)),
// Actor
value("actor_before_death", int(GameObject::eActorBeforeDeath)),
- //-AVO
-
- // vehicle
+ // Vehicle
value("on_attach_vehicle", int(GameObject::eAttachVehicle)),
value("on_detach_vehicle", int(GameObject::eDetachVehicle)),
value("on_use_vehicle", int(GameObject::eUseVehicle)),
-
- // weapon
+ // Weapon
value("weapon_jammed", int(GameObject::eOnWeaponJammed)),
value("weapon_zoom_in", int(GameObject::eOnWeaponZoomIn)),
value("weapon_zoom_out", int(GameObject::eOnWeaponZoomOut)),
+ value("weapon_magazine_empty", int(GameObject::eOnWeaponMagazineEmpty)),
+ // Inventory
+ value("item_to_belt", int(GameObject::eItemToBelt)),
+ value("item_to_slot", int(GameObject::eItemToSlot)),
+ value("item_to_ruck", int(GameObject::eItemToRuck)),
+ //-AVO
value("map_location_added", int(GameObject::eMapLocationAdded))
],
diff --git a/src/xrGame/script_game_object_script2.cpp b/src/xrGame/script_game_object_script2.cpp
index fdf38acfcc3..fd4bfd10c61 100644
--- a/src/xrGame/script_game_object_script2.cpp
+++ b/src/xrGame/script_game_object_script2.cpp
@@ -106,7 +106,6 @@ luabind::class_& script_register_game_object1(luabind::class_
.def("group", &CScriptGameObject::Group)
.def("change_team", (void (CScriptGameObject::*)(u8, u8, u8))(&CScriptGameObject::ChangeTeam))
.def("set_visual_memory_enabled", &CScriptGameObject::SetVisualMemoryEnabled)
- // XXX: this is a workaround, since luabind can't determine default function arguments...
.def("kill", (void (CScriptGameObject::*)(CScriptGameObject*))&CScriptGameObject::Kill)
.def("kill", (void (CScriptGameObject::*)(CScriptGameObject*, bool))(&CScriptGameObject::Kill))
.def("hit", &CScriptGameObject::Hit)
diff --git a/src/xrGame/script_game_object_script3.cpp b/src/xrGame/script_game_object_script3.cpp
index bce41d611bf..9494f81ced8 100644
--- a/src/xrGame/script_game_object_script3.cpp
+++ b/src/xrGame/script_game_object_script3.cpp
@@ -283,7 +283,9 @@ luabind::class_& script_register_game_object2(luabind::class_
.def("character_icon", &CScriptGameObject::CharacterIcon)
.def("character_rank", &CScriptGameObject::CharacterRank)
.def("set_character_rank", &CScriptGameObject::SetCharacterRank)
+ .def("change_character_rank", &CScriptGameObject::ChangeCharacterRank)
.def("character_reputation", &CScriptGameObject::CharacterReputation)
+ .def("set_character_reputation", &CScriptGameObject::SetCharacterReputation)
.def("change_character_reputation", &CScriptGameObject::ChangeCharacterReputation)
.def("character_community", &CScriptGameObject::CharacterCommunity)
.def("set_character_community", &CScriptGameObject::SetCharacterCommunity)
@@ -434,13 +436,12 @@ luabind::class_& script_register_game_object2(luabind::class_
.def("start_particles", &CScriptGameObject::start_particles)
.def("stop_particles", &CScriptGameObject::stop_particles)
- //Alundaio: Extended exports
- //For Car
+ // Alundaio: Extended exports
+ // For Car
.def("attach_vehicle", &CScriptGameObject::AttachVehicle)
.def("detach_vehicle", &CScriptGameObject::DetachVehicle)
.def("get_attached_vehicle", &CScriptGameObject::GetAttachedVehicle)
-#ifdef GAME_OBJECT_EXTENDED_EXPORTS
.def("reset_bone_protections", &CScriptGameObject::ResetBoneProtections)
.def("iterate_feel_touch", &CScriptGameObject::IterateFeelTouch)
.def("get_luminocity_hemi", &CScriptGameObject::GetLuminocityHemi)
@@ -456,16 +457,16 @@ luabind::class_& script_register_game_object2(luabind::class_
.def("remove_memory_visible_object", &CScriptGameObject::RemoveMemoryVisibleObject)
.def("remove_memory_hit_object", &CScriptGameObject::RemoveMemoryHitObject)
- //For Ammo
+ // For Ammo
.def("ammo_get_count", &CScriptGameObject::AmmoGetCount)
.def("ammo_set_count", &CScriptGameObject::AmmoSetCount)
.def("ammo_box_size", &CScriptGameObject::AmmoBoxSize)
- //For Weapons
+ // For Weapons
.def("weapon_addon_attach", &CScriptGameObject::Weapon_AddonAttach)
.def("weapon_addon_detach", &CScriptGameObject::Weapon_AddonDetach)
- //For Weapon & Outfit
+ // For Weapon & Outfit
.def("add_upgrade", &CScriptGameObject::AddUpgrade)
.def("install_upgrade", &CScriptGameObject::InstallUpgrade)
.def("has_upgrade", &CScriptGameObject::HasUpgrade)
@@ -474,24 +475,25 @@ luabind::class_& script_register_game_object2(luabind::class_
.def("can_install_upgrade", &CScriptGameObject::CanInstallUpgrade)
.def("can_add_upgrade", &CScriptGameObject::CanAddUpgrade)
.def("iterate_installed_upgrades", &CScriptGameObject::IterateInstalledUpgrades)
+ .def("weapon_in_grenade_mode", &CScriptGameObject::WeaponInGrenadeMode)
// For CHudItem
.def("play_hud_motion", &CScriptGameObject::PlayHudMotion)
.def("switch_state", &CScriptGameObject::SwitchState)
.def("get_state", &CScriptGameObject::GetState)
+
// For EatableItem
.def("set_remaining_uses", &CScriptGameObject::SetRemainingUses)
.def("get_remaining_uses", &CScriptGameObject::GetRemainingUses)
.def("get_max_uses", &CScriptGameObject::GetMaxUses)
+
// Phantom
.def("phantom_set_enemy", &CScriptGameObject::PhantomSetEnemy)
+
// Actor
.def("set_character_icon", &CScriptGameObject::SetCharacterIcon)
-#endif
- //-Alundaio
-#ifdef GAME_OBJECT_CASTING_EXPORTS
- // Casting objects
+ // Casting
.def("cast_GameObject", &ObjectCast)
.def("cast_Car", &ObjectCast)
.def("cast_Heli", &ObjectCast)
@@ -528,8 +530,46 @@ luabind::class_& script_register_game_object2(luabind::class_
//.def("cast_Torch", &ObjectCast)
//.def("cast_WeaponMagazinedWGrenade", &ObjectCast)
//.def("cast_InventoryBox", &ObjectCast)
-#endif // GAME_OBJECT_CASTING_EXPORTS
+ //-Alundaio
+ //AVO: additional functions
+ //.def("is_game_object", &CScriptGameObject::IsGameObject)
+ //.def("is_car", &CScriptGameObject::IsCar)
+ //.def("is_helicopter", &CScriptGameObject::IsHeli)
+ //.def("is_holder", &CScriptGameObject::IsHolderCustom)
+ .def("is_entity_alive", &CScriptGameObject::IsEntityAlive)
+ .def("is_inventory_item", &CScriptGameObject::IsInventoryItem)
+ .def("is_inventory_owner", &CScriptGameObject::IsInventoryOwner)
+ .def("is_actor", &CScriptGameObject::IsActor)
+ .def("is_custom_monster", &CScriptGameObject::IsCustomMonster)
+ .def("is_weapon", &CScriptGameObject::IsWeapon)
+ //.def("is_medkit", &CScriptGameObject::IsMedkit)
+ //.def("is_eatable_item", &CScriptGameObject::IsEatableItem)
+ //.def("is_antirad", &CScriptGameObject::IsAntirad)
+ .def("is_outfit", &CScriptGameObject::IsCustomOutfit)
+ .def("is_scope", &CScriptGameObject::IsScope)
+ .def("is_silencer", &CScriptGameObject::IsSilencer)
+ .def("is_grenade_launcher", &CScriptGameObject::IsGrenadeLauncher)
+ .def("is_weapon_magazined", &CScriptGameObject::IsWeaponMagazined)
+ .def("is_space_restrictor", &CScriptGameObject::IsSpaceRestrictor)
+ .def("is_stalker", &CScriptGameObject::IsStalker)
+ .def("is_anomaly", &CScriptGameObject::IsAnomaly)
+ .def("is_monster", &CScriptGameObject::IsMonster)
+ //.def("is_explosive", &CScriptGameObject::IsExplosive)
+ //.def("is_script_zone", &CScriptGameObject::IsScriptZone)
+ //.def("is_projector", &CScriptGameObject::IsProjector)
+ .def("is_trader", &CScriptGameObject::IsTrader)
+ .def("is_hud_item", &CScriptGameObject::IsHudItem)
+ //.def("is_food_item", &CScriptGameObject::IsFoodItem)
+ .def("is_artefact", &CScriptGameObject::IsArtefact)
+ .def("is_ammo", &CScriptGameObject::IsAmmo)
+ //.def("is_missile", &CScriptGameObject::IsMissile)
+ //.def("is_physics_shell_holder", &CScriptGameObject::IsPhysicsShellHolder)
+ //.def("is_grenade", &CScriptGameObject::IsGrenade)
+ //.def("is_bottle_item", &CScriptGameObject::IsBottleItem)
+ //.def("is_torch", &CScriptGameObject::IsTorch)
+ .def("is_weapon_gl", &CScriptGameObject::IsWeaponGL)
+ .def("is_inventory_box", &CScriptGameObject::IsInventoryBox)
.def("is_on_belt", &CScriptGameObject::IsOnBelt)
.def("item_on_belt", &CScriptGameObject::ItemOnBelt)
diff --git a/src/xrGame/script_game_object_use.cpp b/src/xrGame/script_game_object_use.cpp
index 90b3f72be8f..44a642f88dc 100644
--- a/src/xrGame/script_game_object_use.cpp
+++ b/src/xrGame/script_game_object_use.cpp
@@ -59,7 +59,7 @@ int CScriptGameObject::clsid() const { return (object().clsid()); }
LPCSTR CScriptGameObject::Name() const { return (*object().cName()); }
shared_str CScriptGameObject::cName() const { return (object().cName()); }
LPCSTR CScriptGameObject::Section() const { return (*object().cNameSect()); }
-void CScriptGameObject::Kill(CScriptGameObject* who, bool bypass_actor_check /*AVO: added for actor before death callback*/)
+void CScriptGameObject::Kill(CScriptGameObject* who, bool bypass_actor_check)
{
CEntity* l_tpEntity = smart_cast(&object());
if (psActorFlags.test(AF_GODMODE) && !!l_tpEntity->cast_actor())
diff --git a/src/xrGame/script_movement_action.h b/src/xrGame/script_movement_action.h
index cd7fefbbd8a..e229170f7ca 100644
--- a/src/xrGame/script_movement_action.h
+++ b/src/xrGame/script_movement_action.h
@@ -114,7 +114,7 @@ class CScriptMovementAction : public CScriptAbstractAction
IC void SetMovementType(const MonsterSpace::EMovementType tMovementType);
IC void SetPathType(const DetailPathManager::EDetailPathType tPathType);
void SetObjectToGo(CScriptGameObject* tpObjectToGo);
- IC void SetPatrolPath(const CPatrolPath* path, shared_str path_name);
+ IC void SetPatrolPath(const CPatrolPath* path, const shared_str& path_name);
IC void SetPosition(const Fvector& tPosition);
IC void SetSpeed(float fSpeed);
IC void SetPatrolStart(EPatrolStartType tPatrolPathStart);
diff --git a/src/xrGame/script_movement_action_inline.h b/src/xrGame/script_movement_action_inline.h
index 7e5d0a1fefa..7c2c7e3a097 100644
--- a/src/xrGame/script_movement_action_inline.h
+++ b/src/xrGame/script_movement_action_inline.h
@@ -76,7 +76,7 @@ IC void CScriptMovementAction::SetPathType(const DetailPathManager::EDetailPathT
m_bCompleted = false;
}
-IC void CScriptMovementAction::SetPatrolPath(const CPatrolPath* path, shared_str path_name)
+IC void CScriptMovementAction::SetPatrolPath(const CPatrolPath* path, const shared_str& path_name)
{
m_path = path;
m_path_name = path_name;
diff --git a/src/xrGame/sight_manager.cpp b/src/xrGame/sight_manager.cpp
index 75f56ab576d..754ab6fe5a4 100644
--- a/src/xrGame/sight_manager.cpp
+++ b/src/xrGame/sight_manager.cpp
@@ -65,7 +65,7 @@ void CSightManager::vfValidateAngleDependency(float x1, float& x2, float x3)
BOOL g_ai_dbg_sight = 0;
#endif // #ifdef DEBUG
-float g_ai_aim_min_speed = PI_DIV_8 / 2.f;
+float g_ai_aim_min_speed = 0.24f; // PI_DIV_8 / 2.f; //Alundaio
float g_ai_aim_min_angle = PI_DIV_8 / 2.f;
float g_ai_aim_max_angle = PI_DIV_4;
BOOL g_ai_aim_use_smooth_aim = 1;
diff --git a/src/xrGame/space_restrictor.cpp b/src/xrGame/space_restrictor.cpp
index c2287aeb4ce..44f031cb5fd 100644
--- a/src/xrGame/space_restrictor.cpp
+++ b/src/xrGame/space_restrictor.cpp
@@ -23,6 +23,7 @@
//Alundaio
#include "RadioactiveZone.h"
+#include "ZoneCampfire.h"
BOOL g_ai_die_in_anomaly = 0;
//-Alundaio
@@ -67,8 +68,9 @@ bool CSpaceRestrictor::net_Spawn(CSE_Abstract* data)
if (!result)
return (FALSE);
- CCustomZone* zone = smart_cast(this);
- if (g_ai_die_in_anomaly == 0 || !zone || smart_cast(zone))
+ //Alundaio: zone visible for ai if g_ai_die_in_anomaly = 1 unless it's Radioactive Zone or Campfire
+ CCustomZone* zone = smart_cast(this);
+ if (g_ai_die_in_anomaly == 0 || !zone || smart_cast(zone) || smart_cast(zone))
spatial.type &= ~STYPE_VISIBLEFORAI;
setEnabled(FALSE);
diff --git a/src/xrGame/stalker_animation_manager_update.cpp b/src/xrGame/stalker_animation_manager_update.cpp
index b31cb94c2e8..6a7b4881850 100644
--- a/src/xrGame/stalker_animation_manager_update.cpp
+++ b/src/xrGame/stalker_animation_manager_update.cpp
@@ -229,12 +229,14 @@ void CStalkerAnimationManager::update()
catch (...)
{
Msg("! error in stalker with visual %s and ID %u", *object().cNameVisual(), object().ID());
+ /* avo: prevent game from crashing */
head().reset();
torso().reset();
legs().reset();
global().reset();
return;
// throw;
+ /* avo: end */
}
STOP_PROFILE
}
diff --git a/src/xrGame/stalker_animation_torso.cpp b/src/xrGame/stalker_animation_torso.cpp
index b6934c0587c..21ebc1b65e1 100644
--- a/src/xrGame/stalker_animation_torso.cpp
+++ b/src/xrGame/stalker_animation_torso.cpp
@@ -30,13 +30,15 @@ MotionID CStalkerAnimationManager::aim_animation(
if (slot != 2)
return (animation[6].A[index]);
-#if 1 // def DEBUG
if (animation[6].A.size() < 7)
{
+ //Alundaio: No need for message as many npcs have special danger move and very few don't
+#ifndef MASTER_GOLD
Msg("! cannot find special danger animations for object with visual %s", object().cNameVisual().c_str());
+#endif
+ //-Alundaio
return (animation[6].A[index]);
}
-#endif // DEBUG
switch (index)
{
diff --git a/src/xrGame/stalker_combat_actions.cpp b/src/xrGame/stalker_combat_actions.cpp
index 4546cc063e8..b9d980931a8 100644
--- a/src/xrGame/stalker_combat_actions.cpp
+++ b/src/xrGame/stalker_combat_actions.cpp
@@ -434,6 +434,7 @@ void CStalkerActionKillEnemy::execute()
#endif // TEST_MENTAL_STATE
inherited::execute();
+
//Alundaio: Prevent Stalkers from shooting at walls for prolonged periods due to kill if not visible
const CEntityAlive* enemy = object().memory().enemy().selected();
if (enemy && enemy->g_Alive())
@@ -538,10 +539,6 @@ void CStalkerActionTakeCover::execute()
object().brain().affect_cover(true);
}
- //. Add fire here
- // if (object().memory().visual().visible_now(object().memory().enemy().selected()) && object().can_kill_enemy())
- // if (object().memory().visual().visible_now(object().memory().enemy().selected()))
-
if (object().movement().path_completed()) // && (object().memory().enemy().selected()->Position().distance_to_sqr(object().Position()) >= 10.f))
{
object().best_cover_can_try_advance();
@@ -820,7 +817,6 @@ void CStalkerActionDetourEnemy::initialize()
//#ifndef SILENT_COMBAT
//Alundaio: Added sanity to make sure enemy exists
if (object().memory().enemy().selected() && object().memory().enemy().selected()->human_being() && object().agent_manager().member().group_behaviour())
- //Alundaio: END
//object().sound().play(eStalkerSoundNeedBackup);
object().sound().play(eStalkerSoundDetour);
//#endif
@@ -1064,31 +1060,38 @@ void CStalkerActionSuddenAttack::execute()
//Alundaio: Removed check to allow stalkers to sneak up on enemy even if they are in a group.
//if (object().agent_manager().member().combat_members().size() > 1)
- // m_storage->set_property(eWorldPropertyUseSuddenness, false);
- //-Alundaio
+ // m_storage->set_property(eWorldPropertyUseSuddenness,false);
+ //Alundaio: END
const CEntityAlive* enemy = object().memory().enemy().selected();
if (!enemy)
+ {
+ m_storage->set_property(eWorldPropertyUseSuddenness, false);
return;
+ }
CMemoryInfo mem_object = object().memory().memory(enemy);
+
if (!mem_object.m_object)
+ {
+ m_storage->set_property(eWorldPropertyUseSuddenness, false);
return;
+ }
- //Alundaio: Don't aim at ceiling or floor
- bool visible_now = object().memory().visual().visible_now(enemy);
-
+ const bool visible_now = object().memory().visual().visible_now(enemy);
if (visible_now)
object().sight().setup(CSightAction(enemy, true));
else
{
//Alundaio: Prevent stalkers from staring at floor or ceiling for this action
u32 const level_time = object().memory().visual().visible_object_time_last_seen(mem_object.m_object);
- if (Device.dwTimeGlobal >= level_time + 3000 && _abs(
- object().Position().y - mem_object.m_object_params.m_position.y) > 3.5f)
+ if (Device.dwTimeGlobal >= level_time + 3000 &&
+ _abs(object().Position().y - mem_object.m_object_params.m_position.y) > 3.5f)
{
- Fvector3 Vpos = {
- mem_object.m_object_params.m_position.x, object().Position().y + 1.f,
+ const Fvector3 Vpos =
+ {
+ mem_object.m_object_params.m_position.x,
+ object().Position().y + 1.f,
mem_object.m_object_params.m_position.z
};
object().sight().setup(CSightAction(SightManager::eSightTypePosition, Vpos, true));
@@ -1102,11 +1105,13 @@ void CStalkerActionSuddenAttack::execute()
if (object().movement().accessible(mem_object.m_object_params.m_level_vertex_id))
object().movement().set_level_dest_vertex(mem_object.m_object_params.m_level_vertex_id);
else
+ {
object().movement().set_nearest_accessible_position(
ai().level_graph().vertex_position(mem_object.m_object_params.m_level_vertex_id),
mem_object.m_object_params.m_level_vertex_id);
+ }
- if (!visible_now)
+ /*if (!visible_now)
{
u32 target_vertex_id = object().movement().level_path().dest_vertex_id();
if (object().ai_location().level_vertex_id() == target_vertex_id)
@@ -1114,9 +1119,9 @@ void CStalkerActionSuddenAttack::execute()
m_storage->set_property(eWorldPropertyUseSuddenness, false);
return;
}
- }
+ }*/
- float distance = object().Position().distance_to(mem_object.m_object_params.m_position);
+ const float distance = object().Position().distance_to(mem_object.m_object_params.m_position);
if (distance >= 15.f)
{
object().movement().set_body_state(eBodyStateStand);
@@ -1253,7 +1258,9 @@ void CStalkerActionCriticalHit::initialize()
min_queue_interval, max_queue_interval);
}
else
+ {
object().set_goal(eObjectActionIdle, object().best_weapon());
+ }
}
object().sight().setup(CSightAction(SightManager::eSightTypeCurrentDirection, true, true));
diff --git a/src/xrGame/stalker_combat_planner.cpp b/src/xrGame/stalker_combat_planner.cpp
index 738da893b4f..dca32c58ef0 100644
--- a/src/xrGame/stalker_combat_planner.cpp
+++ b/src/xrGame/stalker_combat_planner.cpp
@@ -464,6 +464,7 @@ void CStalkerCombatPlanner::add_actions()
add_condition(action, eWorldPropertyUseSuddenness, true);
add_condition(action, eWorldPropertyEnemyWounded, false);
add_condition(action, eWorldPropertyInSmartCover, false);
+ add_condition(action, eWorldPropertyEnemy, true);
add_effect(action, eWorldPropertyEnemy, false);
add_operator(eWorldOperatorSuddenAttack, action);
diff --git a/src/xrGame/trade2.cpp b/src/xrGame/trade2.cpp
index ebafec3d4db..05e2d958e98 100644
--- a/src/xrGame/trade2.cpp
+++ b/src/xrGame/trade2.cpp
@@ -63,7 +63,7 @@ bool CTrade::CanTrade()
return true;
}
-void CTrade::TransferItem(CInventoryItem* pItem, bool bBuying, bool bFree)
+void CTrade::TransferItem(CInventoryItem* pItem, bool bBuying, bool bFree /*= false*/)
{
// сумма сделки учитывая ценовой коэффициент
// актер цену не говорит никогда, все делают за него
@@ -137,7 +137,7 @@ CInventory& CTrade::GetTradeInv(SInventoryOwner owner)
CTrade* CTrade::GetPartnerTrade() { return pPartner.inv_owner->GetTrade(); }
CInventory* CTrade::GetPartnerInventory() { return &GetTradeInv(pPartner); }
CInventoryOwner* CTrade::GetPartner() { return pPartner.inv_owner; }
-u32 CTrade::GetItemPrice(PIItem pItem, bool b_buying, bool bFree)
+u32 CTrade::GetItemPrice(PIItem pItem, bool b_buying, bool bFree /*= false*/)
{
if (bFree)
return 0;
@@ -217,6 +217,9 @@ u32 CTrade::GetItemPrice(PIItem pItem, bool b_buying, bool bFree)
clamp(action_factor, _min(trade_factors.enemy_factor(), trade_factors.friend_factor()),
_max(trade_factors.enemy_factor(), trade_factors.friend_factor()));
+ if (action_factor == 0)
+ return 0;
+
// computing deficit_factor
// float deficit_factor = partner.inv_owner->deficit_factor(pItem->object().cNameSect());
constexpr float deficit_factor = 1.f;
diff --git a/src/xrGame/trade_parameters_inline.h b/src/xrGame/trade_parameters_inline.h
index 4984a3fc596..d94d6f98b17 100644
--- a/src/xrGame/trade_parameters_inline.h
+++ b/src/xrGame/trade_parameters_inline.h
@@ -77,6 +77,9 @@ IC void CTradeParameters::process(_action_type type, CInifile& ini_file, const s
auto E = S.Data.cend();
for (; I != E; ++I)
{
+ if (!pSettings->section_exist(I->first))
+ continue;
+
if (!(*I).second.size())
{
_action.disable((*I).first);
@@ -84,9 +87,11 @@ IC void CTradeParameters::process(_action_type type, CInifile& ini_file, const s
}
string256 temp0, temp1;
- THROW3(_GetItemCount(*(*I).second) == 2, "Invalid parameters in section", *section);
- _action.enable((*I).first, CTradeFactors((float)atof(_GetItem(*(*I).second, 0, temp0)),
- (float)atof(_GetItem(*(*I).second, 1, temp1))));
+ //THROW3(_GetItemCount(I->second.c_str()) == 2, "Invalid parameters in section", section.c_str());
+ cpcstr param1 = _GetItem(I->second.c_str(), 0, temp0);
+ cpcstr param2 = _GetItemCount(I->second.c_str()) >= 2 ? _GetItem(I->second.c_str(), 1, temp1) : param1;
+
+ _action.enable(I->first, CTradeFactors((float)atof(param1), (float)atof(param2)));
}
}
diff --git a/src/xrGame/ui/Restrictions.cpp b/src/xrGame/ui/Restrictions.cpp
index e975af7e93e..df0c4a877cf 100644
--- a/src/xrGame/ui/Restrictions.cpp
+++ b/src/xrGame/ui/Restrictions.cpp
@@ -31,13 +31,14 @@ u32 get_rank(const shared_str& section)
}
}
+ //R_ASSERT3(res != -1, "cannot find rank for", section.c_str());
if (res == -1)
{
- Msg("Setting rank to 0. Cannot find rank for: [%s]", section.c_str());
+ Msg("! Setting rank to 0. Cannot find rank for: [%s]", section.c_str());
// Xottab_DUTY: I'm not sure if it's save to leave it -1
res = 0;
}
- //R_ASSERT3(res != -1, "cannot find rank for", section.c_str());
+
return res;
}
diff --git a/src/xrGame/ui/UIActorMenu.cpp b/src/xrGame/ui/UIActorMenu.cpp
index 1b21d757926..a776c525eab 100644
--- a/src/xrGame/ui/UIActorMenu.cpp
+++ b/src/xrGame/ui/UIActorMenu.cpp
@@ -159,6 +159,7 @@ void CUIActorMenu::SetMenuMode(EMenuMode mode)
InitActorInfo();
if (m_currMenuMode != mmUndefined && m_currMenuMode != mmInventory)
InitPartnerInfo();
+ highlight_equipped();
CurModeToScript();
} // if
@@ -526,6 +527,8 @@ void CUIActorMenu::UpdateItemsPlace()
UpdateOutfit();
UpdateActor();
}
+
+ highlight_equipped();
}
// ================================================================
@@ -868,6 +871,25 @@ void CUIActorMenu::highlight_weapons_for_addon(PIItem addon_item, CUIDragDropLis
} // for i
}
+void CUIActorMenu::highlight_equipped() const
+{
+ // Highlight 'equipped' items in actor bag
+ CUIDragDropListEx* slot_list = m_pLists[eInventoryBagList];
+ u32 const cnt = slot_list->ItemsCount();
+ for (u32 i = 0; i < cnt; ++i)
+ {
+ CUICellItem* ci = slot_list->GetItemIdx(i);
+ const auto item = static_cast(ci->m_pData);
+ if (!item)
+ continue;
+
+ if (item->m_highlight_equipped && item->m_pInventory && item->m_pInventory->ItemFromSlot(item->BaseSlot()) == item)
+ ci->m_select_equipped = true;
+ else
+ ci->m_select_equipped = false;
+ }
+}
+
// -------------------------------------------------------------------
void CUIActorMenu::ClearAllLists()
@@ -981,9 +1003,10 @@ bool CUIActorMenu::CanSetItemToList(PIItem item, CUIDragDropListEx* l, u16& ret_
void CUIActorMenu::HighlightSectionInSlot(pcstr section, EDDListType type, u16 slot_id /*= 0*/)
{
CUIDragDropListEx* slot_list = GetListByType(type);
-
if (!slot_list)
slot_list = m_pLists[eInventoryBagList];
+ if (!slot_list)
+ return;
u32 const cnt = slot_list->ItemsCount();
for (u32 i = 0; i < cnt; ++i)
@@ -1008,9 +1031,10 @@ void CUIActorMenu::HighlightForEachInSlot(const luabind::functor& functor,
return;
CUIDragDropListEx* slot_list = GetListByType(type);
-
if (!slot_list)
slot_list = m_pLists[eInventoryBagList];
+ if (!slot_list)
+ return;
u32 const cnt = slot_list->ItemsCount();
for (u32 i = 0; i < cnt; ++i)
diff --git a/src/xrGame/ui/UIActorMenu.h b/src/xrGame/ui/UIActorMenu.h
index ecf76bcd22f..a5fe42487ad 100644
--- a/src/xrGame/ui/UIActorMenu.h
+++ b/src/xrGame/ui/UIActorMenu.h
@@ -222,6 +222,7 @@ class CUIActorMenu final : public CUIDialogWnd, public CUIWndCallback
void highlight_weapons_for_ammo(PIItem ammo_item, CUIDragDropListEx* ddlist);
bool highlight_addons_for_weapon(PIItem weapon_item, CUICellItem* ci);
void highlight_weapons_for_addon(PIItem addon_item, CUIDragDropListEx* ddlist);
+ void highlight_equipped() const;
protected:
void Construct();
@@ -393,12 +394,17 @@ class CUIActorMenu final : public CUIDialogWnd, public CUIWndCallback
IC UIHint* get_hint_wnd() { return m_hint_wnd; }
- CScriptGameObject* GetCurrentItemAsGameObject();
- void HighlightSectionInSlot(pcstr section, EDDListType type, u16 slot_id = 0);
- void HighlightForEachInSlot(const luabind::functor& functor, EDDListType type, u16 slot_id);
+ //AxelDominator && Alundaio consumable use condition
+ void RefreshCurrentItemCell();
- void RefreshCurrentItemCell();
- void DonateCurrentItem(CUICellItem* cell_item); //Alundaio: Donate item via context menu while in trade menu
+ CScriptGameObject* GetCurrentItemAsGameObject();
+ void HighlightSectionInSlot(pcstr section, EDDListType type, u16 slot_id = 0);
+ void HighlightForEachInSlot(const luabind::functor& functor, EDDListType type, u16 slot_id);
+ bool ToSlotScript(CScriptGameObject* GO, bool force_place, u16 slot_id);
+ bool ToBeltScript(CScriptGameObject* GO, bool b_use_cursor_pos);
+
+ //-AxelDominator && Alundaio consumable use condition
+ void DonateCurrentItem(CUICellItem* cell_item); //Alundaio: Donate item via context menu while in trade menu
pcstr GetDebugType() override { return "CUIActorMenu"; }
}; // class CUIActorMenu
diff --git a/src/xrGame/ui/UIActorMenuDeadBodySearch.cpp b/src/xrGame/ui/UIActorMenuDeadBodySearch.cpp
index 2369b0a8320..9c7c7fb2768 100644
--- a/src/xrGame/ui/UIActorMenuDeadBodySearch.cpp
+++ b/src/xrGame/ui/UIActorMenuDeadBodySearch.cpp
@@ -64,7 +64,7 @@ void CUIActorMenu::InitDeadBodySearchMode()
TIItemContainer items_list;
if (m_pPartnerInvOwner)
{
- m_pPartnerInvOwner->inventory().AddAvailableItems(items_list, false); // true
+ m_pPartnerInvOwner->inventory().AddAvailableItems(items_list, false, m_pPartnerInvOwner->is_alive());
UpdatePartnerBag();
}
else
@@ -87,7 +87,7 @@ void CUIActorMenu::InitDeadBodySearchMode()
CBaseMonster* monster = smart_cast(m_pPartnerInvOwner);
// only for partner, box = no, monster = no
- if (m_pPartnerInvOwner && !monster)
+ if (m_pPartnerInvOwner && !monster && !m_pPartnerInvOwner->is_alive())
{
CInfoPortionWrapper known_info_registry;
known_info_registry.registry().init(m_pPartnerInvOwner->object_id());
diff --git a/src/xrGame/ui/UIActorMenuInventory.cpp b/src/xrGame/ui/UIActorMenuInventory.cpp
index c6a93120948..0d1ec74e450 100644
--- a/src/xrGame/ui/UIActorMenuInventory.cpp
+++ b/src/xrGame/ui/UIActorMenuInventory.cpp
@@ -34,6 +34,7 @@
#include "CustomDetector.h"
#include "PDA.h"
#include "actor_defs.h"
+#include "script_game_object_impl.h"
void move_item_from_to(u16 from_id, u16 to_id, u16 what_id);
@@ -466,8 +467,15 @@ void CUIActorMenu::InitInventoryContents(CUIDragDropListEx* pBagList, bool onlyB
InitCellForSlot(ARTEFACT_SLOT);
if (!m_pActorInvOwner->inventory().SlotIsPersistent(PDA_SLOT))
InitCellForSlot(PDA_SLOT);
- if (!m_pActorInvOwner->inventory().SlotIsPersistent(TORCH_SLOT))
- InitCellForSlot(TORCH_SLOT); //Alundaio: TODO find out why this crash when you unequip
+ //if (!m_pActorInvOwner->inventory().SlotIsPersistent(TORCH_SLOT))
+ // InitCellForSlot(TORCH_SLOT); // Alundaio: TODO find out why this crash when you unequip
+
+ //for custom slots that exist past LAST_SLOT
+ for (u16 i = SLOTS_COUNT; i <= m_pActorInvOwner->inventory().LastSlot(); ++i)
+ {
+ if (!m_pActorInvOwner->inventory().SlotIsPersistent(i))
+ InitCellForSlot(i);
+ }
//-Alundaio
curr_list = m_pLists[eInventoryBeltList];
@@ -507,6 +515,30 @@ bool CUIActorMenu::TryActiveSlot(CUICellItem* itm)
return false;
}
+bool CUIActorMenu::ToSlotScript(CScriptGameObject* GO, bool force_place, u16 slot_id)
+{
+ CInventoryItem* iitem = smart_cast(GO->object().dcast_GameObject());
+
+ if (!iitem || !m_pActorInvOwner->inventory().InRuck(iitem))
+ return false;
+
+ CUIDragDropListEx* invlist = GetListByType(iActorBag);
+ CUICellContainer* c = invlist->GetContainer();
+ auto& child_list = c->GetChildWndList();
+
+ for (CUIWindow* it : child_list)
+ {
+ CUICellItem* i = static_cast(it);
+ PIItem pitm = static_cast(i->m_pData);
+ if (pitm == iitem)
+ {
+ ToSlot(i, force_place, slot_id);
+ return true;
+ }
+ }
+ return false;
+}
+
bool CUIActorMenu::ToSlot(CUICellItem* itm, bool force_place, u16 slot_id)
{
CUIDragDropListEx* old_owner = itm->OwnerList();
@@ -546,7 +578,7 @@ bool CUIActorMenu::ToSlot(CUICellItem* itm, bool force_place, u16 slot_id)
}
}
- [[maybe_unused]] bool result = !b_own_item || m_pActorInvOwner->inventory().Slot(slot_id, iitem);
+ [[maybe_unused]] const bool result = !b_own_item || m_pActorInvOwner->inventory().Slot(slot_id, iitem);
VERIFY(result);
CUICellItem* i = old_owner->RemoveItem(itm, (old_owner == new_owner));
@@ -681,6 +713,30 @@ bool CUIActorMenu::ToBag(CUICellItem* itm, bool b_use_cursor_pos)
return false;
}
+bool CUIActorMenu::ToBeltScript(CScriptGameObject* GO, bool b_use_cursor_pos)
+{
+ CInventoryItem* iitem = smart_cast(GO->object().dcast_GameObject());
+
+ if (!iitem || !m_pActorInvOwner->inventory().InRuck(iitem))
+ return false;
+
+ CUIDragDropListEx* invlist = GetListByType(iActorBag);
+ CUICellContainer* c = invlist->GetContainer();
+ auto child_list = c->GetChildWndList();
+
+ for (CUIWindow* it : child_list)
+ {
+ CUICellItem* i = static_cast(it);
+ PIItem pitm = static_cast(i->m_pData);
+ if (pitm == iitem)
+ {
+ ToBelt(i, b_use_cursor_pos);
+ return true;
+ }
+ }
+ return false;
+}
+
bool CUIActorMenu::ToBelt(CUICellItem* itm, bool b_use_cursor_pos)
{
PIItem iitem = (PIItem)itm->m_pData;
@@ -767,7 +823,7 @@ CUIDragDropListEx* CUIActorMenu::GetSlotList(u16 slot_idx)
case ARTEFACT_SLOT:
case BINOCULAR_SLOT:
- case GRENADE_SLOT: // fake
+ default:
if (m_currMenuMode == mmTrade)
{
return m_pLists[eTradeActorBagList];
@@ -934,8 +990,8 @@ void CUIActorMenu::PropertiesBoxForSlots(PIItem item, bool& b_show)
bool bAlreadyDressed = false;
u16 cur_slot = item->BaseSlot();
- if (!pOutfit && !pHelmet && cur_slot != NO_ACTIVE_SLOT && !inv.SlotIsPersistent(cur_slot) && m_pActorInvOwner->
- inventory().ItemFromSlot(cur_slot) != item /*&& inv.CanPutInSlot(item, cur_slot)*/)
+ if (!pOutfit && !pHelmet && cur_slot != NO_ACTIVE_SLOT && !inv.SlotIsPersistent(cur_slot) &&
+ inv.ItemFromSlot(cur_slot) != item /*&& inv.CanPutInSlot(item, cur_slot)*/)
{
m_UIPropertiesBox->AddItem("st_move_to_slot", NULL, INVENTORY_TO_SLOT_ACTION);
b_show = true;
@@ -952,7 +1008,8 @@ void CUIActorMenu::PropertiesBoxForSlots(PIItem item, bool& b_show)
{
if (!pHelmet)
{
- if (m_currMenuMode == mmDeadBodySearch)
+ const bool has_translation = StringTable().translate("st_unequip", nullptr);
+ if (m_currMenuMode == mmDeadBodySearch || !has_translation)
m_UIPropertiesBox->AddItem("st_move_to_bag", nullptr, INVENTORY_TO_BAG_ACTION);
else
m_UIPropertiesBox->AddItem("st_unequip", nullptr, INVENTORY_TO_BAG_ACTION);
@@ -1138,7 +1195,7 @@ void CUIActorMenu::PropertiesBoxForUsing(PIItem item, bool& b_show)
shared_str section_name = GO->cNameSect();
//ability to set eat string from settings
- act_str = READ_IF_EXISTS(pSettings, r_string, section_name, "default_use_text", 0);
+ act_str = READ_IF_EXISTS(pSettings, r_string, section_name, "default_use_text", nullptr);
if (act_str)
{
m_UIPropertiesBox->AddItem(act_str, nullptr, INVENTORY_EAT_ACTION);
@@ -1174,35 +1231,67 @@ void CUIActorMenu::PropertiesBoxForUsing(PIItem item, bool& b_show)
}
//1st Custom Use action
- act_str = READ_IF_EXISTS(pSettings, r_string, section_name, "use1_text", 0);
- if (act_str)
+ pcstr functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use1_functor", nullptr);
+ if (functor_name)
{
- m_UIPropertiesBox->AddItem(act_str, nullptr, INVENTORY_EAT2_ACTION);
- b_show = true;
+ luabind::functor funct1;
+ if (GEnv.ScriptEngine->functor(functor_name, funct1))
+ {
+ act_str = funct1(GO->lua_game_object());
+ if (act_str)
+ {
+ m_UIPropertiesBox->AddItem(act_str, nullptr, INVENTORY_EAT2_ACTION);
+ b_show = true;
+ }
+ }
}
- //2nd Custom Use action
- act_str = READ_IF_EXISTS(pSettings, r_string, section_name, "use2_text", 0);
- if (act_str)
+ // 2nd Custom Use action
+ functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use2_functor", nullptr);
+ if (functor_name)
{
- m_UIPropertiesBox->AddItem(act_str, nullptr, INVENTORY_EAT3_ACTION);
- b_show = true;
+ luabind::functor funct1;
+ if (GEnv.ScriptEngine->functor(functor_name, funct1))
+ {
+ act_str = funct1(GO->lua_game_object());
+ if (act_str)
+ {
+ m_UIPropertiesBox->AddItem(act_str, nullptr, INVENTORY_EAT3_ACTION);
+ b_show = true;
+ }
+ }
}
- //3rd Custom Use action
- act_str = READ_IF_EXISTS(pSettings, r_string, section_name, "use3_text", 0);
- if (act_str)
+ // 3rd Custom Use action
+ functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use3_functor", nullptr);
+ if (functor_name)
{
- m_UIPropertiesBox->AddItem(act_str, nullptr, INVENTORY_EAT4_ACTION);
- b_show = true;
+ luabind::functor funct1;
+ if (GEnv.ScriptEngine->functor(functor_name, funct1))
+ {
+ act_str = funct1(GO->lua_game_object());
+ if (act_str)
+ {
+ m_UIPropertiesBox->AddItem(act_str, nullptr, INVENTORY_EAT4_ACTION);
+ b_show = true;
+ }
+ }
}
- //4th Custom Use action
- act_str = READ_IF_EXISTS(pSettings, r_string, section_name, "use4_text", 0);
- if (act_str)
+ // 4th Custom Use action
+ functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use4_functor", nullptr);
+ if (functor_name)
{
- m_UIPropertiesBox->AddItem(act_str, nullptr, INVENTORY_EAT5_ACTION);
- b_show = true;
+ luabind::functor funct1;
+ if (GEnv.ScriptEngine->functor(functor_name, funct1))
+ {
+ act_str = funct1(GO->lua_game_object());
+ if (act_str)
+ {
+ m_UIPropertiesBox->AddItem(act_str, nullptr, INVENTORY_EAT5_ACTION);
+ b_show = true;
+ }
+ }
}
}
@@ -1247,8 +1336,11 @@ void CUIActorMenu::PropertiesBoxForRepair(PIItem item, bool& b_show)
//Alundaio: Ability to donate item during trade
void CUIActorMenu::PropertiesBoxForDonate(PIItem item, bool& b_show)
{
- m_UIPropertiesBox->AddItem("st_donate", nullptr, INVENTORY_DONATE_ACTION);
- b_show = true;
+ if (!item->IsQuestItem())
+ {
+ m_UIPropertiesBox->AddItem("st_donate", nullptr, INVENTORY_DONATE_ACTION);
+ b_show = true;
+ }
}
//-Alundaio
@@ -1271,9 +1363,8 @@ void CUIActorMenu::ProcessPropertiesBoxClicked(CUIWindow* w, void* d)
case INVENTORY_EAT_ACTION: TryUseItem(cell_item); break;
case INVENTORY_EAT2_ACTION:
{
- CGameObject* GO = smart_cast(item);
- const pcstr functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use1_functor", 0);
- if (functor_name)
+ const CGameObject* GO = smart_cast(item);
+ if (cpcstr functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use1_action_functor", nullptr))
{
luabind::functor funct1;
if (GEnv.ScriptEngine->functor(functor_name, funct1))
@@ -1286,9 +1377,8 @@ void CUIActorMenu::ProcessPropertiesBoxClicked(CUIWindow* w, void* d)
}
case INVENTORY_EAT3_ACTION:
{
- CGameObject* GO = smart_cast(item);
- const pcstr functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use2_functor", 0);
- if (functor_name)
+ const CGameObject* GO = smart_cast(item);
+ if (cpcstr functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use2_action_functor", nullptr))
{
luabind::functor funct2;
if (GEnv.ScriptEngine->functor(functor_name, funct2))
@@ -1301,9 +1391,8 @@ void CUIActorMenu::ProcessPropertiesBoxClicked(CUIWindow* w, void* d)
}
case INVENTORY_EAT4_ACTION:
{
- CGameObject* GO = smart_cast(item);
- const pcstr functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use3_functor", 0);
- if (functor_name)
+ const CGameObject* GO = smart_cast(item);
+ if (cpcstr functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use3_action_functor", nullptr))
{
luabind::functor funct3;
if (GEnv.ScriptEngine->functor(functor_name, funct3))
@@ -1316,9 +1405,8 @@ void CUIActorMenu::ProcessPropertiesBoxClicked(CUIWindow* w, void* d)
}
case INVENTORY_EAT5_ACTION:
{
- CGameObject* GO = smart_cast(item);
- const pcstr functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use4_functor", 0);
- if (functor_name)
+ const CGameObject* GO = smart_cast(item);
+ if (cpcstr functor_name = READ_IF_EXISTS(pSettings, r_string, GO->cNameSect(), "use4_action_functor", nullptr))
{
luabind::functor funct4;
if (GEnv.ScriptEngine->functor(functor_name, funct4))
diff --git a/src/xrGame/ui/UIActorMenu_action.cpp b/src/xrGame/ui/UIActorMenu_action.cpp
index 9665c7b9c92..22e546ee4b1 100644
--- a/src/xrGame/ui/UIActorMenu_action.cpp
+++ b/src/xrGame/ui/UIActorMenu_action.cpp
@@ -254,8 +254,10 @@ bool CUIActorMenu::OnItemDbClick(CUICellItem* itm)
ToBag(itm, false);
}
else if (!ToSlot(itm, false, iitem_to_place->BaseSlot()))
+ {
if (!ToBelt(itm, false))
ToSlot(itm, true, iitem_to_place->BaseSlot());
+ }
break;
}
case iActorBelt:
@@ -319,6 +321,16 @@ bool CUIActorMenu::OnItemFocusReceive(CUICellItem* itm)
itm->m_selected = true;
set_highlight_item(itm);
+
+ luabind::functor funct1;
+ if (GEnv.ScriptEngine->functor("actor_menu_inventory.CUIActorMenu_OnItemFocusReceive", funct1))
+ {
+ PIItem _iitem = (PIItem)itm->m_pData;
+
+ const CGameObject* GO = _iitem ? smart_cast(_iitem) : nullptr;
+ if (GO)
+ funct1(GO->lua_game_object());
+ }
return true;
}
@@ -331,6 +343,16 @@ bool CUIActorMenu::OnItemFocusLost(CUICellItem* itm)
InfoCurItem(NULL);
clear_highlight_lists();
+ luabind::functor funct1;
+ if (GEnv.ScriptEngine->functor("actor_menu_inventory.CUIActorMenu_OnItemFocusLost", funct1))
+ {
+ PIItem _iitem = (PIItem)itm->m_pData;
+
+ const CGameObject* GO = _iitem ? smart_cast(_iitem) : nullptr;
+ if (GO)
+ funct1(GO->lua_game_object());
+ }
+
return true;
}
diff --git a/src/xrGame/ui/UIActorMenu_script.cpp b/src/xrGame/ui/UIActorMenu_script.cpp
index 1ba0054ef09..c0a28730a6c 100644
--- a/src/xrGame/ui/UIActorMenu_script.cpp
+++ b/src/xrGame/ui/UIActorMenu_script.cpp
@@ -135,6 +135,8 @@ SCRIPT_EXPORT(CUIActorMenu, (CUIDialogWnd),
.def("IsShown", &CUIActorMenu::IsShown)
.def("ShowDialog", &CUIActorMenu::ShowDialog)
.def("HideDialog", &CUIActorMenu::HideDialog)
+ .def("ToSlot", &CUIActorMenu::ToSlotScript)
+ .def("ToBelt", &CUIActorMenu::ToBeltScript)
];
using namespace luabind;
@@ -159,7 +161,9 @@ SCRIPT_EXPORT(CUIPdaWnd, (CUIDialogWnd),
.def("IsShown", &CUIPdaWnd::IsShown)
.def("ShowDialog", &CUIPdaWnd::ShowDialog)
.def("HideDialog", &CUIPdaWnd::HideDialog)
- .def("SetActiveSubdialog", &CUIPdaWnd::SetActiveSubdialog_script)
+ .def("SetActiveSubdialog", +[](CUIPdaWnd* self, pcstr section) { self->SetActiveSubdialog(section); })
+ .def("SetActiveDialog", &CUIPdaWnd::SetActiveDialog)
+ .def("GetActiveDialog", &CUIPdaWnd::GetActiveDialog)
.def("GetActiveSection", &CUIPdaWnd::GetActiveSection)
.def("GetTabControl", &CUIPdaWnd::GetTabControl)
];
diff --git a/src/xrGame/ui/UICellCustomItems.cpp b/src/xrGame/ui/UICellCustomItems.cpp
index 8db40782a01..da179462e93 100644
--- a/src/xrGame/ui/UICellCustomItems.cpp
+++ b/src/xrGame/ui/UICellCustomItems.cpp
@@ -10,6 +10,8 @@
namespace detail
{
+static constexpr pcstr ICON_LAYER_FIELD = "icon_layer";
+
struct is_helper_pred
{
bool operator()(CUICellItem* child) { return child->IsHelper(); }
@@ -30,6 +32,43 @@ CUIInventoryCellItem::CUIInventoryCellItem(CInventoryItem* itm)
inherited::SetTextureRect(rect);
inherited::SetStretchTexture(true);
+
+ //Alundaio; Layered icon
+ for (u8 i = 0; i < 255; ++i)
+ {
+ string32 layer_str;
+ xr_sprintf(layer_str, "%u%s", i, detail::ICON_LAYER_FIELD);
+ if (!pSettings->line_exist(itm->m_section_id, layer_str))
+ break;
+
+ cpcstr section = pSettings->r_string(itm->m_section_id, layer_str);
+ if (!section)
+ continue;
+
+ string32 temp;
+ const Fvector2 offset
+ {
+ pSettings->r_float(itm->m_section_id, strconcat(temp, layer_str, "_x")),
+ pSettings->r_float(itm->m_section_id, strconcat(temp, layer_str, "_y"))
+ };
+
+ cpcstr field_scale = strconcat(temp, layer_str, "_scale");
+ const float scale = pSettings->read_if_exists(itm->m_section_id, field_scale, 1.0f);
+
+ //cpcstr field_color = strconcat(temp, layer_str, "_color");
+ //const u32 color = READ_IF_EXISTS(pSettings, r_color, itm->m_section_id, field_color, 0);
+
+ CreateLayer(section, offset, scale);
+ }
+ //-Alundaio
+}
+
+void CUIInventoryCellItem::OnAfterChild(CUIDragDropListEx* parent_list)
+{
+ for (SIconLayer* layer : m_layers)
+ {
+ layer->m_icon = InitLayer(layer->m_icon, layer->m_name, layer->offset, parent_list->GetVerticalPlacement(), layer->m_scale);
+ }
}
bool CUIInventoryCellItem::EqualTo(CUICellItem* itm)
@@ -61,11 +100,136 @@ bool CUIInventoryCellItem::IsHelperOrHasHelperChild()
CUIDragItem* CUIInventoryCellItem::CreateDragItem()
{
- return IsHelperOrHasHelperChild() ? NULL : inherited::CreateDragItem();
+ if (IsHelperOrHasHelperChild())
+ return nullptr;
+
+ CUIDragItem* i = inherited::CreateDragItem();
+
+ for (const SIconLayer* layer : m_layers)
+ {
+ CUIStatic* s = xr_new("Layer");
+ s->SetAutoDelete(true);
+ s->SetShader(InventoryUtilities::GetEquipmentIconsShader());
+ InitLayer(s, layer->m_name, layer->offset, false, layer->m_scale);
+ s->SetTextureColor(i->wnd()->GetTextureColor());
+ i->wnd()->AttachChild(s);
+ }
+
+ return i;
+}
+
+void CUIInventoryCellItem::SetTextureColor(u32 color)
+{
+ inherited::SetTextureColor(color);
+ for (const SIconLayer* layer : m_layers)
+ {
+ if (layer->m_icon)
+ layer->m_icon->SetTextureColor(color);
+ }
}
bool CUIInventoryCellItem::IsHelper() { return object()->is_helper_item(); }
void CUIInventoryCellItem::SetIsHelper(bool is_helper) { object()->set_is_helper(is_helper); }
+
+//Alundaio
+void CUIInventoryCellItem::RemoveLayer(const SIconLayer* layer)
+{
+ for (auto it = m_layers.begin(); m_layers.end() != it; ++it)
+ {
+ if ((*it) == layer)
+ {
+ DetachChild((*it)->m_icon);
+ m_layers.erase(it);
+ break;
+ }
+ }
+}
+
+void CUIInventoryCellItem::CreateLayer(pcstr section, Fvector2 offset, float scale)
+{
+ SIconLayer* layer = xr_new();
+ layer->m_name = section;
+ layer->offset = offset;
+ //layer->m_color = color;
+ layer->m_scale = scale;
+ m_layers.push_back(layer);
+}
+
+CUIStatic* CUIInventoryCellItem::InitLayer(CUIStatic* s, pcstr section,
+ Fvector2 addon_offset, bool b_rotate, float scale)
+{
+ if (!s)
+ {
+ s = xr_new("Layer");
+ s->SetAutoDelete(true);
+ AttachChild(s);
+ s->SetShader(InventoryUtilities::GetEquipmentIconsShader());
+ s->SetTextureColor(GetTextureColor());
+ }
+
+ Fvector2 base_scale;
+
+ if (Heading())
+ {
+ base_scale.x = (GetHeight() / (INV_GRID_WIDTHF * m_grid_size.x)) * scale;
+ base_scale.y = (GetWidth() / (INV_GRID_HEIGHTF * m_grid_size.y)) * scale;
+ }
+ else
+ {
+ base_scale.x = (GetWidth() / (INV_GRID_WIDTHF * m_grid_size.x)) * scale;
+ base_scale.y = (GetHeight() / (INV_GRID_HEIGHTF * m_grid_size.y)) * scale;
+ }
+ Fvector2 cell_size
+ {
+ pSettings->r_float(section, "inv_grid_width") * INV_GRID_WIDTHF,
+ pSettings->r_float(section, "inv_grid_height") * INV_GRID_HEIGHTF
+ };
+
+ Frect tex_rect
+ {
+ pSettings->r_float(section, "inv_grid_x") * INV_GRID_WIDTHF,
+ pSettings->r_float(section, "inv_grid_y") * INV_GRID_HEIGHTF
+ };
+
+ tex_rect.rb.add(tex_rect.lt, cell_size);
+
+ cell_size.mul(base_scale);
+
+ if (b_rotate)
+ {
+ s->SetWndSize(Fvector2{ cell_size.y, cell_size.x });
+
+ const Fvector2 new_offset
+ {
+ addon_offset.y * base_scale.x,
+ GetHeight() - addon_offset.x * base_scale.x - cell_size.x
+ };
+ addon_offset = new_offset;
+ addon_offset.x *= UICore::get_current_kx();
+ }
+ else
+ {
+ s->SetWndSize(cell_size);
+ addon_offset.mul(base_scale);
+ }
+
+ s->SetWndPos(addon_offset);
+ s->SetTextureRect(tex_rect);
+ s->SetStretchTexture(true);
+
+ s->EnableHeading(b_rotate);
+
+ if (b_rotate)
+ {
+ s->SetHeading(GetHeading());
+ const Fvector2 offs{ 0.0f, s->GetWndSize().y };
+ s->SetHeadingPivot(Fvector2{ 0.0f, 0.0f }, /*Fvector2{ 0.0f, 0.0f }*/offs, true);
+ }
+
+ return s;
+}
+//-Alundaio
+
void CUIInventoryCellItem::Update()
{
inherited::Update();
@@ -83,6 +247,12 @@ void CUIInventoryCellItem::Update()
}
SetTextureColor(color);
+
+ for (SIconLayer* layer : m_layers)
+ {
+ layer->m_icon = InitLayer(layer->m_icon, layer->m_name, layer->offset, Heading(), layer->m_scale);
+ layer->m_icon->SetTextureColor(color);
+ }
}
void CUIInventoryCellItem::UpdateItemText()
diff --git a/src/xrGame/ui/UICellCustomItems.h b/src/xrGame/ui/UICellCustomItems.h
index 765dfe98680..bdc2655a8d0 100644
--- a/src/xrGame/ui/UICellCustomItems.h
+++ b/src/xrGame/ui/UICellCustomItems.h
@@ -2,10 +2,21 @@
#include "UICellItem.h"
#include "Weapon.h"
+struct SIconLayer
+{
+ pcstr m_name;
+ CUIStatic* m_icon;
+ Fvector2 offset;
+ //u32 m_color;
+ float m_scale;
+};
+
class CUIInventoryCellItem : public CUICellItem
{
typedef CUICellItem inherited;
+ xr_vector m_layers;
+
public:
CUIInventoryCellItem(CInventoryItem* itm);
@@ -18,6 +29,15 @@ class CUIInventoryCellItem : public CUICellItem
void Update();
CInventoryItem* object() { return (CInventoryItem*)m_pData; }
+ //Alundaio
+ void OnAfterChild(CUIDragDropListEx* parent_list) override;
+ void SetTextureColor(u32 color) override;
+
+ void RemoveLayer(const SIconLayer* layer);
+ void CreateLayer(pcstr name, Fvector2 offset, float scale);
+ CUIStatic* InitLayer(CUIStatic* s, pcstr section, Fvector2 addon_offset, bool b_rotate, float scale);
+ //-Alundaio
+
pcstr GetDebugType() override { return "CUIInventoryCellItem"; }
};
diff --git a/src/xrGame/ui/UICellItem.cpp b/src/xrGame/ui/UICellItem.cpp
index 1e2997c3bf3..9df84efd5e9 100644
--- a/src/xrGame/ui/UICellItem.cpp
+++ b/src/xrGame/ui/UICellItem.cpp
@@ -226,7 +226,7 @@ void CUICellItem::UpdateConditionProgressBar()
if (eitm)
{
const u8 max_uses = eitm->GetMaxUses();
- if (max_uses > 1)
+ if (max_uses > 0)
{
const u8 remaining_uses = eitm->GetRemainingUses();
diff --git a/src/xrGame/ui/UICellItem.h b/src/xrGame/ui/UICellItem.h
index f07254b0092..8c8c8925a81 100644
--- a/src/xrGame/ui/UICellItem.h
+++ b/src/xrGame/ui/UICellItem.h
@@ -86,6 +86,7 @@ class CUICellItem : public CUIStatic
bool m_b_destroy_childs;
bool m_selected;
bool m_select_armament;
+ bool m_select_equipped{};
bool m_cur_mark;
bool m_has_upgrade;
};
diff --git a/src/xrGame/ui/UIDialogWnd.cpp b/src/xrGame/ui/UIDialogWnd.cpp
index 132dcd8f341..e0c17835af9 100644
--- a/src/xrGame/ui/UIDialogWnd.cpp
+++ b/src/xrGame/ui/UIDialogWnd.cpp
@@ -80,6 +80,6 @@ void CUIDialogWnd::ShowDialog(bool bDoHideIndicators)
void CUIDialogWnd::HideDialog()
{
- if (IsShown())
+ if (GetHolder() && IsShown())
GetHolder()->StopDialog(this);
}
diff --git a/src/xrGame/ui/UIDragDropListEx.cpp b/src/xrGame/ui/UIDragDropListEx.cpp
index ae8f760dd46..4bba28ea491 100644
--- a/src/xrGame/ui/UIDragDropListEx.cpp
+++ b/src/xrGame/ui/UIDragDropListEx.cpp
@@ -8,6 +8,8 @@
#include "Inventory.h"
//-Alundaio
+extern int g_inv_highlight_equipped;
+
CUIDragItem* CUIDragDropListEx::m_drag_item = NULL;
void CUICell::Clear()
@@ -650,11 +652,14 @@ bool CUICellContainer::AddSimilar(CUICellItem* itm)
return false;
//Alundaio: Don't stack equipped items
- extern int g_inv_highlight_equipped;
- if (g_inv_highlight_equipped)
+ PIItem iitem = (PIItem)itm->m_pData;
+ if (iitem && iitem->m_pInventory)
{
- const PIItem iitem = static_cast(itm->m_pData);
- if (iitem && iitem->m_pInventory && iitem->m_pInventory->ItemFromSlot(iitem->BaseSlot()) == iitem)
+ if (g_inv_highlight_equipped)
+ if (iitem->m_pInventory->ItemFromSlot(iitem->BaseSlot()) == iitem)
+ return false;
+
+ if (pSettings->line_exist(iitem->m_section_id, "dont_stack") && pSettings->r_bool(iitem->m_section_id, "dont_stack"))
return false;
}
//-Alundaio
@@ -673,19 +678,20 @@ CUICellItem* CUICellContainer::FindSimilar(CUICellItem* itm)
{
for (auto& it : m_ChildWndList)
{
- // XXX: Xottab_DUTY: find out why different casts used for different configurations
- // and maybe use only one cast
#ifdef DEBUG
auto i = smart_cast(it);
#else
auto i = (CUICellItem*)it;
#endif
//Alundaio: Don't stack equipped items
- extern int g_inv_highlight_equipped;
- if (g_inv_highlight_equipped)
+ PIItem iitem = (PIItem)i->m_pData;
+ if (iitem && iitem->m_pInventory)
{
- auto iitem = static_cast(i->m_pData);
- if (iitem && iitem->m_pInventory && iitem->m_pInventory->ItemFromSlot(iitem->BaseSlot()) == iitem)
+ if (g_inv_highlight_equipped)
+ if (iitem->m_pInventory->ItemFromSlot(iitem->BaseSlot()) == iitem)
+ continue;
+
+ if (pSettings->line_exist(iitem->m_section_id, "dont_stack") && pSettings->r_bool(iitem->m_section_id, "dont_stack"))
continue;
}
//-Alundaio
@@ -1078,18 +1084,8 @@ void CUICellContainer::Draw()
select_mode = 1;
else if (ui_cell.m_item->m_select_armament)
select_mode = 3;
- else
- {
- //Alundaio: Highlight equipped items
- extern int g_inv_highlight_equipped;
- if (g_inv_highlight_equipped)
- {
- PIItem iitem = static_cast(ui_cell.m_item->m_pData);
- if (iitem && iitem->m_pInventory && iitem->m_pInventory->ItemFromSlot(iitem->BaseSlot()) == iitem)
- select_mode = 2;
- }
- //-Alundaio
- }
+ else if (ui_cell.m_item->m_select_equipped && g_inv_highlight_equipped)
+ select_mode = 2;
}
Fvector2 tp;
diff --git a/src/xrGame/ui/UIInventoryUtilities.cpp b/src/xrGame/ui/UIInventoryUtilities.cpp
index 17b818c0a20..672124bf6c3 100644
--- a/src/xrGame/ui/UIInventoryUtilities.cpp
+++ b/src/xrGame/ui/UIInventoryUtilities.cpp
@@ -331,9 +331,10 @@ LPCSTR InventoryUtilities::GetTimePeriodAsString(pstr _buff, u32 buff_sz, ALife:
int cnt = 0;
_buff[0] = 0;
- if (month1 != month2)
- cnt = xr_sprintf(
- _buff + cnt, buff_sz - cnt, "%d %s ", month2 - month1, *StringTable().translate("ui_st_months"));
+ u8 yrdiff = ((year2 - year1) * 12);
+
+ if (month1 != month2 || yrdiff > 0)
+ cnt = xr_sprintf(_buff + cnt, buff_sz - cnt, "%d %s", month2 + (yrdiff - month1), *CStringTable().translate("ui_st_months"));
if (!cnt && day1 != day2)
cnt = xr_sprintf(_buff + cnt, buff_sz - cnt, "%d %s", day2 - day1, *StringTable().translate("ui_st_days"));
diff --git a/src/xrGame/ui/UIItemInfo.cpp b/src/xrGame/ui/UIItemInfo.cpp
index eb93af24b81..d613444d4d0 100644
--- a/src/xrGame/ui/UIItemInfo.cpp
+++ b/src/xrGame/ui/UIItemInfo.cpp
@@ -280,7 +280,7 @@ void CUIItemInfo::InitItem(CUICellItem* pCellItem, CInventoryItem* pCompareItem,
}
TryAddConditionInfo(*pInvItem, pCompareItem);
TryAddWpnInfo(*pInvItem, pCompareItem);
- TryAddArtefactInfo(pInvItem->object().cNameSect());
+ TryAddArtefactInfo(*pInvItem);
TryAddOutfitInfo(*pInvItem, pCompareItem);
TryAddUpgradeInfo(*pInvItem);
TryAddBoosterInfo(*pInvItem);
@@ -350,14 +350,14 @@ void CUIItemInfo::TryAddWpnInfo(CInventoryItem& pInvItem, CInventoryItem* pCompa
}
}
-void CUIItemInfo::TryAddArtefactInfo(const shared_str& af_section)
+void CUIItemInfo::TryAddArtefactInfo(CInventoryItem& pInvItem)
{
if (!UIArtefactParams)
return;
- if (UIArtefactParams->Check(af_section))
+ if (UIArtefactParams->Check(pInvItem.object().cNameSect()))
{
- UIArtefactParams->SetInfo(af_section);
+ UIArtefactParams->SetInfo(pInvItem);
UIDesc->AddWindow(UIArtefactParams, false);
}
}
diff --git a/src/xrGame/ui/UIItemInfo.h b/src/xrGame/ui/UIItemInfo.h
index 2335b6e70dc..0479347c5bb 100644
--- a/src/xrGame/ui/UIItemInfo.h
+++ b/src/xrGame/ui/UIItemInfo.h
@@ -43,7 +43,7 @@ class CUIItemInfo final : public CUIWindow
void TryAddConditionInfo(CInventoryItem& pInvItem, CInventoryItem* pCompareItem);
void TryAddWpnInfo(CInventoryItem& pInvItem, CInventoryItem* pCompareItem);
- void TryAddArtefactInfo(const shared_str& af_section);
+ void TryAddArtefactInfo(CInventoryItem& pInvItem);
void TryAddOutfitInfo(CInventoryItem& pInvItem, CInventoryItem* pCompareItem);
void TryAddUpgradeInfo(CInventoryItem& pInvItem);
void TryAddBoosterInfo(CInventoryItem& pInvItem);
diff --git a/src/xrGame/ui/UIMap.cpp b/src/xrGame/ui/UIMap.cpp
index 196ff37f51e..9e88f0ac3b3 100644
--- a/src/xrGame/ui/UIMap.cpp
+++ b/src/xrGame/ui/UIMap.cpp
@@ -552,9 +552,7 @@ void CUILevelMap::SendMessage(CUIWindow* pWnd, s16 msg, void* pData)
}
}
else if (msg == MAP_HIDE_HINT)
- {
MapWnd()->HideHint(pWnd);
- }
else if (msg == MAP_SELECT_SPOT)
MapWnd()->SpotSelected(pWnd);
else if (msg == MAP_SELECT_SPOT2)
diff --git a/src/xrGame/ui/UIMapWnd.cpp b/src/xrGame/ui/UIMapWnd.cpp
index d60f258202e..5b254347114 100644
--- a/src/xrGame/ui/UIMapWnd.cpp
+++ b/src/xrGame/ui/UIMapWnd.cpp
@@ -597,7 +597,7 @@ void CUIMapWnd::ActivatePropertiesBox(CUIWindow* w)
luabind::functor funct;
if (GEnv.ScriptEngine->functor("pda.property_box_add_properties", funct))
{
- funct(m_UIPropertiesBox, m_cur_location->ObjectID(), (LPCSTR)m_cur_location->GetLevelName().c_str(), m_cur_location);
+ funct(m_UIPropertiesBox, m_cur_location->ObjectID(), (LPCSTR)m_cur_location->GetLevelName().c_str(), m_cur_location->GetHint());
}
// Только для меток игрока
diff --git a/src/xrGame/ui/UIMapWnd.h b/src/xrGame/ui/UIMapWnd.h
index 1407512fe4d..2df2673de0b 100644
--- a/src/xrGame/ui/UIMapWnd.h
+++ b/src/xrGame/ui/UIMapWnd.h
@@ -19,6 +19,7 @@ class CMapSpot;
class CGameTask;
class CUIXml;
class UIHint;
+class CUIPropertiesBox;
using GAME_MAPS = xr_map;
diff --git a/src/xrGame/ui/UIOutfitInfo.cpp b/src/xrGame/ui/UIOutfitInfo.cpp
index 56e77d070aa..356d377e672 100644
--- a/src/xrGame/ui/UIOutfitInfo.cpp
+++ b/src/xrGame/ui/UIOutfitInfo.cpp
@@ -10,32 +10,18 @@
#include "player_hud.h"
#include "UIHelper.h"
-constexpr cpcstr immunity_names[] =
+constexpr std::tuple immunity_names[] =
{
- "burn_immunity",
- "shock_immunity",
- "chemical_burn_immunity",
- "radiation_immunity",
- "telepatic_immunity",
- "wound_immunity",
- "fire_wound_immunity",
- "strike_immunity",
- "explosion_immunity",
- nullptr
-};
-
-constexpr cpcstr immunity_st_names[] =
-{
- "ui_inv_outfit_burn_protection",
- "ui_inv_outfit_shock_protection",
- "ui_inv_outfit_chemical_burn_protection",
- "ui_inv_outfit_radiation_protection",
- "ui_inv_outfit_telepatic_protection",
- "ui_inv_outfit_wound_protection",
- "ui_inv_outfit_fire_wound_protection",
- "ui_inv_outfit_strike_protection",
- "ui_inv_outfit_explosion_protection",
- nullptr
+ // { hit type, "immunity", "immunity text" }
+ { ALife::eHitTypeBurn, "burn_immunity", "ui_inv_outfit_burn_protection" },
+ { ALife::eHitTypeShock, "shock_immunity", "ui_inv_outfit_shock_protection" },
+ { ALife::eHitTypeChemicalBurn, "chemical_burn_immunity", "ui_inv_outfit_chemical_burn_protection" },
+ { ALife::eHitTypeRadiation, "radiation_immunity", "ui_inv_outfit_radiation_protection" },
+ { ALife::eHitTypeTelepatic, "telepatic_immunity", "ui_inv_outfit_telepatic_protection" },
+ { ALife::eHitTypeStrike, "strike_immunity", "ui_inv_outfit_strike_protection" },
+ { ALife::eHitTypeWound, "wound_immunity", "ui_inv_outfit_wound_protection" },
+ { ALife::eHitTypeExplosion, "explosion_immunity", "ui_inv_outfit_explosion_protection" },
+ { ALife::eHitTypeFireWound, "fire_wound_immunity", "ui_inv_outfit_fire_wound_protection" },
};
CUIOutfitImmunity::CUIOutfitImmunity()
@@ -47,23 +33,23 @@ CUIOutfitImmunity::CUIOutfitImmunity()
m_magnitude = 1.0f;
}
-bool CUIOutfitImmunity::InitFromXml(CUIXml& xml_doc, LPCSTR base_str, u32 hit_type)
+bool CUIOutfitImmunity::InitFromXml(CUIXml& xml_doc, pcstr base_str, pcstr immunity, pcstr immunity_text)
{
CUIXmlInit::InitWindow(xml_doc, base_str, 0, this);
string256 buf;
- strconcat(sizeof(buf), buf, base_str, ":", immunity_names[hit_type]);
+ strconcat(sizeof(buf), buf, base_str, ":", immunity);
if (!CUIXmlInit::InitWindow(xml_doc, buf, 0, this, false))
return false;
CUIXmlInit::InitStatic(xml_doc, buf, 0, &m_name);
- m_name.TextItemControl()->SetTextST(immunity_st_names[hit_type]);
+ m_name.TextItemControl()->SetTextST(immunity_text);
- strconcat(sizeof(buf), buf, base_str, ":", immunity_names[hit_type], ":progress_immunity");
+ strconcat(sizeof(buf), buf, base_str, ":", immunity, ":progress_immunity");
m_progress.InitFromXml(xml_doc, buf);
- strconcat(sizeof(buf), buf, base_str, ":", immunity_names[hit_type], ":static_value");
+ strconcat(sizeof(buf), buf, base_str, ":", immunity, ":static_value");
if (xml_doc.NavigateToNode(buf, 0) && !CallOfPripyatMode)
{
CUIXmlInit::InitStatic(xml_doc, buf, 0, &m_value);
@@ -92,7 +78,7 @@ void CUIOutfitImmunity::SetProgressValue(float cur, float comp)
// ===========================================================================================
void CUIOutfitInfo::InitFromXml(CUIXml& xml_doc)
{
- LPCSTR base_str = "outfit_info";
+ const LPCSTR base_str = "outfit_info";
CUIXmlInit::InitWindow(xml_doc, base_str, 0, this);
@@ -104,51 +90,49 @@ void CUIOutfitInfo::InitFromXml(CUIXml& xml_doc)
strconcat(sizeof(buf), buf, base_str, ":", "prop_line");
m_Prop_line = UIHelper::CreateStatic(xml_doc, buf, this, false);
- Fvector2 pos;
- pos.set(0.0f, 0.0f);
+ Fvector2 pos{};
if (m_Prop_line)
pos.set(0.0f, m_Prop_line->GetWndPos().y + m_Prop_line->GetWndSize().y);
else if (m_caption)
pos.set(0.0f, m_caption->GetWndSize().y);
- for (u32 i = 0; i < max_count; ++i)
+ for (const auto [hit_type, immunity, immunity_text] : immunity_names)
{
- auto immunity = xr_new();
- if (!immunity->InitFromXml(xml_doc, base_str, i))
+ auto item = xr_new();
+ if (!item->InitFromXml(xml_doc, base_str, immunity, immunity_text))
{
- xr_delete(immunity);
+ xr_delete(item);
continue;
}
- immunity->SetAutoDelete(true);
- AttachChild(immunity);
- immunity->SetWndPos(pos);
- pos.y += immunity->GetWndSize().y;
-
- m_items[i] = immunity;
+ item->SetAutoDelete(true);
+ AttachChild(item);
+ item->SetWndPos(pos);
+ pos.y += item->GetWndSize().y;
+ m_items[hit_type] = item;
}
+
pos.x = GetWndSize().x;
SetWndSize(pos);
}
void CUIOutfitInfo::UpdateInfo(CCustomOutfit* cur_outfit, CCustomOutfit* slot_outfit)
{
- CActor* actor = smart_cast(Level().CurrentViewEntity());
+ const CActor* actor = smart_cast(Level().CurrentViewEntity());
if (!actor || !cur_outfit)
{
return;
}
- for (u32 i = 0; i < max_count; ++i)
+ for (auto& [hit_type, item] : m_items)
{
- if (!m_items[i])
+ if (!item)
continue;
- if (i == ALife::eHitTypeFireWound)
+ if (hit_type == ALife::eHitTypeFireWound)
continue;
- ALife::EHitType hit_type = (ALife::EHitType)i;
- float max_power = actor->conditions().GetZoneMaxPower(hit_type);
+ const float max_power = actor->conditions().GetZoneMaxPower(hit_type);
float cur = cur_outfit->GetDefHitTypeProtection(hit_type);
cur /= max_power; // = 0..1
@@ -159,10 +143,10 @@ void CUIOutfitInfo::UpdateInfo(CCustomOutfit* cur_outfit, CCustomOutfit* slot_ou
slot = slot_outfit->GetDefHitTypeProtection(hit_type);
slot /= max_power; // = 0..1
}
- m_items[i]->SetProgressValue(cur, slot);
+ item->SetProgressValue(cur, slot);
}
- if (m_items[ALife::eHitTypeFireWound])
+ if (const auto& fireWoundItem = m_items[ALife::eHitTypeFireWound])
{
IKinematics* ikv = smart_cast(actor->Visual());
VERIFY(ikv);
@@ -185,31 +169,30 @@ void CUIOutfitInfo::UpdateInfo(CCustomOutfit* cur_outfit, CCustomOutfit* slot_ou
// slot += slot_outfit->GetBoneArmor(spine_bone);
//}
}
- float max_power = actor->conditions().GetMaxFireWoundProtection();
+ const float max_power = actor->conditions().GetMaxFireWoundProtection();
cur /= max_power;
slot /= max_power;
- m_items[ALife::eHitTypeFireWound]->SetProgressValue(cur, slot);
+ fireWoundItem->SetProgressValue(cur, slot);
}
}
void CUIOutfitInfo::UpdateInfo(CHelmet* cur_helmet, CHelmet* slot_helmet)
{
- CActor* actor = smart_cast(Level().CurrentViewEntity());
+ const CActor* actor = smart_cast(Level().CurrentViewEntity());
if (!actor || !cur_helmet)
{
return;
}
- for (u32 i = 0; i < max_count; ++i)
+ for (auto& [hit_type, item] : m_items)
{
- if (!m_items[i])
+ if (!item)
continue;
- if (i == ALife::eHitTypeFireWound)
+ if (hit_type == ALife::eHitTypeFireWound)
continue;
- ALife::EHitType hit_type = (ALife::EHitType)i;
- float max_power = actor->conditions().GetZoneMaxPower(hit_type);
+ const float max_power = actor->conditions().GetZoneMaxPower(hit_type);
float cur = cur_helmet->GetDefHitTypeProtection(hit_type);
cur /= max_power; // = 0..1
@@ -220,18 +203,18 @@ void CUIOutfitInfo::UpdateInfo(CHelmet* cur_helmet, CHelmet* slot_helmet)
slot = slot_helmet->GetDefHitTypeProtection(hit_type);
slot /= max_power; // = 0..1
}
- m_items[i]->SetProgressValue(cur, slot);
+ item->SetProgressValue(cur, slot);
}
- if (m_items[ALife::eHitTypeFireWound])
+ if (const auto& fireWoundItem = m_items[ALife::eHitTypeFireWound])
{
IKinematics* ikv = smart_cast(actor->Visual());
VERIFY(ikv);
- u16 spine_bone = ikv->LL_BoneID("bip01_head");
+ const u16 spine_bone = ikv->LL_BoneID("bip01_head");
- float cur = cur_helmet->GetBoneArmor(spine_bone) * cur_helmet->GetCondition();
- float slot = (slot_helmet) ? slot_helmet->GetBoneArmor(spine_bone) * slot_helmet->GetCondition() : cur;
+ const float cur = cur_helmet->GetBoneArmor(spine_bone) * cur_helmet->GetCondition();
+ const float slot = (slot_helmet) ? slot_helmet->GetBoneArmor(spine_bone) * slot_helmet->GetCondition() : cur;
- m_items[ALife::eHitTypeFireWound]->SetProgressValue(cur, slot);
+ fireWoundItem->SetProgressValue(cur, slot);
}
}
diff --git a/src/xrGame/ui/UIOutfitInfo.h b/src/xrGame/ui/UIOutfitInfo.h
index a36743a8684..72a632a6a3f 100644
--- a/src/xrGame/ui/UIOutfitInfo.h
+++ b/src/xrGame/ui/UIOutfitInfo.h
@@ -14,7 +14,7 @@ class CUIOutfitImmunity final : public CUIWindow
public:
CUIOutfitImmunity();
- bool InitFromXml(CUIXml& xml_doc, LPCSTR base_str, u32 hit_type);
+ bool InitFromXml(CUIXml& xml_doc, pcstr base_str, pcstr immunity, pcstr immunity_text);
void SetProgressValue(float cur, float comp);
pcstr GetDebugType() override { return "CUIOutfitImmunity"; }
@@ -41,13 +41,7 @@ class CUIOutfitInfo final : public CUIWindow
pcstr GetDebugType() override { return "CUIOutfitInfo"; }
protected:
- enum
- {
- max_count = ALife::eHitTypeMax - 3
- };
-
CUIStatic* m_caption{};
CUIStatic* m_Prop_line{};
- CUIOutfitImmunity* m_items[max_count]{};
-
+ xr_unordered_map m_items;
}; // class CUIOutfitInfo
diff --git a/src/xrGame/ui/UIPdaWnd.cpp b/src/xrGame/ui/UIPdaWnd.cpp
index 2f069eb67b8..79cce2d20ca 100644
--- a/src/xrGame/ui/UIPdaWnd.cpp
+++ b/src/xrGame/ui/UIPdaWnd.cpp
@@ -162,8 +162,8 @@ void CUIPdaWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData)
}
default:
{
- R_ASSERT(m_pActiveDialog);
- m_pActiveDialog->SendMessage(pWnd, msg, pData);
+ if (m_pActiveDialog)
+ m_pActiveDialog->SendMessage(pWnd, msg, pData);
}
};
}
@@ -175,20 +175,24 @@ void CUIPdaWnd::Show(bool status)
{
InventoryUtilities::SendInfoToActor("ui_pda");
- if (!m_pActiveDialog)
+ if (!m_sActiveSection.empty())
+ SetActiveSubdialog(m_sActiveSection);
+ else
{
- if (pUIMapWnd && !pUITaskWnd)
- SetActiveSubdialog("eptMap");
- else
- SetActiveSubdialog("eptTasks");
+ cpcstr subdialog = pUIMapWnd && !pUITaskWnd ? "eptMap" : "eptTasks";
+ SetActiveSubdialog(subdialog);
+ UITabControl->SetActiveTab(subdialog);
}
- m_pActiveDialog->Show(true);
}
else
{
InventoryUtilities::SendInfoToActor("ui_pda_hide");
CurrentGameUI()->UIMainIngameWnd->SetFlashIconState_(CUIMainIngameWnd::efiPdaTask, false);
- m_pActiveDialog->Show(false);
+ if (m_pActiveDialog)
+ {
+ m_pActiveDialog->Show(false);
+ m_pActiveDialog = pUITaskWnd; //hack for script window
+ }
g_btnHint->Discard();
g_statHint->Discard();
}
@@ -197,12 +201,12 @@ void CUIPdaWnd::Show(bool status)
void CUIPdaWnd::Update()
{
inherited::Update();
- m_pActiveDialog->Update();
+
+ if (m_pActiveDialog)
+ m_pActiveDialog->Update();
if (m_clock)
- {
m_clock->SetText(GetGameTimeAsString(InventoryUtilities::etpTimeToMinutes).c_str());
- }
if (pUILogsWnd)
Device.seqParallel.push_back(fastdelegate::FastDelegate0<>(pUILogsWnd, &CUILogsWnd::PerformWork));
@@ -210,12 +214,13 @@ void CUIPdaWnd::Update()
void CUIPdaWnd::SetActiveSubdialog(const shared_str& section)
{
- if (m_sActiveSection == section)
- return;
+ //if (m_sActiveSection == section)
+ // return;
if (m_pActiveDialog)
{
- UIMainPdaFrame->DetachChild(m_pActiveDialog);
+ if (UIMainPdaFrame->IsChild(m_pActiveDialog))
+ UIMainPdaFrame->DetachChild(m_pActiveDialog);
m_pActiveDialog->Show(false);
}
@@ -241,8 +246,7 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section)
luabind::functor functor;
if (GEnv.ScriptEngine->functor("pda.set_active_subdialog", functor))
{
- CUIDialogWndEx* scriptWnd = functor(section.c_str());
- if (scriptWnd)
+ if (CUIDialogWndEx* scriptWnd = functor(section.c_str()))
{
scriptWnd->SetHolder(CurrentDialogHolder());
m_pActiveDialog = scriptWnd;
@@ -254,16 +258,18 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section)
InventoryUtilities::SendInfoToActor("ui_pda_actor_info");
}
- R_ASSERT(m_pActiveDialog);
- UIMainPdaFrame->AttachChild(m_pActiveDialog);
- m_pActiveDialog->Show(true);
-
- if (UITabControl->GetActiveId() != section)
+ if (m_pActiveDialog)
+ {
+ if (!UIMainPdaFrame->IsChild(m_pActiveDialog))
+ UIMainPdaFrame->AttachChild(m_pActiveDialog);
+ m_pActiveDialog->Show(true);
+ m_sActiveSection = section;
+ SetActiveCaption();
+ }
+ else
{
- UITabControl->SetActiveTab(section);
+ m_sActiveSection = "";
}
- m_sActiveSection = section;
- SetActiveCaption();
}
void CUIPdaWnd::SetActiveCaption()
@@ -319,25 +325,13 @@ void CUIPdaWnd::Draw()
void CUIPdaWnd::DrawHint()
{
- if (m_pActiveDialog == pUITaskWnd && pUITaskWnd)
- {
+ if (m_sActiveSection == "eptTasks" && pUITaskWnd)
pUITaskWnd->DrawHint();
- }
- if (m_pActiveDialog == pUIMapWnd && pUIMapWnd)
- {
+ else if (m_sActiveSection == "eptMap" && pUIMapWnd)
pUIMapWnd->DrawHint();
- }
- else if (m_pActiveDialog == pUIFactionWarWnd && pUIFactionWarWnd)
- {
- //m_hint_wnd->Draw();
- }
- else if (m_pActiveDialog == pUIRankingWnd && pUIRankingWnd)
- {
+ else if (m_sActiveSection == "eptRanking" && pUIRankingWnd)
pUIRankingWnd->DrawHint();
- }
- else if (m_pActiveDialog == pUILogsWnd && pUILogsWnd)
- {
- }
+
m_hint_wnd->Draw();
}
@@ -346,7 +340,7 @@ void CUIPdaWnd::UpdatePda()
if (pUILogsWnd)
pUILogsWnd->UpdateNews();
- if (m_pActiveDialog == pUITaskWnd && pUITaskWnd)
+ if (m_sActiveSection == "eptTasks" && pUITaskWnd)
{
pUITaskWnd->ReloadTaskInfo();
}
@@ -354,7 +348,7 @@ void CUIPdaWnd::UpdatePda()
void CUIPdaWnd::UpdateRankingWnd()
{
- if (pUIRankingWnd)
+ if (pUIRankingWnd && pUIRankingWnd->IsShown())
pUIRankingWnd->Update();
}
diff --git a/src/xrGame/ui/UIPdaWnd.h b/src/xrGame/ui/UIPdaWnd.h
index a6d71836231..367fc56862d 100644
--- a/src/xrGame/ui/UIPdaWnd.h
+++ b/src/xrGame/ui/UIPdaWnd.h
@@ -77,11 +77,13 @@ class CUIPdaWnd final : public CUIDialogWnd
void SetCaption(pcstr text);
void Show_SecondTaskWnd(bool status);
void Show_MapLegendWnd(bool status);
- pcstr GetActiveSection() { return m_sActiveSection.c_str(); };
- CUITabControl* GetTabControl() const { return UITabControl; };
+ void SetActiveDialog(CUIWindow* wnd) { m_pActiveDialog = wnd; }
+ CUIWindow* GetActiveDialog() const { return m_pActiveDialog; }
+ pcstr GetActiveSection() const { return m_sActiveSection.c_str(); }
void SetActiveSubdialog(const shared_str& section);
- void SetActiveSubdialog_script(pcstr section) { SetActiveSubdialog(section); };
+ CUITabControl* GetTabControl() const { return UITabControl; }
+
virtual bool StopAnyMove() { return false; }
void UpdatePda();
void UpdateRankingWnd();
diff --git a/src/xrGame/ui/UIRankingWnd.cpp b/src/xrGame/ui/UIRankingWnd.cpp
index 969e504e174..afff80e955e 100644
--- a/src/xrGame/ui/UIRankingWnd.cpp
+++ b/src/xrGame/ui/UIRankingWnd.cpp
@@ -21,33 +21,46 @@
#include "character_reputation.h"
#include "relation_registry.h"
#include "UICharacterInfo.h"
+#include "UIRankFaction.h"
+#include "UIAchievements.h"
+#include "UIRankingsCoC.h"
#include "xrUICore/ui_base.h"
#define PDA_RANKING_XML "pda_ranking.xml"
CUIRankingWnd::CUIRankingWnd()
- : CUIWindow("CUIRankingWnd"),
- m_delay(3000), m_previous_time(Device.dwTimeGlobal), m_stat_count(0),
+ : CUIWindow("CUIRankingWnd"), m_delay(3000), m_previous_time(Device.dwTimeGlobal),
m_last_monster_icon_back(""), m_last_monster_icon(""), m_last_weapon_icon("") {}
CUIRankingWnd::~CUIRankingWnd()
{
- auto b = m_achieves_vec.begin(), e = m_achieves_vec.end();
- for (; b != e; ++b)
- xr_delete(*b);
+ for (auto& achievement : m_achieves_vec)
+ xr_delete(achievement);
m_achieves_vec.clear();
+
+ //Alundaio: CoC Rankings
+ for (auto& ranking : m_coc_ranking_vec)
+ xr_delete(ranking);
+ m_coc_ranking_vec.clear();
+
+ xr_delete(m_coc_ranking_actor);
+ //-Alundaio
}
void CUIRankingWnd::Show(bool status)
{
if (status)
{
- m_actor_ch_info->InitCharacter(Actor()->object_id());
+ if (m_actor_ch_info)
+ m_actor_ch_info->InitCharacter(Actor()->object_id());
- string64 buf;
- xr_sprintf(buf, sizeof(buf), "%d %s", Actor()->get_money(), "RU");
- m_money_value->SetText(buf);
- m_money_value->AdjustWidthToText();
+ if (m_money_value)
+ {
+ string64 buf;
+ xr_sprintf(buf, sizeof(buf), "%d %s", Actor()->get_money(), "RU");
+ m_money_value->SetText(buf);
+ m_money_value->AdjustWidthToText();
+ }
update_info();
inherited::Update();
}
@@ -56,7 +69,8 @@ void CUIRankingWnd::Show(bool status)
void CUIRankingWnd::Update()
{
- inherited::Update();
+ if (inherited::IsShown())
+ inherited::Update();
if (Device.dwTimeGlobal - m_previous_time > m_delay)
{
m_previous_time = Device.dwTimeGlobal;
@@ -80,70 +94,72 @@ bool CUIRankingWnd::Init()
std::ignore = UIHelper::CreateStatic(xml, "center_background", this, false);
std::ignore = UIHelper::CreateFrameWindow(xml, "down_background", this, false);
- m_actor_ch_info = xr_new();
- m_actor_ch_info->SetAutoDelete(true);
- AttachChild(m_actor_ch_info);
- m_actor_ch_info->InitCharacterInfo(&xml, "actor_ch_info");
+ if (xml.NavigateToNode("actor_ch_info"))
+ {
+ m_actor_ch_info = xr_new();
+ m_actor_ch_info->SetAutoDelete(true);
+ AttachChild(m_actor_ch_info);
+ m_actor_ch_info->InitCharacterInfo(&xml, "actor_ch_info");
- auto* community = m_actor_ch_info->GetIcon(CUICharacterInfo::eCommunity);
- auto* communityCaption = m_actor_ch_info->GetIcon(CUICharacterInfo::eCommunityCaption);
+ auto* community = m_actor_ch_info->GetIcon(CUICharacterInfo::eCommunity);
+ auto* communityCaption = m_actor_ch_info->GetIcon(CUICharacterInfo::eCommunityCaption);
- if (community && communityCaption)
- {
- communityCaption->AdjustWidthToText();
- pos = community->GetWndPos();
- pos.x = communityCaption->GetWndPos().x + communityCaption->GetWndSize().x + 10.0f;
- community->SetWndPos(pos);
+ if (community && communityCaption)
+ {
+ communityCaption->AdjustWidthToText();
+ pos = community->GetWndPos();
+ pos.x = communityCaption->GetWndPos().x + communityCaption->GetWndSize().x + 10.0f;
+ community->SetWndPos(pos);
+ }
}
std::ignore = UIHelper::CreateFrameWindow(xml, "actor_icon_over", this, false);
- auto* money_caption = UIHelper::CreateStatic(xml, "money_caption", this);
- m_money_value = UIHelper::CreateStatic(xml, "money_value", this);
- money_caption->AdjustWidthToText();
- pos = money_caption->GetWndPos();
- pos.x += money_caption->GetWndSize().x + 10.0f;
- m_money_value->SetWndPos(pos);
+ auto* money_caption = UIHelper::CreateStatic(xml, "money_caption", this, false);
+ m_money_value = UIHelper::CreateStatic(xml, "money_value", this, false);
+ if (money_caption && m_money_value)
+ {
+ money_caption->AdjustWidthToText();
+ pos = money_caption->GetWndPos();
+ pos.x += money_caption->GetWndSize().x + 10.0f;
+ m_money_value->SetWndPos(pos);
+ }
- auto* center_caption = UIHelper::CreateStatic(xml, "center_caption", this);
+ if (auto* center_caption = UIHelper::CreateStatic(xml, "center_caption", this, false))
+ {
+ string256 buf;
+ xr_strcpy(buf, center_caption->GetText());
+ xr_strcat(buf, StringTable().translate("ui_ranking_center_caption").c_str());
+ center_caption->SetText(buf);
+ }
std::ignore = UIHelper::CreateStatic (xml, "fraction_static", this, false);
std::ignore = UIHelper::CreateFrameLine(xml, "fraction_line1", this, false);
std::ignore = UIHelper::CreateFrameLine(xml, "fraction_line2", this, false);
+ // Dynamic stats
XML_NODE stored_root = xml.GetLocalRoot();
XML_NODE node = xml.NavigateToNode("stat_info", 0);
xml.SetLocalRoot(node);
- m_stat_count = (u32)xml.GetNodesNum(node, "stat");
+ auto stat_count = xml.GetNodesNum(node, "stat");
const u32 value_color = CUIXmlInit::GetColor(xml, "value", 0, 0xFFffffff);
- for (u8 i = 0; i < m_stat_count; ++i)
+ for (size_t i = 0; i < stat_count; ++i)
{
- m_stat_caption[i] = xr_new("Caption");
- AttachChild(m_stat_caption[i]);
- m_stat_caption[i]->SetAutoDelete(true);
- CUIXmlInit::InitStatic(xml, "stat", i, m_stat_caption[i]);
- m_stat_caption[i]->AdjustWidthToText();
-
- m_stat_info[i] = xr_new("Info");
- AttachChild(m_stat_info[i]);
- m_stat_info[i]->SetAutoDelete(true);
- CUIXmlInit::InitStatic(xml, "stat", i, m_stat_info[i]);
-
- m_stat_info[i]->SetTextColor(value_color);
-
- pos.y = m_stat_caption[i]->GetWndPos().y;
- pos.x = m_stat_caption[i]->GetWndPos().x + m_stat_caption[i]->GetWndSize().x + 5.0f;
- m_stat_info[i]->SetWndPos(pos);
+ auto* stat_caption = UIHelper::CreateStatic(xml, "stat", i, this);
+ stat_caption->AdjustWidthToText();
+
+ auto* stat_info = m_stat_info.emplace_back(UIHelper::CreateStatic(xml, "stat", i, this));
+
+ stat_info->SetTextColor(value_color);
+
+ pos.y = stat_caption->GetWndPos().y;
+ pos.x = stat_caption->GetWndPos().x + stat_caption->GetWndSize().x + 5.0f;
+ stat_info->SetWndPos(pos);
}
xml.SetLocalRoot(stored_root);
- string256 buf;
- xr_strcpy(buf, center_caption->GetText());
- xr_strcat(buf, StringTable().translate("ui_ranking_center_caption").c_str());
- center_caption->SetText(buf);
-
m_factions_list = UIHelper::CreateScrollView(xml, "fraction_list", this, false);
if (m_factions_list)
{
@@ -166,6 +182,7 @@ bool CUIRankingWnd::Init()
}
}
+ // Monsters & weapons
m_monster_icon_back = UIHelper::CreateStatic(xml, "monster_icon_back", this, false);
m_monster_icon = UIHelper::CreateStatic(xml, "monster_icon", this, false);
std::ignore = UIHelper::CreateFrameWindow(xml, "monster_background", this, false);
@@ -176,6 +193,7 @@ bool CUIRankingWnd::Init()
std::ignore = UIHelper::CreateFrameWindow(xml, "favorite_weapon_ramka", this, false);
std::ignore = UIHelper::CreateFrameWindow(xml, "favorite_weapon_over", this, false);
+ // Achievements
std::ignore = UIHelper::CreateFrameWindow(xml, "achievements_background", this, false);
m_achievements = UIHelper::CreateScrollView(xml, "achievements_wnd", this, false);
if (m_achievements)
@@ -191,6 +209,37 @@ bool CUIRankingWnd::Init()
add_achievement(xml, item.first);
}
}
+
+ //Alundaio: CoC Rankings
+ u8 topRankCount = 50;
+ luabind::functor getRankingArraySize;
+
+ if (GEnv.ScriptEngine->functor("pda.get_rankings_array_size", getRankingArraySize))
+ {
+ topRankCount = getRankingArraySize();
+ }
+
+ std::ignore = UIHelper::CreateFrameWindow(xml, "coc_ranking_background", this, false);
+ if (auto* coc_ranking = UIHelper::CreateScrollView(xml, "coc_ranking_wnd", this, false))
+ {
+ coc_ranking->SetWindowName("coc_ranking_list");
+
+ for (u8 i = 1; i <= topRankCount; i++)
+ {
+ auto character_rank_item = m_coc_ranking_vec.emplace_back(xr_new(coc_ranking));
+ character_rank_item->init_from_xml(xml, i, false);
+ }
+ }
+
+ if (auto* coc_ranking_actor_view = UIHelper::CreateScrollView(xml, "coc_ranking_wnd_actor", this, false))
+ {
+ coc_ranking_actor_view->SetWindowName("coc_ranking_list_actor");
+
+ m_coc_ranking_actor = xr_new(coc_ranking_actor_view);
+ m_coc_ranking_actor->init_from_xml(xml, topRankCount + 1, true);
+ }
+ //-Alundaio
+
xml.SetLocalRoot(stored_root);
return true;
@@ -235,68 +284,88 @@ void CUIRankingWnd::update_info()
for (const auto& achievement : m_achieves_vec)
achievement->Update();
+ for (const auto& ranking : m_coc_ranking_vec)
+ ranking->Update();
+
get_statistic();
get_best_monster();
get_favorite_weapon();
- if (!m_factions_list)
- return;
-
- bool force_rating = false;
- for (u8 i = 0; i < m_factions_list->GetSize(); ++i)
+ if (m_factions_list)
{
- if (const auto* ui_faction = smart_cast(m_factions_list->GetItem(i)))
+ bool force_rating = false;
+ for (u8 i = 0; i < m_factions_list->GetSize(); ++i)
{
- if (ui_faction->get_cur_sn() != i + 1)
+ if (const auto* ui_faction = smart_cast(m_factions_list->GetItem(i)))
{
- force_rating = true;
- break;
+ if (ui_faction->get_cur_sn() != i + 1)
+ {
+ force_rating = true;
+ break;
+ }
}
}
- }
- for (u8 i = 0; i < m_factions_list->GetSize(); ++i)
- {
- if (auto* ui_faction = smart_cast(m_factions_list->GetItem(i)))
+ for (u8 i = 0; i < m_factions_list->GetSize(); ++i)
{
- ui_faction->update_info(i + 1);
- ui_faction->rating(i + 1, force_rating);
+ if (auto* ui_faction = smart_cast