Jump to content

Recommended Posts

Kondr48    307

В файле xray\xr_3da\xrRender\r__screenshot.cpp находим:

case IRender_interface::SM_NORMAL: 

Заменяем:

CHK_DX				(D3DXSaveSurfaceToFileInMemory (&saved,D3DXIFF_JPG,pFB,0,0));  

на:

CHK_DX				(D3DXSaveSurfaceToFileInMemory (&saved,D3DXIFF_PNG,pFB,0,0)); 

Теперь расширение, чуть выше меняем:

ss_%s_%s_(%s).jpg 

на, соответственно:

ss_%s_%s_(%s).png 

P. S. на самом деле, кроме формата png есть и другие варианты)

typedef enum _D3DXIMAGE_FILEFORMAT
{
    D3DXIFF_BMP         = 0,
    D3DXIFF_JPG         = 1,
    D3DXIFF_TGA         = 2,
    D3DXIFF_PNG         = 3,
    D3DXIFF_DDS         = 4,
    D3DXIFF_PPM         = 5,
    D3DXIFF_DIB         = 6,
    D3DXIFF_HDR         = 7,       //high dynamic range formats
    D3DXIFF_PFM         = 8,       //
    D3DXIFF_FORCE_DWORD = 0x7fffffff

} 

Т. е, доступны такие расширения, как: bmp, jpg, tga, png, dds, ppm, dib, hdr, pfm.

 

 

 

 

  • Like 2
  • Полезно 1

Share this post


Link to post
Share on other sites
Kondr48    307
Добавлено Kondr48,

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

  • Like 1

Share this post


Link to post
Share on other sites
Romann    495

 

 

Для сборки нам понадобится установить на ПК: 

 2. Visual Studio 2010 Service Pack 1 

 4. DirectX SDK June 2007. Если ставили 2010, то 2007 ОБЯЗАТЕЛЬНО нужно ставить после 10. 5. Windows SDK

Может кто подсказать, где всё это взять? Сутки шарюсь по сети, или везде всё мертвое(ссылки), или не пойми чего попадается..

Добавлено Kondr48,

DirectX SDK June 2007 https://yadi.sk/d/qVnFuMeP3KGta2


Машина: проц. Intel® Core™ i5-2430M CPU 2.40GHz ,ОЗУ 6,00Гб ,видео 2 Гб,Win7х64

 

Химера конечно сильный хищник, а все держится дома. Чего же ты пришел к ней домой и пытаешься её убить?

                                                                                                                                                                          © Болотный Доктор

Share this post


Link to post
Share on other sites
Demosfen    66

@Kondr48 Это хорошо, т.е если у костюма 80% пулестойкости то стреляем ему хоть в руку, хоть в голову, эффект будет одинаковый так?

Добавлено Kondr48,

Именно.

Добавлено Kondr48,

Пройдёт 80% хита.


e3a8e807c7a6fe1ae21bbcf87b090697b2cc5527

Share this post


Link to post
Share on other sites
Shkiper2012    29

Ссылка на "Сборка исходников, необходимые программы" не работает, либо пост удалён/перенесён.

Если перенесён, то куда?

Share this post


Link to post
Share on other sites
alexus95    1

Всем привет.недавно попытался адаптировать фичу от bak,которая возвращает функцию рождения артефактов.так вот только возникли проблемы в файлах customzone.cpp и customzone.h. использовал ревизию 201 с xp-dev.кто хорошо разбирается в движке,прошу пожалуйста помогите мне.вас отблагодарю

 

Добавлено Kondr48,

О каких конкретно проблемах-то речь?)

Share this post


Link to post
Share on other sites
aromatizer    2,320
В 27.06.2017 в 00:03, Kondr48 сказал:

Исправление пулестойкости костюмов.

 

Хочу уточнить: это работает только для ГГ?

Добавлено Kondr48,

Скорее всего для НПС тоже, но лучше проверить.


Отношения между людьми- главная ценность в человеческом обществе.
Любая полученная информация- это только повод для размышлений, а не побуждение к действию.
Это должен знать каждый: уроки боевой подготовки Дяди Саши https://yadi.sk/d/60Ec2B06goLAE
Накопано и накнопано:https://yadi.sk/d/mzVY5jQEspwpt

Share this post


Link to post
Share on other sites
Fagot.    389

Ссылка из шапки "Сборка исходников, необходимые программы" ведёт не туда, куда надо

 

Прошёл опять по ссылке - всё также. Ссылка ведёт на пост, в котором нет "необходимых программ".

Edited by Fagot.
Добавлено Kondr48,

Я вообще этот свой пост что-то не наблюдаю в теме...

Добавлено Kondr48,

Все на месте. Там просто в некоторых постах спойлеры побились. При случае поправлю.

  • Полезно 1

Share this post


Link to post
Share on other sites
Zander_driver    4,626

Подкину еще немножко своих правок, для движка OGSR
 

Скрытый текст


 

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

xrGame/ui/uiTextureMaster.h


// file:		UITextureMaster.h
// description:	holds info about shared textures. able to initialize external
//				through IUITextureControl interface
// created:		11.05.2005
// author:		Serge Vynnychenko
// mail:		narrator@gsc-game.kiev.ua
//
// copyright 2005 GSC Game World

#pragma once

#include "ui_defs.h"

class IUISimpleTextureControl;

struct TEX_INFO{
	shared_str	file;
	Frect		rect;
	LPCSTR		get_file_name	()	{return *file;}
	Frect		get_rect		()	{return rect;}
};

class CUITextureMaster{
public:

	static void ParseShTexInfo			(LPCSTR xml_file);
	static void ParseConfigIcon			(LPCSTR section);
	static LPCSTR CheckName(LPCSTR texture_name);

	static void		InitTexture			(LPCSTR texture_name,		IUISimpleTextureControl* tc);
	static void		InitTexture			(LPCSTR texture_name, const char* shader_name, IUISimpleTextureControl* tc);
	static float	GetTextureHeight	(LPCSTR texture_name);
	static float	GetTextureWidth		(LPCSTR texture_name);
	static Frect	GetTextureRect		(LPCSTR texture_name);
	static LPCSTR	GetTextureFileName	(LPCSTR texture_name);
	static void		GetTextureShader	(LPCSTR texture_name, ui_shader& sh);
	static TEX_INFO	FindItem			(LPCSTR texture_name, LPCSTR def_texture_name);
	static void WriteLog();
	static bool		CheckTextureExist	(LPCSTR texture_name);

protected:
	IC	static bool IsSh					(const char* texture_name);



//	typedef xr_string region_name;
//	typedef xr_string shader_name;
//	typedef xr_map<region_name, Frect>				regions;
//	typedef xr_map<region_name, Frect>::iterator	regions_it;
//	typedef xr_map<shader_name, regions>			shared_textures;
//	typedef xr_map<shader_name, regions>::iterator	shared_textures_it;

	static xr_map<shared_str, TEX_INFO>					m_textures;

//	static	shared_textures		m_shTex;
#ifdef DEBUG
	static u32		m_time;
#endif 
};

 

