X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fclient.qc;h=e55fc78eefce53b1856e1dbfeeb01bf1281343f9;hb=4a7bd436b75bc975c98e7b5de69aca8074f450b6;hp=3a2b6f01c34fb447c239a2f712a99bfea61790d1;hpb=b3126a1e33c04b2e318afc6f745d96a41d1f0623;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index 3a2b6f01c..e55fc78ee 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -51,7 +52,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -138,6 +140,8 @@ bool ClientData_Send(entity this, entity to, int sf) if (CS(e).race_completed) sf |= BIT(0); // forced scoreboard if (CS(to).spectatee_status) sf |= BIT(1); // spectator ent number follows if (CS(e).zoomstate) sf |= BIT(2); // zoomed + if (observe_blocked_if_eliminated && INGAME(to)) + sf |= BIT(3); // observing blocked if (autocvar_sv_showspectators == 1 || (autocvar_sv_showspectators && IS_SPEC(to))) sf |= BIT(4); // show spectators @@ -256,7 +260,7 @@ void PutObserverInServer(entity this, bool is_forced, bool use_spawnpoint) { if (vote_called) { VoteCount(false); } this.ready = false; - recount_ready = true; + if (warmup_stage || game_starttime > time) recount_ready = true; } entcs_update_players(this); } @@ -307,7 +311,7 @@ void PutObserverInServer(entity this, bool is_forced, bool use_spawnpoint) TRANSMUTE(Observer, this); - if(recount_ready) ReadyCount(); + if(recount_ready) ReadyCount(); // FIXME: please add comment about why this is delayed WaypointSprite_PlayerDead(this); accuracy_resend(this); @@ -534,6 +538,19 @@ void FixPlayermodel(entity player) setcolor(player, stof(autocvar_sv_defaultplayercolors)); } +void GiveWarmupResources(entity this) +{ + SetResource(this, RES_SHELLS, warmup_start_ammo_shells); + SetResource(this, RES_BULLETS, warmup_start_ammo_nails); + SetResource(this, RES_ROCKETS, warmup_start_ammo_rockets); + SetResource(this, RES_CELLS, warmup_start_ammo_cells); + SetResource(this, RES_PLASMA, warmup_start_ammo_plasma); + SetResource(this, RES_FUEL, warmup_start_ammo_fuel); + SetResource(this, RES_HEALTH, warmup_start_health); + SetResource(this, RES_ARMOR, warmup_start_armorvalue); + STAT(WEAPONS, this) = WARMUP_START_WEAPONS; +} + void PutPlayerInServer(entity this) { if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE); @@ -576,17 +593,10 @@ void PutPlayerInServer(entity this) this.takedamage = DAMAGE_AIM; this.effects = EF_TELEPORT_BIT | EF_RESTARTANIM_BIT; - if (warmup_stage) { - SetResource(this, RES_SHELLS, warmup_start_ammo_shells); - SetResource(this, RES_BULLETS, warmup_start_ammo_nails); - SetResource(this, RES_ROCKETS, warmup_start_ammo_rockets); - SetResource(this, RES_CELLS, warmup_start_ammo_cells); - SetResource(this, RES_PLASMA, warmup_start_ammo_plasma); - SetResource(this, RES_FUEL, warmup_start_ammo_fuel); - SetResource(this, RES_HEALTH, warmup_start_health); - SetResource(this, RES_ARMOR, warmup_start_armorvalue); - STAT(WEAPONS, this) = WARMUP_START_WEAPONS; - } else { + if (warmup_stage) + GiveWarmupResources(this); + else + { SetResource(this, RES_SHELLS, start_ammo_shells); SetResource(this, RES_BULLETS, start_ammo_nails); SetResource(this, RES_ROCKETS, start_ammo_rockets); @@ -633,7 +643,8 @@ void PutPlayerInServer(entity this) this.respawn_flags = 0; this.respawn_time = 0; STAT(RESPAWN_TIME, this) = 0; - this.scale = ((q3compat && autocvar_sv_q3compat_changehitbox) ? 0.9 : autocvar_sv_player_scale); + // DP model scaling uses 1/16 accuracy and 13/16 is closest to 56/69 + this.scale = ((q3compat && autocvar_sv_q3compat_changehitbox) ? 0.8125 : autocvar_sv_player_scale); this.fade_time = 0; this.pain_finished = 0; this.pushltime = 0; @@ -809,6 +820,9 @@ void PutPlayerInServer(entity this) this.alivetime = time; antilag_clear(this, CS(this)); + + if (warmup_stage < 0 || warmup_stage > 1) + ReadyCount(); } /** Called when a client spawns in the server */ @@ -1037,6 +1051,8 @@ void SendWelcomeMessage(entity this, int msg_type) WriteString(msg_type, autocvar_g_xonoticversion); WriteByte(msg_type, CS(this).version_mismatch); WriteByte(msg_type, (CS(this).version < autocvar_gameversion)); + WriteByte(msg_type, autocvar_g_warmup > 1 ? autocvar_g_warmup : map_minplayers); + WriteByte(msg_type, GetPlayerLimit()); MUTATOR_CALLHOOK(BuildMutatorsPrettyString, ""); string modifications = M_ARGV(0, string); @@ -1150,7 +1166,7 @@ void ClientConnect(entity this) if (!autocvar_sv_foginterval && world.fog != "") stuffcmd(this, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n")); - if (autocvar_sv_teamnagger && !(autocvar_bot_vs_human && AvailableTeams() == 2)) + if (autocvar_sv_teamnagger && !(autocvar_bot_vs_human && AVAILABLE_TEAMS == 2)) if(!MUTATOR_CALLHOOK(HideTeamNagger, this)) send_CSQC_teamnagger(); @@ -1172,10 +1188,21 @@ void ClientConnect(entity this) Handicap_Initialize(this); + // playban + if (PlayerInList(this, autocvar_g_playban_list)) + TRANSMUTE(Observer, this); + + if (PlayerInList(this, autocvar_g_muteban_list)) // muteban + CS(this).muted = true; + MUTATOR_CALLHOOK(ClientConnect, this); if (player_count == 1) + { + if (autocvar_sv_autopause && server_is_dedicated) + setpause(0); localcmd("\nsv_hook_firstjoin\n"); + } } /* ============= @@ -1191,6 +1218,20 @@ void ClientDisconnect(entity this) { assert(IS_CLIENT(this), return); + /* from "ignore" command */ + strfree(this.ignore_list); + FOREACH_CLIENT(IS_REAL_CLIENT(it) && it.ignore_list, + { + if(it.crypto_idfp && it.crypto_idfp != "") + continue; + string mylist = ignore_removefromlist(it, this); + if(it.ignore_list) + strunzone(it.ignore_list); + + it.ignore_list = strzone(mylist); + }); + /* from "ignore" command */ + PlayerStats_GameReport_FinalizePlayer(this); if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE); if (CS(this).active_minigame) part_minigame(this); @@ -1236,7 +1277,7 @@ void ClientDisconnect(entity this) if (this.personal) delete(this.personal); this.playerid = 0; - ReadyCount(); + if (warmup_stage || game_starttime > time) ReadyCount(); if (vote_called && IS_REAL_CLIENT(this)) VoteCount(false); player_powerups_remove_all(this); // stop powerup sound @@ -1980,10 +2021,11 @@ int GetPlayerLimit() { if(g_duel) return 2; // TODO: this workaround is needed since the mutator hook from duel can't be activated before the gametype is loaded (e.g. switching modes via gametype vote screen) - int player_limit = autocvar_g_maxplayers; + // don't return map_maxplayers during intermission as it would interfere with MapHasRightSize() + int player_limit = (autocvar_g_maxplayers >= 0 || intermission_running) ? autocvar_g_maxplayers : map_maxplayers; MUTATOR_CALLHOOK(GetPlayerLimit, player_limit); player_limit = M_ARGV(0, int); - return player_limit; + return player_limit < maxclients ? player_limit : 0; } /** @@ -2007,6 +2049,17 @@ int nJoinAllowed(entity this, entity ignore) if(this && (Player_GetForcedTeamIndex(this) == TEAM_FORCE_SPECTATOR)) return 0; // forced spectators can never join + static float msg_time = 0; + if(this && !INGAME(this) && ignore && PlayerInList(this, autocvar_g_playban_list)) + { + if(time > msg_time) + { + Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PLAYBAN); + msg_time = time + 0.5; + } + return 0; + } + // TODO simplify this int totalClients = 0; int currentlyPlaying = 0; @@ -2025,10 +2078,9 @@ int nJoinAllowed(entity this, entity ignore) else if(player_limit > 0 && currentlyPlaying < player_limit) free_slots = min(maxclients - totalClients, player_limit - currentlyPlaying); - static float msg_time = 0; if(this && !INGAME(this) && ignore && !free_slots && time > msg_time) { - Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PREVENT); + Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PREVENT, player_limit); msg_time = time + 0.5; } @@ -2046,6 +2098,32 @@ bool joinAllowed(entity this) return true; } +void show_entnum(entity this) +{ + // waypoint editor implements a similar feature for waypoints + if (waypointeditor_enabled) + return; + + if (wasfreed(this.wp_aimed)) + this.wp_aimed = NULL; + + WarpZone_crosshair_trace_plusvisibletriggers(this); + entity ent = NULL; + if (trace_ent) + { + ent = trace_ent; + if (ent != this.wp_aimed) + { + string str = sprintf( + "^7ent #%d\n^8 netname: ^3%s\n^8 classname: ^5%s\n^8 origin: ^2'%s'", + etof(ent), ent.netname, ent.classname, vtos(ent.origin)); + debug_text_3d((ent.absmin + ent.absmax) * 0.5, str, 0, 7, '0 0 0'); + } + } + if (this.wp_aimed != ent) + this.wp_aimed = ent; +} + .string shootfromfixedorigin; .bool dualwielding_prev; bool PlayerThink(entity this) @@ -2067,6 +2145,8 @@ bool PlayerThink(entity this) if (frametime) player_powerups(this); + if (frametime && autocvar_sv_show_entnum) show_entnum(this); + if (IS_DEAD(this)) { if (this.personal && g_race_qualifying) { if (time > this.respawn_time) { @@ -2211,11 +2291,18 @@ void ObserverOrSpectatorThink(entity this) } } + if (frametime && autocvar_sv_show_entnum) show_entnum(this); + if (IS_BOT_CLIENT(this) && !CS(this).autojoin_checked) { CS(this).autojoin_checked = true; TRANSMUTE(Player, this); PutClientInServer(this); + + .entity weaponentity = weaponentities[0]; + if(this.(weaponentity).m_weapon == WEP_Null) + W_NextWeapon(this, 0, weaponentity); + return; } @@ -2247,10 +2334,12 @@ void ObserverOrSpectatorThink(entity this) } CS(this).impulse = 0; } else if(PHYS_INPUT_BUTTON_ATCK2(this)) { - this.would_spectate = false; - this.flags &= ~FL_JUMPRELEASED; - TRANSMUTE(Observer, this); - PutClientInServer(this); + if(!observe_blocked_if_eliminated || !INGAME(this)) { + this.would_spectate = false; + this.flags &= ~FL_JUMPRELEASED; + TRANSMUTE(Observer, this); + PutClientInServer(this); + } } else if(!SpectateUpdate(this) && !SpectateNext(this)) { PutObserverInServer(this, false, true); this.would_spectate = true; @@ -2267,6 +2356,7 @@ void ObserverOrSpectatorThink(entity this) if ((is_spec && !(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this))) || (!is_spec && !(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this)))) { this.flags |= FL_JUMPRELEASED; + // primary attack pressed if(this.flags & FL_SPAWNING) { this.flags &= ~FL_SPAWNING;