Skocz do zawartości

Edytowanie OpenXRay


Gość Diegtiariow

Rekomendowane odpowiedzi

Gość Diegtiariow

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/

Odnośnik do komentarza
Udostępnij na innych stronach

  • Gość zmienił(a) tytuł na Edytowanie OpenXRay

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.
Uwaga: Twój wpis zanim będzie widoczny, będzie wymagał zatwierdzenia moderatora.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Usuń formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

×
×
  • Dodaj nową pozycję...

Powiadomienie o plikach cookie

Korzystając z tej strony, zgadzasz się na nasze Warunki użytkowania.