const int SP_DMGTAKEN = 11;
// game mode specific indices are not in common/, but in server/scores_rules.qc!
-const int CH_INFO = 0;
-const int CH_TRIGGER = -3;
-const int CH_WEAPON_A = -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_TRIGGER_SINGLE = 3;
-const int CH_SHOTS = -4;
-const int CH_SHOTS_SINGLE = 4;
-const int CH_WEAPON_B = -1;
-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 float ATTEN_NONE = 0;
-const float ATTEN_MIN = 0.015625;
-const float ATTEN_NORM = 0.5;
-const float ATTEN_LARGE = 1;
-const float ATTEN_IDLE = 2;
-const float ATTEN_STATIC = 3;
-const float ATTEN_MAX = 3.984375;
-
-const float VOL_BASE = 0.7;
-const float VOL_BASEVOICE = 1.0;
-
// WEAPONTODO: move this into separate/new projectile handling code // this sets sounds and other properties of the projectiles in csqc
const int PROJECTILE_ELECTRO = 1;
const int PROJECTILE_ROCKET = 2;
{
WriteHeader(MSG_ENTITY, ENT_CLIENT_INVENTORY);
entity e = self.owner;
- if (/*IS_SPEC(e)*/ (e.classname == "spectator")) e = e.enemy;
+ if (IS_SPEC(e)) e = e.enemy;
Inventory data = e.inventory;
Inventory_Write(data);
return true;
entity _item = self;
entity e;
- FOR_EACH_SPEC(e)
+ FOR_EACH_CLIENT(e) if (IS_SPEC(e) || IS_OBSERVER(e))
{
setself(e);
if(self.superspec_flags & SSF_ITEMMSG)
--- /dev/null
+#ifdef SVQC
+
+bool autocvar_bot_sound_monopoly;
+
+.entity realowner;
+bool sound_allowed(int to, entity e)
+{
+ for ( ; ; )
+ {
+ if (e.classname == "body") e = e.enemy;
+ else if (e.realowner && e.realowner != e) e = e.realowner;
+ else if (e.owner && e.owner != e) e = e.owner;
+ else break;
+ }
+ // sounds to self may always pass
+ if (to == MSG_ONE && e == msg_entity) return true;
+ // sounds by players can be removed
+ if (autocvar_bot_sound_monopoly && IS_REAL_CLIENT(e)) return false;
+ // anything else may pass
+ return true;
+}
+
+/** hack: string precache_sound(string s) = #19; */
+int precache_sound_index(string s) = #19;
+
+const int SVC_SOUND = 6;
+const int SVC_STOPSOUND = 16;
+
+const int SND_VOLUME = BIT(0);
+const int SND_ATTENUATION = BIT(1);
+const int SND_LARGEENTITY = BIT(3);
+const int SND_LARGESOUND = BIT(4);
+
+void soundtoat(int to, entity e, vector o, int chan, string samp, float vol, float attenu)
+{
+ if (!sound_allowed(to, e)) return;
+ int entno = etof(e);
+ int idx = precache_sound_index(samp);
+ attenu = floor(attenu * 64);
+ vol = floor(vol * 255);
+ int sflags = 0;
+ if (vol != 255) sflags |= SND_VOLUME;
+ if (attenu != 64) sflags |= SND_ATTENUATION;
+ if (entno >= 8192 || chan < 0 || chan > 7) sflags |= SND_LARGEENTITY;
+ if (idx >= 256) sflags |= SND_LARGESOUND;
+ WriteByte(to, SVC_SOUND);
+ WriteByte(to, sflags);
+ if (sflags & SND_VOLUME) WriteByte(to, vol);
+ if (sflags & SND_ATTENUATION) WriteByte(to, attenu);
+ if (sflags & SND_LARGEENTITY)
+ {
+ WriteShort(to, entno);
+ WriteByte(to, chan);
+ }
+ else
+ {
+ WriteShort(to, (entno << 3) | chan);
+ }
+ if (sflags & SND_LARGESOUND) WriteShort(to, idx);
+ else WriteByte(to, idx);
+ WriteCoord(to, o.x);
+ WriteCoord(to, o.y);
+ WriteCoord(to, o.z);
+}
+
+void soundto(int _dest, entity e, int chan, string samp, float vol, float _atten)
+{
+ if (!sound_allowed(_dest, e)) return;
+ vector o = e.origin + 0.5 * (e.mins + e.maxs);
+ soundtoat(_dest, e, o, chan, samp, vol, _atten);
+}
+void soundat(entity e, vector o, int chan, string samp, float vol, float _atten)
+{
+ soundtoat(((chan & 8) ? MSG_ALL : MSG_BROADCAST), e, o, chan, samp, vol, _atten);
+}
+void stopsoundto(int _dest, entity e, int chan)
+{
+ if (!sound_allowed(_dest, e)) return;
+ int entno = num_for_edict(e);
+ if (entno >= 8192 || chan < 0 || chan > 7)
+ {
+ int idx = precache_sound_index(SND(Null));
+ int sflags = SND_LARGEENTITY;
+ if (idx >= 256) sflags |= SND_LARGESOUND;
+ WriteByte(_dest, SVC_SOUND);
+ WriteByte(_dest, sflags);
+ WriteShort(_dest, entno);
+ WriteByte(_dest, chan);
+ if (sflags & SND_LARGESOUND) WriteShort(_dest, idx);
+ else WriteByte(_dest, idx);
+ WriteCoord(_dest, e.origin.x);
+ WriteCoord(_dest, e.origin.y);
+ WriteCoord(_dest, e.origin.z);
+ }
+ else
+ {
+ WriteByte(_dest, SVC_STOPSOUND);
+ WriteShort(_dest, entno * 8 + chan);
+ }
+}
+void stopsound(entity e, int chan)
+{
+ if (!sound_allowed(MSG_BROADCAST, e)) return;
+ stopsoundto(MSG_BROADCAST, e, chan); // unreliable, gets there fast
+ stopsoundto(MSG_ALL, e, chan); // in case of packet loss
+}
+
+void play2(entity e, string filename)
+{
+ msg_entity = e;
+ soundtoat(MSG_ONE, world, '0 0 0', CH_INFO, filename, VOL_BASE, ATTEN_NONE);
+}
+
+.float spamtime;
+/** use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame) */
+float spamsound(entity e, int chan, string samp, float vol, float _atten)
+{
+ if (!sound_allowed(MSG_BROADCAST, e)) return false;
+ if (time > e.spamtime)
+ {
+ e.spamtime = time;
+ _sound(e, chan, samp, vol, _atten);
+ return true;
+ }
+ return false;
+}
+
+void play2team(float t, string filename)
+{
+ if (autocvar_bot_sound_monopoly) return;
+ entity head;
+ FOR_EACH_REALPLAYER(head)
+ {
+ if (head.team == t) play2(head, filename);
+ }
+}
+
+void play2all(string samp)
+{
+ if (autocvar_bot_sound_monopoly) return;
+ _sound(world, CH_INFO, samp, VOL_BASE, ATTEN_NONE);
+}
+
+#endif
SOUND(Null, "misc/null");
#include "all.inc"
-
+#include "all.qc"
#endif
#ifndef SOUND_H
#define SOUND_H
+const int CH_INFO = 0;
+const int CH_TRIGGER = -3;
+const int CH_WEAPON_A = -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_TRIGGER_SINGLE = 3;
+const int CH_SHOTS = -4;
+const int CH_SHOTS_SINGLE = 4;
+const int CH_WEAPON_B = -1;
+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 float ATTEN_NONE = 0;
+const float ATTEN_MIN = 0.015625;
+const float ATTEN_NORM = 0.5;
+const float ATTEN_LARGE = 1;
+const float ATTEN_IDLE = 2;
+const float ATTEN_STATIC = 3;
+const float ATTEN_MAX = 3.984375;
+
+const float VOL_BASE = 0.7;
+const float VOL_BASEVOICE = 1.0;
+
// Play all sounds via sound7, for access to the extra channels.
// Otherwise, channels 8 to 15 would be blocked for a weird QW feature.
#ifdef SVQC
#endif
#define sound(e, c, s, v, a) _sound(e, c, Sound_fixpath(s), v, a)
+/**
+ * because sound7 didn't have origin
+ *
+ * @param e sound owner
+ * @param o sound origin
+ * @param chan sound channel
+ * @param samp sound filename
+ * @param vol sound volume
+ * @param atten sound attenuation
+ * @param speed
+ * @param sf
+ */
+#define sound8(e, o, chan, samp, vol, atten, speed, sf) \
+ do \
+ { \
+ entity __e = e; \
+ vector old_origin = __e.origin; \
+ vector old_mins = __e.mins; \
+ vector old_maxs = __e.maxs; \
+ setorigin(__e, o); \
+ setsize(__e, '0 0 0', '0 0 0'); \
+ sound7(__e, chan, samp, vol, atten, speed, sf); \
+ setorigin(__e, old_origin); \
+ setsize(__e, old_mins, old_maxs); \
+ } \
+ while (0)
+
CLASS(Sound, Object)
ATTRIB(Sound, m_id, int, 0)
ATTRIB(Sound, sound_str, string(), func_null)
#define Sound_fixpath(this) _Sound_fixpath((this).sound_str())
string _Sound_fixpath(string base)
{
- if (base == "") return string_null;
- #define extensions(x) \
- x(wav) \
- x(ogg) \
- x(flac) \
- /**/
- string full, relative;
- #define tryext(ext) { if (fexists(full = strcat("sound/", relative = strcat(base, "." #ext)))) break; }
- do
- {
- extensions(tryext);
+ if (base == "") return string_null;
+ #define extensions(x) \
+ x(wav) \
+ x(ogg) \
+ x(flac) \
+ /**/
+ string full, relative;
+ #define tryext(ext) { if (fexists(full = strcat("sound/", relative = strcat(base, "." #ext)))) break; }
+ do
+ {
+ extensions(tryext);
#undef tryext
#undef extensions
- LOG_WARNINGF("Missing sound: \"%s\"\n", full);
- return string_null;
- }
- while (0);
- return relative;
+ LOG_WARNINGF("Missing sound: \"%s\"\n", full);
+ return string_null;
+ }
+ while (0);
+ return relative;
}
METHOD(Sound, sound_precache, void(entity this))
{
#ifndef SERVER_ALL_H
#define SERVER_ALL_H
+int maxclients;
+
+const string STR_PLAYER = "player";
+const string STR_SPECTATOR = "spectator";
+const string STR_OBSERVER = "observer";
+
+#define IS_PLAYER(v) ((v).classname == STR_PLAYER)
+#define IS_SPEC(v) ((v).classname == STR_SPECTATOR)
+#define IS_OBSERVER(v) ((v).classname == STR_OBSERVER)
+
+#define IS_CLIENT(v) (v.flags & FL_CLIENT)
+#define IS_BOT_CLIENT(v) (clienttype(v) == CLIENTTYPE_BOT)
+#define IS_REAL_CLIENT(v) (clienttype(v) == CLIENTTYPE_REAL)
+#define IS_NOT_A_CLIENT(v) (clienttype(v) == CLIENTTYPE_NOTACLIENT)
+
+#define IS_MONSTER(v) (v.flags & FL_MONSTER)
+#define IS_VEHICLE(v) (v.vehicle_flags & VHF_ISVEHICLE)
+#define IS_TURRET(v) (v.turret_flags & TUR_FLAG_ISTURRET)
+
+#define FOR_EACH_CLIENTSLOT(v) for (v = world; (v = nextent(v)) && (num_for_edict(v) <= maxclients); )
+#define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if (IS_CLIENT(v))
+#define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if (IS_REAL_CLIENT(v))
+
+#define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if (IS_PLAYER(v))
+#define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if (IS_SPEC(v))
+#define FOR_EACH_OBSERVER(v) FOR_EACH_CLIENT(v) if (IS_OBSERVER(v))
+#define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if (IS_PLAYER(v))
+
+#define FOR_EACH_MONSTER(v) for (v = world; (v = findflags(v, flags, FL_MONSTER)) != world; )
+
#include "../common/effects/all.qh"
#include "../common/models/all.qh"
#include "../common/sounds/all.qh"
bool autocvar_bot_nofire;
#define autocvar_bot_number cvar("bot_number")
#define autocvar_bot_prefix cvar_string("bot_prefix")
-bool autocvar_bot_sound_monopoly;
#define autocvar_bot_suffix cvar_string("bot_suffix")
bool autocvar_bot_usemodelnames;
int autocvar_bot_vs_human;
const int FL_SPAWNING = BIT(18);
const int FL_PICKUPITEMS = BIT(19);
-const int SVC_SOUND = 6;
-const int SVC_STOPSOUND = 16;
const int SVC_SETVIEW = 5;
const int RESPAWN_FORCE = 1;
float team1_score, team2_score, team3_score, team4_score;
-float maxclients;
-
// flag set on worldspawn so that the code knows if it is dedicated or not
float server_is_dedicated;
warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
}
-float sound_allowed(float destin, entity e)
-{
- // sounds from world may always pass
- for (;;)
- {
- if (e.classname == "body")
- e = e.enemy;
- else if (e.realowner && e.realowner != e)
- e = e.realowner;
- else if (e.owner && e.owner != e)
- e = e.owner;
- else
- break;
- }
- // sounds to self may always pass
- if (destin == MSG_ONE)
- if (e == msg_entity)
- return true;
- // sounds by players can be removed
- if (autocvar_bot_sound_monopoly)
- if (IS_REAL_CLIENT(e))
- return false;
- // anything else may pass
- return true;
-}
-
-void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float attenu)
-{
- float entno, idx;
-
- if (!sound_allowed(_dest, e))
- return;
-
- entno = num_for_edict(e);
- idx = precache_sound_index(samp);
-
- int sflags;
- sflags = 0;
-
- attenu = floor(attenu * 64);
- vol = floor(vol * 255);
-
- if (vol != 255)
- sflags |= SND_VOLUME;
- if (attenu != 64)
- sflags |= SND_ATTENUATION;
- if (entno >= 8192 || chan < 0 || chan > 7)
- sflags |= SND_LARGEENTITY;
- if (idx >= 256)
- sflags |= SND_LARGESOUND;
-
- WriteByte(_dest, SVC_SOUND);
- WriteByte(_dest, sflags);
- if (sflags & SND_VOLUME)
- WriteByte(_dest, vol);
- if (sflags & SND_ATTENUATION)
- WriteByte(_dest, attenu);
- if (sflags & SND_LARGEENTITY)
- {
- WriteShort(_dest, entno);
- WriteByte(_dest, chan);
- }
- else
- {
- WriteShort(_dest, entno * 8 + chan);
- }
- if (sflags & SND_LARGESOUND)
- WriteShort(_dest, idx);
- else
- WriteByte(_dest, idx);
-
- WriteCoord(_dest, o.x);
- WriteCoord(_dest, o.y);
- WriteCoord(_dest, o.z);
-}
-void soundto(float _dest, entity e, float chan, string samp, float vol, float _atten)
-{
- vector o;
-
- if (!sound_allowed(_dest, e))
- return;
-
- o = e.origin + 0.5 * (e.mins + e.maxs);
- soundtoat(_dest, e, o, chan, samp, vol, _atten);
-}
-void soundat(entity e, vector o, float chan, string samp, float vol, float _atten)
-{
- soundtoat(((chan & 8) ? MSG_ALL : MSG_BROADCAST), e, o, chan, samp, vol, _atten);
-}
-void stopsoundto(float _dest, entity e, float chan)
-{
- float entno;
-
- if (!sound_allowed(_dest, e))
- return;
-
- entno = num_for_edict(e);
-
- if (entno >= 8192 || chan < 0 || chan > 7)
- {
- float idx, sflags;
- idx = precache_sound_index(SND(Null));
- sflags = SND_LARGEENTITY;
- if (idx >= 256)
- sflags |= SND_LARGESOUND;
- WriteByte(_dest, SVC_SOUND);
- WriteByte(_dest, sflags);
- WriteShort(_dest, entno);
- WriteByte(_dest, chan);
- if (sflags & SND_LARGESOUND)
- WriteShort(_dest, idx);
- else
- WriteByte(_dest, idx);
- WriteCoord(_dest, e.origin.x);
- WriteCoord(_dest, e.origin.y);
- WriteCoord(_dest, e.origin.z);
- }
- else
- {
- WriteByte(_dest, SVC_STOPSOUND);
- WriteShort(_dest, entno * 8 + chan);
- }
-}
-void stopsound(entity e, float chan)
-{
- if (!sound_allowed(MSG_BROADCAST, e))
- return;
-
- stopsoundto(MSG_BROADCAST, e, chan); // unreliable, gets there fast
- stopsoundto(MSG_ALL, e, chan); // in case of packet loss
-}
-
-void play2(entity e, string filename)
-{
- //stuffcmd(e, strcat("play2 ", filename, "\n"));
- msg_entity = e;
- soundtoat(MSG_ONE, world, '0 0 0', CH_INFO, filename, VOL_BASE, ATTEN_NONE);
-}
-
-// use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame)
-.float spamtime;
-float spamsound(entity e, float chan, string samp, float vol, float _atten)
-{
- if (!sound_allowed(MSG_BROADCAST, e))
- return false;
-
- if (time > e.spamtime)
- {
- e.spamtime = time;
- _sound(e, chan, samp, vol, _atten);
- return true;
- }
- return false;
-}
-
-void play2team(float t, string filename)
-{
- entity head;
-
- if (autocvar_bot_sound_monopoly)
- return;
-
- FOR_EACH_REALPLAYER(head)
- {
- if (head.team == t)
- play2(head, filename);
- }
-}
-
-void play2all(string samp)
-{
- if (autocvar_bot_sound_monopoly)
- return;
-
- _sound(world, CH_INFO, samp, VOL_BASE, ATTEN_NONE);
-}
-
void PrecachePlayerSounds(string f);
void precache_playermodel(string m)
{
#define PROJECTILE_TOUCH if(WarpZone_Projectile_Touch()) return
-const string STR_PLAYER = "player";
-const string STR_SPECTATOR = "spectator";
-const string STR_OBSERVER = "observer";
-
-#define IS_PLAYER(v) ((v).classname == STR_PLAYER)
-#define IS_SPEC(v) ((v).classname == STR_SPECTATOR)
-#define IS_OBSERVER(v) ((v).classname == STR_OBSERVER)
-#define IS_CLIENT(v) (v.flags & FL_CLIENT)
-#define IS_BOT_CLIENT(v) (clienttype(v) == CLIENTTYPE_BOT)
-#define IS_REAL_CLIENT(v) (clienttype(v) == CLIENTTYPE_REAL)
-#define IS_NOT_A_CLIENT(v) (clienttype(v) == CLIENTTYPE_NOTACLIENT)
-
-#define IS_MONSTER(v) (v.flags & FL_MONSTER)
-#define IS_VEHICLE(v) (v.vehicle_flags & VHF_ISVEHICLE)
-#define IS_TURRET(v) (v.turret_flags & TUR_FLAG_ISTURRET)
-
-#define FOR_EACH_CLIENTSLOT(v) for(v = world; (v = nextent(v)) && (num_for_edict(v) <= maxclients); )
-#define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(IS_CLIENT(v))
-#define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(IS_REAL_CLIENT(v))
-
-#define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(IS_PLAYER(v))
-#define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if (!IS_PLAYER(v)) // Samual: shouldn't this be IS_SPEC(v)? and rather create a separate macro to include observers too
-#define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(IS_PLAYER(v))
-
-#define FOR_EACH_MONSTER(v) for(v = world; (v = findflags(v, flags, FL_MONSTER)) != world; )
-
#define CENTER_OR_VIEWOFS(ent) (ent.origin + (IS_PLAYER(ent) ? ent.view_ofs : ((ent.mins + ent.maxs) * 0.5)))
// copies a string to a tempstring (so one can strunzone it)
//#NO AUTOCVARS END
-
-// Sound functions
-//string precache_sound (string s) = #19;
-// hack
-float precache_sound_index (string s) = #19;
-
-const float SND_VOLUME = BIT(0);
-const float SND_ATTENUATION = BIT(1);
-const float SND_LARGEENTITY = BIT(3);
-const float SND_LARGESOUND = BIT(4);
-
const float INITPRIO_FIRST = 0;
const float INITPRIO_GAMETYPE = 0;
const float INITPRIO_GAMETYPE_FALLBACK = 1;