示例#1
0
void CommandParser::ParseStringCommand(int cmd, const string& s, PlayerInfo& info)
{
	LocalString str;
	PrintMsgFunc prev_func = g_print_func;
	g_print_func = [&str](cstring s)
	{
		if(!str.empty())
			str += "\n";
		str += s;
	};

	switch((CMD)cmd)
	{
	case CMD_ARENA:
		ArenaCombat(s.c_str());
		break;
	}

	g_print_func = prev_func;

	if(!str.empty())
	{
		NetChangePlayer& c = Add1(info.changes);
		c.type = NetChangePlayer::GENERIC_CMD_RESPONSE;
		c.str = str.Pin();
	}
}
示例#2
0
void CommandParser::ListEffects(Unit* u)
{
	if(u->effects.empty())
	{
		Msg("Unit have no effects.");
		return;
	}

	LocalString s;
	s = Format("Unit effects (%u):", u->effects.size());
	for(Effect& e : u->effects)
	{
		s += Format("\n%s, power %g, source ", EffectInfo::effects[(int)e.effect].id, e.power);
		switch(e.source)
		{
		case EffectSource::Temporary:
			s += Format("temporary, time %g", e.time);
			break;
		case EffectSource::Perk:
			s += Format("perk (%s)", PerkInfo::perks[e.source_id].id);
			break;
		case EffectSource::Permanent:
			s += "permanent";
			break;
		}
	}
	Msg(s.c_str());
}
示例#3
0
void CommandParser::ListPerks(PlayerController* pc)
{
	if(pc->perks.empty())
	{
		Msg("Unit have no perks.");
		return;
	}

	LocalString s;
	s = Format("Unit perks (%u):", pc->perks.size());
	for(TakenPerk& tp : pc->perks)
	{
		PerkInfo& info = PerkInfo::perks[(int)tp.perk];
		s += Format("\n%s", info.id);
		if(info.value_type == PerkInfo::Attribute)
			s += Format(" (%s)", Attribute::attributes[tp.value].id);
		else if(info.value_type == PerkInfo::Skill)
			s += Format(" (%s)", Skill::skills[tp.value].id);
	}
	Msg(s.c_str());
}
示例#4
0
void CommandParser::ListStats(Unit* u)
{
	int hp = int(u->hp);
	if(hp == 0 && u->hp > 0)
		hp = 1;
	Msg("--- %s (%s) level %d ---", u->GetName(), u->data->id.c_str(), u->level);
	if(u->data->stat_profile && !u->data->stat_profile->subprofiles.empty() && !u->IsPlayer())
	{
		Msg("Profile %s.%s (weapon:%s armor:%s)",
			u->data->stat_profile->id.c_str(),
			u->data->stat_profile->subprofiles[u->stats->subprofile.index]->id.c_str(),
			Skill::skills[(int)WeaponTypeInfo::info[u->stats->subprofile.weapon].skill].id,
			Skill::skills[(int)GetArmorTypeSkill((ARMOR_TYPE)u->stats->subprofile.armor)].id);
	}
	Msg("Health: %d/%d (bonus: %+g, regeneration: %+g/sec, natural: x%g)", hp, (int)u->hpmax, u->GetEffectSum(EffectId::Health),
		u->GetEffectSum(EffectId::Regeneration), u->GetEffectMul(EffectId::NaturalHealingMod));
	Msg("Stamina: %d/%d", (int)u->stamina, (int)u->stamina_max);
	Msg("Melee attack: %s (bonus: %+g), ranged: %s (bonus: %+g)",
		(u->HaveWeapon() || u->data->type == UNIT_TYPE::ANIMAL) ? Format("%d", (int)u->CalculateAttack()) : "-",
		u->GetEffectSum(EffectId::MeleeAttack),
		u->HaveBow() ? Format("%d", (int)u->CalculateAttack(&u->GetBow())) : "-",
		u->GetEffectSum(EffectId::RangedAttack));
	Msg("Defense %d (bonus: %+g), block: %s", (int)u->CalculateDefense(), u->GetEffectSum(EffectId::Defense),
		u->HaveShield() ? Format("%d", (int)u->CalculateBlock()) : "");
	Msg("Mobility: %d (bonus %+g)", (int)u->CalculateMobility(), u->GetEffectSum(EffectId::Mobility));
	Msg("Carry: %g/%g (mod: x%g)", float(u->weight) / 10, float(u->weight_max) / 10, u->GetEffectMul(EffectId::Carry));
	Msg("Magic resistance: %d%%", (int)((1.f - u->CalculateMagicResistance()) * 100));
	Msg("Poison resistance: %d%%", (int)((1.f - u->GetEffectMul(EffectId::PoisonResistance)) * 100));
	LocalString s = "Attributes: ";
	for(int i = 0; i < (int)AttributeId::MAX; ++i)
		s += Format("%s:%d ", Attribute::attributes[i].id, u->stats->attrib[i]);
	Msg(s.c_str());
	s = "Skills: ";
	for(int i = 0; i < (int)SkillId::MAX; ++i)
	{
		if(u->stats->skill[i] > 0)
			s += Format("%s:%d ", Skill::skills[i].id, u->stats->skill[i]);
	}
	Msg(s.c_str());
}
示例#5
0
bool CommandParser::ParseStream(BitStreamReader& f, PlayerInfo& info)
{
	LocalString str;
	PrintMsgFunc prev_func = g_print_func;
	g_print_func = [&str](cstring s)
	{
		if(!str.empty())
			str += "\n";
		str += s;
	};

	bool result = ParseStreamInner(f);

	g_print_func = prev_func;

	if(result && !str.empty())
	{
		NetChangePlayer& c = Add1(info.changes);
		c.type = NetChangePlayer::GENERIC_CMD_RESPONSE;
		c.str = str.Pin();
	}

	return result;
}
示例#6
0
//=================================================================================================
void TeamPanel::Draw(ControlDrawData*)
{
	GamePanel::Draw();

	Rect rect = {
		pos.x + 8,
		pos.y + 8,
		pos.x + size.x - 16,
		pos.y + size.y - 16
	};
	GUI.DrawText(GUI.fBig, txTeam, DTF_TOP | DTF_CENTER, Color::Black, rect);

	Int2 offset = global_pos + Int2(8, 40 - scrollbar.offset);
	rect = Rect::Create(Int2(global_pos.x + 8, global_pos.y + 40), Int2(size.x - 52, size.y - 96));

	Vec2 share = Team.GetShare();
	int pc_share = (int)round(share.x * 100);
	int npc_share = (int)round(share.y * 100);
	LocalString s;

	if(!picking)
		picked = -1;

	int n = 0;
	int hitbox_counter = 0;
	hitboxes.clear();
	Matrix mat;
	for(Unit* u : Team.members)
	{
		if(u->GetClass() != Class::INVALID)
		{
			TEX t = ClassInfo::classes[(int)u->GetClass()].icon;
			Int2 img_size;
			Vec2 scale;
			Control::ResizeImage(t, Int2(32, 32), img_size, scale);
			mat = Matrix::Transform2D(nullptr, 0.f, &scale, nullptr, 0.f, &Vec2((float)offset.x, (float)offset.y));
			GUI.DrawSprite2(t, mat, nullptr, &rect, Color::White);
		}
		if(u == Team.leader)
			GUI.DrawSprite(tKorona, Int2(offset.x + 32, offset.y), Color::White, &rect);
		if(!u->IsAlive())
			GUI.DrawSprite(tCzaszka, Int2(offset.x + 64, offset.y), Color::White, &rect);

		Rect r2 = {
			offset.x + 96,
			offset.y,
			offset.x + 1000,
			offset.y + 32
		};
		s = "$h+";
		s += Format(txCharInTeam, u->GetName(), u->IsPlayer() ? pc_share : (u->hero->free ? 0 : npc_share), u->GetCredit());
		if(u->IsPlayer() && Net::IsOnline())
		{
			if(Net::IsServer())
			{
				if(u != game.pc->unit)
					s += Format(txPing, N.peer->GetAveragePing(u->player->player_info->adr));
			}
			else if(u == game.pc->unit)
				s += Format(txPing, N.peer->GetAveragePing(N.server));
			s += Format(txDays, u->player->free_days);
		}
		s += ")$h-";
		if(!GUI.DrawText(GUI.default_font, s->c_str(), DTF_VCENTER | DTF_SINGLELINE | DTF_PARSE_SPECIAL, (n == picked ? Color::White : Color::Black), r2, &rect, &hitboxes, &hitbox_counter))
			break;

		offset.y += 32;
		++n;
	}

	scrollbar.Draw();

	int count = (Net::IsOnline() ? 4 : 2);
	for(int i = 0; i < count; ++i)
		bt[i].Draw();

	DrawBox();
}
示例#7
0
文件: Main.cpp 项目: lcs2/carpg
//=================================================================================================
void LogProcessorFeatures()
{
	bool x64 = false;
	bool MMX = false;
	bool SSE = false;
	bool SSE2 = false;
	bool SSE3 = false;
	bool SSSE3 = false;
	bool SSE41 = false;
	bool SSE42 = false;
	bool SSE4a = false;
	bool AVX = false;
	bool XOP = false;
	bool FMA3 = false;
	bool FMA4 = false;

	int info[4];
	__cpuid(info, 0);
	int nIds = info[0];

	__cpuid(info, 0x80000000);
	int nExIds = info[0];

	// Detect Instruction Set
	if(nIds >= 1)
	{
		__cpuid(info, 0x00000001);
		MMX = (info[3] & ((int)1 << 23)) != 0;
		SSE = (info[3] & ((int)1 << 25)) != 0;
		SSE2 = (info[3] & ((int)1 << 26)) != 0;
		SSE3 = (info[2] & ((int)1 << 0)) != 0;

		SSSE3 = (info[2] & ((int)1 << 9)) != 0;
		SSE41 = (info[2] & ((int)1 << 19)) != 0;
		SSE42 = (info[2] & ((int)1 << 20)) != 0;

		AVX = (info[2] & ((int)1 << 28)) != 0;
		FMA3 = (info[2] & ((int)1 << 12)) != 0;
	}

	if(nExIds >= 0x80000001)
	{
		__cpuid(info, 0x80000001);
		x64 = (info[3] & ((int)1 << 29)) != 0;
		SSE4a = (info[2] & ((int)1 << 6)) != 0;
		FMA4 = (info[2] & ((int)1 << 16)) != 0;
		XOP = (info[2] & ((int)1 << 11)) != 0;
	}

	LocalString s = "Processor features: ";
	if(x64)
		s += "x64, ";
	if(MMX)
		s += "MMX, ";
	if(SSE)
		s += "SSE, ";
	if(SSE2)
		s += "SSE2, ";
	if(SSE3)
		s += "SSE3, ";
	if(SSSE3)
		s += "SSSE3, ";
	if(SSE41)
		s += "SSE41, ";
	if(SSE42)
		s += "SSE42, ";
	if(SSE4a)
		s += "SSE4a, ";
	if(AVX)
		s += "AVX, ";
	if(XOP)
		s += "XOP, ";
	if(FMA3)
		s += "FMA3, ";
	if(FMA4)
		s += "FMA4, ";

	if(s.at_back(1) == ',')
		s.pop(2);
	else
		s += "(none)";

	Info(s);
}
示例#8
0
文件: Main.cpp 项目: lcs2/carpg
//=================================================================================================
// G³ówna funkcja programu
//=================================================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	ErrorHandler& error_handler = ErrorHandler::Get();
	error_handler.RegisterHandler();

	GetCompileTime();

	// logger (w tym przypadku prelogger bo jeszcze nie wiemy gdzie to zapisywaæ)
	PreLogger plog;
	Logger::global = &plog;

	// stwórz foldery na zapisy
	CreateDirectory("saves", nullptr);
	CreateDirectory("saves/single", nullptr);
	CreateDirectory("saves/multi", nullptr);

	//-------------------------------------------------------------------------
	// pocz¹tek
	time_t t = time(0);
	tm t2;
	localtime_s(&t2, &t);
	Info("CaRpg " VERSION_STR);
	Info("Date: %04d-%02d-%02d", t2.tm_year + 1900, t2.tm_mon + 1, t2.tm_mday);
	Info("Build date: %s", g_ctime.c_str());
	Info("Process ID: %d", GetCurrentProcessId());
	{
		cstring build_type =
#ifdef _DEBUG
			"debug ";
#else
			"release ";
#endif
		Info("Build type: %s", build_type);
	}
	LogProcessorFeatures();

	Game game;
	Engine::StartupOptions options;
	Bool3 windowed = None,
		console = None;
	game.cfg_file = "carpg.cfg";
	bool log_to_file;
	string log_filename;

	//-------------------------------------------------------------------------
	// parsuj linie komend
	int cmd_len = strlen(lpCmdLine) + 1;
	char* cmd_line = new char[cmd_len];
	memcpy(cmd_line, lpCmdLine, cmd_len);
	char** argv;
	Info("Parsing command line.");
	int argc = ParseCmdLine(cmd_line, &argv);
	bool restarted = false;

	for(int i = 0; i < argc; ++i)
	{
		char c = argv[i][0];
		if(c != '-' && c != '+')
		{
			Warn("Unknown command line parameter '%s'.", argv[i]);
			continue;
		}

		cstring arg = argv[i] + 1;
		if(c == '+')
			game.ParseConfigVar(arg);
		else
		{
			if(strcmp(arg, "config") == 0)
			{
				if(argc != i + 1 && argv[i + 1][0] != '-')
				{
					++i;
					game.cfg_file = argv[i];
					Info("Configuration file: %s", game.cfg_file.c_str());
				}
				else
					Warn("No argument for parameter '-config'!");
			}
			else if(strcmp(arg, "single") == 0)
				game.quickstart = QUICKSTART_SINGLE;
			else if(strcmp(arg, "host") == 0)
				game.quickstart = QUICKSTART_HOST;
			else if(strcmp(arg, "join") == 0)
				game.quickstart = QUICKSTART_JOIN_LAN;
			else if(strcmp(arg, "joinip") == 0)
				game.quickstart = QUICKSTART_JOIN_IP;
			else if(strcmp(arg, "console") == 0)
				console = True;
			else if(strcmp(arg, "windowed") == 0)
				windowed = True;
			else if(strcmp(arg, "fullscreen") == 0)
				windowed = False;
			else if(strcmp(arg, "nosound") == 0)
				game.nosound = true;
			else if(strcmp(arg, "nomusic") == 0)
				game.nomusic = true;
			else if(strcmp(arg, "test") == 0)
			{
				game.testing = true;
				console = True;
			}
			else if(strcmp(arg, "delay-1") == 0)
				utility::InitDelayLock();
			else if(strcmp(arg, "delay-2") == 0)
				utility::WaitForDelayLock(2);
			else if(strcmp(arg, "delay-3") == 0)
				utility::WaitForDelayLock(3);
			else if(strcmp(arg, "delay-4") == 0)
				utility::WaitForDelayLock(4);
			else if(strcmp(arg, "restart") == 0)
			{
				if(!restarted)
				{
					// try to open mutex
					Info("Game restarted.");
					HANDLE mutex = OpenMutex(SYNCHRONIZE, FALSE, RESTART_MUTEX_NAME);
					if(mutex)
					{
						// wait for previous application to close
						WaitForSingleObject(mutex, INFINITE);
						CloseHandle(mutex);
					}
					restarted = true;
				}
			}
			else
				Warn("Unknown switch '%s'.", arg);
		}
	}

	LoadSystemDir();

	//-------------------------------------------------------------------------
	// wczytaj plik konfiguracyjny
	Info("Loading config file");
	Config& cfg = Game::Get().cfg;
	Config::Result result = cfg.Load(game.cfg_file.c_str());
	if(result == Config::NO_FILE)
		Info("Config file not found '%s'.", game.cfg_file.c_str());
	else if(result == Config::PARSE_ERROR)
		Error("Config file parse error '%s' : %s", game.cfg_file.c_str(), cfg.GetError().c_str());

	error_handler.ReadConfiguration(cfg);

	// konsola
	if(console == None)
		console = cfg.GetBool3("console", False);
	if(console == True)
	{
		game.have_console = true;

		// konsola
		AllocConsole();
		freopen("CONIN$", "r", stdin);
		freopen("CONOUT$", "w", stdout);
		freopen("CONOUT$", "w", stderr);

		// polskie znaki w konsoli, tymczasowe rozwi¹zanie
		SetConsoleCP(1250);
		SetConsoleOutputCP(1250);
	}

	setlocale(LC_COLLATE, "");
	setlocale(LC_CTYPE, "");

	// tryb okienkowy
	if(windowed == None)
	{
		Bool3 b = cfg.GetBool3("fullscreen", True);
		if(b == True)
			windowed = False;
		else
			windowed = True;
	}
	options.fullscreen = (windowed == False);

	// rozdzielczoϾ
	const string& res = cfg.GetString("resolution", "0x0");
	if(sscanf_s(res.c_str(), "%dx%d", &options.size.x, &options.size.y) != 2)
	{
		Warn("Settings: Invalid resolution value '%s'.", res.c_str());
		options.size = Int2::Zero;
	}
	else
		Info("Settings: Resolution %dx%d.", options.size.x, options.size.y);

	// refresh
	game.wnd_hz = cfg.GetInt("refresh", 0);
	Info("Settings: Refresh rate %d Hz.", game.wnd_hz);

	// adapter
	game.used_adapter = cfg.GetInt("adapter", 0);
	Info("Settings: Adapter %d.", game.used_adapter);

	// logowanie
	log_to_file = (cfg.GetBool3("log", True) == True);

	// plik logowania
	if(log_to_file)
		log_filename = cfg.GetString("log_filename", "log.txt");

	game.hardcore_option = ToBool(cfg.GetBool3("hardcore_mode", False));

	// nie zatrzymywanie gry w razie braku aktywnoœci okna
	if(cfg.GetBool3("inactive_update", False) == True)
		game.inactive_update = true;

	// dŸwiêk / muzyka
	bool play_sound = true, play_music = true;
	if(cfg.GetBool3("play_sound", True) == False)
	{
		cfg.Remove("play_sound");
		play_sound = false;
	}
	if(cfg.GetBool3("play_music", True) == False)
	{
		cfg.Remove("play_music");
		play_music = false;
	}
	if(game.nosound || cfg.GetBool3("nosound", False) == True)
	{
		game.nosound = true;
		Info("Settings: no sound.");
	}
	if(game.nomusic || cfg.GetBool3("nomusic", False) == True)
	{
		game.nomusic = true;
		Info("Settings: no music.");
	}
	if(game.nomusic && game.nosound)
		game.disabled_sound = true;
	game.sound_volume = Clamp(cfg.GetInt("sound_volume", 100), 0, 100);
	game.music_volume = Clamp(cfg.GetInt("music_volume", 100), 0, 100);
	if(!play_sound)
	{
		game.sound_volume = 0;
		cfg.Add("sound_volume", "0");
	}
	if(!play_music)
	{
		game.music_volume = 0;
		cfg.Add("music_volume", "0");
	}

	// ustawienia myszki
	game.mouse_sensitivity = Clamp(cfg.GetInt("mouse_sensitivity", 50), 0, 100);
	game.mouse_sensitivity_f = Lerp(0.5f, 1.5f, float(game.mouse_sensitivity) / 100);

	// tryb multiplayer
	game.player_name = cfg.GetString("nick", "");
