...
 
Commits (22)
Tue Nov 27 07:24:07 CET 2018
Sun Dec 16 07:25:19 CET 2018
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -951,68 +951,13 @@ effect machinegun_impact
tex 40 40
velocityjitter 300 300 300
velocitymultiplier 0.200000
effect grenadelauncher_muzzleflash
type smoke
airfriction 12
alpha 256 256 512
color 0x202020 0x404040
count 1.500000
lightcolor 2 1.5 0.2
lightradiusfade 2000
lightradius 200
originjitter 1.5 1.5 1.5
size 5 5
tex 0 8
velocityjitter 20 20 20
velocitymultiplier 0.030000
effect grenadelauncher_muzzleflash
type spark
airfriction 5
alpha 0 128 1024
color 0xffdb96 0xff5400
count 16
originjitter 1 1 1
size 10 20
stretchfactor 2.500000
tex 48 55
velocityjitter 100 100 100
velocitymultiplier 0.500000
effect TR_GRENADE
type smoke
alpha 300 400 780
bounce 1
color 0x101010 0x000000
originjitter 1 1 1
sizeincrease 10
size 3 2
tex 0 8
trailspacing 4
velocityjitter 1 1 1
velocitymultiplier -0.020000
effect TR_GRENADE
type static
airfriction 8
alpha 100 144 988
color 0xffdf72 0x811200
notunderwater
sizeincrease -15
size 5 2
alpha 133 200 150
color 0xff0000 0xff0000
size 5 5
tex 48 55
trailspacing 4
velocityjitter 32 32 32
velocitymultiplier -1
effect TR_GRENADE
type bubble
alpha 256 256 256
bounce 1.500000
color 0x404040 0x808080
gravity -0.125000
liquidfriction 4
size 1 1
tex 62 62
trailspacing 16
underwater
velocityjitter 16 16 16
trailspacing 6
effect TR_KNIGHTSPIKE
type smoke
alpha 300 400 600
......@@ -1358,29 +1303,6 @@ effect electro_combo
size 30 30
tex 33 33
velocitymultiplier 0.300000
effect crylink_muzzleflash
type smoke
alpha 128 128 2024
color 0xdd9cff 0xff0090
count 0.500000
lightcolor 1.6 0.2 2
lightradiusfade 2000
lightradius 200
size 15 20
tex 65 65
velocitymultiplier 0.010000
effect crylink_muzzleflash
type spark
airfriction 12
alpha 0 128 1024
color 0xA080C0 0xA080C0
count 5
originjitter 1 1 1
size 5 10
stretchfactor 1.500000
tex 35 36
velocityjitter 200 200 200
velocitymultiplier 0.300000
effect crylink_impact
type decal
alpha 256 256 0
......@@ -1547,58 +1469,6 @@ effect nex_impact
tex 41 41
velocityjitter 300 300 600
velocitymultiplier 2.500000
effect hagar_muzzleflash
type smoke
alpha 256 256 512
color 0x202020 0x404040
count 2
lightcolor 2 1.5 0.2
lightradiusfade 2000
lightradius 200
originjitter 1.5 1.5 1.5
size 5 5
tex 0 8
velocityjitter 6 6 6
velocitymultiplier 0.010000
effect hagar_muzzleflash
type spark
airfriction 12
alpha 0 128 1024
color 0xff8400 0xff4200
count 15
originjitter 1 1 1
rotate -180 180 -400 400
size 5 10
stretchfactor 2
tex 48 55
velocityjitter 200 200 200
velocitymultiplier 0.500000
effect hagar_bounce
type smoke
alpha 256 256 256
color 0x202020 0x404040
count 2
lightcolor 2 1.5 0.2
lightradiusfade 300
lightradius 60
originjitter 1.5 1.5 1.5
size 5 5
tex 0 8
velocityjitter 6 6 6
velocitymultiplier 0.010000
effect hagar_bounce
type spark
airfriction 12
alpha 0 256 256
bounce 1.500000
color 0xFFFDD9 0xFFFDD9
count 15
gravity 1
originjitter 1 1 1
size 3 3
tex 40 40
velocityjitter 600 600 600
velocitymultiplier 0.500000
effect hagar_explode
type decal
alpha 256 256 0
......@@ -1677,82 +1547,54 @@ effect hagar_explode
tex 40 40
velocityjitter 224 224 224
velocityoffset 0 0 80
effect rocketlauncher_muzzleflash
type smoke
airfriction 2
alpha 256 256 256
color 0x202020 0x404040
count 10
originjitter 1.5 1.5 1.5
sizeincrease 20
size 1 1
tex 0 8
velocityjitter 40 40 40
velocitymultiplier -0.130000
effect rocketlauncher_muzzleflash
type smoke
airfriction 9
alpha 10 25 20
color 0xFFFDD9 0xFFFDD9
count 6
originjitter 3 3 3
rotate -180 180 -30 30
sizeincrease 20
size 5 10
tex 35 36
velocityjitter 100 100 100
velocitymultiplier 0.300000
effect TR_ROCKET
type smoke
alpha 200 300 200
bounce 1
color 0x000000 0x666666
color 0xaa6660 0xaa6600
lightcolor 6 3 1
lightradius 150
notunderwater
originjitter 2 2 2
rotate -180 180 -30 30
sizeincrease 11
size 3 4
sizeincrease 10
size 1 2
tex 0 8
trailspacing 10
trailspacing 8
velocityjitter 3 3 3
velocitymultiplier -0.020000
effect TR_ROCKET
type static
airfriction 8
alpha 100 144 588
alpha 100 144 1000
color 0xffdf72 0x811200
sizeincrease -20
size 20 20
tex 48 55
trailspacing 5
velocityjitter 32 32 32
velocitymultiplier -1.500000
effect TR_ROCKET
type static
airfriction 8
alpha 100 144 388
color 0xffdf72 0x811200
sizeincrease -30
size 7 7
tex 48 55
trailspacing 4
trailspacing 5
velocityjitter 32 32 32
velocitymultiplier -1.500000
effect TR_ROCKET
type bubble
alpha 256 256 256
bounce 1.500000
gravity -0.125000
liquidfriction 4
size 1 2
tex 62 62
trailspacing 16
underwater
velocityjitter 16 16 16
velocitymultiplier -0.310000
effect TR_ROCKET
type spark
airfriction 5
alpha 444 512 1866
alpha 444 512 1066
bounce 1
color 0xFFFDD9 0xFFFDD9
notunderwater
originjitter 1 1 1
size 0.500000 0.500000
size 0.300000 0.900000
stretchfactor 0.300000
tex 40 40
trailspacing 20
trailspacing 8
velocityjitter 100 100 100
velocitymultiplier -0.310000
effect rocket_explode
......@@ -2795,7 +2637,7 @@ effect smoking_smallemitter
velocityjitter 5 5 20
effect TR_CRYLINKPLASMA
type static
alpha 256 256 1024
alpha 256 256 624
color 0x5522aa 0x6622ff
sizeincrease 8
size 2 2
......@@ -2805,10 +2647,10 @@ effect TR_CRYLINKPLASMA
velocitymultiplier -0.010000
effect TR_CRYLINKPLASMA
type static
alpha 256 256 2600
alpha 256 256 1000
color 0x5522aa 0x6622ff
sizeincrease 15
size 3 3
sizeincrease 17
size 4 3
tex 3 3
trailspacing 16
velocityjitter 2 2 2
......@@ -5596,42 +5438,17 @@ effect impact_flesh
tex 24 32
velocityjitter 96 96 96
velocitymultiplier 5
effect tr_hagar
type smoke
alpha 300 400 780
bounce 1
color 0x101010 0x000000
originjitter 1 1 1
sizeincrease 10
size 3 2
tex 0 8
trailspacing 4
velocityjitter 1 1 1
velocitymultiplier -0.020000
effect tr_hagar
type static
airfriction 8
alpha 100 144 988
alpha 100 144 1400
color 0xffdf72 0x811200
notunderwater
sizeincrease -15
size 5 2
size 3 2
tex 48 55
trailspacing 4
trailspacing 2
velocityjitter 32 32 32
velocitymultiplier -1
effect tr_hagar
type bubble
alpha 256 256 256
bounce 1.500000
color 0x404040 0x808080
gravity -0.125000
liquidfriction 4
size 1 1
tex 62 62
trailspacing 16
underwater
velocityjitter 16 16 16
effect damage_laser
type smoke
airfriction -0.350000
......
ast "Asturian" "Asturianu" 73%
de "German" "Deutsch" 99%
de_CH "German (Switzerland)" "Deutsch (Schweiz)" 99%
ast "Asturian" "Asturianu" 69%
de "German" "Deutsch" 92%
de_CH "German (Switzerland)" "Deutsch (Schweiz)" 92%
en "English" "English" 100%
en_AU "English (Australia)" "English (Australia)" 86%
es "Spanish" "Español" 99%
fr "French" "Français" 99%
ga "Irish" "Irish" 35%
it "Italian" "Italiano" 99%
hu "Hungarian" "Magyar" 57%
nl "Dutch" "Nederlands" 70%
pl "Polish" "Polski" 81%
pt "Portuguese" "Português" 98%
pt_BR "Portuguese (Brazil)" "Português (Brasil)" 99%
ro "Romanian" "Romana" 83%
fi "Finnish" "Suomi" 33%
el "Greek" "Ελληνική" 43%
be "Belarusian" "Беларуская" 61%
bg "Bulgarian" "Български" 68%
ru "Russian" "Русский" 99%
sr "Serbian" "Српски" 71%
uk "Ukrainian" "Українська" 57%
zh_CN "Chinese (China)" "中文" 63%
zh_TW "Chinese (Taiwan)" "國語" 68%
ko "Korean" "한국의" 33%
en_AU "English (Australia)" "English (Australia)" 81%
es "Spanish" "Español" 92%
fr "French" "Français" 96%
ga "Irish" "Irish" 34%
it "Italian" "Italiano" 100%
hu "Hungarian" "Magyar" 51%
nl "Dutch" "Nederlands" 66%
pl "Polish" "Polski" 76%
pt "Portuguese" "Português" 91%
pt_BR "Portuguese (Brazil)" "Português (Brasil)" 95%
ro "Romanian" "Romana" 78%
fi "Finnish" "Suomi" 32%
el "Greek" "Ελληνική" 42%
be "Belarusian" "Беларуская" 58%
bg "Bulgarian" "Български" 64%
ru "Russian" "Русский" 100%
sr "Serbian" "Српски" 66%
uk "Ukrainian" "Українська" 53%
zh_CN "Chinese (China)" "中文" 60%
zh_TW "Chinese (Taiwan)" "國語" 65%
ko "Korean" "한국의" 32%
......@@ -565,8 +565,6 @@ bool HUD_WouldShowCursor()
{
if(autocvar__hud_configure)
return true;
if(hud_panel_radar_mouse)
return true;
if(mv_active)
return true;
//entity local_player = ((csqcplayer) ? csqcplayer : CSQCModel_server2csqc(player_localentnum - 1)); // TODO: doesn't use regular cursor handling
......@@ -700,10 +698,15 @@ void HUD_Main()
HUD_Panel_Draw(HUD_PANEL(QUICKMENU));
HUD_Panel_Draw(HUD_PANEL(SCOREBOARD));
bool cursor_active_prev = cursor_active;
int cursor_active_prev = cursor_active;
cursor_active = HUD_WouldShowCursor();
if (cursor_active_prev != cursor_active && autocvar_hud_cursormode)
{
setcursormode(cursor_active);
// cursor inactive this frame, will be set to 1 the next frame
if (cursor_active)
cursor_active = -1;
}
if (intermission == 2)
HUD_Reset();
......
......@@ -259,6 +259,7 @@ bool QuickMenu_Page_Load(string target_submenu, bool new_page)
TC(bool, new_page);
string s = string_null, cmd = string_null, z_submenu;
QuickMenu_Page_ActivatedEntry = -1;
if (new_page == 0)
QuickMenu_Page = 0;
else
......@@ -384,6 +385,7 @@ bool QuickMenu_ActionForNumber(int num)
if (QuickMenu_Page_Command[num] != "")
{
QuickMenu_Page_ActivatedEntry_Time = time + 0.1;
localcmd(strcat("\n", QuickMenu_Page_Command[num], "\n"));
QuickMenu_TimeOut = ((autocvar_hud_panel_quickmenu_time > 0) ? time + autocvar_hud_panel_quickmenu_time : 0);
return true;
......@@ -397,7 +399,6 @@ void QuickMenu_Page_ActiveEntry(int entry_num)
{
TC(int, entry_num);
QuickMenu_Page_ActivatedEntry = entry_num;
QuickMenu_Page_ActivatedEntry_Time = time + 0.1;
if(QuickMenu_Page_Command[QuickMenu_Page_ActivatedEntry])
{
bool f = QuickMenu_ActionForNumber(QuickMenu_Page_ActivatedEntry);
......@@ -513,19 +514,22 @@ void QuickMenu_Mouse()
int entry_num = min(QuickMenu_Page_Entries - 1, floor((mousepos.y - first_entry_pos) / fontsize.y));
if (QuickMenu_IsLastPage || entry_num != QUICKMENU_MAXLINES - 2)
{
// recycling panel_pos as entry_pos
panel_pos.y = first_entry_pos + entry_num * fontsize.y;
vector color;
if(mouseClicked & S_MOUSE1)
color = '0.5 1 0.5';
else if(hudShiftState & S_CTRL)
color = '1 1 0.3';
else
color = '1 1 1';
drawfill(panel_pos, vec2(panel_size.x, fontsize.y), color, .2, DRAWFLAG_NORMAL);
if(!mouseClicked && (prevMouseClicked & S_MOUSE1))
QuickMenu_Page_ActiveEntry((entry_num < QUICKMENU_MAXLINES - 1) ? entry_num + 1 : 0);
if (time > QuickMenu_Page_ActivatedEntry_Time)
{
vector entry_pos = panel_pos;
entry_pos.y = first_entry_pos + entry_num * fontsize.y;
vector color;
if (mouseClicked & S_MOUSE1)
color = '0.5 1 0.5';
else if (hudShiftState & S_CTRL)
color = '1 1 0.3';
else
color = '1 1 1';
drawfill(entry_pos, vec2(panel_size.x, fontsize.y), color, .2, DRAWFLAG_NORMAL);
}
}
}
}
......@@ -664,8 +668,7 @@ void HUD_QuickMenu()
}
HUD_Quickmenu_DrawEntry(panel_pos, sprintf("%d: %s%s", i, color, QuickMenu_Page_Description[i]), option, fontsize);
if(QuickMenu_Page_ActivatedEntry_Time && time < QuickMenu_Page_ActivatedEntry_Time
&& QuickMenu_Page_ActivatedEntry == i)
if (time < QuickMenu_Page_ActivatedEntry_Time && QuickMenu_Page_ActivatedEntry == i)
drawfill(panel_pos, vec2(panel_size.x, fontsize.y), '0.5 1 0.5', .2, DRAWFLAG_NORMAL);
panel_pos.y += fontsize.y;
......@@ -776,6 +779,7 @@ void QuickMenu_Default(string target_submenu)
string tc_cmd;
QUICKMENU_SMENU(_("Chat"), "Chat")
QUICKMENU_SMENU_PL(CTX(_("QMCMD^Send public message to")), "Send public message to", "commandmode say %s:^7", 0, 1)
QUICKMENU_ENTRY_TC(CTX(_("QMCMD^nice one")), "say %s", ":-) / nice one", CTX(_("QMCMD^:-) / nice one")))
QUICKMENU_ENTRY_TC(CTX(_("QMCMD^good game")), "say %s", "good game", CTX(_("QMCMD^good game")))
QUICKMENU_ENTRY_TC(CTX(_("QMCMD^hi / good luck")), "say %s", "hi / good luck and have fun", CTX(_("QMCMD^hi / good luck and have fun")))
......
......@@ -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,41 @@ 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"\
" +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 +430,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 +486,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 +648,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 +897,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;
}
......
......@@ -359,6 +359,11 @@ void MapVote_Draw()
ymax -= chat_sizey;
hud_fontsize = HUD_GetFontsize("hud_fontsize");
if (gametypevote)
{
gtv_text_size = hud_fontsize * 1.4;
gtv_text_size_small = hud_fontsize * 1.1;
}
pos.y = ymin;
pos.z = 0;
......@@ -680,9 +685,6 @@ void MapVote_Init()
mapvote_chosenmap = strzone(ReadString());
if ( gametypevote == 2 )
gametypevote = 0;
gtv_text_size = hud_fontsize*1.4;
gtv_text_size_small = hud_fontsize*1.1;
}
MapVote_ReadMask();
......
......@@ -1592,6 +1592,15 @@ void HUD_Mouse(entity player)
return;
}
if (cursor_active == -1) // starting to display the cursor
{
// since HUD_Mouse is called by CSQC_UpdateView before CSQC_InputEvent,
// in the first frame mousepos is the mouse position of the last time
// the cursor was displayed, thus we ignore it to avoid a glictch
cursor_active = 1;
return;
}
if(!autocvar_hud_cursormode)
update_mousepos();
......
......@@ -16,7 +16,7 @@ entity viewmodels[MAX_WEAPONSLOTS];
vector viewloc_mousepos;
bool cursor_active;
int cursor_active;
int cursor_type;
const int CURSOR_NORMAL = 0;
const int CURSOR_MOVE = 1;
......
......@@ -478,7 +478,8 @@ MUTATOR_HOOKFUNCTION(ft, PlayerPreThink, CBC_ORDER_FIRST)
//if(player.freezetag_frozen_timeout > 0 && time < player.freezetag_frozen_timeout)
//player.iceblock.alpha = ICE_MIN_ALPHA + (ICE_MAX_ALPHA - ICE_MIN_ALPHA) * (player.freezetag_frozen_timeout - time) / (player.freezetag_frozen_timeout - player.freezetag_frozen_time);
IntrusiveList reviving_players = NULL;
entity reviving_players_last = NULL;
entity reviving_players_first = NULL;
if(player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
n = -1;
......@@ -487,11 +488,15 @@ MUTATOR_HOOKFUNCTION(ft, PlayerPreThink, CBC_ORDER_FIRST)
n = 0;
vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
FOREACH_CLIENT(IS_PLAYER(it) && IS_REVIVING(player, it, revive_extra_size), {
if (!reviving_players)
reviving_players = IL_NEW();
IL_PUSH(reviving_players, it);
if (reviving_players_last)
reviving_players_last.chain = it;
reviving_players_last = it;
if (!reviving_players_first)
reviving_players_first = it;
++n;
});
if (reviving_players_last)
reviving_players_last.chain = NULL;
}
if (!n) // no teammate nearby
......@@ -522,26 +527,23 @@ MUTATOR_HOOKFUNCTION(ft, PlayerPreThink, CBC_ORDER_FIRST)
}
// EVERY team mate nearby gets a point (even if multiple!)
IL_EACH(reviving_players, true, {
for(entity it = reviving_players_first; it; it = it.chain)
{
GameRules_scoring_add(it, FREEZETAG_REVIVALS, +1);
GameRules_scoring_add(it, SCORE, +1);
nades_GiveBonus(it, autocvar_g_nades_bonus_score_low);
});
}
entity first = IL_FIRST(reviving_players);
entity first = reviving_players_first;
Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, first.netname);
Send_Notification(NOTIF_ONE, first, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED, player.netname, first.netname);
}
if (reviving_players)
IL_EACH(reviving_players, true, {
STAT(REVIVE_PROGRESS, it) = STAT(REVIVE_PROGRESS, player);
});
for(entity it = reviving_players_first; it; it = it.chain)
STAT(REVIVE_PROGRESS, it) = STAT(REVIVE_PROGRESS, player);
}
if (reviving_players)
IL_DELETE(reviving_players);
return true;
}
......
......@@ -129,6 +129,8 @@ MUTATOR_HOOKFUNCTION(lms, reset_map_players)
});
}
// FIXME add support for sv_ready_restart_after_countdown
// that is find a way to respawn/reset players IN GAME without setting lives to 0
MUTATOR_HOOKFUNCTION(lms, ReadLevelCvars)
{
// incompatible
......@@ -258,6 +260,7 @@ MUTATOR_HOOKFUNCTION(lms, ClientConnect)
}
}
// FIXME LMS doesn't allow clients to spectate due to its particular implementation
MUTATOR_HOOKFUNCTION(lms, AutoJoinOnConnection)
{
if(autocvar_g_campaign)
......
......@@ -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
......
......@@ -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"
......@@ -804,6 +805,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
......@@ -984,6 +986,7 @@ void ClientPreConnect(entity this)
((IS_REAL_CLIENT(this)) ? this.netaddress : "bot")
));
}
IP2Country_SetPlayer(self);
}
#endif
......@@ -1131,6 +1134,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()
{
......
......@@ -808,7 +808,9 @@ void Damage(entity targ, entity inflictor, entity attacker, float damage, int de
}
else if(IS_PLAYER(attacker))
{
if(deathtype != DEATH_FIRE.m_id)
// if enemy gets frozen in this frame and receives other damage don't
// play the typehitsound e.g. when hit by multiple bullets of the shotgun
if (deathtype != DEATH_FIRE.m_id && (!STAT(FROZEN, victim) || time > victim.freeze_time))
{
attacker.typehitsound += 1;
}
......
......@@ -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; });
......
This diff is collapsed.