xrGame/ui/uiTextureMaster.cpp


// file:		UITextureMaster.h
// description:	holds info about shared textures. able to initialize external controls
//				through IUITextureControl interface
// created:		11.05.2005
// author:		Serge Vynnychenko
// mail:		narrator@gsc-game.kiev.ua
//
// copyright 2005 GSC Game World


#include "StdAfx.h"
#include "UITextureMaster.h"
#include "uiabstract.h"
#include "xrUIXmlParser.h"

xr_map<shared_str, TEX_INFO>	CUITextureMaster::m_textures;
#ifdef DEBUG
u32									CUITextureMaster::m_time = 0;
#endif

void CUITextureMaster::WriteLog(){
#ifdef DEBUG
	Msg("UI texture manager work time is %d ms", m_time);
#endif
}
void CUITextureMaster::ParseShTexInfo(LPCSTR xml_file){
	CUIXml xml;
	xml.Init(CONFIG_PATH, UI_PATH, xml_file);
	shared_str file = xml.Read("file_name",0,""); 

//	shared_textures_it	sht_it = m_shTex.find(texture);
//	if (m_shTex.end() == sht_it)
//	{
		int num = xml.GetNodesNum("",0,"texture");
//		regions regs;
		for (int i = 0; i<num; i++)
		{
			TEX_INFO info;

			info.file = file;

			info.rect.x1 = xml.ReadAttribFlt("texture",i,"x");
			info.rect.x2 = xml.ReadAttribFlt("texture",i,"width") + info.rect.x1;
			info.rect.y1 = xml.ReadAttribFlt("texture",i,"y");
			info.rect.y2 = xml.ReadAttribFlt("texture",i,"height") + info.rect.y1;
			shared_str id = xml.ReadAttrib("texture",i,"id");

			m_textures.insert(mk_pair(id,info));
		}
//		m_shTex.insert(mk_pair(texture, regs));
//	}
}

LPCSTR CUITextureMaster::CheckName(const char* texture_name){
	LPCSTR r;
	if (pSettings->section_exist(texture_name))
	{
		shared_str subsection = pSettings->r_string(texture_name, "icon_section", texture_name);
		subsection = pSettings->r_string(subsection, "used_icon_texture", subsection.c_str());
		r = subsection.c_str();
	}
	else {
		r = texture_name;
	}
	if (!CheckTextureExist(r)) ParseConfigIcon(r);
	if (!CheckTextureExist(r)) r = texture_name;
	return r;
}

void CUITextureMaster::ParseConfigIcon(LPCSTR section){
	if (pSettings->section_exist(section))
	{
		shared_str subsection = pSettings->r_string(section, "icon_section", section);
		subsection = pSettings->r_string(subsection, "used_icon_texture", subsection);
		int place_id = pSettings->r_float(subsection, "icon_group", 0);
		TEX_INFO info;
		shared_str file = "ui\\ui_icon_equipment";
		if (place_id != 0) file.sprintf("ui\\ui_icon_equipment_%u", place_id);
		info.file = file;
			info.rect.x1 = pSettings->r_float(subsection, "inv_grid_x", 0) * 50;
			info.rect.x2 = (pSettings->r_float(subsection, "inv_grid_width", 0) * 50) + info.rect.x1;
			info.rect.y1 = pSettings->r_float(subsection, "inv_grid_y", 0) * 50;
			info.rect.y2 = (pSettings->r_float(subsection, "inv_grid_height", 0) * 50) + info.rect.y1;
			//shared_str id = subsection;
		if (!CheckTextureExist(subsection.c_str())) m_textures.insert(mk_pair(subsection,info));
	}
}

bool CUITextureMaster::IsSh(const char* texture_name){
	return strstr(texture_name,"\\") ? false : true;
}

void CUITextureMaster::InitTexture(const char* texture_name, IUISimpleTextureControl* tc){
	const char* ntn = CheckName(texture_name);
#ifdef DEBUG
	CTimer T;
	T.Start();
#endif

	xr_map<shared_str, TEX_INFO>::iterator	it;

	it = m_textures.find(ntn);

	if (it != m_textures.end())
	{
		tc->CreateShader(*((*it).second.file));
		tc->SetOriginalRectEx((*it).second.rect);
#ifdef DEBUG
		m_time += T.GetElapsed_ms();
#endif
		return;
	}
	tc->CreateShader(ntn);
#ifdef DEBUG
	m_time += T.GetElapsed_ms();
#endif
}

void CUITextureMaster::InitTexture(const char* texture_name, const char* shader_name, IUISimpleTextureControl* tc){
	const char* ntn = CheckName(texture_name);
#ifdef DEBUG
	CTimer T;
	T.Start();
#endif

	xr_map<shared_str, TEX_INFO>::iterator	it;

	it = m_textures.find(ntn);

	if (it != m_textures.end())
	{
		tc->CreateShader(*((*it).second.file), shader_name);
		tc->SetOriginalRectEx((*it).second.rect);
#ifdef DEBUG
		m_time += T.GetElapsed_ms();
#endif
		return;
	}
	tc->CreateShader(ntn, shader_name);
#ifdef DEBUG
	m_time += T.GetElapsed_ms();
#endif
}

float CUITextureMaster::GetTextureHeight(const char* texture_name){
	const char* ntn = CheckName(texture_name);
	xr_map<shared_str, TEX_INFO>::iterator	it;
	it = m_textures.find(ntn);

	if (it != m_textures.end())
		return (*it).second.rect.height();
	// KD: we don't need to die :)
//	R_ASSERT3(false,"CUITextureMaster::GetTextureHeight Can't find texture", texture_name);
	//ParseConfigIcon(texture_name);
	Msg("! CUITextureMaster::GetTextureHeight Can't find texture", texture_name);
	return 0;
}

bool CUITextureMaster::CheckTextureExist(const char* texture_name){
	//const char* ntn = CheckName(texture_name);
	xr_map<shared_str, TEX_INFO>::iterator	it;
	it = m_textures.find(texture_name);

	if (it != m_textures.end())
		return true;
	// Zander: I want to know if such a texture exists in advance
	return false;
}

Frect CUITextureMaster::GetTextureRect(const char* texture_name){
	const char* ntn = CheckName(texture_name);
	xr_map<shared_str, TEX_INFO>::iterator	it;
	it = m_textures.find(ntn);
	if (it != m_textures.end())
		return (*it).second.rect;

	// KD: we don't need to die :)
//	R_ASSERT3(false,"CUITextureMaster::GetTextureHeight Can't find texture", texture_name);
	//ParseConfigIcon(texture_name);
	Msg("! CUITextureMaster::GetTextureRect Can't find texture", texture_name);
	return Frect();
}

float CUITextureMaster::GetTextureWidth(const char* texture_name){
	const char* ntn = CheckName(texture_name);
	xr_map<shared_str, TEX_INFO>::iterator	it;
	it = m_textures.find(ntn);

	if (it != m_textures.end())
		return (*it).second.rect.width();
	// KD: we don't need to die :)
//	R_ASSERT3(false,"CUITextureMaster::GetTextureHeight Can't find texture", texture_name);
	//ParseConfigIcon(texture_name);
	Msg("! CUITextureMaster::GetTextureWidth Can't find texture", texture_name);
	return 0;
}

