]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into TimePath/csqc_sounds
authorTimePath <andrew.hardaker1995@gmail.com>
Mon, 16 Nov 2015 10:34:04 +0000 (21:34 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Mon, 16 Nov 2015 10:34:04 +0000 (21:34 +1100)
# Conflicts:
# qcsrc/client/main.qc
# qcsrc/server/cl_player.qh

30 files changed:
qcsrc/client/hud/panel/radar.qc
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/miscfunctions.qc
qcsrc/client/miscfunctions.qh
qcsrc/client/progs.inc
qcsrc/client/shownames.qc
qcsrc/client/view.qc
qcsrc/common/constants.qh
qcsrc/common/effects/qc/all.inc
qcsrc/common/effects/qc/globalsound.qc [new file with mode: 0644]
qcsrc/common/effects/qc/globalsound.qh [new file with mode: 0644]
qcsrc/common/ent_cs.qc [new file with mode: 0644]
qcsrc/common/ent_cs.qh [new file with mode: 0644]
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/physics.qc
qcsrc/common/sounds/sound.qh
qcsrc/common/weapons/weapon/arc.qc
qcsrc/lib/net.qh
qcsrc/lib/warpzone/common.qc
qcsrc/server/autocvars.qh
qcsrc/server/cl_client.qc
qcsrc/server/cl_player.qc
qcsrc/server/cl_player.qh
qcsrc/server/command/cmd.qc
qcsrc/server/defs.qh
qcsrc/server/ent_cs.qc [deleted file]
qcsrc/server/ent_cs.qh [deleted file]
qcsrc/server/miscfunctions.qc
qcsrc/server/progs.inc

index ad3e79ce53467b8b13c170fcdbe4d073e216ee1b..c06fcdbfe218e87ad282ac0fbec2093ec6d96ce7 100644 (file)
@@ -359,6 +359,8 @@ void HUD_Radar()
        }
        for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
        {
+               if (!tm.m_entcs_private) continue;
+               if (entcs_is_self(tm)) continue;
                color2 = GetPlayerColor(tm.sv_entnum);
                //if(color == NUM_SPECTATOR || color == color2)
                        draw_teamradar_player(tm.origin, tm.angles, Team_ColorRGB(color2));
index 1d543af2607457e97cf3fa85338116f72a5ce864..f4852ab7f73c9833f181862bd3e4a1e4f2fce63e 100644 (file)
@@ -327,47 +327,6 @@ float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
 // --------------------------------------------------------------------------
 // BEGIN OPTIONAL CSQC FUNCTIONS
 
-void Ent_RemoveEntCS()
-{
-       SELFPARAM();
-       entcs_receiver[this.sv_entnum] = NULL;
-}
-
-NET_HANDLE(ENT_CLIENT_ENTCS, bool isnew)
-{
-       make_pure(this);
-       this.classname = "entcs_receiver";
-       InterpolateOrigin_Undo();
-       int sf = ReadByte();
-
-       if(sf & BIT(0))
-               this.sv_entnum = ReadByte();
-       if (sf & BIT(1))
-       {
-               this.origin_x = ReadShort();
-               this.origin_y = ReadShort();
-               this.origin_z = ReadShort();
-               setorigin(this, this.origin);
-       }
-       if (sf & BIT(2))
-       {
-               this.angles_y = ReadByte() * 360.0 / 256;
-               this.angles_x = this.angles_z = 0;
-       }
-       if (sf & BIT(3))
-               this.healthvalue = ReadByte() * 10;
-       if (sf & BIT(4))
-               this.armorvalue = ReadByte() * 10;
-
-       return = true;
-
-       entcs_receiver[this.sv_entnum] = this;
-       this.entremove = Ent_RemoveEntCS;
-       this.iflags |= IFLAG_ORIGIN;
-
-       InterpolateOrigin_Note();
-}
-
 void Ent_Remove();
 
 void Ent_RemovePlayerScore()
index 48f7621879e63ace51b83a5904b4db03aebfdede..9229b718a5dbe33b5a27e059e7f7feb2745f7f10 100644 (file)
@@ -141,8 +141,6 @@ float g_balance_electro_secondary_bouncefactor;
 float g_balance_electro_secondary_bouncestop;
 float g_trueaim_minrange;
 
-entity entcs_receiver[255]; // 255 is the engine limit on maxclients
-
 float hud;
 float view_quality;
 int framecount;
index ab4cb1f15673c6c952872e83e22f2048c3b15237..bbe0722fd7dad9464b9a8df5a3d1ceb7537d3059 100644 (file)
@@ -482,55 +482,25 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
        }
 }
 
-vector getplayerorigin(int pl)
+// TODO: entcs
+float getplayeralpha(int pl)
 {
-       entity e;
-
-       e = CSQCModel_server2csqc(pl + 1);
-       if(e)
-               return e.origin;
-
-       e = entcs_receiver[pl];
-       if(e)
-               return e.origin;
-
-       return GETPLAYERORIGIN_ERROR;
-}
-
-float getplayeralpha(float pl)
-{
-       entity e;
-
-       e = CSQCModel_server2csqc(pl + 1);
-       if(e)
-               return e.alpha;
-
-       return 1;
+       entity e = CSQCModel_server2csqc(pl + 1);
+       return (e) ? e.alpha : 1;
 }
 
-vector getcsqcplayercolor(float pl)
+// TODO: entcs
+vector getcsqcplayercolor(int pl)
 {
-       entity e;
-
-       e = CSQCModel_server2csqc(pl);
-       if(e)
-       {
-               if(e.colormap > 0)
-                       return colormapPaletteColor(((e.colormap >= 1024) ? e.colormap : stof(getplayerkeyvalue(e.colormap - 1, "colors"))) & 0x0F, true);
-       }
-
-       return '1 1 1';
+       entity e = CSQCModel_server2csqc(pl);
+       return (e && e.colormap > 0) ? colormapPaletteColor(((e.colormap >= 1024) ? e.colormap : stof(getplayerkeyvalue(e.colormap - 1, "colors"))) & 0x0F, true) : '1 1 1';
 }
 
-float getplayerisdead(float pl)
+// TODO: entcs
+bool getplayerisdead(int pl)
 {
-       entity e;
-
-       e = CSQCModel_server2csqc(pl + 1);
-       if(e)
-               return e.csqcmodel_isdead;
-
-       return false;
+       entity e = CSQCModel_server2csqc(pl + 1);
+       return e ? e.csqcmodel_isdead : false;
 }
 
 /** engine callback */
index 60048d0497bdd65279c9ec7f1e57c0551031bab2..520b5e47de7196597d7bae4a198d7b7b741de665 100644 (file)
@@ -143,9 +143,6 @@ void PolyDrawModel(entity e);
 
 void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector rgb, float a, float drawflag);
 
-const vector GETPLAYERORIGIN_ERROR = '1123581321 2357111317 3141592653'; // way out of bounds for anything on the map
-vector getplayerorigin(int pl);
-
 float getplayeralpha(float pl);
 
 vector getcsqcplayercolor(float pl);
index 1e939b77035169aa0fd727d954155c9a4ccb1d45..4a6b587882c744ae15e9c16036025acbbca336d6 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "../common/animdecide.qc"
 #include "../common/effects/effectinfo.qc"
+#include "../common/ent_cs.qc"
 #include "../common/mapinfo.qc"
 #include "../common/movetypes/include.qc"
 #include "../common/net_notice.qc"
index 300521545354cad1a34efbca961a6193b8e8c9a5..0dbffb8747fdda70a032fc4a5797df509ea0d63a 100644 (file)
@@ -8,8 +8,10 @@
 
 #include "../lib/csqcmodel/cl_model.qh"
 
+entity shownames_ent[255];
+
 // self.isactive = player is in range and coordinates/status (health and armor) are up to date
-// self.origin = player origin TODO: should maybe move this so it's the origin of the shownames tag already in SSQC for culling?
+// self.origin = player origin
 // self.healthvalue
 // self.armorvalue
 // self.sameteam = player is on same team as local client
 
 const float SHOWNAMES_FADESPEED = 4;
 const float SHOWNAMES_FADEDELAY = 0.4;
