Get rid of old SavedCoords struct, rewrite transition code to new system

This commit is contained in:
mittorn 2018-10-25 04:51:23 +07:00
parent ecb31d4533
commit b55f4aeeb0
8 changed files with 212 additions and 351 deletions

View File

@ -5,9 +5,6 @@
#include "coop_util.h"
#include "gravgunmod.h"
struct SavedCoords g_SavedCoords, s_SavedCoords;
static float msglimittime1, msglimittime2;
cvar_t mp_coop = { "mp_coop", "0", FCVAR_SERVER };
@ -42,21 +39,6 @@ edict_t *COOP_FindLandmark( const char *pLandmarkName )
return NULL;
}
void COOP_ValidateOffset( void )
{
if( !g_SavedCoords.validoffset )
{
edict_t *landmark = COOP_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;
}
}
void UTIL_CoopPlayerMessage( CBaseEntity *pPlayer, int channel, float time, unsigned int color1, unsigned int color2, float x, float y, const char *format, ... )
{
if( !pPlayer )
@ -158,57 +140,22 @@ void UTIL_CleanSpawnPoint( Vector origin, float dist )
}
Vector COOP_FixupSpawnPoint(Vector spawn)
Vector COOP_FixupSpawnPoint( Vector vecOrigin, bool fDuck )
{
int i = 0;
// predict that spawn point is almost correct
while( i < 2 ) // 2 player heights
{
Vector point = spawn + Vector( 0, 0, 36 * i );
Vector point = vecOrigin + Vector( 0, 0, 36 * i );
TraceResult tr;
UTIL_TraceHull( point, point, ignore_monsters, (mp_unduck.value&&g_fSavedDuck)?head_hull:human_hull, NULL, &tr );
UTIL_TraceHull( point, point, ignore_monsters, (mp_unduck.value&&fDuck)?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;
return vecOrigin;
}
void UTIL_BecomeSpectator( CBasePlayer *pPlayer )
@ -247,14 +194,13 @@ void UTIL_SpawnPlayer( CBasePlayer *pPlayer )
}
char * UTIL_CoopPlayerName( CBaseEntity *pPlayer )
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
@ -319,29 +265,19 @@ bool UTIL_CoopIsBadPlayer( CBaseEntity *plr )
return false;
}
bool g_fPause;
void COOP_ClearData( void )
{
// nullify
SavedCoords l_SavedCoords = {0};
g_SavedCoords = l_SavedCoords;
g_fPause = false;
msglimittime1 = msglimittime2 = 0;
}
bool g_fPause;
void COOP_ApplyData( 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" );
msglimittime1 = msglimittime2 = 0;
g_fPause = false;
}
// use this to translate GGMMapOffset during changelevel
@ -351,6 +287,9 @@ struct GGMLandmarkTransition
char targetMap[32];
char landmarkName[32];
Vector vecLandmark;
bool fTriggerUsed;
bool fSavedPos;
GGMPosition pos;
};
@ -373,12 +312,43 @@ struct GGMMapState
GGMMapState *g_pMapStates;
GGMMapState *g_pCurrentMap;
GGMLandmarkTransition g_landmarkTransition;
struct GGMCoopState
{
struct GGMPosition savedPos;
bool fSaved;
} g_CoopState;
edict_t *COOP_FindLandmark( const char *pLandmarkName );
void COOP_MarkTriggers( void )
{
CBaseEntity *pTrigger = NULL;
while( pTrigger = UTIL_FindEntityByClassname( pTrigger, "trigger_changelevel" ) )
{
struct COOPChangelevelData *pData = COOP_GetTriggerData( pTrigger );
pData->fIsBack = !strcmp( pData->pszMapName, g_landmarkTransition.sourceMap );
// if( gpGlobals->startspot && STRING(gpGlobals->startspot) && !strcmp(STRING(gpGlobals->startspot), m_szLandmarkName) )
// m_coopData.fIsBack = true;
pTrigger->pev->renderamt = 127;
pTrigger->pev->effects &= ~EF_NODRAW;
pTrigger->pev->rendermode = kRenderTransColor;
pTrigger->pev->rendercolor = g_vecZero;
if( pData->fIsBack )
pTrigger->pev->rendercolor.z = 255;
else
pTrigger->pev->rendercolor.y = 255;
}
}
bool COOP_ProcessTransition( void )
{
bool fAddCurrent = true;
edict_t *landmark;
g_CoopState.savedPos = g_landmarkTransition.pos;
g_CoopState.fSaved = g_landmarkTransition.fSavedPos;
if( !mp_coop.value )
return false;
@ -416,16 +386,22 @@ bool COOP_ProcessTransition( void )
return true;
}
void COOP_SetupLandmarkTransition( const char *szNextMap, const char *szNextSpot, Vector vecLandmarkOffset )
void COOP_SetupLandmarkTransition( const char *szNextMap, const char *szNextSpot, Vector vecLandmarkOffset, struct GGMPosition *pPos )
{
strncpy(g_landmarkTransition.sourceMap, STRING(gpGlobals->mapname), 31 );
strncpy(g_landmarkTransition.targetMap, szNextMap, 31 );
strncpy(g_landmarkTransition.landmarkName, szNextSpot, 31 );
g_landmarkTransition.vecLandmark = vecLandmarkOffset;
if( pPos )
{
g_landmarkTransition.pos = *pPos;
g_landmarkTransition.fSavedPos = true;
}
}
void COOP_ServerActivate( void )
{
COOP_MarkTriggers();
if( !COOP_ProcessTransition() )
{
ALERT( at_console, "Transition failed, new game started\n");
@ -463,7 +439,7 @@ void COOP_ServerActivate( void )
}
}
}
g_landmarkTransition.landmarkName[0] = false;
memset( &g_landmarkTransition, 0, sizeof( GGMLandmarkTransition ) );
}
bool COOP_GetOrigin( Vector *pvecNewOrigin, const Vector &vecOrigin, const char *pszMapName )
@ -624,63 +600,13 @@ bool COOP_PlayerDeath( CBasePlayer *pPlayer )
return false;
}
bool UTIL_CoopGetSpawnPoint( Vector *origin, Vector *angles)
bool COOP_SetDefaultSpawnPosition( CBasePlayer *pPlayer )
{
if(!g_SavedCoords.valid)
if( !g_CoopState.fSaved )
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 );
COOP_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;
return GGM_RestorePosition( pPlayer, &g_CoopState.savedPos );
}
CBaseEntity *UTIL_CoopGetPlayerTrain( CBaseEntity *pPlayer)
{
CBaseEntity *train = NULL;

View File

@ -1,5 +1,6 @@
#ifndef COOP_UTIL_H
#define COOP_UTIL_H
#include "gravgunmod.h"
extern cvar_t mp_gravgun_players;
extern cvar_t mp_coop;
extern cvar_t mp_coop_nofriendlyfire;
@ -20,35 +21,24 @@ extern cvar_t materials_txt;
extern bool g_fSavedDuck;
extern bool g_fPause;
struct SavedCoords
struct COOPChangelevelData
{
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 fIsBack;
bool fSkipSpawnCheck;
struct GGMPosition savedPosition;
bool fSpawnSaved;
bool fUsed;
bool fDuck;
unsigned int bitsTouchCount;
float flRepeatTimer;
const char *pszMapName;
bool fValid;
};
void COOP_ValidateOffset( void );
void UTIL_CleanSpawnPoint( Vector origin, float radius );
char *UTIL_CoopPlayerName( CBaseEntity *pPlayer );
bool UTIL_CoopGetSpawnPoint( Vector *point, Vector *angles);
void UTIL_CoopSaveTrain( CBaseEntity *pPlayer, SavedCoords *coords);
Vector COOP_FixupSpawnPoint(Vector spawn);
bool COOP_SetDefaultSpawnPosition( CBasePlayer *pPlayer );
Vector COOP_FixupSpawnPoint( Vector vecOrigin, bool fDuck );
void COOP_ClearData( void );
void COOP_ApplyData( void );
void UTIL_CoopPrintMessage( const char *format, ... );
@ -83,7 +73,6 @@ public:
extern CWeaponList g_WeaponList;
extern struct SavedCoords g_SavedCoords, s_SavedCoords;
struct COOPChangelevelData *COOP_GetTriggerData( CBaseEntity *pTrigger );
#endif // COOP_UTIL_H

View File

@ -65,58 +65,13 @@ extern EHANDLE g_pLastSpawn;
edict_t *CGameRules::GetPlayerSpawnSpot( CBasePlayer *pPlayer )
{
edict_t *pentSpawnSpot = EntSelectSpawnPoint( pPlayer );
if( pPlayer->gravgunmod_data.m_state == STATE_POINT_SELECT )
{
pPlayer->gravgunmod_data.m_state = STATE_SPAWNED;
pPlayer->pev->effects &= ~EF_NODRAW;
pPlayer->pev->takedamage = DAMAGE_YES;
pPlayer->pev->flags &= ~FL_SPECTATOR;
pPlayer->pev->movetype = MOVETYPE_WALK;
CLIENT_COMMAND( pPlayer->edict(), "touch_show _coopm*\n" );
return NULL;
}
if( mp_coop.value )
UTIL_CleanSpawnPoint( pentSpawnSpot->v.origin, 100 );
if( g_pLastSpawn )
pPlayer->pev->origin = VARS( pentSpawnSpot )->origin + Vector( 0, 0, 1 );
pPlayer->pev->v_angle = g_vecZero;
pPlayer->pev->velocity = g_vecZero;
pPlayer->pev->angles = VARS( pentSpawnSpot )->angles;
pPlayer->pev->punchangle = g_vecZero;
if( !(pPlayer->pev->flags & FL_SPECTATOR ) )
if( mp_coop.value )
if( !UTIL_CoopGetSpawnPoint( &pPlayer->pev->origin, &pPlayer->pev->angles ) )
{
if( !g_pLastSpawn )
{
hudtextparms_t params = {};
params.fadeinTime = 0.5;
params.fadeoutTime = .5;
params.holdTime = 10;
params.channel = 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\nplease fly to it manually\nand press attack button" );
// select spawn point
pPlayer->gravgunmod_data.m_state = STATE_POINT_SELECT;
pPlayer->m_afButtonPressed = 0;
if(pPlayer->pev->origin.Length() > 8192)
pPlayer->pev->origin = g_vecZero;
}
}
pPlayer->pev->fixangle = TRUE;
pPlayer->pev->origin = COOP_FixupSpawnPoint( pPlayer->pev->origin );
if( g_fSavedDuck )
pPlayer->pev->flags |= FL_DUCKING;
return pentSpawnSpot;
}

View File

@ -961,8 +961,9 @@ bool GGM_RestorePosition( CBasePlayer *pPlayer, struct GGMPosition *pos )
}
if( mp_coop.value && !fOriginSet )
{
g_pGameRules->GetPlayerSpawnSpot( pPlayer );
if( pPlayer->gravgunmod_data.m_state = STATE_POINT_SELECT )
if( !COOP_SetDefaultSpawnPosition( pPlayer ) )
g_pGameRules->GetPlayerSpawnSpot( pPlayer );
if( pPlayer->gravgunmod_data.m_state == STATE_POINT_SELECT )
return false;
}
@ -973,6 +974,7 @@ bool GGM_RestorePosition( CBasePlayer *pPlayer, struct GGMPosition *pos )
UTIL_SetSize( pPlayer->pev, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX );
}
pPlayer->pev->angles = pos->vecAngles;
pPlayer->pev->fixangle = TRUE;
return true;
}
@ -1033,7 +1035,7 @@ bool GGM_PlayerSpawn( CBasePlayer *pPlayer )
return true;
}
if( mp_spectator.value && pPlayer->gravgunmod_data.m_state == STATE_CONNECTED || !pPlayer->gravgunmod_data.pState )
if( ( mp_coop.value || mp_spectator.value ) && pPlayer->gravgunmod_data.m_state == STATE_CONNECTED || !pPlayer->gravgunmod_data.pState )
{
if( !pPlayer->gravgunmod_data.pState )
GGM_ChatPrintf( pPlayer, "This nickname busy! Please login or change nickname\n" );
@ -1041,6 +1043,8 @@ bool GGM_PlayerSpawn( CBasePlayer *pPlayer )
pPlayer->gravgunmod_data.m_state = STATE_SPECTATOR_BEGIN;
pPlayer->RemoveAllItems( TRUE );
UTIL_BecomeSpectator( pPlayer );
if( !COOP_SetDefaultSpawnPosition( pPlayer ) )
g_pGameRules->GetPlayerSpawnSpot( pPlayer );
return true;
}
@ -1090,7 +1094,8 @@ bool GGM_PlayerSpawn( CBasePlayer *pPlayer )
{
}
g_pGameRules->GetPlayerSpawnSpot( pPlayer );
if( !COOP_SetDefaultSpawnPosition( pPlayer ) )
g_pGameRules->GetPlayerSpawnSpot( pPlayer );
}
else
{

View File

@ -185,6 +185,6 @@ void GGM_SaveState( CBasePlayer *pPlayer );
bool GGM_PlayerSpawn( CBasePlayer *pPlayer );
const char *GGM_GetAuthID( CBasePlayer *pPlayer );
void GGM_ServerActivate( void );
void COOP_SetupLandmarkTransition( const char *szNextMap, const char *szNextSpot, Vector vecLandmarkOffset );
void COOP_SetupLandmarkTransition( const char *szNextMap, const char *szNextSpot, Vector vecLandmarkOffset, struct GGMPosition *pPos );
#endif // GRAVGUNMOD_H

View File

@ -613,30 +613,31 @@ void CHalfLifeMultiplay::PlayerSpawn( CBasePlayer *pPlayer )
addDefault = FALSE;
}
if( addDefault )
if( !mp_coop.value )
{
pPlayer->GiveNamedItem( "weapon_crowbar" );
pPlayer->GiveNamedItem( "weapon_9mmhandgun" );
pPlayer->GiveAmmo( 68, "9mm", _9MM_MAX_CARRY );// 4 full reloads
}
if( addDefault )
{
pPlayer->GiveNamedItem( "weapon_crowbar" );
pPlayer->GiveNamedItem( "weapon_9mmhandgun" );
pPlayer->GiveAmmo( 68, "9mm", _9MM_MAX_CARRY );// 4 full reloads
}
if( (int)cvar_allow_gravgun.value == 2 )
pPlayer->GiveNamedItem( "weapon_gravgun" );
if( (int)cvar_allow_ar2.value == 2 )
pPlayer->GiveNamedItem( "weapon_ar2" );
if( !cvar_ar2_mp5.value )
{
pPlayer->GiveAmmo( cvar_ar2_bullets.value, "AR2", 120 );
pPlayer->GiveAmmo( cvar_ar2_balls.value, "AR2grenades", 3 );
if( (int)cvar_allow_gravgun.value == 2 )
pPlayer->GiveNamedItem( "weapon_gravgun" );
if( (int)cvar_allow_ar2.value == 2 )
pPlayer->GiveNamedItem( "weapon_ar2" );
if( !cvar_ar2_mp5.value )
{
pPlayer->GiveAmmo( cvar_ar2_bullets.value, "AR2", 120 );
pPlayer->GiveAmmo( cvar_ar2_balls.value, "AR2grenades", 3 );
}
if( (int)cvar_allow_bigcock.value == 2 )
pPlayer->GiveNamedItem( "weapon_big_cock" );
if( (int)cvar_allow_gateofbabylon.value == 2 )
pPlayer->GiveNamedItem( "weapon_gateofbabylon" );
}
if( (int)cvar_allow_bigcock.value == 2 )
pPlayer->GiveNamedItem( "weapon_big_cock" );
if( (int)cvar_allow_gateofbabylon.value == 2 )
pPlayer->GiveNamedItem( "weapon_gateofbabylon" );
if( mp_coop.value )
else
{
// pPlayer->GiveNamedItem( "item_suit" );
g_WeaponList.GiveToPlayer(pPlayer);
}
}

