Перейти к содержанию

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

 

Так как я человек лени, мне было лень искать по всяким форумам людей кто будет редактировать движок. В связи с этим я решил взяться за OpenXRay (честь и хвала его создателям), так как он собирается и редактируется без проблем.  Я хочу оставить тут записи тем людям что хотят, хоть как-то отредактировать движок(новые слоты, новые характеристики и т.д.). 

Спойлер
Спойлер

Если у вас так же, как и у меня есть подходящие уроки, то поделитесь с людьми, ведь даже нам иногда могут помочь:)

WARNING!!! Все правки производятся в xrGame.dll. Если же они делаются не там, то будет сделан отдельный спойлер для правок других библиотек!!!
Пожалуй первыми моими уроками будет вот это:

Спойлер

Первое что мы будем редактировать файл UIActorMenuInitialize.cpp.

Ищем вот эту строку:


 constexpr std::tuple<eActorMenuListType, cpcstr, cpcstr, cpcstr, cpcstr, bool> inventory_lists[] =

Как вы наверно заметили(если хотя бы немного знаете инглишь),то это таблица с некоторыми ссылками, а именно на такие параметры как: иконка, степень повреждённости(прогресс бар), подсветка и иконка блокировки(как у шлема в экзоскелете или артефактов).
Добавляем туда вот такие строки:


        { eInventoryKnifeList,     "dragdrop_knife",           "progess_bar_knife",   "knife_slot_highlight",    nullptr,            true }, // Нож
        { eInventoryBinocularList, "dragdrop_binocular",       nullptr,               "binocular_slot_highlight",nullptr,            true }, // Бинокль


        
Если хотим в бинокле сделать прогресс-бар, то можно добавить во второй строке на место первой nullptr вот это "progess_bar_binocular". (главное не забыть добавить это в actor_menu).
Теперь ищем вот эту строку:


    std::tuple<eActorMenuListType, cpcstr, CUIWindow*> inventory_lists[] =


    
Это также таблица в которую нужно добавить вот эти строки:


        { eInventoryKnifeList,     "dragdrop_knife",     m_pInventoryWnd }, // Нож
        { eInventoryBinocularList, "dragdrop_binocular", m_pInventoryWnd }, // Бинокль


        
Также ищем вот эту строку:

    BindDragDropListEvents(m_pLists[eInventoryAutomaticList]);
    
И буквально после нее добавляем вот это:


    BindDragDropListEvents(m_pLists[eInventoryKnifeList]);
    BindDragDropListEvents(m_pLists[eInventoryBinocularList]);


    
С первым файлом пожалуй закончили. Приступаем ко второму, а именно UIActorMenuInventory.cpp

В нём нам нужна строка


void CUIActorMenu::InitInventoryMode()

Это опять таблица, в нее (желательно в середину) нужно добавить вот это:


    m_pLists[eInventoryKnifeList]->Show(true);
    m_pLists[eInventoryBinocularList]->Show(true);


Теперь в таблице    


 CUIDragDropListEx* all_lists[] =

Добавляем через запятую следующее(желательно как изначально сделано) то есть вот это:


m_pLists[eInventoryKnifeList], m_pLists[eInventoryBinocularList],

Добавить так, чтобы всё выглядело так(хотя это необязательно):


m_pLists[eInventoryBeltList], 
m_pLists[eInventoryPistolList], 
m_pLists[eInventoryAutomaticList], 
m_pLists[eInventoryKnifeList], 
m_pLists[eInventoryBinocularList],
m_pLists[eInventoryOutfitList], 
m_pLists[eInventoryHelmetList], 
m_pLists[eInventoryDetectorList], 
m_pLists[eInventoryBagList],
m_pLists[eTradeActorBagList], 
m_pLists[eTradeActorList]


        
С еще одной таблицей мы покончили. Не беспокойтесь, их будет еще очень немножко много:)
И как я и обещал, нам нужно изменить еще одну таблицу. Ищем строку     if (onlyBagList)
Сразу после нее идёт список слотов:


INV_SLOT2
INV_SLOT3


И т.д. 

Так сразу после них, нужно удалить следующие строки:


    if (!m_pActorInvOwner->inventory().SlotIsPersistent(KNIFE_SLOT))
    if (!m_pActorInvOwner->inventory().SlotIsPersistent(BINOCULAR_SLOT))

Теперь меняем следующую таблицу, ее можно найти по такой строке:


CUIDragDropListEx* CUIActorMenu::GetSlotList(u16 slot_idx)

В ней нужно поменять:


case KNIFE_SLOT:
case BINOCULAR_SLOT:

На следующее:


    case KNIFE_SLOT: return m_pLists[eInventoryKnifeList]; break;

    case BINOCULAR_SLOT: return m_pLists[eInventoryBinocularList]; break;

Со вторым файлом покончили. Теперь следующий, а именно     UIActorMenu.cpp
В начале мы добавим к инклудам следующие два файла:


#include "WeaponKnife.h"

#include "WeaponBinocular.h"


В таблицу


 EDDListType CUIActorMenu::GetListType(CUIDragDropListEx* l)


 
Добавляем следующее:


    if (l == m_pLists[eInventoryKnifeList])
        return iActorSlot;
    if (l == m_pLists[eInventoryBinocularList])
        return iActorSlot;


        
В таблицу


void CUIActorMenu::clear_highlight_lists()

    m_pLists[eInventoryBinocularList]->Highlight(false);
    m_pLists[eInventoryKnifeList]->Highlight(false);

 

В таблицу


void CUIActorMenu::highlight_item_slot(CUICellItem* cell_item)

Добавляем после 


    CWeapon* weapon = smart_cast<CWeapon*>(item);

Вот это:


    CWeaponKnife* knife = smart_cast<CWeaponKnife*>(item);
    CWeaponBinoculars* binoculars = smart_cast<CWeaponBinoculars*>(item);

Также после 


    if (weapon && (slot_id == INV_SLOT_2 || slot_id == INV_SLOT_3))
    {
        m_pLists[eInventoryPistolList]->Highlight(true);
        m_pLists[eInventoryAutomaticList]->Highlight(true);
        return;
    }

Добавляем вот это:


    if (knife && slot_id == KNIFE_SLOT)
    {
        m_pLists[eInventoryKnifeList]->Highlight(true);
        return;
    }
    if (binoculars && slot_id == BINOCULAR_SLOT)
    {
        m_pLists[eInventoryBinocularList]->Highlight(true);
        return;
    }


В таблицу


void CUIActorMenu::ClearAllLists()

    m_pLists[eInventoryKnifeList]->ClearAll(true);
    m_pLists[eInventoryBinocularList]->ClearAll(true);


    
Теперь в файле UIActorMenu.h добавим ссылки:
В таблицу 


    enum eActorMenuListType

Вот это:


        eInventoryKnifeList,
        eInventoryBinocularList,    

Всё, можно собирать движок(если вы закончили). И когда вы его соберете мы приступим к самому UI. Сразу предупреждаю, я не учу вас рисовать, так что рисовать будете сами, я покажу только примерно, все UI вам нужно будет подгонять самим, под свой инвентарь. Для редактирования возьмём actor_menu.xml этот файл отвечает за разрешение 1024x768 вроде, а actor_menu_16.xml отвечает за широкоформат, в нём делаете практически точно так же как и в первом, в них будут различаться только координаты и на пару пикселей размер(если знакомы с UI то сами знаете).
Так, побазарили и хватит, приступим к редактированию:
После 


    <detector_slot_highlight x="463" y="330" width="96" height="48" stretch="1">
        <texture>ui_inGame2_detector_highlighter</texture>
    </detector_slot_highlight>


Добавляем следующее(сделана на примере детектора, но работает просто чудесно)


    <knife_slot_highlight x="463" y="350" width="96" height="48" stretch="1">
        <texture>ui_inGame2_detector_highlighter</texture>
    </knife_slot_highlight>

    <binocular_slot_highlight x="463" y="370" width="96" height="48" stretch="1">
        <texture>ui_inGame2_detector_highlighter</texture>
    </binocular_slot_highlight>


Теперь после


    <progess_bar_outfit x="484" y="309" width="58" height="5" horz="1" min="0" max="1" pos="0">
        <progress>
            <texture r="142" g="149" b="149">ui_inGame2_inventory_status_bar</texture>
        </progress>
        <min_color r="196" g="18" b="18"/>
        <middle_color r="255" g="255" b="118"/>
        <max_color r="107" g="207" b="119"/>
    </progess_bar_outfit>