#define LIMIT(x) if(x.length() > 16) x = x.substr(0,16)
	LIMIT(game.player_name);
	game.server_name = cfg.GetString("server_name", "");
	LIMIT(game.server_name);
	game.server_pswd = cfg.GetString("server_pswd", "");
	LIMIT(game.server_pswd);
	game.max_players = Clamp(cfg.GetInt("server_players", DEFAULT_PLAYERS), MIN_PLAYERS, MAX_PLAYERS);
	game.server_ip = cfg.GetString("server_ip", "");
	game.mp_timeout = Clamp(cfg.GetFloat("timeout", 10.f), 1.f, 3600.f);

	// szybki start
	if(game.quickstart == QUICKSTART_NONE)
	{
		const string& mode = cfg.GetString("quickstart", "");
		if(mode == "single")
			game.quickstart = QUICKSTART_SINGLE;
		else if(mode == "host")
			game.quickstart = QUICKSTART_HOST;
		else if(mode == "join")
			game.quickstart = QUICKSTART_JOIN_LAN;
		else if(mode == "joinip")
			game.quickstart = QUICKSTART_JOIN_IP;
	}

	// autopicked class in MP
	{
		const string& clas = cfg.GetString("autopick", "");
		if(!clas.empty())
		{
			if(clas == "random")
				game.autopick_class = Class::RANDOM;
			else
			{
				ClassInfo* ci = ClassInfo::Find(clas);
				if(ci)
				{
					if(ClassInfo::IsPickable(ci->class_id))
						game.autopick_class = ci->class_id;
					else
						Warn("Settings [autopick]: Class '%s' is not pickable by players.", clas.c_str());
				}
				else
					Warn("Settings [autopick]: Invalid class '%s'.", clas.c_str());
			}
		}
	}

	// autostart serwera
	game.autostart_count = cfg.GetInt("autostart");
	if(game.autostart_count < -1)
		game.autostart_count = -1;
	else if(game.autostart_count > MAX_PLAYERS || game.autostart_count == 0)
		game.autostart_count = -1;

	//game.kick_timer = max(0, cfg.GetInt("kick_timer", 900));
	game.mp_port = Clamp(cfg.GetInt("port", PORT), 0, 0xFFFF);

	// autopicked class in quickstart
	{
		const string& clas = cfg.GetString("class", "");
		if(!clas.empty())
		{
			ClassInfo* ci = ClassInfo::Find(clas);
			if(ci)
			{
				if(ClassInfo::IsPickable(ci->class_id))
					game.quickstart_class = ci->class_id;
				else
					Warn("Settings [class]: Class '%s' is not pickable by players.", clas.c_str());
			}
			else
				Warn("Settings [class]: Invalid class '%s'.", clas.c_str());
		}
	}

	game.quickstart_name = cfg.GetString("name", "Test");
	if(game.quickstart_name.empty())
		game.quickstart_name = "Test";

	game.change_title_a = ToBool(cfg.GetBool3("change_title", False));

	// pozycja rozmiar okien
	int con_pos_x = cfg.GetInt("con_pos_x"),
		con_pos_y = cfg.GetInt("con_pos_y");

	if(game.have_console && (con_pos_x != -1 || con_pos_y != -1))
	{
		HWND con = GetConsoleWindow();
		Rect rect;
		GetWindowRect(con, (RECT*)&rect);
		if(con_pos_x != -1)
			rect.Left() = con_pos_x;
		if(con_pos_y != -1)
			rect.Top() = con_pos_y;
		SetWindowPos(con, 0, rect.Left(), rect.Top(), 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
	}

	options.force_size.x = cfg.GetInt("wnd_size_x");
	options.force_size.y = cfg.GetInt("wnd_size_y");
	options.force_pos.x = cfg.GetInt("wnd_pos_x");
	options.force_pos.y = cfg.GetInt("wnd_pos_y");

	// multisampling
	int multisampling = cfg.GetInt("multisampling", 0),
		multisampling_quality = cfg.GetInt("multisampling_quality", 0);
	game.SetStartingMultisampling(multisampling, multisampling_quality);

	// inne
	game.cl_postfx = cfg.GetBool("cl_postfx", true);
	game.cl_normalmap = cfg.GetBool("cl_normalmap", true);
	game.cl_specularmap = cfg.GetBool("cl_specularmap", true);
	game.cl_glow = cfg.GetBool("cl_glow", true);
	game.shader_version = cfg.GetInt("cl_shader_version");
	if(game.shader_version != -1 && game.shader_version != 2 && game.shader_version != 3)
	{
		Warn("Settings: Unknown shader version %d.", game.shader_version);
		game.shader_version = -1;
	}
	options.vsync = cfg.GetBool("vsync", true);
	game.grass_range = cfg.GetFloat("grass_range", 40.f);
	if(game.grass_range < 0.f)
		game.grass_range = 0.f;
	{
		const string& screenshot_format = cfg.GetString("screenshot_format", "jpg");
		if(screenshot_format == "jpg")
			game.screenshot_format = D3DXIFF_JPG;
		else if(screenshot_format == "bmp")
			game.screenshot_format = D3DXIFF_BMP;
		else if(screenshot_format == "tga")
			game.screenshot_format = D3DXIFF_TGA;
		else if(screenshot_format == "png")
			game.screenshot_format = D3DXIFF_PNG;
		else
		{
			Warn("Settings: Unknown screenshot format '%s'. Defaulting to jpg.", screenshot_format.c_str());
			game.screenshot_format = D3DXIFF_JPG;
		}
	}

	game.disable_net_stats = cfg.GetBool("disable_net_stats");

	game.SetConfigVarsFromFile();
	game.ApplyConfigVars();

	//-------------------------------------------------------------------------
	// logger
	int ile = 0;
	if(game.have_console)
		++ile;
	if(log_to_file)
		++ile;

	if(ile == 2)
	{
		MultiLogger* multi = new MultiLogger;
		ConsoleLogger* clog = new ConsoleLogger;
		TextLogger* tlog = new TextLogger(log_filename.c_str());
		multi->loggers.push_back(clog);
		multi->loggers.push_back(tlog);
		plog.Apply(multi);
		Logger::global = multi;
	}
	else if(ile == 1)
	{
		if(game.have_console)
		{
			ConsoleLogger* l = new ConsoleLogger;
			plog.Apply(l);
			Logger::global = l;
		}
		else
		{
			TextLogger* l = new TextLogger(log_filename.c_str());
			plog.Apply(l);
			Logger::global = l;
		}
	}
	else
	{
		Logger* l = new Logger;
		plog.Clear();
		Logger::global = l;
	}

	//-------------------------------------------------------------------------
	// skrypty instalacyjne
	if(!RunInstallScripts())
	{
		MessageBox(nullptr, "Failed to run installation scripts. Check log for details.", nullptr, MB_OK | MB_ICONERROR | MB_TASKMODAL);
		return 3;
	}

	//-------------------------------------------------------------------------
	// jêzyk
	LoadLanguages();
	const string& lang = cfg.GetString("language", "");
	extern string g_lang_prefix;
	if(lang == "")
	{
		LocalString s;
		if(!ShowPickLanguageDialog(s.get_ref()))
		{
			ClearLanguages();
			delete[] cmd_line;
			delete[] argv;
			delete Logger::global;
			return 2;
		}
		else
		{
			g_lang_prefix = s;
			cfg.Add("language", s->c_str());
		}
	}
	else
		g_lang_prefix = lang;

	//-------------------------------------------------------------------------
	// pseudolosowoϾ
	uint cfg_seed = cfg.GetUint("seed"), seed;
	if(cfg_seed == 0)
		seed = (uint)time(nullptr);
	else
	{
		seed = cfg_seed;
		game.force_seed = seed;
	}
	game.next_seed = cfg.GetUint("next_seed");
	game.force_seed_all = ToBool(cfg.GetBool3("force_seed", False));
	Info("random seed: %u/%u/%d", seed, game.next_seed, (game.force_seed_all ? 1 : 0));
	Srand(seed);

	// inne
	game.check_updates = ToBool(cfg.GetBool3("check_updates", True));
	game.skip_tutorial = ToBool(cfg.GetBool3("skip_tutorial", False));

	// zapisz konfiguracjê
	game.SaveCfg();

	//-------------------------------------------------------------------------
	// rozpocznij grê
	Info("Starting game engine.");
	bool b = game.Start0(options);

	//-------------------------------------------------------------------------
	// sprz¹tanie
	delete[] cmd_line;
	delete[] argv;
	delete Logger::global;

	return (b ? 0 : 1);
}