-void Draw_ShowNames(entity ent)
+void Draw_ShowNames(entity this)
 {
-       if(!autocvar_hud_shownames)
-               return;
-
-       if(ent.sv_entnum == player_localentnum) // ent is me or person i'm spectating
-               if(!(autocvar_hud_shownames_self && autocvar_chase_active))
-                       return;
-
-       if(ent.sameteam || (!ent.sameteam && autocvar_hud_shownames_enemies))
+       if (!autocvar_hud_shownames) return;
+       if (this.sv_entnum == player_localentnum)  // self or spectatee
+               if (!(autocvar_hud_shownames_self && autocvar_chase_active)) return;
+       if (!this.sameteam && !autocvar_hud_shownames_enemies) return;
+       bool hit;
+       if (!autocvar_hud_shownames_crosshairdistance && this.sameteam)
        {
-               ent.origin_z += autocvar_hud_shownames_offset;
-
-               float hit;
-               if(ent.sameteam && !autocvar_hud_shownames_crosshairdistance)
-               {
-                       hit = 1;
-               }
-               else
-               {
-                       traceline(view_origin, ent.origin, MOVE_NORMAL, ent);
-                       if(trace_fraction < 1 && (trace_networkentity != ent.sv_entnum && trace_ent.entnum != ent.sv_entnum))
-                               hit = 0;
-                       else
-                               hit = 1;
-               }
-
-               // handle tag fading
-               float overlap = false, onscreen, crosshairdistance;
-               vector o, eo;
-
-               o = project_3d_to_2d(ent.origin);
-
-               if(autocvar_hud_shownames_antioverlap)
+               hit = true;
+       }
+       else
+       {
+               traceline(view_origin, this.origin, MOVE_NORMAL, this);
+               hit = !(trace_fraction < 1 && (trace_networkentity != this.sv_entnum && trace_ent.entnum != this.sv_entnum));
+       }
+       // handle tag fading
+       bool overlap = false;
+       vector o = project_3d_to_2d(this.origin + eZ * autocvar_hud_shownames_offset);
+       float dist = vlen(this.origin - view_origin);
+       if (autocvar_hud_shownames_antioverlap)
+       {
+               // fade tag out if another tag that is closer to you overlaps
+               for (entity e = world; (e = find(e, classname, "shownames_tag")); )
                {
-                       // fade tag out if another tag that is closer to you overlaps
-                       entity e;
-                       for(e = world; (e = find(e, classname, "shownames_tag")); )
+                       if (e == this) continue;
+                       vector eo = project_3d_to_2d(e.origin);
+                       if (eo.z < 0 || eo.x < 0 || eo.y < 0 || eo.x > vid_conwidth || eo.y > vid_conheight) continue;
+                       eo.z = 0;
+                       if (vlen((eX * o.x + eY * o.y) - eo) < autocvar_hud_shownames_antioverlap_distance
+                           && dist > vlen(e.origin - view_origin))
                        {
-                               if(e == ent)
-                                       continue;
-                               eo = project_3d_to_2d(e.origin);
-                               if (!(eo.z < 0 || eo.x < 0 || eo.y < 0 || eo.x > vid_conwidth || eo.y > vid_conheight))
-                               {
-                                       eo.z = 0;
-                                       if(vlen((eX * o.x + eY * o.y) - eo) < autocvar_hud_shownames_antioverlap_distance && vlen(ent.origin - view_origin) > vlen(e.origin - view_origin))
-                                       {
-                                               overlap = true;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-
-               onscreen = (o.z >= 0 && o.x >= 0 && o.y >= 0 && o.x <= vid_conwidth && o.y <= vid_conheight);
-               crosshairdistance = sqrt( pow(o.x - vid_conwidth/2, 2) + pow(o.y - vid_conheight/2, 2) );
-
-               if(autocvar_hud_shownames_crosshairdistance)
-               {
-                       if(autocvar_hud_shownames_crosshairdistance > crosshairdistance)
-                               ent.pointtime = time;
-
-                       if (ent.pointtime + autocvar_hud_shownames_crosshairdistance_time <= time)
                                overlap = true;
-                       else
-                               overlap = (autocvar_hud_shownames_crosshairdistance_antioverlap ? overlap : false); // override what antioverlap says unless allowed by cvar.
-               }
-
-               if(!ent.fadedelay)
-                       ent.fadedelay = time + SHOWNAMES_FADEDELAY;
-
-               if(!ent.sameteam && (!onscreen || !hit)) // out of view, fade out
-               {
-                       ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * frametime);
-                       ent.fadedelay = 0; // reset fade in delay, enemy has left the view
-               }
-               else if(ent.csqcmodel_isdead) // dead player, fade out slowly
-                       ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * 0.25 * frametime);
-               else if(overlap) // tag overlap detected, fade out
-                       ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * frametime);
-               else if(ent.sameteam) // fade in for team mates
-                       ent.alpha = min(1, ent.alpha + SHOWNAMES_FADESPEED * frametime);
-               else if(time > ent.fadedelay) // fade in for enemies
-                       ent.alpha = min(1, ent.alpha + SHOWNAMES_FADESPEED * frametime);
-
-               // multiply by player alpha
-               if(!ent.sameteam || (ent.sv_entnum == player_localentnum))
-                       ent.alpha *= getplayeralpha(ent.sv_entnum-1);
-
-               if(ent.alpha < ALPHA_MIN_VISIBLE && gametype != MAPINFO_TYPE_CTS)
-                       return;
-
-               float dist;
-               dist = vlen(ent.origin - view_origin);
-
-               float a;
-               a = autocvar_hud_shownames_alpha;
-               a *= ent.alpha;
-               if(autocvar_hud_shownames_maxdistance)
-               {
-                       if(dist >= autocvar_hud_shownames_maxdistance)
-                               return;
-                       a *= ((autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance) - max(0, dist - autocvar_hud_shownames_mindistance)) / (autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance);
+                               break;
+                       }
                }
-
-               if(!a)
-                       return;
-
-               float resize;
-               resize = 1;
-               if(autocvar_hud_shownames_resize) // limit resize so its never smaller than 0.5... gets unreadable
-                       resize = 0.5 + 0.5 * ((autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance) - max(0, dist - autocvar_hud_shownames_mindistance)) / (autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance);
-
-               // draw the sprite image
-               if(o.z >= 0)
+       }
+       bool onscreen = (o.z >= 0 && o.x >= 0 && o.y >= 0 && o.x <= vid_conwidth && o.y <= vid_conheight);
+       float crosshairdistance = sqrt(pow(o.x - vid_conwidth / 2, 2) + pow(o.y - vid_conheight / 2, 2));
+       if (autocvar_hud_shownames_crosshairdistance)
+       {
+               if (autocvar_hud_shownames_crosshairdistance > crosshairdistance) this.pointtime = time;
+               if (this.pointtime + autocvar_hud_shownames_crosshairdistance_time <= time) overlap = true;
+               else overlap = (autocvar_hud_shownames_crosshairdistance_antioverlap ? overlap : false); // override what antioverlap says unless allowed by cvar.
+       }
+       if (!this.fadedelay) this.fadedelay = time + SHOWNAMES_FADEDELAY;
+       if (this.csqcmodel_isdead)                                                                   // dead player, fade out slowly
+       {
+               this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * 0.25 * frametime);
+       }
+       else if (!this.sameteam && (!onscreen || !hit)) // out of view, fade out
+       {
+               this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * frametime);
+               this.fadedelay = 0;                         // reset fade in delay, enemy has left the view
+       }
+       else if (overlap)                               // tag overlap detected, fade out
+       {
+               this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * frametime);
+       }
+       else if (this.sameteam)  // fade in for team mates
+       {
+               this.alpha = min(1, this.alpha + SHOWNAMES_FADESPEED * frametime);
+       }
+       else if (time > this.fadedelay)  // fade in for enemies
+       {
+               this.alpha = min(1, this.alpha + SHOWNAMES_FADESPEED * frametime);
+       }
+       float a = autocvar_hud_shownames_alpha * this.alpha;
+       // multiply by player alpha
+       if (!this.sameteam || (this.sv_entnum == player_localentnum))
+       {
+               float f = getplayeralpha(this.sv_entnum - 1);
+               if (f == 0) f = 1;
+               if (f < 0) f = 0;
+               // FIXME: alpha is negative when dead, breaking death fade
+               if (!this.csqcmodel_isdead) a *= f;
+       }
+       if (a < ALPHA_MIN_VISIBLE && gametype != MAPINFO_TYPE_CTS) return;
+       if (autocvar_hud_shownames_maxdistance)
+       {
+               if (dist >= autocvar_hud_shownames_maxdistance) return;
+               float f = autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance;
+               a *= (f - max(0, dist - autocvar_hud_shownames_mindistance)) / f;
+       }
+       if (!a) return;
+       float resize = 1;
+       if (autocvar_hud_shownames_resize)  // limit resize so its never smaller than 0.5... gets unreadable
+       {
+               float f = autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance;
+               resize = 0.5 + 0.5 * (f - max(0, dist - autocvar_hud_shownames_mindistance)) / f;
+       }
+       // draw the sprite image
+       if (o.z >= 0)
+       {
+               o.z = 0;
+               vector mySize = (eX * autocvar_hud_shownames_aspect + eY) * autocvar_hud_shownames_fontsize;
+               vector myPos = o - '0.5 0 0' * mySize.x - '0 1 0' * mySize.y;
+               // size scaling
+               mySize.x *= resize;
+               mySize.y *= resize;
+               myPos.x += 0.5 * (mySize.x / resize - mySize.x);
+               myPos.y += (mySize.y / resize - mySize.y);
+               // this is where the origin of the string
+               vector namepos = myPos;
+               float namewidth = mySize.x;
+               if (autocvar_hud_shownames_status && this.sameteam)
                {
-                       o.z = 0;
-
-                       vector myPos, mySize;
-                       mySize = (eX * autocvar_hud_shownames_aspect + eY) * autocvar_hud_shownames_fontsize;
-                       myPos = o - '0.5 0 0' * mySize.x - '0 1 0' * mySize.y;
-
-                       // size scaling
-                       mySize.x *= resize;
-                       mySize.y *= resize;
-
-                       myPos.x += 0.5 * (mySize.x / resize - mySize.x);
-                       myPos.y += (mySize.y / resize - mySize.y);
-
-                       vector namepos; // this is where the origin of the string
-                       float namewidth;
-
-                       namepos = myPos;
-                       namewidth = mySize.x;
-
-                       if(autocvar_hud_shownames_status && teamplay)
+                       vector v = namepos + '0 1 0' * autocvar_hud_shownames_fontsize * resize;
+                       vector s = eX * 0.5 * mySize.x + eY * resize * autocvar_hud_shownames_statusbar_height;
+                       if (this.healthvalue > 0)
                        {
-                               if(ent.sameteam)
-                               {
-                                       if(ent.healthvalue > 0)
-                                       {
-                                               HUD_Panel_DrawProgressBar(namepos + '0 1 0' * autocvar_hud_shownames_fontsize * resize, eX * 0.5 * mySize.x + eY * resize * autocvar_hud_shownames_statusbar_height, "nametag_statusbar", ent.healthvalue/autocvar_hud_panel_healtharmor_maxhealth, 0, 1, '1 0 0', a, DRAWFLAG_NORMAL);
-
-                                               if(ent.armorvalue > 0)
-                                                       HUD_Panel_DrawProgressBar(namepos + '0 1 0' * autocvar_hud_shownames_fontsize * resize + eX * 0.5 * mySize.x, eX * 0.5 * mySize.x + eY * resize * autocvar_hud_shownames_statusbar_height, "nametag_statusbar", ent.armorvalue/autocvar_hud_panel_healtharmor_maxarmor, 0, 0, '0 1 0', a, DRAWFLAG_NORMAL);
-                                       }
-                               }
+                               HUD_Panel_DrawProgressBar(v, s, "nametag_statusbar",
+                                       this.healthvalue / autocvar_hud_panel_healtharmor_maxhealth, false, 1, '1 0 0', a,
+                                       DRAWFLAG_NORMAL);
+                       }
+                       if (this.armorvalue > 0)
+                       {
+                               HUD_Panel_DrawProgressBar(v + eX * 0.5 * mySize.x, s, "nametag_statusbar",
+                                       this.armorvalue / autocvar_hud_panel_healtharmor_maxarmor, false, 0, '0 1 0', a,
+                                       DRAWFLAG_NORMAL);
                        }
-
-                       string s;
-                       s = GetPlayerName(ent.sv_entnum-1);
-                       if((autocvar_hud_shownames_decolorize == 1 && teamplay) || autocvar_hud_shownames_decolorize == 2)
-                               s = playername(s, GetPlayerColor(ent.sv_entnum-1));
-
-                       drawfontscale = '1 1 0' * resize;
-                       s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
-
-                       float width;
-                       width = stringwidth(s, true, '1 1 0' * autocvar_hud_shownames_fontsize);
-
-                       if (width != namewidth)
-                               namepos.x += (namewidth - width) / 2;
-                       drawcolorcodedstring(namepos, s, '1 1 0' * autocvar_hud_shownames_fontsize, a, DRAWFLAG_NORMAL);
-                       drawfontscale = '1 1 0';
                }
+               string s = GetPlayerName(this.sv_entnum - 1);
+               if ((autocvar_hud_shownames_decolorize == 1 && teamplay)
+                   || autocvar_hud_shownames_decolorize == 2) s = playername(s, GetPlayerColor(this.sv_entnum - 1));
+               drawfontscale = '1 1 0' * resize;
+               s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
+               float width = stringwidth(s, true, '1 1 0' * autocvar_hud_shownames_fontsize);
+               if (width != namewidth) namepos.x += (namewidth - width) / 2;
+               drawcolorcodedstring(namepos, s, '1 1 0' * autocvar_hud_shownames_fontsize, a, DRAWFLAG_NORMAL);
+               drawfontscale = '1 1 0';
        }
 }
 