View File

@ -2858,7 +2858,7 @@ edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer )
if( !FStrEq( STRING( pSpot->pev->netname ), STRING( gpGlobals->mapname ) ) )
continue;
// check if it is placed in wall
UTIL_TraceHull( pSpot->pev->origin, pSpot->pev->origin , missile, (mp_unduck.value&&g_fSavedDuck)?head_hull:human_hull, NULL, &tr );
UTIL_TraceHull( pSpot->pev->origin, pSpot->pev->origin , missile, human_hull, NULL, &tr );
if( tr.fStartSolid || tr.fAllSolid )
continue;
// trace down to find if there is no floor
@ -3116,13 +3116,6 @@ int CBasePlayer::Restore( CRestore &restore )
m_flNextAttack = UTIL_WeaponTimeBase();
#endif
// restored player has some bugs untill respawned
if( mp_coop.value )
{
gravgunmod_data.m_state = STATE_CONNECTED;
SetThink( &CBasePlayer::Spawn );
pev->nextthink = gpGlobals->time + 0.5;
}
return status;
}

View File

@ -1326,7 +1326,6 @@ public:
void EXPORT TriggerChangeLevel( void );
void EXPORT ExecuteChangeLevel( void );
void EXPORT TouchChangeLevel( CBaseEntity *pOther );
void EXPORT UpdateColor();
void ChangeLevelNow( CBaseEntity *pActivator );
static edict_t *FindLandmark( const char *pLandmarkName );
@ -1343,14 +1342,7 @@ public:
char m_szLandmarkName[cchMapNameMost]; // trigger_changelevel only: landmark on next map
string_t m_changeTarget;
float m_changeTargetDelay;
unsigned int m_uTouchCount;
bool m_bUsed;
Vector m_vecSpawnOrigin;
Vector m_vecSpawnAngles;
bool m_fSpawnSaved;
bool m_fIsBack;
bool m_fSkipSpawnCheck; // skip 30 seconds check when called by multimanager or trigger_once
float m_flRepeatTimer;
struct COOPChangelevelData m_coopData;
};
LINK_ENTITY_TO_CLASS( trigger_changelevel, CChangeLevel )
@ -1366,6 +1358,14 @@ TYPEDESCRIPTION CChangeLevel::m_SaveData[] =
IMPLEMENT_SAVERESTORE( CChangeLevel, CBaseTrigger )
struct COOPChangelevelData *COOP_GetTriggerData( CBaseEntity *pTrigger )
{
CChangeLevel *pChangeLevel = (CChangeLevel*)pTrigger;
pChangeLevel->m_coopData.pszMapName = pChangeLevel->m_szMapName;
return &pChangeLevel->m_coopData;
}
//
// Cache user-entity-field values until spawn is called.
//
@ -1404,8 +1404,8 @@ When the player touches this, he gets sent to the map listed in the "map" variab
*/
void CChangeLevel::Spawn( void )
{
m_uTouchCount = 0;
m_bUsed = false;
m_coopData.bitsTouchCount = 0;
m_coopData.fUsed = false;
if( FStrEq( m_szMapName, "" ) )
ALERT( at_console, "a trigger_changelevel doesn't have a map" );
@ -1418,25 +1418,7 @@ void CChangeLevel::Spawn( void )
}
InitTrigger();
if( !( pev->spawnflags & SF_CHANGELEVEL_USEONLY ) )
{
SetTouch( &CChangeLevel::TouchChangeLevel );
if( mp_coop.value )
{
if( gpGlobals->startspot && STRING(gpGlobals->startspot) && !strcmp(STRING(gpGlobals->startspot), m_szLandmarkName) )
m_fIsBack = true;
// set color (got from XDM)
if( m_fIsBack )
pev->rendercolor.z = 255;
else
pev->rendercolor.y = 255;
pev->renderamt = 127;
pev->effects &= ~EF_NODRAW;
pev->rendermode = kRenderTransColor;
SetThink( &CChangeLevel::UpdateColor );
pev->nextthink = gpGlobals->time + 2;
}
}
//ALERT( at_console, "TRANSITION: %s (%s)\n", m_szMapName, m_szLandmarkName );
}
@ -1479,11 +1461,11 @@ edict_t *CChangeLevel::FindLandmark( const char *pLandmarkName )
void CChangeLevel::UseChangeLevel( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
// if not activated by touch, do not count players
m_bUsed = true;
m_coopData.fUsed = true;
if( pCaller && FClassnameIs( pCaller->edict(), "multi_manager" ) || FClassnameIs( pCaller->edict(), "trigger_once" ) )
m_fSkipSpawnCheck = true;
m_coopData.fSkipSpawnCheck = true;
else
m_fSkipSpawnCheck = false;
m_coopData.fSkipSpawnCheck = false;
const char *classname = NULL;
if( pCaller && pCaller->pev->classname )
classname = STRING( pCaller->pev->classname );
@ -1491,27 +1473,6 @@ void CChangeLevel::UseChangeLevel( CBaseEntity *pActivator, CBaseEntity *pCaller
ChangeLevelNow( pActivator );
}
void CChangeLevel::UpdateColor( void )
{
Vector origin = VecBModelOrigin(pev);
Vector point, angles;
CBaseEntity *pPlayer;
pev->nextthink = gpGlobals->time + 30;
/*if( !m_fIsBack && (pPlayer = UTIL_FindEntityByClassname( NULL, "info_player_start" )) )
if( (origin - pPlayer->pev->origin).Length() < 500 )
m_fIsBack = true;*/
if( !m_fIsBack && UTIL_CoopGetSpawnPoint( &point, &angles ) )
if( (origin - point).Length() < 500 )
m_fIsBack = true;
pev->rendercolor = g_vecZero;
if( m_fIsBack )
pev->rendercolor.z = 255;
else
pev->rendercolor.y = 255;
}
// If some player is on train with global state, save id
CBaseEntity *FindTriggerTransition( char *pVolumeName )
@ -1537,46 +1498,97 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
{
edict_t *pentLandmark;
LEVELLIST levels[16];
// LEVELLIST levels[16];
hudtextparms_t params = {};
params.fadeinTime = 0.5;
params.fadeoutTime = .5;
params.holdTime = 10;
params.r2 = params.g2 = params.b2 = params.a2 = params.r1 = params.g1 = params.b1 = params.a1 = 255;
bool valid = false;
ASSERT( !FStrEq( m_szMapName, "" ) );
if( s_SavedCoords.valid )
if( m_coopData.fValid )
return; //already pending
// forget touch by some fool
if( gpGlobals->time - pev->dmgtime > 30)
m_coopData.bitsTouchCount = 0;
// find best candidate for default spawn point
if( !m_coopData.fSpawnSaved )
{
m_uTouchCount = 0;
pev->nextthink = gpGlobals->time + 30;
CBasePlayer *pRealActivator = NULL;
if( pActivator )
{
// trigger touch
if( pActivator->IsNetClient() )
pRealActivator = (CBasePlayer*)pActivator;
// activate by path track?
if( !pRealActivator && pActivator->IsBSPModel() )
{
for( int i = 1; i < gpGlobals->maxClients; i++ )
{
CBaseEntity *plr = UTIL_PlayerByIndex( i );
if( plr && plr->IsNetClient() && plr->pev->groundentity == pActivator->edict() )
{
pRealActivator = (CBasePlayer*)plr;
break;
}
}
}
// activate by something other, player nearest to transition volume center
if( !pRealActivator && m_coopData.fUsed )
{
CBaseEntity *pTransition = FindTriggerTransition( m_szLandmarkName );
if( pTransition )
{
Vector vecOrigin = VecBModelOrigin( pTransition->pev );
float dist = 9999;
for( int i = 1; i < gpGlobals->maxClients; i++ )
{
CBaseEntity *plr = UTIL_PlayerByIndex( i );
if( plr && plr->IsNetClient() && pTransition->Intersects( plr ) )
{
float diff = (vecOrigin - plr->pev->origin).Length();
if( dist > diff )
{
dist = diff;
pRealActivator = (CBasePlayer *)plr;
break;
}
}
}
}
}
}
if( pRealActivator )
{
GGM_SavePosition(pRealActivator, &m_coopData.savedPosition);
m_hActivator = pRealActivator;
m_coopData.fSpawnSaved = true;
}
}
if(mp_coop.value)
{
SavedCoords l_SavedCoords = {};
// if not activated by touch, do not count players
if( !m_bUsed )
if( !m_coopData.fUsed )
{
m_uTouchCount |= 1 << ( ENTINDEX( pActivator->edict() ) - 1);
CBaseEntity *pActTrain = UTIL_CoopGetPlayerTrain(m_hActivator);
// Keep first toucher coords to save correct spawn angles
if( !m_fSpawnSaved && pActivator->IsPlayer() )
{
m_vecSpawnOrigin = pActivator->pev->origin;
m_vecSpawnAngles = pActivator->pev->angles;
m_fSpawnSaved = true;
UTIL_CoopSaveTrain( pActivator, &l_SavedCoords );
}
unsigned int count1 = 0;
unsigned int count2 = 0;
unsigned int count1 = 0; // players that touched
unsigned int count2 = 0; // all players
unsigned int i = 0;
m_coopData.bitsTouchCount |= 1 << ( ENTINDEX( pActivator->edict() ) - 1);
// loop through all clients, count number of players
for( i = 1; i <= gpGlobals->maxClients; i++ )
{
@ -1586,37 +1598,32 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
if( !pTrain && UTIL_CoopIsBadPlayer( plr ) )
continue;
// refuse
if( plr && (pTrain != pActTrain) )
return;
// count only players spawned more 30 seconds ago
if( plr && plr->IsPlayer() && (pTrain || (gpGlobals->time -((CBasePlayer*)plr)->gravgunmod_data.m_flSpawnTime ) > 30 ) && plr->pev->modelindex )
{
count2++;
// player touched trigger, save it's coordinates
if( m_uTouchCount & (1<<(i - 1)) )
{
// player touched trigger, count it
if( m_coopData.bitsTouchCount & (1<<(i - 1)) )
count1++;
if( InTransitionVolume( plr, m_szLandmarkName ))
{
l_SavedCoords.fDuck |= !!(plr->pev->flags & FL_DUCKING);
UTIL_CoopSaveTrain( plr, &l_SavedCoords );
l_SavedCoords.iCount++;
}
}
}
}
i = 0;
if( !l_SavedCoords.trainsaved )
if( !pActTrain )
{
if( !count2 )
{
if( pActivator && pActivator->IsPlayer() && m_flRepeatTimer - gpGlobals->time < -1 )
if( pActivator && pActivator->IsPlayer() && m_coopData.flRepeatTimer - gpGlobals->time < -1 )
{
CBasePlayer *pPlayer = (CBasePlayer*)pActivator;
//UTIL_CoopPrintMessage("%s^7 trying activate changelevel too early\n", UTIL_CoopPlayerName( pPlayer ));
UTIL_CleanSpawnPoint( pPlayer->pev->origin, 50 );
m_flRepeatTimer = gpGlobals->time;
m_coopData.flRepeatTimer = gpGlobals->time;
pPlayer->gravgunmod_data.m_iLocalConfirm = -2;
}
@ -1624,8 +1631,6 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
return;
}
if( count1 > 1 && count1 < count2 / 3 )
i = count1 - count1 < count2 / 3;
if( count1 > 1 && count1 < count2 / 3 )
i = 1;
@ -1637,7 +1642,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
if( count2 )
{
pev->rendercolor.x = count1 * 255 / count2;
if( m_fIsBack )
if( m_coopData.fIsBack )
pev->rendercolor.z = 255 - pev->rendercolor.x;
else
pev->rendercolor.y = 255 - pev->rendercolor.x;
@ -1645,40 +1650,22 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
ALERT( at_console, "^3CHANGELEVEL:^7 %d %d\n", count2, count1 );
if( !m_fIsBack && count1 > 1 && count1 < count2 / 3 )
if( !m_coopData.fIsBack && count1 > 1 && count1 < count2 / 3 )
return;
//if( count1 <= 1 && count2 == 2 )
// return;
if( m_fIsBack )
if( m_coopData.fIsBack )
if( !COOP_ConfirmMenu( this, pActivator, count2, m_szMapName ) )
return;
}
if( m_fSpawnSaved )
{
l_SavedCoords.triggerangles = m_vecSpawnAngles;
l_SavedCoords.triggerorigin = m_vecSpawnOrigin;
valid = true;
}
ALERT( at_console, "^2CHANGELEVEL:^7 %d %d %d\n", count2, count1, (int)m_fIsBack);
ALERT( at_console, "^2CHANGELEVEL:^7 %d %d %d\n", count2, count1, (int)m_coopData.fIsBack);
}
else
{
l_SavedCoords.fDuck = false;
// Get current player's coordinates
if( pActivator && pActivator->IsPlayer() )
{
l_SavedCoords.triggerangles = pActivator->pev->angles;
l_SavedCoords.triggerorigin = pActivator->pev->origin;
valid = true;
l_SavedCoords.fDuck |= !!(pActivator->pev->flags & FL_DUCKING);
}
}
UTIL_CoopSaveTrain( pActivator, &l_SavedCoords );
s_SavedCoords = l_SavedCoords;
@ -1687,8 +1674,8 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
else if( g_pGameRules->IsDeathmatch() )
return;
m_uTouchCount = 0;
m_bUsed = false;
m_coopData.bitsTouchCount = 0;
m_coopData.fUsed = false;
// Some people are firing these multiple times in a frame, disable
if( gpGlobals->time == pev->dmgtime )
return;
@ -1706,7 +1693,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
{
CBaseEntity *plr = UTIL_PlayerByIndex( i );
if( plr && plr->IsPlayer() && ( !FindTriggerTransition( m_szLandmarkName ) || (gpGlobals->time -((CBasePlayer*)plr)->gravgunmod_data.m_flSpawnTime ) > 30 || m_fSkipSpawnCheck ) )
if( plr && plr->IsPlayer() && ( !FindTriggerTransition( m_szLandmarkName ) || (gpGlobals->time -((CBasePlayer*)plr)->gravgunmod_data.m_flSpawnTime ) > 30 || m_coopData.fSkipSpawnCheck ) )
{
if( InTransitionVolume( plr, m_szLandmarkName ))
{
@ -1726,13 +1713,17 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
}
else if( ( (gpGlobals->time -((CBasePlayer*)pPlayer)->gravgunmod_data.m_flSpawnTime ) < 30 ) && FindTriggerTransition( m_szLandmarkName ) || !InTransitionVolume( pPlayer, m_szLandmarkName ) )
{
ALERT( at_console, "Player isn't in the transition volume %s, aborting\n", m_szLandmarkName );
if( !m_fSkipSpawnCheck )
if( !m_coopData.fSkipSpawnCheck )
{
ALERT( at_console, "Player isn't in the transition volume %s, aborting\n", m_szLandmarkName );
return;
}
else
ALERT( at_console, "Player isn't in the transition volume %s, but changelevel forced\n", m_szLandmarkName );
}
else ALERT( at_console, "Player is in the transition volume %s, changing level now\n", m_szLandmarkName );
UTIL_CoopPrintMessage( "%s^7 activated changelevel, spawncheck is %d\n", UTIL_CoopPlayerName( pPlayer ), (int)!m_fSkipSpawnCheck );
UTIL_CoopPrintMessage( "%s^7 activated changelevel, spawncheck is %d\n", UTIL_CoopPlayerName( pPlayer ), (int)!m_coopData.fSkipSpawnCheck );
// This object will get removed in the call to CHANGE_LEVEL, copy the params into "safe" memory
strcpy( st_szNextMap, m_szMapName );
@ -1746,10 +1737,10 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
if( !FNullEnt( pentLandmark ) )
{
strcpy( st_szNextSpot, m_szLandmarkName );
strcpy( s_SavedCoords.landmark, m_szLandmarkName );
s_SavedCoords.offset = gpGlobals->vecLandmarkOffset = VARS( pentLandmark )->origin;
gpGlobals->vecLandmarkOffset = VARS( pentLandmark )->origin;
}
// Create an entity to fire the changetarget
if( m_changeTarget )
{
@ -1769,6 +1760,8 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
}
}
m_coopData.fValid = true;
//ALERT( at_console, "Level touches %d levels\n", ChangeList( levels, 16 ) );
ALERT( at_console, "CHANGE LEVEL: %s %s\n", st_szNextMap, st_szNextSpot );
COOP_ResetVote();
@ -1793,9 +1786,8 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
}
g_fPause = true;
}
s_SavedCoords.fUsed = m_bUsed;
s_SavedCoords.valid = valid;
COOP_SetupLandmarkTransition( st_szNextMap, st_szNextSpot, gpGlobals->vecLandmarkOffset );
COOP_SetupLandmarkTransition( st_szNextMap, st_szNextSpot, gpGlobals->vecLandmarkOffset, m_coopData.fSpawnSaved?&m_coopData.savedPosition:NULL );
// wait 5 frames to make sure all players are in reconnected state
if( mp_coop_reconnect_hack.value )
@ -1812,7 +1804,7 @@ void CChangeLevel::TouchChangeLevel( CBaseEntity *pOther )
if( !FClassnameIs( pOther->pev, "player" ) )
return;
m_fSkipSpawnCheck = false;
m_coopData.fSkipSpawnCheck = false;
ChangeLevelNow( pOther );
}