Добавляем 


    <progess_bar_knife x="484" y="324" width="58" height="5" horz="1" min="0" max="1" pos="0">
        <progress>
            <texture r="142" g="149" b="149">ui_inGame2_inventory_status_bar</texture>
        </progress>
        <min_color r="196" g="18" b="18"/>
        <middle_color r="255" g="255" b="118"/>
        <max_color r="107" g="207" b="119"/>
    </progess_bar_knife>


Также добавляем после


    <dragdrop_detector x="458" y="328" width="106" height="55"
        cell_width="41" cell_height="41" rows_num="1" cols_num="2"
        custom_placement="0" a="0" virtual_cells="1" vc_vert_align="c"
        vc_horiz_align="c"/>


Вот это вот


    <dragdrop_knife x="458" y="348" width="106" height="55"
        cell_width="41" cell_height="41" rows_num="1" cols_num="2"
        custom_placement="0" a="0" virtual_cells="1" vc_vert_align="c"
        vc_horiz_align="c"/>

    <dragdrop_binocular x="458" y="368" width="106" height="55"
        cell_width="41" cell_height="41" rows_num="1" cols_num="2"
        custom_placement="0" a="0" virtual_cells="1" vc_vert_align="c"
        vc_horiz_align="c"/>

Теперь в system.ltx исправим следующие строки:


slot_persistent_1   = true   ;knife
slot_active_1       = true

На вот это:


slot_persistent_1   = false   ;knife
slot_active_1       = true

Также это:


slot_persistent_5   = true   ;binocular
slot_active_5       = true

На это:


slot_persistent_5   = false   ;binocular
slot_active_5       = true

Вот пожалуй и всё. Но если у вас вдруг случился вылет, сразу же бежим кидать в меня тапком, чтобы я нашёл ошибку, а то я уже говорил, что пишу в два часа ночи, а это значит что я несу всякий бред. После того как сообщите свою ошибку(желательно с логом, а он ОБЯЗАТЕЛЬНО будет(если его нет, то вы накосячили где-то, где я не давал корректировку.))

Автор данного урока: Doctor_Oz(Даниил Озол)

Спойлер

Первым делом изменим кол-во артефактов в самом рюкзаке. (смысла не ищите, его нет XD)


Откроем файл Inventory.cpp и найдём строчку 


m_iMaxBelt = pSettings->read_if_exists<s32>("inventory", "max_belt", 5);

Нам нужно изменить цифру(большую не ставьте, не рекомендую). Лично я уже изменил на 8(сначала была 5).


m_iMaxBelt = pSettings->read_if_exists<s32>("inventory", "max_belt", 5);


Так как мы изменили системное кол-во артефактов, нам надо изменить макс. кол-во ячеек которые могут быть открыты с помощью костюма.
Откроем файл CustomOutfit.cpp и найдём функцию:


void CCustomOutfit::Load(LPCSTR section)

В этой функции найдём строчку:


clamp(m_artefact_count, (u32)0, (u32)5);

И изменим на:


clamp(m_artefact_count, (u32)0, (u32)8);


Так же в файле найдём функцию(да я знаю что переменная, но всё же):


bool CCustomOutfit::install_upgrade_impl(LPCSTR section, bool test)

А в ней найдём точно такую же строку и изменяем ее также:


clamp(m_artefact_count, (u32)0, (u32)5);

На:
 


clamp(m_artefact_count, (u32)0, (u32)8);

Вот пожалуй и всё. Теперь вы можете просто изменить кол-во артефактов в outfit.ltx, UI и System.ltx также, как делали(если делали конечно, если нет то google в помощь).

Автор данного урока: Doctor_Oz(Даниил Озол)

Автор правки: Doctor_Oz(Даниил Озол)

Спойлер

Под редакцию попадает два файла: Torch.cpp и Torch.h

Ну пожалуй приступим. Откроем файл Torch.cpp и если вы ничего там не редактировали ищем функцию на 76 строке


void CTorch::Load(LPCSTR section)
{
    inherited::Load(section);
    light_trace_bone = pSettings->r_string(section, "light_trace_bone");

    m_bNightVisionEnabled = !!pSettings->r_bool(section, "night_vision");
}

Меняем её на:
 


void CTorch::Load(LPCSTR section)
{
    inherited::Load(section);
    light_trace_bone = pSettings->r_string(section, "light_trace_bone");

	m_light_section = READ_IF_EXISTS(pSettings, r_string, section, "light_section", "torch_definition");
	if (pSettings->line_exist(section, "snd_turn_on"))
		m_sounds.LoadSound(section, "snd_turn_on", "sndTurnOn", false, SOUND_TYPE_ITEM_USING);
	if (pSettings->line_exist(section, "snd_turn_off"))
		m_sounds.LoadSound(section, "snd_turn_off", "sndTurnOff", false, SOUND_TYPE_ITEM_USING);

    m_bNightVisionEnabled = !!pSettings->r_bool(section, "night_vision");
}

Теперь ищем функцию void CTorch::Switch(bool light_on) и дабы вам не заморачиваться(если вы конечно НЕ редактировали файл до этого) просто изменим её на это:
 


void CTorch::Switch(bool light_on)
{
	CActor* pActor = smart_cast<CActor*>(H_Parent());
	if (pActor)
	{
		if (light_on && !m_switched_on)
		{
			if (m_sounds.FindSoundItem("SndTurnOn", false))
				m_sounds.PlaySound("SndTurnOn", pActor->Position(), NULL, !!pActor->HUDview());
		}
		else if (!light_on && m_switched_on)
		{
			if (m_sounds.FindSoundItem("SndTurnOff", false))
				m_sounds.PlaySound("SndTurnOff", pActor->Position(), NULL, !!pActor->HUDview());
		}
	}
	
    m_switched_on = light_on;
    if (can_use_dynamic_lights())
    {
        light_render->set_active(light_on);

        // CActor *pA = smart_cast<CActor *>(H_Parent());
        // if(!pA)
        light_omni->set_active(light_on);
    }
    glow_render->set_active(light_on);

    if (*light_trace_bone)
    {
        IKinematics* pVisual = smart_cast<IKinematics*>(Visual());
        VERIFY(pVisual);
        u16 bi = pVisual->LL_BoneID(light_trace_bone);

        pVisual->LL_SetBoneVisible(bi, light_on, TRUE);
        pVisual->CalculateBones(TRUE);
    }
}

Также меняем функцию bool CTorch::net_Spawn(CSE_Abstract* DC) на это:


bool CTorch::net_Spawn(CSE_Abstract* DC)
{
    CSE_Abstract* e = (CSE_Abstract*)(DC);
    CSE_ALifeItemTorch* torch = smart_cast<CSE_ALifeItemTorch*>(e);
    R_ASSERT(torch);
    cNameVisual_set(torch->get_visual());

    R_ASSERT(!GetCForm());
    R_ASSERT(smart_cast<IKinematics*>(Visual()));
    CForm = xr_new<CCF_Skeleton>(this);

    if (!inherited::net_Spawn(DC))
        return (FALSE);

    bool b_r2 = GEnv.Render->GenerationIsR2OrHigher();

    IKinematics* K = smart_cast<IKinematics*>(Visual());
    CInifile* pUserData = K->LL_UserData();
    R_ASSERT3(pUserData, "Empty Torch user data!", torch->get_visual());
	R_ASSERT2(pUserData->section_exist(m_light_section), "Section not found in torch user data! Check 'light_section' field in config");
	lanim = LALib.FindItem(pUserData->r_string(m_light_section, "color_animator"));
	guid_bone = K->LL_BoneID(pUserData->r_string(m_light_section, "guide_bone"));
	VERIFY(guid_bone != BI_NONE);

	Fcolor clr = pUserData->r_fcolor(m_light_section, (b_r2) ? "color_r2" : "color");
    fBrightness = clr.intensity();
	float range = pUserData->r_float(m_light_section, (b_r2) ? "range_r2" : "range");
    light_render->set_color(clr);
    light_render->set_range(range);

    if (b_r2)
    {
        bool useVolumetric = pUserData->read_if_exists<bool>(m_light_section, "volumetric_enabled", false);
        light_render->set_volumetric(useVolumetric);
        if (useVolumetric)
        {
            float volQuality = pUserData->read_if_exists<float>(m_light_section, "volumetric_quality", 1.f);
            clamp(volQuality, 0.f, 1.f);
            light_render->set_volumetric_quality(volQuality);

            float volIntensity = pUserData->read_if_exists<float>(m_light_section, "volumetric_intensity", 1.f);
            clamp(volIntensity, 0.f, 10.f);
            light_render->set_volumetric_intensity(volIntensity);

            float volDistance = pUserData->read_if_exists<float>(m_light_section, "volumetric_distance", 1.f);
            clamp(volDistance, 0.f, 1.f);
            light_render->set_volumetric_distance(volDistance);
        }
    }

	Fcolor clr_o = pUserData->r_fcolor(m_light_section, (b_r2) ? "omni_color_r2" : "omni_color");
	float range_o = pUserData->r_float(m_light_section, (b_r2) ? "omni_range_r2" : "omni_range");
    light_omni->set_color(clr_o);
    light_omni->set_range(range_o);

	light_render->set_cone(deg2rad(pUserData->r_float(m_light_section, "spot_angle")));
	light_render->set_texture(READ_IF_EXISTS(pUserData,r_string,m_light_section, "spot_texture",(0)));

	glow_render->set_texture(pUserData->r_string(m_light_section, "glow_texture"));
    glow_render->set_color(clr);
	glow_render->set_radius(pUserData->r_float(m_light_section, "glow_radius"));

    //включить/выключить фонарик
    Switch(torch->m_active);
    VERIFY(!torch->m_active || (torch->ID_Parent != 0xffff));

    if (torch->ID_Parent == 0)
        SwitchNightVision(torch->m_nightvision_active, false);
    // else
    //	SwitchNightVision	(false, false);

    m_delta_h = PI_DIV_2 - atan((range * 0.5f) / _abs(TORCH_OFFSET.x));

    return (TRUE);
}

