Jump to content

Edytowanie OpenXRay


Recommended Posts

OPENXRAY:

 

REPOZYTORIUM ZWYKŁEGO SILNIKA:

 

UWAGA!!! Wszystkie poprawki dokonywane są w pliku xrGame.dll. Jeśli nie zostaną tam utworzone, będzie utworzony osobny spoiler do edycji innych bibliotek !!!

 

LEKCJE OD DOCTOR_OZ:

Spoiler

JAK DODAĆ NOWE SLOTY DO INWENTARZA (NÓŻ, LORNETKĘ, itd.):

Spoiler

Autor tej lekcji: Doctor_Oz (Даниил Озол)

 

Będziemy edytować plik UIActorMenuInitialize.cpp.

Szukamy tej linijki:

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

Jak zapewne zauważyliście (jeśli chociaż trochę znacie język angielski), to jest to tablica z kilkoma odnośnikami, a dokładnie na takie parametry jak: ikonka, stopień uszkodzenia (pasek stanu), podświetlenie i ikonka blokady (jak w hełmie w egzoszkielecie lub artefaktów).

Dodajemy tutaj takie linijki:

{ eInventoryKnifeList,     "dragdrop_knife",           "progess_bar_knife",   "knife_slot_highlight",    nullptr,            true }, // Nóż
{ eInventoryBinocularList, "dragdrop_binocular",       nullptr,               "binocular_slot_highlight",nullptr,            true }, // Lornetka

Jeśli chcemy w lornetce zrobić pasek stanu, to można dodać w drugiej linijce na miejsce pierwszej z wartością "nullptr" - wartość "progess_bar_binocular" (najważniejsze, aby nie zapomnieć dodać tego do actor_menu).

Teraz szukamy tej linijki:

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

Jest to także tablica, do której trzeba dodać te linijki:

{ eInventoryKnifeList,     "dragdrop_knife",     m_pInventoryWnd }, // Nóż
{ eInventoryBinocularList, "dragdrop_binocular", m_pInventoryWnd }, // Lornetka

Szukamy tej linijki:

BindDragDropListEvents(m_pLists[eInventoryAutomaticList]);

I dokładnie po niej dodajemy to:

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

 

 

Z pierwszym plikiem już skończyliśmy pracę. Przechodzimy do drugiego, a mianowicie UIActorMenuInventory.cpp.

W nim potrzebna jest nam linijka:

void CUIActorMenu::InitInventoryMode()

To znowu tablica, a w niej (najlepiej na środku) musisz dodać to:

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

Teraz w tablicy:

CUIDragDropListEx* all_lists[] =

Dodajemy następujące elementy, oddzielając je przecinkami (najlepiej tak, jak pierwotnie zrobiono), czyli to:

m_pLists[eInventoryKnifeList], m_pLists[eInventoryBinocularList],

 

Trzeba dodać tak, aby wszystko wyglądało tak (chociaż jest to nieobowiązkowe):

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]

 

Z jeszcze jedną tablicą skończyliśmy pracę. Nie martw się, będzie ich jeszcze trochę więcej:)
Trzeba zmienić jeszcze jedną tablicę. Szukamy linijki:

if (onlyBagList)

Od razu po niej jest lista slotów:

INV_SLOT2
INV_SLOT3

itd.

 

Od razu po nich, trzeba usunąć następujące linijki:

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

Następnie zmieniamy kolejną tablicę, można ją znaleźć po takiej linijce:

CUIDragDropListEx* CUIActorMenu::GetSlotList(u16 slot_idx)

W niej trzeba zmienić:

case KNIFE_SLOT:
case BINOCULAR_SLOT:

na:

case KNIFE_SLOT: return m_pLists[eInventoryKnifeList]; break;

case BINOCULAR_SLOT: return m_pLists[eInventoryBinocularList]; break;

 

Z drugim plikiem skończyliśmy pracę. Teraz następny, a dokładnie UIActorMenu.cpp.

Na początku dodamy do include dwa pliki:

#include "WeaponKnife.h"