LPCSTR CUITextureMaster::GetTextureFileName(const char* texture_name){
	const char* ntn = CheckName(texture_name);
	xr_map<shared_str, TEX_INFO>::iterator	it;
	it = m_textures.find(ntn);

	if (it != m_textures.end())
		return *((*it).second.file);
	// KD: we don't need to die :)
//	R_ASSERT3(false,"CUITextureMaster::GetTextureHeight Can't find texture", texture_name);
	Msg("! CUITextureMaster::GetTextureFileName Can't find texture", texture_name);
	//ParseConfigIcon(texture_name);
	return 0;
}

TEX_INFO CUITextureMaster::FindItem(LPCSTR texture_name, LPCSTR def_texture_name)
{
	const char* ntn = CheckName(texture_name);
	xr_map<shared_str, TEX_INFO>::iterator	it;
	it = m_textures.find(ntn);

	if (it != m_textures.end())
		return (it->second);
	else{
		R_ASSERT2(m_textures.find(def_texture_name)!=m_textures.end(),ntn);
		return FindItem	(def_texture_name,NULL);
	}
}

void CUITextureMaster::GetTextureShader(LPCSTR texture_name, ui_shader& sh){
	const char* ntn = CheckName(texture_name);
	xr_map<shared_str, TEX_INFO>::iterator	it;
	it = m_textures.find(ntn);

//	R_ASSERT3(it != m_textures.end(), "can't find texture", texture_name);
	if (it == m_textures.end())
		Msg("! CUITextureMaster::GetTextureShader Can't find texture", texture_name);

	sh->create("hud\\default", *((*it).second.file));	
}

 

 


 

 

 


 

Скрытый текст


 

Описание: Функции чтения данных из конфига, принимают значения по умолчанию, возвращаемые в случае если нет такой строки/секции.

+ Эта правка необходима для предыдущей.

xrCore/xr_ini.h


#pragma once

class   CInifile;
struct  xr_token;

class XRCORE_API CInifile {
 public:
  using Item = std::pair<shared_str, shared_str>;
  struct XRCORE_API Sect {
    shared_str Name;
    string_unordered_map<shared_str, shared_str> Data;
    std::vector<Item> Unordered;
    BOOL line_exist ( LPCSTR, LPCSTR* = nullptr );
    u32 line_count();

	LPCSTR		r_string( LPCSTR );
	u32			r_u32( LPCSTR );
	float		r_float( LPCSTR );

	Ivector2	r_ivector2( LPCSTR );
	Fvector3	r_fvector3( LPCSTR );
  };
  using Root = string_unordered_map<shared_str, Sect*>;

  static_assert(std::is_same_v<Root::key_equal, string_hash::transparent_key_equal>, "Invalid key_equal"); //Нужная проверка в будущем, не убирать!

  // factorisation 
  static CInifile* Create  ( LPCSTR, BOOL = TRUE );
  static void      Destroy ( CInifile* );
  static IC BOOL   IsBOOL  ( LPCSTR B ) {
    return ( xr_strcmp( B, "on" ) == 0
             || xr_strcmp( B, "yes" ) == 0
             || xr_strcmp( B, "true" ) == 0
             || xr_strcmp( B, "1" ) == 0 );
  }

 private:
  LPSTR fName;
  Root  DATA;
  void  Load ( IReader*, LPCSTR );

 public:
  bool bReadOnly;
  BOOL bSaveAtEnd;

 public:
  CInifile ( IReader*, LPCSTR = 0 );
  CInifile ( LPCSTR, BOOL = TRUE, BOOL = TRUE, BOOL = TRUE );
  virtual ~CInifile ();

  bool save_as ( LPCSTR = 0 );
  std::string get_as_string();

  LPCSTR fname () { return fName; };

  Sect& r_section      ( LPCSTR );
  Sect& r_section      ( const shared_str& );
  BOOL  line_exist     ( LPCSTR, LPCSTR );
  BOOL  line_exist     ( const shared_str&, const shared_str& );
  u32   line_count     ( LPCSTR );
  u32   line_count     ( const shared_str& );
  BOOL  section_exist  ( LPCSTR );
  BOOL  section_exist  ( const shared_str& );
  Root& sections       () { return DATA; }
  const Root& sections () const { return DATA; }

  CLASS_ID r_clsid    ( LPCSTR, LPCSTR );
  CLASS_ID r_clsid    ( const shared_str& S, LPCSTR L ) {
    return r_clsid( S.c_str(), L );
  }

  LPCSTR   r_string   ( LPCSTR, LPCSTR ); // оставляет кавычки
  LPCSTR   r_string   ( const shared_str& S, LPCSTR L ) {
    return r_string( S.c_str(), L );
  } // оставляет кавычки

  shared_str r_string_wb ( LPCSTR, LPCSTR ); // убирает кавычки
  shared_str r_string_wb ( const shared_str& S, LPCSTR L ) {
    return r_string_wb( S.c_str(), L );
  } // убирает кавычки
  
  shared_str r_string( LPCSTR, LPCSTR, shared_str );
  
  LPCSTR r_string( LPCSTR, LPCSTR, LPCSTR );
  LPCSTR r_string ( const shared_str& S, LPCSTR L, LPCSTR Defstr ) {
    return r_string( S.c_str(), L, Defstr );
  }
  LPCSTR r_string ( const shared_str& S, LPCSTR L, shared_str Defstr ) {
    return r_string( S.c_str(), L, Defstr.c_str() );
  }

  u8       r_u8       ( LPCSTR, LPCSTR );
  u8       r_u8       ( const shared_str& S, LPCSTR L ) {
    return r_u8( S.c_str(), L );
  }

  u16      r_u16      ( LPCSTR, LPCSTR );
  u16      r_u16      ( const shared_str& S, LPCSTR L ) {
    return r_u16( S.c_str(), L );
  }

  u32      r_u32      ( LPCSTR, LPCSTR );
  u32      r_u32      ( const shared_str& S, LPCSTR L ) {
    return r_u32( S.c_str(), L );
  }

  s8       r_s8       ( LPCSTR, LPCSTR );
  s8       r_s8       ( const shared_str& S, LPCSTR L ) {
    return r_s8( S.c_str(), L );
  }

  s16      r_s16      ( LPCSTR, LPCSTR );
  s16      r_s16      ( const shared_str& S, LPCSTR L ) {
    return r_s16( S.c_str(), L );
  }

  s32      r_s32      ( LPCSTR, LPCSTR );
  s32      r_s32      ( const shared_str& S, LPCSTR L ) {
    return r_s32( S.c_str(), L );
  }

  float    r_float    ( LPCSTR, LPCSTR );
  float    r_float    ( const shared_str& S, LPCSTR L ) {
    return r_float( S.c_str(), L );
  }

  float    r_float    ( LPCSTR, LPCSTR, float );
  float    r_float    ( const shared_str& S, LPCSTR L, float Defval ) {
    return r_float( S.c_str(), L, Defval );
  }