Последнее было добавлено не для звука, а потому что мы изменили TORCH_DEFINITION на m_light_section и теперь нам надо зарегистрировать этот самый m_light_section
Откроем файл Torch.h и сразу после     Fvector m_focus; добавим вот это:     shared_str m_light_section;
Чтобы получилось вот это:


    float m_delta_h;
    Fvector2 m_prev_hp;
    bool m_switched_on;
    ref_light light_render;
    ref_light light_omni;
    ref_glow glow_render;
    Fvector m_focus;
    shared_str m_light_section;

Так же torch.zip в папку sounds закиньте звуки включения и выключения(изначально они одинаковые, но вы можете поменять на свои)

Так же в файле где у вас хранится device_torch (изначально он находится в misc\items.ltx), в сам device_torch нужно добавить строки:
snd_turn_on                              = torch\ваше_название_звука_включения ;(тут писать без расширения .ogg)
snd_turn_off                             = torch\ваше_название_звука_выключения ;(тут писать без расширения .ogg)

Автор данного урока: Doctor_Oz(Даниил Озол)

Автор правки: На данный момент неизвестен, кроме ника на GitHub (revolucas), код был взят из открытого репозитория Call of Chernobyl (ссылка на коммит)

Спойлер

Под редакторство попадает только один файл в движке и один в gamedat'e.
Сначала начнём с движка, откроем файл: UIActorMenuInventory.cpp 
И если он у вас уже отредактирован ищем функцию: void CUIActorMenu::PropertiesBoxForUsing(PIItem item, bool& b_show)
А в ней вот эти строки:


			// XXX: Xottab_DUTY: remove this..
			if (!xr_strcmp(section_name, "vodka") || !xr_strcmp(section_name, "energy_drink"))
				act_str = "st_drink";
			else if (!xr_strcmp(section_name, "bread") || !xr_strcmp(section_name, "kolbasa") || !xr_strcmp(
				section_name, "conserva"))
				act_str = "st_eat";
			else
				act_str = "st_use";

И заменяем их полностью на:


        act_str = READ_IF_EXISTS(pSettings, r_string, section_name, "use_caption", "st_use");

Теперь при использовании ЛЮБОГО предмета, будет высвечиваться надпись "Использовать"
Дабы её изменить, достаточно в секции нужно предмета указать:
use_caption = st_ваш_id_текста
Главное не забудьте локализировать эту надпись, иначе вы будете видеть надпись "st_ваш_id_текста"

Автор данного урока: Doctor_Oz(Даниил Озол)

Автор правки: Suhar_ (Lex_Addon)

Спойлер

Итак, долгожданный урок по добавлению рюкзака. Распинаться не будем, сразу приступим. В xrGame создайте фильтр (нажмите на какую нибудь папку, я выбрал xrGame/core/client/objects/item&weapons/) и назовите его Backpack. В нём создайте новый элемент. При создании высветиться список и в нём нужно выбрать .cpp . Снизу надо ввести название ActorBackpack.cpp. Точно таким же образом создаём файл .h название отличается тем что вместо .cpp нужно вписать .h. 

После того как мы их создали начнём редактирование их. Сначала откроем ActorBackpack.h, выделим всё в нём комбинацией клавиш ctrl + a и в него впишем это:


#pragma once

#include "inventory_item_object.h"

class CBackpack : public CInventoryItemObject {
private:
	typedef	CInventoryItemObject inherited;
public:
	CBackpack();
	virtual					~CBackpack();

	virtual void			Load(LPCSTR section);

	virtual void			Hit(float P, ALife::EHitType hit_type);

	virtual void			OnMoveToSlot(const SInvItemPlace& prev);
	virtual void			OnMoveToRuck(const SInvItemPlace& previous_place);
	virtual void			OnH_A_Chield();

public:
	float					m_additional_weight;
	float					m_additional_weight2;
	float					m_fPowerRestoreSpeed;
	float					m_fPowerLoss;

	virtual bool            net_Spawn(CSE_Abstract* DC);
	virtual void			net_Export(NET_Packet& P);
	virtual void			net_Import(NET_Packet& P);
	
protected:
	virtual bool			install_upgrade_impl(LPCSTR section, bool test);
}; 

Теперь открывает ActorBackpack.cpp и туда вписываем:


#include "stdafx.h"
#include "ActorBackpack.h"
#include "Actor.h"
#include "Inventory.h"

CBackpack::CBackpack()
{
	m_flags.set(FUsingCondition, FALSE);
}

CBackpack::~CBackpack()
{

}

void CBackpack::Load(LPCSTR section)
{
	inherited::Load(section);

	m_additional_weight = pSettings->r_float(section, "additional_inventory_weight");
	m_additional_weight2 = pSettings->r_float(section, "additional_inventory_weight2");
	m_fPowerRestoreSpeed = READ_IF_EXISTS(pSettings, r_float, section, "power_restore_speed", 0.0f);
	m_fPowerLoss = READ_IF_EXISTS(pSettings, r_float, section, "power_loss", 1.0f);
	clamp(m_fPowerLoss, EPS, 1.0f);

	m_flags.set(FUsingCondition, READ_IF_EXISTS(pSettings, r_bool, section, "use_condition", TRUE));
}

bool CBackpack::net_Spawn(CSE_Abstract* DC)
{
	return inherited::net_Spawn(DC);
}

void CBackpack::net_Export(NET_Packet& P)
{
	inherited::net_Export(P);
	P.w_float_q8(GetCondition(), 0.0f, 1.0f);
}

void CBackpack::net_Import(NET_Packet& P)
{
	inherited::net_Import(P);
	float _cond;
	P.r_float_q8(_cond, 0.0f, 1.0f);
	SetCondition(_cond);
}

void CBackpack::OnH_A_Chield()
{
	inherited::OnH_A_Chield();
}

void CBackpack::OnMoveToSlot(const SInvItemPlace& previous_place)
{
	inherited::OnMoveToSlot(previous_place);
}

void CBackpack::OnMoveToRuck(const SInvItemPlace& previous_place)
{
	inherited::OnMoveToRuck(previous_place);
}

void CBackpack::Hit(float hit_power, ALife::EHitType hit_type)
{
	if (IsUsingCondition() == false) return;
	hit_power *= GetHitImmunity(hit_type);
	ChangeCondition(-hit_power);
} 

bool CBackpack::install_upgrade_impl(LPCSTR section, bool test)
{
	bool result = inherited::install_upgrade_impl(section, test);

	result |= process_if_exists(section, "power_restore_speed", &CInifile::r_float, m_fPowerRestoreSpeed, test);
	result |= process_if_exists(section, "power_loss", &CInifile::r_float, m_fPowerLoss, test);
	clamp(m_fPowerLoss, 0.0f, 1.0f);

	result |= process_if_exists(section, "additional_inventory_weight", &CInifile::r_float, m_additional_weight, test);
	result |= process_if_exists(section, "additional_inventory_weight2", &CInifile::r_float, m_additional_weight2, test);

	return result;
} 

Всё, эти файлы можно закрывать. Их трогать будем в случае если вам понадобится добавить  какую то функцию в рюкзак по типу ЗСД(замкнутой системы дыхания, то есть попросту сделать кислородный баллон). Теперь займёмся функцией добавление переносимого веса. Откроем Actor_Movement.cpp и ищем функцию:
 


