Skip to content

Commit afc85df

Browse files
AxelDominatoRXottab-DUTY
authored andcommitted
Added functionality for multiple item usage
You can now have items with multiple uses, with proper display using progress bars and all of the bells and whistles.
1 parent 4da9bb6 commit afc85df

File tree

10 files changed

+88
-19
lines changed

10 files changed

+88
-19
lines changed

src/xrGame/ActorHelmet.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ void CHelmet::Load(LPCSTR section)
4949

5050
m_BonesProtectionSect = READ_IF_EXISTS(pSettings, r_string, section, "bones_koeff_protection", "");
5151
m_fShowNearestEnemiesDistance = READ_IF_EXISTS(pSettings, r_float, section, "nearest_enemies_show_dist", 0.0f);
52+
53+
// Added by Axel, to enable optional condition use on any item
54+
m_flags.set(FUsingCondition, READ_IF_EXISTS(pSettings, r_bool, section, "use_condition", true));
5255
}
5356

5457
void CHelmet::ReloadBonesProtection()

src/xrGame/CustomOutfit.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ void CCustomOutfit::Load(LPCSTR section)
102102

103103
m_BonesProtectionSect = READ_IF_EXISTS(pSettings, r_string, section, "bones_koeff_protection", "");
104104
bIsHelmetAvaliable = !!READ_IF_EXISTS(pSettings, r_bool, section, "helmet_avaliable", true);
105+
106+
// Added by Axel, to enable optional condition use on any item
107+
m_flags.set(FUsingCondition, READ_IF_EXISTS(pSettings, r_bool, section, "use_condition", true));
105108
}
106109

107110
void CCustomOutfit::ReloadBonesProtection()

src/xrGame/ExplosiveItem.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ void CExplosiveItem::Load(LPCSTR section)
1414
{
1515
inherited::Load(section);
1616
CExplosive::Load(section);
17-
m_flags.set(FUsingCondition, TRUE);
17+
// Added by Axel, to enable optional condition use on any item
18+
m_flags.set(FUsingCondition, READ_IF_EXISTS(pSettings, r_bool, section, "use_condition", true));
1819
CDelayedActionFuse::Initialize(
1920
pSettings->r_float(section, "time_to_explode"), pSettings->r_float(section, "condition_to_explode"));
2021
VERIFY(pSettings->line_exist(section, "set_timer_particles"));

src/xrGame/Inventory.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ bool CInventory::Eat(PIItem pIItem)
10731073
if (IsGameTypeSingle() && Actor()->m_inventory == this)
10741074
Actor()->callback(GameObject::eUseObject)((smart_cast<CGameObject*>(pIItem))->lua_game_object());
10751075

1076-
if (pItemToEat->Empty())
1076+
if (pItemToEat->CanDelete())
10771077
{
10781078
pIItem->SetDropManual(TRUE);
10791079
return false;

src/xrGame/Weapon.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,9 @@ void CWeapon::Load(LPCSTR section)
472472
m_zoom_params.m_bUseDynamicZoom = READ_IF_EXISTS(pSettings, r_bool, section, "scope_dynamic_zoom", false);
473473
m_zoom_params.m_sUseZoomPostprocess = nullptr;
474474
m_zoom_params.m_sUseBinocularVision = nullptr;
475+
476+
// Added by Axel, to enable optional condition use on any item
477+
m_flags.set(FUsingCondition, READ_IF_EXISTS(pSettings, r_bool, section, "use_condition", true));
475478
}
476479

477480
void CWeapon::LoadFireParams(LPCSTR section)

src/xrGame/eatable_item.cpp

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@
1414
#include "entity_alive.h"
1515
#include "EntityCondition.h"
1616
#include "InventoryOwner.h"
17+
#include "UIGameCustom.h"
1718

1819
CEatableItem::CEatableItem()
1920
{
20-
m_iPortionsNum = -1;
2121
m_physic_item = 0;
22+
m_iMaxUses = 1;
23+
m_iRemainingUses = 1;
24+
m_bRemoveAfterUse = true;
2225
}
2326

2427
CEatableItem::~CEatableItem() {}
@@ -32,15 +35,35 @@ void CEatableItem::Load(LPCSTR section)
3235
{
3336
inherited::Load(section);
3437

35-
m_iPortionsNum = pSettings->r_s32(section, "eat_portions_num");
36-
VERIFY(m_iPortionsNum < 10000);
38+
m_iRemainingUses = m_iMaxUses = READ_IF_EXISTS(pSettings, r_u16, section, "max_uses", 1);
39+
m_bRemoveAfterUse = READ_IF_EXISTS(pSettings, r_bool, section, "remove_after_use", true);
40+
41+
if (IsUsingCondition())
42+
SetCondition((float)m_iRemainingUses / (float)m_iMaxUses );
43+
}
44+
45+
void CEatableItem::load(IReader& packet)
46+
{
47+
inherited::load(packet);
48+
49+
m_iRemainingUses = packet.r_u16();
50+
}
51+
52+
void CEatableItem::save(NET_Packet& packet)
53+
{
54+
inherited::save(packet);
55+
56+
packet.w_u16(m_iRemainingUses);
3757
}
3858

3959
BOOL CEatableItem::net_Spawn(CSE_Abstract* DC)
4060
{
4161
if (!inherited::net_Spawn(DC))
4262
return FALSE;
4363

64+
if (IsUsingCondition())
65+
SetCondition((float)m_iRemainingUses / (float)m_iMaxUses);
66+
4467
return TRUE;
4568
};
4669

@@ -50,7 +73,7 @@ bool CEatableItem::Useful() const
5073
return false;
5174

5275
//проверить не все ли еще съедено
53-
if (m_iPortionsNum == 0)
76+
if (m_iRemainingUses == 0)
5477
return false;
5578

5679
return true;
@@ -108,10 +131,14 @@ bool CEatableItem::UseBy(CEntityAlive* entity_alive)
108131
Level().Send(tmp_packet);
109132
}
110133