  Fcolor   r_fcolor   ( LPCSTR, LPCSTR );
  Fcolor   r_fcolor   ( const shared_str& S, LPCSTR L ) {
    return r_fcolor( S.c_str(), L );
  }

  u32      r_color    ( LPCSTR, LPCSTR );
  u32      r_color    ( const shared_str& S, LPCSTR L ) {
    return r_color( S.c_str(), L );
  }

  Ivector2 r_ivector2 ( LPCSTR, LPCSTR );
  Ivector2 r_ivector2 ( const shared_str& S, LPCSTR L ) {
    return r_ivector2( S.c_str(), L );
  }

  Ivector3 r_ivector3 ( LPCSTR, LPCSTR );
  Ivector3 r_ivector3 ( const shared_str& S, LPCSTR L ) {
    return r_ivector3( S.c_str(), L );
  }

  Ivector4 r_ivector4 ( LPCSTR, LPCSTR );
  Ivector4 r_ivector4 ( const shared_str& S, LPCSTR L ) {
    return r_ivector4( S.c_str(), L );
  }

  Fvector2 r_fvector2 ( LPCSTR, LPCSTR );
  Fvector2 r_fvector2 ( const shared_str& S, LPCSTR L ) {
    return r_fvector2( S.c_str(), L );
  }

  Fvector3 r_fvector3 ( LPCSTR, LPCSTR );
  Fvector3 r_fvector3 ( const shared_str& S, LPCSTR L ) {
    return r_fvector3( S.c_str(), L );
  }

  Fvector4 r_fvector4 ( LPCSTR, LPCSTR );
  Fvector4 r_fvector4 ( const shared_str& S, LPCSTR L ) {
    return r_fvector4( S.c_str(), L );
  }
  
  // Add by Zander
 

  Fvector2 r_fvec2 ( LPCSTR, LPCSTR, LPCSTR, u8 );
  Fvector2 r_fvec2 ( const shared_str& S, LPCSTR L, LPCSTR K, u8 I ) {
    return r_fvec2( S.c_str(), L, K, I );
  }

  Fvector3 r_fvec3 ( LPCSTR, LPCSTR, LPCSTR, LPCSTR, u8 );
  Fvector3 r_fvec3 ( const shared_str& S, LPCSTR L, LPCSTR K, LPCSTR M, u8 I ) {
    return r_fvec3( S.c_str(), L, K, M, I );
  }

  Fvector4 r_fvec4 ( LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPCSTR, u8 );
  Fvector4 r_fvec4 ( const shared_str& S, LPCSTR L, LPCSTR K, LPCSTR M, LPCSTR N, u8 I ) {
    return r_fvec4( S.c_str(), L, K, M, N, I );
  }
  
  // end add

  BOOL     r_bool     ( LPCSTR, LPCSTR );
  BOOL     r_bool     ( const shared_str& S, LPCSTR L ) {
    return r_bool( S.c_str(), L );
  }

  int      r_token    ( LPCSTR, LPCSTR, const xr_token *token_list );
  BOOL     r_line     ( LPCSTR, int, LPCSTR*, LPCSTR* );
  BOOL     r_line     ( const shared_str&, int, LPCSTR*, LPCSTR* );

  void     w_string   ( LPCSTR, LPCSTR, LPCSTR );
  void     w_u8       ( LPCSTR, LPCSTR, u8     );
  void     w_u16      ( LPCSTR, LPCSTR, u16    );
  void     w_u32      ( LPCSTR, LPCSTR, u32    );
  void     w_s8       ( LPCSTR, LPCSTR, s8     );
  void     w_s16      ( LPCSTR, LPCSTR, s16    );
  void     w_s32      ( LPCSTR, LPCSTR, s32    );
  void     w_float    ( LPCSTR, LPCSTR, float  );
  void     w_fcolor   ( LPCSTR, LPCSTR, const Fcolor& );
  void     w_color    ( LPCSTR, LPCSTR, u32    );
  void     w_ivector2 ( LPCSTR, LPCSTR, const Ivector2& );
  void     w_ivector3 ( LPCSTR, LPCSTR, const Ivector3& );
  void     w_ivector4 ( LPCSTR, LPCSTR, const Ivector4& );
  void     w_fvector2 ( LPCSTR, LPCSTR, const Fvector2& );
  void     w_fvector3 ( LPCSTR, LPCSTR, const Fvector3& );
  void     w_fvector4 ( LPCSTR, LPCSTR, const Fvector4& );
  void     w_bool     ( LPCSTR, LPCSTR, bool   );

  void     remove_line ( LPCSTR, LPCSTR );
  void     remove_section( LPCSTR );
};

// Main configuration file
extern XRCORE_API CInifile *pSettings;

 

xrCore/xr_ini.cpp


#include "stdafx.h"


#include "fs_internal.h"

XRCORE_API CInifile *pSettings = nullptr;


CInifile* CInifile::Create( const char* szFileName, BOOL ReadOnly ) {
  return xr_new<CInifile>( szFileName, ReadOnly );
}

void CInifile::Destroy( CInifile* ini ) {
  xr_delete( ini );
}


//Тело функций Inifile
XRCORE_API void _parse( LPSTR dest, LPCSTR src ) {
  if ( src ) {
    bool bInsideSTR = false;
    while ( *src ) {
      if ( isspace( (u8)*src ) ) {
        if ( bInsideSTR ) { *dest++ = *src++; continue; }
        while ( *src && iswspace( *src ) ) src++;
        continue;
      }
      else if ( *src == '"' ) {
        bInsideSTR = !bInsideSTR;
      }
      *dest++ = *src++;
    }
  }
  *dest = 0;
}


XRCORE_API void _decorate( LPSTR dest, LPCSTR src ) {
  if (src) {
    bool bInsideSTR = false;
    while ( *src ) {
      if ( *src == ',' ) {
        if ( bInsideSTR )
          *dest++ = *src++;
        else {
          *dest++ = *src++;
          *dest++ = ' ';
        }
        continue;
      }
      else if ( *src=='"' ) {
        bInsideSTR = !bInsideSTR;
      }
      *dest++ = *src++;
    }
  }
  *dest = 0;
}


BOOL CInifile::Sect::line_exist( LPCSTR L, LPCSTR* val ) {
  shared_str s( L );
  const auto A = Data.find( s );
  if (A != Data.end() ){
    if ( val ) *val = *A->second;
    return TRUE;
  }
  return FALSE;
}

LPCSTR CInifile::Sect::r_string( LPCSTR L ) {
	if (!L || !strlen(L)) //--#SM+#-- [fix for one of "xrDebug - Invalid handler" error log]
		Msg("!![ERROR] CInifile::Sect::r_string: S = [%s], L = [%s]", Name.c_str(), L);

	shared_str k(L);
	const auto A = Data.find(k);
	if (A != Data.end())
		return A->second.c_str();
	else
		FATAL("Can't find variable %s in [%s]", L, Name.c_str());
	return 0;
}