#include "WeaponBinocular.h"

 

Do tablicy:

EDDListType CUIActorMenu::GetListType(CUIDragDropListEx* l)

dodajemy:

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

 

Do tablicy:

void CUIActorMenu::clear_highlight_lists()

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

 

Do tablicy:

void CUIActorMenu::highlight_item_slot(CUICellItem* cell_item)

dodajemy po tym:

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

takie coś:

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

 

Również po:

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

dodajemy:

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

 

Do tablicy:

void CUIActorMenu::ClearAllLists()

dodajemy:

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

 

Teraz w pliku: UIActorMenu.h dodajemy odnośniki:

Do tablicy:

enum eActorMenuListType

to:

eInventoryKnifeList,
eInventoryBinocularList,

 

I to wszystko, można kompilować silnik (jeśli zakończyliście). I kiedy go skompilujecie, przystąpimy do samego UI. Uwaga od twórcy lekcji - rysować będziecie sami, autor pokaże przykładowo, całe UI będziecie musieli samodzielnie dostosowywać, dla swojego inwentarza. Dla edycji bierzemy actor_menu.xml - ten plik odpowiada za rozdzielczość 1024x768, a actor_menu_16.xml odpowiada za panoramiczny rozmiar, w nim robicie praktycznie to samo, co w pierwszym. Będą się jedynie różnić współrzędnymi i rozmiarem kilku pikseli (jeśli jesteście zaznajomieni z UI to sami wiecie).

Przystępujemy do edytowania:

Po fragmencie:

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

dodajemy następujące rzeczy (zrobione na przykładzie detektora, ale działa wyśmienicie):

<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>

 

Teraz po:

<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>

 

Dodajemy:

<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>

 

Również dodajemy po:

<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"/>

 

takie coś:

<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"/>

 

W system.ltx poprawiamy następujące linijki:

slot_persistent_1   = true   ;knife
slot_active_1       = true

na takie coś:

slot_persistent_1   = false   ;knife
slot_active_1       = true

Również:

slot_persistent_5   = true   ;binocular
slot_active_5       = true

na:

slot_persistent_5   = false   ;binocular
slot_active_5       = true

 

To chyba wszystko. Jeśli wystąpi wylot bez logu, to znaczy, że gdzieś jest błąd w kodzie.

 

DODANIE DODATKOWYCH SLOTÓW NA ARTEFAKTY:

Spoiler

Autor lekcji: Doctor_Oz(Даниил Озол)

Autor poprawki: Doctor_Oz(Даниил Озол)

 

Najpierw zmienimy ilość artefaktów w samym plecaku (nie szukaj sensu, nie ma go XD).

 

Otwieramy plik Inventory.cpp i znajdujemy linijkę:

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

Trzeba zmienić cyfrę (odradza się zmiany na większą). Autor lekcji zmienił na 8 (na początku było 5).

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

 

Ponieważ zmieniliśmy systemową ilość artefaktów, musimy zmienić max. liczbę slotów, które mogą zostać otwarte przez pancerz.

Otwieramy plik CustomOutfit.cpp i znajdujemy funkcję:

void CCustomOutfit::Load(LPCSTR section)

W tej funkcji szukamy linijki:

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

i zmieniamy na:

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

 

Również w pliku znajdujemy funkcję (wiadomo, że zmienna, jednakże):

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

a w niej szukamy dokładnie takiej linijki i zmieniamy ją:

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

na:

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

 

I to chyba wszystko. Możecie teraz zmienić ilość slotów na artefakty w outfit.ltx, UI i System.ltx, tak jak było robione (jeśli nie robiliście to Google na pomoc).

 

JAK DODAĆ PRZYCIŚNIĘCIE PRZY WŁĄCZENIU LATARKI:

Spoiler

Autor lekcji: Doctor_Oz(Даниил Озол)

Autor poprawki: nieznany, na GitHub jest revolucas, kod wzięto z otwartego repozytorium Call of Chernobyl (link na commit)

Do edycji będą potrzebne dwa pliki: Torch.cpp i Torch.h.

 

