Skip to content

Commit df41ffd

Browse files
committed
Custom Sound Entity
1 parent 3b3cade commit df41ffd

3 files changed

Lines changed: 92 additions & 1 deletion

File tree

datasrc/network.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,8 @@
299299

300300
NetObjectEx("CustomSoundEntity:CustomObject", "custom-sound-entity@netobj.teeworlds.wiki", [
301301
NetIntAny("m_Vol"),
302-
NetIntAny("m_Offset"),
302+
NetIntAny("m_Distance"),
303+
NetTick("m_StartTick"),
303304
]),
304305

305306
NetObjectEx("CharacterGameTexture", "character-game-texture@netobj.teeworlds.wiki", [

src/game/client/components/resource.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <base/hash.h>
2+
#include <engine/shared/config.h>
23
#include <engine/shared/datafile.h>
34
#include <generated/client_data.h>
45

@@ -70,8 +71,67 @@ void CClientResManager::RenderImageEntity(const CNetObj_CustomImageEntity *pPrev
7071
Graphics()->QuadsEnd();
7172
}
7273

74+
void CClientResManager::RenderSoundEntity(const CNetObj_CustomSoundEntity *pPrev, const CNetObj_CustomSoundEntity *pCur, int ItemID)
75+
{
76+
Uuid SoundID;
77+
mem_copy(&SoundID, pCur->m_Uuid, sizeof(Uuid));
78+
ISound::CSampleHandle Sample = GetResourceSample(SoundID);
79+
if(!Sample.IsValid())
80+
return;
81+
// search and mark the entity as active
82+
CSoundEntity *pEntity = 0;
83+
for(int i = 0; i < m_lSoundEntities.size(); i++)
84+
{
85+
if(ItemID == m_lSoundEntities[i].m_SnapshotID)
86+
{
87+
pEntity = &m_lSoundEntities[i];
88+
pEntity->m_Active = true;
89+
if(mem_comp(pPrev->m_Uuid, pCur->m_Uuid, sizeof(Uuid)) != 0)
90+
{
91+
Sound()->StopVoice(pEntity->m_Voice);
92+
pEntity->m_Voice = Sound()->PlayAt(CSounds::CHN_WORLD, Sample, 1.0f, ISound::FLAG_LOOP, 0, 0);
93+
}
94+
break;
95+
}
96+
}
97+
98+
int Volume = mix(pPrev->m_Vol, pCur->m_Vol, Client()->IntraGameTick());
99+
float Distance = mix(pPrev->m_Distance, pCur->m_Distance, Client()->IntraGameTick()) / 256.0f;
100+
vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCur->m_X, pCur->m_Y), Client()->IntraGameTick());
101+
if(!pEntity)
102+
{
103+
CSoundEntity &NewEntity = m_lSoundEntities.emplace();
104+
NewEntity.m_Active = true;
105+
NewEntity.m_SnapshotID = ItemID;
106+
NewEntity.m_Voice = Sound()->PlayAt(CSounds::CHN_WORLD, Sample, 1.0f, ISound::FLAG_LOOP, 0, 0);
107+
pEntity = &NewEntity;
108+
}
109+
110+
Sound()->SetVoiceVolume(pEntity->m_Voice, Volume / 256.0f);
111+
Sound()->SetVoiceCircle(pEntity->m_Voice, Distance);
112+
Sound()->SetVoicePos(pEntity->m_Voice, Pos.x, Pos.y);
113+
114+
static float s_Time = 0.0f;
115+
if(m_pClient->m_Snap.m_pGameData)
116+
{
117+
s_Time = mix((Client()->PrevGameTick() - m_pClient->m_Snap.m_pGameData->m_GameStartTick) / (float) Client()->GameTickSpeed(),
118+
(Client()->GameTick() - m_pClient->m_Snap.m_pGameData->m_GameStartTick) / (float) Client()->GameTickSpeed(),
119+
Client()->IntraGameTick());
120+
}
121+
float Offset = maximum(s_Time - pCur->m_StartTick / (float) Client()->GameTickSpeed(), 0.0f);
122+
Sound()->SetVoiceTimeOffset(pEntity->m_Voice, Offset);
123+
}
124+
73125
void CClientResManager::OnRender()
74126
{
127+
if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK)
128+
return;
129+
130+
for(int i = 0; i < m_lSoundEntities.size(); i++)
131+
{
132+
m_lSoundEntities[i].m_Active = false;
133+
}
134+
75135
int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
76136
for(int i = 0; i < Num; i++)
77137
{
@@ -84,7 +144,22 @@ void CClientResManager::OnRender()
84144
if(pPrev)
85145
RenderImageEntity((const CNetObj_CustomImageEntity *) pPrev, (const CNetObj_CustomImageEntity *) pData);
86146
}
147+
else if(Config()->m_SndEnable && Item.m_Type == NETOBJTYPE_CUSTOMSOUNDENTITY)
148+
{
149+
const void *pPrev = Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_ID);
150+
if(pPrev)
151+
RenderSoundEntity((const CNetObj_CustomSoundEntity *) pPrev, (const CNetObj_CustomSoundEntity *) pData, Item.m_ID);
152+
}
87153
}
154+
155+
for(int i = 0; i < m_lSoundEntities.size(); i++)
156+
{
157+
if(!m_lSoundEntities[i].m_Active)
158+
{
159+
Sound()->StopVoice(m_lSoundEntities[i].m_Voice);
160+
m_lSoundEntities.remove_index_fast(i);
161+
}
162+
}
88163
}
89164

90165
void CClientResManager::OnMessage(int MsgType, void *pRawMsg)
@@ -198,6 +273,13 @@ void CClientResManager::OnStateChange(int NewState, int OldState)
198273
}
199274
}
200275
m_lResources.clear();
276+
277+
for(int i = 0; i < m_lSoundEntities.size(); i++)
278+
{
279+
if(m_lSoundEntities[i].m_Active)
280+
Sound()->StopVoice(m_lSoundEntities[i].m_Voice);
281+
}
282+
m_lSoundEntities.clear();
201283
}
202284
}
203285
}

src/game/client/components/resource.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,19 @@ class CClientResManager : public CComponent
2121
IOHANDLE m_DownloadTemp;
2222
};
2323

24+
struct CSoundEntity
25+
{
26+
int m_Voice;
27+
int m_SnapshotID;
28+
bool m_Active;
29+
};
30+
array<CSoundEntity> m_lSoundEntities;
2431
array<CClientResource> m_lResources;
2532
void RequestDownload(const Uuid *pRequest);
2633
bool LoadResource(CClientResource *pResource);
2734

2835
void RenderImageEntity(const CNetObj_CustomImageEntity *pPrev, const CNetObj_CustomImageEntity *pCur);
36+
void RenderSoundEntity(const CNetObj_CustomSoundEntity *pPrev, const CNetObj_CustomSoundEntity *pCur, int ItemID);
2937
public:
3038
CClientResManager();
3139
virtual void OnRender();

0 commit comments

Comments
 (0)