Skip to content

Pull ping corrected grenade and timer re-write to master #932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ FortressOne Server
New features
------

* `setinfo precise_grenades on/off` to enable precise timing when throwing grenades. This removes a random, up to, 100ms input delay. (default on)
* `localinfo project_grenades 0/1` [default: 0] Adjust the point at which
grenades are primed to correct for client latency. Does not allow players to
throw grenades any faster, or more frequently; only more consistently.
* Server option to limit `sv_maxclients` to current number of players during quad gametime. `localinfo limit_quad_players 0/1`. Default: `1`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

limit_quad_players has been removed.

* `localinfo forcereload 0/1` Option to prevent forced reloads.
* `+grenade1` and `+grenade2` grenade buttons (more reliable than impulses), push to prime, again to throw.
* `+dropflag` Allows player to hold button and flag will be thrown on contact.
Expand Down
2 changes: 0 additions & 2 deletions csqc/csdefs.qc
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,6 @@ const float CHAN_WEAPON = 1;
const float CHAN_VOICE = 2;
const float CHAN_ITEM = 3;
const float CHAN_BODY = 4;
const float CHAN_GREN1 = 5;
const float CHAN_GREN2 = 6;
const float ATTN_NONE = 0; /* Sounds with this attenuation can be heard throughout the map */
const float ATTN_NORM = 1; /* Standard attenuation */
const float ATTN_IDLE = 2; /* Extra attenuation so that sounds don't travel too far. */
Expand Down
78 changes: 71 additions & 7 deletions csqc/csextradefs.qc
Original file line number Diff line number Diff line change
Expand Up @@ -436,14 +436,77 @@ typedef struct {
} FO_Hud_Settings;
FO_Hud_Settings HudSettings;

typedef struct {
float grentype;
float expires;
float icon_index;
float alpha;
} FO_Hud_Grentimer;
enumflags {
FL_GT_SOUND,
FL_GT_THROWN,
FL_GT_ADJPING
};

FO_Hud_Grentimer FO_Hud_Grentimers[5];
class CsGrenTimer;
CsGrenTimer grentimers[NUM_GREN_TIMERS];

class CsGrenTimer {
float index_;
float primed_at_;
float expires_at_;
float flags_;
float grentype_;

nonvirtual float() index { return index_; };
nonvirtual float() active { return expires_at_ > time; };
nonvirtual float() expiry { return expires_at_; };
nonvirtual float() grentype { return grentype_; };
nonvirtual void() set_thrown { flags_ |= FL_GT_THROWN; };
nonvirtual float() is_thrown { return flags_ & FL_GT_THROWN; };
nonvirtual float() sound_offset {
float offset = max(3.8 - (expires_at_ - time), 0);
return offset;
};

nonvirtual void(float primed_at, float expires_at,
float grentype, float timer_flags) Set;
nonvirtual void() Stop;

nonvirtual void() PauseSound {
if (flags_ & FL_GT_SOUND) // -volume => stop.
soundupdate(this, CHAN_VOICE, "", -1, 0, 0, 0, 0);
};
nonvirtual void() StartSound;

static float next_index_;
static CsGrenTimer last_;

static void() Init {
for (float i = 0; i < grentimers.length; i++)
grentimers[i] = spawn(CsGrenTimer, index_: i);
};

static void() StopAll {
for (float i = 0; i < grentimers.length; i++)
grentimers[i].Stop();
};

static CsGrenTimer() GetNext {
next_index_ = (next_index_ + 1) % grentimers.length;
last_ = grentimers[next_index_];
return last_;
};
static void() SyncPause {
// Time froze, but sound kept running, realign.
for (float i = 0; i < grentimers.length; i++)
if (grentimers[i].active)
grentimers[i].PauseSound();
};

static void() SyncUnpause {
// Time froze, but sound kept running, realign.
for (float i = 0; i < grentimers.length; i++)
if (grentimers[i].active)
grentimers[i].StartSound();
};

static CsGrenTimer() GetLast { return last_; };
};