Otwieramy plik Torch.cpp i jeśli niczego nie edytowaliśmy, to szukamy funkcji w 76 linijce:

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");
}

 

Zmieniamy ją na:

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");
}

 

Szukamy teraz funkcji void CTorch::Switch(bool light_on) i żebyś nie zawracał sobie głowy (jeśli oczywiście NIE edytowałeś wcześniej pliku), po prostu zmień na taką:

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);
    }
}

 

Również zmieniamy funkcję bool CTorch::net_Spawn(CSE_Abstract* DC) na taką:

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"));

    //włączyć/wyłączyć latarkę
    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);
}

 

To ostatnie zostało dodane nie dla dźwięka, a dlatego że zmienialiśmy TORCH_DEFINITION na m_light_section i teraz trzeba zarejestrować ten sam m_light_section.
Otwieramy plik Torch.h i od razu po Fvector m_focus; dodajemy to: shared_str m_light_section;
Aby wyszło tak:

    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;

 

Również torch.zip do folderu sounds, wrzucamy dźwięki włączenia i wyłączenia (początkowo są one jednakowe, ale możecie zmienić na swoje). 

W pliku, gdzie są przechowywane device_torch (początkowo znajduje się on w misc\items.ltx), w samym device_torch trzeba dodać linijki:

snd_turn_on                              = torch\nazwa_dźwięku_włączania ;(pisać bez rozszerzenia .ogg)
snd_turn_off                             = torch\nazwa_dźwięku_wyłączania ;(pisać bez rozszerzenia .ogg)

 

 

ZMIANA NAPISU, PO NACIŚNIĘCIU PRAWEGO PRZYCISKU MYSZY NA UŻYWANY PRZEDMIOT (TYPU "ZJEŚĆ", "WYPIĆ", ITD.) DLA DOWOLNEGO NAPISU:

Spoiler

Autor lekcji: Doctor_Oz(Даниил Озол)

Autor poprawki: Suhar_ (Lex_Addon)

Do edycji będzie tylko jeden plik w silniku i jeden w gamedata.
Na początku zaczniemy od silnika i otworzymy plik: UIActorMenuInventory.cpp
I jeśli już go edytowałeś to szukamy funkcji: void CUIActorMenu::PropertiesBoxForUsing(PIItem item, bool& b_show)
A w niej te linijki:

			// 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";

I zamieniamy je na:

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

Teraz przy korzystaniu z DOWOLNEGO przedmiotu, będzie wyświetlany napis "Użyć".
Aby to zmienić wystarczy podać w sekcji:

use_caption = st_wasz_id_tekstu

Najważniejsze, aby ulokować ten napis - w przeciwnym wypadku, będzie widzieli napis "st_wasz_id_tekstu".

 

LEKCJA NT. DODAWANIA PLECAKA:

Spoiler

W xrGame tworzymy filtr (naciskamy na jakiś folder, twórca lekcji wybrał xrGame/core/client/objects/item&weapons/) i nazwijmy go Backpack. W nim tworzymy nowy element. Podczas tworzenia wyświetli się lista i w niej trzeba wybrać ".cpp". Na dole trzeba wpisać nazwę ActorBackpack.cpp. I takim sposobem tworzymy plik ".h" . Nazwa wyróżni się tym, że zamiast .cpp trzeba wpisać .h. 

Po tym jak je stworzyliśmy, zaczynamy ich edytowanie. Na początku otwieramy ActorBackpack.h, wydzielamy wszystko i umieszczamy w nim to:

#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);
}; 

 

Teraz otwieramy ActorBackpack.cpp i wpisujemy:

#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;
} 

I to wszystko. Pliki można zamknąć. Będziemy je ruszać, jeśli będziemy potrzebowali dodać jakąś funkcję taką jak ZSO (Zamknięty system oddychania - tzn. dodać butlę z tlenem). Teraz zajmiemy się funkcją dodania udźwigu. Otwieramy Actor_Movement.cpp i szukamy funkcji:

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;
}

 

Na początku przed tą linijką:

#include "Artefact.h"