-entity shownames_ent[255];
 void Draw_ShowNames_All()
 {
-       int i;
-       for(i = 0; i < maxclients; ++i)
+       for (int i = 0; i < maxclients; ++i)
        {
-               float t;
-               t = GetPlayerColor(i);
-               if(t == NUM_SPECTATOR)
-                       continue;
-
-               entity e;
-               e = shownames_ent[i];
-               if(!e)
+               entity e = shownames_ent[i];
+               if (!e)
                {
-                       e = new(shownames_tag);
-                       e.sv_entnum = i+1;
-                       shownames_ent[i] = e;
+                       e = shownames_ent[i] = new(shownames_tag);
+                       e.sv_entnum = i + 1;
                }
-
-               entity entcs;
-               entcs = entcs_receiver[i];
-               if(entcs)
+               entity entcs = entcs_receiver[i];
+               if (entcs.m_entcs_private)
                {
                        e.healthvalue = entcs.healthvalue;
                        e.armorvalue = entcs.armorvalue;
-                       e.sameteam = 1; /* (teamplay && (t == myteam)); */
+                       e.sameteam = true;
                }
                else
                {
-                       e.healthvalue = 2342;
+                       e.healthvalue = 0;
                        e.armorvalue = 0;
-                       e.sameteam = 0;
+                       e.sameteam = false;
                }
-
-               setorigin(e, getplayerorigin(i));
-               if(e.origin == GETPLAYERORIGIN_ERROR)
-                       continue;
-
-               e.csqcmodel_isdead = getplayerisdead(i);
-
+               bool dead = getplayerisdead(i);
+               if (!e.csqcmodel_isdead && entcs.has_origin) setorigin(e, entcs.origin);
+               e.csqcmodel_isdead = dead;
                Draw_ShowNames(e);
        }
 }
index 699e2d8ade41b81b6da5922980f2aa4449849009..11c8f431fd81780fe8a0aa9b3cc47305701a0103 100644 (file)
@@ -359,7 +359,7 @@ float TrueAimCheck()
                        break;
        }
 
-       vector traceorigin = getplayerorigin(player_localentnum-1) + (eZ * getstati(STAT_VIEWHEIGHT));
+       vector traceorigin = entcs_receiver[player_localentnum - 1].origin + (eZ * getstati(STAT_VIEWHEIGHT));
 
        vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
 
index 8d8e8df19fecc4965ebf3242946f04282d972d47..1ea5a8bff56aa213d54992e529f7030bc0a65efc 100644 (file)
@@ -55,7 +55,6 @@ NET_HANDLE(_ENT_CLIENT_INIT, bool isnew) { return true; }
 /** Sent as a temp entity from a persistent linked entity */
 REGISTER_NET_TEMP(ENT_CLIENT_INIT)
 
-REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
 REGISTER_NET_LINKED(ENT_CLIENT_SCORES_INFO)
 REGISTER_NET_LINKED(ENT_CLIENT_SCORES)
 REGISTER_NET_LINKED(ENT_CLIENT_TEAMSCORES)
index cda1a638c44895ef04aea7a27bbaf34448df0815..6b5c2fffedd4b3ccb888bf411aec70f81853882e 100644 (file)
@@ -1,5 +1,6 @@
 #include "casings.qc"
 #include "damageeffects.qc"
 #include "gibs.qc"
+#include "globalsound.qc"
 #include "lightningarc.qc"
 #include "modeleffects.qc"
