//------------------------------------------------------------------------ void CItem::StopSound(tSoundID id) { if(id == INVALID_SOUNDID) return; bool synchSound = false; IEntitySoundProxy *pSoundProxy = GetSoundProxy(false); if(pSoundProxy) { for(TInstanceActionMap::iterator it = m_instanceActions.begin(); it != m_instanceActions.end(); ++it) { SInstanceAction &action = it->second; for(int i=0; i<2; i++) { if(action.sound[i].id == id) { pSoundProxy->SetStaticSound(id, false); action.sound[i].id = INVALID_SOUNDID; synchSound = action.sound[i].synch; break; } } } if(synchSound) pSoundProxy->StopSound(id, ESoundStopMode_OnSyncPoint); else pSoundProxy->StopSound(id); } }
//------------------------------------------------------------------------ void SSoundEffect::Activate(EntityId targetId, EntityId ownerId, EntityId weaponId, const char *effect, const char *defaultEffect) { // TODO: make work in MP... IEntity* pEntity = gEnv->pEntitySystem->GetEntity(targetId); IEntity* pOwnerEntity = gEnv->pEntitySystem->GetEntity(ownerId); if(pEntity && gEnv->pSoundSystem && pOwnerEntity) { int soundFlag = FLAG_SOUND_3D; bool repeating = false; bool force3DSound = true; IEntitySoundProxy* pSoundProxy = (IEntitySoundProxy*)pOwnerEntity->GetProxy(ENTITY_PROXY_SOUND); if(pSoundProxy) { //Execute sound at entity position GameWarning("Sound effect: %s (Entity)", defaultEffect); pSoundProxy->PlaySound(defaultEffect, pEntity->GetWorldPos()-pOwnerEntity->GetWorldPos(),FORWARD_DIRECTION, FLAG_SOUND_DEFAULT_3D); // Notify AI system (TODO: Parametrize radius) gEnv->pAISystem->SoundEvent(pEntity->GetWorldPos(), 100.0f, AISE_GENERIC, NULL); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(pEntity->GetWorldPos(),0.5f,ColorB(255,0,0)); } } }
//------------------------------------------------------------------------ ISound *CItem::GetISound(tSoundID id) { IEntitySoundProxy *pSoundProxy = GetSoundProxy(false); if (pSoundProxy) return pSoundProxy->GetSound(id); return 0; }
//------------------------------------------------------------------------ void CItem::Quiet() { IEntitySoundProxy *pSoundProxy = GetSoundProxy(false); if (pSoundProxy) { pSoundProxy->StopAllSounds(); } }
tSoundID CHeavyMountedWeapon::PlayRotationSound() { tSoundID result = 0; IEntitySoundProxy* pSoundProxy = GetSoundProxy(true); if (pSoundProxy) { const ItemString& soundName = m_stats.fp ? m_sharedparams->pMountParams->rotate_sound_fp : m_sharedparams->pMountParams->rotate_sound_tp; result = pSoundProxy->PlaySoundEx(soundName.c_str(), ZERO, FORWARD_DIRECTION, FLAG_SOUND_DEFAULT_3D, 0, 1.0f, 0, 0, eSoundSemantic_Weapon); } return result; }
//------------------------------------------------------------------------ void CGameRulesKingOfTheHillObjective::ClearEntityAudio( SHoldEntityDetails *pDetails ) { IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pDetails->m_id); if(pEntity) { IEntitySoundProxy *soundProxy = (IEntitySoundProxy*) pEntity->GetProxy(ENTITY_PROXY_SOUND); if(soundProxy) { soundProxy->StopAllSounds(); } } }
void CBoidObject::PlaySound( int nIndex ) { if (nIndex >= 0 && nIndex < (int)m_flock->m_bc.sounds.size()) { IEntity *pEntity = gEnv->pEntitySystem->GetEntity(m_entity); if (pEntity) { IEntitySoundProxy* pSndProxy = (IEntitySoundProxy*)pEntity->CreateProxy(ENTITY_PROXY_SOUND); Vec3 ofs(0,0,0),dir(FORWARD_DIRECTION); pSndProxy->PlaySound( m_flock->m_bc.sounds[nIndex],ofs,dir,FLAG_SOUND_DEFAULT_3D, 0, eSoundSemantic_Living_Entity ); } } }
//------------------------------------------------------------------------ void CItem::StopSound(tSoundID id) { if (id == INVALID_SOUNDID) return; bool synchSound = false; IEntitySoundProxy *pSoundProxy = GetSoundProxy(false); if (pSoundProxy) { if(synchSound) pSoundProxy->StopSound(id, ESoundStopMode_OnSyncPoint); else pSoundProxy->StopSound(id); } }
//------------------------------------------------------------------------ void CItem::ReleaseStaticSound(SInstanceAudio *sound) { if (sound->id != INVALID_SOUNDID) { IEntitySoundProxy *pSoundProxy = GetSoundProxy(false); if (pSoundProxy) { pSoundProxy->SetStaticSound(sound->id, false); if(sound->synch) pSoundProxy->StopSound(sound->id,ESoundStopMode_OnSyncPoint); else pSoundProxy->StopSound(sound->id); sound->id = INVALID_SOUNDID; #ifndef ITEM_USE_SHAREDSTRING sound->static_name.resize(0); #else sound->static_name.reset(); #endif } } }
//------------------------------------------------------------------------ void CItem::Quiet() { IEntitySoundProxy *pSoundProxy = GetSoundProxy(false); if (pSoundProxy) { for (TInstanceActionMap::iterator it = m_instanceActions.begin(); it != m_instanceActions.end(); ++it) { SInstanceAction &action = it->second; for (int i=0;i<2;i++) { if (action.sound[i].id != INVALID_SOUNDID) { pSoundProxy->SetStaticSound(action.sound[i].id, false); action.sound[i].id = INVALID_SOUNDID; } } } pSoundProxy->StopAllSounds(); } }
//------------------------------------------------------------------------ void CAmmoPickup::PickUp(EntityId pickerId, bool sound, bool select, bool keepHistory) { if(!CheckAmmoRestrictions(pickerId)) return; SetOwnerId(pickerId); CActor *pActor=GetActor(pickerId); if (!pActor) return; IInventory *pInventory = GetActorInventory(pActor); if (!pInventory) return; if (IsServer()) { // bonus ammo is always put in the actor's inv if (!m_bonusammo.empty()) { for (TAmmoMap::iterator it=m_bonusammo.begin(); it!=m_bonusammo.end(); ++it) { int count=it->second; SetInventoryAmmoCount(it->first, GetInventoryAmmoCount(it->first)+count); if(pActor->IsPlayer()) { ShouldSwitchGrenade(it->first); OnIncendiaryAmmoPickedUp(it->first,count); } } m_bonusammo.clear(); } for (TAmmoMap::iterator it=m_ammo.begin(); it!=m_ammo.end(); ++it) { int count=it->second; SetInventoryAmmoCount(it->first, GetInventoryAmmoCount(it->first)+count); if(pActor->IsPlayer()) { ShouldSwitchGrenade(it->first); OnIncendiaryAmmoPickedUp(it->first,count); } } if (!m_ammoName.empty() && m_ammoCount) { IEntityClass* pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(m_ammoName.c_str()); SetInventoryAmmoCount(pClass, GetInventoryAmmoCount(pClass)+m_ammoCount); if(pActor->IsPlayer()) { ShouldSwitchGrenade(pClass); OnIncendiaryAmmoPickedUp(pClass,m_ammoCount); } } TriggerRespawn(); } //Play sound if(!m_pickup_sound.empty()) { IEntity *pPicker = m_pEntitySystem->GetEntity(pickerId); if(pPicker) { IEntitySoundProxy* pSoundProxy = (IEntitySoundProxy*)pPicker->GetProxy(ENTITY_PROXY_SOUND); if(pSoundProxy) { //Execute sound at picker position pSoundProxy->PlaySound(m_pickup_sound, pPicker->GetWorldPos(),FORWARD_DIRECTION, FLAG_SOUND_DEFAULT_3D, eSoundSemantic_Weapon); } } } RemoveEntity(); }
// add enum of sound you want to play, and add command to game code at appropiate spot void CGameAudio::PlaySound(EGameAudioSounds eSound, IEntity *pEntity, float param, bool stopSound) { int soundFlag = 0; //localActor will get 2D sounds ESoundSemantic eSemantic = eSoundSemantic_None; ISound *pSound = NULL; bool setParam = false; static string soundName; soundName.resize(0); switch(eSound) { case EGameAudioSound_NOSOUND: break; case EGameAudioSound_LAST: break; default: break; } //if(!force3DSound && m_pOwner == m_pGameFramework->GetClientActor() && !m_pOwner->IsThirdPerson() && soundName.size()) //{ // if (bAppendPostfix) // soundName.append("_fp"); //} IEntitySoundProxy *pSoundProxy = pEntity ? (IEntitySoundProxy *)pEntity->CreateProxy(ENTITY_PROXY_SOUND) : NULL; if(soundName.size() && eSound < EGameAudioSound_LAST) //get / create or stop sound { if(m_sounds[eSound].ID != INVALID_SOUNDID) { if(pSoundProxy) pSound = pSoundProxy->GetSound(m_sounds[eSound].ID); else pSound = gEnv->pSoundSystem->GetSound(m_sounds[eSound].ID); if(stopSound) { if(pSound) pSound->Stop(); m_sounds[eSound].ID = INVALID_SOUNDID; return; } } if(!pSound && !stopSound) { pSound = gEnv->pSoundSystem->CreateSound(soundName, soundFlag); if(pSound) { pSound->SetSemantic(eSemantic); //float fTemp = 0.0f; m_sounds[eSound].ID = pSound->GetId(); m_sounds[eSound].bLooping = (pSound->GetFlags() & FLAG_SOUND_LOOP) != 0; m_sounds[eSound].b3D = (pSound->GetFlags() & FLAG_SOUND_3D) != 0; //m_sounds[eSound].nMassIndex = pSound->GetParam("mass", &fTemp, false); //m_sounds[eSound].nSpeedIndex = pSound->GetParam("speed", &fTemp, false); //m_sounds[eSound].nStrengthIndex = pSound->GetParam("strength", &fTemp, false); } } } if(pSound) //set params and play { //pSound->SetPosition(m_pOwner->GetEntity()->GetWorldPos()); if(setParam) { //if (m_sounds[eSound].nMassIndex != -1) // pSound->SetParam(m_sounds[sound].nMassIndex, param); //if (m_sounds[eSound].nSpeedIndex != -1) // pSound->SetParam(m_sounds[sound].nSpeedIndex, param); //if (m_sounds[eSound].nStrengthIndex != -1) // pSound->SetParam(m_sounds[sound].nStrengthIndex, param); } if(!(m_sounds[eSound].bLooping && pSound->IsPlaying())) { if(pSoundProxy) pSoundProxy->PlaySound(pSound); else pSound->Play(); } } }
//------------------------------------------------------------------------ tSoundID CItem::PlayAction(const ItemString &actionName, int layer, bool loop, uint32 flags, float speedOverride) { if(!m_enableAnimations || !IsOwnerInGame()) return (tSoundID)-1; TActionMap::iterator it = m_sharedparams->actions.find(CONST_TEMPITEM_STRING(actionName)); if(it == m_sharedparams->actions.end()) { // GameWarning("Action '%s' not found on item '%s'!", actionName, GetEntity()->GetName()); for(int i=0; i<eIGS_Last; i++) { m_animationTime[i]=0; m_animationSpeed[i]=1.0f; m_animationEnd[i]=0; } return 0; } bool fp = m_stats.fp; if(m_parentId) { CItem *pParent=static_cast<CItem *>(m_pItemSystem->GetItem(m_parentId)); if(pParent) fp=pParent->GetStats().fp; } if(flags&eIPAF_ForceFirstPerson) fp = true; if(flags&eIPAF_ForceThirdPerson) fp = false; int sid=fp?eIGS_FirstPerson:eIGS_ThirdPerson; SAction &action = it->second; tSoundID result = INVALID_SOUNDID; if((flags&eIPAF_Sound) && !action.sound[sid].name.empty() && IsSoundEnabled() && g_pGameCVars->i_soundeffects) { int nSoundFlags = FLAG_SOUND_DEFAULT_3D; nSoundFlags |= flags&eIPAF_SoundStartPaused?FLAG_SOUND_START_PAUSED:0; IEntitySoundProxy *pSoundProxy = GetSoundProxy(true); //GetSound proxy from dualwield master if neccesary if(IsDualWieldSlave()) { CItem *pMaster = static_cast<CItem *>(GetDualWieldMaster()); if(pMaster) { pSoundProxy = pMaster->GetSoundProxy(true); } } EntityId pSkipEnts[3]; int nSkipEnts = 0; // TODO for Marcio :) // check code changes // Skip the Item pSkipEnts[nSkipEnts] = GetEntity()->GetId(); ++nSkipEnts; // Skip the Owner if(GetOwner()) { pSkipEnts[nSkipEnts] = GetOwner()->GetId(); ++nSkipEnts; } if(pSoundProxy) { TempResourceName name; FixResourceName(action.sound[sid].name, name, flags); //nSoundFlags = nSoundFlags | (fp?FLAG_SOUND_DEFAULT_3D|FLAG_SOUND_RELATIVE:FLAG_SOUND_DEFAULT_3D); Vec3 vOffset(0,0,0); if(fp) vOffset.x = 0.3f; // offset for first person weapon to the front if(!g_pGameCVars->i_staticfiresounds) { result = pSoundProxy->PlaySoundEx(name, vOffset, FORWARD_DIRECTION, nSoundFlags, 1.0f, 0, 0, eSoundSemantic_Weapon, pSkipEnts, nSkipEnts); ISound *pSound = pSoundProxy->GetSound(result); if(pSound && action.sound[sid].sphere>0.0f) pSound->SetSphereSpec(action.sound[sid].sphere); } else { SInstanceAudio *pInstanceAudio=0; if(action.sound[sid].isstatic) { TInstanceActionMap::iterator iit = m_instanceActions.find(CONST_TEMPITEM_STRING(actionName)); if(iit == m_instanceActions.end()) { std::pair<TInstanceActionMap::iterator, bool> insertion=m_instanceActions.insert(TInstanceActionMap::value_type(actionName, SInstanceAction())); pInstanceAudio=&insertion.first->second.sound[sid]; } else pInstanceAudio=&iit->second.sound[sid]; } if(pInstanceAudio && (pInstanceAudio->id != INVALID_SOUNDID) && (name != pInstanceAudio->static_name)) ReleaseStaticSound(pInstanceAudio); if(!pInstanceAudio || pInstanceAudio->id == INVALID_SOUNDID) { result = pSoundProxy->PlaySoundEx(name, vOffset, FORWARD_DIRECTION, nSoundFlags, 1.0f, 0, 0, eSoundSemantic_Weapon, pSkipEnts, nSkipEnts); ISound *pSound = pSoundProxy->GetSound(result); if(pSound && action.sound[sid].sphere>0.0f) pSound->SetSphereSpec(action.sound[sid].sphere); } if(action.sound[sid].isstatic) { if(pInstanceAudio->id == INVALID_SOUNDID) { if(pSoundProxy->SetStaticSound(result, true)) { pInstanceAudio->id = result; pInstanceAudio->static_name = name; pInstanceAudio->synch = action.sound[sid].issynched; } } else { ISound *pSound = pSoundProxy->GetSound(pInstanceAudio->id); if(pSound) pSound->Play(1.0, true, true, pSoundProxy); } } } if(gEnv->pAISystem && action.sound[sid].airadius > 0.0f) { EntityId ownerId = GetOwner() ? GetOwner()->GetId() : 0; // associate sound event with vehicle if the shooter is in a vehicle (tank cannon shot, etc) if(CActor *pOwnerActor = GetOwnerActor()) { IVehicle *pOwnerVehicle = pOwnerActor->GetLinkedVehicle(); if(pOwnerVehicle && pOwnerVehicle->GetEntityId()) ownerId = pOwnerVehicle->GetEntityId(); } SAIStimulus stim(AISTIM_SOUND, AISOUND_WEAPON, ownerId?ownerId:GetEntityId() , 0, GetEntity()->GetWorldPos(), ZERO, action.sound[sid].airadius); gEnv->pAISystem->RegisterStimulus(stim); } } } if(flags&eIPAF_Animation) { TempResourceName name; // generate random number only once per call to allow animations to // match across geometry slots (like first person and third person) float randomNumber = Random(); for(int i=0; i<eIGS_Last; i++) { if(!(flags&(1<<i))) continue; int nanimations=action.animation[i].size(); if(nanimations <= 0) continue; int anim = int(randomNumber * float(nanimations)); if(action.animation[i][anim].name.empty()) continue; FixResourceName(action.animation[i][anim].name, name, flags); if((i == eIGS_Owner) || (i == eIGS_OwnerLooped)) { if(!action.animation[i][anim].name.empty()) { bool looping=(eIGS_OwnerLooped==i); CActor *pOwner = GetOwnerActor(); if(pOwner) { if(IsDualWield() && !m_sharedparams->params.dual_wield_pose.empty()) pOwner->PlayAction(name, m_sharedparams->params.dual_wield_pose.c_str(), looping); else pOwner->PlayAction(name, m_sharedparams->params.pose.c_str(), looping); } } continue; } else if(i == eIGS_OffHand) { if(!action.animation[eIGS_OffHand][anim].name.empty()) { CActor *pOwner = GetOwnerActor(); if(pOwner) { CItem *pOffHand = pOwner->GetItemByClass(CItem::sOffHandClass); if(pOffHand && pOffHand!=this) { uint32 ohflags=eIPAF_Default; if(action.animation[eIGS_OffHand][anim].blend==0.0f) ohflags|=eIPAF_NoBlend; pOffHand->PlayAction(action.animation[eIGS_OffHand][anim].name, 0, false, ohflags); } } } continue; } SAnimation &animation=action.animation[i][anim]; if(!animation.name.empty()) { float blend = animation.blend; if(flags&eIPAF_NoBlend) blend = 0.0f; if(speedOverride > 0.0f) PlayAnimationEx(name, i, layer, loop, blend, speedOverride, flags); else PlayAnimationEx(name, i, layer, loop, blend, animation.speed, flags); } if((m_stats.fp || m_stats.viewmode&eIVM_FirstPerson) && i==eIGS_FirstPerson && !animation.camera_helper.empty()) { m_camerastats.animating=true; m_camerastats.helper=animation.camera_helper; m_camerastats.position=animation.camera_pos; m_camerastats.rotation=animation.camera_rot; m_camerastats.follow=animation.camera_follow; m_camerastats.reorient=animation.camera_reorient; } else if(m_camerastats.animating) m_camerastats=SCameraAnimationStats(); } } if(flags&eIPAF_Effect && !action.effect[sid].name.empty()) { // change this to attach, if needed SpawnEffect(sid, action.effect[sid].name.c_str(), action.effect[sid].helper.c_str()); } if(action.children) { for(TAccessoryMap::iterator ait=m_accessories.begin(); ait!=m_accessories.end(); ait++) { EntityId aId=(EntityId)ait->second; CItem *pAccessory=static_cast<CItem *>(m_pItemSystem->GetItem(aId)); if(pAccessory) pAccessory->PlayAction(actionName, layer, loop, flags, speedOverride); } } return result; }
//------------------------------------------------------------------------ void CItem::FixResourceName(const ItemString &inName, TempResourceName &name, int flags, const char *hand, const char *suffix, const char *pose, const char *pov, const char *env) { // the whole thing of fixing is not nice, but at least we don't allocate too often // StringHelper<TempResourceName::SIZE> name (inName.c_str(), inName.length()); name.assign(inName.c_str(), inName.length()); if(!hand) { if(m_stats.hand == eIH_Left) hand = "left"; else hand = "right"; } name.replace("%hand%", hand); if(m_stats.hand == eIH_Left) name.replace("%offhand%", "right"); else name.replace("%offhand%", "left"); if(!suffix) suffix = m_actionSuffix.c_str(); name.replace("%suffix%", suffix); if(!pose) { if(!m_sharedparams->params.pose.empty()) pose = m_sharedparams->params.pose.c_str(); else pose = ""; } name.replace("%pose%", ""); if(!pov) { if((m_stats.fp || flags&eIPAF_ForceFirstPerson) && !(flags&eIPAF_ForceThirdPerson)) pov = ITEM_FIRST_PERSON_TOKEN; else pov = ITEM_THIRD_PERSON_TOKEN; } name.replace("%pov%", pov); if(!env) { // Instead if the weapons sound proxy, the owners is used to retrieve the tail name IEntity *pOwner = GetOwner(); if(GetIWeapon() && pOwner) // restricting to weapon sounds only { if(pOwner) { IEntitySoundProxy *pSoundProxy = (IEntitySoundProxy *)pOwner->GetProxy(ENTITY_PROXY_SOUND); if(!pSoundProxy) pSoundProxy = (IEntitySoundProxy *)pOwner->CreateProxy(ENTITY_PROXY_SOUND); if(pSoundProxy) { // check for a roof 10m above the Owner // recalculate visibility when owner move more than 2 meters pSoundProxy->CheckVisibilityForTailName(10.0f, 2.0f); env = pSoundProxy->GetTailName(); } } } if(!env || !env[0] || !stricmp("indoor", env)) name.replace("%env%", ""); else { static const size_t MAX_LEN = 256; char envstr[MAX_LEN]; envstr[0] = '_'; strncpy(envstr+1, env, MAX_LEN-1); // no 0 pad, if MAX_LEN-1 are copied envstr[MAX_LEN-1] = '\0'; // always zero-terminate name.replace("%env%", envstr); } } else name.replace("%env%", env); }