X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fworld.qc;h=47d2dfaa78d98c309cf5d28507bd477cd2dd5b59;hp=bffb7dbd59f40d30cb682dcbd811ac543a709646;hb=2d9196051973e38c3407c8e78bf6aed6284c115a;hpb=646aba8e9f308418d64eb1ef9953d8bbc98606d7 diff --git a/qcsrc/server/world.qc b/qcsrc/server/world.qc index bffb7dbd59..47d2dfaa78 100644 --- a/qcsrc/server/world.qc +++ b/qcsrc/server/world.qc @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -46,7 +45,6 @@ #include #include #include -#include #include const float LATENCY_THINKRATE = 10; @@ -69,7 +67,7 @@ void PingPLReport_Think(entity this) { WriteHeader(MSG_BROADCAST, TE_CSQC_PINGPLREPORT); WriteByte(MSG_BROADCAST, this.cnt); - WriteShort(MSG_BROADCAST, bound(1, CS(e).ping, 32767)); + WriteShort(MSG_BROADCAST, bound(1, rint(CS(e).ping), 32767)); WriteByte(MSG_BROADCAST, min(ceil(CS(e).ping_packetloss * 255), 255)); WriteByte(MSG_BROADCAST, min(ceil(CS(e).ping_movementloss * 255), 255)); @@ -353,6 +351,7 @@ void cvar_changes_init() BADCVAR("g_ctf_flag_glowtrails"); BADCVAR("g_ctf_dynamiclights"); BADCVAR("g_ctf_flag_pickup_verbosename"); + BADCVAR("g_ctf_flagcarrier_auto_helpme_damage"); BADPRESUFFIX("g_ctf_flag_", "_model"); BADPRESUFFIX("g_ctf_flag_", "_skin"); BADCVAR("g_domination_point_leadlimit"); @@ -388,6 +387,7 @@ void cvar_changes_init() BADCVAR("sv_minigames"); BADCVAR("sv_namechangetimer"); BADCVAR("sv_precacheplayermodels"); + BADCVAR("sv_qcphysics"); BADCVAR("sv_radio"); BADCVAR("sv_stepheight"); BADCVAR("sv_timeout"); @@ -408,12 +408,13 @@ void cvar_changes_init() BADPREFIX("skill_"); BADPREFIX("sv_allow_"); BADPREFIX("sv_cullentities_"); - BADPREFIX("sv_maxidle_"); + BADPREFIX("sv_maxidle"); BADPREFIX("sv_minigames_"); BADPREFIX("sv_radio_"); BADPREFIX("sv_timeout_"); BADPREFIX("sv_vote_"); BADPREFIX("timelimit_"); + BADPRESUFFIX("g_", "_round_timelimit"); // allowed changes to server admins (please sync this to server.cfg) // vi commands: @@ -443,6 +444,7 @@ void cvar_changes_init() BADCVAR("g_ctf_leaderboard"); BADCVAR("g_domination_point_limit"); BADCVAR("g_domination_teams_override"); + BADCVAR("g_freezetag_revive_spawnshield"); BADCVAR("g_freezetag_teams_override"); BADCVAR("g_friendlyfire"); BADCVAR("g_fullbrightitems"); @@ -458,10 +460,11 @@ void cvar_changes_init() BADCVAR("g_physics_clientselect"); BADCVAR("g_pinata"); BADCVAR("g_powerups"); + BADCVAR("g_powerups_drop_ondeath"); BADCVAR("g_player_brightness"); BADCVAR("g_rocket_flying"); BADCVAR("g_rocket_flying_disabledelays"); - BADCVAR("g_spawnshieldtime"); + BADPREFIX("g_spawnshield"); BADCVAR("g_start_delay"); BADCVAR("g_superspectate"); BADCVAR("g_tdm_teams_override"); @@ -487,12 +490,11 @@ void cvar_changes_init() BADCVAR("sv_defaultplayercolors"); BADCVAR("sv_defaultplayermodel"); BADCVAR("sv_defaultplayerskin"); - BADCVAR("sv_maxidle"); BADCVAR("sv_maxrate"); BADCVAR("sv_motd"); BADCVAR("sv_public"); - BADCVAR("sv_ready_restart"); BADCVAR("sv_showfps"); + BADCVAR("sv_showspectators"); BADCVAR("sv_status_privacy"); BADCVAR("sv_taunt"); BADCVAR("sv_vote_call"); @@ -687,6 +689,15 @@ spawnfunc(worldspawn) { server_is_dedicated = boolean(stof(cvar_defstring("is_dedicated"))); + if (autocvar_sv_termsofservice_url && autocvar_sv_termsofservice_url != "") + { + strcpy(sv_termsofservice_url_escaped, strreplace(":", "|", autocvar_sv_termsofservice_url)); + } + else + { + strcpy(sv_termsofservice_url_escaped, "INVALID"); + } + bool wantrestart = false; { if (!server_is_dedicated) @@ -809,11 +820,11 @@ spawnfunc(worldspawn) if(autocvar_g_campaign) CampaignPreInit(); + else + PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode Map_MarkAsRecent(mapname); - PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode - InitGameplayMode(); static_init_late(); static_init_precache(); @@ -832,51 +843,15 @@ spawnfunc(worldspawn) WaypointSprite_Init(); - GameLogInit(); // prepare everything // NOTE for matchid: // changing the logic generating it is okay. But: // it HAS to stay <= 64 chars // character set: ASCII 33-126 without the following characters: : ; ' " \ $ - if(autocvar_sv_eventlog) - { - string s = sprintf("%s.%s.%06d", itos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000)); - matchid = strzone(s); + // strftime(false, "%s") isn't reliable, see strftime_s description + matchid = strzone(sprintf("%d.%s.%06d", autocvar_sv_eventlog_files_counter, strftime_s(), random() * 1000000)); - GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s)); - s = ":gameinfo:mutators:LIST"; - - MUTATOR_CALLHOOK(BuildMutatorsString, s); - s = M_ARGV(0, string); - - // initialiation stuff, not good in the mutator system - if(!autocvar_g_use_ammunition) - s = strcat(s, ":no_use_ammunition"); - - // initialiation stuff, not good in the mutator system - if(autocvar_g_pickup_items == 0) - s = strcat(s, ":no_pickup_items"); - if(autocvar_g_pickup_items > 0) - s = strcat(s, ":pickup_items"); - - // initialiation stuff, not good in the mutator system - if(autocvar_g_weaponarena != "0") - s = strcat(s, ":", autocvar_g_weaponarena, " arena"); - - // TODO to mutator system - if(autocvar_g_norecoil) - s = strcat(s, ":norecoil"); - - // TODO to mutator system - if(autocvar_g_powerups == 0) - s = strcat(s, ":no_powerups"); - if(autocvar_g_powerups > 0) - s = strcat(s, ":powerups"); - - GameLogEcho(s); - GameLogEcho(":gameinfo:end"); - } - else - matchid = strzone(ftos(random())); + if(autocvar_sv_eventlog) + GameLogInit(); // requires matchid to be set cvar_set("nextmap", ""); @@ -890,11 +865,8 @@ spawnfunc(worldspawn) MapInfo_Enumerate(); MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1); - if(fexists(strcat("scripts/", mapname, ".arena"))) - cvar_settemp("sv_q3acompat_machineshotgunswap", "1"); - - if(fexists(strcat("scripts/", mapname, ".defi"))) - cvar_settemp("sv_q3defragcompat", "1"); + q3compat = BITSET(q3compat, Q3COMPAT_ARENA, fexists(strcat("scripts/", mapname, ".arena"))); + q3compat = BITSET(q3compat, Q3COMPAT_DEFI, fexists(strcat("scripts/", mapname, ".defi"))); if(whichpack(strcat("maps/", mapname, ".cfg")) != "") { @@ -1219,7 +1191,7 @@ void DumpStats(float final) FOREACH_CLIENT(IS_REAL_CLIENT(it) || (IS_BOT_CLIENT(it) && autocvar_sv_logscores_bots), { s = strcat(":player:see-labels:", GetPlayerScoreString(it, 0), ":"); s = strcat(s, ftos(rint(time - CS(it).jointime)), ":"); - if(IS_PLAYER(it) || MUTATOR_CALLHOOK(GetPlayerStatus, it)) + if(IS_PLAYER(it) || INGAME_JOINED(it)) s = strcat(s, ftos(it.team), ":"); else s = strcat(s, "spectator:"); @@ -1272,6 +1244,7 @@ only called if a time or frag limit has expired */ void NextLevel() { + cvar_set("_endmatch", "0"); game_stopped = true; intermission_running = true; // game over @@ -1305,10 +1278,18 @@ void NextLevel() GameLogClose(); - FOREACH_CLIENT(IS_PLAYER(it), { + int winner_team = 0; + FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), { FixIntermissionClient(it); if(it.winning) - bprint(playername(it.netname, it.team, false), " ^7wins.\n"); + { + if (teamplay && !winner_team) + { + winner_team = it.team; + bprint(Team_ColorCode(winner_team), Team_ColorName_Upper(winner_team), "^7 team wins the match\n"); + } + bprint(playername(it.netname, it.team, false), " ^7wins\n"); + } }); target_music_kill(); @@ -1322,7 +1303,7 @@ void NextLevel() } -float InitiateSuddenDeath() +int InitiateSuddenDeath() { // Check first whether normal overtimes could be added before initiating suddendeath mode // - for this timelimit_overtime needs to be >0 of course @@ -1339,9 +1320,14 @@ float InitiateSuddenDeath() if(!checkrules_suddendeathend) { if(autocvar_g_campaign) + { checkrules_suddendeathend = time; // no suddendeath in campaign + } else + { checkrules_suddendeathend = time + 60 * autocvar_timelimit_suddendeath; + overtimes = -1; + } if(g_race && !g_race_qualifying) race_StartCompleting(); } @@ -1352,6 +1338,7 @@ float InitiateSuddenDeath() void InitiateOvertime() // ONLY call this if InitiateSuddenDeath returned true { ++checkrules_overtimesadded; + overtimes = checkrules_overtimesadded; //add one more overtime by simply extending the timelimit cvar_set("timelimit", ftos(autocvar_timelimit + autocvar_timelimit_overtime)); Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime * 60); @@ -1388,13 +1375,13 @@ float GetWinningCode(float fraglimitreached, float equality) // set the .winning flag for exactly those players with a given field value void SetWinners(.float field, float value) { - FOREACH_CLIENT(IS_PLAYER(it), { it.winning = (it.(field) == value); }); + FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), { it.winning = (it.(field) == value); }); } // set the .winning flag for those players with a given field value void AddWinners(.float field, float value) { - FOREACH_CLIENT(IS_PLAYER(it), { + FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), { if(it.(field) == value) it.winning = 1; }); @@ -1403,7 +1390,7 @@ void AddWinners(.float field, float value) // clear the .winning flags void ClearWinners() { - FOREACH_CLIENT(IS_PLAYER(it), { it.winning = 0; }); + FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), { it.winning = 0; }); } int fragsleft_last; @@ -1602,19 +1589,18 @@ void CheckRules_World() leadlimit = 0; // no leadlimit for now } - if(timelimit > 0) - { - timelimit += game_starttime; - } - else if (timelimit < 0) + if (autocvar__endmatch || timelimit < 0) { // endmatch NextLevel(); return; } - float wantovertime; - wantovertime = 0; + if(timelimit > 0) + timelimit += game_starttime; + + int overtimes_prev = overtimes; + int wantovertime = 0; if(checkrules_suddendeathend) { @@ -1650,7 +1636,7 @@ void CheckRules_World() if(readyplayers || playerswithlaps >= 2) { checkrules_suddendeathend = 0; - ReadyRestart(); // go to race + ReadyRestart(true); // go to race return; } else @@ -1700,6 +1686,12 @@ void CheckRules_World() if(checkrules_status == WINNING_YES) { + if (overtimes == -1 && overtimes != overtimes_prev) + { + // if suddendeathend overtime has just begun, revert it + checkrules_suddendeathend = 0; + overtimes = overtimes_prev; + } //print("WINNING\n"); NextLevel(); } @@ -1861,25 +1853,25 @@ void readplayerstartcvars() else if (s == "all" || s == "1") { g_weaponarena = 1; - g_weaponarena_list = "All Weapons"; + g_weaponarena_list = "All Weapons Arena"; g_weaponarena_weapons = weapons_all(); } else if (s == "devall") { g_weaponarena = 1; - g_weaponarena_list = "Dev All Weapons"; + g_weaponarena_list = "Dev All Weapons Arena"; g_weaponarena_weapons = weapons_devall(); } else if (s == "most") { g_weaponarena = 1; - g_weaponarena_list = "Most Weapons"; + g_weaponarena_list = "Most Weapons Arena"; g_weaponarena_weapons = weapons_most(); } else if (s == "all_available") { g_weaponarena = 1; - g_weaponarena_list = "All Available Weapons"; + g_weaponarena_list = "All Available Weapons Arena"; // this needs to run after weaponsInMapAll is initialized InitializeEntity(NULL, weaponarena_available_all_update, INITPRIO_FINDTARGET); @@ -1887,7 +1879,7 @@ void readplayerstartcvars() else if (s == "devall_available") { g_weaponarena = 1; - g_weaponarena_list = "Dev All Available Weapons"; + g_weaponarena_list = "Dev All Available Weapons Arena"; // this needs to run after weaponsInMapAll is initialized InitializeEntity(NULL, weaponarena_available_devall_update, INITPRIO_FINDTARGET); @@ -1895,7 +1887,7 @@ void readplayerstartcvars() else if (s == "most_available") { g_weaponarena = 1; - g_weaponarena_list = "Most Available Weapons"; + g_weaponarena_list = "Most Available Weapons Arena"; // this needs to run after weaponsInMapAll is initialized InitializeEntity(NULL, weaponarena_available_most_update, INITPRIO_FINDTARGET); @@ -1903,7 +1895,7 @@ void readplayerstartcvars() else if (s == "none") { g_weaponarena = 1; - g_weaponarena_list = "No Weapons"; + g_weaponarena_list = "No Weapons Arena"; } else { @@ -1917,10 +1909,13 @@ void readplayerstartcvars() if(wep != WEP_Null) { g_weaponarena_weapons |= (wep.m_wepset); - g_weaponarena_list = strcat(g_weaponarena_list, wep.m_name, " & "); + g_weaponarena_list = strcat(g_weaponarena_list, wep.netname, " & "); } } - g_weaponarena_list = strzone(substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3)); + if (g_weaponarena_list != "") // remove trailing " & " + g_weaponarena_list = substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3); + else // no valid weapon found + g_weaponarena_list = "No Weapons Arena"; } if (g_weaponarena) @@ -1928,6 +1923,7 @@ void readplayerstartcvars() g_weapon_stay = 0; // incompatible start_weapons = g_weaponarena_weapons; start_items |= IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS; + g_weaponarena_list = strzone(g_weaponarena_list); } else { @@ -2118,7 +2114,7 @@ void readlevelcvars() MUTATOR_CALLHOOK(ReadLevelCvars); - if (!warmup_stage) + if (!warmup_stage && !autocvar_g_campaign) game_starttime = time + cvar("g_start_delay"); FOREACH(Weapons, it != WEP_Null, { it.wr_init(it); }); @@ -2210,11 +2206,11 @@ void droptofloor(entity this) } bool autocvar_sv_gameplayfix_multiplethinksperframe = true; -void RunThink(entity this) +void RunThink(entity this, float dt) { // don't let things stay in the past. // it is possible to start that way by a trigger with a local time. - if(this.nextthink <= 0 || this.nextthink > time + frametime) + if(this.nextthink <= 0 || this.nextthink > time + dt) return; float oldtime = time; // do we need to save this? @@ -2230,7 +2226,7 @@ void RunThink(entity this) // we don't want to loop in that case, so exit if the new nextthink is // <= the time the qc was told, also exit if it is past the end of the // frame - if(this.nextthink <= time || this.nextthink > oldtime + frametime || !autocvar_sv_gameplayfix_multiplethinksperframe) + if(this.nextthink <= time || this.nextthink > oldtime + dt || !autocvar_sv_gameplayfix_multiplethinksperframe) break; } @@ -2260,8 +2256,8 @@ void Physics_Frame() if(it.move_movetype == MOVETYPE_PUSH || it.move_movetype == MOVETYPE_FAKEPUSH) continue; // these movetypes have no regular think function // handle thinking here - if (getthink(it) && it.nextthink > 0 && it.nextthink <= time + frametime) - RunThink(it); + if (getthink(it) && it.nextthink > 0 && it.nextthink <= time + PHYS_INPUT_TIMELENGTH) + RunThink(it, PHYS_INPUT_TIMELENGTH); } }); @@ -2292,9 +2288,10 @@ void EndFrame() STAT(TYPEHIT_TIME, it) = time; } else if (e.killsound) { STAT(KILL_TIME, it) = time; - } else if (e.damage_dealt) { + } else if (e.hitsound_damage_dealt) { STAT(HIT_TIME, it) = time; - STAT(DAMAGE_DEALT_TOTAL, it) += ceil(e.damage_dealt); + // NOTE: this is not accurate as client code doesn't need so much accuracy for its purposes + STAT(HITSOUND_DAMAGE_DEALT_TOTAL, it) += ceil(e.hitsound_damage_dealt); } }); // add 1 frametime because after this, engine SV_Physics @@ -2305,7 +2302,7 @@ void EndFrame() float altime = time + frametime * (1 + autocvar_g_antilag_nudge); FOREACH_CLIENT(true, { it.typehitsound = false; - it.damage_dealt = 0; + it.hitsound_damage_dealt = 0; it.killsound = false; antilag_record(it, CS(it), altime); }); @@ -2427,6 +2424,8 @@ void Shutdown() WeaponStats_Shutdown(); MapInfo_Shutdown(); + + strfree(sv_termsofservice_url_escaped); } else if(world_initialized == 0) {