float CActor::get_additional_weight() const
{
    float res = 0.0f;
    CCustomOutfit* outfit = GetOutfit();
    if (outfit)
    {
        res += outfit->m_additional_weight;
    }

    for (TIItemContainer::const_iterator it = inventory().m_belt.begin(); inventory().m_belt.end() != it; ++it)
    {
        CArtefact* artefact = smart_cast<CArtefact*>(*it);
        if (artefact)
            res += artefact->AdditionalInventoryWeight();
    }

    return res;
}

Сначала перед ней есть 


#include "Artefact.h"

После неё добавим, но не в функции 


#include "ActorBackpack.h"

Теперь меняем саму функцию на это:
 


float CActor::get_additional_weight() const
{
    float res = 0.0f;
    CCustomOutfit* outfit = GetOutfit();
    if (outfit)
    {
        res += outfit->m_additional_weight;
    }

	CBackpack* pBackpack = smart_cast<CBackpack*>(inventory().ItemFromSlot(BACKPACK_SLOT));
	if (pBackpack)
		res += pBackpack->m_additional_weight;

    for (TIItemContainer::const_iterator it = inventory().m_belt.begin(); inventory().m_belt.end() != it; ++it)
    {
        CArtefact* artefact = smart_cast<CArtefact*>(*it);
        if (artefact)
            res += artefact->AdditionalInventoryWeight();
    }

    return res;
}

Всё с этим файлом закончили. Теперь идём в следующий CustomOutfit.cpp. Мы его редактируем чтобы можно было сделать возможность закрыть слот, например в том же экзоскелете. Сразу после


#include "ActorHelmet.h"

Добавим 


#include "ActorBackpack.h"

Теперь после


    bIsHelmetAvaliable = !!READ_IF_EXISTS(pSettings, r_bool, section, "helmet_avaliable", true);

Добавим:


    bIsBackpackAvaliable = !!READ_IF_EXISTS(pSettings, r_bool, section, "backpack_avaliable", true);

Теперь ищем функцию 


void CCustomOutfit::OnMoveToSlot(const SInvItemPlace& prev)
{
    if (m_pInventory)
    {
        CActor* pActor = smart_cast<CActor*>(H_Parent());
        if (pActor)
        {
            ApplySkinModel(pActor, true, false);
            if (prev.type == eItemPlaceSlot && !bIsHelmetAvaliable)
            {
                CTorch* pTorch = smart_cast<CTorch*>(pActor->inventory().ItemFromSlot(TORCH_SLOT));
                if (pTorch && pTorch->GetNightVisionStatus())
                    pTorch->SwitchNightVision(true, false);
            }
            PIItem pHelmet = pActor->inventory().ItemFromSlot(HELMET_SLOT);
            if (pHelmet && !bIsHelmetAvaliable)
                pActor->inventory().Ruck(pHelmet, false);

        }
    }
}

И меняем на это:


void CCustomOutfit::OnMoveToSlot(const SInvItemPlace& prev)
{
    if (m_pInventory)
    {
        CActor* pActor = smart_cast<CActor*>(H_Parent());
        if (pActor)
        {
            ApplySkinModel(pActor, true, false);
            if (prev.type == eItemPlaceSlot && !bIsHelmetAvaliable)
            {
                CTorch* pTorch = smart_cast<CTorch*>(pActor->inventory().ItemFromSlot(TORCH_SLOT));
                if (pTorch && pTorch->GetNightVisionStatus())
                    pTorch->SwitchNightVision(true, false);
            }
            PIItem pHelmet = pActor->inventory().ItemFromSlot(HELMET_SLOT);
            if (pHelmet && !bIsHelmetAvaliable)
                pActor->inventory().Ruck(pHelmet, false);
			
            PIItem pBackpack = pActor->inventory().ItemFromSlot(BACKPACK_SLOT);
            if (pBackpack && !bIsBackpackAvaliable)
                pActor->inventory().Ruck(pBackpack, false);
        }
    }
}

Дальше идём в CustomOutfit.h и после


    bool bIsHelmetAvaliable;

Добавить


    bool bIsBackpackAvaliable;

Теперь идём в Inventory.cpp и вместо


    false // helmet

Ставим


    false, // helmet
    false // backpack

Теперь в функции 


bool CInventory::CanPutInSlot(PIItem pIItem, u16 slot_id) const

Сразу после 


    if (slot_id == HELMET_SLOT)
    {
        CCustomOutfit* pOutfit = m_pOwner->GetOutfit();
        if (pOutfit && !pOutfit->bIsHelmetAvaliable)
            return false;
    }

Добавим


    if (slot_id == BACKPACK_SLOT)
    {
        CCustomOutfit* pOutfit = m_pOwner->GetOutfit();
        if (pOutfit && !pOutfit->bIsBackpackAvaliable)
            return false;
    }

Всё. Теперь идём в EntityConditions.cpp. Сразу после 
 


#include "ActorHelmet.h"

Добавим 


#include "ActorBackpack.h"

Теперь ищем функцию


float CEntityCondition::HitPowerEffect(float power_loss)

float CEntityCondition::HitPowerEffect(float power_loss)
{
    CInventoryOwner* pInvOwner = smart_cast<CInventoryOwner*>(m_object);
    if (!pInvOwner)
        return power_loss;

    CCustomOutfit* pOutfit = pInvOwner->GetOutfit();
	CHelmet* pHelmet = (CHelmet*)pInvOwner->inventory().ItemFromSlot(HELMET_SLOT);
	CBackpack* pBackpack = (CBackpack*)pInvOwner->inventory().ItemFromSlot(BACKPACK_SLOT);

	return power_loss * (0.5f +(pOutfit?pOutfit->m_fPowerLoss:EPS) + (pHelmet?pHelmet->m_fPowerLoss:EPS) + (pBackpack?pBackpack->m_fPowerLoss:EPS));
}

С очередным файлом закончили. Теперь открываем файл InventoryOwner.cpp и ПЕРЕД этим


float CInventoryOwner::MaxCarryWeight() const

Добавляем


#include "ActorBackpack.h"

И теперь меняем всю функцию 


float CInventoryOwner::MaxCarryWeight() const

На


float CInventoryOwner::MaxCarryWeight() const
{
    float ret = inventory().GetMaxWeight();

    const CCustomOutfit* outfit = GetOutfit();
    if (outfit)
        ret += outfit->m_additional_weight2;

	CBackpack* pBackpack = smart_cast<CBackpack*>(inventory().ItemFromSlot(BACKPACK_SLOT));
	if (pBackpack)
		ret += pBackpack->m_additional_weight2;

    return ret;
}

Теперь переходим в script_game_object_inventory_owner.cpp
И после 


#include "PhysicObject.h"

Добавляем
 


#include "ActorBackpack.h"

Теперь займёмся заменой функций(если что функцией считается не только строка но и всё что в таких скобках {...} после неё):
Заменим это


float CScriptGameObject::GetAdditionalMaxWeight() const

На это


float CScriptGameObject::GetAdditionalMaxWeight() const
{
    CCustomOutfit* outfit = smart_cast<CCustomOutfit*>(&object());
	CBackpack* pBackpack = smart_cast<CBackpack*>(&object());
	if(!outfit && !pBackpack) {
        GEnv.ScriptEngine->script_log(LuaMessageType::Error,
                                        "CCustomOutfit : cannot access class member GetAdditionalMaxWeight!");
        return false;
    }
	if (outfit)
		return (outfit->m_additional_weight2);

	return (pBackpack->m_additional_weight2);
}

Теперь это 


float CScriptGameObject::GetAdditionalMaxWalkWeight() const

На это


float CScriptGameObject::GetAdditionalMaxWalkWeight() const
{
    CCustomOutfit* outfit = smart_cast<CCustomOutfit*>(&object());
	CBackpack* pBackpack = smart_cast<CBackpack*>(&object());
	if(!outfit && !pBackpack) {
        GEnv.ScriptEngine->script_log(LuaMessageType::Error,
                                        "CCustomOutfit : cannot access class member GetAdditionalMaxWalkWeight!");
        return false;
    }
	if (outfit)
		return (outfit->m_additional_weight);

	return (pBackpack->m_additional_weight);
}

Дальше это


void CScriptGameObject::SetAdditionalMaxWeight(float add_max_weight)

На это


void CScriptGameObject::SetAdditionalMaxWeight(float add_max_weight)
{
    CCustomOutfit* outfit = smart_cast<CCustomOutfit*>(&object());
	CBackpack* pBackpack = smart_cast<CBackpack*>(&object());
	if(!outfit && !pBackpack) {
        GEnv.ScriptEngine->script_log(LuaMessageType::Error,
                                        "CCustomOutfit : cannot access class member SetAdditionalMaxWeight!");
        return;
    }
	if (outfit)
		outfit->m_additional_weight2 = add_max_weight;

	if (pBackpack)
		pBackpack->m_additional_weight2 = add_max_weight;
}

