mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2025-02-02 22:11:22 +00:00
Handle sound flags, providing reliable+unicast flags. Also handle other sound flags+networking that only fte clients will benefit from right now.
This commit is contained in:
parent
3fae242613
commit
7bdf911d3a
9 changed files with 179 additions and 38 deletions
|
@ -1157,9 +1157,9 @@ static void CL_ParseStartSoundPacket(void)
|
|||
if (cl.protocol == PROTOCOL_VERSION_BJP3)
|
||||
field_mask |= SND_LARGESOUND;
|
||||
|
||||
//spike -- extra channel flags
|
||||
//spike -- extra flags
|
||||
if (field_mask & SND_FTE_MOREFLAGS)
|
||||
field_mask |= MSG_ReadByte()<<8;
|
||||
field_mask |= MSG_ReadUInt64()<<8;
|
||||
|
||||
if (field_mask & SND_VOLUME)
|
||||
volume = MSG_ReadByte ();
|
||||
|
|
|
@ -929,6 +929,29 @@ void MSG_WriteLong (sizebuf_t *sb, int c)
|
|||
buf[3] = c>>24;
|
||||
}
|
||||
|
||||
void MSG_WriteUInt64 (sizebuf_t *sb, unsigned long long c)
|
||||
{ //0* 10*,*, 110*,*,* etc, up to 0xff followed by 8 continuation bytes
|
||||
byte *buf;
|
||||
int b = 0;
|
||||
unsigned long long l = 128;
|
||||
while (c > l-1u)
|
||||
{ //count the extra bytes we need
|
||||
b++;
|
||||
l <<= 7; //each byte we add gains 8 bits, but we spend one on length.
|
||||
}
|
||||
buf = (byte*)SZ_GetSpace (sb, 1+b);
|
||||
*buf++ = 0xffu<<(8-b) | (c >> (b*8));
|
||||
while(b --> 0)
|
||||
*buf++ = (c >> (b*8))&0xff;
|
||||
}
|
||||
void MSG_WriteInt64 (sizebuf_t *sb, long long c)
|
||||
{ //move the sign bit into the low bit and avoid sign extension for more efficient length coding.
|
||||
if (c < 0)
|
||||
MSG_WriteUInt64(sb, ((unsigned long long)(-1-c)<<1)|1);
|
||||
else
|
||||
MSG_WriteUInt64(sb, c<<1);
|
||||
}
|
||||
|
||||
void MSG_WriteFloat (sizebuf_t *sb, float f)
|
||||
{
|
||||
union
|
||||
|
@ -1099,6 +1122,30 @@ int MSG_ReadLong (void)
|
|||
return c;
|
||||
}
|
||||
|
||||
unsigned long long MSG_ReadUInt64 (void)
|
||||
{ //0* 10*,*, 110*,*,* etc, up to 0xff followed by 8 continuation bytes
|
||||
byte l=0x80, v, b = 0;
|
||||
unsigned long long r;
|
||||
v = MSG_ReadByte();
|
||||
for (; v&l; l>>=1)
|
||||
{
|
||||
v-=l;
|
||||
b++;
|
||||
}
|
||||
r = v<<(b*8);
|
||||
while(b --> 0)
|
||||
r |= MSG_ReadByte()<<(b*8);
|
||||
return r;
|
||||
}
|
||||
long long MSG_ReadInt64 (void)
|
||||
{ //we do some fancy bit recoding for more efficient length coding.
|
||||
unsigned long long c = MSG_ReadUInt64();
|
||||
if (c&1)
|
||||
return -1-(long long)(c>>1);
|
||||
else
|
||||
return (long long)(c>>1);
|
||||
}
|
||||
|
||||
float MSG_ReadFloat (void)
|
||||
{
|
||||
union
|
||||
|
|
|
@ -100,6 +100,8 @@ void MSG_WriteChar (sizebuf_t *sb, int c);
|
|||
void MSG_WriteByte (sizebuf_t *sb, int c);
|
||||
void MSG_WriteShort (sizebuf_t *sb, int c);
|
||||
void MSG_WriteLong (sizebuf_t *sb, int c);
|
||||
void MSG_WriteUInt64 (sizebuf_t *sb, unsigned long long c);
|
||||
void MSG_WriteInt64 (sizebuf_t *sb, long long c);
|
||||
void MSG_WriteFloat (sizebuf_t *sb, float f);
|
||||
void MSG_WriteStringUnterminated (sizebuf_t *sb, const char *s);
|
||||
void MSG_WriteString (sizebuf_t *sb, const char *s);
|
||||
|
@ -118,6 +120,8 @@ int MSG_ReadChar (void);
|
|||
int MSG_ReadByte (void);
|
||||
int MSG_ReadShort (void);
|
||||
int MSG_ReadLong (void);
|
||||
unsigned long long MSG_ReadUInt64 (void);
|
||||
long long MSG_ReadInt64 (void);
|
||||
float MSG_ReadFloat (void);
|
||||
const char *MSG_ReadString (void);
|
||||
|
||||
|
|
|
@ -241,8 +241,9 @@ qpic_t *Draw_PicFromWad2 (const char *name, unsigned int texflags)
|
|||
Con_SafePrintf ("W_GetLumpName: %s not found\n", name);
|
||||
return pic_nul; //johnfitz
|
||||
}
|
||||
if (info->type != TYP_QPIC) Sys_Error ("Draw_PicFromWad: lump \"%s\" is not a qpic", name);
|
||||
if (info->size < sizeof(int)*2 || 8+p->width*p->height < info->size) Sys_Error ("Draw_PicFromWad: pic \"%s\" truncated", name);
|
||||
if (info->type != TYP_QPIC) {Con_SafePrintf ("Draw_PicFromWad: lump \"%s\" is not a qpic\n", name); return pic_nul;}
|
||||
if (info->size < sizeof(int)*2) {Con_SafePrintf ("Draw_PicFromWad: pic \"%s\" is too small for its qpic header (%u bytes)\n", name, info->size); return pic_nul;}
|
||||
if (8+p->width*p->height < info->size) Sys_Error ("Draw_PicFromWad: pic \"%s\" truncated (%u*%u requires %u bytes)\n", name, p->width,p->height, 8+p->width*p->height);
|
||||
|
||||
//Spike -- if we're loading external images, and one exists, then use that instead.
|
||||
if (draw_load24bit && (gl.gltexture=TexMgr_LoadImage (NULL, name, 0, 0, SRC_EXTERNAL, NULL, va("gfx/%s", name), 0, texflags|TEXPREF_MIPMAP|TEXPREF_ALLOWMISSING)))
|
||||
|
|
|
@ -654,6 +654,9 @@ static void PF_sound (void)
|
|||
edict_t *entity;
|
||||
int volume;
|
||||
float attenuation;
|
||||
float ratepct;
|
||||
unsigned int flags;
|
||||
float offset;
|
||||
|
||||
entity = G_EDICT(OFS_PARM0);
|
||||
channel = G_FLOAT(OFS_PARM1);
|
||||
|
@ -661,12 +664,23 @@ static void PF_sound (void)
|
|||
volume = G_FLOAT(OFS_PARM3) * 255;
|
||||
attenuation = G_FLOAT(OFS_PARM4);
|
||||
|
||||
ratepct = (qcvm->argc<6)?100:G_FLOAT(OFS_PARM5);
|
||||
flags = (qcvm->argc<7)?0:G_FLOAT(OFS_PARM6);
|
||||
offset = (qcvm->argc<8)?0:G_FLOAT(OFS_PARM7);
|
||||
|
||||
if (!*sample)
|
||||
{
|
||||
PR_RunWarning("PF_sound: empty string\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ratepct && ratepct != 100)
|
||||
Con_DPrintf("sound() rate scaling is not supported\n");
|
||||
if (flags)
|
||||
Con_DPrintf("sound() flags %#x not supported\n", flags);
|
||||
if (offset)
|
||||
Con_DPrintf("sound() time offsets are not supported\n");
|
||||
|
||||
/* Spike -- these checks are redundant
|
||||
if (volume < 0 || volume > 255)
|
||||
Host_Error ("SV_StartSound: volume = %i", volume);
|
||||
|
|
|
@ -2088,6 +2088,16 @@ static void PF_getsurfaceclippedpoint(void)
|
|||
getsurface_clippointpoly(model, surf, point, result, 0x7fffffff);
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
SPA_POSITION = 0,
|
||||
SPA_S_AXIS = 1,
|
||||
SPA_T_AXIS = 2,
|
||||
SPA_R_AXIS = 3, //normal
|
||||
SPA_TEXCOORDS0 = 4,
|
||||
SPA_LIGHTMAP0_TEXCOORDS = 5,
|
||||
SPA_LIGHTMAP0_COLOR = 6,
|
||||
};
|
||||
static void PF_getsurfacepointattribute(void)
|
||||
{
|
||||
edict_t *ed = G_EDICT(OFS_PARM0);
|
||||
|
@ -2109,11 +2119,11 @@ static void PF_getsurfacepointattribute(void)
|
|||
G_FLOAT(OFS_RETURN+1) = 0;
|
||||
G_FLOAT(OFS_RETURN+2) = 0;
|
||||
break;
|
||||
case 0: //xyz coord
|
||||
case SPA_POSITION:
|
||||
VectorCopy(v->position, G_VECTOR(OFS_RETURN));
|
||||
break;
|
||||
case 1: //s dir
|
||||
case 2: //t dir
|
||||
case SPA_S_AXIS:
|
||||
case SPA_T_AXIS:
|
||||
{
|
||||
//figure out how similar to the normal it is, and negate any influence, so that its perpendicular
|
||||
float sc = -DotProduct(fa->plane->normal, fa->texinfo->vecs[attribute-1]);
|
||||
|
@ -2121,22 +2131,22 @@ static void PF_getsurfacepointattribute(void)
|
|||
VectorNormalize(G_VECTOR(OFS_RETURN));
|
||||
}
|
||||
break;
|
||||
case 3: //normal
|
||||
case SPA_R_AXIS: //normal
|
||||
VectorCopy(fa->plane->normal, G_VECTOR(OFS_RETURN));
|
||||
if (fa->flags & SURF_PLANEBACK)
|
||||
VectorInverse(G_VECTOR(OFS_RETURN));
|
||||
break;
|
||||
case 4: //st coord
|
||||
case SPA_TEXCOORDS0:
|
||||
G_FLOAT(OFS_RETURN+0) = (DotProduct(v->position, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]) / fa->texinfo->texture->width;
|
||||
G_FLOAT(OFS_RETURN+1) = (DotProduct(v->position, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]) / fa->texinfo->texture->height;
|
||||
G_FLOAT(OFS_RETURN+2) = 0;
|
||||
break;
|
||||
case 5: //lmst coord, not actually very useful
|
||||
case SPA_LIGHTMAP0_TEXCOORDS: //lmst coord, not actually very useful
|
||||
G_FLOAT(OFS_RETURN+0) = (DotProduct(v->position, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3] - fa->texturemins[0] + (fa->light_s+.5)*(1<<fa->lmshift)) / (LMBLOCK_WIDTH*(1<<fa->lmshift));
|
||||
G_FLOAT(OFS_RETURN+1) = (DotProduct(v->position, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3] - fa->texturemins[1] + (fa->light_t+.5)*(1<<fa->lmshift)) / (LMBLOCK_HEIGHT*(1<<fa->lmshift));
|
||||
G_FLOAT(OFS_RETURN+2) = 0;
|
||||
break;
|
||||
case 6: //colour
|
||||
case SPA_LIGHTMAP0_COLOR: //colour
|
||||
G_FLOAT(OFS_RETURN+0) = 1;
|
||||
G_FLOAT(OFS_RETURN+1) = 1;
|
||||
G_FLOAT(OFS_RETURN+2) = 1;
|
||||
|
@ -8256,6 +8266,14 @@ void PR_DumpPlatform_f(void)
|
|||
fprintf(f, "const float CHAN_VOICE = %i;\n", 2);
|
||||
fprintf(f, "const float CHAN_ITEM = %i;\n", 3);
|
||||
fprintf(f, "const float CHAN_BODY = %i;\n", 4);
|
||||
|
||||
fprintf(f, "const float SPA_POSITION = %i;\n", SPA_POSITION);
|
||||
fprintf(f, "const float SPA_S_AXIS = %i;\n", SPA_S_AXIS);
|
||||
fprintf(f, "const float SPA_T_AXIS = %i;\n", SPA_T_AXIS);
|
||||
fprintf(f, "const float SPA_R_AXIS = %i;\n", SPA_R_AXIS);
|
||||
fprintf(f, "const float SPA_TEXCOORDS0 = %i;\n", SPA_TEXCOORDS0);
|
||||
fprintf(f, "const float SPA_LIGHTMAP0_TEXCOORDS = %i;\n", SPA_LIGHTMAP0_TEXCOORDS);
|
||||
fprintf(f, "const float SPA_LIGHTMAP0_COLOR = %i;\n", SPA_LIGHTMAP0_COLOR);
|
||||
}
|
||||
|
||||
if (targs & (CS|MN))
|
||||
|
|
|
@ -205,24 +205,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define DPSU_VIEWZOOM (1<<19) // byte factor (0 = 0.0 (not valid), 255 = 1.0)
|
||||
//spike
|
||||
|
||||
#define DEFAULT_SOUND_PACKET_VOLUME 255
|
||||
#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0
|
||||
// a sound with no channel is a local only sound
|
||||
#define SND_VOLUME (1<<0) // a byte
|
||||
#define SND_ATTENUATION (1<<1) // a byte
|
||||
//#define SND_LOOPING (1<<2) // a long (unused in vanilla)
|
||||
|
||||
#define DEFAULT_SOUND_PACKET_VOLUME 255
|
||||
#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0
|
||||
|
||||
//spike -- parsing, but not using at this time
|
||||
#define SND_FTE_MOREFLAGS (1<<2) // a byte, for channel flags
|
||||
//johnfitz -- PROTOCOL_FITZQUAKE -- new bits
|
||||
#define SND_LARGEENTITY (1<<3) // a short + byte (instead of just a short)
|
||||
#define SND_LARGESOUND (1<<4) // a short soundindex (instead of a byte)
|
||||
//johnfitz
|
||||
//spike -- parsing, but not using at this time
|
||||
#define SND_FTE_MOREFLAGS (1<<2) // a byte, for channel flags
|
||||
#define SND_DP_PITCH (1<<5) //dp uses this for pitch...
|
||||
#define SND_FTE_TIMEOFS (1<<6) //signed short, in milliseconds.
|
||||
#define SND_FTE_PITCHADJ (1<<7) //a byte (speed percent (0=100%))
|
||||
#define SND_FTE_VELOCITY (1<<8) //3 shorts (1/8th), for doppler or whatever.
|
||||
#define SND_FTE_FORCELOOP (1<<9) //flag
|
||||
#define SND_FTE_NOSPACIALISE (1<<10)//flag
|
||||
#define SND_FTE_NOREVERB (1<<13) //flat
|
||||
#define SND_FTE_FOLLOW (1<<14) //flag only
|
||||
#define SND_FTE_NOREPLACE (1<<15) //flag only
|
||||
|
||||
#define CF_RELIABLE (1<<0) //send over reliable channel
|
||||
#define CF_FORCELOOP (1<<1) //force looping
|
||||
#define CF_NOSPACIALISE (1<<2) //mono-ize. play on the local player to avoid distance fading.
|
||||
#define CF_NOREVERB (1<<5) //disable reverb effects (for music, QS doesn't have reverb)
|
||||
#define CF_FOLLOW (1<<6) //sound origin follows entity
|
||||
#define CF_NOREPLACE (1<<7) //drop the sound if it would replace one.
|
||||
#define CF_UNICAST (1<<8) //send only to msg_entity
|
||||
#define CF_SENDVELOCITY (1<<9) //include the velocity, for doppler effects.
|
||||
//spike
|
||||
|
||||
//johnfitz -- PROTOCOL_FITZQUAKE -- flags for entity baseline messages
|
||||
|
|
|
@ -308,8 +308,8 @@ extern edict_t *sv_player;
|
|||
void SV_Init (void);
|
||||
|
||||
void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count);
|
||||
void SV_StartSound (edict_t *entity, float *origin, int channel,
|
||||
const char *sample, int volume, float attenuation);
|
||||
void SV_StartSound (edict_t *entity, float *origin, int channel, const char *sample, int volume, float attenuation);
|
||||
void SV_StartSound2 (edict_t *entity, float *origin, int channel, const char *sample, int volume, float attenuation, float speed, int flags, float timeoffset);
|
||||
|
||||
void SV_DropClient (qboolean crash);
|
||||
|
||||
|
|
|
@ -1587,12 +1587,13 @@ Larger attenuations will drop off. (max 4 attenuation)
|
|||
|
||||
==================
|
||||
*/
|
||||
void SV_StartSound (edict_t *entity, float *origin, int channel, const char *sample, int volume, float attenuation)
|
||||
void SV_StartSound2 (edict_t *entity, float *origin, int channel, const char *sample, int volume, float attenuation, float speed, int flags, float timeoffset)
|
||||
{
|
||||
unsigned int sound_num, ent;
|
||||
int i, field_mask;
|
||||
int i, field_mask, client_mask;
|
||||
int p;
|
||||
client_t *cl;
|
||||
sizebuf_t *msg;
|
||||
|
||||
if (volume < 0)
|
||||
Host_Error ("SV_StartSound: volume = %i", volume);
|
||||
|
@ -1641,6 +1642,19 @@ void SV_StartSound (edict_t *entity, float *origin, int channel, const char *sam
|
|||
field_mask |= SND_LARGESOUND;
|
||||
//johnfitz
|
||||
|
||||
//spike
|
||||
if (flags & CF_FORCELOOP) field_mask |= SND_FTE_FORCELOOP;
|
||||
if (flags & CF_NOSPACIALISE) field_mask |= SND_FTE_NOSPACIALISE;
|
||||
// if (flags & CF_PAUSED) field_mask |= SND_FTE_PAUSED;
|
||||
// if (flags & CF_ABSVOLUME) field_mask |= SND_FTE_ABSVOLUME;
|
||||
if (flags & CF_NOREVERB) field_mask |= SND_FTE_NOREVERB;
|
||||
if (flags & CF_FOLLOW) field_mask |= SND_FTE_FOLLOW;
|
||||
if (flags & CF_NOREPLACE) field_mask |= SND_FTE_NOREPLACE;
|
||||
if (flags & CF_SENDVELOCITY) field_mask |= SND_FTE_VELOCITY;
|
||||
if (speed && speed != 1) field_mask |= SND_FTE_PITCHADJ;
|
||||
if (timeoffset) field_mask |= SND_FTE_TIMEOFS;
|
||||
//
|
||||
|
||||
for (p = 0; p < svs.maxclients; p++)
|
||||
{
|
||||
cl = &svs.clients[p];
|
||||
|
@ -1654,43 +1668,74 @@ void SV_StartSound (edict_t *entity, float *origin, int channel, const char *sam
|
|||
if ((field_mask & (SND_LARGEENTITY|SND_LARGESOUND)) && (!cl->protocol_pext2 || sv.protocol == PROTOCOL_NETQUAKE))
|
||||
continue;
|
||||
|
||||
if (flags & CF_UNICAST && cl->edict != PROG_TO_EDICT(pr_global_struct->msg_entity))
|
||||
continue;
|
||||
if (flags & CF_RELIABLE)
|
||||
msg = &cl->message;
|
||||
else
|
||||
msg = &cl->datagram;
|
||||
client_mask = field_mask;
|
||||
if (!(cl->protocol_pext2&PEXT2_REPLACEMENTDELTAS))
|
||||
client_mask &= (SND_VOLUME|SND_ATTENUATION|SND_LARGEENTITY|SND_LARGESOUND);
|
||||
|
||||
// directed messages go only to the entity the are targeted on
|
||||
MSG_WriteByte (&cl->datagram, svc_sound);
|
||||
MSG_WriteByte (&cl->datagram, field_mask);
|
||||
if (field_mask & SND_VOLUME)
|
||||
MSG_WriteByte (&cl->datagram, volume);
|
||||
if (field_mask & SND_ATTENUATION)
|
||||
MSG_WriteByte (&cl->datagram, attenuation*64);
|
||||
MSG_WriteByte (msg, svc_sound);
|
||||
MSG_WriteByte (msg, client_mask&0xff);
|
||||
if (client_mask & SND_FTE_MOREFLAGS)
|
||||
MSG_WriteUInt64 (msg, client_mask>>8);
|
||||
if (client_mask & SND_VOLUME)
|
||||
MSG_WriteByte (msg, volume);
|
||||
if (client_mask & SND_ATTENUATION)
|
||||
MSG_WriteByte (msg, attenuation*64);
|
||||
|
||||
//spike -- stuff
|
||||
if (client_mask & SND_FTE_PITCHADJ)
|
||||
MSG_WriteByte (msg, CLAMP(1, speed*100, 255));
|
||||
if (client_mask & SND_FTE_TIMEOFS)
|
||||
MSG_WriteShort (msg, CLAMP(-32768, timeoffset*1000, 32767));
|
||||
if (client_mask & SND_FTE_VELOCITY)
|
||||
{
|
||||
MSG_WriteShort (msg, CLAMP(-32768, entity->v.velocity[0]*8, 32767));
|
||||
MSG_WriteShort (msg, CLAMP(-32768, entity->v.velocity[1]*8, 32767));
|
||||
MSG_WriteShort (msg, CLAMP(-32768, entity->v.velocity[2]*8, 32767));
|
||||
}
|
||||
if (client_mask & SND_DP_PITCH)
|
||||
MSG_WriteShort (msg, CLAMP(-32768, speed*4000, 32767));
|
||||
//end spike
|
||||
|
||||
//johnfitz -- PROTOCOL_FITZQUAKE
|
||||
if (field_mask & SND_LARGEENTITY)
|
||||
if (client_mask & SND_LARGEENTITY)
|
||||
{
|
||||
if ((cl->protocol_pext2 & PEXT2_REPLACEMENTDELTAS) && ent > 0x7fff)
|
||||
{
|
||||
MSG_WriteShort(&cl->datagram, (ent>>8) | 0x8000);
|
||||
MSG_WriteByte(&cl->datagram, ent & 0xff);
|
||||
MSG_WriteShort(msg, (ent>>8) | 0x8000);
|
||||
MSG_WriteByte(msg, ent & 0xff);
|
||||
}
|
||||
else
|
||||
MSG_WriteShort (&cl->datagram, ent);
|
||||
MSG_WriteByte (&cl->datagram, channel);
|
||||
MSG_WriteShort (msg, ent);
|
||||
MSG_WriteByte (msg, channel);
|
||||
}
|
||||
else
|
||||
MSG_WriteShort (&cl->datagram, (ent<<3) | channel);
|
||||
if ((field_mask & SND_LARGESOUND) || sv.protocol == PROTOCOL_VERSION_BJP3)
|
||||
MSG_WriteShort (&cl->datagram, sound_num);
|
||||
MSG_WriteShort (msg, (ent<<3) | channel);
|
||||
if ((client_mask & SND_LARGESOUND) || sv.protocol == PROTOCOL_VERSION_BJP3)
|
||||
MSG_WriteShort (msg, sound_num);
|
||||
else
|
||||
MSG_WriteByte (&cl->datagram, sound_num);
|
||||
MSG_WriteByte (msg, sound_num);
|
||||
//johnfitz
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (origin)
|
||||
MSG_WriteCoord (&cl->datagram, origin[i], sv.protocolflags);
|
||||
MSG_WriteCoord (msg, origin[i], sv.protocolflags);
|
||||
else
|
||||
MSG_WriteCoord (&cl->datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]), sv.protocolflags);
|
||||
MSG_WriteCoord (msg, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]), sv.protocolflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
void SV_StartSound (edict_t *entity, float *origin, int channel, const char *sample, int volume, float attenuation)
|
||||
{
|
||||
SV_StartSound2 (entity, origin, channel, sample, volume, attenuation, 100, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
|
Loading…
Reference in a new issue