Skip to content

Commit

Permalink
Примитивная многоприцельность с использованием переспауна
Browse files Browse the repository at this point in the history
На оружие можно устанаваливать прицелы, которые указаны в scope_name и
в scope_names. В последнем можно указывать список через запятую. При
установке прицела ищется параметр

scope_respawn_СЕКЦИЯ_ПРИЦЕЛА

и если найдена, и в качестве значения указана секция отличная от
текущей, то оружие переспаунивается с использованием этой секции. Если
прицел снимается, то проверяется значение параметра

scope_respawn

Пример

[wpn_hk416_acog]
scope_name = wpn_addon_elcan
scope_respawn_wpn_addon_elcan = wpn_m4a1_acog

[wpn_m4a1_acog]:wpn_m4a1
scope_respawn = wpn_hk416_acog

В этом примере на wpn_hk416_acog ставится прицел wpn_addon_elcan. При
установке прицела оружие будет заменено на wpn_m4a1_acog. При снятии с
него прицела оружие будет заменено обратно на wpn_hk416_acog.
  • Loading branch information
dsh2dsh committed Jun 14, 2019
1 parent 5d7e1a9 commit 2545e10
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 9 deletions.
5 changes: 5 additions & 0 deletions ogsr_engine/COMMON_AI/xrServer_Objects_ALife_Items.cpp
Expand Up @@ -653,6 +653,10 @@ void CSE_ALifeItemWeaponMagazinedWGL::STATE_Read (NET_Packet& P, u16 size)
a_elapsed2 = P.r_u16();
//Msg( "~~[%s][%s] update_read: m_bGrenadeMode: [%u], iAmmoElapsed2: [%u], m_ammoType2: [%u]", __FUNCTION__, this->name(), m_bGrenadeMode, a_elapsed2, ammo_type2 );
}
if ( !P.r_eof() ) {
u8 _data = P.r_u8();
m_bGrenadeMode = !!( _data & 0x1 );
}
}

void CSE_ALifeItemWeaponMagazinedWGL::STATE_Write (NET_Packet& P)
Expand All @@ -661,6 +665,7 @@ void CSE_ALifeItemWeaponMagazinedWGL::STATE_Write (NET_Packet& P)

P.w_u8(ammo_type2);
P.w_u16(a_elapsed2);
P.w_u8( m_bGrenadeMode ? 1 : 0 );
//Msg( "~~[%s][%s] update_write: m_bGrenadeMode: [%u], iAmmoElapsed2: [%u], m_ammoType2: [%u]", __FUNCTION__, this->name(), m_bGrenadeMode, a_elapsed2, ammo_type2 );
}

Expand Down
12 changes: 12 additions & 0 deletions ogsr_engine/xrGame/InventoryOwner.cpp
Expand Up @@ -44,6 +44,8 @@ CInventoryOwner::CInventoryOwner ()
m_known_info_registry = xr_new<CInfoPortionWrapper>();
m_tmp_active_slot_num = NO_ACTIVE_SLOT;
m_need_osoznanie_mode = FALSE;

m_tmp_next_item_slot = NO_ACTIVE_SLOT;
}

DLL_Pure *CInventoryOwner::_construct ()
Expand Down Expand Up @@ -296,6 +298,11 @@ void CInventoryOwner::OnItemTake (CInventoryItem *inventory_item)
inventory().Activate(m_tmp_active_slot_num);
m_tmp_active_slot_num = NO_ACTIVE_SLOT;
}

if ( m_tmp_next_item_slot != NO_ACTIVE_SLOT ) {
inventory().Slot( inventory_item, true );
m_tmp_next_item_slot = NO_ACTIVE_SLOT;
}
}

//возвращает текуший разброс стрельбы с учетом движения (в радианах)
Expand Down Expand Up @@ -575,3 +582,8 @@ float CInventoryOwner::ArtefactsAddWeight( bool first ) const {
}
return add_weight;
}