Po niej dodajemy, ale nie w funkcji:

#include "ActorBackpack.h"

 

Teraz zmieniamy samą funkcję na taką:

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;
}

 

Zakończyliśmy pracę z tym plikiem. Idziemy do następnego CustomOutfit.cpp. Edytujemy go po to, aby można było zrobić możliwość zamknięcia slotu, np. w tym egzoszkielecie. Od razu po:

#include "ActorHelmet.h"

dodajemy:

#include "ActorBackpack.h"

 

Teraz po:

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

dodajemy:

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

 

Teraz szukamy funkcji:

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);

        }
    }
}

 

i zmieniamy na taką:

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);
        }
    }
}

 

Dalej wchodzimy w CustomOutfit.h i po:

    bool bIsHelmetAvaliable;

dodajemy:

    bool bIsBackpackAvaliable;

 

Teraz wchodzimy w Inventory.cpp i zamiast:

    false // helmet

stawiamy:

    false, // helmet
    false // backpack

 

Teraz w funkcji:

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

 

Od razu po:

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

dodajemy:

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

 

I to wszystko. Wchodzimy teraz do EntityConditions.cpp. Po:

#include "ActorHelmet.h"

dodajemy:

#include "ActorBackpack.h"

 

Szukamy funkcji:

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));
}

 

Zakończyliśmy pracę z kolejnym plikiem. Otwieramy plik InventoryOwner.cpp i PRZED tym:

float CInventoryOwner::MaxCarryWeight() const

dodajemy:

#include "ActorBackpack.h"

 

I zmieniamy całą funkcję:

float CInventoryOwner::MaxCarryWeight() const

na:

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;
}

 

Przechodzimy do script_game_object_inventory_owner.cpp.

I po:

#include "PhysicObject.h"

dodajemy:

#include "ActorBackpack.h"

 

Teraz zajmujemy się zamianą funkcji (funkcja to nie tylko linijka, ale wszystko w nawiasach klamrowych{...} po niej):

Zamieniamy to:

float CScriptGameObject::GetAdditionalMaxWeight() const

na:

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);
}

 

Teraz to:

float CScriptGameObject::GetAdditionalMaxWalkWeight() const

na:

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);
}

 

Później to:

void CScriptGameObject::SetAdditionalMaxWeight(float add_max_weight)

na:

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;
}

 

Teraz to:

void CScriptGameObject::SetAdditionalMaxWalkWeight(float add_max_walk_weight)

na:

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;
}

 

I to wszystko. Zajmiemy się teraz częścią związaną z UI.

Otwieramy UIActorMenu.h i po:

        eInventoryHelmetList,

dodajemy:

        eInventoryBackpackList,

 

Otwieramy UIActorMenu.cpp i od razu po:

#include "ActorHelmet.h"

dodajemy:

#include "ActorBackpack.h"

 

Teraz do funkcji:

EDDListType CUIActorMenu::GetListType(CUIDragDropListEx* l)

po:

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

dodajemy:

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

 

W funkcji:

void CUIActorMenu::clear_highlight_lists()

po:

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

dodajemy:

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

 

W funkcji:

void CUIActorMenu::highlight_item_slot(CUICellItem* cell_item)

po:

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

dodajemy:

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

 

Dalej po:

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

dodajemy:

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

 

W funkcji:

void CUIActorMenu::ClearAllLists()

po:

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

dodajemy:

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

 

Wchodzimy do UIActorMenuInventory.cpp

#include "actor_defs.h"

piszemy:

#include "ActorBackpack.h"

 

W funkcji:

void CUIActorMenu::InitInventoryMode()

po:

    ShowIfExist(m_pLists[eInventoryHelmetList], true);

dodajemy:

    ShowIfExist(m_pLists[eInventoryBackpackList], true);

 

Później w funkcji:

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

po:

		m_pLists[eInventoryHelmetList],

dodajemy:

		m_pLists[eInventoryBackpackList], 

 

Szukamy linijki:

    InitCellForSlot(HELMET_SLOT);