Теперь это


void CScriptGameObject::SetAdditionalMaxWalkWeight(float add_max_walk_weight)

На это


void CScriptGameObject::SetAdditionalMaxWalkWeight(float add_max_walk_weight)
{
    CCustomOutfit* outfit = smart_cast<CCustomOutfit*>(&object());
	CBackpack* pBackpack = smart_cast<CBackpack*>(&object());
	if(!outfit && !pBackpack) {
        GEnv.ScriptEngine->script_log(LuaMessageType::Error,
                                        "CCustomOutfit : cannot access class member SetAdditionalMaxWalkWeight!");
        return;
    }
	if (outfit)
		outfit->m_additional_weight = add_max_walk_weight;

	if (pBackpack)
		pBackpack->m_additional_weight = add_max_walk_weight;
}

Всё, теперь займёмся UI составляющей

Откроем UIActorMenu.h и после


        eInventoryHelmetList,

Добавить:


        eInventoryBackpackList,


Открываем UIActorMenu.cpp и сразу после
 


#include "ActorHelmet.h"

Добавим


#include "ActorBackpack.h"

Теперь в функцию


EDDListType CUIActorMenu::GetListType(CUIDragDropListEx* l)

Сразу после 


    if (l == m_pLists[eInventoryHelmetList] && m_pLists[eInventoryHelmetList] != nullptr)
        return iActorSlot;

Добавим


    if (l == m_pLists[eInventoryBackpackList] && m_pLists[eInventoryBackpackList] != nullptr)
        return iActorSlot;

Теперь в функции


void CUIActorMenu::clear_highlight_lists()

Сразу после


    if (m_pLists[eInventoryHelmetList])
        m_pLists[eInventoryHelmetList]->Highlight(false);

Добавим


    if (m_pLists[eInventoryBackpackList])
        m_pLists[eInventoryBackpackList]->Highlight(false);

В функции 


void CUIActorMenu::highlight_item_slot(CUICellItem* cell_item)

Сразу после


    CHelmet* helmet = smart_cast<CHelmet*>(item);

Добавим


    CBackpack* backpack = smart_cast<CBackpack*>(item);

Дальше после


    if (helmet && slot_id == HELMET_SLOT)
    {
        if (m_pLists[eInventoryHelmetList])
            m_pLists[eInventoryHelmetList]->Highlight(true);
        return;
    }

Добавим
 


    if (backpack && slot_id == BACKPACK_SLOT)
    {
        if (m_pLists[eInventoryBackpackList])
            m_pLists[eInventoryBackpackList]->Highlight(true);
        return;
    }

Дальше в функции


void CUIActorMenu::ClearAllLists()

После


    if (m_pLists[eInventoryHelmetList])
        m_pLists[eInventoryHelmetList]->ClearAll(true);

Добавим


    if (m_pLists[eInventoryBackpackList])
        m_pLists[eInventoryBackpackList]->ClearAll(true);

Теперь идём в UIActorMenuInventory.cpp


#include "actor_defs.h"

Пишем


#include "ActorBackpack.h"

В функции 


void CUIActorMenu::InitInventoryMode()

После


    ShowIfExist(m_pLists[eInventoryHelmetList], true);

Добавляем
 


    ShowIfExist(m_pLists[eInventoryBackpackList], true);

Дальше в функции
 


void CUIActorMenu::OnInventoryAction(PIItem pItem, u16 action_type)

Сразу после
 


		m_pLists[eInventoryHelmetList],

Добавляем


		m_pLists[eInventoryBackpackList], 

Теперь ищем строку
 


    InitCellForSlot(HELMET_SLOT);

И сразу после неё
 


    InitCellForSlot(BACKPACK_SLOT);

Теперь функцию
 


bool CUIActorMenu::ToSlot(CUICellItem* itm, bool force_place, u16 slot_id)

Меняем на
 


bool CUIActorMenu::ToSlot(CUICellItem* itm, bool force_place, u16 slot_id)
{
    CUIDragDropListEx* old_owner = itm->OwnerList();
    PIItem iitem = (PIItem)itm->m_pData;

    bool b_own_item = (iitem->parent_id() == m_pActorInvOwner->object_id());
    if (slot_id == HELMET_SLOT)
    {
        CCustomOutfit* pOutfit = m_pActorInvOwner->GetOutfit();
        if (pOutfit && !pOutfit->bIsHelmetAvaliable)
            return false;
    }
	
    if (slot_id == BACKPACK_SLOT)
    {
        CCustomOutfit* pOutfit = m_pActorInvOwner->GetOutfit();
        if (pOutfit && !pOutfit->bIsBackpackAvaliable)
            return false;
    }

    if (m_pActorInvOwner->inventory().CanPutInSlot(iitem, slot_id))
    {
        CUIDragDropListEx* new_owner = GetSlotList(slot_id);

        //Alundaio
        if (!new_owner)
            return true;

        /*if (slot_id == GRENADE_SLOT || !new_owner)
        {
            return true; // fake, sorry (((
        }
        else*/ if (slot_id == OUTFIT_SLOT)
        {
            CCustomOutfit* pOutfit = smart_cast<CCustomOutfit*>(iitem);
            CBackpack* pBackpack = smart_cast<CBackpack*>(iitem);
            if (pOutfit && !pOutfit->bIsHelmetAvaliable)
            {
                CUIDragDropListEx* helmet_list = GetSlotList(HELMET_SLOT);
                if (helmet_list && helmet_list->ItemsCount() == 1)
                {
                    CUICellItem* helmet_cell = helmet_list->GetItemIdx(0);
                    ToBag(helmet_cell, false);
                }
            }
			
            if (pOutfit && !pOutfit->bIsBackpackAvaliable)
            {
                CUIDragDropListEx* backpack_list = GetSlotList(BACKPACK_SLOT);
                if (backpack_list && backpack_list->ItemsCount() == 1)
                {
                    CUICellItem* backpack_cell = backpack_list->GetItemIdx(0);
                    ToBag(backpack_cell, false);
                }
            }
        }

        bool result = (!b_own_item) || m_pActorInvOwner->inventory().Slot(slot_id, iitem);
        VERIFY(result);

        CUICellItem* i = old_owner->RemoveItem(itm, (old_owner == new_owner));

        while (i->ChildsCount())
        {
            CUICellItem* child = i->PopChild(nullptr);
            old_owner->SetItem(child);
        }

        new_owner->SetItem(i);

        SendEvent_Item2Slot(iitem, m_pActorInvOwner->object_id(), slot_id);

        SendEvent_ActivateSlot(slot_id, m_pActorInvOwner->object_id());

        // ColorizeItem						( itm, false );
        if (slot_id == OUTFIT_SLOT)
        {
            MoveArtefactsToBag();
        }
        return true;
    }
    else
    { // in case slot is busy
        if (!force_place || slot_id == NO_ACTIVE_SLOT)
            return false;

        if (m_pActorInvOwner->inventory().SlotIsPersistent(slot_id) && slot_id != DETECTOR_SLOT)
            return false;

        if (slot_id == INV_SLOT_2 && m_pActorInvOwner->inventory().CanPutInSlot(iitem, INV_SLOT_3))
            return ToSlot(itm, force_place, INV_SLOT_3);

        if (slot_id == INV_SLOT_3 && m_pActorInvOwner->inventory().CanPutInSlot(iitem, INV_SLOT_2))
            return ToSlot(itm, force_place, INV_SLOT_2);

        CUIDragDropListEx* slot_list = GetSlotList(slot_id);
        if (!slot_list)
            return false;

        const PIItem _iitem = m_pActorInvOwner->inventory().ItemFromSlot(slot_id);

        CUIDragDropListEx* invlist = GetListByType(iActorBag);
        if (invlist != slot_list)
        {
            if (!slot_list->ItemsCount() == 1)
                return false;

            CUICellItem* slot_cell = slot_list->GetItemIdx(0);
            if (!(slot_cell && static_cast<PIItem>(slot_cell->m_pData) == _iitem))
                return false;

            if (ToBag(slot_cell, false) == false)
                return false;
        }
        else
        {
            //Alundaio: Since the player's inventory is being used as a slot we need to search for cell with matching m_pData
            auto container = slot_list->GetContainer();
            auto child_list = container->GetChildWndList();
            for (auto& it : child_list)
            {
                CUICellItem* i = static_cast<CUICellItem*>(it);
                const PIItem pitm = static_cast<PIItem>(i->m_pData);
                if (pitm == _iitem)
                {
                    if (ToBag(i, false))
                        break;

                    return false;
                }
            }

            return ToSlot(itm, false, slot_id);
        }

        bool result = ToSlot(itm, false, slot_id);
        if (b_own_item && result && slot_id == DETECTOR_SLOT)
        {
            CCustomDetector* det = smart_cast<CCustomDetector*>(iitem);
            det->ToggleDetector(g_player_hud->attached_item(0) != NULL);
        }

        return result;
    }
}