float CInifile::Sect::r_float( LPCSTR L ) {
	LPCSTR C = r_string(L);
	return float(atof(C));
}

u32 CInifile::Sect::r_u32( LPCSTR L ) {
	LPCSTR C = r_string(L);
	return u32(atoi(C));
}

Fvector3 CInifile::Sect::r_fvector3( LPCSTR L ) {
	LPCSTR   C = r_string(L);
	Fvector3 V = { 0.f, 0.f, 0.f };
	sscanf(C, "%f,%f,%f", &V.x, &V.y, &V.z);
	return V;
}

Ivector2 CInifile::Sect::r_ivector2( LPCSTR L ) {
	LPCSTR   C = r_string(L);
	Ivector2 V = { 0, 0 };
	sscanf(C, "%d,%d", &V.x, &V.y);
	return V;
}

u32 CInifile::Sect::line_count() {
	return u32( Data.size() );
}

CInifile::CInifile( IReader* F, LPCSTR path ) {
  fName      = 0;
  bReadOnly  = true;
  bSaveAtEnd = FALSE;
  Load( F, path );
}


CInifile::CInifile( LPCSTR szFileName, BOOL ReadOnly, BOOL bLoad, BOOL SaveAtEnd ) {
  fName       = szFileName ? xr_strdup( szFileName ) : 0;
  bReadOnly   = !!ReadOnly;
  bSaveAtEnd  = SaveAtEnd;
  if ( bLoad ) {
    string_path path, folder;
    _splitpath( fName, path, folder, 0, 0 );
    strcat( path, folder );
    IReader* R = FS.r_open( szFileName );
    if ( R ) {
      Load( R, path );
      FS.r_close( R );
    }
  }
}


CInifile::~CInifile() {
  if ( !bReadOnly && bSaveAtEnd ) {
    if ( !save_as() )
      Log( "!Can't save inifile:", fName );
  }
  xr_free( fName );
  for ( auto &I : DATA ) xr_delete( I.second );
}


static void insert_item( CInifile::Sect *tgt, const CInifile::Item& I ) {
  auto sect_it = tgt->Data.find( I.first );
  if ( sect_it != tgt->Data.end() && sect_it->first.equal( I.first ) ) {
    sect_it->second = I.second;
    auto found = std::find_if(
      tgt->Unordered.begin(), tgt->Unordered.end(),
      [&]( const auto &it ) {
        return xr_strcmp( *it.first, *I.first ) == 0;
      }
    );
    if ( found != tgt->Unordered.end() ) {
      found->second = I.second;
    }
  }
  else {
    tgt->Data.insert({ I.first, I.second });
    tgt->Unordered.push_back( I );
  }
}


void CInifile::Load ( IReader* F, LPCSTR path ) {
  R_ASSERT( F );
  Sect       *Current = nullptr;
  string4096 str;
  string4096 str2;

  while ( !F->eof() ) {
    F->r_string( str, sizeof( str ) );
    _Trim( str );
    LPSTR semi   = strchr( str, ';' );
    LPSTR semi_1 = strchr( str, '/' );

    if ( semi_1 && ( *(semi_1 + 1) == '/' ) && ( (!semi) || ( semi && ( semi_1 < semi ) ) ) )
      semi = semi_1;

    if ( semi )
      *semi = 0;

    if ( str[ 0 ] && ( str[ 0 ] == '#' ) && strstr( str, "#include" ) ) {
      string64 inc_name;
      R_ASSERT( path && path[ 0 ] );
      if ( _GetItem( str, 1, inc_name, '"' ) ) {
        string_path fn, inc_path, folder;
        strconcat( sizeof( fn ), fn, path, inc_name );
        _splitpath( fn, inc_path, folder, 0, 0 );
        strcat( inc_path, folder );
        IReader* I = FS.r_open( fn );
        R_ASSERT3( I, "Can't find include file:", inc_name );
        Load( I, inc_path );
        FS.r_close( I );
      }
    }
    else if ( str[ 0 ] && ( str[ 0 ] == '[' ) ) {
      // insert previous filled section
      if ( Current ) {
        auto I = DATA.find( Current->Name );
        if ( I != DATA.end() )
          FATAL( "Duplicate section '%s' found.", Current->Name.c_str() );
        DATA.insert({ Current->Name, Current });
      }
      Current = xr_new<Sect>();
      Current->Name = 0;
      // start new section
      R_ASSERT3( strchr( str, ']' ), "Bad ini section found: ", str );
      LPCSTR inherited_names = strstr( str, "]:" );
      if ( 0 != inherited_names ) {
        VERIFY2( bReadOnly, "Allow for readonly mode only." );
        inherited_names += 2;
        int cnt = _GetItemCount( inherited_names );
        for ( int k = 0; k < cnt; ++k ) {
          xr_string tmp;
          _GetItem( inherited_names, k, tmp );
          Sect& inherited = r_section( tmp.c_str() );
          for ( auto &it : inherited.Data ) {
            Item I = { it.first, it.second };
            insert_item( Current, I );
          }
        }
      }
      *strchr( str, ']' ) = 0;
      Current->Name = strlwr( str + 1 );
    }
    else {
      if ( Current ) {
        char* name = str;
        char* t    = strchr( name, '=' );
        if ( t ) {
          *t = 0;
          _Trim( name );
          _parse( str2, ++t );
        }
        else {
          _Trim( name );
          str2[ 0 ] = 0;
        }

        if ( name[ 0 ] ) {
          Item I;
          I.first  = name;
          I.second = str2[ 0 ] ? str2 : 0;
          if ( bReadOnly ) {
            if ( *I.first )
              insert_item( Current, I );
          }
          else {
            if ( *I.first || *I.second )
              insert_item( Current, I );
          }
        }
      }
    }
  }

  if ( Current ) {
    auto I = DATA.find( Current->Name );
    if ( I != DATA.end() )
      FATAL( "Duplicate section '%s' found.", Current->Name.c_str() );
    DATA.insert({ Current->Name, Current });
  }
}


bool CInifile::save_as( LPCSTR new_fname ) {
  // save if needed
  if ( new_fname && new_fname[ 0 ] ) {
    xr_free( fName );
    fName = xr_strdup( new_fname );
  }
  R_ASSERT( fName && fName[ 0 ] );
  IWriter* F = FS.w_open_ex( fName );
  if ( F ) {
    string512 temp, val;
    for ( const auto &r_it : DATA ) {
      sprintf_s( temp, sizeof( temp ), "[%s]", r_it.first.c_str() );
      F->w_string( temp );
      for ( const auto &I : r_it.second->Unordered ) {
        if ( *I.first ) {
          if ( *I.second ) {
            _decorate( val, *I.second );
            {
              // only name and value
              sprintf_s( temp, sizeof( temp ), "%8s%-32s = %-32s", " ", *I.first, val );
            }
          }
          else {
            {
              // only name
              sprintf_s( temp, sizeof( temp ), "%8s%-32s = ", " ", *I.first );
            }
          }
        }
        else {
          // no name, so no value
          temp[ 0 ] = 0;
        }
        _TrimRight( temp );
        if ( temp[ 0 ] ) F->w_string( temp );
      }
      F->w_string( " " );
    }
    FS.w_close( F );
    return true;
  }
  return false;
}