i po niej:

    InitCellForSlot(BACKPACK_SLOT);

 

Funkcję:

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

zmieniamy na:

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;
    }
}

 

W funkcji:

CUIDragDropListEx* CUIActorMenu::GetSlotList(u16 slot_idx)

po:

    case HELMET_SLOT: return m_pLists[eInventoryHelmetList]; break;

dodajemy:

    case BACKPACK_SLOT: return m_pLists[eInventoryBackpackList]; break;

 

Funkcję:

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

zmieniamy na:

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();

    // Flaga dla wyłączenia punktu kontekstowego menu: Dress Outfit, jeśli pancerz jest już założony
    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;
    }
}

 

W funkcji:

void CUIActorMenu::UpdateOutfit()

po:

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

dodajemy:

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

 

Otwieramy plik UIActorMenuInitialize.cpp

Szukamy tej linijki:

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

i po niej dodajemy:

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

 

Szukamy linijek:

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

dodajemy po nich:

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

 

Szukamy linijki:

    BindDragDropListEvents(m_pLists[eInventoryHelmetList]);

i po niej dodajemy:

    BindDragDropListEvents(m_pLists[eInventoryBackpackList]);

 

Wchodzimy do pliku UIInventoryUpgradeWnd.cpp

I tam, jak wszędzie, dodajemy:

#include "ActorBackpack.h"

 

Później w funkcji:

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

zmieniamy to:

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

na to:

        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());
        }

 

Wchodzimy do xrServerEntities

Szukamy tam pliku object_factory_register.cpp

I w nim po:

#include "ActorHelmet.h"

dodajemy:

#include "ActorBackpack.h"

 

Szukamy linijki:

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

i po niej dodajemy:

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

 

Wchodzimy do pliku clsid_game.h

I po:

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

dodajemy:

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

 

Wchodzimy do pliku inventory_space.h

I po:

    HELMET_SLOT, // helmet

dodajemy:

	BACKPACK_SLOT, // backpack

 

Wchodzimy do pliku xrServer_Objects_ALife_Items.cpp
I po:

////////////////////////////////////////////////////////////////////////////
// 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); }

dodajemy:

////////////////////////////////////////////////////////////////////////////
// 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); }

 

Później wchodzimy do xrServer_Objects_ALife_Items.h

I po:

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
};

dodajemy:

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
};

 

Wchodzimy do pliku xrServer_Objects_ALife_Items_script2.cpp

I po:

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

dodajemy:

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

 

I to wszystko. Zakończyliśmy pracę z silnikiem. Mało już zostało pracy. Edytować .xml, zrobić plik plecaka i zarejestrować go w System.ltx
W tym samym System.ltx zmieniami slots_count zamiast 12 na 13
Po:

slot_persistent_12  = false ;helmet
slot_active_12      = false

dodajemy:

slot_persistent_13  = false ;backpack
slot_active_13      = false

Jest to już koniec prac. Testowy plik plecaka:  backpack.ltx  , teraz wystarczy go zarejestrować w System.ltx i dodać do folderu misc dla wygody. 

 

LEKCJA "WYGANIAMY NARUTO Z GG":

Spoiler

Autor lekcji: Doctor_Oz (Даниил Озол)
Kod został dostarczony od twórcy M.F.S. Team

 

Edytować trzeba jeden plik - ActorAnimation.cpp.

Szukamy funkcji:

void CActor::g_SetAnimation(u32 mstate_rl)

W niej szukamy linijki:

                        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];

Po tych linijkach są takie nawiasy klamrowe "}" i po piątej piszemy dany kod:

		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
        }

I to wszystko.

 

Screeny po zmianie:

ss-06-01-22-19-51-58-arenass-06-01-22-19-51-59-arenass-06-01-22-19-52-06-arenass-06-01-22-19-52-07-arena

 

 

ŹRÓDŁO:

https://ap-pro.ru/forums/topic/3457-redaktirovanie-openxray/

  • Positive 1
Link to comment
Share on other sites

  • Wojownik changed the title to Edytowanie OpenXRay

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.

Comunity