void CInventoryOwner::SetNextItemSlot( u32 slot ) {
m_tmp_next_item_slot = slot;
}
3 changes: 3 additions & 0 deletions ogsr_engine/xrGame/InventoryOwner.h
Expand Up @@ -104,6 +104,7 @@ class CInventoryOwner : public CAttachmentOwner {
bool m_bAllowTrade;

u32 m_tmp_active_slot_num;
u32 m_tmp_next_item_slot;
//////////////////////////////////////////////////////////////////////////
// сюжетная информация
public:
Expand Down Expand Up @@ -216,6 +217,8 @@ class CInventoryOwner : public CAttachmentOwner {
virtual float missile_throw_force ();
virtual bool use_throw_randomness ();
virtual bool NeedOsoznanieMode () {return m_need_osoznanie_mode!=FALSE;}

void SetNextItemSlot( u32 );
};

#include "inventory_owner_inline.h"
17 changes: 16 additions & 1 deletion ogsr_engine/xrGame/Weapon.cpp
Expand Up @@ -385,11 +385,27 @@ void CWeapon::Load (LPCSTR section)

UpdateZoomOffset();

m_allScopeNames.clear();
m_highlightAddons.clear();
if(m_eScopeStatus == ALife::eAddonAttachable)
{
m_sScopeName = pSettings->r_string(section,"scope_name");
m_iScopeX = pSettings->r_s32(section,"scope_x");
m_iScopeY = pSettings->r_s32(section,"scope_y");

m_allScopeNames.push_back( m_sScopeName );
if ( pSettings->line_exist( section, "scope_names" ) ) {
LPCSTR S = pSettings->r_string( section, "scope_names" );
if ( S && S[ 0 ] ) {
string128 _scopeItem;
int count = _GetItemCount( S );
for ( int it = 0; it < count; ++it ) {
_GetItem( S, it, _scopeItem );
m_allScopeNames.push_back( _scopeItem );
m_highlightAddons.push_back( _scopeItem );
}
}
}
}

if(m_eSilencerStatus == ALife::eAddonAttachable)
Expand Down Expand Up @@ -462,7 +478,6 @@ void CWeapon::Load (LPCSTR section)
m_hit_probability[i] = READ_IF_EXISTS(pSettings,r_float,section,temp,1.f);
}

m_highlightAddons.clear();
if (pSettings->line_exist(section, "highlight_addons")) {
LPCSTR S = pSettings->r_string(section, "highlight_addons");
if (S && S[0]) {
Expand Down
1 change: 1 addition & 0 deletions ogsr_engine/xrGame/Weapon.h
Expand Up @@ -211,6 +211,7 @@ class CWeapon : public CHudItemObject,

//названия секций подключаемых аддонов
shared_str m_sScopeName;
std::vector<shared_str> m_allScopeNames;
shared_str m_sSilencerName;
shared_str m_sGrenadeLauncherName;

Expand Down
76 changes: 68 additions & 8 deletions ogsr_engine/xrGame/WeaponMagazined.cpp
Expand Up @@ -18,6 +18,7 @@
#include "string_table.h"
#include "WeaponBinoculars.h"
#include "WeaponBinocularsVision.h"
#include "ai_object_location.h"

#include "game_object_space.h"
#include "script_callback_ex.h"
Expand Down Expand Up @@ -828,7 +829,7 @@ bool CWeaponMagazined::CanAttach(PIItem pIItem)
if( pScope &&
m_eScopeStatus == ALife::eAddonAttachable &&
(m_flagsAddOnState&CSE_ALifeItemWeapon::eWeaponAddonScope) == 0 &&
(m_sScopeName == pIItem->object().cNameSect()) )
std::find( m_allScopeNames.begin(), m_allScopeNames.end(), pIItem->object().cNameSect() ) != m_allScopeNames.end() )
return true;
else if( pSilencer &&
m_eSilencerStatus == ALife::eAddonAttachable &&
Expand Down Expand Up @@ -869,11 +870,11 @@ bool CWeaponMagazined::Attach(PIItem pIItem, bool b_send_event)
CScope* pScope = smart_cast<CScope*>(pIItem);
CSilencer* pSilencer = smart_cast<CSilencer*>(pIItem);
CGrenadeLauncher* pGrenadeLauncher = smart_cast<CGrenadeLauncher*>(pIItem);

if(pScope &&
m_eScopeStatus == CSE_ALifeItemWeapon::eAddonAttachable &&
(m_flagsAddOnState&CSE_ALifeItemWeapon::eWeaponAddonScope) == 0 &&
(m_sScopeName == pIItem->object().cNameSect()))
std::find( m_allScopeNames.begin(), m_allScopeNames.end(), pIItem->object().cNameSect() ) != m_allScopeNames.end() )
{
m_flagsAddOnState |= CSE_ALifeItemWeapon::eWeaponAddonScope;
result = true;
Expand Down Expand Up @@ -904,16 +905,17 @@ bool CWeaponMagazined::Attach(PIItem pIItem, bool b_send_event)
pIItem->object().DestroyObject ();
};

UpdateAddonsVisibility();
InitAddons();
if ( !ScopeRespawn( pIItem ) ) {
UpdateAddonsVisibility();
InitAddons();
}

return true;
}
else
return inherited::Attach(pIItem, b_send_event);
}