BOOL CInifile::section_exist( LPCSTR S ) {
  shared_str k( S );
  const auto I = DATA.find( k );
  return I != DATA.end();
}


BOOL CInifile::line_exist( LPCSTR S, LPCSTR L ) {
  if ( !section_exist( S ) ) return FALSE;
  Sect&   I = r_section( S );
  shared_str k( L );
  const auto A = I.Data.find( k );
  return A != I.Data.end();
}

u32 CInifile::line_count( LPCSTR Sname ) {
  Sect& S = r_section( Sname );
  return S.line_count();
}


CInifile::Sect& CInifile::r_section ( const shared_str& S ) {
  return r_section( S.c_str() );
}


BOOL CInifile::line_exist ( const shared_str& S, const shared_str& L ) {
  return line_exist( S.c_str(), L.c_str() );
}


u32 CInifile::line_count ( const shared_str& S ) {
  return line_count( S.c_str() );
}


BOOL CInifile::section_exist ( const shared_str& S ) {
  return section_exist( S.c_str() );
}


CInifile::Sect& CInifile::r_section( LPCSTR S ) {
  R_ASSERT( S && strlen( S ), "Empty section (null\\'') passed into CInifile::r_section(). See info above ^, check your configs and 'call stack'." ); //--#SM+#--

  char section[ 256 ];
  strcpy_s( section, sizeof( section ), S );
  shared_str k = strlwr( section );
  const auto I = DATA.find( k );
  if ( I == DATA.end() )
    FATAL( "Can't open section '%s'", S );
  return  *I->second;
}

LPCSTR CInifile::r_string ( LPCSTR S, LPCSTR L ) {
  if ( !S || !L || !strlen( S ) || !strlen( L ) ) //--#SM+#-- [fix for one of "xrDebug - Invalid handler" error log]
    Msg( "!![ERROR] CInifile::r_string: S = [%s], L = [%s]", S, L );

  Sect&   I = r_section( S );
  shared_str k( L );
  const auto A = I.Data.find( k );
  if ( A != I.Data.end() )
    return A->second.c_str();
  else
    FATAL( "Can't find variable %s in [%s]", L, S );
  return 0;
}

shared_str CInifile::r_string ( LPCSTR S, LPCSTR L, shared_str Defstr ) {
  if ( !S || !L || !strlen( S ) || !strlen( L ) ) //--#SM+#-- [fix for one of "xrDebug - Invalid handler" error log]
    Msg( "!![ERROR] CInifile::r_string: S = [%s], L = [%s]", S, L );

  Sect&   I = r_section( S );
  shared_str k( L );
  const auto A = I.Data.find( k );
  if ( A != I.Data.end() )
    return A->second.c_str();
  else
    return Defstr;
}

LPCSTR CInifile::r_string ( LPCSTR S, LPCSTR L, LPCSTR Defstr ) {
  if ( !S || !L || !strlen( S ) || !strlen( L ) ) //--#SM+#-- [fix for one of "xrDebug - Invalid handler" error log]
    Msg( "!![ERROR] CInifile::r_string: S = [%s], L = [%s]", S, L );

  Sect&   I = r_section( S );
  shared_str k( L );
  const auto A = I.Data.find( k );
  if ( A != I.Data.end() )
    return A->second.c_str();
  else
    return Defstr;
}


shared_str CInifile::r_string_wb( LPCSTR S, LPCSTR L ) {
  LPCSTR _base = r_string( S, L );
  if ( 0 == _base ) return  shared_str( 0 );
  string512 _original;
  strcpy_s( _original, _base );
  u32 _len = xr_strlen( _original );
  if ( 0 == _len ) return  shared_str( "" );
  if ( '"' == _original[ _len - 1 ] ) _original[ _len - 1 ] = 0; // skip end
  if ( '"' == _original[ 0 ] ) return  shared_str( &_original[ 0 ] + 1 ); // skip begin
  return shared_str( _original );
}


u8 CInifile::r_u8 ( LPCSTR S, LPCSTR L ) {
  LPCSTR C = r_string( S, L );
  return u8( atoi( C ) );
}


u16 CInifile::r_u16 ( LPCSTR S, LPCSTR L ) {
  LPCSTR C = r_string( S, L );
  return u16( atoi( C ) );
}


u32 CInifile::r_u32 ( LPCSTR S, LPCSTR L ) {
  LPCSTR C = r_string( S, L );
  return u32( atoi( C ) );
}


s8 CInifile::r_s8 ( LPCSTR S, LPCSTR L ) {
  LPCSTR C = r_string( S, L );
  return s8( atoi( C ) );
}


s16 CInifile::r_s16 ( LPCSTR S, LPCSTR L ) {
  LPCSTR C = r_string( S, L );
  return s16( atoi( C ) );
}


s32 CInifile::r_s32 ( LPCSTR S, LPCSTR L ) {
  LPCSTR C = r_string( S, L );
  return s32( atoi( C ) );
}


float CInifile::r_float ( LPCSTR S, LPCSTR L ) {
  LPCSTR C = r_string( S, L );
  return float( atof( C ) );
}

float CInifile::r_float ( LPCSTR S, LPCSTR L, float Defval ) {
	if(!line_exist( S, L )) return Defval;
  LPCSTR C = r_string( S, L);
  return float( atof( C ) );
}


Fcolor CInifile::r_fcolor ( LPCSTR S, LPCSTR L ) {
  LPCSTR C = r_string( S, L );
  Fcolor V = { 0, 0, 0, 0 };
  sscanf( C, "%f,%f,%f,%f", &V.r, &V.g, &V.b, &V.a );
  return V;
}


u32 CInifile::r_color ( LPCSTR S, LPCSTR L ) {
  LPCSTR C = r_string( S, L );
  u32    r = 0, g = 0, b = 0, a = 255;
  sscanf( C, "%d,%d,%d,%d", &r, &g, &b, &a );
  return color_rgba( r, g, b, a );
}


Ivector2 CInifile::r_ivector2 ( LPCSTR S, LPCSTR L ) {
  LPCSTR   C = r_string( S, L );
  Ivector2 V = { 0, 0 };
  sscanf( C, "%d,%d", &V.x, &V.y );
  return V;
}


Ivector3 CInifile::r_ivector3 ( LPCSTR S, LPCSTR L ) {
  LPCSTR  C = r_string( S, L );
  Ivector V = { 0, 0, 0 };
  sscanf( C, "%d,%d,%d", &V.x, &V.y, &V.z );
  return V;
}


Ivector4 CInifile::r_ivector4 ( LPCSTR S, LPCSTR L ) {
  LPCSTR   C = r_string( S, L );
  Ivector4 V = { 0, 0, 0, 0 };
  sscanf( C, "%d,%d,%d,%d", &V.x, &V.y, &V.z, &V.w );
  return V;
}