111-
if (m_iPortionsNum > 0)
112-
--m_iPortionsNum;
134+
if (m_iRemainingUses > 0)
135+
--m_iRemainingUses;
113136
else
114-
m_iPortionsNum = 0;
137+
m_iRemainingUses = 0;
138+
139+
SetCondition((float)m_iRemainingUses / (float)m_iMaxUses);
140+
CurrentGameUI()->HideActorMenu();
141+
CurrentGameUI()->ShowActorMenu();
115142

116143
return true;
117144
}

src/xrGame/eatable_item.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,27 @@ class CEatableItem : public CInventoryItem
1313
protected:
1414
CPhysicItem* m_physic_item;
1515

16+
u16 m_iMaxUses;
17+
u16 m_iRemainingUses;
18+
bool m_bRemoveAfterUse;
19+
1620
public:
1721
CEatableItem();
1822
virtual ~CEatableItem();
1923
virtual IFactoryObject* _construct();
2024
virtual CEatableItem* cast_eatable_item() { return this; }
2125
virtual void Load(LPCSTR section);
26+
void load(IReader& packet) override;
27+
void save(NET_Packet& packet) override;
2228
virtual bool Useful() const;
2329

2430
virtual BOOL net_Spawn(CSE_Abstract* DC);
2531

2632
virtual void OnH_B_Independent(bool just_before_destroy);
2733
virtual void OnH_A_Independent();
2834
virtual bool UseBy(CEntityAlive* npc);
29-
virtual bool Empty() { return PortionsNum() == 0; };
30-
int PortionsNum() const { return m_iPortionsNum; }
31-
protected:
32-
int m_iPortionsNum;
35+
virtual bool Empty() const { return m_iRemainingUses == 0; }
36+
bool CanDelete() const { return Empty() && m_bRemoveAfterUse == true; }
37+
virtual u16 GetMaxUses() const { return m_iMaxUses; }
38+
virtual u16 GetRemainingUses() const { return m_iRemainingUses; }
3339
};

