Advanced coop spawnpoint generation

This commit is contained in:
mittorn 2016-09-29 22:23:37 +07:00
parent 0b22605eb4
commit dd54375dd6
5 changed files with 145 additions and 6 deletions

View File

@ -670,13 +670,25 @@ void PlayerPostThink( edict_t *pEntity )
pPlayer->PostThink( );
}
void CoopClearData( void );
void CoopClearWeaponList( void );
void ParmsNewLevel( void )
{
// retrieve the pointer to the save data
SAVERESTOREDATA *pSaveData = (SAVERESTOREDATA *)gpGlobals->pSaveData;
if ( pSaveData )
pSaveData->connectionCount = BuildChangeList( pSaveData->levelList, MAX_LEVEL_CONNECTIONS );
else
if( mp_coop_changelevel.value )
{
CoopClearData();
CoopClearWeaponList();
}
}
void ParmsChangeLevel( void )
{
// retrieve the pointer to the save data
@ -684,6 +696,13 @@ void ParmsChangeLevel( void )
if ( pSaveData )
pSaveData->connectionCount = BuildChangeList( pSaveData->levelList, MAX_LEVEL_CONNECTIONS );
else
if( mp_coop_changelevel.value )
{
CoopClearData();
CoopClearWeaponList();
}
}

View File

@ -57,6 +57,9 @@ 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 );
//=========================================================
//=========================================================
@ -72,6 +75,8 @@ edict_t *CGameRules::GetPlayerSpawnSpot( CBasePlayer *pPlayer )
pPlayer->pev->velocity = g_vecZero;
pPlayer->pev->angles = VARS( pentSpawnSpot )->angles;
pPlayer->pev->punchangle = g_vecZero;
if( mp_coop_changelevel.value && !CoopRestorePlayerCoords( pPlayer, &pPlayer->pev->origin, &pPlayer->pev->angles ))
CoopGetSpawnPoint( &pPlayer->pev->origin, &pPlayer->pev->angles );
pPlayer->pev->fixangle = TRUE;
return pentSpawnSpot;

View File

@ -84,8 +84,17 @@ public:
for(int i = 0; i < m_iWeapons;i++)
player->GiveNamedItem(weapons[i]);
}
void Clear()
{
m_iWeapons = 0;
}
} g_WeaponList;
void CoopClearWeaponList( void )
{
g_WeaponList.Clear();
}
//*********************************************************
// Rules for the half-life multiplayer game.
//*********************************************************

View File

@ -1445,6 +1445,92 @@ void CChangeLevel::UseChangeLevel( CBaseEntity *pActivator, CBaseEntity *pCaller
ChangeLevelNow( pActivator );
}
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;
} g_SavedCoords;
void CoopClearData( void )
{
// nullify
SavedCoords l_SavedCoords = {};
g_SavedCoords = l_SavedCoords;
}
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.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(!strcmp(ip, g_SavedCoords.ip[i]))
{
TraceResult tr;
Vector point = g_SavedCoords.origin[i] + g_SavedCoords.offset;
UTIL_TraceHull( point, point, missile, human_hull, NULL, &tr );
g_SavedCoords.ip[i][0] = 0;
if( tr.fStartSolid )
return false;
*origin = point;
*angles = g_SavedCoords.angles[i];
return true;
}
}
return false;
}
bool CoopGetSpawnPoint( Vector *point, Vector *angles)
{
if(!g_SavedCoords.valid)
return false;
validateoffset();
*point = g_SavedCoords.triggerorigin + g_SavedCoords.offset;
*angles = g_SavedCoords.triggerangles;
if( !g_SavedCoords.validspawnpoint )
{
TraceResult tr;
Vector angle;
UTIL_MakeVectorsPrivate( *angles, (float*)&angle, NULL, NULL );
UTIL_TraceHull( *point, *point + angle * 100, missile, human_hull, NULL, &tr );
if( !tr.fStartSolid )
{
g_SavedCoords.triggerorigin = tr.vecEndPos;
g_SavedCoords.validspawnpoint = true;
}
else
g_SavedCoords.valid = false;
}
return true;
}
void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
{
edict_t *pentLandmark;
@ -1454,9 +1540,11 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
if(mp_coop_changelevel.value)
{
SavedCoords l_SavedCoords = {};
// if not activated by touch, do not count players
if( !m_bUsed )
{
m_uTouchCount |= ENTINDEX( pActivator->edict() );
unsigned int count1 = m_uTouchCount;
unsigned int count2 = 0;
@ -1475,6 +1563,17 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
if( plr )
{
count2++;
char *ip = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( plr->edict() ), "ip" );
// player touched trigger, save it's coordinates
if( m_uTouchCount & (i - 1) )
{
strcpy(l_SavedCoords.ip[l_SavedCoords.iCount], ip );
l_SavedCoords.origin[l_SavedCoords.iCount] = plr->pev->origin;
l_SavedCoords.angles[l_SavedCoords.iCount] = plr->pev->angles;
l_SavedCoords.iCount++;
}
}
}
@ -1495,7 +1594,13 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
if( count1 == 1 && count2 == 2 )
return;
g_SavedCoords.triggerangles = pActivator->pev->angles;
g_SavedCoords.triggerorigin = pActivator->pev->origin;
g_SavedCoords.valid = true;
}
g_SavedCoords = l_SavedCoords;
}
// Don't work in deathmatch
else if( g_pGameRules->IsDeathmatch() )
@ -1544,7 +1649,8 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
if( !FNullEnt( pentLandmark ) )
{
strcpy( st_szNextSpot, m_szLandmarkName );
gpGlobals->vecLandmarkOffset = VARS( pentLandmark )->origin;
strcpy( g_SavedCoords.landmark, m_szLandmarkName );
g_SavedCoords.offset = gpGlobals->vecLandmarkOffset = VARS( pentLandmark )->origin;
}
//ALERT( at_console, "Level touches %d levels\n", ChangeList( levels, 16 ) );
ALERT( at_console, "CHANGE LEVEL: %s %s\n", st_szNextMap, st_szNextSpot );

View File

@ -1585,11 +1585,11 @@ void UTIL_CleanSpawnPoint( Vector origin, float dist )
{
if( ent->IsPlayer() )
{
TraceResult tr = {0};
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);
UTIL_SetOrigin(ent->pev, tr.vecEndPos);
if( !tr.fAllSolid )
UTIL_SetOrigin(ent->pev, tr.vecEndPos);
}
}
}