// scoreboard stuff
typedef struct {
Expand Down Expand Up @@ -542,6 +605,7 @@ float grentimer_waiting;
float jumpsound_cooldown;
float last_pmove_onground;
float last_vel_z;
float last_death_time;

vector FO_Hud_Icon_Size = [24, 24, 0];
vector FO_Hud_Icon_Font_Size = [8, 8, 0];
Expand Down
2 changes: 1 addition & 1 deletion csqc/csprogs.src
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ csextradefs.qc
../share/commondefs.qc
../share/common_helpers.qc
../share/common_vote.qc
settings.qc
sui_sys.qc
vote.qc
status.qc
Expand All @@ -19,6 +20,5 @@ main.qc
events.qc
hud_helpers.qc
hud.qc
settings.qc
input.qc
#endlist
123 changes: 86 additions & 37 deletions csqc/events.qc
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
void ParseSBAR();
void ParseGrenPrimed(float grentype, float timertype);
void AddGrenTimer(float grentype, float offset);
void AddSilentGrenTimer(float grentype, float offset);
void StartGrenTimer(float slot, float grentype, float offset);
void AddGrenTimer(float grentype, float offset);
void PlayGrenTimer(float offset);
void ParseGrenPrimed(float grentype, float primed_at, float explodes_at);
float StartGrenTimer(float primed_at, float expires_at, float grentype, float play_sound);

void() CSQC_Parse_Event = {
float msgtype = readbyte();
Expand Down Expand Up @@ -104,14 +100,17 @@ void() CSQC_Parse_Event = {
SBAR.Identify = readstring();
break;
case MSG_GRENPRIMED:
float grentype = readfloat();
float timertype = cvar(FOCMD_GRENTIMER);
ParseGrenPrimed(grentype, timertype);
float grentype = readbyte();
float primed_at = readfloat();
float explodes_at = readfloat();
ParseGrenPrimed(grentype, primed_at, explodes_at);
break;
case MSG_GRENTHROWN:
ApplyTransparencyToGrenTimer();
CsGrenTimer last = CsGrenTimer::GetLast();
last.set_thrown();
break;
case MSG_PLAYERDIE:
last_death_time = readfloat();
StopGrenTimers();
break;
case MSG_CLIENT_MENU:
Expand Down Expand Up @@ -302,48 +301,98 @@ void() CSQC_Parse_Event = {
case MSG_VOTE_MAP_DELETE:
RemoveVoteMap(readstring(), FALSE);
break;
case MSG_PAUSE:
CsGrenTimer::SyncPause();
break;
case MSG_UNPAUSE:
CsGrenTimer::SyncUnpause();
break;
}
}

void PlayGrenTimer(float offset) {
local float channel = CHAN_GREN1;
local float soundtime;
local float highest_soundtime = -1;
DEFCVAR_FLOAT(fo_grentimer_debug, 0);

for(float i = CHAN_GREN1; i <= CHAN_GREN5; i++) {
soundtime = getsoundtime(self, i);
string cached_timer;
string GetGrenTimerSound() {
string wav = CVARS(FOCMD_GRENTIMERSOUND);

if (soundtime < 0) {
channel = i;
break;
}
if (cached_timer != wav) {
precache_sound(wav);
cached_timer = wav;
}
return wav;
}

void CsGrenTimer::StartSound() {
if !(this.flags_ & FL_GT_SOUND)
return;

string wav = GetGrenTimerSound();
float volume = CVARF(FOCMD_GRENTIMERVOLUME);

// Note there's a bug where soundupdate returns false for a new sample, even
// though it's started.
soundupdate(this, CHAN_VOICE, wav, volume, 0, 0, 0, sound_offset());
}


void CsGrenTimer::Set(float primed_at, float expires_at, float _grentype,
float timer_flags) {
grentype_ = _grentype;
primed_at_ = primed_at;
expires_at_ = expires_at;
flags_ = timer_flags;

if (soundtime > highest_soundtime) {
highest_soundtime = soundtime;
channel = i;
}
if (this.flags_ & FL_GT_ADJPING) {
local float rtt =
getplayerkeyfloat(player_localnum, INFOKEY_P_PING) / 1000;
expires_at_ -= rtt/2;
}

local string sound = cvar_string(FOCMD_GRENTIMERSOUND);
localsound(sound, channel, cvar(FOCMD_GRENTIMERVOLUME)); // required because soundupdate doesn't reset getsoundtime
soundupdate(self, channel, sound, cvar(FOCMD_GRENTIMERVOLUME), 0, 0, 0, offset);
StartSound();
}

void ParseGrenPrimed(float grentype, float timertype) {
if(timertype == 0) {
AddSilentGrenTimer(grentype, 0);
void CsGrenTimer::Stop() {
expires_at_ = -1;
PauseSound(); // Pause is really stop.
flags_ = 0;
}

void StopGrenTimers() {
// New style.
for (float i = 0; i < NUM_GREN_TIMERS; i++)
grentimers[i].Stop();
}

void ParseGrenPrimed(float grentype, float primed_at, float explodes_at) {
if (grentype == GR_TYPE_FLARE || grentype == GR_TYPE_CALTROP)
return;
}

if(timertype == 1) {
AddGrenTimer(grentype, 0);
if (primed_at < last_death_time)
return;

local float timer_flags = 0;
switch (CVARF(FOCMD_GRENTIMER)) {
case 0: break;
case 1: timer_flags = FL_GT_SOUND; break;
// 2 [and something sane for anything we don't recognize.]
default: timer_flags = FL_GT_SOUND | FL_GT_ADJPING; break;
}

if(timertype == 2) {
local float offset = getplayerkeyfloat(player_localnum, INFOKEY_P_PING)/1000;
AddGrenTimer(grentype, offset);
return;
float debug_print_state = CVARF(fo_grentimer_debug) & 1;

CsGrenTimer timer = CsGrenTimer::GetNext();
timer.Set(primed_at, explodes_at, grentype, timer_flags);

if (debug_print_state) {
float ping = getplayerkeyfloat(player_localnum, INFOKEY_P_PING) / 1000;

float expires_old = time + 3.8 - ping;
float expires_new = timer.expiry();
float expires_ideal = explodes_at - ping/2;

print(sprintf("primed_at=%0.2f explodes_at=%0.2f fuse=%0.2f\n",
primed_at, explodes_at, explodes_at - primed_at));
}
}

Expand Down
2 changes: 1 addition & 1 deletion csqc/hud.qc
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ void Hud_DrawFlagStatusBar(string panelid)
{
if (FlagInfoLines[i].id)
{
alpha = FlagInfoLines[i].state == FLAGINFO_HOME ? cvar("fo_hud_idle_alpha") : 1;
alpha = FlagInfoLines[i].state == FLAGINFO_HOME ? CVARF(fo_hud_idle_alpha) : 1;
string icon = FlagInfoLines[i].icon.filename;
vector iconcolour = FlagInfoLines[i].icon.colour;
float bigfont = 8 * (Hud_Panels[HUD_PANEL_FLAGINFO].TextScale ? Hud_Panels[HUD_PANEL_FLAGINFO].TextScale : Hud_Panels[HUD_PANEL_FLAGINFO].Scale);
Expand Down
43 changes: 0 additions & 43 deletions csqc/hud_helpers.qc
Original file line number Diff line number Diff line change
Expand Up @@ -230,20 +230,6 @@ void Hud_DrawStringLMPThreshold(vector pos, string value, float size, float thre
}
}

string FormatCfgString(string line, string field, string value)
{
line = strcat(line, "\n", field, ":", value);

return line;
}

string FormatCfgVector(string line, string field, vector value)
{
line = strcat(line, "\n", field, ":", strcat(ftos(value_x), ",", ftos(value_y)));

return line;
}

string GetPanelString(string line, string name)
{
line = FormatCfgVector(line, strcat(name, ".position"), DrawPanel.Position);
Expand Down Expand Up @@ -483,32 +469,3 @@ vector DrawOffsetString(string msg, vector size, vector fontSize, vector pos, ve

return pos;
}

void AddGrenTimer(float grentype, float offset) {
if (grentype == GR_TYPE_FLARE || grentype == GR_TYPE_CALTROP)
return;

for(float i = 0; i < FO_Hud_Grentimers.length; i++) {
if(FO_Hud_Grentimers[i].grentype == 0) {
StartGrenTimer(i, grentype, offset);
PlayGrenTimer(offset);
break;
}
}
}

void AddSilentGrenTimer(float grentype, float offset) {
for(float i = 0; i < FO_Hud_Grentimers.length; i++) {
if(FO_Hud_Grentimers[i].grentype == 0) {
StartGrenTimer(i, grentype, offset);
break;
}
}
}

void StartGrenTimer(float slot, float grentype, float offset) {
FO_Hud_Grentimers[slot].grentype = grentype;
FO_Hud_Grentimers[slot].icon_index = grentype;
FO_Hud_Grentimers[slot].alpha = 1;
FO_Hud_Grentimers[slot].expires = time + 3.8 - offset;
}
Loading