...
 
Commits (8)
......@@ -541,7 +541,7 @@ void CSQCModel_Effects_Apply(entity this)
if(this.csqcmodel_modelflags & MF_ROTATE)
{
this.renderflags |= RF_USEAXIS;
makevectors(this.angles + '0 100 0' * fmod(time, 3.6));
MAKEVECTORS(makevectors, this.angles + '0 100 0' * fmod(time, 3.6), v_forward, v_right, v_up);
}
if(this.csqcmodel_modelflags & MF_TRACER)
tref = EFFECT_TR_WIZSPIKE.m_id;
......
......@@ -74,6 +74,8 @@ bool autocvar_hud_panel_scoreboard_spectators_showping = true;
bool autocvar_hud_panel_scoreboard_spectators_aligned = false;
float autocvar_hud_panel_scoreboard_minwidth = 0.4;
AUTOCVAR(_scoreboard_instagib, bool, false, "");
// wrapper to put all possible scores titles through gettext
string TranslateScoresLabel(string l)
{
......@@ -116,6 +118,7 @@ string TranslateScoresLabel(string l)
case "suicides": return CTX(_("SCO^suicides"));
case "takes": return CTX(_("SCO^takes"));
case "ticks": return CTX(_("SCO^ticks"));
case "country": return CTX(_("SCO^country"));
default: return l;
}
}
......@@ -365,7 +368,7 @@ void Cmd_Scoreboard_Help()
// otherwise the previous exclusive rule warns anyway
// e.g. -teams,rc,cts,lms/kills ?+rc/kills
#define SCOREBOARD_DEFAULT_COLUMNS \
"ping pl fps name |" \
"ping pl fps name country |" \
" -teams,rc,cts,inv,lms/kills +ft,tdm/kills ?+rc,inv/kills" \
" -teams,lms/deaths +ft,tdm/deaths" \
" +tdm/sum" \
......@@ -382,17 +385,42 @@ void Cmd_Scoreboard_Help()
" +dom/ticks +dom/takes" \
" -lms,rc,cts,inv,nb/score"
#define SCOREBOARD_DEFAULT_COLUMNS_INSTAGIB \
"ping pl fps name country |" \
" -teams,rc,cts,inv,lms/kills +ft,tdm/kills ?+rc,inv/kills" \
" -teams,lms/deaths +ft,tdm/deaths" \
" +tdm/sum" \
" -teams,lms,rc,cts,inv,ka/suicides +ft,tdm/suicides ?+rc,inv/suicides" \
" -cts,dm,tdm,ka,ft/frags" /* tdm already has this in "score" */ \
" -cts,nb,rc/accuracy" \
" +tdm,ft,dom,ons,as/teamkills"\
" -rc,cts,nb/deaths" \
" +ctf/pickups +ctf/fckills +ctf/returns +ctf/caps +ons/takes +ons/caps" \
" +lms/lives +lms/rank" \
" +kh/kckills +kh/losses +kh/caps" \
" ?+rc/laps ?+rc/time +rc,cts/fastest" \
" +as/objectives +nb/faults +nb/goals" \
" +ka/pickups +ka/bckills +ka/bctime +ft/revivals" \
" +dom/ticks +dom/takes" \
" -lms,rc,cts,inv,nb/score"
void Cmd_Scoreboard_SetFields(int argc)
{
TC(int, argc);
int i, slash;
string str, pattern;
string str, pattern, default_scoreboard;
bool have_name = false, have_primary = false, have_secondary = false, have_separator = false;
int missing;
if(!gametype)
return; // do nothing, we don't know gametype and scores yet
if (autocvar__scoreboard_instagib) {
default_scoreboard = SCOREBOARD_DEFAULT_COLUMNS_INSTAGIB;
} else {
default_scoreboard = SCOREBOARD_DEFAULT_COLUMNS;
}
// sbt_fields uses strunzone on the titles!
if(!sbt_field_title[0])
for(i = 0; i < MAX_SBT_FIELDS; ++i)
......@@ -403,16 +431,12 @@ void Cmd_Scoreboard_SetFields(int argc)
argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
if(argc < 3)
argc = tokenizebyseparator(strcat("0 1 ", SCOREBOARD_DEFAULT_COLUMNS), " ");
argc = tokenizebyseparator(strcat("0 1 ", default_scoreboard), " ");
if(argc == 3)
{
if(argv(2) == "default" || argv(2) == "expand_default")
{
if(argv(2) == "expand_default")
cvar_set("scoreboard_columns", SCOREBOARD_DEFAULT_COLUMNS);
argc = tokenizebyseparator(strcat("0 1 ", SCOREBOARD_DEFAULT_COLUMNS), " ");
}
if(argv(2) == "default")
argc = tokenizebyseparator(strcat("0 1 ", default_scoreboard), " ");
else if(argv(2) == "all")
{
string s = "ping pl name |"; // scores without a label
......@@ -463,6 +487,7 @@ void Cmd_Scoreboard_SetFields(int argc)
{
case "ping": sbt_field[sbt_num_fields] = SP_PING; break;
case "pl": sbt_field[sbt_num_fields] = SP_PL; break;
case "country": sbt_field[sbt_num_fields] = SP_COUNTRY; break;
case "kd": case "kdr": case "kdratio": sbt_field[sbt_num_fields] = SP_KDRATIO; break;
case "sum": case "diff": case "k-d": sbt_field[sbt_num_fields] = SP_SUM; break;
case "name": case "nick": sbt_field[sbt_num_fields] = SP_NAME; have_name = true; break;
......@@ -624,6 +649,10 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field)
sbt_field_rgb = '1 1 1' - '0 1 1' * tmp;
return ftos(f);
case SP_COUNTRY:
float cn = pl.(scores(SP_COUNTRY));
return chr2str((cn >> 8) & 0xff, cn & 0xff);
case SP_PL:
if (!pl.gotscores)
return _("N/A");
......@@ -869,7 +898,7 @@ void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, i
if(field == SP_SEPARATOR)
break;
if(is_spec && field != SP_NAME && field != SP_PING) {
if(is_spec && field != SP_NAME && field != SP_PING && field != SP_COUNTRY) {
pos.x += sbt_field_size[i] + hud_fontsize.x;
continue;
}
......
......@@ -93,18 +93,19 @@ void draw_teamradar_player(vector coord3d, vector pangles, vector rgb)
coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(coord3d));
makevectors(pangles - '0 1 0' * teamradar_angle);
vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
MAKEVECTORS(makevectors, pangles - '0 1 0' * teamradar_angle, forward, right, up);
if(v_flipped)
{
v_forward.x = -v_forward.x;
v_right.x = -v_right.x;
v_up.x = -v_up.x;
forward.x = -forward.x;
right.x = -right.x;
up.x = -up.x; // TODO: unused!
}
v_forward.z = 0;
v_forward = normalize(v_forward);
v_forward.y *= -1.0;
v_right.x = -v_forward.y;
v_right.y = v_forward.x;
forward.z = 0;
forward = normalize(forward);
forward.y *= -1.0;
right.x = -forward.y;
right.y = forward.x;
if(rgb == '1 1 1')
rgb2 = '0 0 0';
......@@ -112,17 +113,17 @@ void draw_teamradar_player(vector coord3d, vector pangles, vector rgb)
rgb2 = '1 1 1';
R_BeginPolygon("", 0);
R_PolygonVertex(coord+v_forward*3, '0 0 0', rgb2, panel_fg_alpha);
R_PolygonVertex(coord+v_right*4-v_forward*2.5, '0 1 0', rgb2, panel_fg_alpha);
R_PolygonVertex(coord-v_forward*2, '1 0 0', rgb2, panel_fg_alpha);
R_PolygonVertex(coord-v_right*4-v_forward*2.5, '1 1 0', rgb2, panel_fg_alpha);
R_PolygonVertex(coord+forward*3, '0 0 0', rgb2, panel_fg_alpha);
R_PolygonVertex(coord+right*4-forward*2.5, '0 1 0', rgb2, panel_fg_alpha);
R_PolygonVertex(coord-forward*2, '1 0 0', rgb2, panel_fg_alpha);
R_PolygonVertex(coord-right*4-forward*2.5, '1 1 0', rgb2, panel_fg_alpha);
R_EndPolygon();
R_BeginPolygon("", 0);
R_PolygonVertex(coord+v_forward*2, '0 0 0', rgb, panel_fg_alpha);
R_PolygonVertex(coord+v_right*3-v_forward*2, '0 1 0', rgb, panel_fg_alpha);
R_PolygonVertex(coord-v_forward, '1 0 0', rgb, panel_fg_alpha);
R_PolygonVertex(coord-v_right*3-v_forward*2, '1 1 0', rgb, panel_fg_alpha);
R_PolygonVertex(coord+forward*2, '0 0 0', rgb, panel_fg_alpha);
R_PolygonVertex(coord+right*3-forward*2, '0 1 0', rgb, panel_fg_alpha);
R_PolygonVertex(coord-forward, '1 0 0', rgb, panel_fg_alpha);
R_PolygonVertex(coord-right*3-forward*2, '1 1 0', rgb, panel_fg_alpha);
R_EndPolygon();
}
......
......@@ -1946,10 +1946,7 @@ void CSQC_UpdateView(entity this, float w, float h)
// Render the Scene
view_origin = getpropertyvec(VF_ORIGIN);
view_angles = getpropertyvec(VF_ANGLES);
makevectors(view_angles);
view_forward = v_forward;
view_right = v_right;
view_up = v_up;
MAKEVECTORS(makevectors, view_angles, view_forward, view_right, view_up);
#ifdef BLURTEST
if(time > blurtest_time0 && time < blurtest_time1)
......
......@@ -571,6 +571,12 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, OnEntityPreSpawn)
return true;
}
MUTATOR_HOOKFUNCTION(mutator_instagib, FixClientCvars)
{
entity player = M_ARGV(0, entity);
stuffcmd(player, "cl_cmd settemp _scoreboard_instagib 1\n");
}
MUTATOR_HOOKFUNCTION(mutator_instagib, BuildMutatorsString)
{
M_ARGV(0, string) = strcat(M_ARGV(0, string), ":instagib");
......
......@@ -31,6 +31,8 @@ REGISTER_SP(SCORE);
REGISTER_SP(DMG);
REGISTER_SP(DMGTAKEN);
REGISTER_SP(COUNTRY);
REGISTER_SP(KILLS);
REGISTER_SP(DEATHS);
REGISTER_SP(SUICIDES);
......@@ -84,6 +86,9 @@ REGISTER_SP(NEXBALL_FAULTS);
REGISTER_SP(ONS_TAKES);
REGISTER_SP(ONS_CAPS);
// accuracy
REGISTER_SP(ACC_VAPORIZER);
#endif
......
......@@ -15,7 +15,7 @@ float autocvar_g_vehicle_bumblebee_turnspeed = 120;
float autocvar_g_vehicle_bumblebee_pitchspeed = 60;
float autocvar_g_vehicle_bumblebee_pitchlimit = 60;
float autocvar_g_vehicle_bumblebee_friction = 0.5;
bool autocvar_g_vehicle_bumblebee_swim = false;
bool autocvar_g_vehicle_bumblebee_swim = true;
float autocvar_g_vehicle_bumblebee_energy = 500;
float autocvar_g_vehicle_bumblebee_energy_regen = 50;
......
......@@ -36,3 +36,4 @@
#include <server/mutators/_mod.inc>
#include <server/pathlib/_mod.inc>
#include <server/weapons/_mod.inc>
#include <server/ip2country.qc>
......@@ -15,6 +15,7 @@
#include "g_damage.qh"
#include "handicap.qh"
#include "g_hook.qh"
#include "ip2country.qh"
#include "command/common.qh"
#include "command/vote.qh"
#include "clientkill.qh"
......@@ -801,6 +802,7 @@ void PutClientInServer(entity this)
} else if (IS_PLAYER(this)) {
PutPlayerInServer(this);
}
SetCountryToScoreboard(this);
}
// TODO do we need all these fields, or should we stop autodetecting runtime
......@@ -981,6 +983,7 @@ void ClientPreConnect(entity this)
((IS_REAL_CLIENT(this)) ? this.netaddress : "bot")
));
}
IP2Country_SetPlayer(self);
}
#endif
......@@ -1126,6 +1129,10 @@ void ClientConnect(entity this)
CS(this).jointime = time;
#ifndef DP_EXT_PRECONNECT
IP2Country_SetPlayer(self);
#endif
if (IS_REAL_CLIENT(this))
{
if (g_weaponarena_weapons == WEPSET(TUBA))
......
......@@ -1648,6 +1648,27 @@ void GameCommand_warp(int request, int argc)
}
}
void GameCommand_ip2country(float request, float argc)
{
switch(request)
{
case CMD_REQUEST_COMMAND:
IP2Country_command(argc);
return;
case CMD_REQUEST_USAGE:
default:
LOG_INFO("\nUsage:^3 sv_cmd ip2country command [arguments]\n");
LOG_INFO("Available commands:\n");
LOG_INFO(" ^2status^7: list requests in process\n");
LOG_INFO(" ^2reset^7: timeout all current requests\n");
LOG_INFO(" ^2lookup ip^7: query country for ip\n");
LOG_INFO(" ^2flushcache^7: remove all ips from cache\n");
LOG_INFO(" ^2players^7: list players with ip and country code\n");
LOG_INFO(" ^2change ID CN^7: change country code by player id\n");
return;
}
}
/* use this when creating a new command, making sure to place it in alphabetical order... also,
** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
void GameCommand_(int request)
......@@ -1707,6 +1728,7 @@ SERVER_COMMAND(stuffto, "Send a command to be executed on a client") { GameComma
SERVER_COMMAND(trace, "Various debugging tools with tracing") { GameCommand_trace(request, arguments); }
SERVER_COMMAND(unlockteams, "Enable the ability for players to switch or enter teams") { GameCommand_unlockteams(request); }
SERVER_COMMAND(warp, "Choose different level in campaign") { GameCommand_warp(request, arguments); }
SERVER_COMMAND(ip2country, "Get country code by ip") { GameCommand_ip2country(request, arguments); }
void GameCommand_macro_help()
{
......
......@@ -18,6 +18,7 @@
#include "scores.qh"
#include "scores_rules.qh"
#include "teamplay.qh"
#include "ip2country.qh"
#include "weapons/weaponstats.qh"
#include "../common/constants.qh"
#include <common/net_linked.qh>
......@@ -882,6 +883,8 @@ spawnfunc(worldspawn)
WeaponStats_Init();
IP2Country_Init();
Nagger_Init();
next_pingtime = time + 5;
......@@ -2211,6 +2214,7 @@ void Shutdown()
db_save(TemporaryDB, "server-temp.db");
}
CheatShutdown(); // must be after cheatcount check
IP2Country_Cleanup();
db_close(ServerProgsDB);
db_close(TemporaryDB);
LOG_TRACE("Saving persistent data... done!");
......
#include "ip2country.qh"
float IP2Country_cachedb;
.entity ip2country_cbent;
.string netaddress;
.ip2country_callback callbackfunction;
.float started_at;
void IP2Country_Init() {
registercvar("sv_ip2country", "1");
registercvar("sv_ip2country_localcn", "XX");
registercvar("sv_ip2country_timeout", "15");
registercvar("sv_ip2country_server", "http://api.vinnica.in/country?type=xonotic&ip=");
LOG_INFO("Loading cached ips\n");
IP2Country_cachedb = db_load(IP2COUNTRY_DBNAME);
}
void IP2Country_Cleanup() {
entity e;
for(e = world; (e = find(e, classname, "ip2country_cbprovider"));)
IP2Country_FreeCallbackEnt(e);
LOG_INFO("Saving cached ips\n");
db_save(IP2Country_cachedb, IP2COUNTRY_DBNAME);
db_close(IP2Country_cachedb);
}
void IP2Country_CacheIP(string ip, string cn) {
LOG_DEBUGF("Cached ip %s %s\n", ip, cn);
db_put(IP2Country_cachedb, ip, cn);
}
string IP2Country_Cache_Get(string ip) {
return db_get(IP2Country_cachedb, ip);
}
void IP2Country_AddCallback(string ip, ip2country_callback callback, float timeout, entity callbackent) {
if(timeout <= 0)
timeout = cvar("sv_ip2country_timeout");
entity cb = spawn();
cb.classname = "ip2country_cbprovider";
cb.netaddress = strzone(ip);
cb.ip2country_cbent = callbackent;
cb.callbackfunction = callback;
cb.started_at = time;
setthink(cb, IP2Country_RequestTimeout);
cb.nextthink = time + timeout;
}
void IP2Country_ExecCallback(string ip, string cn) {
entity e;
for(e = world; (e = find(e, classname, "ip2country_cbprovider")); ) {
if(e.netaddress == ip) {
e.callbackfunction(ip, cn, e.ip2country_cbent);
IP2Country_FreeCallbackEnt(e);
}
}
}
void IP2Country_FreeCallbackEnt(entity e) {
if(e.netaddress)
strunzone(e.netaddress);
remove(e);
}
void IP2Country_RequestTimeout(entity e) {
LOG_INFOF("\nIP to country request for ip : %s timed out after %f", e.netaddress, time - e.started_at);
e.callbackfunction(e.netaddress, "", e.ip2country_cbent);
IP2Country_FreeCallbackEnt(e);
}
int is_local(string IP) {
string ipl;
ipl = strtolower(IP);
if(strncmp(ipl, "local", 5) == 0)
return 1;
else if(strncmp(ipl, "127.", 4) == 0)
return 1;
else if(strncmp(ipl, "10.", 3) == 0)
return 1;
else if(strncmp(ipl, "192.168.", 8) == 0)
return 1;
else if(strncmp(ipl, "169.254.", 8) == 0)
return 1;
else if(strncmp(ipl, "172.16.", 7) == 0)
return 1;
else
return 0;
}
void IP2Country_lookup(string ip, ip2country_callback callback, float timeout, entity cbent) {
string res;
if(!cvar("sv_ip2country"))
return;
if(is_local(ip) == 1) {
callback(ip, cvar_string("sv_ip2country_localcn"), cbent);
return;
}
res = IP2Country_Cache_Get(ip);
if(res != "") {
callback(ip, res, cbent);
return;
}
IP2Country_AddCallback(ip, callback, timeout, cbent);
if (cvar_string("sv_ip2country_server") == "") {
LOG_INFOF("\nCan't lookup ip - %s, because sv_ip2country_server is not set", ip);
return;
}
uri_get(strcat(cvar_string("sv_ip2country_server"), ip), URI_GET_IP2C);
}
void IP2Country_Get_Callback(float id, float status, string data) {
string cn, ip;
if (status) {
LOG_INFOF("\nIP lookup failed, status: %f", status);
return;
}
tokenizebyseparator(data, " ");
cn = substring(argv(0), 0, 2);
ip = argv(1);
if (cn == "--") {
LOG_INFOF("\nServer can't determine country for ip -- %s", ip);
IP2Country_ExecCallback(ip, "");
return;
}
IP2Country_CacheIP(ip, cn);
IP2Country_ExecCallback(ip, cn);
}
void IP2Country_DumpToConsole(string ip, string cn, entity e) {
LOG_INFOF("Country for IP %s: %s\n", ip, (cn == "") ? "Unknown" : cn);
}
void IP2Country_check(string ip) {
IP2Country_lookup(ip, IP2Country_DumpToConsole, 0, world);
}
void IP2Country_status() {
entity e;
LOG_INFO("^3Requests in process:\n");
for(e = world; (e = find(e, classname, "ip2country_cbprovider"));)
LOG_INFOF("%-30s: ^5%4.2f\n", e.netaddress, time - e.started_at);
}
void IP2Country_reset() {
entity e;
for(e = world; (e = find(e, classname, "ip2country_cbprovider"));) {
e.think();
}
}
void IP2Country_flushcache() {
db_close(IP2Country_cachedb);
IP2Country_cachedb = db_create();
db_save(IP2Country_cachedb, IP2COUNTRY_DBNAME);
LOG_INFO("ip2country cache flushed\n");
}
void SetPlayerCountry(entity player, string cn) {
if(player.ip2country_code)
strunzone(player.ip2country_code);
player.ip2country_code = strzone(strtoupper(cn));
}
void SetCountryToScoreboard(entity player) {
string cn;
if(CS(player).scorekeeper && player.ip2country_code) {
cn = player.ip2country_code;
PlayerScore_Set(player, SP_COUNTRY, (str2chr(cn, 0) << 8) + str2chr(cn, 1));
} else {
LOG_INFOF("Player %s has no scorekeeper\n", player.netname);
}
}
void IP2Country_PlayerCallback(string ip, string cn, entity player) {
SetPlayerCountry(player, cn);
}
void IP2Country_SetPlayer(entity player) {
if(IS_REAL_CLIENT(player))
IP2Country_lookup(player.netaddress, IP2Country_PlayerCallback, 0, player);
else
SetPlayerCountry(player, "");
}
void IP2Country_players() {
FOREACH_CLIENT(IS_REAL_CLIENT(it), {
LOG_INFOF("#%-2d %12s^7 %18s [%2s]\n", num_for_edict(it), it.netname, it.netaddress, it.ip2country_code);
});
}
void IP2Country_redraw() {
FOREACH_CLIENT(IS_REAL_CLIENT(it), {
SetCountryToScoreboard(it);
});
}
void IP2Country_ChangeCountry(entity player, string country) {
if(strlen(country) == 2 && IS_REAL_CLIENT(player)) {
SetPlayerCountry(player, country);
SetCountryToScoreboard(player);
}
}
void IP2Country_command(float argc) {
if(argc < 2)
goto wrong_argument;
switch(argv(1)) {
case "status":
IP2Country_status();
if (argc != 2)
goto wrong_argument;
return;
case "reset":
if (argc != 2)
goto wrong_argument;
IP2Country_reset();
return;
case "flushcache":
if (argc != 2)
goto wrong_argument;
IP2Country_flushcache();
return;
case "players":
if (argc != 2)
goto wrong_argument;
IP2Country_players();
return;
case "redraw":
if (argc != 2)
goto wrong_argument;
IP2Country_redraw();
return;
case "lookup":
if (argc != 3)
goto wrong_argument;
IP2Country_check(argv(2));
return;
case "change":
if (argc != 4)
goto wrong_argument;
entity client = GetFilteredEntity(argv(2));
IP2Country_ChangeCountry(client, argv(3));
return;
default:
LOG_INFO("Wrong command\n"
"Available commands: status,reset,flushcache,players,lookup,change\n");
return;
}
:wrong_argument
LOG_INFO("Wrong argument count\n");
}
#ifndef IP2COUNTRY_H
#define IP2COUNTRY_H
#define IP2COUNTRY_DBNAME "ip2country.db"
typedef void(string, string, entity) ip2country_callback;
const int URI_GET_IP2C = 33;
.string ip2country_code;
void IP2Country_Init();
void IP2Country_Cleanup();
void IP2Country_lookup(string, ip2country_callback, float, entity);
void IP2Country_Get_Callback(float, float, string);
void IP2Country_FreeCallbackEnt(entity);
void IP2Country_RequestTimeout(entity);
void IP2Country_check(string);
void IP2Country_command(float);
void IP2Country_SetPlayer(entity);
void IP2Country_redraw();
void SetCountryToScoreboard(entity);
#endif
......@@ -35,6 +35,7 @@
#include "../lib/csqcmodel/sv_model.qh"
#include "../lib/warpzone/anglestransform.qh"
#include "../lib/warpzone/server.qh"
#include "ip2country.qh"
void crosshair_trace(entity pl)
{
......@@ -1138,6 +1139,10 @@ void URI_Get_Callback(float id, float status, string data)
{
// handled
}
else if (id == URI_GET_IP2C)
{
IP2Country_Get_Callback(id, status, data);
}
else if (id == URI_GET_DISCARD)
{
// discard
......
......@@ -271,11 +271,13 @@ float PlayerScore_Clear(entity player)
sk = CS(player).scorekeeper;
FOREACH(Scores, true, {
if(it != SP_COUNTRY) {
if(sk.(scores(it)) != 0)
if(scores_label(it) != "")
sk.SendFlags |= (2 ** (i % 16));
if(i != SP_ELO.m_id)
sk.(scores(it)) = 0;
}
});
return 1;
......@@ -286,6 +288,7 @@ void Score_ClearAll()
entity sk;
float t;
FOREACH_CLIENTSLOT(true, {
if(it != SP_COUNTRY) {
sk = CS(it).scorekeeper;
if (!sk) continue;
FOREACH(Scores, true, {
......@@ -294,6 +297,7 @@ void Score_ClearAll()
sk.SendFlags |= (2 ** (i % 16));
if(i != SP_ELO.m_id)
sk.(scores(it)) = 0;
}
});
});
for(t = 0; t < 16; ++t)
......@@ -309,6 +313,7 @@ void Score_ClearAll()
sk.(teamscores(j)) = 0;
}
}
IP2Country_redraw();
}
void PlayerScore_Attach(entity player)
......
......@@ -51,6 +51,8 @@ void ScoreRules_basics(int teams, float sprio, float stprio, float score_enabled
ScoreInfo_SetLabel_PlayerScore(SP_DMG, "dmg", 0);
ScoreInfo_SetLabel_PlayerScore(SP_DMGTAKEN, "dmgtaken", SFL_LOWER_IS_BETTER);
ScoreInfo_SetLabel_PlayerScore(SP_ELO, "elo", 0);
ScoreInfo_SetLabel_PlayerScore(SP_COUNTRY, "country", 0);
ScoreInfo_SetLabel_PlayerScore(SP_ACC_VAPORIZER, "accuracy", 0);
if(STAT(SHOWFPS))
ScoreInfo_SetLabel_PlayerScore(SP_FPS, "fps", 0);
......
......@@ -63,6 +63,7 @@ void accuracy_resend(entity e)
void accuracy_add(entity this, Weapon w, int fired, int hit)
{
int orig_wep = w.m_id;
if (IS_INDEPENDENT_PLAYER(this)) return;
entity a = CS(this).accuracy;
if (!a) return;
......@@ -84,7 +85,22 @@ void accuracy_add(entity this, Weapon w, int fired, int hit)
a.fired_time = time;
}
if (b == accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid])) return; // no change
int new_b = accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid]);
if (b == new_b) return; // no change
if (orig_wep == WEP_VAPORIZER.m_id) {
int acc;
if (new_b == 0) {
acc = 0;
} else if (new_b == 255) {
acc = 1.0;
} else {
acc = (new_b - 1) / 100;
}
// hack to make acc look same
PlayerScore_Set(this, SP_ACC_VAPORIZER, acc * 100);
}
int sf = 1 << (wepid % 24);
a.SendFlags |= sf;
FOREACH_CLIENT(IS_SPEC(it) && it.enemy == this, { CS(it).accuracy.SendFlags |= sf; });
......
......@@ -34,7 +34,7 @@ set g_vehicle_bumblebee_turnspeed 120
set g_vehicle_bumblebee_pitchspeed 60
set g_vehicle_bumblebee_pitchlimit 60
set g_vehicle_bumblebee_friction 0.5
set g_vehicle_bumblebee_swim 0
set g_vehicle_bumblebee_swim 1
set g_vehicle_bumblebee_energy 500
set g_vehicle_bumblebee_energy_regen 50
......
This diff is collapsed.