diff --git a/qcsrc/common/effects/qc/globalsound.qc b/qcsrc/common/effects/qc/globalsound.qc
new file mode 100644 (file)
index 0000000..413df98
--- /dev/null
@@ -0,0 +1,417 @@
+#include "globalsound.qh"
+
+#include "../common/ent_cs.qh"
+
+#ifdef IMPLEMENTATION
+       #include "../../animdecide.qh"
+
+       #ifdef SVQC
+               #include "../../../server/cl_player.qh"
+       #endif
+
+       REGISTER_NET_TEMP(globalsound)
+       REGISTER_NET_TEMP(playersound)
+
+       #ifdef SVQC
+               /**
+                * @param from the source entity, its position is sent
+                * @param gs the global sound def
+                * @param r a random number in 0..1
+                */
+               void globalsound(int channel, entity from, entity gs, float r, int chan, float vol, float atten)
+               {
+                       if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return;
+                       WriteHeader(channel, globalsound);
+                       WriteByte(channel, gs.m_id);
+                       WriteByte(channel, r * 255);
+                       WriteByte(channel, etof(from));
+                       WriteByte(channel, fabs(chan));
+                       WriteByte(channel, floor(vol * 255));
+                       WriteByte(channel, floor(atten * 64));
+                       vector o = from.origin + 0.5 * (from.mins + from.maxs);
+                       WriteCoord(channel, o.x);
+                       WriteCoord(channel, o.y);
+                       WriteCoord(channel, o.z);
+               }
+
+               /**
+               * @param from the source entity, its position is sent
+               * @param ps the player sound def
+               * @param r a random number in 0..1
+               */
+               void playersound(int channel, entity from, entity ps, float r, int chan, float vol, float atten)
+               {
+                       if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return;
+                       WriteHeader(channel, playersound);
+                       WriteByte(channel, ps.m_id);
+                       WriteByte(channel, r * 255);
+                       WriteByte(channel, etof(from));
+                       WriteByte(channel, fabs(chan));
+                       WriteByte(channel, floor(vol * 255));
+                       WriteByte(channel, floor(atten * 64));
+                       entcs_force_origin(from);
+                       vector o = from.origin + 0.5 * (from.mins + from.maxs);
+                       WriteCoord(channel, o.x);
+                       WriteCoord(channel, o.y);
+                       WriteCoord(channel, o.z);
+               }
+       #endif
+
+       string GlobalSound_sample(string pair, float r);
+
+       #ifdef CSQC
+
+               NET_HANDLE(globalsound, bool isnew)
+               {
+                       entity gs = GlobalSounds_from(ReadByte());
+                       float r = ReadByte() / 255;
+                       string sample = GlobalSound_sample(gs.m_globalsoundstr, r);
+                       int who = ReadByte();
+                       int chan = ReadByte();
+                       float vol = ReadByte() / 255;
+                       float atten = ReadByte() / 64;
+                       vector o;
+                       o.x = ReadCoord();
+                       o.y = ReadCoord();
+                       o.z = ReadCoord();
+                       if (who == player_currententnum)
+                       {
+                               // client knows better, play at current position to unlag
+                               entity e = findfloat(world, entnum, who);
+                               sound7(e, chan, sample, vol, atten, 0, 0);
+                       }
+                       else
+                       {
+                               entity e = new(globalsound);
+                               e.origin = o;
+                               sound8(e, o, chan, sample, vol, atten, 0, 0);
+                               remove(e);  // debug with: e.think = SUB_Remove; e.nextthink = time + 1;
+                       }
+                       return true;
+               }
+
+               NET_HANDLE(playersound, bool isnew)
+               {
+                       entity ps = PlayerSounds_from(ReadByte());
+                       float r = ReadByte() / 255;
+                       int who = ReadByte();
+                       entity e = entcs_receiver[who - 1];
+                       UpdatePlayerSounds(e);
+                       string s = e.(ps.m_playersoundfld);
+                       string sample = GlobalSound_sample(s, r);
+                       int chan = ReadByte();
+                       float vol = ReadByte() / 255;
+                       float atten = ReadByte() / 64;
+                       vector o;
+                       o.x = ReadCoord();
+                       o.y = ReadCoord();
+                       o.z = ReadCoord();
+                       if (e)
+                       {
+                               // TODO: for non-visible players, origin should probably continue to be updated as long as the sound is playing
+                               e.origin = o;
+                               sound7(e, chan, sample, vol, atten, 0, 0);
+                       }
+                       else
+                       {
+                           LOG_WARNINGF("Missing entcs data for player %i\n", e);
+                // Can this happen?
+                               entity e = new(playersound);
+                               e.origin = o;
+                               sound8(e, o, chan, sample, vol, atten, 0, 0);
+                               remove(e);  // debug with: e.think = SUB_Remove; e.nextthink = time + 1;
+                       }
+                       return true;
+               }
+
+       #endif
+
+       string GlobalSound_sample(string pair, float r)
+       {
+               int n;
+               {
+                       string s = cdr(pair);
+                       if (s) n = stof(s);
+                       else n = 0;
+               }
+               string sample = car(pair);
+               if (n > 0) sample = sprintf("%s%d.wav", sample, floor(r * n + 1));  // randomization
+               else sample = sprintf("%s.wav", sample);
+               return sample;
+       }
+
+       void PrecacheGlobalSound(string sample)
+       {
+               int n;
+               {
+                       string s = cdr(sample);
+                       if (s) n = stof(s);
+                       else n = 0;
+               }
+               sample = car(sample);
+               if (n > 0)
+               {
+                       for (int i = 1; i <= n; ++i)
+                               precache_sound(sprintf("%s%d.wav", sample, i));
+               }
+               else
+               {
+                       precache_sound(sprintf("%s.wav", sample));
+               }
+       }
+
+       entity GetVoiceMessage(string type)
+       {
+               FOREACH(PlayerSounds, it.m_playersoundstr == type && it.instanceOfVoiceMessage == true, LAMBDA(return it));
+               return NULL;
+       }
+
+       entity GetPlayerSound(string type)
+       {
+               FOREACH(PlayerSounds, it.m_playersoundstr == type && it.instanceOfVoiceMessage == false, LAMBDA(return it));
+               return NULL;
+       }
+
+       string allvoicesamples;
+       STATIC_INIT(allvoicesamples)
+       {
+               FOREACH(PlayerSounds, it.instanceOfVoiceMessage, LAMBDA(
+                       allvoicesamples = strcat(allvoicesamples, " ", it.m_playersoundstr)
+                                                                          ));
+               allvoicesamples = strzone(substring(allvoicesamples, 1, -1));
+       }
+
+       .string _GetPlayerSoundSampleField(string type, bool voice)
+       {
+               GetPlayerSoundSampleField_notFound = false;
+               entity e = voice ? GetVoiceMessage(type) : GetPlayerSound(type);
+               if (e) return e.m_playersoundfld;
+               GetPlayerSoundSampleField_notFound = true;
+               return playersound_taunt.m_playersoundfld;
+       }
+
+       .string GetVoiceMessageSampleField(string type)
+       {
+               return _GetPlayerSoundSampleField(type, true);
+       }
+
+       void PrecachePlayerSounds(string f)
+       {
+               int fh = fopen(f, FILE_READ);
+               if (fh < 0)
+               {
+                       LOG_WARNINGF("Player sound file not found: %s\n", f);
+                       return;
+               }
+               for (string s; (s = fgets(fh)); )
+               {
+                       int n = tokenize_console(s);
+                       if (n != 3)
+                       {
+                               if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s);
+                               continue;
+                       }
+                       string file = argv(1);
+                       string variants = argv(2);
+                       PrecacheGlobalSound(strcat(file, " ", variants));
+               }
+               fclose(fh);
+       }
+
+       #ifdef CSQC
+
+               .string GetPlayerSoundSampleField(string type)
+               {
+                       return _GetPlayerSoundSampleField(type, false);
+               }
+
+               void ClearPlayerSounds(entity this)
+               {
+                       FOREACH(PlayerSounds, true, LAMBDA(
+                               .string fld = it.m_playersoundfld;
+                               if (this.(fld))
+       {
+               strunzone(this.(fld));
+               this.(fld) = string_null;
+       }
+                                                             ));
+               }
+
+               bool LoadPlayerSounds(entity this, string f, bool strict)
+               {
+                       int fh = fopen(f, FILE_READ);
+                       if (fh < 0)
+                       {
+                               if (strict) LOG_WARNINGF("Player sound file not found: %s\n", f);
+                               return false;
+                       }
+                       for (string s; (s = fgets(fh)); )
+                       {
+                               int n = tokenize_console(s);
+                               if (n != 3)
+                               {
+                                       if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s);
+                                       continue;
+                               }
+                               string key = argv(0);
+                               var.string field = GetPlayerSoundSampleField(key);
+                               if (GetPlayerSoundSampleField_notFound) field = GetVoiceMessageSampleField(key);
+                               if (GetPlayerSoundSampleField_notFound)
+                               {
+                                       LOG_TRACEF("Invalid sound info field: %s\n", key);
+                                       continue;
+                               }
+                               string file = argv(1);
+                               string variants = argv(2);
+                               if (this.(field)) strunzone(this.(field));
+                               this.(field) = strzone(strcat(file, " ", variants));
+                       }
+                       fclose(fh);
+                       return true;
+               }
+
+               .string model_for_playersound;
+               .int skin_for_playersound;
+
+               bool autocvar_g_debug_defaultsounds;
+
+               void UpdatePlayerSounds(entity this)
+               {
+                       if (this.model == this.model_for_playersound && this.skin == this.skin_for_playersound) return;
+                       if (this.model_for_playersound) strunzone(this.model_for_playersound);
+                       this.model_for_playersound = strzone(this.model);
+                       this.skin_for_playersound = this.skin;
+                       ClearPlayerSounds(this);
+                       LoadPlayerSounds(this, "sound/player/default.sounds", true);
+                       if (this.model == "null" || autocvar_g_debug_defaultsounds) return;
+                       if (LoadPlayerSounds(this, get_model_datafilename(this.model, this.skin, "sounds"), false)) return;
+                       LoadPlayerSounds(this, get_model_datafilename(this.model, 0, "sounds"), true);
+               }
+
+       #endif
+
+       #ifdef SVQC
+
+               void _GlobalSound(entity gs, entity ps, string sample, int chan, int voicetype, bool fake)
+               {
+                       SELFPARAM();
+                       if (gs == NULL && ps == NULL && sample == "") return;
+                       float r = random();
+                       if (sample != "") sample = GlobalSound_sample(sample, r);
+                       switch (voicetype)
+                       {
+                               case VOICETYPE_LASTATTACKER_ONLY:
+                               case VOICETYPE_LASTATTACKER:
+                               {
+                                       if (!fake)
+                                       {
+                                               if (!this.pusher) break;
+                                               msg_entity = this.pusher;
+                                               if (IS_REAL_CLIENT(msg_entity))
+                                               {
+                                                       float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE;
+                                                       if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASEVOICE, atten);
+                                                       else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASEVOICE, atten);
+                                                       else soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten);
+                                               }
+                                       }
+                                       if (voicetype == VOICETYPE_LASTATTACKER_ONLY) break;
+                                       msg_entity = this;
+                                       if (IS_REAL_CLIENT(msg_entity))
+                                       {
+                                               if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASE, ATTEN_NONE);
+                                               else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASE, ATTEN_NONE);
+                                               else soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NONE);
+                                       }
+                                       break;
+                               }
+                               case VOICETYPE_TEAMRADIO:
+                               {
+                                       #define X() \
+                                               do \
+                                               { \
+                                                       float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE; \
+                                                       if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASEVOICE, atten); \
+                                                       else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASEVOICE, atten); \
+                                                       else soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); \
+                                               } \
+                                               while (0)
+
+                                       if (fake) { msg_entity = this; X(); }
+                                       else
+                                       {
+                                               FOR_EACH_REALCLIENT(msg_entity)
+                                               {
+                                                       if (!teamplay || msg_entity.team == this.team) X();
+                                               }
+                                       }
+               #undef X
+                                       break;
+                               }
+                               case VOICETYPE_AUTOTAUNT:
+                               case VOICETYPE_TAUNT:
+                               {
+                                       if (voicetype == VOICETYPE_AUTOTAUNT) if (!sv_autotaunt) { break; }else {}
+                                       else if (IS_PLAYER(this) && this.deadflag == DEAD_NO) animdecide_setaction(this, ANIMACTION_TAUNT,
+                                                       true);
+                                       if (!sv_taunt) break;
+                                       if (autocvar_sv_gentle) break;
+                                       float tauntrand = 0;
+                                       if (voicetype == VOICETYPE_AUTOTAUNT) tauntrand = random();
+                                       #define X() \
+                                               do \
+                                               { \
+                                                       if (voicetype != VOICETYPE_AUTOTAUNT || tauntrand < msg_entity.cvar_cl_autotaunt) \
+                                                       { \
+                                                               float atten = (msg_entity.cvar_cl_voice_directional >= 1) \
+                                                                   ? bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, \
+                                                                       ATTEN_MAX) \
+                                                                       : ATTEN_NONE; \
+                                                               if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASEVOICE, atten); \
+                                                               else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASEVOICE, atten); \
+                                                               else soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); \
+                                                       } \
+                                               } \
+                                               while (0)
+                                       if (fake)
+                                       {
+                                               msg_entity = this;
+                                               X();
+                                       }
+                                       else
+                                       {
+                                               FOR_EACH_REALCLIENT(msg_entity)
+                                               {
+                                                       X();
+                                               }
+                                       }
+               #undef X
+                                       break;
+                               }
+                               case VOICETYPE_PLAYERSOUND:
+                               {
+                                       msg_entity = this;
+                                       if (fake)
+                                       {
+                                               if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASE, ATTEN_NORM);
+                                               else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASE, ATTEN_NORM);
+                                               else soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NORM);
+                                       }
+                                       else
+                                       {
+                                               if (gs) globalsound(MSG_ALL, this, gs, r, chan, VOL_BASE, ATTEN_NORM);
+                                               else if (ps) playersound(MSG_ALL, this, ps, r, chan, VOL_BASE, ATTEN_NORM);
+                                               else _sound(this, chan, sample, VOL_BASE, ATTEN_NORM);
+                                       }
+                                       break;
+                               }
+                               default:
+                               {
+                                       backtrace("Invalid voice type!");
+                                       break;
+                               }
+                       }
+               }
+
+       #endif
+#endif
diff --git a/qcsrc/common/effects/qc/globalsound.qh b/qcsrc/common/effects/qc/globalsound.qh
new file mode 100644 (file)
index 0000000..e8baf1b
--- /dev/null
@@ -0,0 +1,145 @@
+#ifndef GLOBALSOUND_H
+#define GLOBALSOUND_H
+
+// player sounds, voice messages
+
+.string m_playersoundstr;
+..string m_playersoundfld;
+
+REGISTRY(PlayerSounds, BITS(8) - 1)
+#define PlayerSounds_from(i) _PlayerSounds_from(i, NULL)
+#define REGISTER_PLAYERSOUND(id) \
+       .string _playersound_##id; \
+       REGISTER(PlayerSounds, playersound, id, m_id, new(PlayerSound)) \
+       { \
+               make_pure(this); \
+               this.m_playersoundstr = #id; \
+               this.m_playersoundfld = _playersound_##id; \
+       }
+REGISTER_REGISTRY(PlayerSounds)
+REGISTRY_SORT(PlayerSounds, 0)
+STATIC_INIT(PlayerSounds_renumber)
+{
+       FOREACH(PlayerSounds, true, LAMBDA(it.m_id = i));
+}
+REGISTRY_CHECK(PlayerSounds)
+
+// TODO implement fall and falling
+
+REGISTER_PLAYERSOUND(death)
+REGISTER_PLAYERSOUND(drown)
+REGISTER_PLAYERSOUND(fall)
+REGISTER_PLAYERSOUND(falling)
+REGISTER_PLAYERSOUND(gasp)
+REGISTER_PLAYERSOUND(jump)
+REGISTER_PLAYERSOUND(pain100)
+REGISTER_PLAYERSOUND(pain25)
+REGISTER_PLAYERSOUND(pain50)
+REGISTER_PLAYERSOUND(pain75)
+
+.bool instanceOfVoiceMessage;
+.int m_playersoundvt;
+#define REGISTER_VOICEMSG(id, vt) \
+       .string _playersound_##id; \
+       REGISTER(PlayerSounds, playersound, id, m_id, new(VoiceMessage)) \
+       { \
+               make_pure(this); \
+               this.instanceOfVoiceMessage = true; \
+               this.m_playersoundstr = #id; \
+               this.m_playersoundfld = _playersound_##id; \
+               this.m_playersoundvt = vt; \
+       }
+
+const int VOICETYPE_PLAYERSOUND = 10;
+const int VOICETYPE_TEAMRADIO = 11;
+const int VOICETYPE_LASTATTACKER = 12;
+const int VOICETYPE_LASTATTACKER_ONLY = 13;
+const int VOICETYPE_AUTOTAUNT = 14;
+const int VOICETYPE_TAUNT = 15;
+
+REGISTER_VOICEMSG(attack, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(attackinfive, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(coverme, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(defend, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(freelance, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(incoming, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(meet, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(needhelp, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(seenflag, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(taunt, VOICETYPE_TAUNT)
+REGISTER_VOICEMSG(teamshoot, VOICETYPE_LASTATTACKER)
+
+// reserved sound names for the future (some models lack sounds for them):
+// _VOICEMSG(flagcarriertakingdamage)
+// _VOICEMSG(getflag)
+// reserved sound names for the future (ALL models lack sounds for them):
+// _VOICEMSG(affirmative)
+// _VOICEMSG(attacking)
+// _VOICEMSG(defending)
+// _VOICEMSG(roaming)
+// _VOICEMSG(onmyway)
+// _VOICEMSG(droppedflag)
+// _VOICEMSG(negative)
+// _VOICEMSG(seenenemy)
+
+.string m_globalsoundstr;
+REGISTRY(GlobalSounds, BITS(8) - 1)
+#define GlobalSounds_from(i) _GlobalSounds_from(i, NULL)
+#define REGISTER_GLOBALSOUND(id, str) \
+       REGISTER(GlobalSounds, GS, id, m_id, new(GlobalSound)) \
+       { \
+               make_pure(this); \
+               this.m_globalsoundstr = str; \
+       }
+REGISTER_REGISTRY(GlobalSounds)
+REGISTRY_SORT(GlobalSounds, 0)
+STATIC_INIT(GlobalSounds_renumber)
+{
+       FOREACH(GlobalSounds, true, LAMBDA(it.m_id = i));
+}
+REGISTRY_CHECK(GlobalSounds)
+void PrecacheGlobalSound(string samplestring);
+PRECACHE(GlobalSounds)
+{
+       FOREACH(GlobalSounds, true, LAMBDA(PrecacheGlobalSound(it.m_globalsoundstr)));
+}
+
+REGISTER_GLOBALSOUND(STEP, "misc/footstep0 6")
+REGISTER_GLOBALSOUND(STEP_METAL, "misc/metalfootstep0 6")
+REGISTER_GLOBALSOUND(FALL, "misc/hitground 4")
+REGISTER_GLOBALSOUND(FALL_METAL, "misc/metalhitground 4")
+
+bool GetPlayerSoundSampleField_notFound;
+void PrecachePlayerSounds(string f);
+#ifdef CSQC
+       .string GetVoiceMessageSampleField(string type);
+       .string GetPlayerSoundSampleField(string type);
+       void ClearPlayerSounds(entity this);
+       float LoadPlayerSounds(entity this, string f, bool strict);
+       void UpdatePlayerSounds(entity this);
+#endif
+
+#ifdef SVQC
+
+       void _GlobalSound(entity gs, entity ps, string sample, float chan, float voicetype, bool fake);
+       #define GlobalSound(def, chan, voicetype) _GlobalSound(def, NULL, string_null, chan, voicetype, false)
+       #define GlobalSound_string(def, chan, voicetype) _GlobalSound(NULL, NULL, def, chan, voicetype, false)
+       #define PlayerSound(def, chan, voicetype) _GlobalSound(NULL, def, string_null, chan, voicetype, false)
+       #define VoiceMessage(def, msg) \
+               do \
+               { \
+                       entity VM = def; \
+                       int voicetype = VM.m_playersoundvt; \
+                       bool ownteam = (voicetype == VOICETYPE_TEAMRADIO); \
+                       int flood = Say(this, ownteam, world, msg, true); \
+                       bool fake; \
+                       if (IS_SPEC(this) || IS_OBSERVER(this) || flood < 0) fake = true; \
+                       else if (flood > 0) fake = false; \
+                       else break; \
+                       _GlobalSound(NULL, VM, string_null, CH_VOICE, voicetype, fake); \
+               } \
+               while (0)
+
+#endif
+
+#endif
diff --git a/qcsrc/common/ent_cs.qc b/qcsrc/common/ent_cs.qc
new file mode 100644 (file)
index 0000000..e016dd3
--- /dev/null
@@ -0,0 +1,165 @@
+#include "ent_cs.qh"
+
+// #define PROP(public, fld, sv, cl)
+#define ENTCS_NETPROPS(PROP) \
+       PROP(true, sv_entnum, \
+       { WriteByte(MSG_ENTITY, etof(player) - 1); }, \
+       { this.sv_entnum = ReadByte(); }) \
+    \
+       PROP(false, origin, \
+       { WriteShort(MSG_ENTITY, this.origin.x);  WriteShort(MSG_ENTITY, this.origin.y); \
+         WriteShort(MSG_ENTITY, this.origin.z); }, \
+       { this.has_origin = true; vector v; v.x = ReadShort(); v.y = ReadShort(); v.z = ReadShort(); setorigin(this, v); }) \
+    \
+       PROP(false, angles_y, \
+       { WriteByte(MSG_ENTITY, this.angles.y / 360 * 256); }, \
+       { vector v = '0 0 0'; v.y = ReadByte() / 256 * 360; this.angles = v; }) \
+    \
+       PROP(false, health, \
+       { WriteByte(MSG_ENTITY, this.health / 10);  /* FIXME: use a better scale? */ }, \
+       { this.healthvalue = ReadByte() * 10; }) \
+    \
+       PROP(false, armorvalue, \
+       { WriteByte(MSG_ENTITY, this.armorvalue / 10);  /* FIXME: use a better scale? */ }, \
+       { this.armorvalue = ReadByte() * 10; }) \
+    \
+       PROP(true, netname, \
+       { WriteString(MSG_ENTITY, this.netname); }, \
+       { if (this.netname) strunzone(this.netname); this.netname = strzone(ReadString()); }) \
+    \
+       PROP(true, model, \
+       { WriteString(MSG_ENTITY, this.model); }, \
+       { if (this.model) strunzone(this.model); this.model = strzone(ReadString()); }) \
+    \
+       PROP(true, skin, \
+       { WriteByte(MSG_ENTITY, this.skin); }, \
+       { this.skin = ReadByte(); }) \
+    \
+       /**/
+
+#ifdef SVQC
+
+       int ENTCS_PUBLICMASK = 0;
+       STATIC_INIT(ENTCS_PUBLICMASK)
+       {
+               int i = 1;
+               #define X(public, fld, sv, cl) { if (public) ENTCS_PUBLICMASK |= BIT(i); } i += 1;
+               ENTCS_NETPROPS(X);
+       #undef X
+               if (i >= BITS(16 - 1)) LOG_FATAL("Exceeded ENTCS_NETPROPS limit");
+       }
+
+       bool entcs_customize()
+       {
+               SELFPARAM();
+               entity player = this.owner;
+               return IS_PLAYER(player)             // player must be active
+                      && player.deadflag == DEAD_NO // player must be alive
+               ;
+       }
+
+       bool entcs_send(entity this, entity to, int sf)
+       {
+               entity player = this.owner;
+               sf |= 1;
+               if (IS_PLAYER(to) || to.caplayer)                                  // unless spectating,
+               {
+                       bool same_team = (to == player) || (teamplay && player.team == to.team);
+                       if (!same_team && !radar_showennemies) sf &= ENTCS_PUBLICMASK; // no private updates
+               }
+               sf |= this.m_forceupdate;
+               this.m_forceupdate = 0;
+               WriteHeader(MSG_ENTITY, ENT_CLIENT_ENTCS);
+               WriteShort(MSG_ENTITY, sf);
+               int i = 1;
+               #define X(public, fld, sv, cl) { if (sf & BIT(i)) sv; } i += 1;
+               ENTCS_NETPROPS(X);
+       #undef X
+               return true;
+       }
+
+       void entcs_think()
+       {
+               SELFPARAM();
+               this.nextthink = time + 0.033333333333;  // TODO: increase this to like 0.15 once the client can do smoothing
+               entity o = this.owner;
+               int i = 1;
+               #define X(public, fld, sv, cl) \
+                       if (o.fld != this.fld) \
+                       { \
+                               this.fld = o.fld; \
+                               this.SendFlags |= BIT(i); \
+                       } \
+                       i += 1;
+               ENTCS_NETPROPS(X);
+       #undef X
+       }
+
+       void entcs_attach(entity player)
+       {
+               entity e = player.entcs = new(entcs_sender);
+               make_pure(e);
+               e.owner = player;
+               e.think = entcs_think;
+               e.nextthink = time;
+               Net_LinkEntity(e, false, 0, entcs_send);
+               e.customizeentityforclient = entcs_customize;
+       }
+
+       void entcs_detach(entity player)
+       {
+               if (!player.entcs) return;
+               remove(player.entcs);
+               player.entcs = NULL;
+       }
+
+#endif
+
+#ifdef CSQC
+
+       void Ent_RemoveEntCS()
+       {
+               SELFPARAM();
+               entcs_receiver[this.sv_entnum] = NULL;
+       }
+
+       void entcs_think()
+       {
+               SELFPARAM();
+               this.nextthink = time;
+               entity e = CSQCModel_server2csqc(this.sv_entnum + 1);
+               bool exists = !!e;
+               if (exists)
+               {
+                       this.has_origin = true;
+                       this.origin = e.origin;
+                       // `cl_forceplayermodels 1` sounds will be wrong until the player has been in the PVS, but so be it
+                       this.model = e.model;
+               }
+       }
+
+       NET_HANDLE(ENT_CLIENT_ENTCS, bool isnew)
+       {
+               if (isnew)
+               {
+                       make_pure(this);
+                       this.classname = "entcs_receiver";
+                       this.entremove = Ent_RemoveEntCS;
+                       this.think = entcs_think;
+                       this.nextthink = time;
+               }
+               InterpolateOrigin_Undo();
+               int sf = ReadShort();
+               this.has_origin = false;
+               this.m_entcs_private = boolean(sf & 1);
+               int i = 1;
+               #define X(public, fld, sv, cl) { if (sf & BIT(i)) cl; } i += 1;
+               ENTCS_NETPROPS(X);
+       #undef X
+               entcs_receiver[this.sv_entnum] = this;
+               this.iflags |= IFLAG_ORIGIN;
+               InterpolateOrigin_Note();
+               return true;
+       }
+
+#endif
diff --git a/qcsrc/common/ent_cs.qh b/qcsrc/common/ent_cs.qh
new file mode 100644 (file)
index 0000000..598ff05
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef ENT_CS_H
+#define ENT_CS_H
+
+REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
+
+/** True when private information such as origin is available */
+.bool m_entcs_private;
+
+/** True when a recent origin is available */
+.bool has_origin;
+
+#ifdef SVQC
+/**
+ * The point of these entities is to avoid the problems
+ * with clientprediction.
+ * If you add SendEntity to players, the engine will not
+ * do any prediction anymore, and you'd have to write the whole
+ * prediction code in CSQC, you want that? :P
+ * Data can depend on gamemode. For now, it serves as GPS entities
+ * in onslaught... YAY ;)
+ */
+
+.entity entcs;
+
+bool entcs_customize();
+
+bool entcs_send(entity this, entity to, int sf);
+
+void entcs_think();
+
+void entcs_attach(entity e);
+
+void entcs_detach(entity e);
+
+.int m_forceupdate;
+
+/** Force an origin update, for player sounds */
+#define entcs_force_origin(e) ((e).entcs.m_forceupdate = BIT(2))
+
+#endif
+
+#ifdef CSQC
+
+entity entcs_receiver[255]; // 255 is the engine limit on maxclients
+#define entcs_is_self(e) ((e).sv_entnum + 1 == player_localentnum)
+
+#endif
+
+#endif
index 64ef0581de63f521a6063cd9e2c4754c24fc99c2..7ee3e3eab72d84228fe2360e7d46a8137ede8fe1 100644 (file)
@@ -346,7 +346,7 @@ void Monster_Sound(.string samplefield, float sound_delay, float delaytoo, float
        if(delaytoo)
        if(time < self.msound_delay)
                return; // too early
-       _GlobalSound(self.(samplefield), chan, VOICETYPE_PLAYERSOUND, false);
+       GlobalSound_string(self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
 
        self.msound_delay = time + sound_delay;
 }
index a49f79df833d9d1652cae099adada98937d134a7..ad5f13808637f592d46ecdea365092b7a5813c71 100644 (file)
@@ -1100,27 +1100,19 @@ void PM_check_frozen()
 void PM_check_hitground()
 {SELFPARAM();
 #ifdef SVQC
-       if (IS_ONGROUND(self))
-       if (IS_PLAYER(self)) // no fall sounds for observers thank you very much
-       if (self.wasFlying)
-       {
-               self.wasFlying = 0;
-               if (self.waterlevel < WATERLEVEL_SWIMMING)
-               if (time >= self.ladder_time)
-               if (!self.hook)
-               {
-                       self.nextstep = time + 0.3 + random() * 0.1;
-                       trace_dphitq3surfaceflags = 0;
-                       tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
-                       if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
-                       {
-                               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
-                                       GlobalSound(GS_FALL_METAL, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                               else
-                                       GlobalSound(GS_FALL, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                       }
-               }
-       }
+       if (!IS_PLAYER(this)) return; // no fall sounds for observers thank you very much
+       if (!IS_ONGROUND(this)) return;
+       if (!this.wasFlying) return;
+    this.wasFlying = false;
+    if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
+    if (time < this.ladder_time) return;
+    if (this.hook) return;
+    this.nextstep = time + 0.3 + random() * 0.1;
+    trace_dphitq3surfaceflags = 0;
+    tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
+    if ((trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS)) return;
+    entity fall = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS) ? GS_FALL_METAL : GS_FALL;
+    GlobalSound(fall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
 #endif
 }
 
index 36bdaa833085db167c5190b946d7a701e5592faa..503290b6c03f916fbd0972eba1f767cef0360e5c 100644 (file)
@@ -1,22 +1,29 @@
 #ifndef SOUND_H
 #define SOUND_H
 
+// negative = SVQC autochannels
+// positive = one per entity
+
 const int CH_INFO = 0;
-const int CH_TRIGGER = -3;
 const int CH_WEAPON_A = -1;
+const int CH_WEAPON_B = -1;
 const int CH_WEAPON_SINGLE = 1;
 const int CH_VOICE = -2;
-const int CH_BGM_SINGLE = 8;
-const int CH_AMBIENT = -9;
+// const int CH_VOICE_SINGLE = 2;
+const int CH_TRIGGER = -3;
 const int CH_TRIGGER_SINGLE = 3;
 const int CH_SHOTS = -4;
 const int CH_SHOTS_SINGLE = 4;
-const int CH_WEAPON_B = -1;
+// const int CH_TUBA = -5;
+const int CH_TUBA_SINGLE = 5;
 const int CH_PAIN = -6;
 const int CH_PAIN_SINGLE = 6;
 const int CH_PLAYER = -7;
 const int CH_PLAYER_SINGLE = 7;
-const int CH_TUBA_SINGLE = 5;
+// const int CH_BGM_SINGLE = -8;
+const int CH_BGM_SINGLE = 8;
+const int CH_AMBIENT = -9;
+// const int CH_AMBIENT_SINGLE = 9;
 
 const float ATTEN_NONE = 0;
 const float ATTEN_MIN = 0.015625;
index b873e62388d1c5f19755a9d3c6f5b0da5cdc63a0..749237fa311b9c70c6c6e97714d946e908536926 100644 (file)
@@ -1227,7 +1227,7 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                else
                {
                        // use player origin so that third person display still works
-                       self.origin = getplayerorigin(player_localnum) + ('0 0 1' * getstati(STAT_VIEWHEIGHT));
+                       self.origin = entcs_receiver[player_localnum].origin + ('0 0 1' * getstati(STAT_VIEWHEIGHT));
                }
        }
 
index 5a683f54c2562b3d3f6091cd6724e6529d700ec8..7a43a49ebf630029d5b2196ee4fe0c71b36f985c 100644 (file)
 
 #ifdef CSQC
        #define REGISTER_NET_LINKED(id) \
-               [[accumulate]] NET_HANDLE(id, bool) \
+               [[accumulate]] NET_HANDLE(id, bool isnew) \
                { \
                        this = self; \
                        this.sourceLocFile = __FILE__; \
                        this.sourceLocLine = __LINE__; \
+                       if (!this) isnew = true; \
                } \
                REGISTER(LinkedEntities, NET, id, m_id, new(net_linked_packet)) \
                { \
index 50339a73038121a5b8541200be0aede37db6bd1a..0f898c3401b1b41df7b15ad1bcc717600f4a8002 100644 (file)
@@ -576,8 +576,6 @@ bool WarpZoneLib_BadEntity(entity e)
        if (is_pure(e)) return true;
        switch (s)
        {
-               case "entcs_sender":
-               case "entcs_receiver":
                // case "net_linked": // actually some real entities are linked without classname, fail
                case "":
                        return true;
index 6cd7e2395a2acd17b62a8862691e62c7d52e6298..c271b65b49523721b47972de15f7a6caf9e6b8de 100644 (file)
@@ -437,7 +437,6 @@ bool autocvar_waypoint_benchmark;
 float autocvar_sv_gameplayfix_gravityunaffectedbyticrate;
 bool autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag;
 float autocvar_g_trueaim_minrange;
-bool autocvar_g_debug_defaultsounds;
 float autocvar_g_grab_range;
 int autocvar_g_max_info_autoscreenshot;
 bool autocvar_physics_ode;
index 24a63d5aab0e8823b07b5fec3eb73dba70528d7c..26d089245f4822a15966f7505dc68bc3a54ccf74 100644 (file)
@@ -3,7 +3,6 @@
 #include "anticheat.qh"
 #include "cl_impulse.qh"
 #include "cl_player.qh"
-#include "ent_cs.qh"
 #include "ipban.qh"
 #include "miscfunctions.qh"
 #include "portals.qh"
@@ -23,6 +22,7 @@
 #include "bot/bot.qh"
 #include "bot/navigation.qh"
 
+#include "../common/ent_cs.qh"
 #include "../common/vehicles/all.qh"
 #include "../common/triggers/teleporters.qh"
 
@@ -175,7 +175,6 @@ void setplayermodel(entity e, string modelname)
        precache_model(modelname);
        _setmodel(e, modelname);
        player_setupanimsformodel();
-       UpdatePlayerSounds(e);
 }
 
 /*
@@ -405,7 +404,6 @@ void FixPlayermodel(entity player)
        if(chmdl || oldskin != player.skin) // model or skin has changed
        {
                player.species = player_getspecies(player); // update species
-               UpdatePlayerSounds(player); // update skin sounds
        }
 
        if(!teamplay)
@@ -1180,7 +1178,7 @@ void ClientConnect ()
        else
                stuffcmd(self, "set _teams_available 0\n");
 
-       attach_entcs(self);
+       entcs_attach(self);
 
        bot_relinkplayerlist();
 
@@ -1266,7 +1264,7 @@ void ClientDisconnect ()
 
        bot_clientdisconnect();
 
-       detach_entcs(self);
+       entcs_detach(self);
 
        if(autocvar_sv_eventlog)
                GameLogEcho(strcat(":part:", ftos(self.playerid)));
@@ -1307,8 +1305,6 @@ void ClientDisconnect ()
        if(self.weaponorder_byimpulse)
                strunzone(self.weaponorder_byimpulse);
 
-       ClearPlayerSounds(self);
-
        if(self.personal)
                remove(self.personal);
 
index b49488b0553701cb528de71fd1261c0326c38e65..a9a5d03cbe2e93965f73b25e603cfbc31a5f5288 100644 (file)
@@ -959,282 +959,3 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo
 
        return ret;
 }
-
-int GetVoiceMessageVoiceType(string type)
-{
-       if (type == "taunt") return VOICETYPE_TAUNT;
-       if (type == "teamshoot") return VOICETYPE_LASTATTACKER;
-       return VOICETYPE_TEAMRADIO;
-}
-
-.string GetVoiceMessageSampleField(string type)
-{
-       GetPlayerSoundSampleField_notFound = false;
-       switch (type)
-       {
-#define X(m) case #m: return playersound_##m;
-               ALLVOICEMSGS(X)
-#undef X
-       }
-       GetPlayerSoundSampleField_notFound = true;
-       return playersound_taunt;
-}
-
-.string GetPlayerSoundSampleField(string type)
-{
-       GetPlayerSoundSampleField_notFound = false;
-       switch (type)
-       {
-#define X(m) case #m: return playersound_##m;
-               ALLPLAYERSOUNDS(X)
-#undef X
-       }
-       GetPlayerSoundSampleField_notFound = true;
-       return playersound_taunt;
-}
-
-void PrecacheGlobalSound(string sample)
-{
-       int n;
-       {
-               string s = cdr(sample);
-               if (s) n = stof(s);
-               else n = 0;
-       }
-       sample = car(sample);
-       if (n > 0)
-       {
-               for (int i = 1; i <= n; ++i)
-                       precache_sound(sprintf("%s%d.wav", sample, i));
-       }
-       else
-       {
-               precache_sound(sprintf("%s.wav", sample));
-       }
-}
-
-string allvoicesamples;
-
-void PrecachePlayerSounds(string f)
-{
-       int fh = fopen(f, FILE_READ);
-       if (fh < 0)
-       {
-               LOG_WARNINGF("Player sound file not found: %s\n", f);
-               return;
-       }
-       for (string s; (s = fgets(fh)); )
-       {
-               int n = tokenize_console(s);
-               if (n != 3)
-               {
-                       if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s);
-                       continue;
-               }
-               string file = argv(1);
-               string variants = argv(2);
-               PrecacheGlobalSound(strcat(file, " ", variants));
-       }
-       fclose(fh);
-
-       if (!allvoicesamples)
-       {
-#define X(m) allvoicesamples = strcat(allvoicesamples, " ", #m);
-               ALLVOICEMSGS(X)
-#undef X
-               allvoicesamples = strzone(substring(allvoicesamples, 1, -1));
-       }
-}
-
-void ClearPlayerSounds(entity this)
-{
-#define X(m) if (this.playersound_##m) { strunzone(this.playersound_##m); this.playersound_##m = string_null; }
-       ALLPLAYERSOUNDS(X)
-       ALLVOICEMSGS(X)
-#undef X
-}
-
-bool LoadPlayerSounds(string f, bool strict)
-{
-       SELFPARAM();
-       int fh = fopen(f, FILE_READ);
-       if (fh < 0)
-       {
-               if (strict) LOG_WARNINGF("Player sound file not found: %s\n", f);
-               return false;
-       }
-       for (string s; (s = fgets(fh)); )
-       {
-               int n = tokenize_console(s);
-               if (n != 3)
-               {
-                       if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s);
-                       continue;
-               }
-               string key = argv(0);
-               var .string field = GetPlayerSoundSampleField(key);
-               if (GetPlayerSoundSampleField_notFound) field = GetVoiceMessageSampleField(key);
-               if (GetPlayerSoundSampleField_notFound)
-               {
-                       LOG_TRACEF("Invalid sound info field: %s\n", key);
-                       continue;
-               }
-               string file = argv(1);
-               string variants = argv(2);
-               if (self.(field)) strunzone(self.(field));
-               self.(field) = strzone(strcat(file, " ", variants));
-       }
-       fclose(fh);
-       return true;
-}
-
-.int modelindex_for_playersound;
-.int skin_for_playersound;
-
-void UpdatePlayerSounds(entity this)
-{
-       if (this.modelindex == this.modelindex_for_playersound && this.skin == this.skin_for_playersound) return;
-       this.modelindex_for_playersound = this.modelindex;
-       this.skin_for_playersound = this.skin;
-       ClearPlayerSounds(this);
-       LoadPlayerSounds("sound/player/default.sounds", true);
-       if (autocvar_g_debug_defaultsounds) return;
-       if (!LoadPlayerSounds(get_model_datafilename(this.model, this.skin, "sounds"), false))
-               LoadPlayerSounds(get_model_datafilename(this.model, 0, "sounds"), true);
-}
-
-void _GlobalSound(string sample, int chan, int voicetype, bool fake)
-{
-       SELFPARAM();
-       if (sample == "") return;
-       int n;
-       {
-               string s = cdr(sample);
-               if (s) n = stof(s);
-               else n = 0;
-       }
-       sample = car(sample);
-       if (n > 0) sample = sprintf("%s%d.wav", sample, floor(random() * n + 1));  // randomization
-       else sample = sprintf("%s.wav", sample);
-       switch (voicetype)
-       {
-               case VOICETYPE_LASTATTACKER_ONLY:
-               case VOICETYPE_LASTATTACKER:
-               {
-                       if (!fake)
-                       {
-                               if (!this.pusher) break;
-                               msg_entity = this.pusher;
-                               if (IS_REAL_CLIENT(msg_entity))
-                               {
-                                       float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE;
-                                       soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten);
-                               }
-                       }
-                       if (voicetype == VOICETYPE_LASTATTACKER_ONLY) break;
-                       msg_entity = this;
-                       if (IS_REAL_CLIENT(msg_entity)) soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NONE);
-                       break;
-               }
-               case VOICETYPE_TEAMRADIO:
-               {
-                       #define X() \
-                               do \
-                               { \
-                                       float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE; \
-                                       soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); \
-                               } \
-                               while (0)
-
-                       if (fake) { msg_entity = this; X(); }
-                       else
-                       {
-                               FOR_EACH_REALCLIENT(msg_entity)
-                               {
-                                       if (!teamplay || msg_entity.team == this.team) X();
-                               }
-                       }
-                       #undef X
-                       break;
-               }
-               case VOICETYPE_AUTOTAUNT:
-               case VOICETYPE_TAUNT:
-               {
-                       if (voicetype == VOICETYPE_AUTOTAUNT) if (!sv_autotaunt) { break; }else {}
-                       else if (IS_PLAYER(this) && this.deadflag == DEAD_NO) animdecide_setaction(this, ANIMACTION_TAUNT, true);
-                       if (!sv_taunt) break;
-                       if (autocvar_sv_gentle) break;
-                       float tauntrand = 0;
-                       if (voicetype == VOICETYPE_AUTOTAUNT) tauntrand = random();
-                       #define X() \
-                               do \
-                               { \
-                                       if (voicetype != VOICETYPE_AUTOTAUNT || tauntrand < msg_entity.cvar_cl_autotaunt) \
-                                       { \
-                                               float atten = (msg_entity.cvar_cl_voice_directional >= 1) \
-                                                   ? bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTEN_MAX) \
-                                                       : ATTEN_NONE; \
-                                               soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); \
-                                       } \
-                               } \
-                               while (0)
-                       if (fake)
-                       {
-                               msg_entity = this;
-                               X();
-                       }
-                       else
-                       {
-                               FOR_EACH_REALCLIENT(msg_entity)
-                               {
-                                       X();
-                               }
-                       }
-                       #undef X
-                       break;
-               }
-               case VOICETYPE_PLAYERSOUND:
-               {
-                       if (fake)
-                       {
-                               msg_entity = this;
-                               soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NORM);
-                       }
-                       else
-                       {
-                               _sound(this, chan, sample, VOL_BASE, ATTEN_NORM);
-                       }
-                       break;
-               }
-               default:
-               {
-                       backtrace("Invalid voice type!");
-                       break;
-               }
-       }
-}
-
-void PlayerSound(.string samplefield, int chan, float voicetype)
-{
-       SELFPARAM();
-       _GlobalSound(this.(samplefield), chan, voicetype, false);
-}
-
-void VoiceMessage(string type, string msg)
-{
-       SELFPARAM();
-       var .string sample = GetVoiceMessageSampleField(type);
-       if (GetPlayerSoundSampleField_notFound)
-       {
-               sprint(this, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples));
-               return;
-       }
-       int voicetype = GetVoiceMessageVoiceType(type);
-       bool ownteam = (voicetype == VOICETYPE_TEAMRADIO);
-       int flood = Say(this, ownteam, world, msg, true);
-       bool fake;
-       if (IS_SPEC(this) || IS_OBSERVER(this) || flood < 0) fake = true;
-       else if (flood > 0) fake = false;
-       else return;
-       _GlobalSound(this.(sample), CH_VOICE, voicetype, fake);
-}
index 37bc06310b0d2af80a1d7295f1b2072b41bda189..e55b1c6147fac06acf8af7e1b6bed992e73bc96e 100644 (file)
@@ -39,86 +39,4 @@ void PlayerDamage(entity inflictor, entity attacker, float damage, int deathtype
 .float muted;
 int Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol);
 
-// player sounds, voice messages
-// TODO implemented fall and falling
-#define ALLPLAYERSOUNDS(X) \
-       X(death) \
-       X(drown) \
-       X(fall) \
-       X(falling) \
-       X(gasp) \
-       X(jump) \
-       X(pain100) \
-       X(pain25) \
-       X(pain50) \
-       X(pain75)
-
-#define ALLVOICEMSGS(X) \
-       X(attack) \
-       X(attackinfive) \
-       X(coverme) \
-       X(defend) \
-       X(freelance) \
-       X(incoming) \
-       X(meet) \
-       X(needhelp) \
-       X(seenflag) \
-       X(taunt) \
-       X(teamshoot)
-
-// reserved sound names for the future (some models lack sounds for them):
-// _VOICEMSG(flagcarriertakingdamage)
-// _VOICEMSG(getflag)
-// reserved sound names for the future (ALL models lack sounds for them):
-// _VOICEMSG(affirmative)
-// _VOICEMSG(attacking)
-// _VOICEMSG(defending)
-// _VOICEMSG(roaming)
-// _VOICEMSG(onmyway)
-// _VOICEMSG(droppedflag)
-// _VOICEMSG(negative)
-// _VOICEMSG(seenenemy)
-
-#define X(m) .string playersound_##m;
-ALLPLAYERSOUNDS(X)
-ALLVOICEMSGS(X)
-#undef X
-
-bool GetPlayerSoundSampleField_notFound;
-float GetVoiceMessageVoiceType(string type);
-.string GetVoiceMessageSampleField(string type);
-.string GetPlayerSoundSampleField(string type);
-void PrecacheGlobalSound(string samplestring);
-void PrecachePlayerSounds(string f);
-void ClearPlayerSounds(entity this);
-float LoadPlayerSounds(string f, bool strict);
-void UpdatePlayerSounds(entity this);
-#define FakeGlobalSound(sample, chan, voicetype) _GlobalSound(sample, chan, voicetype, true)
-void _GlobalSound(string sample, float chan, float voicetype, bool fake);
-#define GlobalSound(def, chan, voicetype) _GlobalSound((def).m_globalsoundstr, chan, voicetype, false)
-void PlayerSound(.string samplefield, float chan, float voicetype);
-void VoiceMessage(string type, string msg);
-
-.string m_globalsoundstr;
-REGISTRY(GlobalSounds, BITS(8) - 1)
-#define GlobalSounds_from(i) _GlobalSounds_from(i, NULL)
-#define REGISTER_GLOBALSOUND(id, str) \
-       REGISTER(GlobalSounds, GS, id, m_id, new(GlobalSound)) \
-       { \
-               make_pure(this); \
-               this.m_globalsoundstr = str; \
-       }
-REGISTER_REGISTRY(GlobalSounds)
-REGISTRY_SORT(GlobalSounds)
-REGISTRY_CHECK(GlobalSounds)
-PRECACHE(GlobalSounds)
-{
-       FOREACH(GlobalSounds, true, LAMBDA(PrecacheGlobalSound(it.m_globalsoundstr)));
-}
-
-REGISTER_GLOBALSOUND(STEP, "misc/footstep0 6")
-REGISTER_GLOBALSOUND(STEP_METAL, "misc/metalfootstep0 6")
-REGISTER_GLOBALSOUND(FALL, "misc/hitground 4")
-REGISTER_GLOBALSOUND(FALL_METAL, "misc/metalhitground 4")
-
 #endif
index ac21bc62dcc61b6ff73d68350ae9cafa38699b4c..6cac1c4f0620fb5a224e6d8dd2c0a5a39a865873 100644 (file)
@@ -601,8 +601,14 @@ void ClientCommand_voice(float request, float argc, string command)
                {
                        if (argv(1) != "")
                        {
-                               if (argc >= 3) VoiceMessage(argv(1), substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
-                               else VoiceMessage(argv(1), "");
+                               entity e = GetVoiceMessage(argv(1));
+                               if (!e)
+                               {
+                                       sprint(this, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples));
+                                       return;
+                               }
+                               if (argc >= 3) VoiceMessage(e, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
+                               else VoiceMessage(e, "");
 
                                return;
                        }
index 23855b603a27887487c013097b701cf686337793..c04acac1593aa6bb8880c9ea77bf96d2b0ffcc64 100644 (file)
@@ -301,13 +301,6 @@ float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end)
 
 float next_pingtime;
 
-const float VOICETYPE_PLAYERSOUND = 10;
-const float VOICETYPE_TEAMRADIO = 11;
-const float VOICETYPE_LASTATTACKER = 12;
-const float VOICETYPE_LASTATTACKER_ONLY = 13;
-const float VOICETYPE_AUTOTAUNT = 14;
-const float VOICETYPE_TAUNT = 15;
-
 // autotaunt system
 .float cvar_cl_autotaunt;
 .float cvar_cl_voice_directional;
diff --git a/qcsrc/server/ent_cs.qc b/qcsrc/server/ent_cs.qc
deleted file mode 100644 (file)
index 9c98e7d..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-#include "ent_cs.qh"
-
-float entcs_customize()
-{
-       SELFPARAM();
-       entity o = self.owner;
-       if(o.deadflag != DEAD_NO)
-               return false;
-       if (!IS_PLAYER(o))
-               return false;
-       if(other == o)
-               return false;
-       if((IS_PLAYER(other)) || other.caplayer)
-               if(!teamplay || o.team != other.team)
-                       if (!radar_showennemies)
-                               return false;
-       return true;
-}
-
-bool entcs_send(entity this, entity to, int sf)
-{
-       WriteHeader(MSG_ENTITY, ENT_CLIENT_ENTCS);
-       WriteByte(MSG_ENTITY, sf);
-       if(sf & BIT(0))
-               WriteByte(MSG_ENTITY, num_for_edict(self.owner) - 1);
-       if(sf & BIT(1))
-       {
-               WriteShort(MSG_ENTITY, self.origin.x);
-               WriteShort(MSG_ENTITY, self.origin.y);
-               WriteShort(MSG_ENTITY, self.origin.z);
-       }
-       if(sf & BIT(2))
-               WriteByte(MSG_ENTITY, self.angles.y * 256.0 / 360);
-       if(sf & BIT(3))
-               WriteByte(MSG_ENTITY, self.health / 10); // FIXME use a better scale?
-       if(sf & BIT(4))
-               WriteByte(MSG_ENTITY, self.armorvalue / 10); // FIXME use a better scale?
-       return true;
-}
-
-void entcs_think()
-{
-       SELFPARAM();
-       self.nextthink = time + 0.033333333333; // increase this to like 0.15 once the client can do smoothing
-       entity o = self.owner;
-       if (o.origin != self.origin)
-       {
-               setorigin(self, o.origin);
-               self.SendFlags |= BIT(1);
-       }
-       if (o.angles.y != self.angles.y)
-       {
-               self.angles = o.angles;
-               self.SendFlags |= BIT(2);
-       }
-       if (o.health != self.health)
-       {
-               self.health = o.health;
-               self.SendFlags |= BIT(3);
-       }
-       if (o.armorvalue != self.armorvalue)
-       {
-               self.armorvalue = o.armorvalue;
-               self.SendFlags |= BIT(4);
-       }
-}
-
-entity attach_entcs(entity e)
-{
-       entity ent = e.entcs = new(entcs_sender);
-       make_pure(ent);
-       ent.owner = e;
-       ent.think = entcs_think;
-       ent.nextthink = time;
-
-       Net_LinkEntity(ent, false, 0, entcs_send);
-       ent.customizeentityforclient = entcs_customize;
-
-       return ent;
-}
-
-void detach_entcs(entity e)
-{
-       if (!e.entcs) return;
-       remove(e.entcs);
-       e.entcs = NULL;
-}
diff --git a/qcsrc/server/ent_cs.qh b/qcsrc/server/ent_cs.qh
deleted file mode 100644 (file)
index 1cfc854..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef ENT_CS_H
-#define ENT_CS_H
-
-/**
- * The point of these entities is to avoid the problems
- * with clientprediction.
- * If you add SendEntity to players, the engine will not
- * do any prediction anymore, and you'd have to write the whole
- * prediction code in CSQC, you want that? :P
- * Data can depend on gamemode. For now, it serves as GPS entities
- * in onslaught... YAY ;)
- */
-
-.entity entcs;
-
-float entcs_customize();
-
-bool entcs_send(entity this, entity to, int sf);
-
-void entcs_think();
-
-entity attach_entcs(entity e);
-
-void detach_entcs(entity e);
-
-#endif
index 8c874044faa42db0b81096576ccb4bfb2a2c032b..f03b2e7ceb15dbac4f831b5839a3c97116141055 100644 (file)
@@ -703,7 +703,6 @@ void readplayerstartcvars()
        warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
 }
 
-void PrecachePlayerSounds(string f);
 void precache_playermodel(string m)
 {
        float globhandle, i, n;
index 08a9d4d22b14f1ff50540d4f2e64ee7862f03f40..e23909812d27dd6494ace3e26b6a9aa42ce49d7a 100644 (file)
@@ -10,7 +10,6 @@
 #include "cl_client.qc"
 #include "cl_impulse.qc"
 #include "cl_player.qc"
-#include "ent_cs.qc"
 #include "g_damage.qc"
 #include "g_hook.qc"
 // #include "g_lights.qc" // TODO: was never used
@@ -58,6 +57,7 @@
 #include "../common/campaign_file.qc"
 #include "../common/campaign_setup.qc"
 #include "../common/effects/effectinfo.qc"
+#include "../common/ent_cs.qc"
 #include "../common/mapinfo.qc"
 #include "../common/minigames/minigames.qc"
 #include "../common/minigames/sv_minigames.qc"