DEFINE_ACTION_FUNCTION(AActor, A_InquisitorCheckLand) { // [BC] This is handled server-side. if ( NETWORK_InClientMode() ) { return; } self->reactiontime--; if (self->reactiontime < 0 || self->velx == 0 || self->vely == 0 || self->z <= self->floorz) { // [BC] Set the thing's state. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SetThingState( self, STATE_SEE ); self->SetState (self->SeeState); self->reactiontime = 0; self->flags &= ~MF_NOGRAVITY; S_StopSound (self, CHAN_ITEM); return; } if (!S_IsActorPlayingSomething (self, CHAN_ITEM, -1)) { S_Sound (self, CHAN_ITEM|CHAN_LOOP, "inquisitor/jump", 1, ATTN_NORM); } }
/* ================= Host_RestartAmbientSounds Write ambient sounds into demo ================= */ void Host_RestartAmbientSounds( void ) { soundlist_t soundInfo[64]; string curtrack, looptrack; int i, nSounds; fs_offset_t position; if( !SV_Active( )) { return; } nSounds = S_GetCurrentStaticSounds( soundInfo, 64 ); for( i = 0; i < nSounds; i++ ) { if( !soundInfo[i].looping || soundInfo[i].entnum == -1 ) continue; MsgDev( D_NOTE, "Restarting sound %s...\n", soundInfo[i].name ); S_StopSound( soundInfo[i].entnum, soundInfo[i].channel, soundInfo[i].name ); SV_StartSound( pfnPEntityOfEntIndex( soundInfo[i].entnum ), CHAN_STATIC, soundInfo[i].name, soundInfo[i].volume, soundInfo[i].attenuation, 0, soundInfo[i].pitch ); } // restart soundtrack if( S_StreamGetCurrentState( curtrack, looptrack, &position )) { SV_StartMusic( curtrack, looptrack, position ); } }
void SN_StopSequence(mobj_t *mobj) { seqnode_t *node; for(node = SequenceListHead; node; node = node->next) { if(node->mobj == mobj) { S_StopSound(mobj); if(node->stopSound) { S_StartSoundAtVolume(mobj, node->stopSound, node->volume); } if(SequenceListHead == node) { SequenceListHead = node->next; } if(node->prev) { node->prev->next = node->next; } if(node->next) { node->next->prev = node->prev; } Z_Free(node); ActiveSequences--; } } }
//=========================================================================== // S_SectorSound // Doom-like sector sounds: when a new sound starts, stop any old ones // from the same origin. //=========================================================================== void S_SectorSound(sector_t *sec, int id) { mobj_t *origin = (mobj_t *) &sec->soundorg; S_StopSound(0, origin); S_StartSound(id, origin); }
// // ACS_funcStopSound // static void ACS_funcStopSound(ACS_FUNCARG) { Mobj *mo = P_FindMobjFromTID(args[0], NULL, thread->trigger); int chan = argc > 1 ? args[1] & 7 : CHAN_BODY; if(!mo) return; S_StopSound(mo, chan); }
void DPillar::PlayPillarSound() { if (predicting || !m_Sector) return; if (m_Status == init) S_Sound(m_Sector->soundorg, CHAN_BODY, "plats/pt1_mid", 1, ATTN_NORM); else if (m_Status == finished) S_StopSound(m_Sector->soundorg); }
void APowerFlight::InitEffect () { Owner->flags2 |= MF2_FLY; Owner->flags |= MF_NOGRAVITY; if (Owner->z <= Owner->floorz) { Owner->momz = 4*FRACUNIT; // thrust the player in the air a bit } if (Owner->momz <= -35*FRACUNIT) { // stop falling scream S_StopSound (Owner, CHAN_VOICE); } }
void AInventory::BecomeItem () { if (!(flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) { UnlinkFromWorld (nullptr); flags |= MF_NOBLOCKMAP|MF_NOSECTOR; LinkToWorld (nullptr); } RemoveFromHash (); flags &= ~MF_SPECIAL; ChangeStatNum(STAT_INVENTORY); // stop all sounds this item is playing. for(int i = 1;i<=7;i++) S_StopSound(this, i); SetState (FindState("Held")); }
void DEarthquake::Tick () { int i; if (m_Spot == NULL) { Destroy (); return; } if (!S_IsActorPlayingSomething (m_Spot, CHAN_BODY, m_QuakeSFX)) { S_Sound (m_Spot, CHAN_BODY | CHAN_LOOP, m_QuakeSFX, 1, ATTN_NORM); } if (m_DamageRadius > 0) { for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && !(players[i].cheats & CF_NOCLIP)) { AActor *victim = players[i].mo; fixed_t dist; dist = P_AproxDistance (victim->x - m_Spot->x, victim->y - m_Spot->y); // Check if in damage radius if (dist < m_DamageRadius && victim->z <= victim->floorz) { if (pr_quake() < 50) { P_DamageMobj (victim, NULL, NULL, pr_quake.HitDice (1), NAME_None); } // Thrust player around angle_t an = victim->angle + ANGLE_1*pr_quake(); P_ThrustMobj (victim, an, m_Intensity << (FRACBITS-1)); } } } } if (--m_Countdown == 0) { if (S_IsActorPlayingSomething(m_Spot, CHAN_BODY, m_QuakeSFX)) { S_StopSound(m_Spot, CHAN_BODY); } Destroy(); } }
// // EV_CeilingCrushStop // Stop a ceiling from crushing! // [RH] Passed a tag instead of a line and rewritten to use list // BOOL EV_CeilingCrushStop (int tag) { BOOL rtn = false; DCeiling *scan; TThinkerIterator<DCeiling> iterator; while ( (scan = iterator.Next ()) ) { if (scan->m_Tag == tag && scan->m_Direction != 0) { S_StopSound (scan->m_Sector->soundorg); scan->m_OldDirection = scan->m_Direction; scan->m_Direction = 0; // in-stasis; rtn = true; } } return rtn; }
void DIntermissionScreen::Destroy() { if (mPaletteChanged) { PalEntry *palette; int i; palette = screen->GetPalette (); for (i = 0; i < 256; ++i) { palette[i] = GPalette.BaseColors[i]; } screen->UpdatePalette (); NoWipe = 5; mPaletteChanged = false; M_EnableMenu(true); } S_StopSound(CHAN_VOICE); Super::Destroy(); }
DEFINE_ACTION_FUNCTION(AActor, A_InquisitorCheckLand) { self->reactiontime--; if (self->reactiontime < 0 || self->velx == 0 || self->vely == 0 || self->Z() <= self->floorz) { self->SetState (self->SeeState); self->reactiontime = 0; self->flags &= ~MF_NOGRAVITY; S_StopSound (self, CHAN_ITEM); return; } if (!S_IsActorPlayingSomething (self, CHAN_ITEM, -1)) { S_Sound (self, CHAN_ITEM|CHAN_LOOP, "inquisitor/jump", 1, ATTN_NORM); } }
// // A_Lower // Lowers current weapon, // and changes weapon at bottom. // void A_Lower(player_t* player, pspdef_t* psp) { psp->sy += LOWERSPEED; // Is already down. if(psp->sy < WEAPONBOTTOM ) return; // Player is dead. if(player->playerstate == PST_DEAD) { psp->sy = WEAPONBOTTOM; // don't bring weapon back up return; } // // [d64] stop plasma buzz // if(player->readyweapon == wp_plasma) { pls_buzzing = false; S_StopSound(NULL, sfx_electric); } // The old weapon has been lowered off the screen, // so change the weapon and start raising it if(!player->health) { // Player is dead, so keep the weapon off screen. P_SetPsprite(player, ps_weapon, S_000); return; } P_SetPsprite(player, ps_flash, S_000); //villsa player->readyweapon = player->pendingweapon; P_BringUpWeapon(player); }
DEFINE_ACTION_FUNCTION(AActor, A_AcolyteDie) { int i; // [RH] Disable translucency here. self->RenderStyle = STYLE_Normal; // Only the Blue Acolyte does extra stuff on death. if (self->GetClass()->TypeName != NAME_AcolyteBlue) return; // Make sure somebody is still alive for (i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i] && players[i].health > 0) break; } if (i == MAXPLAYERS) return; // Make sure all the other blue acolytes are dead. TThinkerIterator<AActor> iterator(NAME_AcolyteBlue); AActor *other; while ( (other = iterator.Next ()) ) { if (other != self && other->health > 0) { // Found a living one return; } } players[i].mo->GiveInventoryType (QuestItemClasses[6]); players[i].SetLogNumber (14); S_StopSound (CHAN_VOICE); S_Sound (CHAN_VOICE, "svox/voc14", 1, ATTN_NORM); }
void P_BringUpWeapon(player_t* player) { statenum_t newstate; if(player->pendingweapon == wp_nochange) player->pendingweapon = player->readyweapon; if(player->pendingweapon == wp_chainsaw) S_StartSound(player->mo, sfx_sawup); else if(player->pendingweapon == wp_plasma) { pls_buzzing = true; S_StartSound(player->mo, sfx_electric); } // // [kex] hack for making sure the buzzing sound is stopped // when plasma rifle is not equipped // if(pls_buzzing && player->pendingweapon != wp_plasma) { pls_buzzing = false; S_StopSound(NULL, sfx_electric); } newstate = weaponinfo[player->pendingweapon].upstate; player->pendingweapon = wp_nochange; player->psprites[ps_weapon].sx = FRACUNIT; player->psprites[ps_weapon].sy = WEAPONBOTTOM; player->psprites[ps_weapon].alpha = 0xff; player->psprites[ps_flash].alpha = 0xff; P_SetPsprite(player, ps_weapon, newstate); }
/* ===================== CL_ParseServerMessage ===================== */ void CL_ParseServerMessage(void) { unsigned int bits; int i, cmd, prevcmd; int playernum, version, stylenum, signon, statnum; int stopsound, entitynum, channel; byte colors; player_info_t *player; lightstyle_t *style; const char *stylemap, *name; // // if recording demos, copy the message out // if (cl_shownet.value == 1) Con_Printf("%i ", net_message.cursize); else if (cl_shownet.value == 2) Con_Printf("------------------\n"); cl.onground = false; // unless the server says otherwise // // parse the message // prevcmd = svc_bad; MSG_BeginReading(); while (1) { if (msg_badread) Host_Error("%s: Bad server message", __func__); cmd = MSG_ReadByte(); if (cmd == -1) { SHOWNET("END OF MESSAGE"); return; // end of message } // if the high bit of the command byte is set, it is a fast update if (cmd & 128) { SHOWNET("fast update"); CL_ParseUpdate(cmd & 127); continue; } SHOWNET(svc_strings[cmd]); // other commands switch (cmd) { case svc_nop: break; case svc_time: cl.mtime[1] = cl.mtime[0]; cl.mtime[0] = MSG_ReadFloat(); break; case svc_clientdata: CL_ParseClientdata(); break; case svc_version: version = MSG_ReadLong(); if (!Protocol_Known(version)) Host_Error("%s: Server returned unknown protocol version %i", __func__, version); cl.protocol = version; break; case svc_disconnect: Host_EndGame("Server disconnected\n"); case svc_print: Con_Printf("%s", MSG_ReadString()); break; case svc_centerprint: SCR_CenterPrint(MSG_ReadString()); break; case svc_stufftext: Cbuf_AddText("%s", MSG_ReadString()); break; case svc_damage: V_ParseDamage(); break; case svc_serverinfo: CL_ParseServerInfo(); vid.recalc_refdef = true; // leave intermission full screen break; case svc_setangle: for (i = 0; i < 3; i++) cl.viewangles[i] = MSG_ReadAngle(); break; case svc_setview: cl.viewentity = MSG_ReadShort(); break; case svc_lightstyle: stylenum = MSG_ReadByte(); if (stylenum >= MAX_LIGHTSTYLES) Sys_Error("svc_lightstyle > MAX_LIGHTSTYLES"); stylemap = MSG_ReadString(); style = cl_lightstyle + stylenum; snprintf(style->map, MAX_STYLESTRING, "%s", stylemap); style->length = strlen(style->map); break; case svc_sound: CL_ParseStartSoundPacket(); break; case svc_stopsound: stopsound = MSG_ReadShort(); /* 3-bit channel encoded in lsb */ entitynum = stopsound >> 3; channel = stopsound & 7; S_StopSound(entitynum, channel); break; case svc_updatename: Sbar_Changed(); playernum = MSG_ReadByte(); if (playernum >= cl.maxclients) Host_Error("%s: svc_updatename > MAX_SCOREBOARD", __func__); name = MSG_ReadString(); player = cl.players + playernum; snprintf(player->name, MAX_SCOREBOARDNAME, "%s", name); break; case svc_updatefrags: Sbar_Changed(); playernum = MSG_ReadByte(); if (playernum >= cl.maxclients) Host_Error("%s: svc_updatefrags > MAX_SCOREBOARD", __func__); player = cl.players + playernum; player->frags = MSG_ReadShort(); break; case svc_updatecolors: Sbar_Changed(); playernum = MSG_ReadByte(); if (playernum >= cl.maxclients) Host_Error("%s: svc_updatecolors > MAX_SCOREBOARD", __func__); colors = MSG_ReadByte(); player = cl.players + playernum; player->topcolor = (colors & 0xf0) >> 4; player->bottomcolor = colors & 0x0f; /* FIXME - is this the right check for current player? */ if (playernum == cl.viewentity) cl_color.value = colors; CL_NewTranslation(playernum); break; case svc_particle: R_ParseParticleEffect(); break; case svc_spawnbaseline: entitynum = MSG_ReadShort(); // must use CL_EntityNum() to force cl.num_entities up CL_ParseBaseline(CL_EntityNum(entitynum), 0); break; case svc_fitz_spawnbaseline2: /* FIXME - check here that protocol is FITZ? => Host_Error() */ entitynum = MSG_ReadShort(); bits = MSG_ReadByte(); // must use CL_EntityNum() to force cl.num_entities up CL_ParseBaseline(CL_EntityNum(entitynum), bits); break; case svc_spawnstatic: CL_ParseStatic(0); break; case svc_fitz_spawnstatic2: /* FIXME - check here that protocol is FITZ? => Host_Error() */ bits = MSG_ReadByte(); CL_ParseStatic(bits); break; case svc_temp_entity: CL_ParseTEnt(); break; case svc_setpause: cl.paused = MSG_ReadByte(); if (cl.paused) CDAudio_Pause(); else CDAudio_Resume(); break; case svc_signonnum: signon = MSG_ReadByte(); if (signon <= cls.signon) Host_Error("Received signon %d when at %d", signon, cls.signon); cls.signon = signon; CL_SignonReply(); break; case svc_killedmonster: cl.stats[STAT_MONSTERS]++; break; case svc_foundsecret: cl.stats[STAT_SECRETS]++; break; case svc_updatestat: statnum = MSG_ReadByte(); if (statnum < 0 || statnum >= MAX_CL_STATS) Sys_Error("svc_updatestat: %d is invalid", statnum); cl.stats[statnum] = MSG_ReadLong(); break; case svc_spawnstaticsound: CL_ParseStaticSound(); break; case svc_fitz_spawnstaticsound2: /* FIXME - check here that protocol is FITZ? => Host_Error() */ CL_ParseFitzStaticSound2(); break; case svc_cdtrack: cl.cdtrack = MSG_ReadByte(); cl.looptrack = MSG_ReadByte(); if ((cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1)) CDAudio_Play((byte)cls.forcetrack, true); else CDAudio_Play((byte)cl.cdtrack, true); break; case svc_intermission: cl.intermission = 1; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen break; case svc_finale: cl.intermission = 2; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint(MSG_ReadString()); break; case svc_cutscene: cl.intermission = 3; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint(MSG_ReadString()); break; case svc_sellscreen: Cmd_ExecuteString("help", src_command); break; /* Various FITZ protocol messages - FIXME - !protocol => Host_Error */ case svc_fitz_skybox: MSG_ReadString(); // FIXME - TODO break; case svc_fitz_bf: Cmd_ExecuteString("bf", src_command); break; case svc_fitz_fog: /* FIXME - TODO */ MSG_ReadByte(); // density MSG_ReadByte(); // red MSG_ReadByte(); // green MSG_ReadByte(); // blue MSG_ReadShort(); // time break; default: Host_Error("%s: Illegible server message. Previous was %s", __func__, svc_strings[prevcmd]); } prevcmd = cmd; } }
static void PickConversationReply () { const char *replyText = NULL; FStrifeDialogueReply *reply = (FStrifeDialogueReply *)ConversationItems[ConversationMenu.lastOn].c.extra; bool takestuff; int i; M_ClearMenus (); CleanupConversationMenu (); if (reply == NULL) { return; } // Check if you have the requisite items for this choice for (i = 0; i < 3; ++i) { if (!CheckStrifeItem (reply->ItemCheck[i], reply->ItemCheckAmount[i])) { // No, you don't. Say so and let the NPC animate negatively. if (reply->QuickNo) { Printf ("%s\n", reply->QuickNo); } ConversationNPC->ConversationAnimation (2); return; } } // Yay, you do! Let the NPC animate affirmatively. ConversationNPC->ConversationAnimation (1); // If this reply gives you something, then try to receive it. takestuff = true; if (reply->GiveType != NULL) { AInventory *item = static_cast<AInventory *> (Spawn (reply->GiveType, 0, 0, 0)); // Items given here should not count as items! if (item->flags & MF_COUNTITEM) { level.total_items--; item->flags &= ~MF_COUNTITEM; } item->flags |= MF_DROPPED; if (!item->TryPickup (players[consoleplayer].mo)) { item->Destroy (); takestuff = false; } } // Take away required items if the give was successful or none was needed. if (takestuff) { for (i = 0; i < 3; ++i) { TakeStrifeItem (reply->ItemCheck[i], reply->ItemCheckAmount[i]); } replyText = reply->QuickYes; } else { replyText = "You seem to have enough!"; } // Update the quest log, if needed. if (reply->LogNumber != 0) { players[consoleplayer].SetLogNumber (reply->LogNumber); } // Does this reply alter the speaker's conversation node? If NextNode is positive, // the next time they talk, the will show the new node. If it is negative, then they // will show the new node right away without terminating the dialogue. if (reply->NextNode != 0) { int rootnode = FindNode (ConversationNPC->GetDefault()->Conversation); if (reply->NextNode < 0) { ConversationNPC->Conversation = StrifeDialogues[rootnode - reply->NextNode - 1]; if (gameaction != ga_slideshow) { P_StartConversation (ConversationNPC, players[consoleplayer].mo); return; } else { S_StopSound (ConversationNPC, CHAN_VOICE); } } else { ConversationNPC->Conversation = StrifeDialogues[rootnode + reply->NextNode - 1]; } } if (replyText != NULL) { Printf ("%s\n", replyText); } ConversationNPC->angle = ConversationNPCAngle; }
// // T_MoveCeiling // void DCeiling::RunThink () { EResult res; switch (m_Direction) { case 0: // IN STASIS break; case 1: // UP res = MoveCeiling (m_Speed, m_TopHeight, m_Direction); if (res == pastdest) { S_StopSound (m_Sector->soundorg); S_Sound (m_Sector->soundorg, CHAN_BODY, "plats/pt1_stop", 1, ATTN_NORM); switch (m_Type) { case ceilCrushAndRaise: m_Direction = -1; m_Speed = m_Speed1; PlayCeilingSound (); break; // movers with texture change, change the texture then get removed case genCeilingChgT: case genCeilingChg0: m_Sector->special = m_NewSpecial; case genCeilingChg: m_Sector->ceilingpic = m_Texture; // fall through default: Destroy (); break; } } break; case -1: // DOWN res = MoveCeiling (m_Speed, m_BottomHeight, m_Crush, m_Direction); if (res == pastdest) { S_StopSound (m_Sector->soundorg); S_Sound (m_Sector->soundorg, CHAN_BODY, "plats/pt1_stop", 1, ATTN_NORM); switch (m_Type) { case ceilCrushAndRaise: case ceilCrushRaiseAndStay: m_Speed = m_Speed2; m_Direction = 1; PlayCeilingSound (); break; // in the case of ceiling mover/changer, change the texture // then remove the active ceiling case genCeilingChgT: case genCeilingChg0: m_Sector->special = m_NewSpecial; case genCeilingChg: m_Sector->ceilingpic = m_Texture; // fall through default: Destroy (); break; } } else // ( res != pastdest ) { if (res == crushed) { switch (m_Type) { case ceilCrushAndRaise: case ceilLowerAndCrush: if (m_Speed1 == FRACUNIT && m_Speed2 == FRACUNIT) m_Speed = FRACUNIT / 8; break; default: break; } } } break; } }
//================================================================== // // T_VerticalDoor // //================================================================== void T_VerticalDoor(vldoor_t * door) { result_e res; switch (door->direction) { case 0: // WAITING if (!--door->topcountdown) switch (door->type) { case normal: door->direction = -1; // time to go back down S_StartSound(&door->sector->soundorg, sfx_doropn); break; case close30ThenOpen: door->direction = 1; S_StartSound(&door->sector->soundorg, sfx_doropn); break; default: break; } break; case 2: // INITIAL WAIT if (!--door->topcountdown) { switch (door->type) { case raiseIn5Mins: door->direction = 1; door->type = normal; S_StartSound(&door->sector->soundorg, sfx_doropn); break; default: break; } } break; case -1: // DOWN res = T_MovePlane(door->sector, door->speed, door->sector->floorheight, false, 1, door->direction); if (res == pastdest) { switch (door->type) { case normal: case close: door->sector->specialdata = NULL; P_RemoveThinker(&door->thinker); // unlink and free S_StartSound(&door->sector->soundorg, sfx_dorcls); break; case close30ThenOpen: door->direction = 0; door->topcountdown = 35 * 30; break; default: break; } } else if (res == crushed) { switch (door->type) { case close: // DON'T GO BACK UP! break; default: door->direction = 1; S_StartSound(&door->sector->soundorg, sfx_doropn); break; } } break; case 1: // UP res = T_MovePlane(door->sector, door->speed, door->topheight, false, 1, door->direction); if (res == pastdest) { switch (door->type) { case normal: door->direction = 0; // wait at top door->topcountdown = door->topwait; break; case close30ThenOpen: case open: door->sector->specialdata = NULL; P_RemoveThinker(&door->thinker); // unlink and free S_StopSound(&door->sector->soundorg); break; default: break; } } break; } }
void P_Stop(void) { int i = 0; int action = gameaction; // // [d64] stop plasma buzz // S_StopSound(NULL, sfx_electric); for(i = 0; i < MAXPLAYERS; i++) { // take away cards and stuff if(playeringame[i]) { G_PlayerFinishLevel(i); } } // [kex] reset damage indicators if(p_damageindicator.value) { ST_ClearDamageMarkers(); } // free level tags Z_FreeTags(PU_LEVEL, PU_PURGELEVEL-1); if(automapactive) { AM_Stop(); } // music continues on exit if defined if(!P_GetMapInfo(gamemap)->contmusexit) { S_StopMusic(); } // end iwad demo playback here if(demoplayback && iwadDemo) { demoplayback = false; iwadDemo = false; } // do wipe/melt effect if(gameaction != ga_loadgame) { if(r_wipe.value) { if(gameaction != ga_warpquick) { WIPE_MeltScreen(); } else { S_StopMusic(); WIPE_FadeScreen(8); } } else { if(gameaction == ga_warpquick) { S_StopMusic(); } } } S_ResetSound(); // action is warpquick only because the user // cancelled demo playback... // boot the user back to the title screen if(gameaction == ga_warpquick && demoplayback) { gameaction = ga_title; demoplayback = false; } else { gameaction = action; } }
void A_ShutUp (AActor *self) { S_StopSound (self, CHAN_ITEM); }
/* * Read a sound delta from the message buffer and play it. * Only used with psv_frame2 packets. */ void Cl_ReadSoundDelta2(deltatype_t type, boolean skip) { int sound = 0, soundFlags = 0; byte flags = 0; clmobj_t *cmo = NULL; thid_t mobjId = 0; sector_t *sector = NULL; polyobj_t *poly = NULL; mobj_t *emitter = NULL; float volume = 1; if(type == DT_SOUND) { // Delta ID is the sound ID. sound = Msg_ReadShort(); } else if(type == DT_MOBJ_SOUND) { if((cmo = Cl_FindMobj(mobjId = Msg_ReadShort())) != NULL) { if(cmo->flags & CLMF_HIDDEN) { // We can't play sounds from hidden mobjs, because we // aren't sure exactly where they are located. cmo = NULL; } else { emitter = &cmo->mo; } } } else if(type == DT_SECTOR_SOUND) { int index = (ushort) Msg_ReadShort(); if(index < numsectors) { sector = SECTOR_PTR(index); emitter = (mobj_t *) §or->soundorg; } } else /* DT_POLY_SOUND */ { int index = (ushort) Msg_ReadShort(); if(index < po_NumPolyobjs) { poly = PO_PTR(index); emitter = (mobj_t *) &poly->startSpot; } } flags = Msg_ReadByte(); if(type != DT_SOUND) { // The sound ID. sound = Msg_ReadShort(); } if(flags & SNDDF_VOLUME) { byte b = Msg_ReadByte(); if(b == 255) { // Full volume, no attenuation. soundFlags |= DDSF_NO_ATTENUATION; } else { volume = b / 127.0f; } } if(flags & SNDDF_REPEAT) { soundFlags |= DDSF_REPEAT; } // The delta has been read. Are we skipping? if(skip) return; // Now the entire delta has been read. // Should we start or stop a sound? if(volume > 0 && sound > 0) { // Do we need to queue this sound? if(type == DT_MOBJ_SOUND && !cmo) { // Create a new Hidden clmobj. cmo = Cl_CreateMobj(mobjId); cmo->flags |= CLMF_HIDDEN | CLMF_SOUND; cmo->sound = sound; cmo->volume = volume; /*#ifdef _DEBUG Con_Printf("Cl_ReadSoundDelta2(%i): Queueing: id=%i snd=%i vol=%.2f\n", type, mobjId, sound, volume); #endif */ // The sound will be started when the clmobj is unhidden. return; } // We will start a sound. if(type != DT_SOUND && !emitter) { // Not enough information. #ifdef _DEBUG Con_Printf("Cl_ReadSoundDelta2(%i): Insufficient data, snd=%i\n", type, sound); #endif return; } // Sounds originating from the viewmobj should really originate // from the real player mobj. if(cmo && cmo == playerstate[consoleplayer].cmo) { /*#ifdef _DEBUG Con_Printf("Cl_ReadSoundDelta2(%i): ViewMobj sound...\n", type); #endif */ emitter = players[consoleplayer].mo; } // First stop any sounds originating from the same emitter. // We allow only one sound per emitter. if(type != DT_SOUND && emitter) { S_StopSound(0, emitter); } S_LocalSoundAtVolume(sound | soundFlags, emitter, volume); /*#ifdef _DEBUG Con_Printf("Cl_ReadSoundDelta2(%i): Start snd=%i [%x] vol=%.2f", type, sound, flags, volume); if(cmo) Con_Printf(", mo=%i\n", cmo->mo.thinker.id); else if(sector) Con_Printf(", sector=%i\n", GET_SECTOR_IDX(sector)); else if(poly) Con_Printf(", poly=%i\n", GET_POLYOBJ_IDX(poly)); else Con_Printf("\n"); #endif */ } else if(sound >= 0) { // We must stop a sound. We'll only stop sounds from // specific sources. if(emitter) { S_StopSound(sound, emitter); /*#ifdef _DEBUG Con_Printf("Cl_ReadSoundDelta2(%i): Stop sound %i", type, sound); if(cmo) Con_Printf(", mo=%i\n", cmo->mo.thinker.id); else if(sector) Con_Printf(", sector=%i\n", GET_SECTOR_IDX(sector)); else if(poly) Con_Printf(", poly=%i\n", GET_POLYOBJ_IDX(poly)); else Con_Printf("\n"); #endif */ } } }