Fvector2 CInifile::r_fvector2 ( LPCSTR S, LPCSTR L ) {
  LPCSTR   C = r_string( S, L );
  Fvector2 V = { 0.f, 0.f };
  sscanf( C, "%f,%f", &V.x, &V.y );
  return V;
}


Fvector3 CInifile::r_fvector3 ( LPCSTR S, LPCSTR L ) {
  LPCSTR   C = r_string( S, L );
  Fvector3 V = { 0.f, 0.f, 0.f };
  sscanf( C, "%f,%f,%f", &V.x, &V.y, &V.z );
  return V;
}


Fvector4 CInifile::r_fvector4 ( LPCSTR S, LPCSTR L ) {
  LPCSTR   C = r_string( S, L );
  Fvector4 V = { 0.f, 0.f, 0.f, 0.f };
  sscanf( C, "%f,%f,%f,%f", &V.x, &V.y, &V.z, &V.w );
  return V;
}

// Add by Zander

Fvector2 CInifile::r_fvec2 ( LPCSTR S, LPCSTR L, LPCSTR K, u8 I ) {
	Msg("CInifile::r_fvec2 [%s], [%s], [%s], [%f]", S, L, K, I);
	LPCSTR   C1 = r_string( S, L, "0.0" );
	LPCSTR   C2 = r_string( S, K, "0.0" );
	string128 a;
	float f = 0.f;
	shared_str tl;
	Fvector2 V = { 0.f, 0.f };
	if (_GetItemCount( C1 ) > I) {
		f = float(atof(_GetItem(C1, I, a, ',', "0.0", true)));
		tl = shared_str(_GetItem(C1, I, a, ',', "0.0", true));
		sscanf(tl.c_str(), "%f", &V.x);
	}
	else { f = 0.f; V.x = 0.f; }
	Msg("CInifile::r_fvec2 549 [%f], [%s]", f, tl.c_str());
	if (_GetItemCount( C2 ) > I) {
		f = float(atof(_GetItem(C2, I, a, ',', "0.0", true)));
		tl = shared_str(_GetItem(C2, I, a, ',', "0.0", true));
		sscanf(tl.c_str(), "%f", &V.y);
	}
	else { f = 0.f; V.y = 0.f; }
	Msg("CInifile::r_fvec2 556 [%f], [%s]", f, tl.c_str());
	Msg("Return: V.x[%f], V.y[%f]", V.x, V.y);
	return V;
}


Fvector3 CInifile::r_fvec3 ( LPCSTR S, LPCSTR L, LPCSTR K, LPCSTR M, u8 I ) {
	Msg("CInifile::r_fvec3 [%s], [%s], [%s], [%s], [%f]", S, L, K, M, I);
	LPCSTR   C1 = r_string( S, L, "0.0" );
	LPCSTR   C2 = r_string( S, K, "0.0" );
	LPCSTR   C3 = r_string( S, M, "0.0" );
	string128 a;
	float f = 0.f;
	shared_str tl;
	Fvector3 V = { 0.f, 0.f, 0.f };
	if (_GetItemCount( C1 ) > I) {
		f = float(atof(_GetItem(C1, I, a, ',', "0.0", true)));
		tl = shared_str(_GetItem(C1, I, a, ',', "0.0", true));
		sscanf(tl.c_str(), "%f", &V.x);
	}
	else { f = 0.f; V.x = 0.f; }
	Msg("CInifile::r_fvec3 577 [%f], [%s]", f, tl.c_str());
	if (_GetItemCount( C2 ) > I) {
		f = float(atof(_GetItem(C2, I, a, ',', "0.0", true)));
		tl = shared_str(_GetItem(C2, I, a, ',', "0.0", true));
		sscanf(tl.c_str(), "%f", &V.y);
	}
	else { f = 0.f; V.y = 0.f; }
	Msg("CInifile::r_fvec3 584 [%f], [%s]", f, tl.c_str());
	if (_GetItemCount( C3 ) > I) {
		f = float(atof(_GetItem(C3, I, a, ',', "0.0", true)));
		tl = shared_str(_GetItem(C3, I, a, ',', "0.0", true));
		sscanf(tl.c_str(), "%f", &V.z);
	}
	else { f = 0.f; V.z = 0.f; }
	Msg("CInifile::r_fvec3 591 [%f], [%s]", f, tl.c_str());
	Msg("Return: V.x[%f], V.y[%f], V.z[%f]", V.x, V.y, V.z);
	return V;
}


Fvector4 CInifile::r_fvec4 ( LPCSTR S, LPCSTR L, LPCSTR K, LPCSTR M, LPCSTR N, u8 I ) {
	Msg("CInifile::r_fvec4 [%s], [%s], [%s], [%s], [%s], [%f]", S, L, K, M, N, I);
	LPCSTR   C1 = r_string( S, L, "0.0" );
	LPCSTR   C2 = r_string( S, K, "0.0" );
	LPCSTR   C3 = r_string( S, M, "0.0" );
	LPCSTR   C4 = r_string( S, N, "0.0" );
	string128 a;
	float f = 0.f;
	shared_str tl;
	Fvector4 V = { 0.f, 0.f, 0.f, 0.f };
	if (_GetItemCount( C1 ) > I) {
		f = float(atof(_GetItem(C1, I, a, ',', "0.0", true)));
		tl = shared_str(_GetItem(C1, I, a, ',', "0.0", true));
		sscanf(tl.c_str(), "%f", &V.x);
	}
	else { f = 0.f; V.x = 0.f; }
	Msg("CInifile::r_fvec4 613 [%f], [%s]", f, tl.c_str());
	if (_GetItemCount( C2 ) > I) {
		f = float(atof(_GetItem(C2, I, a, ',', "0.0", true)));
		tl = shared_str(_GetItem(C2, I, a, ',', "0.0", true));
		sscanf(tl.c_str(), "%f", &V.y);
	}
	else { f = 0.f; V.y = 0.f; }
	Msg("CInifile::r_fvec4 620 [%f], [%s]", f, tl.c_str());
	if (_GetItemCount( C3 ) > I) {
		f = float(atof(_GetItem(C3, I, a, ',', "0.0", true)));
		tl = shared_str(_GetItem(C3, I, a, ',', "0.0", true));
		sscanf(tl.c_str(), "%f", &V.z);
	}
	else { f = 0.f; V.z = 0.f; }
	Msg("CInifile::r_fvec4 627 [%f], [%s]", f, tl.c_str());
	if (_GetItemCount( C4 ) > I) {
		f = float(atof(_GetItem(C4, I, a, ',', "0.0", true)));
		tl = shared_str(_GetItem(C4, I, a, ',', "0.0", true));
		sscanf(tl.c_str(), "%f", &V.w);
	}
	else { f = 0.f; V.w = 0.f; }
	Msg("CInifile::r_fvec4 634 [%f], [%s]", f, tl.c_str());
	Msg("Return: V.x[%f], V.y[%f], V.z[%f], V.w[%f]", V.x, V.y, V.z, V.w);
	return V;
}

// end add

BOOL CInifile::r_bool ( LPCSTR S, LPCSTR L ) {
  LPCSTR C = r_string( S, L );
  char   B[ 8 ];
  strncpy( B, C, 7 );
  strlwr( B );
  return IsBOOL( B );
}


