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(); } }
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()); }
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()); }
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()); }
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; }
//================================================================================================= 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(); }
//================================================================================================= 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); }
//================================================================================================= // 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); }