From f40cfbb151ffe25020a7d2ff0023df17ede070c5 Mon Sep 17 00:00:00 2001 From: div0 Date: Tue, 3 Feb 2009 12:58:02 +0000 Subject: [PATCH] add a new cheat "impulse 404"; some CSQC refactorings; distribute prandom seed as shared entity git-svn-id: svn://svn.icculus.org/nexuiz/trunk@5724 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/client/Main.qc | 109 ++++++++++++--------------- data/qcsrc/client/main.qh | 3 +- data/qcsrc/client/particles.qc | 15 ++-- data/qcsrc/client/projectile.qc | 1 + data/qcsrc/client/waypointsprites.qc | 20 ++--- data/qcsrc/common/constants.qh | 54 ++++++------- data/qcsrc/server/cl_impulse.qc | 35 ++++++++- data/qcsrc/server/g_damage.qc | 6 ++ data/qcsrc/server/g_world.qc | 25 ++++++ data/qcsrc/server/miscfunctions.qc | 16 ++-- 10 files changed, 171 insertions(+), 113 deletions(-) diff --git a/data/qcsrc/client/Main.qc b/data/qcsrc/client/Main.qc index 7ca84246c..62a7bc532 100644 --- a/data/qcsrc/client/Main.qc +++ b/data/qcsrc/client/Main.qc @@ -444,6 +444,20 @@ void Ent_ReadEntCS() } void Ent_Remove(); + +void Ent_RemovePlayerScore() +{ + float i; + + if(self.owner) + { + SetTeam(self.owner, -1); + self.owner.gotscores = 0; + for(i = 0; i < MAX_SCORE; ++i) + self.owner.(scores[i]) = 0; // clear all scores + } +} + void Ent_ReadPlayerScore() { float i, n; @@ -495,6 +509,8 @@ void Ent_ReadPlayerScore() if(o.sort_prev) Sbar_UpdatePlayerPos(o); // if not registered, we cannot do this yet! + + self.entremove = Ent_RemovePlayerScore; } void Ent_ReadTeamScore() @@ -585,6 +601,11 @@ void Ent_Nagger() warmup_stage = (nags & 16); } +void Ent_RandomSeed() +{ + psrandom(ReadShort()); +} + // CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured. // The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS. void Ent_RadarLink(); @@ -610,42 +631,29 @@ void(float bIsNewEntity) CSQC_Ent_Update = } #endif self.enttype = t; - if(self.enttype == ENT_CLIENT_ENTCS) - Ent_ReadEntCS(); - else if(self.enttype == ENT_CLIENT_SCORES) - Ent_ReadPlayerScore(); - else if(self.enttype == ENT_CLIENT_TEAMSCORES) - Ent_ReadTeamScore(); - else if(self.enttype == ENT_CLIENT_POINTPARTICLES) - Ent_PointParticles(); - else if(self.enttype == ENT_CLIENT_RAINSNOW) - Ent_RainOrSnow(); - else if(self.enttype == ENT_CLIENT_LASER) - Ent_Laser(); - else if(self.enttype == ENT_CLIENT_NAGGER) - Ent_Nagger(); - else if(self.enttype == ENT_CLIENT_WAYPOINT) - Ent_WaypointSprite(); - else if(self.enttype == ENT_CLIENT_RADARLINK) - Ent_RadarLink(); - else if(self.enttype == ENT_CLIENT_PROJECTILE) - Ent_Projectile(); - else if(self.enttype == ENT_CLIENT_GIBSPLASH) - Ent_GibSplash(); - else if(self.enttype == ENT_CLIENT_DAMAGEINFO) - Ent_DamageInfo(); - else if(self.enttype == ENT_CLIENT_CASING) - Ent_Casing(); - else if(self.enttype == ENT_CLIENT_INIT) - Ent_Init(); - else if(self.enttype == ENT_CLIENT_SCORES_INFO) - Ent_ScoresInfo(); - else if(self.enttype == ENT_CLIENT_MAPVOTE) - Ent_MapVote(); - else if(self.enttype == ENT_CLIENT_CLIENTDATA) - Ent_ClientData(); - else - error(strcat("unknown entity type in CSQC_Ent_Update: ", ftos(self.enttype), "\n")); + switch(t) + { + case ENT_CLIENT_ENTCS: Ent_ReadEntCS(); break; + case ENT_CLIENT_SCORES: Ent_ReadPlayerScore(); break; + case ENT_CLIENT_TEAMSCORES: Ent_ReadTeamScore(); break; + case ENT_CLIENT_RAINSNOW: Ent_RainOrSnow(); break; + case ENT_CLIENT_LASER: Ent_Laser(); break; + case ENT_CLIENT_NAGGER: Ent_Nagger(); break; + case ENT_CLIENT_WAYPOINT: Ent_WaypointSprite(); break; + case ENT_CLIENT_RADARLINK: Ent_RadarLink(); break; + case ENT_CLIENT_PROJECTILE: Ent_Projectile(); break; + case ENT_CLIENT_GIBSPLASH: Ent_GibSplash(); break; + case ENT_CLIENT_DAMAGEINFO: Ent_DamageInfo(); break; + case ENT_CLIENT_CASING: Ent_Casing(); break; + case ENT_CLIENT_INIT: Ent_Init(); break; + case ENT_CLIENT_SCORES_INFO: Ent_ScoresInfo(); break; + case ENT_CLIENT_MAPVOTE: Ent_MapVote(); break; + case ENT_CLIENT_CLIENTDATA: Ent_ClientData(); break; + case ENT_CLIENT_RANDOMSEED: Ent_RandomSeed(); break; + default: + error(strcat("unknown entity type in CSQC_Ent_Update: ", ftos(self.enttype), "\n")); + break; + } time = savetime; }; @@ -655,35 +663,14 @@ void(float bIsNewEntity) CSQC_Ent_Update = void Ent_Remove() { float i; - if(self.enttype == ENT_CLIENT_SCORES) - { - if(self.owner) - { - SetTeam(self.owner, -1); - self.owner.gotscores = 0; - for(i = 0; i < MAX_SCORE; ++i) - self.owner.(scores[i]) = 0; // clear all scores - } - } else if(self.enttype == ENT_CLIENT_TEAMSCORES) - { - /* - if(self.owner) - RemoveTeam(self.owner); - */ - // we don't NEED to remove them... they won't display anyway - // plus, svqc never does this anyway - } else if(self.enttype == ENT_CLIENT_POINTPARTICLES) - { - Ent_PointParticles_Remove(); - } - else if(self.enttype == ENT_CLIENT_WAYPOINT) - Ent_RemoveWaypointSprite(); - else if(self.enttype == ENT_CLIENT_PROJECTILE) - Ent_RemoveProjectile(); + + if(self.entremove) + self.entremove(); self.enttype = 0; self.classname = ""; self.draw = menu_sub_null; + self.entremove = menu_sub_null; // TODO possibly set more stuff to defaults } // CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(self) as well. diff --git a/data/qcsrc/client/main.qh b/data/qcsrc/client/main.qh index 8ef3984da..e4c88366d 100644 --- a/data/qcsrc/client/main.qh +++ b/data/qcsrc/client/main.qh @@ -110,6 +110,7 @@ entity teamslots[17]; // 17 teams (including "spectator team") .void(void) draw; .void(void) draw2d; +.void(void) entremove; float drawframetime; vector view_origin, view_angles, view_forward, view_right, view_up; @@ -142,4 +143,4 @@ float vid_width, vid_height, vid_pixelheight; float camera_active; // Demo camera is active if set to TRUE float chase_active_backup; float camera_roll; -vector camera_direction; \ No newline at end of file +vector camera_direction; diff --git a/data/qcsrc/client/particles.qc b/data/qcsrc/client/particles.qc index 471efd40b..24956482a 100644 --- a/data/qcsrc/client/particles.qc +++ b/data/qcsrc/client/particles.qc @@ -91,6 +91,13 @@ void Draw_PointParticles() self.origin = o; } +void Ent_PointParticles_Remove() +{ + if(self.noise) + strunzone(self.noise); + self.noise = string_null; +} + void Ent_PointParticles() { float f; @@ -144,13 +151,7 @@ void Ent_PointParticles() setsize(self, self.mins, self.maxs); self.solid = SOLID_NOT; self.draw = Draw_PointParticles; -} - -void Ent_PointParticles_Remove() -{ - if(self.noise) - strunzone(self.noise); - self.noise = string_null; + self.entremove = Ent_PointParticles_Remove; } void Draw_Rain() diff --git a/data/qcsrc/client/projectile.qc b/data/qcsrc/client/projectile.qc index 92e285135..c465a898b 100644 --- a/data/qcsrc/client/projectile.qc +++ b/data/qcsrc/client/projectile.qc @@ -283,6 +283,7 @@ void Ent_Projectile() InterpolateOrigin_Note(); self.draw = Projectile_Draw; + self.entremove = Ent_RemoveProjectile; } void Projectile_Precache() diff --git a/data/qcsrc/client/waypointsprites.qc b/data/qcsrc/client/waypointsprites.qc index 5854eafe8..010f0aaeb 100644 --- a/data/qcsrc/client/waypointsprites.qc +++ b/data/qcsrc/client/waypointsprites.qc @@ -200,6 +200,16 @@ void Draw_WaypointSprite() drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP); } +void Ent_RemoveWaypointSprite() +{ + if(self.netname) + strunzone(self.netname); + if(self.netname2) + strunzone(self.netname2); + if(self.netname3) + strunzone(self.netname3); +} + void Ent_WaypointSprite() { float sendflags, f; @@ -267,16 +277,8 @@ void Ent_WaypointSprite() } InterpolateOrigin_Note(); -} -void Ent_RemoveWaypointSprite() -{ - if(self.netname) - strunzone(self.netname); - if(self.netname2) - strunzone(self.netname2); - if(self.netname3) - strunzone(self.netname3); + self.entremove = Ent_RemoveWaypointSprite; } void WaypointSprite_Load() diff --git a/data/qcsrc/common/constants.qh b/data/qcsrc/common/constants.qh index af99d7f72..b0cc447c7 100644 --- a/data/qcsrc/common/constants.qh +++ b/data/qcsrc/common/constants.qh @@ -72,6 +72,7 @@ const float ENT_CLIENT_CASING = 15; const float ENT_CLIENT_INIT = 16; const float ENT_CLIENT_MAPVOTE = 17; const float ENT_CLIENT_CLIENTDATA = 18; +const float ENT_CLIENT_RANDOMSEED = 19; const float SPRITERULE_DEFAULT = 0; const float SPRITERULE_TEAMPLAY = 1; @@ -358,32 +359,33 @@ float PROJECTILE_BULLET_GLOWING = 18; // Deathtypes (weapon deathtypes are the IT_* constants below) // NOTE: when adding death types, please add an explanation to Docs/spamlog.txt too. -float DEATH_SPECIAL_START = 10000; -float DEATH_FALL = 10000; -float DEATH_TELEFRAG = 10001; -float DEATH_DROWN = 10002; -float DEATH_HURTTRIGGER = 10003; -float DEATH_LAVA = 10004; -float DEATH_SLIME = 10005; -float DEATH_KILL = 10006; -float DEATH_NOAMMO = 10007; -float DEATH_SWAMP = 10008; -float DEATH_TEAMCHANGE = 10009; -float DEATH_AUTOTEAMCHANGE = 10010; -float DEATH_CAMP = 10011; -float DEATH_SHOOTING_STAR = 10012; -float DEATH_ROT = 10013; -float DEATH_MIRRORDAMAGE = 10014; -float DEATH_TOUCHEXPLODE = 10015; -float DEATH_TURRET = 10100; - -float DEATH_WEAPONMASK = 0xFF; -float DEATH_HITTYPEMASK = 0x1F00; // which is WAY below 10000 used for normal deaths -float HITTYPE_SECONDARY = 0x100; -float HITTYPE_SPLASH = 0x200; -float HITTYPE_BOUNCE = 0x400; -float HITTYPE_HEADSHOT = 0x800; -float HITTYPE_RESERVED = 0x1000; // unused yet +float DEATH_SPECIAL_START = 10000; +float DEATH_FALL = 10000; +float DEATH_TELEFRAG = 10001; +float DEATH_DROWN = 10002; +float DEATH_HURTTRIGGER = 10003; +float DEATH_LAVA = 10004; +float DEATH_SLIME = 10005; +float DEATH_KILL = 10006; +float DEATH_NOAMMO = 10007; +float DEATH_SWAMP = 10008; +float DEATH_TEAMCHANGE = 10009; +float DEATH_AUTOTEAMCHANGE = 10010; +float DEATH_CAMP = 10011; +float DEATH_SHOOTING_STAR = 10012; +float DEATH_ROT = 10013; +float DEATH_MIRRORDAMAGE = 10014; +float DEATH_TOUCHEXPLODE = 10015; +float DEATH_CHEAT = 10016; +float DEATH_TURRET = 10100; + +float DEATH_WEAPONMASK = 0xFF; +float DEATH_HITTYPEMASK = 0x1F00; // which is WAY below 10000 used for normal deaths +float HITTYPE_SECONDARY = 0x100; +float HITTYPE_SPLASH = 0x200; +float HITTYPE_BOUNCE = 0x400; +float HITTYPE_HEADSHOT = 0x800; +float HITTYPE_RESERVED = 0x1000; // unused yet // macros to access these #define DEATH_ISSPECIAL(t) ((t) >= DEATH_SPECIAL_START) diff --git a/data/qcsrc/server/cl_impulse.qc b/data/qcsrc/server/cl_impulse.qc index a7939070f..7eff0e931 100644 --- a/data/qcsrc/server/cl_impulse.qc +++ b/data/qcsrc/server/cl_impulse.qc @@ -84,6 +84,7 @@ void printsurfaceinfo(entity e, vector v) * 143: emergency teleport * 144: printsurfaceinfo * 145: distance + * 147: unfairly eliminate * * TODO: * 200 to 209: prev weapon shortcuts @@ -95,10 +96,11 @@ void printsurfaceinfo(entity e, vector v) void ImpulseCommands (void) { local float imp; + vector org; float i; float m; float wep; - entity e; + entity e, e2; imp = self.impulse; if (!imp || gameover) @@ -410,6 +412,37 @@ void ImpulseCommands (void) traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 65536, FALSE, self); sprint(self, strcat("distance: ", ftos(fabs(vlen(trace_endpos - (self.origin + self.view_ofs)))), "\n")); break; + case 148: + FOR_EACH_PLAYER(e) + { + if(e.playermodel == "models/player/jeandarc.zym" + || e.playermodel == "models/player/pyria.zym" + || e.playermodel == "models/player/skadi.zym" + || e.playermodel == "models/player/visitant.zym") + { + makevectors(e.angles); + traceline(e.origin, e.origin + v_right * 256, MOVE_NORMAL, e); + } + else + { + org_x = random(); + org_y = random(); + org_z = 0; + org = normalize(org); + traceline(e.origin, e.origin + org * 256, MOVE_NORMAL, e); // random direction + } + + org = findbetterlocation(trace_endpos, 12); + + e2 = spawn(); + setorigin(e2, org); + pointparticles(particleeffectnum("rocket_explode"), org, '0 0 0', 1); + sound(e2, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + RadiusDamage(e2, e, 1000, 0, 128, e, 500, DEATH_CHEAT, world); + remove(e2); + } + print("404 Sportsmanship not found.\n"); + break; } } } diff --git a/data/qcsrc/server/g_damage.qc b/data/qcsrc/server/g_damage.qc index 11d17d34c..9d533e8dd 100644 --- a/data/qcsrc/server/g_damage.qc +++ b/data/qcsrc/server/g_damage.qc @@ -280,6 +280,8 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) bprint ("^1",s, "^1 thought he found a nice camping ground\n"); else if (deathtype == DEATH_MIRRORDAMAGE) bprint ("^1",s, "^1 didn't become friends with the Lord of Teamplay\n"); + else if (deathtype == DEATH_CHEAT) + bprint ("^1",s, "^1 unfairly eliminated himself\n"); else if (deathtype != DEATH_TEAMCHANGE) bprint ("^1",s, "^1 couldn't resist the urge to self-destruct\n"); @@ -390,6 +392,8 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) bprint ("^1",s, "^1 was pushed into the line of fire by ^1", a, "\n"); else if(deathtype == DEATH_TOUCHEXPLODE) bprint ("^1",s, "^1 was pushed into an accident by ^1", a, "\n"); + else if(deathtype == DEATH_CHEAT) + bprint ("^1",s, "^1 was unfairly eliminated by ^1", a, "\n"); else bprint ("^1",s, "^1 was fragged by ", a, "\n"); } @@ -519,6 +523,8 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) bprint ("^1",s, "^1 was mowed down by a turret \n"); else if(deathtype == DEATH_TOUCHEXPLODE) bprint ("^1",s, "^1 died in an accident\n"); + else if(deathtype == DEATH_CHEAT) + bprint ("^1",s, "^1 was unfairly eliminated\n"); else if(sv_gentle) bprint ("^1",s, "^1 needs a restart\n"); diff --git a/data/qcsrc/server/g_world.qc b/data/qcsrc/server/g_world.qc index 6d865a243..d0b39fc49 100644 --- a/data/qcsrc/server/g_world.qc +++ b/data/qcsrc/server/g_world.qc @@ -298,6 +298,30 @@ void detect_maptype() #endif } +entity randomseed; +float RandomSeed_Send(entity to, float sf) +{ + WriteByte(MSG_ENTITY, ENT_CLIENT_RANDOMSEED); + WriteShort(MSG_ENTITY, self.cnt); +} +void RandomSeed_Think() +{ + self.cnt = bound(0, floor(random() * 65536), 65535); + self.nextthink = time + 5; +} +void RandomSeed_Spawn() +{ + randomseed = spawn(); + randomseed.think = RandomSeed_Think; + Net_LinkEntity(randomseed, FALSE, 0, RandomSeed_Send); + + entity oldself; + oldself = self; + self = randomseed; + self.think(); // sets random seed and nextthink + self = oldself; +} + float world_already_spawned; void RegisterWeapons(); void Nagger_Init(); @@ -557,6 +581,7 @@ void spawnfunc_worldspawn (void) records_reply = strzone(getrecords()); ClientInit_Spawn(); + RandomSeed_Spawn(); world_initialized = 1; } diff --git a/data/qcsrc/server/miscfunctions.qc b/data/qcsrc/server/miscfunctions.qc index 4473d7595..e70e6ebc3 100644 --- a/data/qcsrc/server/miscfunctions.qc +++ b/data/qcsrc/server/miscfunctions.qc @@ -1633,15 +1633,20 @@ void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer) #define IFTARGETED if(!self.nottargeted && self.targetname != "") void() SUB_Remove; -void Net_LinkEntityWithSize(entity e, float docull, float dt, vector mi, vector ma, float(entity, float) sendfunc) +void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc) { + vector mi, ma; + if(e.classname == "") e.classname = "net_linked"; if(e.model == "" || self.modelindex == 0) + { + mi = self.mins; + ma = self.maxs; setmodel(e, "null"); - - setsize(e, mi, ma); + setsize(e, mi, ma); + } e.SendEntity = sendfunc; e.SendFlags = 0xFFFFFF; @@ -1656,11 +1661,6 @@ void Net_LinkEntityWithSize(entity e, float docull, float dt, vector mi, vector } } -void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc) -{ - Net_LinkEntityWithSize(e, docull, dt, e.mins, e.maxs, sendfunc); -} - void adaptor_think2touch() { entity o; -- 2.39.2