src/xrGame/inventory_item.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ void CInventoryItem::Load(LPCSTR section)
110110
m_flags.set(FCanTrade, m_can_trade);
111111
m_flags.set(FIsQuestItem, READ_IF_EXISTS(pSettings, r_bool, section, "quest_item", FALSE));
112112

113+
// Added by Axel, to enable optional condition use on any item
114+
m_flags.set(FUsingCondition, READ_IF_EXISTS(pSettings, r_bool, section, "use_condition", false));
115+
113116
if (BaseSlot() != NO_ACTIVE_SLOT || Belt())
114117
{
115118
m_flags.set(FRuckDefault, pSettings->r_bool(section, "default_to_ruck"));
@@ -127,7 +130,7 @@ void CInventoryItem::ChangeCondition(float fDeltaCondition)
127130

128131
void CInventoryItem::Hit(SHit* pHDS)
129132
{
130-
if (!m_flags.test(FUsingCondition))
133+
if (IsUsingCondition() == false)
131134
return;
132135

133136
float hit_power = pHDS->damage();

src/xrGame/inventory_item.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class CInventoryItem : public CAttachableItem,
104104
virtual void OnEvent(NET_Packet& P, u16 type);
105105

106106
virtual bool Useful() const; // !!! Переопределить. (см. в Inventory.cpp)
107+
virtual bool IsUsingCondition() const { return (m_flags.test(FUsingCondition) > 0); }
107108
virtual bool Attach(PIItem pIItem, bool b_send_event) { return false; }
108109
virtual bool Detach(PIItem pIItem) { return false; }
109110
//при детаче спаунится новая вещь при заданно названии секции

src/xrGame/ui/UICellItem.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "uicursor.h"
44
#include "inventory_item.h"
55
#include "UIDragDropListEx.h"
6+
#include "eatable_item.h"
67
#include "xr_level_controller.h"
78
#include "xrEngine/xr_input.h"
89
#include "Level.h"
@@ -204,11 +205,32 @@ void CUICellItem::UpdateConditionProgressBar()
204205
if (m_pParentList && m_pParentList->GetConditionProgBarVisibility())
205206
{
206207
PIItem itm = (PIItem)m_pData;
207-
CWeapon* pWeapon = smart_cast<CWeapon*>(itm);
208-
CCustomOutfit* pOutfit = smart_cast<CCustomOutfit*>(itm);
209-
CHelmet* pHelmet = smart_cast<CHelmet*>(itm);
210-
if (pWeapon || pOutfit || pHelmet)
208+
209+
if (itm->IsUsingCondition())
211210
{
211+
float cond = itm->GetCondition();
212+
213+
CEatableItem* eitm = smart_cast<CEatableItem*>(itm);
214+
if (eitm)
215+
{
216+
const u16 max_uses = eitm->GetMaxUses();
217+
if (max_uses > 1)
218+
{
219+
const u16 remaining_uses = eitm->GetRemainingUses();
220+
if (remaining_uses < 1)
221+
cond = 0.0f;
222+
else if (max_uses > 8)
223+
cond = (float)remaining_uses / (float)max_uses;
224+
else
225+
{
226+
cond = (float)remaining_uses * 0.125f - 0.0625f;
227+
m_pConditionState->ShowBackground(false);
228+
}
229+
230+
m_pConditionState->m_bUseColor = false;
231+
}
232+
}
233+
212234
Ivector2 itm_grid_size = GetGridSize();
213235
if (m_pParentList->GetVerticalPlacement())
214236
std::swap(itm_grid_size.x, itm_grid_size.y);
@@ -219,7 +241,7 @@ void CUICellItem::UpdateConditionProgressBar()
219241
float y = itm_grid_size.y * (cell_size.y + cell_space.y) - m_pConditionState->GetHeight() - 2.f;
220242

221243
m_pConditionState->SetWndPos(Fvector2().set(x, y));
222-
m_pConditionState->SetProgressPos(iCeil(itm->GetCondition() * 13.0f) / 13.0f);
244+
m_pConditionState->SetProgressPos(iCeil(cond * 13.0f) / 13.0f);
223245
m_pConditionState->Show(true);
224246
return;
225247
}

0 commit comments

Comments
 (0)