Дальше в функции


CUIDragDropListEx* CUIActorMenu::GetSlotList(u16 slot_idx)

Сразу после


    case HELMET_SLOT: return m_pLists[eInventoryHelmetList]; break;

Добавляем


    case BACKPACK_SLOT: return m_pLists[eInventoryBackpackList]; break;

Теперь функцию 
 


void CUIActorMenu::PropertiesBoxForSlots(PIItem item, bool& b_show)

Меняем на


void CUIActorMenu::PropertiesBoxForSlots(PIItem item, bool& b_show)
{
    CCustomOutfit* pOutfit = smart_cast<CCustomOutfit*>(item);
    CHelmet* pHelmet = smart_cast<CHelmet*>(item);
    CBackpack* pBackpack = smart_cast<CBackpack*>(item);
    CInventory& inv = m_pActorInvOwner->inventory();

    // Флаг-признак для невлючения пункта контекстного меню: Dreess Outfit, если костюм уже надет
    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)*/)
    {
        m_UIPropertiesBox->AddItem("st_move_to_slot", NULL, INVENTORY_TO_SLOT_ACTION);
        b_show = true;
    }
    if (item->Belt() && inv.CanPutInBelt(item))
    {
        m_UIPropertiesBox->AddItem("st_move_on_belt", NULL, INVENTORY_TO_BELT_ACTION);
        b_show = true;
    }

    if (item->Ruck() && inv.CanPutInRuck(item) && (cur_slot == NO_ACTIVE_SLOT || !inv.SlotIsPersistent(cur_slot)))
    {
        if (!pOutfit)
        {
            if (!pHelmet)
            {
				if (!pBackpack)
				{
					if (m_currMenuMode == mmDeadBodySearch)
						m_UIPropertiesBox->AddItem("st_move_to_bag", nullptr, INVENTORY_TO_BAG_ACTION);
					else
						m_UIPropertiesBox->AddItem("st_unequip", nullptr, INVENTORY_TO_BAG_ACTION);
				}
				else
					m_UIPropertiesBox->AddItem("st_undress_backpack", NULL, INVENTORY_TO_BAG_ACTION);
            }
            else
                m_UIPropertiesBox->AddItem("st_undress_helmet", NULL, INVENTORY_TO_BAG_ACTION);
        }
        else
            m_UIPropertiesBox->AddItem("st_undress_outfit", NULL, INVENTORY_TO_BAG_ACTION);

        bAlreadyDressed = true;
        b_show = true;
    }
    if (pOutfit && !bAlreadyDressed)
    {
        m_UIPropertiesBox->AddItem("st_dress_outfit", NULL, INVENTORY_TO_SLOT_ACTION);
        b_show = true;
    }

    CCustomOutfit* outfit_in_slot = m_pActorInvOwner->GetOutfit();
    if (pHelmet && !bAlreadyDressed && (!outfit_in_slot || outfit_in_slot->bIsHelmetAvaliable))
    {
        m_UIPropertiesBox->AddItem("st_dress_helmet", NULL, INVENTORY_TO_SLOT_ACTION);
        b_show = true;
    }
    if (pBackpack && !bAlreadyDressed && (!outfit_in_slot || outfit_in_slot->bIsBackpackAvaliable))
    {
        m_UIPropertiesBox->AddItem("st_dress_backpack", NULL, INVENTORY_TO_SLOT_ACTION);
        b_show = true;
    }
}

Теперь в функции
 


void CUIActorMenu::UpdateOutfit()

Сразу после


    if (m_pLists[eInventoryHelmetList])
    {
        if (outfit && !outfit->bIsHelmetAvaliable)
            m_pLists[eInventoryHelmetList]->SetCellsCapacity({ 0, 0 });
        else
            m_pLists[eInventoryHelmetList]->SetCellsCapacity(m_pLists[eInventoryHelmetList]->MaxCellsCapacity());
    }

Добавляем
 


   if (m_pLists[eInventoryBackpackList])
    {
        if (outfit && !outfit->bIsBackpackAvaliable)
            m_pLists[eInventoryBackpackList]->SetCellsCapacity({ 0, 0 });
        else
            m_pLists[eInventoryBackpackList]->SetCellsCapacity(m_pLists[eInventoryBackpackList]->MaxCellsCapacity());
    }

Теперь откроем файл UIActorMenuInitialize.cpp

Найдём данную строку


        { eInventoryHelmetList,    	"dragdrop_helmet",          "progess_bar_helmet",  	"helmet_slot_highlight",   "helmet_over",      false },

И после добавим


        { eInventoryBackpackList,    "dragdrop_backpack",          nullptr,  	"backpack_slot_highlight",   "backpack_over",      false },

Теперь ищем строки


    if (m_pLists[eInventoryHelmetList])
        m_pLists[eInventoryHelmetList]->SetMaxCellsCapacity(m_pLists[eInventoryHelmetList]->CellsCapacity());

Добавим после них


    if (m_pLists[eInventoryBackpackList])
        m_pLists[eInventoryBackpackList]->SetMaxCellsCapacity(m_pLists[eInventoryBackpackList]->CellsCapacity());

Теперь ищем строку


    BindDragDropListEvents(m_pLists[eInventoryHelmetList]);

И после неё добавим


    BindDragDropListEvents(m_pLists[eInventoryBackpackList]);

Теперь идём в файл UIInventoryUpgradeWnd.cpp
И там также как и везде добавляем
 


#include "ActorBackpack.h"

Дальше в функции
 


void CUIInventoryUpgradeWnd::InitInventory(CUICellItem* cellItem, bool can_upgrade)

Меняем это
 


        else if (smart_cast<CCustomOutfit*>(m_inv_item) || smart_cast<CHelmet*>(m_inv_item))
        {
            is_shader = true;
            m_item->SetShader(InventoryUtilities::GetOutfitUpgradeIconsShader());
        }

На это
 


        else if (smart_cast<CCustomOutfit*>(m_inv_item) || smart_cast<CHelmet*>(m_inv_item) || smart_cast<CBackpack*>(m_inv_item))
        {
            is_shader = true;
            m_item->SetShader(InventoryUtilities::GetOutfitUpgradeIconsShader());
        }

Теперь идём в xrServerEntities
Ищем там файл object_factory_register.cpp
И в нём сразу после 
 


#include "ActorHelmet.h"

Добавляем


#include "ActorBackpack.h"

Теперь ищем строку
 


    ADD(CHelmet, CSE_ALifeItem, CLSID_EQUIPMENT_HELMET, "helmet");

И сразу после неё добавляем
 


    ADD(CBackpack, CSE_ALifeItemBackpack, CLSID_EQUIPMENT_BACKPACK, "equ_backpack");

Теперь идём в файл clsid_game.h
И там после
 


#define CLSID_EQUIPMENT_HELMET MK_CLSID('E', 'Q', '_', 'H', 'L', 'M', 'E', 'T')

Добавляем
 


#define CLSID_EQUIPMENT_BACKPACK MK_CLSID('E','Q','_','B','A','K','P','K')

Теперь идём в файл inventory_space.h

И после 



    HELMET_SLOT, // helmet

Добавляем
 


	BACKPACK_SLOT, // backpack

Теперь идём в файл xrServer_Objects_ALife_Items.cpp
И сразу после
 


////////////////////////////////////////////////////////////////////////////
// CSE_ALifeItemHelmet
////////////////////////////////////////////////////////////////////////////
CSE_ALifeItemHelmet::CSE_ALifeItemHelmet(LPCSTR caSection) : CSE_ALifeItem(caSection) {}
CSE_ALifeItemHelmet::~CSE_ALifeItemHelmet() {}
void CSE_ALifeItemHelmet::STATE_Read(NET_Packet& tNetPacket, u16 size) { inherited::STATE_Read(tNetPacket, size); }
void CSE_ALifeItemHelmet::STATE_Write(NET_Packet& tNetPacket) { inherited::STATE_Write(tNetPacket); }
void CSE_ALifeItemHelmet::UPDATE_Read(NET_Packet& tNetPacket)
{
    inherited::UPDATE_Read(tNetPacket);
    tNetPacket.r_float_q8(m_fCondition, 0.0f, 1.0f);
}

