#include "main.qh"
-#include <common/effects/qc/all.qh>
+#include "defs.qh"
+#include <common/ent_cs.qh>
+#include "miscfunctions.qh"
+#include <common/effects/effect.qh>
+#include <common/effects/qc/_mod.qh>
+#include <common/effects/all.qh>
+#include <common/effects/all.inc>
#include "hud/_mod.qh"
#include "mapvoting.qh"
#include "mutators/events.qh"
#include <common/minigames/cl_minigames_hud.qh>
#include <common/net_linked.qh>
#include <common/net_notice.qh>
+#include <common/scores.qh>
#include <common/triggers/include.qh>
#include <common/vehicles/all.qh>
#include <lib/csqcmodel/cl_model.qh>
prvm_language = strzone(cvar_string("prvm_language"));
#ifdef WATERMARK
- LOG_INFOF("^4CSQC Build information: ^1%s\n", WATERMARK);
+ LOG_INFOF("^4CSQC Build information: ^1%s", WATERMARK);
#endif
{
registercvar("cl_jumpspeedcap_min", "");
registercvar("cl_jumpspeedcap_max", "");
+ registercvar("cl_shootfromfixedorigin", "");
+
registercvar("cl_multijump", "1");
registercvar("cl_spawn_near_teammate", "1");
GetTeam(NUM_SPECTATOR, true); // add specs first
+ for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
+ weapon_accuracy[w] = -1;
+
// precaches
if(autocvar_cl_reticle)
if(!isNew && n != this.sv_entnum)
{
//print("A CSQC entity changed its owner!\n");
- LOG_INFOF("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", etof(this), this.classname);
+ LOG_INFOF("A CSQC entity changed its owner! (edict: %d, classname: %s)", etof(this), this.classname);
isNew = true;
Ent_Remove(this);
}
// RegisterPlayer(o);
//playerchecker will do this for us later, if it has not already done so
- int sf, lf;
- sf = ReadShort();
- lf = ReadShort();
+ int sf = ReadShort();
+ int lf = ReadShort();
FOREACH(Scores, true, {
- int p = 1 << (i % 16);
+ int p = 1 << (i % 16);
if (sf & p)
{
if (lf & p)
else
o.(scores(it)) = ReadChar();
}
- });
+ });
return = true;
{
make_pure(this);
int i;
- entity o;
this.team = ReadByte();
- o = this.owner = GetTeam(this.team, true); // these team numbers can always be trusted
+ entity o = this.owner = GetTeam(this.team, true); // these team numbers can always be trusted
- int sf, lf;
#if MAX_TEAMSCORE <= 8
- sf = ReadByte();
- lf = ReadByte();
+ int sf = ReadByte();
+ int lf = ReadByte();
#else
- sf = ReadShort();
- lf = ReadShort();
+ int sf = ReadShort();
+ int lf = ReadShort();
#endif
- int p;
- for(i = 0, p = 1; i < MAX_TEAMSCORE; ++i, p *= 2)
- if(sf & p)
+ for(i = 0; i < MAX_TEAMSCORE; ++i)
+ if(sf & BIT(i))
{
- if(lf & p)
+ if(lf & BIT(i))
o.(teamscores(i)) = ReadInt24_t();
else
o.(teamscores(i)) = ReadChar();
make_pure(this);
float newspectatee_status;
- int f = ReadByte();
+ int f = ReadByte();
- scoreboard_showscores_force = (f & 1);
+ scoreboard_showscores_force = (f & BIT(0));
- if(f & 2)
+ if(f & BIT(1))
{
newspectatee_status = ReadByte();
if(newspectatee_status == player_localnum + 1)
else
newspectatee_status = 0;
- spectatorbutton_zoom = (f & 4);
+ spectatorbutton_zoom = (f & BIT(2));
- if(f & 16)
+ if(f & BIT(4))
{
num_spectators = ReadByte();
NET_HANDLE(ENT_CLIENT_NAGGER, bool isnew)
{
make_pure(this);
- int i, j, b, f;
+ int i, j, b, f;
- int nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS
+ int nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS
if(!(nags & BIT(2)))
{
for(i = 1; i <= maxclients; i += 8)
{
f = ReadByte();
- for(j = i-1, b = 1; b < 256; b *= 2, ++j)
+ for(j = i-1, b = BIT(0); b < BIT(8); b <<= 1, ++j)
if (!(f & b))
if(playerslots[j])
playerslots[j].ready = 0;
NET_HANDLE(ENT_CLIENT_ELIMINATEDPLAYERS, bool isnew)
{
make_pure(this);
- int i, j, b, f;
-
- int sf = ReadByte();
- if(sf & 1)
- {
- for(j = 0; j < maxclients; ++j)
- if(playerslots[j])
+ int sf = 0;
+ serialize(byte, 0, sf);
+ if (sf & 1) {
+ for (int j = 0; j < maxclients; ++j) {
+ if (playerslots[j]) {
playerslots[j].eliminated = 1;
- for(i = 1; i <= maxclients; i += 8)
- {
- f = ReadByte();
- for(j = i-1, b = 1; b < 256; b *= 2, ++j)
- if (!(f & b))
- if(playerslots[j])
- playerslots[j].eliminated = 0;
+ }
+ }
+ for (int i = 1; i <= maxclients; i += 8) {
+ int f = 0;
+ serialize(byte, 0, f);
+ for (int b = 0; b < 8; ++b) {
+ if (f & BIT(b)) continue;
+ int j = i - 1 + b;
+ if (playerslots[j]) {
+ playerslots[j].eliminated = 0;
+ }
+ }
}
}
return true;
NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew)
{
make_pure(this);
- int sf = ReadInt24_t();
+ int sf = ReadInt24_t();
if (sf == 0) {
for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
weapon_accuracy[w] = -1;
int f = 1;
for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) {
if (sf & f) {
- int b = ReadByte();
+ int b = ReadByte();
if (b == 0)
weapon_accuracy[w] = -1;
else if (b == 255)
void Spawn_Draw(entity this)
{
+ if(this.alpha <= 0)
+ return;
+
__pointparticles(this.cnt, this.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1));
}
float alph;
vector org = getpropertyvec(VF_ORIGIN);
if(this.fade_start)
- alph = bound(0, (this.fade_end - vlen(org - this.origin - 0.5 * (this.mins + this.maxs))) / (this.fade_end - this.fade_start), 1);
+ {
+ if(vdist(org - this.origin, >, this.fade_end))
+ alph = 0; // save on some processing
+ else if(vdist(org - this.origin, <, this.fade_start))
+ alph = 1; // more processing saved
+ else
+ alph = bound(0, (this.fade_end - vlen(org - this.origin - 0.5 * (this.mins + this.maxs))) / (this.fade_end - this.fade_start), 1);
+ }
else
alph = 1;
//printf("%v <-> %v\n", view_origin, this.origin + 0.5 * (this.mins + this.maxs));
NET_HANDLE(ENT_CLIENT_SPAWNPOINT, bool is_new)
{
float teamnum = (ReadByte() - 1);
- vector spn_origin;
- spn_origin.x = ReadCoord();
- spn_origin.y = ReadCoord();
- spn_origin.z = ReadCoord();
+ vector spn_origin = ReadVector();
this.team = (teamnum + 1);
if(entnum)
{
- this.origin_x = ReadCoord();
- this.origin_y = ReadCoord();
- this.origin_z = ReadCoord();
+ this.origin = ReadVector();
if(is_new)
{
{
if (t != this.enttype || isnew)
{
- LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", etof(this), this.entnum, this.enttype, t);
+ LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)", etof(this), this.entnum, this.enttype, t);
Ent_Remove(this);
clearentity(this);
isnew = true;
{
if (!isnew)
{
- LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", etof(this), this.entnum, t);
+ LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)", etof(this), this.entnum, t);
isnew = true;
}
}
FOREACH(LinkedEntities, it.m_id == t, {
if (isnew) this.classname = it.netname;
if (autocvar_developer_csqcentities)
- LOG_INFOF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)\n", isnew, savetime, this, this.entnum, this.enttype, this.classname, t);
+ LOG_INFOF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)", isnew, savetime, this, this.entnum, this.enttype, this.classname, t);
done = it.m_read(this, NULL, isnew);
MUTATOR_CALLHOOK(Ent_Update, this, isnew);
break;
if(this.snd_looping > 0)
{
- sound(this, this.snd_looping, SND_Null, VOL_BASE, autocvar_g_jetpack_attenuation);
+ sound(this, this.snd_looping, SND_Null, VOL_BASE, autocvar_cl_jetpack_attenuation);
this.snd_looping = 0;
}
// CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(this) as well.
void CSQC_Ent_Remove(entity this)
{
- if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Ent_Remove() with this=%i {.entnum=%d, .enttype=%d}\n", this, this.entnum, this.enttype);
+ if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Ent_Remove() with this=%i {.entnum=%d, .enttype=%d}", this, this.entnum, this.enttype);
if (wasfreed(this))
{
LOG_WARN("CSQC_Ent_Remove called for already removed entity. Packet loss?");
// CSQC_Parse_StuffCmd : Provides the stuffcmd string in the first parameter that the server provided. To execute standard behavior, simply execute localcmd with the string.
void CSQC_Parse_StuffCmd(string strMessage)
{
- if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage);
+ if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_StuffCmd(\"%s\")", strMessage);
localcmd(strMessage);
}
// CSQC_Parse_Print : Provides the print string in the first parameter that the server provided. To execute standard behavior, simply execute print with the string.
void CSQC_Parse_Print(string strMessage)
{
- if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_Print(\"%s\")\n", strMessage);
+ if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_Print(\"%s\")", strMessage);
print(ColorTranslateRGB(strMessage));
}
// CSQC_Parse_CenterPrint : Provides the centerprint_hud string in the first parameter that the server provided.
void CSQC_Parse_CenterPrint(string strMessage)
{
- if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage);
+ if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_CenterPrint(\"%s\")", strMessage);
centerprint_hud(strMessage);
}
FOREACH(TempEntities, it.m_id == nTEID, {
if (autocvar_developer_csqcentities)
- LOG_INFOF("CSQC_Parse_TempEntity() nTEID=%s (%d)\n", it.netname, nTEID);
+ LOG_INFOF("CSQC_Parse_TempEntity() nTEID=%s (%d)", it.netname, nTEID);
return it.m_read(NULL, NULL, true);
});
if (autocvar_developer_csqcentities)
- LOG_INFOF("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
+ LOG_INFOF("CSQC_Parse_TempEntity() with nTEID=%d", nTEID);
// No special logic for this temporary entity; return 0 so the engine can handle it
return false;
forcefog = strzone(ReadString());
armorblockpercent = ReadByte() / 255.0;
+ damagepush_speedfactor = ReadByte() / 255.0;
serverflags = ReadByte();
race_checkpoint = ReadByte();
race_time = ReadInt24_t();
race_previousbesttime = ReadInt24_t();
+ race_mypreviousbesttime = ReadInt24_t();
if(race_previousbestname)
strunzone(race_previousbestname);
- race_previousbestname = strzone(ReadString());
+ string pbestname = ReadString();
+ if(autocvar_cl_race_cptimes_onlyself)
+ {
+ race_previousbesttime = race_mypreviousbesttime;
+ race_mypreviousbesttime = 0;
+ race_previousbestname = strzone("");
+ }
+ else
+ race_previousbestname = strzone(pbestname);
race_checkpointtime = time;
race_penaltyaccumulator = 0;
race_laptime = time; // valid
}
-
break;
case RACE_NET_CHECKPOINT_CLEAR:
race_nextcheckpoint = ReadByte();
race_nextbesttime = ReadInt24_t();
+ if(b != RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING) // not while spectating (matches server)
+ race_mybesttime = ReadInt24_t();
if(race_nextbestname)
strunzone(race_nextbestname);
- race_nextbestname = strzone(ReadString());
+ string newname = ReadString();
+ if(autocvar_cl_race_cptimes_onlyself && b != RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING)
+ {
+ race_nextbesttime = race_mybesttime;
+ race_mybesttime = 0;
+ race_nextbestname = strzone("");
+ }
+ else
+ race_nextbestname = strzone(newname);
break;
case RACE_NET_CHECKPOINT_HIT_RACE:
race_mycheckpointlapsdelta -= 256;
if(race_mycheckpointenemy)
strunzone(race_mycheckpointenemy);
- race_mycheckpointenemy = strzone(ReadString());
+ int who = ReadByte();
+ if(who)
+ race_mycheckpointenemy = strzone(entcs_GetName(who - 1));
+ else
+ race_mycheckpointenemy = strzone(""); // TODO: maybe string_null works fine here?
break;
case RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT:
race_othercheckpointlapsdelta -= 256;
if(race_othercheckpointenemy)
strunzone(race_othercheckpointenemy);
- race_othercheckpointenemy = strzone(ReadString());
+ int what = ReadByte();
+ if(what)
+ race_othercheckpointenemy = strzone(entcs_GetName(what - 1));
+ else
+ race_othercheckpointenemy = strzone(""); // TODO: maybe string_null works fine here?
break;
case RACE_NET_PENALTY_RACE: