From 6f4868ab9f2a3c3a32063abd23c0678995b22ca4 Mon Sep 17 00:00:00 2001 From: driAn Date: Sun, 14 Oct 2007 12:58:26 +0000 Subject: [PATCH] footsteps git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@1357 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/bot/bot.cpp | 2 +- source/src/clientgame.cpp | 11 ++- source/src/clients2c.cpp | 2 +- source/src/entities.cpp | 2 +- source/src/entity.h | 5 +- source/src/main.cpp | 1 + source/src/physics.cpp | 6 +- source/src/protos.h | 4 +- source/src/rendermodel.cpp | 1 + source/src/server.cpp | 80 +----------------- source/src/serveractions.h | 121 ++++++++++++++++++++++++++++ source/src/sound.cpp | 161 ++++++++++++++++++++++++++----------- source/src/weapon.cpp | 14 ++-- source/src/world.cpp | 1 + source/src/worldio.cpp | 3 +- 15 files changed, 266 insertions(+), 148 deletions(-) create mode 100644 source/src/serveractions.h diff --git a/source/src/bot/bot.cpp b/source/src/bot/bot.cpp index fc64d198..2cd11207 100644 --- a/source/src/bot/bot.cpp +++ b/source/src/bot/bot.cpp @@ -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; } diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index cf5da65a..419ab88f 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -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)); diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 44f1e872..eebfc47c 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -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; diff --git a/source/src/entities.cpp b/source/src/entities.cpp index 8997c883..0eb165a2 100644 --- a/source/src/entities.cpp +++ b/source/src/entities.cpp @@ -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) { diff --git a/source/src/entity.h b/source/src/entity.h index 90ef46ba..cadcf42c 100644 --- a/source/src/entity.h +++ b/source/src/entity.h @@ -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 - diff --git a/source/src/main.cpp b/source/src/main.cpp index 4ecea390..80c9c9cc 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -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(); diff --git a/source/src/physics.cpp b/source/src/physics.cpp index 0967e6f1..cea6972c 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -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); diff --git a/source/src/protos.h b/source/src/protos.h index 18862be9..ee64c660 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -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); diff --git a/source/src/rendermodel.cpp b/source/src/rendermodel.cpp index 830de009..840f9b5e 100644 --- a/source/src/rendermodel.cpp +++ b/source/src/rendermodel.cpp @@ -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); } diff --git a/source/src/server.cpp b/source/src/server.cpp index ad049be7..a220bdcd 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -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 { diff --git a/source/src/serveractions.h b/source/src/serveractions.h new file mode 100644 index 00000000..5570467e --- /dev/null +++ b/source/src/serveractions.h @@ -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; + } +}; \ No newline at end of file diff --git a/source/src/sound.cpp b/source/src/sound.cpp index 1cbe59fb..cdeeae43 100644 --- a/source/src/sound.cpp +++ b/source/src/sound.cpp @@ -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 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 &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); } diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index 15676f4a..d59afcdc 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -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; diff --git a/source/src/world.cpp b/source/src/world.cpp index 7a75a9ad..d4d6986f 100644 --- a/source/src/world.cpp +++ b/source/src/world.cpp @@ -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; } diff --git a/source/src/worldio.cpp b/source/src/worldio.cpp index 7893da51..8b2e8a50 100644 --- a/source/src/worldio.cpp +++ b/source/src/worldio.cpp @@ -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