UBOOL USwFMOD::PlaySound ( AActor* Actor, INT Id, USound* Sound, FVector Location, FLOAT Volume, FLOAT Radius, FLOAT Pitch ) { guard(USwFMOD::PlaySound); //SWF_LOG( NAME_DevSound, TEXT("%s >> %s :: [%s],[%s],[%s],[%s],[%s],[%s],[%s]"), SWF_PLOG, *ToStr(FSwSoundId(Id)), *ToStr(Actor,true), *ToStr(Sound), *ToStr(Location), *ToStr(Volume), *ToStr(Radius), *ToStr(Pitch) ); FMOD_RESULT result; if( !Viewport || !Sound ) return 0; // Sound slot rules FSwSoundId SoundId = FSwSoundId(Id); if( SoundId.GetSlot() != SLOT_None ) { for( FSwChannelEnumerator it(System); it; ++it ) { FMOD::Channel* channel = *it; if( IsChannelValid(channel) ) { FSwSoundId cid = GetChannelId(channel); // If Actor is the same and Slot is the same: // - prevent this sound from plaing if NoOverride // - stop the old sound otherwise if( cid.GetSlot() == SoundId.GetSlot() && cid.GetActor() == SoundId.GetActor() ) { if( cid.GetNoOverride() ) { //SWF_LOG( NAME_DevSound, TEXT("%s -- %s :: NO OVERRIDE <%s> <%s>"), SWF_PLOG, *ToStr(FSwSoundId(Id)), *PrintChannel(channel) ); return 0; } //SWF_LOG( NAME_DevSound, TEXT("%s -- %s :: STOP <%s> <%s>"), SWF_PLOG, *ToStr(SoundId), *PrintChannel(channel) ); SWF_FMOD_CALL( channel->setUserData(NULL) ); SWF_FMOD_CALL( channel->stop() ); } } } } // Register sample FMOD::Sound* sample = RegisterSoundSample(Sound); if( !sample ) return 0; // Sample defaults FLOAT deffrequency; FLOAT defvolume; FLOAT defpanning; INT defpriority; FMOD_MODE fmode; SWF_FMOD_RCALL0( sample->getDefaults( &deffrequency, &defvolume, &defpanning, &defpriority ) ); SWF_FMOD_RCALL0( sample->getMode(&fmode) ); // Channel defaults FMOD::ChannelGroup* channelgroup = EffectChannels; FMOD_CHANNELINDEX channelindex = FMOD_CHANNEL_FREE; FLOAT mindist = ToFMODFloat(DistanceMin); FLOAT radius = ToFMODFloat(Radius); TSwSortMinMax( mindist, radius ); FMOD_VECTOR location = ToFMODVector(Location); FMOD_VECTOR velocity = ToFMODNormal(FVector(0,0,0)); FLOAT frequency = deffrequency * Pitch; FLOAT volume = defvolume * Volume; FLOAT panning = defpanning * 1.0f; INT priority = PrioritySound; // 2D or 3D? AActor* ViewActor = Viewport->Actor->ViewTarget ? Viewport->Actor->ViewTarget : Viewport->Actor; UBOOL bIs3D = Actor && (b3DCameraSounds || Actor != ViewActor); if( bIs3D ) { fmode &= ~FMOD_2D; fmode |= FMOD_3D | FMOD_3D_LINEARROLLOFF; // Radius, location & Velocity FMOD_VECTOR location = ToFMODVector(Actor->Location); FMOD_VECTOR velocity = ToFMODVector(Actor->Velocity); SWF_VERIFY_FLOAT( mindist ); SWF_VERIFY_FLOAT( radius ); SWF_VERIFY_FMODVECTOR( location ); SWF_VERIFY_FMODVECTOR( velocity ); } else { fmode &= ~FMOD_3D; fmode |= FMOD_2D; } // Sound effects other than WAV go into compressed group (conversations most likely) if( Sound->FileType != SoundType_WAV ) { priority = PrioritySpeech; channelgroup = CompressedChannels; //fmode |= FMOD_CREATESTREAM; } // Ambient sounds if( SoundId.GetSlot() == SLOT_Ambient ) { priority = PriorityAmbient; channelgroup = AmbientChannels; fmode &= ~FMOD_LOOP_OFF; fmode |= FMOD_LOOP_NORMAL; } // Update FMOD to free finished channels guard(UpdateFMOD); SWF_FMOD_RCALL0( System->update() ); unguard; // Play sound FMOD::Channel* channel; SWF_FMOD_RCALL0( System->playSound(channelindex, sample, true, &channel) ); // SWF_FMOD_RCALL0( VerifyNewChannel(channel) ); // Update channel SWF_FMOD_RCALL0( channel->setUserData( SoundId.ToUserData() ) ); SWF_FMOD_RCALL0( channel->setChannelGroup(channelgroup) ); SWF_FMOD_RCALL0( channel->setMode(fmode) ); if( HasFlag(fmode,FMOD_3D) ) { SWF_FMOD_RCALL0( channel->set3DMinMaxDistance(mindist, radius) ); SWF_FMOD_RCALL0( channel->set3DAttributes(&location,&velocity) ); } else { SWF_FMOD_RCALL0( channel->setPan(panning) ); } SWF_FMOD_RCALL0( channel->setFrequency(frequency) ); SWF_FMOD_RCALL0( channel->setVolume(volume) ); SWF_FMOD_RCALL0( channel->setPriority(priority) ); SWF_FMOD_RCALL0( channel->setPaused(false) ); // Apply channel group's properties ApplyChannelGroup(channelgroup); // Update FMOD to apply channel updates immediately guard(UpdateFMOD); SWF_FMOD_RCALL0( System->update() ); unguard; //SWF_LOG( NAME_DevSound, TEXT("%s << %s :: [%s],[%s],[%s],[%s],[%s],[%s],[%s]"), SWF_PLOG, *ToStr(Actor,true), *ToStr(Id), *ToStr(Sound), *ToStr(Location), *ToStr(Volume), *ToStr(Radius), *ToStr(Pitch) ); return 1; unguard; }
// done 0x03 void Channel::MakeYouLeft(WorldPacket *data) { MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE); *data << uint32(GetChannelId()); *data << uint8(IsConstant()); }
// done 0x03 void Channel::MakeYouLeft(WorldPacket* data) { MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE); *data << uint32(GetChannelId()); *data << uint8(0); // can be 0x00 and 0x01 }
void USwFMOD::Update( FPointRegion Region, FCoords& Coords ) { guard(USwFMOD::Update); FMOD_RESULT result; //SWF_LOG( NAME_DevSound, TEXT("%s >> %s :: [%s],[%s]"), SWF_PLOG, *ToStr(Region), *ToStr(Coords) ); if( !Viewport || !Viewport->IsValid() || !Viewport->Actor || !Viewport->Actor->IsValid() ) return; // Load geometry if( bOcclusion ) { static ULevel* level = NULL; if( Viewport->Actor->GetLevel() != level ) { level = Viewport->Actor->GetLevel(); LoadGeometry(); } } // Time passes... DOUBLE DeltaTime = appSeconds() - LastTime; LastTime += DeltaTime; DeltaTime = Clamp( DeltaTime, 0.0, 1.0 ); // Get viewactor AActor* ViewActor = Viewport->Actor->ViewTarget ? Viewport->Actor->ViewTarget : Viewport->Actor; // Is viewport realtime ? UBOOL Realtime = Viewport->IsRealtime() && Viewport->Actor->Level->Pauser == TEXT(""); // Default viewport coords FVector location = FVector(0,0,0); FVector velocity = FVector(0,0,0); FVector forward = FVector(1,0,0); FVector up = FVector(0,0,1); // // Update listener // guard(USwFMODAudio::Update::UpdateListener); // Use ViewActor coords FCoords coords = GMath.UnitCoords / ViewActor->Rotation;; coords.Origin = ViewActor->Location; // Set viewport coords location = coords.Origin; velocity = ViewActor->Velocity; forward = coords.XAxis; up = coords.ZAxis; // verify SWF_VERIFY_FVECTOR(location); SWF_VERIFY_FVECTOR(velocity); SWF_VERIFY_FVECTOR_NORMAL(forward); SWF_VERIFY_FVECTOR_NORMAL(up); // Default listener coords FMOD_VECTOR fm_pos = {0,0,0}; FMOD_VECTOR fm_vel = {0,0,0}; FMOD_VECTOR fm_fwd = {0,0,1}; FMOD_VECTOR fm_up = {0,1,0}; // Set listener coords fm_pos = ToFMODVector(location); fm_vel = ToFMODVector(velocity); fm_fwd = ToFMODNormal(forward); fm_up = ToFMODNormal(up); // verify SWF_VERIFY_FMODVECTOR(fm_pos); SWF_VERIFY_FMODVECTOR(fm_vel); SWF_VERIFY_FMODVECTOR_NORMAL(fm_fwd); SWF_VERIFY_FMODVECTOR_NORMAL(fm_up); // Update SWF_FMOD_CALL( System->set3DListenerAttributes( 0, &fm_pos, &fm_vel, &fm_fwd, &fm_up ) ); unguard; // // Zone effects // guard(USwFMODAudio::Update::UpdateZone); /*// Default zone properties UBOOL bWaterZone = 0; UBOOL bReverbZone = 0; UBOOL bRaytraceReverb = 0; BYTE MasterGain = 100; INT CutoffHz = 6000; BYTE Delay[6] = {20,34,0,0,0,0}; BYTE Gain[6] = {150,70,0,0,0,0}; // Get zone properties if( Region.Zone && Region.Zone->IsValid() ) { bWaterZone = Region.Zone->bWaterZone; bReverbZone = Region.Zone->bReverbZone; bRaytraceReverb = Region.Zone->bRaytraceReverb; MasterGain = Region.Zone->MasterGain; CutoffHz = Region.Zone->CutoffHz; appMemcpy(Delay, Region.Zone->Delay, 6*sizeof(BYTE)); appMemcpy(Gain, Region.Zone->Gain, 6*sizeof(BYTE)); }*/ unguard; // // Update sounds. // guard(USwFMODAudio::Update::UpdateSounds); // Iterate through all channels for( FSwChannelEnumerator it(System); it; ++it ) { FMOD::Channel* channel = *it; if( !IsChannelValid(channel) ) continue; // Channel data FMOD::Sound* sample = GetChannelSample(channel); if( !sample ) continue; UObject* object = GetSampleObject(sample); if( !object ) continue; USound* sound = Cast<USound>(object); FSwSoundId id = GetChannelId(channel); AActor* actor = id.GetActor(); FMOD_MODE fmode; SWF_FMOD_CALL( channel->getMode(&fmode) ); UBOOL bIs3D = HasFlag(fmode,FMOD_3D); // Sample defaults FLOAT deffrequency; FLOAT defvolume; FLOAT defpanning; INT defpriority; SWF_FMOD_CALL( sample->getDefaults( &deffrequency, &defvolume, &defpanning, &defpriority ) ); if( sound ) { if( actor && actor->IsValid() ) { // Ambient sounds if( id.GetSlot() == SLOT_Ambient ) { if( actor->AmbientSound != sound || FDist(location, actor->Location) > actor->WorldSoundRadius() + AmbientHysteresis || !Realtime ) { // Stop ambient sound //SWF_LOG( NAME_DevSound, TEXT("%s -- %s :: Ambient OUT [%d]"), SWF_PLOG, *ToStr(id) ); SWF_FMOD_CALL( channel->setUserData(NULL) ); SWF_FMOD_CALL( channel->stop() ); continue; } else { // Update ambient sound properties. FLOAT volume = actor->SoundVolume / 255.0f; FLOAT frequency = (actor->SoundPitch / 64.0f) * deffrequency; SWF_VERIFY_FLOAT(volume); SWF_VERIFY_FLOAT(frequency); SWF_FMOD_CALL( channel->setVolume( volume ) ); SWF_FMOD_CALL( channel->setFrequency( frequency ) ); if( bIs3D ) { // Update 3D sound properties FLOAT mindist = ToFMODFloat(DistanceMin); FLOAT radius = ToFMODFloat( actor->WorldSoundRadius() ); TSwSortMinMax( mindist, radius ); SWF_VERIFY_FLOAT(radius); SWF_VERIFY_FLOAT(mindist); SWF_FMOD_CALL( channel->set3DMinMaxDistance( mindist, radius ) ); } } } if( bIs3D ) { // Update 3D sound properties FMOD_VECTOR snd_pos = ToFMODVector(actor->Location); FMOD_VECTOR snd_vel = ToFMODVector(actor->Velocity); SWF_VERIFY_FMODVECTOR(snd_pos); SWF_VERIFY_FMODVECTOR(snd_vel); SWF_FMOD_CALL( channel->set3DAttributes(&snd_pos, &snd_vel) ); } } } } unguard; // // Play ambient sounds // if( Realtime ) { guard(USwFMODAudio::Update::PlayAmbient); for( INT i=0; i<Viewport->Actor->GetLevel()->Actors.Num(); ++i ) { AActor* Actor = Viewport->Actor->GetLevel()->Actors(i); if( Actor && Actor->AmbientSound && FDist(location, Actor->Location) <= Actor->WorldSoundRadius() ) { FSwSoundId ambientid = FSwSoundId(Actor,SLOT_Ambient,0); //SWF_LOG( NAME_DevSound, TEXT("%s -- %s :: Ambient TEST IN [%s]"), SWF_PLOG, *ToStr(ambientid) ); // Find this sound in currently playing ones FMOD::Channel* ambientchannel = NULL; for( FSwChannelEnumerator it(System,AmbientChannels); it; ++it ) { FMOD::Channel* channel = *it; if( IsChannelValid(channel) && GetChannelId(channel) == ambientid ) { //SWF_LOG( NAME_DevSound, TEXT("%s -- %s :: Ambient FOUND IN [%s]"), SWF_PLOG, *ToStr(GetChannelId(channel)) ); ambientchannel = channel; break; } } // If not found play ambient if( !ambientchannel ) { //SWF_LOG( NAME_DevSound, TEXT("%s -- %s :: Ambient PLAY IN [%s][%s]"), SWF_PLOG, *ToStr(ambientid), *ToStr(Actor->AmbientSound) ); PlaySound( Actor, ambientid.GetId(), Actor->AmbientSound, Actor->Location, Actor->SoundVolume/255.0f, Actor->WorldSoundRadius(), Actor->SoundPitch/64.0f ); } } } unguard; } // // Music // guard(UpdateMusic) /* REQUIREMENTS SongSection is updated at realtime by audio sys MTRAN_Fade* only fade out, not in music changes caused by transition only ttransition reset on change MTRAN_None = don't change MTRAN_Instant = instant change MTRAN_Segue = seamless? MTRAN_Fade = 1s fade MTRAN_FastFade = 1/3s fade MTRAN_SlowFade = 5s fade */ // find music channel FMOD::Channel* musicchannel = NULL; for( FSwChannelEnumerator it(System,MusicChannels); it; ++it ) { FMOD::Channel* channel = *it; if( !IsChannelValid(channel) ) continue; if( !musicchannel ) { musicchannel = channel; } else { // there can be only one music SWF_LOG( NAME_DevSound, TEXT("%s :: %s :: StopMusic %s"), SWF_PLOG, *PrintChannel(channel) ); SWF_FMOD_CALL( channel->setUserData(NULL) ); SWF_FMOD_CALL( channel->stop() ); } } if( Viewport->Actor->Transition != MTRAN_None ) { // init fading if( MusicFade < 0 ) { SWF_LOG( NAME_DevSound, TEXT("%s :: %s :: Music transition %s S:%s T:%s "), SWF_PLOG , *ToStr(Viewport->Actor->Song) , *ToStr(Viewport->Actor->SongSection) , *ToStr(Viewport->Actor->Transition)); switch( Viewport->Actor->Transition ) { case MTRAN_Instant: MusicFadeTime = -1.0f; break; // Instant case MTRAN_Segue: MusicFadeTime = -1.0f; // Instant precached if( Viewport->Actor->Song && !Viewport->Actor->Song->Handle ) RegisterMusic(Viewport->Actor->Song); break; case MTRAN_Fade: MusicFadeTime = 1.0f; break; // 1s fadeout case MTRAN_FastFade: MusicFadeTime = 0.33f; break; // 1/3s fadeout case MTRAN_SlowFade: MusicFadeTime = 5.0f; break; // 5s fadeout default: MusicFadeTime = -1.0f; break; // Unknown,instant } MusicFade = MusicFadeTime; } // deduct delta MusicFade -= DeltaTime; //SWF_LOG( NAME_DevSound, TEXT("%s << %s :: MusicFade %s %s"), SWF_PLOG, *ToStr(MusicFade), *ToStr(MusicFadeTime) ); if( MusicFade > 0 ) { // fade volume if( musicchannel && MusicFadeTime > 0 ) { SWF_FMOD_CALL( musicchannel->setVolume( MusicFade / MusicFadeTime) ); } } else { // play new MusicFade = -1; Viewport->Actor->Transition = MTRAN_None; PlayMusic( Viewport->Actor->Song, musicchannel, Viewport->Actor->SongSection, Viewport->Actor->CdTrack, static_cast<EMusicTransition>(Viewport->Actor->Transition) ); } } else { // Update section if( musicchannel ) { // update section // FIXME:: getPosition doesn't work with volume 0 (virtual?) UINT sec = 0; result = musicchannel->getPosition(&sec,FMOD_TIMEUNIT_MODORDER); if( result == FMOD_OK ) { Viewport->Actor->SongSection = sec; } // Update position if( IsChannelValid(musicchannel) ) { UINT row = 0; result = musicchannel->getPosition(&row,FMOD_TIMEUNIT_MODROW); if( result == FMOD_OK ) { // IT/MOD/XM UINT pattern = 0; result = musicchannel->getPosition(&pattern,FMOD_TIMEUNIT_MODPATTERN); if( result == FMOD_OK ) { MusicPositions(Viewport->Actor->SongSection).row = row; MusicPositions(Viewport->Actor->SongSection).pattern = pattern; } } else { // MPEG/OGG UINT ms = 0; result = musicchannel->getPosition(&ms,FMOD_TIMEUNIT_MS); if( result == FMOD_OK ) { MusicPositions(Viewport->Actor->SongSection).ms = ms; } } } } else if( Viewport->Actor->Song && VolumeMusic > 0 ) { // Restart missing/dropped song (bad channel priorities?) SWF_LOG( NAME_DevSound, TEXT("%s :: %s :: Restarting missing song %s S:%s T:%s "), SWF_PLOG , *ToStr(Viewport->Actor->Song) , *ToStr(Viewport->Actor->SongSection) , *ToStr(Viewport->Actor->Transition)); Viewport->Actor->Transition = MTRAN_Instant; } } unguard; // Update FMOD guard(UpdateFMOD); SWF_FMOD_CALL( System->update() ); unguard; //SWF_LOG( NAME_DevSound, TEXT("%s << %s :: [%s],[%s]"), SWF_PLOG, *ToStr(Region), *ToStr(Coords) ); unguard; }
void Channel::Say(ObjectGuid p, const char* what, uint32 lang) { if (!what) return; if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) lang = LANG_UNIVERSAL; uint32 sec = 0; Player* plr = sObjectMgr.GetPlayer(p); bool speakInLocalDef = false; bool speakInWorldDef = false; if (plr) { sec = plr->GetSession()->GetSecurity(); if (plr->isGameMaster()) { speakInLocalDef = true; // speakInWorldDef = true; } HonorRankInfo honorInfo = plr->GetHonorRankInfo(); //We can speak in local defense if we're above this rank (see .h file) if (honorInfo.rank >= SPEAK_IN_LOCALDEFENSE_RANK) speakInLocalDef = true; // Are we not allowed to speak in WorldDefense at all? // if (honorInfo.rank >= SPEAK_IN_WORLDDEFENSE_RANK) // speakInWorldDef = true; } if (!IsOn(p)) { WorldPacket data; MakeNotMember(&data); SendToOne(&data, p); } else if (m_players[p].IsMuted() || (GetChannelId() == CHANNEL_ID_LOCAL_DEFENSE && !speakInLocalDef) || (GetChannelId() == CHANNEL_ID_WORLD_DEFENSE && !speakInWorldDef)) { WorldPacket data; MakeMuted(&data); SendToOne(&data, p); } else if (m_moderate && !m_players[p].IsModerator() && sec < SEC_GAMEMASTER) { WorldPacket data; MakeNotModerator(&data); SendToOne(&data, p); } else { uint32 messageLength = strlen(what) + 1; WorldPacket data(SMSG_MESSAGECHAT, 1 + 4 + 8 + 4 + m_name.size() + 1 + 8 + 4 + messageLength + 1); data << uint8(CHAT_MSG_CHANNEL); data << uint32(lang); data << m_name; data << uint32(0); data << ObjectGuid(p); data << uint32(messageLength); data << what; data << uint8(plr ? plr->GetChatTag() : uint8(CHAT_TAG_NONE)); SendToAll(&data, !m_players[p].IsModerator() ? p : ObjectGuid()); } }
void Channel::Say(Player* player, const char* text, uint32 lang) { if (!text) return; uint32 sec = 0; ObjectGuid guid = player->GetObjectGuid(); Player* plr = sObjectMgr.GetPlayer(guid); bool speakInLocalDef = false; bool speakInWorldDef = false; if (plr) { sec = plr->GetSession()->GetSecurity(); if (plr->isGameMaster()) { speakInLocalDef = true; speakInWorldDef = true; } HonorRankInfo honorInfo = plr->GetHonorRankInfo(); //We can speak in local defense if we're above this rank (see .h file) if (honorInfo.rank >= SPEAK_IN_LOCALDEFENSE_RANK) speakInLocalDef = true; // Are we not allowed to speak in WorldDefense at all? // if (honorInfo.rank >= SPEAK_IN_WORLDDEFENSE_RANK) // speakInWorldDef = true; } if (!IsOn(guid)) { WorldPacket data; MakeNotMember(&data); SendToOne(&data, guid); return; } else if (m_players[guid].IsMuted() || (GetChannelId() == CHANNEL_ID_LOCAL_DEFENSE && !speakInLocalDef) || (GetChannelId() == CHANNEL_ID_WORLD_DEFENSE && !speakInWorldDef)) { WorldPacket data; MakeMuted(&data); SendToOne(&data, guid); return; } if (m_moderate && !m_players[guid].IsModerator() && player->GetSession()->GetSecurity() < SEC_GAMEMASTER) { WorldPacket data; MakeNotModerator(&data); SendToOne(&data, guid); return; } // send channel message if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) lang = LANG_UNIVERSAL; WorldPacket data; ChatHandler::BuildChatPacket(data, CHAT_MSG_CHANNEL, text, Language(lang), player->GetChatTag(), guid, player->GetName(), ObjectGuid(), "", m_name.c_str(), player->GetHonorRankInfo().rank); SendToAll(&data, !m_players[guid].IsModerator() ? guid : ObjectGuid()); }
void Channel::MakeYouLeft(WorldPackets::Channel::ChannelNotify& data) { MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE); data.ChatChannelID = GetChannelId(); //*data << uint8(IsConstant()); }