void CSE_ALifeItemHelmet::UPDATE_Write(NET_Packet& tNetPacket)
{
    inherited::UPDATE_Write(tNetPacket);
    tNetPacket.w_float_q8(m_fCondition, 0.0f, 1.0f);
}

#ifndef XRGAME_EXPORTS
void CSE_ALifeItemHelmet::FillProps(LPCSTR pref, PropItemVec& items) { inherited::FillProps(pref, items); }
#endif // #ifndef XRGAME_EXPORTS

BOOL CSE_ALifeItemHelmet::Net_Relevant() { return (true); }

Добавляем
 


////////////////////////////////////////////////////////////////////////////
// CSE_ALifeItemBackpack
////////////////////////////////////////////////////////////////////////////
CSE_ALifeItemBackpack::CSE_ALifeItemBackpack(LPCSTR caSection) : CSE_ALifeItem(caSection) {}
CSE_ALifeItemBackpack::~CSE_ALifeItemBackpack() {}
void CSE_ALifeItemBackpack::STATE_Read(NET_Packet& tNetPacket, u16 size) { inherited::STATE_Read(tNetPacket, size); }
void CSE_ALifeItemBackpack::STATE_Write(NET_Packet& tNetPacket) { inherited::STATE_Write(tNetPacket); }
void CSE_ALifeItemBackpack::UPDATE_Read(NET_Packet& tNetPacket)
{
    inherited::UPDATE_Read(tNetPacket);
    tNetPacket.r_float_q8(m_fCondition, 0.0f, 1.0f);
}

void CSE_ALifeItemBackpack::UPDATE_Write(NET_Packet& tNetPacket)
{
    inherited::UPDATE_Write(tNetPacket);
    tNetPacket.w_float_q8(m_fCondition, 0.0f, 1.0f);
}

#ifndef XRGAME_EXPORTS
void CSE_ALifeItemBackpack::FillProps(LPCSTR pref, PropItemVec& items) { inherited::FillProps(pref, items); }
#endif // #ifndef XRGAME_EXPORTS

BOOL CSE_ALifeItemBackpack::Net_Relevant() { return (true); }

Дальше идём в xrServer_Objects_ALife_Items.h
И сразу после
 


class CSE_ALifeItemHelmet : public CSE_ALifeItem
{
    using inherited = CSE_ALifeItem;

public:
    CSE_ALifeItemHelmet(LPCSTR caSection);
    virtual ~CSE_ALifeItemHelmet();
    virtual BOOL Net_Relevant();
    virtual void UPDATE_Read(NET_Packet& P);
    virtual void UPDATE_Write(NET_Packet& P);
    virtual void STATE_Read(NET_Packet& P, u16 size);
    virtual void STATE_Write(NET_Packet& P);
    SERVER_ENTITY_EDITOR_METHODS
};

Добавляем
 


class CSE_ALifeItemBackpack : public CSE_ALifeItem
{
    using inherited = CSE_ALifeItem;

public:
    CSE_ALifeItemBackpack(LPCSTR caSection);
    virtual ~CSE_ALifeItemBackpack();
    virtual BOOL Net_Relevant();
    virtual void UPDATE_Read(NET_Packet& P);
    virtual void UPDATE_Write(NET_Packet& P);
    virtual void STATE_Read(NET_Packet& P, u16 size);
    virtual void STATE_Write(NET_Packet& P);
    SERVER_ENTITY_EDITOR_METHODS
};

Теперь идём в файл xrServer_Objects_ALife_Items_script2.cpp
И после
 


SCRIPT_EXPORT(CSE_ALifeItemHelmet, (CSE_ALifeItem),
    { module(luaState)[luabind_class_item1(CSE_ALifeItemHelmet, "cse_alife_item_helmet", CSE_ALifeItem)]; });

Добавляем
 


SCRIPT_EXPORT(CSE_ALifeItemBackpack, (CSE_ALifeItem),
    { module(luaState)[luabind_class_item1(CSE_ALifeItemBackpack, "cse_alife_item_backpack", CSE_ALifeItem)]; });

Всё. С движком закончили. Дальше дело за малым. Отредактировать xml, сделать файл рюкзака и зарегистрировать его в System.ltx
Так же в том же самом System.ltx меняем slots_count вместо 12 на 13
Также после
slot_persistent_12  = false ;helmet
slot_active_12      = false

Добавим

slot_persistent_13  = false ;backpack
slot_active_13      = false

 

Всё, теперь точно закончили. Если что, тестовый файл рюкзака я прикреплю, поэтому достаточно будет зарегистрировать его в System.ltx и добавить в папку misc для удобства. 
Урок Doctor_Oz (Даниил Озол)
Код взят из Call of Chernobyl(нужна будет ссылка попросите, отправлю отдельным сообщением в теме)

Так же если вы в костюм добавите isBackpackAvaiable = false то у вас будет закрыт слот рюкзака(по умолчанию он открыт)
Всем благ! Будут проблемы обращайтесь!

Спойлер

Редактировать надо только один файл, ActorAnimation.cpp
Ищем функцию 


void CActor::g_SetAnimation(u32 mstate_rl)

В ней ищем строки 
 


                        case CArtefact::eIdle: M_torso = TW->moving[moving_idx]; break;
                        case CArtefact::eShowing: M_torso = TW->draw; break;
                        case CArtefact::eHiding: M_torso = TW->holster; break;
                        case CArtefact::eActivating: M_torso = TW->zoom; break;
                        default: M_torso = TW->moving[moving_idx];

После этих строк идут такие скобки } и после 5 пишем данный текст:
 


		else if (!m_bAnimTorsoPlayed)
        {
        if (moving_idx == STorsoWpn::eSprint)
            M_torso = ST->m_torso[0].moving[moving_idx];
        else
            M_torso = ST->m_torso[4].moving[moving_idx]; //Alundaio: Fix torso anim no wpn
        }

Всё, теперь можно собирать. Скриншоты прилагаются:
ss-06-01-22-19-51-58-arena.jpg
ss-06-01-22-19-51-59-arena.jpg
ss-06-01-22-19-52-06-arena.jpgss-06-01-22-19-52-07-arena.jpg

 

Урок от Doctor_Oz (Даниил Озол)
Код был дан разработчиком M.F.S. Team

backpack.ltx

Изменено пользователем Doctor_Oz
  • Мастер! 3
  • Смущение 1
  • Хабар 4

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


Ссылка на сообщение
Поделиться на другие сайты
 

Добавил новый урок.

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


Ссылка на сообщение
Поделиться на другие сайты
 

Я не разбиоаюсь в кодах движков, и хотел бы спросить 2 вопроса.

1. Инструкцию "Как добавить щелчок при включения фонарика" можно провернуть например на OGSR Engine, как я знаю, там код ЗПшного движка.

2. В какой dll. Файл, Torch.h и Torch.cpp будут компилироваться при компиляции движка в dll. Файлы?


973993194_.png.976c126d2bdec0c06760be6027acfaff.png

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


Ссылка на сообщение
Поделиться на другие сайты
 

Hikki 1. ЗП

2. xrGame, в нём же Torch.

  • Жму руку 1

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


Ссылка на сообщение
Поделиться на другие сайты
 
1 минуту назад, Hikki сказал:

Я не разбиоаюсь в кодах движков, и хотел бы спросить 2 вопроса.

1. Инструкцию "Как добавить щелчок при включения фонарика" можно провернуть например на OGSR Engine, как я знаю, там код ЗПшного движка.

2. В какой dll. Файл, Torch.h и Torch.cpp будут компилироваться при компиляции движка в dll. Файлы?

Хм, забыл сказать что ВСЕ уроки чисто по xrGame
Да, это возможно, но вроде в OGSR же есть уже звук щелчка, не?

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


Ссылка на сообщение
Поделиться на другие сайты
 
Только что, Hikki сказал:

OGSR Engine

Если ничего не переименовали, то можно ctrl c ctrl v


Дополнено 0 минут спустя
Только что, Doctor_Oz сказал:

Да, это возможно, но вроде в OGSR же есть уже звук щелчка, не?

Ща гляну

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


Ссылка на сообщение
Поделиться на другие сайты
 
Только что, Misery сказал:

Если ничего не переименовали, то можно ctrl c ctrl v

Не факт, код я брал с СоС'а так что навряд-ли...

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


Ссылка на сообщение
Поделиться на другие сайты
 
Только что, Doctor_Oz сказал:

Да, это возможно, но вроде в OGSR же есть уже звук щелчка, не?

Нема


Дополнено 0 минут спустя

Из весомых отличий могу отметить только, что в OGSR по другому написана загрузка звука

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


Ссылка на сообщение
Поделиться на другие сайты
 