CLASS_ID CInifile::r_clsid ( LPCSTR S, LPCSTR L) {
  LPCSTR C = r_string( S, L );
  return TEXT2CLSID( C );
}


int CInifile::r_token ( LPCSTR S, LPCSTR L, const xr_token *token_list ) {
  LPCSTR C = r_string( S, L );
  for( int i = 0; token_list[ i ].name; i++ )
    if( !stricmp( C, token_list[ i ].name ) )
      return token_list[ i ].id;
  return 0;
}


BOOL CInifile::r_line( LPCSTR S, int L, const char** N, const char** V ) {
  Sect& SS = r_section( S );
  if ( L >= (int)SS.Unordered.size() || L < 0 ) return FALSE;
  const auto &I = SS.Unordered.at( L );
  *N = I.first.c_str();
  *V = I.second.c_str();
  return TRUE;
}


BOOL CInifile::r_line( const shared_str& S, int L, const char** N, const char** V ) {
  return r_line( S.c_str(), L, N, V );
}


void CInifile::w_string ( LPCSTR S, LPCSTR L, LPCSTR V ) {
  R_ASSERT( !bReadOnly );

  // section
  char sect[ 256 ];
  _parse( sect, S );
  _strlwr( sect );
  ASSERT_FMT( sect[ 0 ], "[%s]: wrong section name [%s]", __FUNCTION__, S );
  if ( !section_exist( sect ) ) {
    // create _new_ section
    Sect *NEW = xr_new<Sect>();
    NEW->Name = sect;
    DATA.insert({ NEW->Name, NEW });
  }

  // parse line/value
  char line [ 256 ];
  _parse( line, L );
  ASSERT_FMT( line[ 0 ], "[%s]: wrong param name [%s]", __FUNCTION__, L );
  char value[ 256 ];
  _parse( value, V );

  // duplicate & insert
  Item I;
  I.first  = line;
  I.second = value[ 0 ] ? value : 0;
  Sect* data = &r_section( sect );
  insert_item( data, I );
}


void CInifile::w_u8 ( LPCSTR S, LPCSTR L, u8 V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%d", V );
  w_string( S, L, temp );
}


void CInifile::w_u16 ( LPCSTR S, LPCSTR L, u16 V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%d", V );
  w_string( S, L, temp );
}


void CInifile::w_u32( LPCSTR S, LPCSTR L, u32 V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%d", V );
  w_string( S, L, temp );
}


void CInifile::w_s8 ( LPCSTR S, LPCSTR L, s8 V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%d", V );
  w_string( S, L, temp );
}


void CInifile::w_s16 ( LPCSTR S, LPCSTR L, s16 V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%d", V );
  w_string( S, L, temp );
}


void CInifile::w_s32 ( LPCSTR S, LPCSTR L, s32 V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%d", V );
  w_string( S, L, temp);
}


void CInifile::w_float ( LPCSTR S, LPCSTR L, float V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%f", V );
  w_string( S, L, temp );
}


void CInifile::w_fcolor ( LPCSTR S, LPCSTR L, const Fcolor& V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%f,%f,%f,%f", V.r, V.g, V.b, V.a );
  w_string( S, L, temp );
}


void CInifile::w_color ( LPCSTR S, LPCSTR L, u32 V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%d,%d,%d,%d", color_get_R( V ), color_get_G( V ), color_get_B( V ), color_get_A( V ) );
  w_string( S, L, temp );
}



void CInifile::w_ivector2 ( LPCSTR S, LPCSTR L, const Ivector2& V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%d,%d", V.x, V.y );
  w_string( S, L, temp );
}


void CInifile::w_ivector3 ( LPCSTR S, LPCSTR L, const Ivector3& V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%d,%d,%d", V.x, V.y, V.z );
  w_string( S, L, temp );
}


void CInifile::w_ivector4 ( LPCSTR S, LPCSTR L, const Ivector4& V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%d,%d,%d,%d", V.x, V.y, V.z, V.w );
  w_string( S, L, temp );
}


void CInifile::w_fvector2 ( LPCSTR S, LPCSTR L, const Fvector2& V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%f,%f", V.x, V.y );
  w_string( S, L, temp );
}


void CInifile::w_fvector3 ( LPCSTR S, LPCSTR L, const Fvector3& V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%f,%f,%f", V.x, V.y, V.z );
  w_string( S, L, temp );
}


void CInifile::w_fvector4 ( LPCSTR S, LPCSTR L, const Fvector4& V ) {
  string128 temp;
  sprintf_s( temp, sizeof( temp ), "%f,%f,%f,%f", V.x, V.y, V.z, V.w );
  w_string( S, L, temp );
}


void CInifile::w_bool ( LPCSTR S, LPCSTR L, bool V ) {
  w_string( S, L, V ? "true" : "false" );
}


void CInifile::remove_line( LPCSTR S, LPCSTR L ) {
  R_ASSERT( !bReadOnly );

  if ( line_exist( S, L ) ) {
    Sect& data = r_section( S );
    shared_str k( L );
    auto A = data.Data.find( k );
    R_ASSERT( A != data.Data.end() );
    data.Data.erase( A );
    auto found = std::find_if(
      data.Unordered.begin(), data.Unordered.end(),
      [&]( const auto& it ) {
        return xr_strcmp( *it.first, L ) == 0;
      }
    );
    R_ASSERT( found != data.Unordered.end() );
    data.Unordered.erase( found );
  }
}


void CInifile::remove_section( LPCSTR S ) {
  R_ASSERT( !bReadOnly );

  if ( section_exist( S ) ) {
    shared_str k( S );
    const auto I = DATA.find( k );
    R_ASSERT( I != DATA.end() );
    DATA.erase( I );
  }
}


#include <sstream>

std::string CInifile::get_as_string() {
  std::stringstream str;

  bool first_sect = true;
  for ( const auto &r_it : DATA ) {
    if ( !first_sect ) str << "\r\n";
    first_sect = false;
    str << "[" << r_it.first.c_str() << "]\r\n";
    for ( const auto &I : r_it.second->Unordered ) {
      if ( I.first.c_str() ) {
        if ( I.second.c_str() ) {
          string512 val;
          _decorate( val, I.second.c_str() );
          _TrimRight( val );
          // only name and value
          str << I.first.c_str() << " = " << val << "\r\n";
        }
        else {
          // only name
          str << I.first.c_str() << " =\r\n";
        }
      }
    }
  }

  return str.str();
}


 

 

  • Полезно 1

Тестеры о "Судьбе Зоны": Все это бегает, орет, гоняется друг за другом, попадает в аномалии. Я не знаю что там можно делать и в какой экипировке туда можно идти...

Имею мнение, что >90% модов на сталкер неиграбельны. Делаю свое, играбельное. Внимание: Если вы считаете что с модами на сталкер все ок, то в мое творение вам будет очень тяжко играть.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

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.


  • Recently Browsing   0 members

    No registered users viewing this page.

AMK-Team.ru

×
×
  • Create New...