bool CWeaponMagazined::Detach(const char* item_section_name, bool b_spawn_item)
{
if( m_eScopeStatus == CSE_ALifeItemWeapon::eAddonAttachable &&
Expand All @@ -922,8 +924,10 @@ bool CWeaponMagazined::Detach(const char* item_section_name, bool b_spawn_item)
{
m_flagsAddOnState &= ~CSE_ALifeItemWeapon::eWeaponAddonScope;

UpdateAddonsVisibility();
InitAddons();
if ( !ScopeRespawn( nullptr ) ) {
UpdateAddonsVisibility();
InitAddons();
}

return CInventoryItemObject::Detach(item_section_name, b_spawn_item);
}
Expand Down Expand Up @@ -1404,3 +1408,59 @@ void CWeaponMagazined::net_Relcase(CObject *object)

m_binoc_vision->remove_links(object);
}


bool CWeaponMagazined::ScopeRespawn( PIItem pIItem ) {
std::string scope_respawn = "scope_respawn";
if ( ScopeAttachable() && IsScopeAttached() ) {
scope_respawn += "_";
if ( smart_cast<CScope*>( pIItem ) )
scope_respawn += pIItem->object().cNameSect().c_str();
else
scope_respawn += m_sScopeName.c_str();
}

if ( pSettings->line_exist( cNameSect(), scope_respawn.c_str() ) ) {
LPCSTR S = pSettings->r_string( cNameSect(), scope_respawn.c_str() );
if ( xr_strcmp( cName().c_str(), S ) != 0 ) {
CSE_Abstract* _abstract = Level().spawn_item( S, Position(), ai_location().level_vertex_id(), H_Parent()->ID(), true );
CSE_ALifeDynamicObject* sobj1 = alife_object();
CSE_ALifeDynamicObject* sobj2 = smart_cast<CSE_ALifeDynamicObject*>( _abstract );

NET_Packet P;
P.w_begin( M_UPDATE );
u32 position = P.w_tell();
P.w_u16( 0 );
sobj1->STATE_Write( P );
u16 size = u16( P.w_tell() - position );
P.w_seek( position, &size, sizeof( u16 ) );
u16 id;
P.r_begin( id );
P.r_u16( size );
sobj2->STATE_Read( P, size );

P.w_begin( M_UPDATE );
net_Export( P );
P.r_begin( id );
sobj1->UPDATE_Read( P );

P.w_begin( M_UPDATE );
sobj1->UPDATE_Write( P );
P.r_begin( id );
sobj2->UPDATE_Read( P );

auto io = smart_cast<CInventoryOwner*>( H_Parent() );
auto ii = smart_cast<CInventoryItem*>( this );
if ( io->inventory().InSlot( ii ) )
io->SetNextItemSlot( ii->GetSlot() );

DestroyObject();
sobj2->Spawn_Write( P, TRUE );
Level().Send( P, net_flags( TRUE ) );
F_entity_Destroy( _abstract );

return true;
}
}
return false;
}
1 change: 1 addition & 0 deletions ogsr_engine/xrGame/WeaponMagazined.h
Expand Up @@ -204,6 +204,7 @@ class CWeaponMagazined: public CWeapon
virtual void OnDrawUI();
virtual void net_Relcase(CObject *object);

bool ScopeRespawn( PIItem );
};

#endif //__XR_WEAPON_MAG_H__

3 comments on commit 2545e10

@Shtrecker
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Такой прикол сработает с ганс пушками?

@I-AmDead
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Такой прикол сработает с ганс пушками?

А чем отличаются Ганс пушки от других?

@Shtrecker
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Чем назван Ганс пушки от других?

В гансе на пушках прицелы все на одном худе, надеваешь прицел и кости появляються. В сткопе (для сравнения) для прицела заготовлены секции и худовые модели. А в этом примере именно смена худа ака сткоп.

Please sign in to comment.