Только что, Misery сказал:

Нема

Значит можно добавить, но по OGSR я не помогу, ибо я оттуда ток правки умею тыбзить))

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


Ссылка на сообщение
Поделиться на другие сайты
 

HUD_SOUND::LoadSound
HUD_SOUND::PlaySound
HUD_SOUND::StopSound
HUD_SOUND::DestroySound

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

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


Ссылка на сообщение
Поделиться на другие сайты
 
Только что, Doctor_Oz сказал:

ибо я оттуда ток правки умею тыбзить))

Жиза)

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


Ссылка на сообщение
Поделиться на другие сайты
 

Добавил новый урок.

  • Лайк 1

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


Ссылка на сообщение
Поделиться на другие сайты
 

Ожидайте в течение недели добавление урока по добавлению рюкзака в двиг!!! 

P. S. Если у вас возникла та или иная проблема, то напишите мне пожалуйста, дабы я мог исправить ситуацию. 

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


Ссылка на сообщение
Поделиться на другие сайты
 

Doctor_Oz а не с моих ли это сурсов было взято, из мода "Суждено быть новичком"?
Просто возникли подозрения, потому что у меня всё это уже было сделано в исходниках: звук включения фонарика из ОП, 10 слотов под артефакты (в уроке 8), новые слоты за авторством Suhar_ и мой перенос на движок OpenXray, нужная надпись в мини-окне, которая выводит возможные действия с предметом. Если всё это так, то укажите моё авторство + добавьте других авторов, и ещё не забудьте добавить мою систему ремонта на деталях вдобавок к разряжаемым экзоскелетам)
А иначе как получается: другие люди написали этот код, ты его сюда выложил, зарабатываешь репутацию на этой теме а создателей не указываешь... Нельзя так.

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


Ссылка на сообщение
Поделиться на другие сайты
 
Только что, liner сказал:

Doctor_Oz а не с моих ли это сурсов было взято, из мода "Суждено быть новичком"?
Просто возникли подозрения, потому что у меня всё это уже было сделано в исходниках: звук включения фонарика из ОП, 10 слотов под артефакты (в уроке 8), новые слоты за авторством Suhar_ и мой перенос на движок OpenXray, нужная надпись в мини-окне, которая выводит возможные действия с предметом. Если всё это так, то укажите моё авторство + добавьте других авторов, и ещё не забудьте добавить мою систему ремонта на деталях вдобавок к разряжаемым экзоскелетам)
А иначе как получается: другие люди написали этот код, ты его сюда выложил, зарабатываешь репутацию на этой теме а создателей не указываешь... Нельзя так.

Не-не
Авторы данных правок:
Новые слоты (сам догадался)
Кол-во слотов под артефакты так-же пришлось самому искать.
Звук включения фонарика был взят из СоС (Автор мне лично неизвестен)
use_caption за авторством Suhar_ был взят из  Lex_Addon.

  • Мастер! 1

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


Ссылка на сообщение
Поделиться на другие сайты
 

Если вы используете наработки из других модов, то пожалуйста, не удаляйте копирайты и оставляйте благодарность автору(ам), ведь это элементарная этика модостроения! Ведь это делается за бесплатно!

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


Ссылка на сообщение
Поделиться на другие сайты
 
Только что, liner сказал:

Если вы используете наработки из других модов, то пожалуйста, не удаляйте копирайты и оставляйте благодарность автору(ам), ведь это элементарная этика модостроения! Ведь это делается за бесплатно!

Этим я собирался заняться в течение недели, поэтому всех авторов я отмечу, ибо сам понимаю что обидно когда твои труды выдают за свои, а я между прочим не говорил что автор всех этих правок Я.

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


Ссылка на сообщение
Поделиться на другие сайты
 
Только что, Doctor_Oz сказал:

Кол-во слотов под артефакты так-же пришлось самому искать.

Правки у Suhar_ делались на оригинальном двигле, некоторые вещи пришлось переводить самому под рельсы OpenXray.
Советую глянуть, что у меня реализовано в двигле.

Помню точно, что адаптировал такие моды, как:
деградация артефактов из CoC (Автор: Alundaio)
расширенные свойства брони из Lex Addon (Автор: Suhar_)
ну и то что выше перечислил.

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


Ссылка на сообщение
Поделиться на другие сайты
 
Только что, liner сказал:

Правки у Suhar_ делались на оригинальном двигле, некоторые вещи пришлось переводить самому под рельсы OpenXray.
Советую глянуть, что у меня реализовано в двигле.

Помню точно, что адаптировал такие моды, как:
деградация артефактов из CoC (Автор: Alundaio)
расширенные свойства брони из Lex Addon (Автор: Suhar_)
ну и то что выше перечислил.

Но я не говорил что я брал что-то у вас, я всё брал чисто у Lex, про ваш мод слышу впервые... Так что не надо гнать на меня что я у вас что-то украл. А если не верите мне, то я просто могу скинуть все ссылки на те сайты откуда бралось что-либо.

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


Ссылка на сообщение
Поделиться на другие сайты
 
8 минут назад, Doctor_Oz сказал:

а я между прочим не говорил что автор всех этих правок Я.

Есть такие люди. Одного такого помню. Короче, раньше был проект StalkerDVA (именно так он и назывался!!!). Мультиплеер на ЗП, кооператив, все дела... Но только вот автор оказался ещё той крысой... Адаптировал броню из сткопа, ещё из других модов понемножку, и кстати, за основу проекта взял Soproject, который раньше (в годах так 2010-2013) был популярен как мод, где есть кооператив. Я играл и в то, и в другое. Мануэль снимал видео на этот мультиплеерный мод, его популярность возросла. И так вот, разработчик этого "второго сталкера", Вано как он себя называл, сказал, что релизнет новую версию, как только на его кошельке соберётся 5000 рублей. Это уже полный зашквар. Думаю, ты понял, к чему я всё это. Мод потом через полгода окончательно закрылся.


Дополнено 1 минуту спустя
3 минуты назад, Doctor_Oz сказал:

Так что не надо гнать на меня что я у вас что-то украл. А если не верите мне, то я просто могу скинуть все ссылки на те сайты откуда бралось что-либо.

Я и не утверждал, что это мои правки. Без негатива.

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

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


Ссылка на сообщение
Поделиться на другие сайты
 
Только что, liner сказал:

Есть такие люди. Одного такого помню. Короче, раньше был проект STALKER 2 (именно так он и назывался!!!). Мультиплеер на ЗП, кооператив, все дела... Но только вот автор оказался ещё той крысой... Адаптировал броню из сткопа, ещё из других модов понемножку, и кстати, за основу проекта взял Soproject, который раньше (в годах так 2010-2013) был популярен как мод, где есть кооператив. Я играл и в то, и в другое. Мануэль снимал видео на этот мультиплеерный мод, его популярность возросла. И так вот, разработчик этого "второго сталкера", Вано как он себя называл, сказал, что релизнет новую версию, как только на его кошельке соберётся 5000 рублей. Это уже полный зашквар. Думаю, ты понял, к чему я всё это.

Но я ничего не прошу взамен... Зачем на меня то гнать? Я этого понять не могу. Я во-первых не утверждал что автор правок Я, во-вторых Я не делаю это взамен на что-то. Это делается для таких же людей как Я, ведь даже самая небольшая правка движка занимает уйму времени у новичков. Я конечно тоже мод делаю, но как Я и говорил, Я не собираюсь присваивать чужие правки себе, спрашивается, зачем мне лишние проблемы?
 

  • Жму руку 1

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


Ссылка на сообщение
Поделиться на другие сайты
 

К дополнению про StalkerDVA: потом блогер Неважно, кто выложил видео на всю эту суету. У него похожее мнение, что и у меня. Но то видео по-моему, он уже удалил, ибо я его на его канале уже давно не нахожу.

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


Ссылка на сообщение
Поделиться на другие сайты
 

Добрый день. Если у вас после моего урока по добавлению звука щелчка в фонарик нет звука, Я изменил урок, точнее добавил то что нужно в сам фонарик секцию включения и выключения. Вылетать не будет, но и работать звук. 
P. S. сам только-только разобрался ?

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


Ссылка на сообщение
Поделиться на другие сайты
 

Сделан урок по добавлению рюкзака. Оформление не очень, поэтому прошу оформить модераторов как будет покрасивше. Если у вас будут проблемы касательно этого урока, говорите, поможем.


Дополнено 15 минуты спустя

Добавил урок по изгнанию Наруто из ГГ.

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


Ссылка на сообщение
Поделиться на другие сайты
 

Добрый день, если у вас есть предложения по урокам, то если возможно я добавлю в шапку темы. 

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


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу