diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index 09b82230..d95b672d 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -308,10 +308,9 @@ void CL_CenterPrint( const char *text, float y ) { cl_font_t *font = Con_GetCurFont(); - if( !COM_CheckString( text )) + if( !COM_CheckString( text ) || !font || !font->valid ) return; - clgame.centerPrint.lines = 1; clgame.centerPrint.totalWidth = 0; clgame.centerPrint.time = cl.mtime[0]; // allow pause for centerprint Q_strncpy( clgame.centerPrint.message, text, sizeof( clgame.centerPrint.message )); @@ -322,6 +321,10 @@ void CL_CenterPrint( const char *text, float y ) &clgame.centerPrint.totalHeight, FONT_DRAW_HUD | FONT_DRAW_UTF8 ); + if( font->charHeight ) + clgame.centerPrint.lines = clgame.centerPrint.totalHeight / font->charHeight; + else clgame.centerPrint.lines = 1; + clgame.centerPrint.y = CL_AdjustYPos( y, clgame.centerPrint.totalHeight ); } diff --git a/engine/client/console.c b/engine/client/console.c index 615142a0..07894d17 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -1732,30 +1732,37 @@ Custom debug messages */ int Con_DrawDebugLines( void ) { + notify_t *notify = con.notify; int i, count = 0; int defaultX; int y = 20; + int fontTall; + + if( !con.curFont || !con.curFont->valid ) + return 0; defaultX = refState.width / 4; + fontTall = con.curFont->charHeight + 1; - for( i = 0; i < MAX_DBG_NOTIFY; i++ ) + for( i = 0; i < ARRAYSIZE( con.notify ); i++, notify++ ) { - if( host.realtime < con.notify[i].expire && con.notify[i].key_dest == cls.key_dest ) - { - int x, len; - int fontTall = 0; + int x, len; - Con_DrawStringLen( con.notify[i].szNotify, &len, &fontTall ); - x = refState.width - Q_max( defaultX, len ) - 10; - fontTall += 1; + if( host.realtime > notify->expire ) + continue; - if( y + fontTall > refState.height - 20 ) - return count; + if( notify->key_dest != cls.key_dest ) + continue; - count++; - y = 20 + fontTall * i; - Con_DrawString( x, y, con.notify[i].szNotify, con.notify[i].color ); - } + Con_DrawStringLen( notify->szNotify, &len, NULL ); + x = refState.width - Q_max( defaultX, len ) - 10; + + if( y + fontTall > refState.height - 20 ) + return count; + + count++; + y += fontTall; + CL_DrawString( x, y, notify->szNotify, notify->color, con.curFont, FONT_DRAW_UTF8 | FONT_DRAW_NOLF ); } return count; @@ -1784,7 +1791,7 @@ void Con_DrawDebug( void ) } else { - timeStart = Sys_DoubleTime(); + timeStart = host.realtime; } if( !host.allow_console || Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" )) diff --git a/engine/client/s_load.c b/engine/client/s_load.c index 8a81af3d..17f1dd4e 100644 --- a/engine/client/s_load.c +++ b/engine/client/s_load.c @@ -54,7 +54,7 @@ void S_SoundList_f( void ) if( sc->loopStart >= 0 ) Con_Printf( "L" ); else Con_Printf( " " ); - if( sfx->name[0] == '*' ) + if( sfx->name[0] == '*' || !Q_strncmp( sfx->name, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 )) Con_Printf( " (%2db) %s : %s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name ); else Con_Printf( " (%2db) %s : " DEFAULT_SOUNDPATH "%s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name ); totalSfx++; diff --git a/engine/client/s_main.c b/engine/client/s_main.c index 5a77e24f..3ba4ea13 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -197,6 +197,65 @@ qboolean SND_FStreamIsPlaying( sfx_t *sfx ) return false; } +/* +================= +SND_GetChannelTimeLeft + +TODO: this function needs to be removed after whole sound subsystem rewrite +================= +*/ +static int SND_GetChannelTimeLeft( const channel_t *ch ) +{ + int remaining; + + if( ch->pMixer.finished || !ch->sfx || !ch->sfx->cache ) + return 0; + + if( ch->isSentence ) // sentences are special, count all remaining words + { + int i; + + if( !ch->currentWord ) + return 0; + + // current word + remaining = ch->currentWord->forcedEndSample - ch->currentWord->sample; + + // here we count all remaining words, stopping if no sfx or sound file is available + // see VOX_LoadWord + for( i = ch->wordIndex + 1; i < ARRAYSIZE( ch->words ); i++ ) + { + wavdata_t *sc; + int end; + + // don't continue with broken sentences + if( !ch->words[i].sfx ) + break; + + if( !( sc = S_LoadSound( ch->words[i].sfx ))) + break; + + end = ch->words[i].end; + + if( end ) + remaining += sc->samples * 0.01f * end; + else remaining += sc->samples; + } + } + else + { + int curpos; + int samples; + + // handle position looping + samples = ch->sfx->cache->samples; + curpos = S_ConvertLoopedPosition( ch->sfx->cache, ch->pMixer.sample, ch->use_loop ); + remaining = bound( 0, samples - curpos, samples ); + } + + return remaining; +} + /* ================= SND_PickDynamicChannel @@ -246,11 +305,7 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean continue; // try to pick the sound with the least amount of data left to play - timeleft = 0; - if( ch->sfx ) - { - timeleft = 1; // ch->end - paintedtime - } + timeleft = SND_GetChannelTimeLeft( ch ); if( timeleft < life_left ) { diff --git a/engine/client/sound.h b/engine/client/sound.h index 19f9eead..d55ee533 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -306,6 +306,7 @@ void S_FadeMusicVolume( float fadePercent ); // int S_ZeroCrossingAfter( wavdata_t *pWaveData, int sample ); int S_ZeroCrossingBefore( wavdata_t *pWaveData, int sample ); +int S_ConvertLoopedPosition( wavdata_t *pSource, int samplePosition, qboolean use_loop ); int S_GetOutputData( wavdata_t *pSource, void **pData, int samplePosition, int sampleCount, qboolean use_loop ); void S_SetSampleStart( channel_t *pChan, wavdata_t *pSource, int newPosition ); void S_SetSampleEnd( channel_t *pChan, wavdata_t *pSource, int newEndPosition ); diff --git a/engine/common/lib_common.c b/engine/common/lib_common.c index c0ec5299..5b3673cb 100644 --- a/engine/common/lib_common.c +++ b/engine/common/lib_common.c @@ -410,11 +410,13 @@ char **COM_ConvertToLocalPlatform( EFunctionMangleType to, const char *from, siz if( at ) len = (uint)( at - prev ); else len = (uint)Q_strlen( prev ); + Q_strncpy( symbols[i], prev, Q_min( len + 1, sizeof( symbols[i] ))); - prev = at + 1; if( !at ) break; + + prev = at + 1; } if( i == MAX_NESTED_NAMESPACES ) diff --git a/engine/common/mod_studio.c b/engine/common/mod_studio.c index 251c9a0c..504ff415 100644 --- a/engine/common/mod_studio.c +++ b/engine/common/mod_studio.c @@ -383,6 +383,7 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p // add in programtic controllers pbone = (mstudiobone_t *)((byte *)mod_studiohdr + mod_studiohdr->boneindex); + memset( adj, 0, sizeof( adj )); Mod_StudioCalcBoneAdj( adj, pcontroller ); for( j = numbones - 1; j >= 0; j-- ) diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 9473d79e..0f3f85c7 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -2642,6 +2642,7 @@ void GAME_EXPORT pfnMessageEnd( void ) { const char *name = "Unknown"; float *org = NULL; + word realsize; if( svgame.msg_name ) name = svgame.msg_name; if( !svgame.msg_started ) Host_Error( "MessageEnd: called with no active message\n" ); @@ -2673,7 +2674,8 @@ void GAME_EXPORT pfnMessageEnd( void ) return; } - *(word *)&sv.multicast.pData[svgame.msg_size_index] = svgame.msg_realsize; + realsize = svgame.msg_realsize; + memcpy( &sv.multicast.pData[svgame.msg_size_index], &realsize, sizeof( realsize )); } } else if( svgame.msg[svgame.msg_index].size != -1 ) @@ -2705,7 +2707,8 @@ void GAME_EXPORT pfnMessageEnd( void ) return; } - *(word *)&sv.multicast.pData[svgame.msg_size_index] = svgame.msg_realsize; + realsize = svgame.msg_realsize; + memcpy( &sv.multicast.pData[svgame.msg_size_index], &realsize, sizeof( realsize )); } else {