X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fworld.qc;h=bffb7dbd59f40d30cb682dcbd811ac543a709646;hb=646aba8e9f308418d64eb1ef9953d8bbc98606d7;hp=4c51fe0647dff64802ec8d36a113cdfdb6d04888;hpb=4a69d131ab8541aaea1dac0b2129886d9d9f3827;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/world.qc b/qcsrc/server/world.qc index 4c51fe064..bffb7dbd5 100644 --- a/qcsrc/server/world.qc +++ b/qcsrc/server/world.qc @@ -1,51 +1,53 @@ #include "world.qh" -#include "anticheat.qh" -#include "antilag.qh" -#include "bot/api.qh" -#include "campaign.qh" -#include "cheats.qh" -#include "client.qh" -#include "command/common.qh" -#include "command/getreplies.qh" -#include "command/sv_cmd.qh" -#include "command/vote.qh" -#include "hook.qh" -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include "ipban.qh" +#include +#include #include +#include +#include #include -#include "mapvoting.qh" +#include #include -#include "race.qh" -#include "scores.qh" -#include "scores_rules.qh" -#include "spawnpoints.qh" -#include "teamplay.qh" -#include "weapons/weaponstats.qh" +#include +#include +#include +#include +#include #include -#include "../common/constants.qh" -#include -#include "../common/deathtypes/all.qh" -#include -#include "../common/gamemodes/sv_rules.qh" -#include "../common/mapinfo.qh" -#include "../common/monsters/_mod.qh" -#include "../common/monsters/sv_monsters.qh" -#include "../common/vehicles/all.qh" -#include "../common/notifications/all.qh" -#include "../common/physics/player.qh" -#include "../common/playerstats.qh" -#include "../common/stats.qh" -#include "../common/teams.qh" -#include -#include "../common/mapobjects/trigger/secret.qh" -#include "../common/mapobjects/target/music.qh" -#include "../common/util.qh" -#include "../common/items/_mod.qh" -#include -#include "../common/state.qh" +#include const float LATENCY_THINKRATE = 10; .float latency_sum; @@ -67,7 +69,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, 65535)); + WriteShort(MSG_BROADCAST, bound(1, 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)); @@ -98,7 +100,6 @@ void PingPLReport_Spawn() } const float SPAWNFLAG_NO_WAYPOINTS_FOR_ITEMS = 1; -float world_initialized; void SetDefaultAlpha() { @@ -169,6 +170,7 @@ void cvar_changes_init() #define BADPREFIX(p) if(substring(k, 0, strlen(p)) == p) continue #define BADPRESUFFIX(p,s) if(substring(k, 0, strlen(p)) == p && substring(k, -strlen(s), -1) == s) continue #define BADCVAR(p) if(k == p) continue +#define BADVALUE(p, val) if (k == p && v == val) continue // general excludes and namespaces for server admin used cvars BADPREFIX("help_"); // PN's server has this listed as changed, let's not rat him out for THAT @@ -346,6 +348,7 @@ void cvar_changes_init() BADCVAR("g_chatsounds"); BADCVAR("g_ca_point_leadlimit"); BADCVAR("g_ca_point_limit"); + BADCVAR("g_ca_spectate_enemies"); BADCVAR("g_ctf_captimerecord_always"); BADCVAR("g_ctf_flag_glowtrails"); BADCVAR("g_ctf_dynamiclights"); @@ -489,6 +492,7 @@ void cvar_changes_init() BADCVAR("sv_motd"); BADCVAR("sv_public"); BADCVAR("sv_ready_restart"); + BADCVAR("sv_showfps"); BADCVAR("sv_status_privacy"); BADCVAR("sv_taunt"); BADCVAR("sv_vote_call"); @@ -498,6 +502,8 @@ void cvar_changes_init() BADCVAR("sv_vote_master_commands"); BADCVAR("sv_vote_master_password"); BADCVAR("sv_vote_simple_majority_factor"); + BADVALUE("sys_ticrate", "0.0166667"); + BADVALUE("sys_ticrate", "0.0333333"); BADCVAR("teamplay_mode"); BADCVAR("timelimit_override"); BADPREFIX("g_warmup_"); @@ -518,15 +524,10 @@ void cvar_changes_init() BADCVAR("g_lms_weaponarena"); BADCVAR("g_ctf_stalemate_time"); - if(cvar_string("g_mod_balance") == "Testing") - { - // (temporary) while using the Testing balance, any weapon balance cvars are allowed to be changed - BADPREFIX("g_balance_"); - } - #undef BADPRESUFFIX #undef BADPREFIX #undef BADCVAR +#undef BADVALUE if(pureadding) { @@ -589,7 +590,7 @@ spawnfunc(__init_dedicated_server) delete_fn = remove_unsafely; - entity e = spawn(); + entity e = new(GotoFirstMap); setthink(e, GotoFirstMap); e.nextthink = time; // this is usually 1 at this point @@ -755,6 +756,9 @@ spawnfunc(worldspawn) cvar_changes_init(); // do this very early now so it REALLY matches the server config + // default to RACE_RECORD, can be overwritten by gamemodes + record_type = RACE_RECORD; + // needs to be done so early because of the constants they create static_init(); @@ -942,12 +946,18 @@ spawnfunc(worldspawn) maplist_reply = strzone(getmaplist()); lsmaps_reply = strzone(getlsmaps()); monsterlist_reply = strzone(getmonsterlist()); + bool records_available = false; for(int i = 0; i < 10; ++i) { string s = getrecords(i); - if (s) + if (s != "") + { records_reply[i] = strzone(s); + records_available = true; + } } + if (!records_available) + records_reply[0] = "No records available for the current game mode.\n"; ladder_reply = strzone(getladder()); rankings_reply = strzone(getrankings()); @@ -963,7 +973,7 @@ spawnfunc(worldspawn) // fill sv_curl_serverpackages from .serverpackage files if (autocvar_sv_curl_serverpackages_auto) { - string s = "csprogs-" WATERMARK ".txt"; + string s = "csprogs-" WATERMARK ".dat"; // remove automatically managed files from the list to prevent duplicates for (int i = 0, n = tokenize_console(cvar_string("sv_curl_serverpackages")); i < n; ++i) { @@ -1019,6 +1029,133 @@ spawnfunc(light) delete(this); } +bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance) +{ + float m = e.dphitcontentsmask; + e.dphitcontentsmask = goodcontents | badcontents; + + vector org = boundmin; + vector delta = boundmax - boundmin; + + vector start, end; + start = end = org; + int j; // used after the loop + for(j = 0; j < attempts; ++j) + { + start.x = org.x + random() * delta.x; + start.y = org.y + random() * delta.y; + start.z = org.z + random() * delta.z; + + // rule 1: start inside world bounds, and outside + // solid, and don't start from somewhere where you can + // fall down to evil + tracebox(start, e.mins, e.maxs, start - '0 0 1' * delta.z, MOVE_NORMAL, e); + if (trace_fraction >= 1) + continue; + if (trace_startsolid) + continue; + if (trace_dphitcontents & badcontents) + continue; + if (trace_dphitq3surfaceflags & badsurfaceflags) + continue; + + // rule 2: if we are too high, lower the point + if (trace_fraction * delta.z > maxaboveground) + start = trace_endpos + '0 0 1' * maxaboveground; + vector enddown = trace_endpos; + + // rule 3: make sure we aren't outside the map. This only works + // for somewhat well formed maps. A good rule of thumb is that + // the map should have a convex outside hull. + // these can be traceLINES as we already verified the starting box + vector mstart = start + 0.5 * (e.mins + e.maxs); + traceline(mstart, mstart + '1 0 0' * delta.x, MOVE_NORMAL, e); + if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk") + continue; + traceline(mstart, mstart - '1 0 0' * delta.x, MOVE_NORMAL, e); + if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk") + continue; + traceline(mstart, mstart + '0 1 0' * delta.y, MOVE_NORMAL, e); + if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk") + continue; + traceline(mstart, mstart - '0 1 0' * delta.y, MOVE_NORMAL, e); + if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk") + continue; + traceline(mstart, mstart + '0 0 1' * delta.z, MOVE_NORMAL, e); + if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk") + continue; + + // rule 4: we must "see" some spawnpoint or item + entity sp = NULL; + IL_EACH(g_spawnpoints, checkpvs(mstart, it), + { + if((traceline(mstart, it.origin, MOVE_NORMAL, e), trace_fraction) >= 1) + { + sp = it; + break; + } + }); + if(!sp) + { + int items_checked = 0; + IL_EACH(g_items, checkpvs(mstart, it), + { + if((traceline(mstart, it.origin + (it.mins + it.maxs) * 0.5, MOVE_NORMAL, e), trace_fraction) >= 1) + { + sp = it; + break; + } + + ++items_checked; + if(items_checked >= attempts) + break; // sanity + }); + + if(!sp) + continue; + } + + // find a random vector to "look at" + end.x = org.x + random() * delta.x; + end.y = org.y + random() * delta.y; + end.z = org.z + random() * delta.z; + end = start + normalize(end - start) * vlen(delta); + + // rule 4: start TO end must not be too short + tracebox(start, e.mins, e.maxs, end, MOVE_NORMAL, e); + if(trace_startsolid) + continue; + if(trace_fraction < minviewdistance / vlen(delta)) + continue; + + // rule 5: don't want to look at sky + if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) + continue; + + // rule 6: we must not end up in trigger_hurt + if(tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown)) + continue; + + break; + } + + e.dphitcontentsmask = m; + + if(j < attempts) + { + setorigin(e, start); + e.angles = vectoangles(end - start); + LOG_DEBUG("Needed ", ftos(j + 1), " attempts"); + return true; + } + return false; +} + +float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance) +{ + return MoveToRandomLocationWithinBounds(e, world.mins, world.maxs, goodcontents, badcontents, badsurfaceflags, attempts, maxaboveground, minviewdistance); +} + /* =============================================================================== @@ -1057,7 +1194,7 @@ void DumpStats(float final) s = strcat(s, GetGametype(), "_", GetMapname(), ":", ftos(rint(time))); if(to_console) - LOG_INFO(s); + LOG_HELP(s); if(to_eventlog) GameLogEcho(s); @@ -1073,7 +1210,7 @@ void DumpStats(float final) s = strcat(":labels:player:", GetPlayerScoreString(NULL, 0)); if(to_console) - LOG_INFO(s); + LOG_HELP(s); if(to_eventlog) GameLogEcho(s); if(to_file) @@ -1088,7 +1225,7 @@ void DumpStats(float final) s = strcat(s, "spectator:"); if(to_console) - LOG_INFO(s, playername(it.netname, it.team, false)); + LOG_HELP(s, playername(it.netname, it.team, false)); if(to_eventlog) GameLogEcho(strcat(s, ftos(it.playerid), ":", playername(it.netname, it.team, false))); if(to_file) @@ -1099,7 +1236,7 @@ void DumpStats(float final) { s = strcat(":labels:teamscores:", GetTeamScoreString(0, 0)); if(to_console) - LOG_INFO(s); + LOG_HELP(s); if(to_eventlog) GameLogEcho(s); if(to_file) @@ -1110,7 +1247,7 @@ void DumpStats(float final) s = strcat(":teamscores:see-labels:", GetTeamScoreString(i, 0)); s = strcat(s, ":", ftos(i)); if(to_console) - LOG_INFO(s); + LOG_HELP(s); if(to_eventlog) GameLogEcho(s); if(to_file) @@ -1119,7 +1256,7 @@ void DumpStats(float final) } if(to_console) - LOG_INFO(":end"); + LOG_HELP(":end"); if(to_eventlog) GameLogEcho(":end"); if(to_file) @@ -1136,7 +1273,7 @@ only called if a time or frag limit has expired void NextLevel() { game_stopped = true; - intermission_running = 1; // game over + intermission_running = true; // game over // enforce a wait time before allowing changelevel if(player_count > 0) @@ -1700,7 +1837,7 @@ void readplayerstartcvars() start_ammo_plasma = 0; if (random_start_ammo == NULL) { - random_start_ammo = spawn(); + random_start_ammo = new_pure(random_start_ammo); } start_health = cvar("g_balance_health_start"); start_armorvalue = cvar("g_balance_armor_start"); @@ -1832,7 +1969,7 @@ void readplayerstartcvars() random_start_weapons_count = cvar("g_random_start_weapons_count"); SetResource(random_start_ammo, RES_SHELLS, cvar("g_random_start_shells")); SetResource(random_start_ammo, RES_BULLETS, cvar("g_random_start_bullets")); - SetResource(random_start_ammo, RES_ROCKETS,cvar("g_random_start_rockets")); + SetResource(random_start_ammo, RES_ROCKETS, cvar("g_random_start_rockets")); SetResource(random_start_ammo, RES_CELLS, cvar("g_random_start_cells")); SetResource(random_start_ammo, RES_PLASMA, cvar("g_random_start_plasma")); } @@ -1892,16 +2029,11 @@ void readplayerstartcvars() start_ammo_cells = max(0, start_ammo_cells); start_ammo_plasma = max(0, start_ammo_plasma); start_ammo_fuel = max(0, start_ammo_fuel); - SetResource(random_start_ammo, RES_SHELLS, - max(0, GetResource(random_start_ammo, RES_SHELLS))); - SetResource(random_start_ammo, RES_BULLETS, - max(0, GetResource(random_start_ammo, RES_BULLETS))); - SetResource(random_start_ammo, RES_ROCKETS, - max(0, GetResource(random_start_ammo, RES_ROCKETS))); - SetResource(random_start_ammo, RES_CELLS, - max(0, GetResource(random_start_ammo, RES_CELLS))); - SetResource(random_start_ammo, RES_PLASMA, - max(0, GetResource(random_start_ammo, RES_PLASMA))); + SetResource(random_start_ammo, RES_SHELLS, max(0, GetResource(random_start_ammo, RES_SHELLS))); + SetResource(random_start_ammo, RES_BULLETS, max(0, GetResource(random_start_ammo, RES_BULLETS))); + SetResource(random_start_ammo, RES_ROCKETS, max(0, GetResource(random_start_ammo, RES_ROCKETS))); + SetResource(random_start_ammo, RES_CELLS, max(0, GetResource(random_start_ammo, RES_CELLS))); + SetResource(random_start_ammo, RES_PLASMA, max(0, GetResource(random_start_ammo, RES_PLASMA))); warmup_start_ammo_shells = max(0, warmup_start_ammo_shells); warmup_start_ammo_nails = max(0, warmup_start_ammo_nails);