diff --git a/cl_dll/hud_spectator.cpp b/cl_dll/hud_spectator.cpp index 91e8fa37..ff6eb8ff 100644 --- a/cl_dll/hud_spectator.cpp +++ b/cl_dll/hud_spectator.cpp @@ -993,7 +993,7 @@ void CHudSpectator::DrawOverviewLayer() if ( hasMapImage) { i = m_MapSprite->numframes / (4*3); - i = sqrt(i); + i = sqrt(float(i)); xTiles = i*4; yTiles = i*3; } diff --git a/cl_dll/input_xash3d.cpp b/cl_dll/input_xash3d.cpp index 033af962..63cdfbeb 100644 --- a/cl_dll/input_xash3d.cpp +++ b/cl_dll/input_xash3d.cpp @@ -54,7 +54,7 @@ float rel_pitch; #define IMPULSE_DOWN 2 #define IMPULSE_UP 4 -bool CL_IsDead(); +int CL_IsDead( void ); Vector dead_viewangles(0, 0, 0); void IN_ToggleButtons( float forwardmove, float sidemove ) diff --git a/cl_dll/util.cpp b/cl_dll/util.cpp index 52dc2f61..655bde64 100644 --- a/cl_dll/util.cpp +++ b/cl_dll/util.cpp @@ -32,6 +32,10 @@ extern vec3_t vec3_origin; +#ifdef _MSC_VER +vec3_t vec3_origin; +#endif + double sqrt( double x ); float Length( const float *v ) diff --git a/dlls/Android.mk b/dlls/Android.mk index b97dd8e1..4274bb85 100644 --- a/dlls/Android.mk +++ b/dlls/Android.mk @@ -131,7 +131,8 @@ LOCAL_SRC_FILES := agrunt.cpp airtank.cpp \ big_cock.cpp \ ../pm_shared/pm_debug.c \ ../pm_shared/pm_math.c \ - ../pm_shared/pm_shared.c + ../pm_shared/pm_shared.c \ + coop.cpp # ../game_shared/voice_gamemgr.cpp LOCAL_LDLIBS := -llog diff --git a/dlls/client.cpp b/dlls/client.cpp index 60ee9390..b9ade580 100644 --- a/dlls/client.cpp +++ b/dlls/client.cpp @@ -51,7 +51,7 @@ extern int gmsgSayText; extern int g_teamplay; void LinkUserMessages( void ); -void BecomeSpectator( CBasePlayer *pPlayer ); +void UTIL_BecomeSpectator( CBasePlayer *pPlayer ); /* * used by kill command and disconnect command * ROBIN: Moved here from player.cpp, to allow multiple player models @@ -85,7 +85,7 @@ BOOL ClientConnect( edict_t *pEntity, const char *pszName, const char *pszAddres { pl->m_state = STATE_UNINITIALIZED; pl->RemoveAllItems( TRUE ); - BecomeSpectator( pl ); + UTIL_BecomeSpectator( pl ); } } @@ -228,7 +228,7 @@ void ClientPutInServer( edict_t *pEntity ) if( mp_spectator.value ) { pPlayer->RemoveAllItems( TRUE ); - BecomeSpectator( pPlayer ); + UTIL_BecomeSpectator( pPlayer ); } // Reset interpolation during first frame @@ -610,6 +610,10 @@ void ClientUserInfoChanged( edict_t *pEntity, char *infobuffer ) // Set the name g_engfuncs.pfnSetClientKeyValue( ENTINDEX(pEntity), infobuffer, "name", sName ); + // prevent phantom nickname changed messages + if( mp_coop.value && ((CBasePlayer *)pEntity->pvPrivateData)->m_state == STATE_UNINITIALIZED ) + return; + char text[256]; snprintf( text, 256, "* %s changed name to %s\n", STRING(pEntity->v.netname), g_engfuncs.pfnInfoKeyValue( infobuffer, "name" ) ); MESSAGE_BEGIN( MSG_ALL, gmsgSayText, NULL ); @@ -710,7 +714,7 @@ void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) { plr->m_state = STATE_UNINITIALIZED; plr->RemoveAllItems( TRUE ); - BecomeSpectator( plr ); + UTIL_BecomeSpectator( plr ); //plr->Spawn(); } } diff --git a/dlls/coop.cpp b/dlls/coop.cpp new file mode 100644 index 00000000..e532579e --- /dev/null +++ b/dlls/coop.cpp @@ -0,0 +1,629 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "player.h" +#include "coop_util.h" + + +GlobalMenu g_GlobalMenu; + + +struct SavedCoords g_SavedCoords, s_SavedCoords; + + +void UTIL_CleanSpawnPoint( Vector origin, float dist ) +{ + CBaseEntity *ent = NULL; + while( ( ent = UTIL_FindEntityInSphere( ent, origin, dist ) ) != NULL ) + { + if( ent->IsPlayer() ) + { + TraceResult tr; + UTIL_TraceHull( ent->pev->origin + Vector( 0, 0, 36), ent->pev->origin + Vector( RANDOM_FLOAT( -150, 150 ), RANDOM_FLOAT( -150, 150 ), 0 ), dont_ignore_monsters, human_hull, ent->edict(), &tr); + //UTIL_TraceModel( ent->pev->origin + Vector( 0, 0, 36), ent->pev->origin + Vector( RANDOM_FLOAT( -150, 150 ), RANDOM_FLOAT( -150, 150 ), 0 ), 0, ent->edict(), &tr); + if( !tr.fAllSolid ) + UTIL_SetOrigin(ent->pev, tr.vecEndPos); + } + } +} + + +Vector UTIL_FixupSpawnPoint(Vector spawn) +{ + int i = 0; + // predict that spawn point is almost correct + while( i < 2 ) // 2 player heights + { + Vector point = spawn + Vector( 0, 0, 36 * i ); + TraceResult tr; + UTIL_TraceHull( point, point, ignore_monsters, (mp_unduck.value&&g_fSavedDuck)?head_hull:human_hull, NULL, &tr ); + if( !tr.fStartSolid && !tr.fAllSolid ) + return point; + i = -i; + if( i >= 0 ) + i++; + } + return spawn; +} + +void UTIL_CoopSaveTrain( CBaseEntity *pPlayer, SavedCoords *coords) +{ + if( coords->trainsaved ) + return; + + CBaseEntity *train = UTIL_CoopGetPlayerTrain(pPlayer); + if( !train ) + { + ALERT( at_console, "^1NO TRAIN!\n"); + return; + } + ALERT( at_console, "^1TRAIN IS %s\n", STRING( train->pev->classname ) ); + + if( !pPlayer->IsPlayer() ) + { + // it is trainnitself, try find player on it + CBaseEntity *pList; + Vector mins = pPlayer->pev->absmin; + Vector maxs = pPlayer->pev->absmax; + maxs.z += 72; + int count = UTIL_EntitiesInBox( &pList, 1, mins, maxs, FL_ONGROUND ); + if( count && pList && pList->IsPlayer() ) + pPlayer = pList; + else + { + ALERT( at_console, "Train without players\n" ); + return; + } + } + + strcpy( coords->trainglobal, STRING(train->pev->globalname) ); + coords->trainoffset = pPlayer->pev->origin - VecBModelOrigin(train->pev); + coords->trainsaved = true; +} + +void UTIL_BecomeSpectator( CBasePlayer *pPlayer ) +{ + //pPlayer->m_bDoneFirstSpawn = true; + pPlayer->pev->takedamage = DAMAGE_NO; + pPlayer->pev->flags |= FL_SPECTATOR; + pPlayer->pev->flags |= FL_NOTARGET; + pPlayer->pev->effects |= EF_NODRAW; + pPlayer->pev->solid = SOLID_NOT; + pPlayer->pev->movetype = MOVETYPE_NOCLIP; + pPlayer->pev->modelindex = 0; + pPlayer->pev->health = 1; + pPlayer->m_pGoalEnt = NULL; + return; +} + +void UTIL_SpawnPlayer( CBasePlayer *pPlayer ) +{ + pPlayer->m_state = STATE_SPAWNED; + pPlayer->m_iRespawnFrames = 0; + pPlayer->pev->effects &= ~EF_NODRAW; + + pPlayer->pev->takedamage = DAMAGE_YES; + pPlayer->pev->flags &= ~FL_SPECTATOR; + pPlayer->pev->movetype = MOVETYPE_WALK; + pPlayer->Spawn(); + CLIENT_COMMAND( pPlayer->edict(), "touch_show _coopm*\n" ); + +} + +char * UTIL_CoopPlayerName( CBaseEntity *pPlayer ) +{ + if( !pPlayer ) + return (char*)"unnamed(NULL)"; + return (char*)( ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected" ); +} + +bool g_fSavedDuck; + +char *badlist[256] = { +"player", // does not even can set own name +"talat", +"hmse", +"mhmd", +"aeman", +"famas", +"danek", +"ame syia", +"melih", +"aliance", +"vladick" +}; + +void UTIL_CoopKickPlayer(CBaseEntity *pPlayer) +{ + int i; + + if( !pPlayer ) + return; + + char *name = UTIL_CoopPlayerName( pPlayer ); + SERVER_COMMAND( UTIL_VarArgs( "kick %d\n", ENTINDEX(pPlayer->pev->pContainingEntity) - 1 ) ); + + if( strlen( name ) < 5 ) + return; + + // find last slot + for( i = 0; badlist[i]; i++ ); + + badlist[i] = strdup( name ); +} + +bool UTIL_CoopIsBadPlayer( CBaseEntity *plr ) +{ + if( !plr ) + return false; + + for( int i = 0; badlist[i];i++ ) + if( strcasestr( (char*)UTIL_CoopPlayerName( plr ), badlist[i] ) ) + return true; + + return false; +} + +struct checkpoint_s +{ + char str[32]; + float time; + Vector origin; + Vector angles; +} g_checkpoints[4]; + + +void CoopClearData( void ) +{ + // nullify + SavedCoords l_SavedCoords = {0}; + g_SavedCoords = l_SavedCoords; + memset( &g_checkpoints, 0, sizeof( g_checkpoints ) ); +} + +bool g_fPause; +void CoopApplyData( void ) +{ + if( s_SavedCoords.valid ) + { + struct SavedCoords null1 = {0}; + g_SavedCoords = s_SavedCoords; + s_SavedCoords = null1; + g_fSavedDuck = g_SavedCoords.fDuck; + } + g_fPause = false; + ALERT( at_console, "^2CoopApplyData()\n" ); + memset( &g_checkpoints, 0, sizeof( g_checkpoints ) ); +} + + +int g_iMenu; + + +void UTIL_CoopLocalConfirmMenu(CBasePlayer *pPlayer) +{ + const char *menu[] = { + "No", + "Cancel", + "Do not confirm", + "Don't confirm", + "Единая Россия" + }; + + menu[pPlayer->m_iConfirmKey = RANDOM_LONG(2,4)] = "Confirm"; + UTIL_CoopShowMenu(pPlayer, "Confirm changing map BACK (NOT RECOMMENDED)?", ARRAYSIZE(menu), menu); + pPlayer->m_iMenuState = MENUSTATE_LOCAL_CONFIRM; +} + + +void GlobalMenu::Process( CBasePlayer *pPlayer, int imenu ) +{ + if( pPlayer->pev->flags & FL_SPECTATOR ) + return; + if( gpGlobals->time - m_flTime > 30 ) + { + g_iMenu = 0; + return; + } + + switch( g_iMenu ) + { + case 1: // touch blue trigger + m_iVoteCount++; + + if( imenu == 1 ) // confirm + { + if( m_iBanCount >= 2 ) + { + UTIL_CoopKickPlayer( pPlayer ); + m_iConfirm-= 5; + return; + } + m_iConfirm++; + MESSAGE_BEGIN( MSG_ALL, 8, NULL ); // svc_print + WRITE_BYTE( 3 ); // PRINT_CHAT + WRITE_STRING( UTIL_VarArgs( "%s^7 confirmed map change\n", ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected")); + MESSAGE_END(); + + } + if( imenu == 2 ) // cancel + { + m_iConfirm--; + if( pPlayer == m_pPlayer ) + m_iConfirm -= 100; // player mistake + } + if( imenu == 3 ) + { + m_iBanCount++; + if( m_iBanCount >= 2 && m_iConfirm > -50 ) + UTIL_CoopKickPlayer( m_pPlayer ); + } + break; + case 2: // vote by request + MESSAGE_BEGIN( MSG_ALL, 8, NULL ); // svc_print + WRITE_BYTE( 3 ); // PRINT_CHAT + WRITE_STRING( UTIL_VarArgs( "%s^7 selected ^3%s\n", ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected", maps[imenu - 1] )); + MESSAGE_END(); + + if( imenu < m_iConfirm ) + { + votes[imenu-1]++; + m_iVoteCount++; + + if( votes[1] >= 2 ) + { + // two players vote for ban + UTIL_CoopKickPlayer( m_pPlayer ); + } + + if( m_iVoteCount >= m_iMaxCount ) + { + for( int i = 0; i <= m_iConfirm; i++ ) + if( votes[i] >= m_iMaxCount ) + { + UTIL_CoopActivateChangeLevel( triggers[i] ); + g_iMenu = 0; + } + + } + + } + } +} +void GlobalMenu::ShowGlobalMenu( const char *title, int count, const char **menu ) +{ + int count2 = 0; + for( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBaseEntity *plr = UTIL_PlayerByIndex( i ); + + if( plr && plr->IsPlayer() && !UTIL_CoopIsBadPlayer( plr ) ) + { + count2++; + CBasePlayer *player = (CBasePlayer *) plr; + UTIL_CoopShowMenu( player, title, count, menu, 30 ); + player->m_iMenuState = MENUSTATE_GLOBAL; + + } + } + m_iMaxCount = count2; + m_iBanCount = 0; +} + +void GlobalMenu::ConfirmMenu( CBasePlayer *pPlayer, CBaseEntity *trigger, const char *mapname ) +{ + if( g_iMenu && gpGlobals->time - m_flTime < 30 ) + return; // wait 30s befor new confirm vote + if( pPlayer->m_iMenuState == MENUSTATE_LOCAL_CONFIRM ) + return; + if( pPlayer->m_iLocalConfirm < 3 ) + { + UTIL_CoopLocalConfirmMenu( pPlayer ); + return; + } + g_iMenu = 1; + m_flTime = gpGlobals->time; + m_pTrigger = trigger; + m_pPlayer = pPlayer; + const char *menu[] = { + "Confirm", + "Cancel", + "BAN" + }; + MESSAGE_BEGIN( MSG_ALL, 8, NULL ); // svc_print + WRITE_BYTE( 3 ); // PRINT_CHAT + WRITE_STRING( UTIL_VarArgs( "%s^7 wants to change map ^1BACKWARDS\n", ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected")); + MESSAGE_END(); + ShowGlobalMenu(UTIL_VarArgs("Confirm changing map BACK TO %s?", mapname), ARRAYSIZE(menu), menu); + +} + + + +void UTIL_CoopCheckpointMenu( CBasePlayer *pPlayer ) +{ + //if( pPlayer->m_state == STATE_SPAWNED ) + { + + if( mp_coop_checkpoints.value ) + { + const char *menu[5] = { + "New checkpoint" + }; + int i; + if( pPlayer->m_state == STATE_SPECTATOR || pPlayer->m_state == STATE_SPECTATOR_BEGIN ) + menu[0] = "Just spawn"; + for( i = 1; g_checkpoints[i-1].time; i++ ) + menu[i] = g_checkpoints[i-1].str; + UTIL_CoopShowMenu( pPlayer, "Select checkpoint", i, menu ); + pPlayer->m_iMenuState = MENUSTATE_CHECKPOINT; + } + } +} + + +void UTIL_CoopNewCheckpoint( entvars_t *pevPlayer ) +{ + memmove( &g_checkpoints[1], &g_checkpoints[0], sizeof ( g_checkpoints[0] ) * 3 ); + g_checkpoints[0].time = gpGlobals->time; + snprintf( g_checkpoints[0].str, 31, "%5s %d", STRING( pevPlayer->netname ), (int)( gpGlobals->time / 60 ) ); + g_checkpoints[0].origin = pevPlayer->origin; + g_checkpoints[0].angles = pevPlayer->angles; + MESSAGE_BEGIN( MSG_ALL, 8, NULL ); // svc_print + WRITE_BYTE( 3 ); // PRINT_CHAT + WRITE_STRING( "New checkpoint availiable\n" ); + MESSAGE_END(); + +} + + +void UTIL_CoopVoteMenu( CBasePlayer *pPlayer ) +{ + int count = 0; + for( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBaseEntity *plr = UTIL_PlayerByIndex( i ); + + if( plr && plr->IsPlayer() ) + { + count++; + } + } + if( count < 4 ) + { + ClientPrint( pPlayer->pev, HUD_PRINTCENTER, "Need at least 4 players to vote changelevel!\n" ); + return; + } + g_GlobalMenu.VoteMenu(pPlayer); +} + +void UTIL_CoopMenu( CBasePlayer *pPlayer ) +{ + if( pPlayer->m_state == STATE_SPAWNED ) + { + pPlayer->m_iMenuState = MENUSTATE_COOPMENU; + if( mp_coop.value ) + { + const char *menu[] = { + "Force respawn", + "Unblock", + "Become spectator", + "Vote changelevel", + "Checkpoint/restore" + }; + int count1 = ARRAYSIZE( menu ) - 1; + if( mp_coop_checkpoints.value ) + count1++; + UTIL_CoopShowMenu( pPlayer, "Coop menu", count1, menu ); + } + } + else if ( pPlayer->m_state == STATE_SPECTATOR ) + { + pPlayer->m_iMenuState = MENUSTATE_COOPMENU_SPEC; + if( mp_coop.value ) + { + const char *menu[] = { + "Spawn", + "Close menu" + }; + UTIL_CoopShowMenu( pPlayer, "Spectator menu", ARRAYSIZE( menu ), menu ); + } + } +} + + +void UTIL_CoopProcessMenu( CBasePlayer *pPlayer, int imenu ) +{ + switch( pPlayer->m_iMenuState ) + { + case MENUSTATE_COOPMENU_SPEC: + if( imenu == 1 ) + { + if( g_checkpoints[0].time ) + UTIL_CoopCheckpointMenu( pPlayer ); + else + { + UTIL_SpawnPlayer( pPlayer ); + pPlayer->m_state = STATE_SPAWNED; + } + } + if( imenu == 2 ) + { + pPlayer->m_state = STATE_SPECTATOR; + CLIENT_COMMAND( pPlayer->edict(), "touch_show _coopm*\n" ); + } + break; + case MENUSTATE_COOPMENU: + if( pPlayer->m_state != STATE_SPAWNED ) + break; + if( imenu == 1 ) + { + pPlayer->RemoveAllItems( TRUE ); + UTIL_SpawnPlayer( pPlayer ); + } + if( imenu == 2 ) + { + UTIL_CleanSpawnPoint( pPlayer->pev->origin, 150 ); + } + if( imenu == 3 ) + { + pPlayer->RemoveAllItems( TRUE ); + UTIL_BecomeSpectator( pPlayer ); + pPlayer->m_state = STATE_SPECTATOR; + } + if( imenu == 4 ) + { + UTIL_CoopVoteMenu( pPlayer ); + } + if( imenu == 5 ) + { + UTIL_CoopCheckpointMenu( pPlayer ); + } + break; + case MENUSTATE_GLOBAL: + if( !UTIL_CoopIsBadPlayer( pPlayer ) ) + g_GlobalMenu.Process( pPlayer, imenu ); + break; + case MENUSTATE_CHECKPOINT: + if( imenu == 1 ) + { + if( pPlayer->m_state == STATE_SPECTATOR_BEGIN ) + UTIL_SpawnPlayer( pPlayer ); + else if( !UTIL_CoopIsBadPlayer( pPlayer ) ) + UTIL_CoopNewCheckpoint( pPlayer->pev ); + } + else if( imenu > 1 && imenu < 5 ) + { + pPlayer->RemoveAllItems( TRUE ); + UTIL_SpawnPlayer( pPlayer ); + pPlayer->pev->origin = g_checkpoints[imenu-2].origin; + pPlayer->pev->angles = g_checkpoints[imenu-2].angles; + } + break; + case MENUSTATE_LOCAL_CONFIRM: + if( imenu - 1 == pPlayer->m_iConfirmKey ) + pPlayer->m_iLocalConfirm++; + else + pPlayer->m_iLocalConfirm = 0; + pPlayer->m_iMenuState = MENUSTATE_NONE; + break; + default: + break; + } + //pPlayer->m_iMenuState = MENUSTATE_NONE; +} + +bool UTIL_CoopRestorePlayerCoords(CBaseEntity *player, Vector *origin, Vector *angles ) +{ + if(!g_SavedCoords.valid) + return false; + UTIL_CoopValidateOffset(); + // compute player by IQ + char *ip = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( player->edict() ), "ip" ); + for( int i = 0;i < g_SavedCoords.iCount;i++) + { + if(ip && ip[0] && !strcmp(ip, g_SavedCoords.ip[i]) ) + { + TraceResult tr; + Vector point = g_SavedCoords.origin[i] + g_SavedCoords.offset; + + UTIL_TraceHull( point, point, missile, (mp_unduck.value&&g_fSavedDuck)?head_hull:human_hull, NULL, &tr ); + + g_SavedCoords.ip[i][0] = 0; + + if( tr.fStartSolid || tr.fAllSolid ) + return false; + *origin = point; + *angles = g_SavedCoords.angles[i]; + return true; + } + } + return false; +} + +bool UTIL_CoopGetSpawnPoint( Vector *origin, Vector *angles) +{ + if(!g_SavedCoords.valid) + return false; + + // spawn on elevator or train + if( g_SavedCoords.trainsaved ) + { + CBaseEntity *train = UTIL_FindEntityByString( NULL, "globalname", g_SavedCoords.trainglobal ); + if( !train ) train = UTIL_FindEntityByString( NULL, "classname", g_SavedCoords.trainglobal ); + if( train && ( !g_SavedCoords.trainuser1 || train->pev->iuser1 == g_SavedCoords.trainuser1 ) ) + { + *angles = g_SavedCoords.triggerangles; + *origin = VecBModelOrigin(train->pev) + g_SavedCoords.trainoffset; + g_SavedCoords.trainuser1 = train->pev->iuser1; + return true; + } + ALERT( at_console, "Failed to get train %s (map design error?)\n", g_SavedCoords.trainglobal ); + } + Vector point = g_SavedCoords.triggerorigin; + *angles = g_SavedCoords.triggerangles; + if( !g_SavedCoords.validspawnpoint ) + { + TraceResult tr; + Vector angle; + UTIL_MakeVectorsPrivate( *angles, (float*)&angle, NULL, NULL ); + UTIL_CoopValidateOffset(); + point = point + g_SavedCoords.offset; + //UTIL_TraceHull( point, point, ignore_monsters, human_hull, NULL, &tr ); + + if( mp_unduck.value && g_fSavedDuck && !g_SavedCoords.fUsed ) + UTIL_TraceHull( point, point + angle * 100, missile, head_hull, NULL, &tr ); + else + UTIL_TraceHull( point, point + angle * 100, ignore_monsters, human_hull, NULL, &tr ); + + if( !tr.fStartSolid && !tr.fAllSolid || ENTINDEX( tr.pHit ) && ENTINDEX( tr.pHit ) <= gpGlobals->maxClients ) + { + //g_SavedCoords.triggerorigin = tr.vecEndPos; + //g_SavedCoords.validspawnpoint = true; + if( tr.pHit && FClassnameIs( tr.pHit, "func_door" ) ) + tr.pHit->v.solid = SOLID_NOT; + ALERT( at_console, "CoopGetSpawnPoint: ^2offset set\n"); + + } + else + { + //g_SavedCoords.valid = false; + ALERT( at_console, "CoopGetSpawnPoint: ^2trace failed\n"); + return false; + } + } + *origin = point; + + return true; +} + + +CBaseEntity *UTIL_CoopGetPlayerTrain( CBaseEntity *pPlayer) +{ + CBaseEntity *train = NULL; + + if( !pPlayer) + return NULL; + + if( !pPlayer->IsPlayer() ) + { + // activated by path track + train = pPlayer; + } + else + { + if( FNullEnt(pPlayer->pev->groundentity)) + return NULL; + + train = CBaseEntity::Instance(pPlayer->pev->groundentity); + } + + if( !train ) + return NULL; + if( !train->pev->globalname ||!STRING(train->pev->globalname) || !STRING(train->pev->globalname)[0] ) + return NULL; + // doors are elevators + if( strcmp( STRING( train->pev->classname ), "func_train") && strcmp( STRING( train->pev->classname ), "func_tracktrain") && strcmp( STRING( train->pev->classname ), "func_door") ) + return NULL; + return train; +} diff --git a/dlls/coop_util.h b/dlls/coop_util.h new file mode 100644 index 00000000..74b02e51 --- /dev/null +++ b/dlls/coop_util.h @@ -0,0 +1,108 @@ +#ifndef COOP_UTIL_H +#define COOP_UTIL_H +extern cvar_t cvar_allow_gravgun; +extern cvar_t cvar_allow_ar2; +extern cvar_t cvar_ar2_mp5; +extern cvar_t cvar_ar2_bullets; +extern cvar_t cvar_ar2_balls; +extern cvar_t cvar_wresptime; +extern cvar_t cvar_iresptime; + +extern cvar_t cvar_gibtime; +extern cvar_t cvar_hgibcount; +extern cvar_t cvar_agibcount; + +extern cvar_t mp_gravgun_players; +extern cvar_t mp_coop; +extern cvar_t mp_coop_changelevel; +extern cvar_t mp_coop_nofriendlyfire; +extern cvar_t mp_coop_disabledmap; +extern cvar_t mp_coop_checkpoints; + +extern cvar_t mp_unduck; +extern cvar_t mp_semclip; +extern cvar_t mp_coop_reconnect_hack; +extern cvar_t mp_coop_noangry; +extern cvar_t mp_spectator; + +extern cvar_t sentences_txt; +extern cvar_t materials_txt; + +extern bool g_fSavedDuck; +extern bool g_fPause; + +struct SavedCoords +{ + char ip[32][32]; + Vector origin[32]; + Vector angles[32]; + char landmark[32]; + Vector triggerorigin; + Vector triggerangles; + Vector offset; + int iCount; + bool valid; + bool validoffset; + bool validspawnpoint; + int changeback; + bool trainsaved; + Vector trainoffset; + char trainglobal[256]; + int trainuser1; + bool fUsed; + bool fDuck; +}; + + + +void UTIL_CoopValidateOffset( void ); +void UTIL_CleanSpawnPoint( Vector origin, float radius ); +char *UTIL_CoopPlayerName( CBaseEntity *pPlayer ); + +bool UTIL_CoopGetSpawnPoint( Vector *point, Vector *angles); + +bool UTIL_CoopRestorePlayerCoords(CBaseEntity *player, Vector *origin, Vector *angles ); +void UTIL_CoopSaveTrain( CBaseEntity *pPlayer, SavedCoords *coords); +Vector UTIL_FixupSpawnPoint(Vector spawn); +void UTIL_CoopActivateChangeLevel( CBaseEntity *pTrigger ); + +#ifdef PLAYER_H +void UTIL_CoopKickPlayer(CBaseEntity *pPlayer); +bool UTIL_CoopIsBadPlayer( CBaseEntity *plr ); +void UTIL_CoopNewCheckpoint( entvars_t *pevPlayer ); +CBaseEntity *UTIL_CoopGetPlayerTrain( CBaseEntity *pPlayer); +void UTIL_CoopMenu( CBasePlayer *pPlayer ); +void UTIL_SpawnPlayer( CBasePlayer *pPlayer ); +void UTIL_BecomeSpectator( CBasePlayer *pPlayer ); +void UTIL_CoopCheckpointMenu( CBasePlayer *pPlayer ); +void UTIL_CoopVoteMenu( CBasePlayer *pPlayer ); +void UTIL_CoopShowMenu( CBasePlayer *pPlayer, const char *title, int count, const char **slot, signed char time = -1 ); +extern int g_iMenu; + +// Show to all spawned players: voting, etc.. +class GlobalMenu +{ +public: + + int m_iConfirm; + int m_iVoteCount; + int m_iMaxCount; + int m_iBanCount; + float m_flTime; + const char *maps[5]; + int votes[5]; + CBaseEntity *triggers[5]; + EHANDLE m_pTrigger; + EHANDLE m_pPlayer; + void VoteMenu( CBasePlayer *pPlayer ); + void ConfirmMenu( CBasePlayer *pPlayer, CBaseEntity *trigger, const char *mapname ); + void ShowGlobalMenu( const char *title, int count, const char **menu ); + void Process( CBasePlayer *pPlayer, int imenu ); +}; + +extern GlobalMenu g_GlobalMenu; +#endif +extern struct SavedCoords g_SavedCoords, s_SavedCoords; + +#endif // COOP_UTIL_H + diff --git a/dlls/crossbow.cpp b/dlls/crossbow.cpp index 2a9c9c09..bf4cf945 100644 --- a/dlls/crossbow.cpp +++ b/dlls/crossbow.cpp @@ -27,6 +27,8 @@ #define BOLT_AIR_VELOCITY 2000 #define BOLT_WATER_VELOCITY 1000 +extern BOOL gPhysicsInterfaceInitialized; + // UNDONE: Save/restore this? Don't forget to set classname and LINK_ENTITY_TO_CLASS() // // OVERLOADS SOME ENTVARS: @@ -181,9 +183,11 @@ void CCrossbowBolt::BoltTouch( CBaseEntity *pOther ) pev->angles.z = RANDOM_LONG( 0, 360 ); pev->nextthink = gpGlobals->time + 60.0; - // g-cont. Setup movewith feature - pev->movetype = MOVETYPE_COMPOUND; // set movewith type - pev->aiment = ENT( pOther->pev ); // set parent + if (gPhysicsInterfaceInitialized) { + // g-cont. Setup movewith feature + pev->movetype = MOVETYPE_COMPOUND; // set movewith type + pev->aiment = ENT( pOther->pev ); // set parent + } } if( UTIL_PointContents( pev->origin ) != CONTENTS_WATER ) diff --git a/dlls/effects.cpp b/dlls/effects.cpp index d076f551..21a57a55 100644 --- a/dlls/effects.cpp +++ b/dlls/effects.cpp @@ -411,7 +411,7 @@ LINK_ENTITY_TO_CLASS( trip_beam, CTripBeam ) void CTripBeam::Spawn( void ) { CLightning::Spawn(); - SetTouch( &TriggerTouch ); + SetTouch( &CLightning::TriggerTouch ); pev->solid = SOLID_TRIGGER; RelinkBeam(); } diff --git a/dlls/game.cpp b/dlls/game.cpp index dc27ab40..03ddf7f9 100644 --- a/dlls/game.cpp +++ b/dlls/game.cpp @@ -56,10 +56,15 @@ cvar_t mp_coop_nofriendlyfire = { "mp_coop_nofriendlyfire", "0", FCVAR_SERVER }; cvar_t mp_coop_disabledmap = { "mp_coop_disabledmap", "", FCVAR_SERVER }; cvar_t mp_coop_reconnect_hack = { "mp_coop_reconnect_hack", "0", FCVAR_SERVER }; cvar_t mp_coop_noangry = { "mp_coop_noangry", "0", FCVAR_SERVER }; +cvar_t mp_coop_checkpoints = { "mp_coop_checkpoints", "1", FCVAR_SERVER }; + cvar_t mp_unduck = { "mp_unduck", "0", FCVAR_SERVER }; cvar_t mp_semclip = { "mp_semclip", "0", FCVAR_SERVER }; cvar_t mp_spectator = { "mp_spectator", "0", FCVAR_SERVER }; +cvar_t materials_txt = { "materials_txt", "sound/materials.txt", FCVAR_SERVER }; +cvar_t sentences_txt = { "sentences_txt", "sound/sentences.txt", FCVAR_SERVER }; + // Engine Cvars cvar_t *g_psv_gravity = NULL; cvar_t *g_psv_aim = NULL; @@ -510,6 +515,10 @@ void GameDLLInit( void ) CVAR_REGISTER( &mp_coop_reconnect_hack ); CVAR_REGISTER( &mp_coop_noangry ); CVAR_REGISTER( &mp_spectator ); + CVAR_REGISTER( &mp_coop_checkpoints ); + + CVAR_REGISTER( &sentences_txt ); + CVAR_REGISTER( &materials_txt ); CVAR_REGISTER( &mp_chattime ); diff --git a/dlls/game.h b/dlls/game.h index c5a61d9a..9828a614 100644 --- a/dlls/game.h +++ b/dlls/game.h @@ -35,31 +35,8 @@ extern cvar_t teamlist; extern cvar_t teamoverride; extern cvar_t defaultteam; extern cvar_t allowmonsters; -extern cvar_t cvar_allow_gravgun; -extern cvar_t cvar_allow_ar2; -extern cvar_t cvar_ar2_mp5; -extern cvar_t cvar_ar2_bullets; -extern cvar_t cvar_ar2_balls; -extern cvar_t cvar_wresptime; -extern cvar_t cvar_iresptime; -extern cvar_t cvar_gibtime; -extern cvar_t cvar_hgibcount; -extern cvar_t cvar_agibcount; - -extern cvar_t mp_gravgun_players; -extern cvar_t mp_coop; -extern cvar_t mp_coop_changelevel; -extern cvar_t mp_coop_nofriendlyfire; -extern cvar_t mp_coop_disabledmap; -extern cvar_t mp_unduck; -extern cvar_t mp_semclip; -extern cvar_t mp_coop_reconnect_hack; -extern cvar_t mp_coop_noangry; -extern cvar_t mp_spectator; - -extern bool g_fSavedDuck; -extern bool g_fPause; +#include "coop_util.h" // Engine Cvars extern cvar_t *g_psv_gravity; diff --git a/dlls/gamerules.cpp b/dlls/gamerules.cpp index aeb652f8..17dd861e 100644 --- a/dlls/gamerules.cpp +++ b/dlls/gamerules.cpp @@ -57,27 +57,8 @@ BOOL CGameRules::CanHaveAmmo( CBasePlayer *pPlayer, const char *pszAmmoName, int return FALSE; } -bool CoopGetSpawnPoint( Vector *point, Vector *angles); -bool CoopRestorePlayerCoords(CBaseEntity *player, Vector *origin, Vector *angles ); -Vector FixupSpawnPoint(Vector spawn) -{ - int i = 0; - // predict that spawn point is almost correct - while( i < 2 ) // 2 player heights - { - Vector point = spawn + Vector( 0, 0, 36 * i ); - TraceResult tr; - UTIL_TraceHull( point, point, ignore_monsters, (mp_unduck.value&&g_fSavedDuck)?head_hull:human_hull, NULL, &tr ); - if( !tr.fStartSolid && !tr.fAllSolid ) - return point; - i = -i; - if( i >= 0 ) - i++; - } - return spawn; -} extern EHANDLE g_pLastSpawn; //========================================================= //========================================================= @@ -107,8 +88,8 @@ edict_t *CGameRules::GetPlayerSpawnSpot( CBasePlayer *pPlayer ) pPlayer->pev->angles = VARS( pentSpawnSpot )->angles; pPlayer->pev->punchangle = g_vecZero; if( !(pPlayer->pev->flags & FL_SPECTATOR ) ) - if( mp_coop_changelevel.value && !CoopRestorePlayerCoords( pPlayer, &pPlayer->pev->origin, &pPlayer->pev->angles )) - if( !CoopGetSpawnPoint( &pPlayer->pev->origin, &pPlayer->pev->angles ) ) + if( mp_coop_changelevel.value && !UTIL_CoopRestorePlayerCoords( pPlayer, &pPlayer->pev->origin, &pPlayer->pev->angles )) + if( !UTIL_CoopGetSpawnPoint( &pPlayer->pev->origin, &pPlayer->pev->angles ) ) { if( !g_pLastSpawn ) { @@ -117,11 +98,11 @@ edict_t *CGameRules::GetPlayerSpawnSpot( CBasePlayer *pPlayer ) params.fadeoutTime = .5; params.holdTime = 10; params.channel = 0; - params.y = 0; + params.x = params.y = -1; params.r2 = params.g2 = params.b2 = params.a2 = params.r1 = params.g1 = params.b1 = params.a1 = 255; - UTIL_HudMessage( pPlayer, params, "Server cannot select a spawnpoint, please fly to it manually and press attack button" ); + UTIL_HudMessage( pPlayer, params, "Server cannot select a spawnpoint\nplease fly to it manually\nand press attack button" ); // select spawn point pPlayer->m_state = STATE_POINT_SELECT; pPlayer->m_afButtonPressed = 0; @@ -133,7 +114,7 @@ edict_t *CGameRules::GetPlayerSpawnSpot( CBasePlayer *pPlayer ) } } pPlayer->pev->fixangle = TRUE; - pPlayer->pev->origin = FixupSpawnPoint( pPlayer->pev->origin ); + pPlayer->pev->origin = UTIL_FixupSpawnPoint( pPlayer->pev->origin ); if( g_fSavedDuck ) pPlayer->pev->flags |= FL_DUCKING; diff --git a/dlls/multiplay_gamerules.cpp b/dlls/multiplay_gamerules.cpp index ce08e7ca..c2f6daab 100644 --- a/dlls/multiplay_gamerules.cpp +++ b/dlls/multiplay_gamerules.cpp @@ -96,38 +96,11 @@ void CoopClearWeaponList( void ) } extern int g_iMenu; -void BecomeSpectator( CBasePlayer *pPlayer ) -{ - //pPlayer->m_bDoneFirstSpawn = true; - pPlayer->pev->takedamage = DAMAGE_NO; - pPlayer->pev->flags |= FL_SPECTATOR; - pPlayer->pev->flags |= FL_NOTARGET; - pPlayer->pev->effects |= EF_NODRAW; - pPlayer->pev->solid = SOLID_NOT; - pPlayer->pev->movetype = MOVETYPE_NOCLIP; - pPlayer->pev->modelindex = 0; - pPlayer->pev->health = 1; - pPlayer->m_pGoalEnt = NULL; - return; -} - -void SpawnPlayer( CBasePlayer *pPlayer ) -{ - pPlayer->m_state = STATE_SPAWNED; - pPlayer->m_iRespawnFrames = 0; - pPlayer->pev->effects &= ~EF_NODRAW; - pPlayer->pev->takedamage = DAMAGE_YES; - pPlayer->pev->flags &= ~FL_SPECTATOR; - pPlayer->pev->movetype = MOVETYPE_WALK; - pPlayer->Spawn(); - CLIENT_COMMAND( pPlayer->edict(), "touch_show _coopm*\n" ); - -} extern int gmsgShowMenu; -void ShowMenu( CBasePlayer *pPlayer, const char *title, int count, const char **slot, signed char time = -1 ) +void UTIL_CoopShowMenu( CBasePlayer *pPlayer, const char *title, int count, const char **slot, signed char time ) { if( pPlayer->m_fTouchMenu) { @@ -161,9 +134,9 @@ void ShowMenu( CBasePlayer *pPlayer, const char *title, int count, const char ** //CLIENT_COMMAND( pPlayer->edict(), "exec touch_default/numbers.cfg\n"); } -void CoopMenu( CBasePlayer *pPlayer ); +void UTIL_CoopMenu( CBasePlayer *pPlayer ); -void CoopVoteMenu( CBasePlayer *pPlayer ); +void UTIL_CoopVoteMenu( CBasePlayer *pPlayer ); //********************************************************* @@ -217,7 +190,7 @@ CHalfLifeMultiplay::CHalfLifeMultiplay() } } -void CoopProcessMenu( CBasePlayer *pPlayer, int imenu ); +void UTIL_CoopProcessMenu( CBasePlayer *pPlayer, int imenu ); BOOL CHalfLifeMultiplay::ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) { @@ -230,7 +203,7 @@ BOOL CHalfLifeMultiplay::ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) if( FStrEq( pcmd, "joincoop" ) ) { if( pPlayer->m_state == STATE_SPECTATOR_BEGIN ) - SpawnPlayer( pPlayer ); + UTIL_SpawnPlayer( pPlayer ); else ClientPrint( pPlayer->pev, HUD_PRINTCONSOLE, "You cannot use joincoop now!\n\n" ); @@ -240,57 +213,13 @@ BOOL CHalfLifeMultiplay::ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) { int imenu = atoi( CMD_ARGV( 1 ) ); - switch( pPlayer->m_state ) - { - case STATE_SPECTATOR_BEGIN: - case STATE_SPECTATOR: - if( imenu == 1 ) - { - SpawnPlayer( pPlayer ); - pPlayer->m_state = STATE_SPAWNED; - } - if( imenu == 2 ) - { - pPlayer->m_state = STATE_SPECTATOR; - CLIENT_COMMAND( pPlayer->edict(), "touch_show _coopm*\n" ); - } - break; - case STATE_SPAWNED: - if( g_iMenu ) - { - CoopProcessMenu( pPlayer, imenu ); - return TRUE; - } - if( imenu == 1 ) - { - pPlayer->RemoveAllItems( TRUE ); - SpawnPlayer( pPlayer ); - } - if( imenu == 2 ) - { - UTIL_CleanSpawnPoint( pPlayer->pev->origin, 150 ); - } - if( imenu == 3 ) - { - pPlayer->RemoveAllItems( TRUE ); - BecomeSpectator( pPlayer ); - pPlayer->m_state = STATE_SPECTATOR; - } - if( imenu == 4 ) - { - CoopVoteMenu( pPlayer ); - } - default: - break; - } + UTIL_CoopProcessMenu( pPlayer, imenu ); + return TRUE; } if( FStrEq( pcmd, "coopmenu" ) ) { - if( !g_iMenu ) - CoopMenu( pPlayer ); - else - ClientPrint( pPlayer->pev, HUD_PRINTCONSOLE, "You cannot use coopmenu now!\n\n" ); + UTIL_CoopMenu( pPlayer ); return TRUE; } @@ -309,7 +238,8 @@ void CHalfLifeMultiplay::RefreshSkillData( void ) // override some values for multiplay. // suitcharger - gSkillData.suitchargerCapacity = 30; + if( !mp_coop.value ) + gSkillData.suitchargerCapacity = 30; // Crowbar whack gSkillData.plrDmgCrowbar = 25; @@ -660,6 +590,7 @@ void CHalfLifeMultiplay::InitHUD( CBasePlayer *pl ) if( pl->m_state == STATE_SPECTATOR_BEGIN ) { + pl->m_iMenuState = MENUSTATE_COOPMENU_SPEC; if( mp_coop.value ) { @@ -667,7 +598,7 @@ void CHalfLifeMultiplay::InitHUD( CBasePlayer *pl ) "Join coop", "Join spectators" }; - ShowMenu( pl, "COOP SERVER", ARRAYSIZE( menu ), menu ); + UTIL_CoopShowMenu( pl, "COOP SERVER", ARRAYSIZE( menu ), menu ); } } } @@ -745,7 +676,7 @@ void CHalfLifeMultiplay::PlayerThink( CBasePlayer *pPlayer ) { if( !mp_coop.value && pPlayer->m_state == STATE_SPECTATOR_BEGIN ) if( pPlayer->m_afButtonPressed & ( IN_DUCK | IN_ATTACK | IN_ATTACK2 | IN_USE | IN_JUMP ) ) - SpawnPlayer( pPlayer ); + UTIL_SpawnPlayer( pPlayer ); if( pPlayer->m_state == STATE_UNINITIALIZED ) if( pPlayer->m_afButtonPressed || pPlayer->pev->button ) { @@ -792,14 +723,14 @@ void CHalfLifeMultiplay::PlayerSpawn( CBasePlayer *pPlayer ) { pPlayer->m_state = STATE_SPECTATOR_BEGIN; pPlayer->RemoveAllItems( TRUE ); - BecomeSpectator( pPlayer ); + UTIL_BecomeSpectator( pPlayer ); return; } if( mp_coop.value && pPlayer->m_state == STATE_POINT_SELECT && !(pPlayer->pev->flags & FL_SPECTATOR) ) { pPlayer->RemoveAllItems( TRUE ); - BecomeSpectator( pPlayer ); + UTIL_BecomeSpectator( pPlayer ); return; } @@ -1339,12 +1270,12 @@ Vector CHalfLifeMultiplay::VecAmmoRespawnSpot( CBasePlayerAmmo *pAmmo ) //========================================================= float CHalfLifeMultiplay::FlHealthChargerRechargeTime( void ) { - return 60; + return cvar_iresptime.value * 2; } float CHalfLifeMultiplay::FlHEVChargerRechargeTime( void ) { - return 30; + return cvar_iresptime.value; } //========================================================= diff --git a/dlls/nodes.cpp b/dlls/nodes.cpp index ed4b4033..a97b6a80 100644 --- a/dlls/nodes.cpp +++ b/dlls/nodes.cpp @@ -45,6 +45,8 @@ LINK_ENTITY_TO_CLASS( info_node_air, CNodeEnt ) #include #include #define CreateDirectory(p, n) mkdir(p, 0777) +#else +#define CreateDirectory(p, n) CreateDirectoryA(p, n) #endif //========================================================= diff --git a/dlls/player.cpp b/dlls/player.cpp index 84c20ad8..8428803e 100644 --- a/dlls/player.cpp +++ b/dlls/player.cpp @@ -92,9 +92,9 @@ TYPEDESCRIPTION CBasePlayer::m_playerSaveData[] = DEFINE_ARRAY( CBasePlayer, m_rgflSuitNoRepeatTime, FIELD_TIME, CSUITNOREPEAT ), DEFINE_FIELD( CBasePlayer, m_lastDamageAmount, FIELD_INTEGER ), - DEFINE_ARRAY( CBasePlayer, m_rgpPlayerItems, FIELD_CLASSPTR, MAX_ITEM_TYPES ), - DEFINE_FIELD( CBasePlayer, m_pActiveItem, FIELD_CLASSPTR ), - DEFINE_FIELD( CBasePlayer, m_pLastItem, FIELD_CLASSPTR ), + DEFINE_ARRAY( CBasePlayer, m_rgpPlayerItems, FIELD_EHANDLE, MAX_ITEM_TYPES ), + DEFINE_FIELD( CBasePlayer, m_pActiveItem, FIELD_EHANDLE ), + DEFINE_FIELD( CBasePlayer, m_pLastItem, FIELD_EHANDLE ), DEFINE_ARRAY( CBasePlayer, m_rgAmmo, FIELD_INTEGER, MAX_AMMO_SLOTS ), DEFINE_FIELD( CBasePlayer, m_idrowndmg, FIELD_INTEGER ), diff --git a/dlls/player.h b/dlls/player.h index 13727506..a74757f6 100644 --- a/dlls/player.h +++ b/dlls/player.h @@ -93,6 +93,18 @@ enum PlayerState STATE_POINT_SELECT }; +enum PlayerMenuState +{ + MENUSTATE_NONE = 0, + MENUSTATE_COOPMENU, + MENUSTATE_COOPMENU_SPEC, + MENUSTATE_CHECKPOINT, + MENUSTATE_GLOBAL, + MENUSTATE_LOCAL_CONFIRM +}; + +#include "whandle.h" + class CBasePlayer : public CBaseMonster { public: @@ -173,10 +185,10 @@ public: int m_iClientFOV; // client's known FOV // usable player items - CBasePlayerItem *m_rgpPlayerItems[MAX_ITEM_TYPES]; - CBasePlayerItem *m_pActiveItem; - CBasePlayerItem *m_pClientActiveItem; // client version of the active item - CBasePlayerItem *m_pLastItem; + EHBasePlayerItem m_rgpPlayerItems[MAX_ITEM_TYPES]; + EHBasePlayerItem m_pActiveItem; + EHBasePlayerItem m_pClientActiveItem; // client version of the active item + EHBasePlayerItem m_pLastItem; // shared ammo slots int m_rgAmmo[MAX_AMMO_SLOTS]; @@ -323,6 +335,9 @@ public: float m_flSpawnTime; PlayerState m_state; bool m_fTouchMenu; + int m_iMenuState; + int m_iLocalConfirm; + int m_iConfirmKey; virtual void Touch( CBaseEntity *pOther ); }; diff --git a/dlls/sound.cpp b/dlls/sound.cpp index b97eee12..c9a46f55 100644 --- a/dlls/sound.cpp +++ b/dlls/sound.cpp @@ -23,6 +23,7 @@ #include "player.h" #include "talkmonster.h" #include "gamerules.h" +#include "game.h" static char *memfgets( byte *pMemFile, int fileSize, int &filePos, char *pBuffer, int bufferSize ); @@ -1264,7 +1265,7 @@ void SENTENCEG_Init() isentencegs = -1; int filePos = 0, fileSize; - byte *pMemFile = g_engfuncs.pfnLoadFileForMe( "sound/sentences.txt", &fileSize ); + byte *pMemFile = g_engfuncs.pfnLoadFileForMe( sentences_txt.string, &fileSize ); if( !pMemFile ) return; @@ -1528,7 +1529,7 @@ void TEXTURETYPE_Init() gcTextures = 0; - pMemFile = g_engfuncs.pfnLoadFileForMe( "sound/materials.txt", &fileSize ); + pMemFile = g_engfuncs.pfnLoadFileForMe( materials_txt.string, &fileSize ); if( !pMemFile ) return; diff --git a/dlls/talkmonster.cpp b/dlls/talkmonster.cpp index a0a52f52..d832c2cc 100644 --- a/dlls/talkmonster.cpp +++ b/dlls/talkmonster.cpp @@ -1342,6 +1342,8 @@ BOOL CTalkMonster::CanFollow( void ) { if( m_MonsterState == MONSTERSTATE_SCRIPT ) { + if( !m_pCine ) + return FALSE; if( !m_pCine->CanInterrupt() ) return FALSE; } diff --git a/dlls/triggers.cpp b/dlls/triggers.cpp index e852a4aa..74ce68fd 100644 --- a/dlls/triggers.cpp +++ b/dlls/triggers.cpp @@ -913,7 +913,7 @@ void CBaseTrigger::HurtTouch( CBaseEntity *pOther ) // HACKHACK -- In multiplayer, players touch this based on packet receipt. // So the players who send packets later aren't always hurt. Keep track of // how much time has passed and whether or not you've touched that player - if( g_pGameRules->IsMultiplayer() ) + if( !mp_coop.value && g_pGameRules->IsMultiplayer() ) { if( pev->dmgtime > gpGlobals->time ) { @@ -1350,6 +1350,7 @@ public: bool m_fSpawnSaved; bool m_fIsBack; bool m_fSkipSpawnCheck; // skip 30 seconds check when called by multimanager or trigger_once + float m_flRepeatTimer; }; LINK_ENTITY_TO_CLASS( trigger_changelevel, CChangeLevel ) @@ -1486,223 +1487,62 @@ void CChangeLevel::UseChangeLevel( CBaseEntity *pActivator, CBaseEntity *pCaller ChangeLevelNow( pActivator ); } -struct SavedCoords +void UTIL_CoopActivateChangeLevel( CBaseEntity *pTrigger ) { - char ip[32][32]; - Vector origin[32]; - Vector angles[32]; - char landmark[32]; - Vector triggerorigin; - Vector triggerangles; - Vector offset; - int iCount; - bool valid; - bool validoffset; - bool validspawnpoint; - int changeback; - bool trainsaved; - Vector trainoffset; - char trainglobal[256]; - int trainuser1; - bool fUsed; - bool fDuck; -} g_SavedCoords, s_SavedCoords; - + CChangeLevel *trigger = (CChangeLevel*) pTrigger; + if( !trigger ) + return; -void CoopClearData( void ) -{ - // nullify - SavedCoords l_SavedCoords = {}; - g_SavedCoords = l_SavedCoords; + trigger->m_bUsed = true; + trigger->ChangeLevelNow( NULL ); } -bool g_fPause; -void CoopApplyData( void ) +void GlobalMenu::VoteMenu( CBasePlayer *pPlayer ) { - if( s_SavedCoords.valid ) + if( g_iMenu && gpGlobals->time - m_flTime < 30 ) + return; // wait 30s befor new confirm vote + CBaseEntity *pTrigger = NULL; + int i = 0; + g_iMenu = 2; + m_flTime = gpGlobals->time; + maps[i++] = "Keep this map"; + maps[i++] = "BAN"; + while( (pTrigger = UTIL_FindEntityByClassname( pTrigger, "trigger_changelevel" )) && (i < 5) ) { - g_SavedCoords = s_SavedCoords; - s_SavedCoords = {}; - g_fSavedDuck = g_SavedCoords.fDuck; - } - g_fPause = false; - ALERT( at_console, "^2CoopApplyData()\n" ); -} - -int g_iMenu; - -void ShowMenu( CBasePlayer *pPlayer, const char *title, int count, const char **slot, signed char time = -1 ); + CChangeLevel *ent = (CChangeLevel *)pTrigger; + votes[i] = 0; + triggers[i] = ent; + maps[i++] = ent->m_szMapName; -bool g_fSavedDuck; -#define CoopPlayerName( pPlayer ) ( ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected" ) + } + votes[i] = 0; + triggers[i] = NULL; + m_iConfirm = i; + m_iVoteCount = 0; + m_pPlayer = pPlayer; + MESSAGE_BEGIN( MSG_ALL, 8, NULL ); // svc_print + WRITE_BYTE( 3 ); // PRINT_CHAT + WRITE_STRING( UTIL_VarArgs( "%s^7 opened vote menu\n", ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected")); + MESSAGE_END(); + ShowGlobalMenu(UTIL_VarArgs("%s requested to force change map", UTIL_CoopPlayerName( pPlayer ) ), i, maps); -void CoopKickPlayer(CBaseEntity *pPlayer) -{ - if( !pPlayer ) - return; - SERVER_COMMAND( UTIL_VarArgs( "kick %d\n", ENTINDEX(pPlayer->pev->pContainingEntity) - 1 ) ); } -// Show to all spawned players: voting, etc.. -class GlobalMenu -{ -public: - - int m_iConfirm; - int m_iVoteCount; - int m_iMaxCount; - int m_iBanCount; - float m_flTime; - const char *maps[5]; - int votes[5]; - CChangeLevel *triggers[5]; - EHANDLE m_pTrigger; - EHANDLE m_pPlayer; - void Process( CBasePlayer *pPlayer, int imenu ) - { - if( pPlayer->pev->flags & FL_SPECTATOR ) - return; - if( gpGlobals->time - m_flTime > 30 ) - { - g_iMenu = 0; - return; - } - - switch( g_iMenu ) - { - case 1: // touch blue trigger - m_iVoteCount++; - - if( imenu == 1 ) // confirm - { - if( m_iBanCount >= 2 ) - { - CoopKickPlayer( pPlayer ); - m_iConfirm-= 5; - return; - } m_iConfirm++; - MESSAGE_BEGIN( MSG_ALL, 8, NULL ); // svc_print - WRITE_BYTE( 3 ); // PRINT_CHAT - WRITE_STRING( UTIL_VarArgs( "%s^7 confirmed map change\n", ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected")); - MESSAGE_END(); - - } - if( imenu == 2 ) // cancel - { - m_iConfirm--; - if( pPlayer == m_pPlayer ) - m_iConfirm -= 100; // player mistake - } - if( imenu == 3 ) - { - m_iBanCount++; - if( m_iBanCount >= 2 && m_iConfirm > -50 ) - CoopKickPlayer( m_pPlayer ); - } - break; - case 2: // vote by request - MESSAGE_BEGIN( MSG_ALL, 8, NULL ); // svc_print - WRITE_BYTE( 3 ); // PRINT_CHAT - WRITE_STRING( UTIL_VarArgs( "%s^7 selected ^3%s\n", ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected", maps[imenu - 1] )); - MESSAGE_END(); - - if( imenu < m_iConfirm ) - { - votes[imenu-1]++; - m_iVoteCount++; - - if( votes[1] >= 2 ) - { - // two players vote for ban - CoopKickPlayer( m_pPlayer ); - } - - if( m_iVoteCount >= m_iMaxCount ) - { - for( int i = 0; i <= m_iConfirm; i++ ) - if( votes[i] >= m_iMaxCount ) - { - if( triggers[i]) - { - triggers[i]->m_bUsed = true; - triggers[i]->ChangeLevelNow( NULL ); - } - g_iMenu = 0; - } - - } - - } - } - } - void ShowGlobalMenu( const char *title, int count, const char **menu ) +void UTIL_CoopValidateOffset( void ) +{ + if( !g_SavedCoords.validoffset) { - int count2 = 0; - for( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *plr = UTIL_PlayerByIndex( i ); - - if( plr && plr->IsPlayer() ) - { - count2++; - ShowMenu( (CBasePlayer *)plr, title, count, menu, 30 ); - - } - } - m_iMaxCount = count2; - m_iBanCount = 0; - } - - void ConfirmMenu( CBasePlayer *pPlayer, CBaseEntity *trigger, const char *mapname ) - { - if( g_iMenu && gpGlobals->time - m_flTime < 30 ) - return; // wait 30s befor new confirm vote - g_iMenu = 1; - m_flTime = gpGlobals->time; - m_pTrigger = trigger; - m_pPlayer = pPlayer; - const char *menu[] = { - "Confirm", - "Cancel", - "BAN" - }; - ShowGlobalMenu(UTIL_VarArgs("Confirm changing map to %s?", mapname), ARRAYSIZE(menu), menu); - - } - void VoteMenu( CBasePlayer *pPlayer ) - { - if( g_iMenu && gpGlobals->time - m_flTime < 30 ) - return; // wait 30s befor new confirm vote - CBaseEntity *pTrigger = NULL; - int i = 0; - g_iMenu = 2; - m_flTime = gpGlobals->time; - maps[i++] = "Keep this map"; - maps[i++] = "BAN"; - while( (pTrigger = UTIL_FindEntityByClassname( pTrigger, "trigger_changelevel" )) && (i < 5) ) - { - CChangeLevel *ent = (CChangeLevel *)pTrigger; - votes[i] = 0; - triggers[i] = ent; - maps[i++] = ent->m_szMapName; - - - } - votes[i] = 0; - triggers[i] = NULL; - m_iConfirm = i; - m_iVoteCount = 0; - m_pPlayer = pPlayer; - ShowGlobalMenu(UTIL_VarArgs("%s requested to force change map", CoopPlayerName( pPlayer ) ), i, maps); - + edict_t *landmark = CChangeLevel::FindLandmark(g_SavedCoords.landmark); + if(landmark) + g_SavedCoords.offset = landmark->v.origin - g_SavedCoords.offset; + else + g_SavedCoords.offset = g_vecZero - g_SavedCoords.offset; + g_SavedCoords.validoffset = true; } - - -}; -GlobalMenu g_GlobalMenu; +} @@ -1716,7 +1556,7 @@ void CChangeLevel::UpdateColor( void ) if( !m_fIsBack && (pPlayer = UTIL_FindEntityByClassname( NULL, "info_player_start" )) ) if( (origin - pPlayer->pev->origin).Length() < 500 ) m_fIsBack = true; - if( !m_fIsBack && CoopGetSpawnPoint( &point, &angles ) ) + if( !m_fIsBack && UTIL_CoopGetSpawnPoint( &point, &angles ) ) if( (origin - point).Length() < 500 ) m_fIsBack = true; pev->rendercolor = g_vecZero; @@ -1732,224 +1572,7 @@ void CChangeLevel::UpdateColor( void ) } -void CoopVoteMenu( CBasePlayer *pPlayer ) -{ - int count = 0; - for( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *plr = UTIL_PlayerByIndex( i ); - - if( plr && plr->IsPlayer() ) - { - count++; - } - } - if( count < 4 ) - { - ClientPrint( pPlayer->pev, HUD_PRINTCENTER, "Need at least 4 players to vote changelevel!\n" ); - return; - } - g_GlobalMenu.VoteMenu(pPlayer); -} -void CoopMenu( CBasePlayer *pPlayer ) -{ - if( g_iMenu && gpGlobals->time - g_GlobalMenu.m_flTime < 30 ) - return; // global menu active - if( pPlayer->m_state == STATE_SPAWNED ) - { - - if( mp_coop.value ) - { - const char *menu[] = { - "Force respawn", - "Unblock", - "Become spectator", - "Vote changelevel" - }; - ShowMenu( pPlayer, "Coop menu", ARRAYSIZE( menu ), menu ); - } - } - else if ( pPlayer->m_state == STATE_SPECTATOR ) - { - if( mp_coop.value ) - { - const char *menu[] = { - "Spawn", - "Close menu" - }; - ShowMenu( pPlayer, "Spectator menu", ARRAYSIZE( menu ), menu ); - } - } -} - -void CoopProcessMenu( CBasePlayer *pPlayer, int imenu ) -{ - return g_GlobalMenu.Process( pPlayer, imenu ); -} - -static void validateoffset( void ) -{ - if( !g_SavedCoords.validoffset) - { - edict_t *landmark = CChangeLevel::FindLandmark(g_SavedCoords.landmark); - if(landmark) - g_SavedCoords.offset = landmark->v.origin - g_SavedCoords.offset; - else - g_SavedCoords.offset = g_vecZero - g_SavedCoords.offset; - g_SavedCoords.validoffset = true; - } -} - -bool CoopRestorePlayerCoords(CBaseEntity *player, Vector *origin, Vector *angles ) -{ - if(!g_SavedCoords.valid) - return false; - validateoffset(); - // compute player by IQ - char *ip = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( player->edict() ), "ip" ); - for( int i = 0;i < g_SavedCoords.iCount;i++) - { - if(ip && ip[0] && !strcmp(ip, g_SavedCoords.ip[i]) ) - { - TraceResult tr; - Vector point = g_SavedCoords.origin[i] + g_SavedCoords.offset; - - UTIL_TraceHull( point, point, missile, (mp_unduck.value&&g_fSavedDuck)?head_hull:human_hull, NULL, &tr ); - - g_SavedCoords.ip[i][0] = 0; - - if( tr.fStartSolid || tr.fAllSolid ) - return false; - *origin = point; - *angles = g_SavedCoords.angles[i]; - return true; - } - } - return false; -} - -bool CoopGetSpawnPoint( Vector *origin, Vector *angles) -{ - if(!g_SavedCoords.valid) - return false; - - // spawn on elevator or train - if( g_SavedCoords.trainsaved ) - { - CBaseEntity *train = UTIL_FindEntityByString( NULL, "globalname", g_SavedCoords.trainglobal ); - if( !train ) train = UTIL_FindEntityByString( NULL, "classname", g_SavedCoords.trainglobal ); - if( train && ( !g_SavedCoords.trainuser1 || train->pev->iuser1 == g_SavedCoords.trainuser1 ) ) - { - *angles = g_SavedCoords.triggerangles; - *origin = VecBModelOrigin(train->pev) + g_SavedCoords.trainoffset; - g_SavedCoords.trainuser1 = train->pev->iuser1; - return true; - } - ALERT( at_console, "Failed to get train %s (map design error?)\n", g_SavedCoords.trainglobal ); - } - Vector point = g_SavedCoords.triggerorigin; - *angles = g_SavedCoords.triggerangles; - if( !g_SavedCoords.validspawnpoint ) - { - TraceResult tr; - Vector angle; - UTIL_MakeVectorsPrivate( *angles, (float*)&angle, NULL, NULL ); - validateoffset(); - point = point + g_SavedCoords.offset; - //UTIL_TraceHull( point, point, ignore_monsters, human_hull, NULL, &tr ); - - if( mp_unduck.value && g_fSavedDuck && !g_SavedCoords.fUsed ) - UTIL_TraceHull( point, point + angle * 100, missile, head_hull, NULL, &tr ); - else - UTIL_TraceHull( point, point + angle * 100, ignore_monsters, human_hull, NULL, &tr ); - - if( !tr.fStartSolid && !tr.fAllSolid || ENTINDEX( tr.pHit ) && ENTINDEX( tr.pHit ) <= gpGlobals->maxClients ) - { - //g_SavedCoords.triggerorigin = tr.vecEndPos; - //g_SavedCoords.validspawnpoint = true; - if( tr.pHit && FClassnameIs( tr.pHit, "func_door" ) ) - tr.pHit->v.solid = SOLID_NOT; - ALERT( at_console, "CoopGetSpawnPoint: ^2offset set\n"); - - } - else - { - //g_SavedCoords.valid = false; - ALERT( at_console, "CoopGetSpawnPoint: ^2trace failed\n"); - return false; - } - } - *origin = point; - - return true; -} - -CBaseEntity *CoopGetPlayerTrain( CBaseEntity *pPlayer) -{ - CBaseEntity *train = NULL; - - if( !pPlayer) - return NULL; - - if( !pPlayer->IsPlayer() ) - { - // activated by path track - train = pPlayer; - } - else - { - if( FNullEnt(pPlayer->pev->groundentity)) - return NULL; - - train = CBaseEntity::Instance(pPlayer->pev->groundentity); - } - - if( !train ) - return NULL; - if( !train->pev->globalname ||!STRING(train->pev->globalname) || !STRING(train->pev->globalname)[0] ) - return NULL; - // doors are elevators - if( strcmp( STRING( train->pev->classname ), "func_train") && strcmp( STRING( train->pev->classname ), "func_tracktrain") && strcmp( STRING( train->pev->classname ), "func_door") ) - return NULL; - return train; -} - // If some player is on train with global state, save id -void CoopSaveTrain( CBaseEntity *pPlayer, SavedCoords *coords) -{ - if( coords->trainsaved ) - return; - - CBaseEntity *train = CoopGetPlayerTrain(pPlayer); - if( !train ) - { - ALERT( at_console, "^1NO TRAIN!\n"); - return; - } - ALERT( at_console, "^1TRAIN IS %s\n", STRING( train->pev->classname ) ); - - if( !pPlayer->IsPlayer() ) - { - // it is trainnitself, try find player on it - CBaseEntity *pList; - Vector mins = pPlayer->pev->absmin; - Vector maxs = pPlayer->pev->absmax; - maxs.z += 72; - int count = UTIL_EntitiesInBox( &pList, 1, mins, maxs, FL_ONGROUND ); - if( count && pList && pList->IsPlayer() ) - pPlayer = pList; - else - { - ALERT( at_console, "Train without players\n" ); - return; - } - } - - strcpy( coords->trainglobal, STRING(train->pev->globalname) ); - coords->trainoffset = pPlayer->pev->origin - VecBModelOrigin(train->pev); - coords->trainsaved = true; -} -void BecomeSpectator( CBasePlayer *pPlayer ); CBaseEntity *FindTriggerTransition( char *pVolumeName ) { @@ -2011,7 +1634,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) m_vecSpawnOrigin = pActivator->pev->origin; m_vecSpawnAngles = pActivator->pev->angles; m_fSpawnSaved = true; - CoopSaveTrain( pActivator, &l_SavedCoords ); + UTIL_CoopSaveTrain( pActivator, &l_SavedCoords ); } unsigned int count1 = 0; unsigned int count2 = 0; @@ -2021,9 +1644,13 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) for( i = 1; i <= gpGlobals->maxClients; i++ ) { CBaseEntity *plr = UTIL_PlayerByIndex( i ); + CBaseEntity *pTrain = UTIL_CoopGetPlayerTrain( plr ); + + if( !pTrain && UTIL_CoopIsBadPlayer( plr ) ) + continue; // count only players spawned more 30 seconds ago - if( plr && plr->IsPlayer() && (CoopGetPlayerTrain(plr) || (gpGlobals->time -((CBasePlayer*)plr)->m_flSpawnTime ) > 30 ) ) + if( plr && plr->IsPlayer() && (pTrain || (gpGlobals->time -((CBasePlayer*)plr)->m_flSpawnTime ) > 30 ) ) { count2++; @@ -2034,7 +1661,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) if( InTransitionVolume( plr, m_szLandmarkName )) { l_SavedCoords.fDuck |= !!(plr->pev->flags & FL_DUCKING); - CoopSaveTrain( plr, &l_SavedCoords ); + UTIL_CoopSaveTrain( plr, &l_SavedCoords ); char *ip = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( plr->edict() ), "ip" ); strcpy(l_SavedCoords.ip[l_SavedCoords.iCount], ip ); l_SavedCoords.origin[l_SavedCoords.iCount] = plr->pev->origin; @@ -2049,53 +1676,74 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) i = 0; if( !l_SavedCoords.trainsaved ) { - if( !count2 ) - { - UTIL_HudMessageAll( params, "Cannot change level: Not enough players! Wait 30 sec before you may changelevel!" ); - return; - } + if( !count2 ) + { + if( pActivator && pActivator->IsPlayer() && m_flRepeatTimer - gpGlobals->time < -1 ) + { + CBasePlayer *pPlayer = (CBasePlayer*)pActivator; + MESSAGE_BEGIN( MSG_ALL, 8, NULL ); // svc_print + WRITE_BYTE( 3 ); // PRINT_CHAT + WRITE_STRING( UTIL_VarArgs( "%s^7 trying activate changelevel too soon\n", ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected")); + MESSAGE_END(); + UTIL_CleanSpawnPoint( pPlayer->pev->origin, 50 ); + m_flRepeatTimer = gpGlobals->time; + pPlayer->m_iLocalConfirm = -2; + } - if( count1 > 1 && count1 < count2 / 3 ) - i = count1 - count1 < count2 / 3; - if( count1 > 1 && count1 < count2 / 3 ) - i = 1; + UTIL_HudMessageAll( params, "Cannot change level: Not enough players!\nWait 30 sec before you may changelevel!" ); + return; + } - if( i ) - UTIL_HudMessageAll( params, UTIL_VarArgs( "%s touched end of map, next is %s %s, %d to go", - ( pActivator->pev->netname && STRING( pActivator->pev->netname )[0] != 0 ) ? STRING( pActivator->pev->netname ) : "unconnected", - st_szNextMap, st_szNextSpot, i ) ); - if( count2 ) - { - pev->rendercolor.x = count1 * 255 / count2; - if( m_fIsBack ) - pev->rendercolor.z = 255 - pev->rendercolor.x; - else - pev->rendercolor.y = 255 - pev->rendercolor.x; - } + if( count1 > 1 && count1 < count2 / 3 ) + i = count1 - count1 < count2 / 3; + if( count1 > 1 && count1 < count2 / 3 ) + i = 1; - ALERT( at_console, "^3CHANGELEVEL:^7 %d %d\n", count2, count1 ); + if( i ) + UTIL_HudMessageAll( params, UTIL_VarArgs( "%s touched end of map\nnext is %s %s, %d to go\n", + ( pActivator->pev->netname && STRING( pActivator->pev->netname )[0] != 0 ) ? STRING( pActivator->pev->netname ) : "unconnected", + st_szNextMap, st_szNextSpot, i ) ); + if( count2 ) + { + pev->rendercolor.x = count1 * 255 / count2; + if( m_fIsBack ) + pev->rendercolor.z = 255 - pev->rendercolor.x; + else + pev->rendercolor.y = 255 - pev->rendercolor.x; + } - if( count1 > 1 && count1 < count2 / 3 ) - return; + ALERT( at_console, "^3CHANGELEVEL:^7 %d %d\n", count2, count1 ); - //if( count1 <= 1 && count2 == 2 ) - // return; + if( count1 > 1 && count1 < count2 / 3 ) + return; - if( m_fIsBack ) - { - if( gpGlobals->time - g_GlobalMenu.m_flTime > 30 ) - { - g_iMenu = 0; - g_GlobalMenu.m_iConfirm = 0; - } - if( g_iMenu != 1 ) + //if( count1 <= 1 && count2 == 2 ) + // return; + + if( m_fIsBack ) { - g_GlobalMenu.ConfirmMenu( (CBasePlayer*)pActivator, this, m_szMapName ); - return; + if( gpGlobals->time - g_GlobalMenu.m_flTime > 30 ) + { + g_iMenu = 0; + g_GlobalMenu.m_iConfirm = 0; + } + if( g_iMenu != 1 ) + { + if( !UTIL_CoopIsBadPlayer( pActivator ) ) + g_GlobalMenu.ConfirmMenu( (CBasePlayer*)pActivator, this, m_szMapName ); + return; + } + if( g_GlobalMenu.m_iConfirm < count2 ) + return; + //if( mp_coop_strongpolicy.value ) + /*{ + // do not allow go back if there are checkpoints, but not near changelevel + if( g_checkpoints[0].time && (g_checkpoints[0].origin - VecBModelOrigin(pev)).Length() > 150 ) + return; + if( count2 < 2 ) + return; + }*/ } - if( g_GlobalMenu.m_iConfirm < count2 ) - return; - } } if( m_fSpawnSaved ) @@ -2119,7 +1767,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) } } - CoopSaveTrain( pActivator, &l_SavedCoords ); + UTIL_CoopSaveTrain( pActivator, &l_SavedCoords ); s_SavedCoords = l_SavedCoords; @@ -2145,18 +1793,18 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) { int count = 0; for( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *plr = UTIL_PlayerByIndex( i ); + { + CBaseEntity *plr = UTIL_PlayerByIndex( i ); - if( plr && plr->IsPlayer() && ( !FindTriggerTransition( m_szLandmarkName ) || (gpGlobals->time -((CBasePlayer*)plr)->m_flSpawnTime ) > 30 ) || m_fSkipSpawnCheck ) - { - if( InTransitionVolume( plr, m_szLandmarkName )) - { - count++; - } + if( plr && plr->IsPlayer() && ( !FindTriggerTransition( m_szLandmarkName ) || (gpGlobals->time -((CBasePlayer*)plr)->m_flSpawnTime ) > 30 || m_fSkipSpawnCheck ) ) + { + if( InTransitionVolume( plr, m_szLandmarkName )) + { + count++; + } - } } + } if( !count ) { ALERT( at_console, "There are no players in transition volume %s, aborting\n", m_szLandmarkName ); @@ -2170,19 +1818,11 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) ALERT( at_console, "Player isn't in the transition volume %s, aborting\n", m_szLandmarkName ); return; } - //else -/* if !pPlayer - { - ALERT( at_console, ", aborting\n" ); - return; - - }*/ - - // shedule remove ke^w on first info_player_start - /*edict_t *playerstart = FIND_ENTITY_BY_CLASSNAME( NULL, "info_player_start" ); - if( !FNullEnt(playerstart) ) - playerstart->v.flags |= FL_KILLME;*/ + MESSAGE_BEGIN( MSG_ALL, 8, NULL ); // svc_print + WRITE_BYTE( 3 ); // PRINT_CHAT + WRITE_STRING( UTIL_VarArgs( "%s^7 activated changelevel\n", ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected")); + MESSAGE_END(); // This object will get removed in the call to CHANGE_LEVEL, copy the params into "safe" memory strcpy( st_szNextMap, m_szMapName ); @@ -2226,33 +1866,27 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) // loop through all clients, reset state if( mp_coop_changelevel.value ) { - for( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *plr = (CBasePlayer*)UTIL_PlayerByIndex( i ); - - // reset all players state - if( plr ) + for( int i = 1; i <= gpGlobals->maxClients; i++ ) { - plr->m_state = STATE_UNINITIALIZED; - plr->RemoveAllItems( TRUE ); - BecomeSpectator( plr ); - //plr->SetThink( &CBasePlayer::Spawn ); - //plr->pev->nextthink = gpGlobals->time + 1; - // HACK: force perform reconnection - if( mp_coop_reconnect_hack.value ) - CLIENT_COMMAND( plr->edict(), "reconnect\n" ); - - //CLIENT_COMMAND( plr->edict(), "alias cmd \"reconnect;unalias cmd\"\n" ); - //MESSAGE_BEGIN( MSG_ONE, 2, NULL, plr->pev ); // svc_disconnect after stufftext - //MESSAGE_END(); - //SERVER_COMMAND( UTIL_VarArgs( "kick %d\n", i-1 ) ); - //SERVER_EXECUTE(); + CBasePlayer *plr = (CBasePlayer*)UTIL_PlayerByIndex( i ); + + // reset all players state to make it spawn again after restart + if( plr ) + { + plr->m_state = STATE_UNINITIALIZED; + plr->RemoveAllItems( TRUE ); + UTIL_BecomeSpectator( plr ); + // HACK: force perform reconnection + if( mp_coop_reconnect_hack.value ) + CLIENT_COMMAND( plr->edict(), "reconnect\n" ); + } } - } - g_fPause = true; + g_fPause = true; } s_SavedCoords.fUsed = m_bUsed; s_SavedCoords.valid = valid; + + // wait 5 frames to make sure all players are in reconnected state if( mp_coop_reconnect_hack.value ) SERVER_COMMAND( UTIL_VarArgs( "wait;wait;wait;wait;wait;changelevel %s %s\n", st_szNextMap, st_szNextSpot ) ); else diff --git a/dlls/util.cpp b/dlls/util.cpp index 48d39d8e..cf73bc49 100644 --- a/dlls/util.cpp +++ b/dlls/util.cpp @@ -1578,21 +1578,6 @@ void UTIL_StripToken( const char *pKey, char *pDest ) pDest[i] = 0; } -void UTIL_CleanSpawnPoint( Vector origin, float dist ) -{ - CBaseEntity *ent = NULL; - while( ( ent = UTIL_FindEntityInSphere( ent, origin, dist ) ) != NULL ) - { - if( ent->IsPlayer() ) - { - TraceResult tr; - UTIL_TraceHull( ent->pev->origin + Vector( 0, 0, 36), ent->pev->origin + Vector( RANDOM_FLOAT( -150, 150 ), RANDOM_FLOAT( -150, 150 ), 0 ), dont_ignore_monsters, human_hull, ent->edict(), &tr); - //UTIL_TraceModel( ent->pev->origin + Vector( 0, 0, 36), ent->pev->origin + Vector( RANDOM_FLOAT( -150, 150 ), RANDOM_FLOAT( -150, 150 ), 0 ), 0, ent->edict(), &tr); - if( !tr.fAllSolid ) - UTIL_SetOrigin(ent->pev, tr.vecEndPos); - } - } -} // -------------------------------------------------------------- // diff --git a/dlls/util.h b/dlls/util.h index adbd45fd..8b4ecf8b 100644 --- a/dlls/util.h +++ b/dlls/util.h @@ -568,4 +568,3 @@ int UTIL_SharedRandomLong( unsigned int seed, int low, int high ); float UTIL_SharedRandomFloat( unsigned int seed, float low, float high ); float UTIL_WeaponTimeBase( void ); -void UTIL_CleanSpawnPoint( Vector origin, float radius ); diff --git a/dlls/weapons.cpp b/dlls/weapons.cpp index 91428812..519dc974 100644 --- a/dlls/weapons.cpp +++ b/dlls/weapons.cpp @@ -394,7 +394,7 @@ void W_Precache( void ) TYPEDESCRIPTION CBasePlayerItem::m_SaveData[] = { DEFINE_FIELD( CBasePlayerItem, m_pPlayer, FIELD_CLASSPTR ), - DEFINE_FIELD( CBasePlayerItem, m_pNext, FIELD_CLASSPTR ), + DEFINE_FIELD( CBasePlayerItem, m_pNext, FIELD_EHANDLE ), //DEFINE_FIELD( CBasePlayerItem, m_fKnown, FIELD_INTEGER ),Reset to zero on load DEFINE_FIELD( CBasePlayerItem, m_iId, FIELD_INTEGER ), // DEFINE_FIELD( CBasePlayerItem, m_iIdPrimary, FIELD_INTEGER ), @@ -1244,7 +1244,7 @@ void CBasePlayerAmmo::DefaultTouch( CBaseEntity *pOther ) //========================================================= int CBasePlayerWeapon::ExtractAmmo( CBasePlayerWeapon *pWeapon ) { - int iReturn; + int iReturn = 0; if( pszAmmo1() != NULL ) { @@ -1304,7 +1304,7 @@ TYPEDESCRIPTION CWeaponBox::m_SaveData[] = { DEFINE_ARRAY( CWeaponBox, m_rgAmmo, FIELD_INTEGER, MAX_AMMO_SLOTS ), DEFINE_ARRAY( CWeaponBox, m_rgiszAmmo, FIELD_STRING, MAX_AMMO_SLOTS ), - DEFINE_ARRAY( CWeaponBox, m_rgpPlayerItems, FIELD_CLASSPTR, MAX_ITEM_TYPES ), + DEFINE_ARRAY( CWeaponBox, m_rgpPlayerItems, FIELD_EHANDLE, MAX_ITEM_TYPES ), DEFINE_FIELD( CWeaponBox, m_cAmmoTypes, FIELD_INTEGER ), }; diff --git a/dlls/weapons.h b/dlls/weapons.h index a7dd8b30..c5ad4ba3 100644 --- a/dlls/weapons.h +++ b/dlls/weapons.h @@ -217,6 +217,9 @@ typedef struct int iId; } AmmoInfo; +#include "whandle.h" + + // Items that the player has in their inventory that they can use class CBasePlayerItem : public CBaseAnimating { @@ -265,7 +268,7 @@ public: static AmmoInfo AmmoInfoArray[ MAX_AMMO_SLOTS ]; CBasePlayer *m_pPlayer; - CBasePlayerItem *m_pNext; + EHBasePlayerItem m_pNext; int m_iId; // WEAPON_??? virtual int iItemSlot( void ) { return 0; } // return 0 to MAX_ITEMS_SLOTS, used in hud @@ -456,7 +459,7 @@ public: BOOL PackWeapon( CBasePlayerItem *pWeapon ); BOOL PackAmmo( int iszName, int iCount ); - CBasePlayerItem *m_rgpPlayerItems[MAX_ITEM_TYPES];// one slot for each + EHBasePlayerItem m_rgpPlayerItems[MAX_ITEM_TYPES];// one slot for each int m_rgiszAmmo[MAX_AMMO_SLOTS];// ammo names int m_rgAmmo[MAX_AMMO_SLOTS];// ammo quantities diff --git a/dlls/whandle.h b/dlls/whandle.h new file mode 100644 index 00000000..179297df --- /dev/null +++ b/dlls/whandle.h @@ -0,0 +1,46 @@ +#ifndef WHANDLE_H +#define WHANDLE_H + + + +class CBasePlayerItem; + +class EHBasePlayerItem : public EHANDLE +{ +public: + operator CBasePlayerItem *() + { + return (CBasePlayerItem *)GET_PRIVATE( Get() ); + } + CBasePlayerItem *operator ->() + { + return (CBasePlayerItem *)GET_PRIVATE( Get() ); + } + template + operator T() + { + return (T)GET_PRIVATE( Get() ); + } + template + T *operator = ( T *pEntity ) + { + edict_t *e = NULL; + if( pEntity ) + e = pEntity->edict(); + return (T*)CBaseEntity::Instance( Set ( e ) ); + } + + // handle = NULL correctly + int operator = ( int null1 ) + { + //assert( !null1 ); + Set(0); + return 0; + } + + bool operator !=(EHBasePlayerItem &other) + { + return Get() != other.Get(); + } +}; +#endif \ No newline at end of file diff --git a/dlls/world.cpp b/dlls/world.cpp index 089db6b5..e8222b55 100644 --- a/dlls/world.cpp +++ b/dlls/world.cpp @@ -230,6 +230,9 @@ void CopyToBodyQue( entvars_t *pev ) if( pev->effects & EF_NODRAW ) return; + if( !g_pBodyQueueHead ) + InitBodyQue(); + entvars_t *pevHead = VARS( g_pBodyQueueHead ); pevHead->angles = pev->angles; diff --git a/pm_shared/pm_shared.c b/pm_shared/pm_shared.c index 8f1dd354..462b3add 100644 --- a/pm_shared/pm_shared.c +++ b/pm_shared/pm_shared.c @@ -33,8 +33,8 @@ #ifdef CLIENT_DLL // Spectator Mode int iJumpSpectator; - float vJumpOrigin[3]; - float vJumpAngles[3]; +extern float vJumpOrigin[3]; +extern float vJumpAngles[3]; #endif static int pm_shared_initialized = 0; @@ -122,6 +122,14 @@ static char grgchTextureType[CTEXTURESMAX]; int g_onladder = 0; +#ifdef CLIENT_DLL +#define materials_path "sound/materials.txt" +#else +#include "cvardef.h" +extern cvar_t materials_txt; +#define materials_path materials_txt.string +#endif + void PM_SwapTextures( int i, int j ) { char chTemp; @@ -173,8 +181,8 @@ void PM_InitTextureTypes() gcTextures = 0; - fileSize = pmove->COM_FileSize( "sound/materials.txt" ); - pMemFile = pmove->COM_LoadFile( "sound/materials.txt", 5, NULL ); + fileSize = pmove->COM_FileSize( materials_path ); + pMemFile = pmove->COM_LoadFile( materials_path, 5, NULL ); if( !pMemFile ) return;