footsteps

git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@1357 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
driAn
2007-10-14 12:58:26 +00:00
parent 7befa37ee5
commit 6f4868ab9f
15 changed files with 266 additions and 148 deletions
+1 -1
View File
@@ -303,7 +303,7 @@ float CBot::GetDistance(entity *e)
bool CBot::SelectGun(int Gun)
{
if(m_pMyEnt->reloading) return false;
if (m_pMyEnt->gunselect != Gun) playsound(S_GUNCHANGE, &m_pMyEnt->o);
if (m_pMyEnt->gunselect != Gun) playsound(S_GUNCHANGE, m_pMyEnt);
m_pMyEnt->gunselect = Gun;
return true;
}
+5 -6
View File
@@ -390,7 +390,7 @@ void dodamage(int damage, playerent *pl, playerent *actor, bool gib, bool local)
if(pl->health<=0) { if(local) dokill(pl, actor, gib); }
else if(pl==player1) playsound(S_PAIN6);
else playsound(S_PAIN1+rnd(5), &pl->o);
else playsound(S_PAIN1+rnd(5), pl);
}
void dokill(playerent *pl, playerent *act, bool gib)
@@ -422,7 +422,7 @@ void dokill(playerent *pl, playerent *act, bool gib)
pl->roll = 60;
pl->move = pl->strafe = 0;
pl->attacking = false;
playsound(S_DIE1+rnd(2), pl!=player1 ? &pl->o : NULL);
playsound(S_DIE1+rnd(2), NULL, NULL, pl == player1 ? NULL : &pl->o);
if(pl==player1)
{
showscores(true);
@@ -665,12 +665,11 @@ votedisplayinfo *curvote = NULL, *calledvote = NULL;
void callvote(char *type, char *arg1, char *arg2)
{
if(calledvote || !type) return;
if(!type || (calledvote && multiplayer(false))) return;
votedisplayinfo *v = newvotedisplayinfo(player1, atoi(type), arg1, arg2);
if(v)
{
calledvote = v;
if(multiplayer(false)) calledvote = v;
ENetPacket *packet = enet_packet_create(NULL, MAXTRANS, ENET_PACKET_FLAG_RELIABLE);
ucharbuf p(packet->data, packet->dataLength);
putint(p, SV_CALLVOTE);
@@ -679,7 +678,7 @@ void callvote(char *type, char *arg1, char *arg2)
{
case SA_MAP:
sendstring(arg1, p);
putint(p, atoi(arg2));
putint(p, nextmode);
break;
default:
putint(p, atoi(arg1));
+1 -1
View File
@@ -128,7 +128,7 @@ void parsemessages(int cn, playerent *d, ucharbuf &p)
}
case SV_SOUND:
playsound(getint(p), !d ? NULL : &d->o);
playsound(getint(p), !d ? NULL : d);
break;
+1 -1
View File
@@ -79,7 +79,7 @@ void pickupeffects(int n, playerent *d)
if(&is)
{
if(d==player1) playsoundc(is.sound);
else playsound(is.sound, &d->o);
else playsound(is.sound, d);
}
switch(e.type)
{
+2 -3
View File
@@ -25,8 +25,8 @@ struct persistent_entity // map entity
struct entity : public persistent_entity
{
bool spawned; // fixme,ah//the only dynamic state of a map entity
bool visible;
bool spawned; //the only dynamic state of a map entity
bool soundinuse;
};
struct itemstat { int add, start, max, sound; };
@@ -416,4 +416,3 @@ struct bounceent : physent // nades, gibs
#define has_akimbo(d) ((d)->gunselect==GUN_PISTOL && (d)->akimbo)
#define WEAPONCHANGE_TIME 400
+1
View File
@@ -459,6 +459,7 @@ int main(int argc, char **argv)
frames++;
checkmapsounds();
checkplayerloopsounds();
computeraytable(camera1->o.x, camera1->o.y);
if(frames>4) SDL_GL_SwapBuffers();
+3 -3
View File
@@ -319,7 +319,7 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime)
pl->vel.z = 2.0f; //1.7f; // physics impulse upwards
if(water) { pl->vel.x /= 8; pl->vel.y /= 8; } // dampen velocity change even harder, gives correct water feel
if(local) playsoundc(S_JUMP);
else if(pl->type==ENT_BOT) playsound(S_JUMP, &pl->o); // Added by Rick
else if(pl->type==ENT_BOT) playsound(S_JUMP, pl); // Added by Rick
}
pl->timeinair = 0;
}
@@ -410,8 +410,8 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime)
}
// play sounds on water transitions
if(!pl->inwater && water) { playsound(S_SPLASH2, &pl->o); pl->vel.z = 0; }
else if(pl->inwater && !water) playsound(S_SPLASH1, &pl->o);
if(!pl->inwater && water) { playsound(S_SPLASH2, NULL, NULL, &pl->o); pl->vel.z = 0; }
else if(pl->inwater && !water) playsound(S_SPLASH1, NULL, NULL, &pl->o);
pl->inwater = water;
// Added by Rick: Easy hack to store previous locations of all players/monsters/bots
if(pl->type==ENT_PLAYER || pl->type==ENT_BOT) ((playerent *)pl)->history.update(pl->o, lastmillis);
+3 -1
View File
@@ -294,12 +294,14 @@ extern void fixcamerarange(physent *cam = camera1);
extern float floor(short x, short y);
// sound
extern void playsound(int n, const vec *loc = NULL, entity *ent = NULL);
extern void playsound(int n, physent *p = NULL, entity *ent = NULL, const vec *loc = NULL);
extern void playsoundc(int n);
extern void initsound();
extern void cleansound();
extern void checkmapsounds();
extern void checkplayerloopsounds();
extern void music(char *name, char *cmd);
extern void clearmapsounds();
// rendermodel
extern void rendermodel(char *mdl, int anim, int tex, float rad, const vec &o, float yaw, float pitch, float speed = 0, int basetime = 0, playerent *d = NULL, char *vwepmdl = NULL, float scale = 1.0f);
+1
View File
@@ -364,6 +364,7 @@ void renderclient(playerent *d, char *mdlname, char *vwepname, int tex)
{ anim = ANIM_ATTACK; speed = 300.0f/8; basetime = d->lastaction; }
else if(!d->move && !d->strafe) { anim = ANIM_IDLE|ANIM_LOOP; }
else { anim = ANIM_RUN|ANIM_LOOP; speed = 1860/d->maxspeed; }
rendermodel(mdlname, anim, tex, 1.5f, o, d->yaw+90, d->pitch/4, speed, basetime, d, vwepname);
}
+1 -79
View File
@@ -1116,85 +1116,7 @@ void changeclientrole(int client, int role, char *pwd = NULL, bool force=false)
else if(pwd && pwd[0]) disconnect_client(client, DISC_SOPLOGINFAIL); // avoid brute-force
}
struct serveraction
{
int type, role;
bool dedicated;
virtual ~serveraction() {}
virtual void perform() = 0;
virtual bool isvalid() { return true; }
};
struct mapaction : serveraction
{
char *map;
int mode;
void perform() { resetmap(map, mode); }
mapaction(char *map, int mode) : map(map), mode(mode) { type = SA_MAP; role = CR_MASTER; dedicated = false; }
~mapaction() { DELETEA(map); }
};
struct playeraction : serveraction
{
int cn;
void disconnect(int reason) { disconnect_client(cn, reason); }
bool isvalid() { return valid_client(cn); }
playeraction(int cn) : cn(cn) {}
};
struct forceteamaction : playeraction
{
void perform() { forceteam(cn, team_opposite(team_int(clients[cn]->team))); }
forceteamaction(int cn) : playeraction(cn) { type = SA_FORCETEAM; role = CR_MASTER; dedicated = true; }
};
struct givemasteraction : playeraction
{
void perform() { changeclientrole(cn, CR_MASTER, NULL, true); }
givemasteraction(int cn) : playeraction(cn) { type = SA_GIVEMASTER; role = CR_ADMIN; dedicated = true; }
};
struct kickaction : playeraction
{
void perform() { disconnect(DISC_MKICK); }
kickaction(int cn) : playeraction(cn) { type = SA_KICK; role = CR_MASTER; dedicated = true; }
};
struct banaction : playeraction
{
void perform()
{
ban b = { clients[cn]->peer->address, servmillis+20*60*1000 };
bans.add(b);
disconnect(DISC_MBAN);
}
banaction(int cn) : playeraction(cn) { type = SA_BAN; role = CR_MASTER; dedicated = true; }
};
struct removebansaction : serveraction
{
void perform() { bans.setsize(0); }
removebansaction() { type = SA_REMBANS; role = CR_MASTER; dedicated = true; }
};
struct mastermodeaction : serveraction
{
int mode;
void perform() { mastermode = mode; }
bool isvalid() { return mode >= 0 && mode < MM_NUM; }
mastermodeaction(int mode) : mode(mode) { type = SA_MASTERMODE; role = CR_MASTER; dedicated = true; }
};
struct autoteamaction : serveraction
{
bool enabled;
void perform()
{
sendf(-1, 1, "ri2", SV_AUTOTEAM, (autoteam = enabled) == 1 ? 1 : 0);
if(m_teammode) shuffleteams();
}
autoteamaction(bool enabled) : enabled(enabled) { type = SA_AUTOTEAM; role = CR_MASTER; dedicated = true; }
};
#include "serveractions.h"
struct voteinfo
{
+121
View File
@@ -0,0 +1,121 @@
// available server actions
struct serveraction
{
int type, role;
bool dedicated;
virtual ~serveraction() {}
virtual void perform() = 0;
virtual bool isvalid() { return true; }
};
struct mapaction : serveraction
{
char *map;
int mode;
void perform() { resetmap(map, mode); }
mapaction(char *map, int mode) : map(map), mode(mode)
{
type = SA_MAP;
role = CR_MASTER;
dedicated = false;
}
~mapaction() { DELETEA(map); }
};
struct playeraction : serveraction
{
int cn;
void disconnect(int reason) { disconnect_client(cn, reason); }
bool isvalid() { return valid_client(cn); }
playeraction(int cn) : cn(cn) {};
};
struct forceteamaction : playeraction
{
void perform() { forceteam(cn, team_opposite(team_int(clients[cn]->team))); }
forceteamaction(int cn) : playeraction(cn)
{
type = SA_FORCETEAM;
role = CR_MASTER;
dedicated = true;
}
};
struct givemasteraction : playeraction
{
void perform() { changeclientrole(cn, CR_MASTER, NULL, true); }
givemasteraction(int cn) : playeraction(cn)
{
type = SA_GIVEMASTER;
role = CR_ADMIN;
dedicated = true;
}
};
struct kickaction : playeraction
{
void perform() { disconnect(DISC_MKICK); }
kickaction(int cn) : playeraction(cn)
{
type = SA_KICK;
role = CR_MASTER;
dedicated = true;
}
};
struct banaction : playeraction
{
void perform()
{
ban b = { clients[cn]->peer->address, servmillis+20*60*1000 };
bans.add(b);
disconnect(DISC_MBAN);
}
banaction(int cn) : playeraction(cn)
{
type = SA_BAN;
role = CR_MASTER;
dedicated = true;
}
};
struct removebansaction : serveraction
{
void perform() { bans.setsize(0); }
removebansaction()
{
type = SA_REMBANS;
role = CR_MASTER;
dedicated = true;
}
};
struct mastermodeaction : serveraction
{
int mode;
void perform() { mastermode = mode; }
bool isvalid() { return mode >= 0 && mode < MM_NUM; }
mastermodeaction(int mode) : mode(mode)
{
type = SA_MASTERMODE;
role = CR_MASTER;
dedicated = true;
}
};
struct autoteamaction : serveraction
{
bool enabled;
void perform()
{
sendf(-1, 1, "ri2", SV_AUTOTEAM, (autoteam = enabled) == 1 ? 1 : 0);
if(m_teammode) shuffleteams();
}
autoteamaction(bool enabled) : enabled(enabled)
{
type = SA_AUTOTEAM;
role = CR_MASTER;
dedicated = true;
}
};
+116 -45
View File
@@ -42,12 +42,29 @@ struct soundslot
int uses, maxuses;
};
struct soundloc
{
vec loc;
bool inuse;
soundslot *slot;
entity *ent;
struct soundloc
{
soundslot *slot;
bool inuse;
int radius, size;
physent *pse; // players/phys
entity *ent; // map ents
vec o; // static
vec loc() { return pse ? pse->o : (ent ? vec(ent->x, ent->y, ent->z) : o); }
void sleep()
{
if(ent) { ent->soundinuse = false; slot->uses--; }
inuse = false;
}
void awake()
{
if(ent) { ent->soundinuse = true; slot->uses++; }
inuse = true;
}
};
vector<soundloc> soundlocs;
@@ -228,41 +245,76 @@ void clearmapsounds()
#else
if(FSOUND_IsPlaying(i)) FSOUND_StopSound();
#endif
soundlocs[i].inuse = false;
soundlocs[i].ent->visible = false;
soundlocs[i].slot->uses--;
soundlocs[i].sleep();
}
mapsounds.setsizenodelete(0);
}
void checkmapsounds()
{
//const vector<entity *> &ents = et->getents();
loopv(ents)
{
entity &e = ents[i];
vec o(e.x, e.y, e.z);
if(e.type!=SOUND || e.visible || camera1->o.dist(o)>=e.attr2) continue;
if(e.type!=SOUND || e.soundinuse || camera1->o.dist(o)>=e.attr2) continue;
playsound(e.attr1, NULL, &e);
}
}
VAR(footsteps, 0, 1, 1);
VAR(footstepradius, 0, 16, 25);
VAR(footstepalign, 5, 15, 4000);
int findsoundloc(int sound, physent *p)
{
loopv(soundlocs) if(soundlocs[i].pse == p && soundlocs[i].slot == &gamesounds[sound]) return i;
return -1;
}
void checkplayerloopsounds()
{
loopv(players)
{
playerent *p = players[i];
if(!p) continue;
if(footsteps && camera1->o.dist(p->o) < footstepradius)
{
int idx = findsoundloc(S_FOOTSTEPS, p);
if(idx == -1 || !soundlocs[idx].inuse)
{
// sync to model animation
int basetime = -((int)(size_t)p&0xFFF);
int time = lastmillis-basetime;
int speed = 1860/p->maxspeed;
// TODO: share with model code
if(time%speed < footstepalign) playsound(S_FOOTSTEPS, p);
}
}
// add other sounds here
}
}
VAR(stereo, 0, 1, 1);
void updatechanvol(int chan, int svol, const vec *loc = NULL, entity *ent = NULL)
void updatechanvol(int chan, int svol, soundloc *sl)
{
int vol = soundvol, pan = 255/2;
if(loc || ent)
if(sl)
{
vec v;
float dist = camera1->o.dist(ent ? vec(ent->x, ent->y, ent->z) : *loc, v);
if(ent)
float dist = camera1->o.dist(sl->loc(), v);
int rad = sl->radius;
if(rad >= 0)
{
int rad = ent->attr2;
if(ent->attr3)
int size = sl->size;
if(size > 0)
{
rad -= ent->attr3;
dist -= ent->attr3;
rad -= size;
dist -= size;
}
vol -= (int)(min(max(dist/rad, 0), 1)*soundvol);
}
@@ -271,6 +323,18 @@ void updatechanvol(int chan, int svol, const vec *loc = NULL, entity *ent = NULL
vol -= (int)(dist*3/4*soundvol/255); // simple mono distance attenuation
if(vol<0) vol = 0;
}
if(sl->pse) // control looping physent sound volume
{
if(sl->slot == &gamesounds[S_FOOTSTEPS]) // control footsteps
{
if(sl->pse->type == ENT_PLAYER || sl->pse->type == ENT_BOT)
{
playerent *p = (playerent *)sl->pse;
bool nofootsteps = p->state != CS_ALIVE || lastmillis-p->lastpain < 300 || (!p->onfloor && p->timeinair>50) || (!p->move && !p->strafe);
if(nofootsteps) vol = 0; // TODO: fade out?
}
}
}
if(stereo && (v.x != 0 || v.y != 0) && dist>0)
{
float yaw = -atan2f(v.x, v.y) - camera1->yaw*RAD; // relative angle of sound along X-Y axis
@@ -286,15 +350,33 @@ void updatechanvol(int chan, int svol, const vec *loc = NULL, entity *ent = NULL
FSOUND_SetVolume(chan, vol);
FSOUND_SetPan(chan, pan);
#endif
}
}
void newsoundloc(int chan, const vec *loc, soundslot *slot, entity *ent = NULL)
int soundrad(int sound)
{
const int rads[] =
{
S_FOOTSTEPS, 16,
-1
};
for(const int *r = rads; *r >= 0; r += 2) if(*r==sound) return r[1];
return -1;
}
soundloc *newsoundloc(int sound, int chan, soundslot *slot, physent *p = NULL, entity *ent = NULL, const vec *loc = NULL)
{
if(!p && !ent && !loc) return NULL;
while(chan >= soundlocs.length()) soundlocs.add().inuse = false;
soundlocs[chan].loc = ent ? vec(ent->x, ent->y, ent->z) : *loc;
soundlocs[chan].inuse = true;
soundlocs[chan].slot = slot;
soundlocs[chan].ent = ent;
soundloc *sl = &soundlocs[chan];
sl->inuse = true;
sl->slot = slot;
sl->pse = p;
sl->ent = ent && !p ? ent : NULL;
sl->o = loc && !ent ? *loc : vec(0,0,0);
sl->radius = ent ? ent->attr2 : soundrad(sound);
sl->size = ent ? ent->attr3 : -1;
sl->awake();
return &soundlocs[chan];
}
void updatevol()
@@ -302,21 +384,15 @@ void updatevol()
if(nosound) return;
loopv(soundlocs) if(soundlocs[i].inuse)
{
soundloc &sl = soundlocs[i];
#ifdef USE_MIXER
if(Mix_Playing(i))
#else
if(FSOUND_IsPlaying(i))
#endif
updatechanvol(i, soundlocs[i].slot->vol, &soundlocs[i].loc, soundlocs[i].ent);
else
{
soundlocs[i].inuse = false;
if(soundlocs[i].ent)
{
soundlocs[i].ent->visible = false;
soundlocs[i].slot->uses--;
}
}
updatechanvol(i, soundlocs[i].slot->vol, &sl);
else sl.sleep();
}
#ifndef USE_MIXER
if(mod && FMUSIC_IsFinished(mod)) musicdone();
@@ -328,12 +404,12 @@ void updatevol()
VARP(maxsoundsatonce, 0, 5, 100);
void playsound(int n, const vec *loc, entity *ent)
void playsound(int n, physent *p, entity *ent, const vec *loc)
{
if(nosound) return;
if(!soundvol) return;
if(!ent)
if(!ent) // fixme
{
static int soundsatonce = 0, lastsoundmillis = 0;
if(totalmillis==lastsoundmillis) soundsatonce++; else soundsatonce = 1;
@@ -372,13 +448,8 @@ void playsound(int n, const vec *loc, entity *ent)
#endif
if(chan<0) return;
if(ent)
{
ent->visible = true;
slot.uses++;
}
if(loc || ent) newsoundloc(chan, loc, &slot, ent);
updatechanvol(chan, slot.vol, loc, ent);
soundloc *sl = p || ent || loc ? newsoundloc(n, chan, &slot, p, ent, loc) : NULL;
updatechanvol(chan, slot.vol, sl);
#ifndef USE_MIXER
FSOUND_SetPaused(chan, false);
#endif
@@ -389,7 +460,7 @@ void playsoundname(char *s, const vec *loc, int vol)
if(!vol) vol = 100;
int id = findsound(s, vol, gamesounds);
if(id < 0) id = addsound(s, vol, 0, gamesounds);
playsound(id, loc);
playsound(id, NULL, NULL, loc);
}
void sound(int *n) { playsound(*n); }
+7 -7
View File
@@ -117,7 +117,7 @@ void reload(playerent *d)
d->ammo[d->gunselect] -= numbullets;
if(has_akimbo(d)) playsoundc(S_RAKIMBO);
else if(d->type==ENT_BOT) playsound(guns[d->gunselect].reload, &d->o);
else if(d->type==ENT_BOT) playsound(guns[d->gunselect].reload, d);
else playsoundc(guns[d->gunselect].reload);
if(d==player1) addmsg(SV_RELOAD, "ri2", lastmillis, d->gunselect);
@@ -274,7 +274,7 @@ void hit(int damage, playerent *d, playerent *at, const vec &vel, int gun, bool
{
h.dir = ivec(int(vel.x*DNF), int(vel.y*DNF), int(vel.z*DNF));
damageeffect(damage, d);
playsound(S_PAIN1+rnd(5), &d->o);
playsound(S_PAIN1+rnd(5), d);
}
}
}
@@ -314,7 +314,7 @@ void splash(projectile &p, vec &v, vec &vold, playerent *notthis, int qdam)
particle_splash(0, 50, 300, v);
if(p.gun!=GUN_GRENADE)
{
playsound(S_FEXPLODE, &v);
playsound(S_FEXPLODE, NULL, NULL, &v);
// no push?
}
else
@@ -476,7 +476,7 @@ VARP(gibspeed, 1, 30, 100);
void addgib(playerent *d)
{
if(!d) return;
playsound(S_GIB, &d->o);
playsound(S_GIB, d);
loopi(gibnum)
{
@@ -555,13 +555,13 @@ void explode_nade(bounceent *i)
{
if(!i) return;
if(i->bouncestate != NADE_THROWED) thrownade(i->owner, vec(0,0,0), i);
playsound(S_FEXPLODE, &i->o);
playsound(S_FEXPLODE, NULL, NULL, &i->o);
newprojectile(i->o, i->o, 1, i->owner==player1, i->owner, GUN_GRENADE);
}
void shootv(int gun, vec &from, vec &to, playerent *d, bool local, int nademillis) // create visual effect from a shot
{
if(guns[gun].sound) playsound(guns[gun].sound, d==player1 ? NULL : &d->o);
if(guns[gun].sound) playsound(guns[gun].sound, d==player1 ? NULL : d);
switch(gun)
{
case GUN_KNIFE:
@@ -707,7 +707,7 @@ bool hasammo(playerent *d) // bot mod
{
if(!d->mag[d->gunselect])
{
if(d->type==ENT_BOT) playsound(S_NOAMMO, &d->o);
if(d->type==ENT_BOT) playsound(S_NOAMMO, d);
else playsoundc(S_NOAMMO);
updatelastaction(d);
d->gunwait[d->gunselect] += 250;
+1
View File
@@ -270,6 +270,7 @@ void empty_world(int factor, bool force) // main empty world creation routine
if(!force && noteditmode()) return;
cleardlights();
pruneundos();
clearmapsounds();
sqr *oldworld = world;
bool copy = false;
if(oldworld && factor<0) { factor = sfactor+1; copy = true; }
+2 -1
View File
@@ -214,6 +214,7 @@ void load_world(char *mname) // still supports all map formats that have
preparectf(true);
cleardlights();
pruneundos();
clearmapsounds();
setnames(mname);
gzFile f = opengzfile(cgzname, "rb9");
if(!f) { conoutf("could not read map %s", cgzname); return; }
@@ -239,7 +240,7 @@ void load_world(char *mname) // still supports all map formats that have
entity &e = ents.add();
gzread(f, &e, sizeof(persistent_entity));
endianswap(&e, sizeof(short), 4);
e.spawned = false;
e.spawned = e.soundinuse = false;
if(e.type==LIGHT)
{
if(!e.attr2) e.attr2 = 255; // needed for MAPVERSION<=2