From 2d0ef9914ae871a9d5824e64fb727aadb2af2c97 Mon Sep 17 00:00:00 2001 From: Night Owl Date: Wed, 30 Nov 2016 01:41:14 +0500 Subject: [PATCH 01/17] Prevent crash when pressed USE and called scripted_sequence. --- dlls/talkmonster.cpp | 2 ++ 1 file changed, 2 insertions(+) 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; } From 74edcd09b335be7a69bafa7f964645556eccb3e9 Mon Sep 17 00:00:00 2001 From: Night Owl Date: Sun, 4 Dec 2016 00:41:40 +0500 Subject: [PATCH 02/17] Make duplicate global variables extern. --- pm_shared/pm_shared.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pm_shared/pm_shared.c b/pm_shared/pm_shared.c index a9ac380f..de855a50 100644 --- a/pm_shared/pm_shared.c +++ b/pm_shared/pm_shared.c @@ -30,8 +30,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; From b7990e270d398a0ecd431cdbc37d37856e7f9e40 Mon Sep 17 00:00:00 2001 From: Roman Chistokhodov Date: Tue, 3 Jan 2017 00:49:22 +0300 Subject: [PATCH 03/17] Remove usage of MOVETYPE_COMPOUND to prevent crash --- dlls/crossbow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlls/crossbow.cpp b/dlls/crossbow.cpp index d34ad25d..63d2efac 100644 --- a/dlls/crossbow.cpp +++ b/dlls/crossbow.cpp @@ -168,8 +168,8 @@ void CCrossbowBolt::BoltTouch( CBaseEntity *pOther ) pev->nextthink = gpGlobals->time + 10.0; // g-cont. Setup movewith feature - pev->movetype = MOVETYPE_COMPOUND; // set movewith type - pev->aiment = ENT( pOther->pev ); // set parent + //pev->movetype = MOVETYPE_COMPOUND; // set movewith type + //pev->aiment = ENT( pOther->pev ); // set parent } if( UTIL_PointContents( pev->origin ) != CONTENTS_WATER ) From 56aa9f4a9c9ab7704af9dbaf1cb72acc5623c1a5 Mon Sep 17 00:00:00 2001 From: Roman Chistokhodov Date: Wed, 4 Jan 2017 22:05:21 +0300 Subject: [PATCH 04/17] Put MOVETYPE_COMPOUND usage under if --- dlls/crossbow.cpp | 10 +++++++--- dlls/world.cpp | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/dlls/crossbow.cpp b/dlls/crossbow.cpp index 63d2efac..45fd922c 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: @@ -167,9 +169,11 @@ void CCrossbowBolt::BoltTouch( CBaseEntity *pOther ) pev->angles.z = RANDOM_LONG( 0, 360 ); pev->nextthink = gpGlobals->time + 10.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/world.cpp b/dlls/world.cpp index fe119919..a065b5be 100644 --- a/dlls/world.cpp +++ b/dlls/world.cpp @@ -822,6 +822,8 @@ static physics_interface_t gPhysicsInterface = DispatchPhysicsEntity, }; +BOOL gPhysicsInterfaceInitialized = FALSE; + int Server_GetPhysicsInterface( int iVersion, server_physics_api_t *pfuncsFromEngine, physics_interface_t *pFunctionTable ) { if( !pFunctionTable || !pfuncsFromEngine || iVersion != SV_PHYSICS_INTERFACE_VERSION ) @@ -834,6 +836,6 @@ int Server_GetPhysicsInterface( int iVersion, server_physics_api_t *pfuncsFromEn // fill engine callbacks memcpy( pFunctionTable, &gPhysicsInterface, sizeof(physics_interface_t) ); - + gPhysicsInterfaceInitialized = TRUE; return TRUE; } From 02532a478bfa63b6abdbbaf6c62e385ec8ba4eef Mon Sep 17 00:00:00 2001 From: mittorn Date: Tue, 10 Jan 2017 16:09:44 +0700 Subject: [PATCH 05/17] Fix visual studio server build --- dlls/effects.cpp | 4 ++-- dlls/nodes.cpp | 2 ++ dlls/weapons.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dlls/effects.cpp b/dlls/effects.cpp index e9492dd6..ecc04a19 100644 --- a/dlls/effects.cpp +++ b/dlls/effects.cpp @@ -410,7 +410,7 @@ LINK_ENTITY_TO_CLASS( trip_beam, CTripBeam ) void CTripBeam::Spawn( void ) { CLightning::Spawn(); - SetTouch( &TriggerTouch ); + SetTouch( &CLightning::TriggerTouch ); pev->solid = SOLID_TRIGGER; RelinkBeam(); } @@ -1267,7 +1267,7 @@ void CSprite::TurnOn( void ) pev->effects = 0; if( ( pev->framerate && m_maxFrame > 1.0 ) || ( pev->spawnflags & SF_SPRITE_ONCE ) ) { - SetThink( &CSprite::CSprite::AnimateThink ); + SetThink( &CSprite::AnimateThink ); pev->nextthink = gpGlobals->time; m_lastTime = gpGlobals->time; } 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/weapons.cpp b/dlls/weapons.cpp index 3e2ef386..ff03bbfc 100644 --- a/dlls/weapons.cpp +++ b/dlls/weapons.cpp @@ -1080,7 +1080,7 @@ void CBasePlayerAmmo::DefaultTouch( CBaseEntity *pOther ) //========================================================= int CBasePlayerWeapon::ExtractAmmo( CBasePlayerWeapon *pWeapon ) { - int iReturn; + int iReturn = 0; if( pszAmmo1() != NULL ) { From 5da21e38d23be01669fade2747425dcc8692e0e9 Mon Sep 17 00:00:00 2001 From: mittorn Date: Tue, 10 Jan 2017 16:45:52 +0700 Subject: [PATCH 06/17] Fix client visual studio build --- cl_dll/hud_spectator.cpp | 2 +- cl_dll/input_xash3d.cpp | 2 +- cl_dll/util.cpp | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) 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 ) From 61bdd7d95e19581bdfb3f7cb033d3783fa66aaaa Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 11 Jan 2017 23:49:55 +0200 Subject: [PATCH 07/17] Do not crash on lost bodyque --- dlls/world.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dlls/world.cpp b/dlls/world.cpp index 4ac56925..327dbc62 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; From c8084e84289e454bf9591a3daa8e45a74767773f Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 12 Jan 2017 01:26:32 +0200 Subject: [PATCH 08/17] Add extended weapon ehandle --- dlls/player.cpp | 6 +++--- dlls/player.h | 10 ++++++---- dlls/weapons.cpp | 4 ++-- dlls/weapons.h | 7 +++++-- dlls/whandle.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 dlls/whandle.h 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..0751da69 100644 --- a/dlls/player.h +++ b/dlls/player.h @@ -93,6 +93,8 @@ enum PlayerState STATE_POINT_SELECT }; +#include "whandle.h" + class CBasePlayer : public CBaseMonster { public: @@ -173,10 +175,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]; diff --git a/dlls/weapons.cpp b/dlls/weapons.cpp index 09a3bbc4..57e80ba9 100644 --- a/dlls/weapons.cpp +++ b/dlls/weapons.cpp @@ -393,7 +393,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 ), @@ -1303,7 +1303,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 223fd79a..31f45ea2 100644 --- a/dlls/weapons.h +++ b/dlls/weapons.h @@ -214,6 +214,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 { @@ -262,7 +265,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 @@ -453,7 +456,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 From dd1fd1c5da9ff1c9ddabee4e06fc6c09f73fecd1 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 15 Jan 2017 15:03:19 +0200 Subject: [PATCH 09/17] Add ability to change materials.txt and sentences.txt paths --- dlls/game.cpp | 6 ++++++ dlls/game.h | 3 +++ dlls/sound.cpp | 5 +++-- pm_shared/pm_shared.c | 12 ++++++++++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/dlls/game.cpp b/dlls/game.cpp index dc27ab40..22197576 100644 --- a/dlls/game.cpp +++ b/dlls/game.cpp @@ -60,6 +60,9 @@ 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; @@ -511,6 +514,9 @@ void GameDLLInit( void ) CVAR_REGISTER( &mp_coop_noangry ); CVAR_REGISTER( &mp_spectator ); + CVAR_REGISTER( &sentences_txt ); + CVAR_REGISTER( &materials_txt ); + CVAR_REGISTER( &mp_chattime ); diff --git a/dlls/game.h b/dlls/game.h index c5a61d9a..c0eb3529 100644 --- a/dlls/game.h +++ b/dlls/game.h @@ -58,6 +58,9 @@ 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; 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/pm_shared/pm_shared.c b/pm_shared/pm_shared.c index 8f1dd354..db9926b7 100644 --- a/pm_shared/pm_shared.c +++ b/pm_shared/pm_shared.c @@ -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; From 04afeb4798452dadc22bd84500b0ca8dc9f8a714 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 15 Jan 2017 15:05:23 +0200 Subject: [PATCH 10/17] Fix too long line that crashed some clients --- dlls/gamerules.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlls/gamerules.cpp b/dlls/gamerules.cpp index aeb652f8..74bc17e8 100644 --- a/dlls/gamerules.cpp +++ b/dlls/gamerules.cpp @@ -117,11 +117,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; From 06cab187628d08f466beeeb823f7b593016a3c39 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 15 Jan 2017 21:58:47 +0200 Subject: [PATCH 11/17] Refactor menu, add checkpoints --- dlls/game.cpp | 3 + dlls/game.h | 2 + dlls/multiplay_gamerules.cpp | 49 +------------ dlls/player.h | 10 +++ dlls/triggers.cpp | 134 +++++++++++++++++++++++++++++++---- 5 files changed, 140 insertions(+), 58 deletions(-) diff --git a/dlls/game.cpp b/dlls/game.cpp index 22197576..03ddf7f9 100644 --- a/dlls/game.cpp +++ b/dlls/game.cpp @@ -56,6 +56,8 @@ 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 }; @@ -513,6 +515,7 @@ 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 ); diff --git a/dlls/game.h b/dlls/game.h index c0eb3529..d28f2779 100644 --- a/dlls/game.h +++ b/dlls/game.h @@ -52,6 +52,8 @@ 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; diff --git a/dlls/multiplay_gamerules.cpp b/dlls/multiplay_gamerules.cpp index ce08e7ca..2ebb4c10 100644 --- a/dlls/multiplay_gamerules.cpp +++ b/dlls/multiplay_gamerules.cpp @@ -240,57 +240,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; - } + 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" ); return TRUE; } @@ -660,6 +616,7 @@ void CHalfLifeMultiplay::InitHUD( CBasePlayer *pl ) if( pl->m_state == STATE_SPECTATOR_BEGIN ) { + pl->m_iMenuState = MENUSTATE_COOPMENU_SPEC; if( mp_coop.value ) { diff --git a/dlls/player.h b/dlls/player.h index 0751da69..0794cb44 100644 --- a/dlls/player.h +++ b/dlls/player.h @@ -93,6 +93,15 @@ enum PlayerState STATE_POINT_SELECT }; +enum PlayerMenuState +{ + MENUSTATE_NONE = 0, + MENUSTATE_COOPMENU, + MENUSTATE_COOPMENU_SPEC, + MENUSTATE_CHECKPOINT, + MENUSTATE_GLOBAL +}; + #include "whandle.h" class CBasePlayer : public CBaseMonster @@ -325,6 +334,7 @@ public: float m_flSpawnTime; PlayerState m_state; bool m_fTouchMenu; + int m_iMenuState; virtual void Touch( CBaseEntity *pOther ); }; diff --git a/dlls/triggers.cpp b/dlls/triggers.cpp index e852a4aa..37715433 100644 --- a/dlls/triggers.cpp +++ b/dlls/triggers.cpp @@ -1508,13 +1508,20 @@ struct SavedCoords bool fDuck; } g_SavedCoords, s_SavedCoords; +struct checkpoint_s +{ + char str[32]; + float time; + Vector origin; +} g_checkpoints[4]; void CoopClearData( void ) { // nullify - SavedCoords l_SavedCoords = {}; + SavedCoords l_SavedCoords = {0}; g_SavedCoords = l_SavedCoords; + memset( &g_checkpoints, 0, sizeof( g_checkpoints ) ); } bool g_fPause; @@ -1522,12 +1529,14 @@ void CoopApplyData( void ) { if( s_SavedCoords.valid ) { + struct SavedCoords null1 = {0}; g_SavedCoords = s_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; @@ -1648,7 +1657,9 @@ public: if( plr && plr->IsPlayer() ) { count2++; - ShowMenu( (CBasePlayer *)plr, title, count, menu, 30 ); + CBasePlayer *player = (CBasePlayer *) plr; + ShowMenu( player, title, count, menu, 30 ); + player->m_iMenuState = MENUSTATE_GLOBAL; } } @@ -1732,6 +1743,39 @@ void CChangeLevel::UpdateColor( void ) } +void CoopCheckpointMenu( CBasePlayer *pPlayer ) +{ + if( pPlayer->m_state == STATE_SPAWNED ) + { + + if( mp_coop_checkpoints.value ) + { + const char *menu[5] = { + "New checkpoint" + }; + int i; + for( i = 1; g_checkpoints[i-1].time; i++ ) + menu[i] = g_checkpoints[i-1].str; + ShowMenu( pPlayer, "Coop menu", i, menu ); + pPlayer->m_iMenuState = MENUSTATE_CHECKPOINT; + } + } +} + + +void 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; + MESSAGE_BEGIN( MSG_ALL, 8, NULL ); // svc_print + WRITE_BYTE( 3 ); // PRINT_CHAT + WRITE_STRING( "New checkpoint availiable\n" ); + MESSAGE_END(); + +} + void CoopVoteMenu( CBasePlayer *pPlayer ) { int count = 0; @@ -1751,26 +1795,30 @@ void CoopVoteMenu( CBasePlayer *pPlayer ) } 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 ) { - + pPlayer->m_iMenuState = MENUSTATE_COOPMENU; if( mp_coop.value ) { const char *menu[] = { "Force respawn", "Unblock", "Become spectator", - "Vote changelevel" + "Vote changelevel", + "Checkpoint/restore" }; - ShowMenu( pPlayer, "Coop menu", ARRAYSIZE( menu ), menu ); + int count1 = ARRAYSIZE( menu ) - 1; + if( mp_coop_checkpoints.value ) + count1++; + ShowMenu( 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[] = { @@ -1782,9 +1830,71 @@ void CoopMenu( CBasePlayer *pPlayer ) } } +void SpawnPlayer( CBasePlayer *pPlayer ); +void BecomeSpectator( CBasePlayer *pPlayer ); + void CoopProcessMenu( CBasePlayer *pPlayer, int imenu ) { - return g_GlobalMenu.Process( pPlayer, imenu ); + switch( pPlayer->m_iMenuState ) + { + case MENUSTATE_COOPMENU_SPEC: + 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 MENUSTATE_COOPMENU: + if( pPlayer->m_state != STATE_SPAWNED ) + break; + 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 ); + } + if( imenu == 5 ) + { + CoopCheckpointMenu( pPlayer ); + } + break; + case MENUSTATE_GLOBAL: + g_GlobalMenu.Process( pPlayer, imenu ); + break; + case MENUSTATE_CHECKPOINT: + if( imenu == 1 ) + { + CoopNewCheckpoint( pPlayer->pev ); + } + else if( imenu > 1 && imenu < 5 ) + { + pPlayer->RemoveAllItems( TRUE ); + SpawnPlayer( pPlayer ); + pPlayer->pev->origin = g_checkpoints[imenu-2].origin; + } + break; + default: + break; + } + //pPlayer->m_iMenuState = MENUSTATE_NONE; } static void validateoffset( void ) @@ -2051,7 +2161,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) { if( !count2 ) { - UTIL_HudMessageAll( params, "Cannot change level: Not enough players! Wait 30 sec before you may changelevel!" ); + UTIL_HudMessageAll( params, "Cannot change level: Not enough players!\nWait 30 sec before you may changelevel!" ); return; } @@ -2061,7 +2171,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) i = 1; if( i ) - UTIL_HudMessageAll( params, UTIL_VarArgs( "%s touched end of map, next is %s %s, %d to go", + UTIL_HudMessageAll( params, UTIL_VarArgs( "%s touched end of map\nnext 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 ) @@ -2148,7 +2258,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) { CBaseEntity *plr = UTIL_PlayerByIndex( i ); - if( plr && plr->IsPlayer() && ( !FindTriggerTransition( m_szLandmarkName ) || (gpGlobals->time -((CBasePlayer*)plr)->m_flSpawnTime ) > 30 ) || m_fSkipSpawnCheck ) + if( plr && plr->IsPlayer() && ( !FindTriggerTransition( m_szLandmarkName ) || (gpGlobals->time -((CBasePlayer*)plr)->m_flSpawnTime ) > 30 || m_fSkipSpawnCheck ) ) { if( InTransitionVolume( plr, m_szLandmarkName )) { From d627ff1528a313c3fe5e9187a733daa1ed48e907 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 18 Jan 2017 18:13:42 +0200 Subject: [PATCH 12/17] Allow incresed charger capacity in coop --- dlls/multiplay_gamerules.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dlls/multiplay_gamerules.cpp b/dlls/multiplay_gamerules.cpp index 2ebb4c10..ae52372b 100644 --- a/dlls/multiplay_gamerules.cpp +++ b/dlls/multiplay_gamerules.cpp @@ -265,7 +265,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; @@ -1296,12 +1297,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; } //========================================================= From ab1ae84bc8f17c651d8fa50e06ea0caa50fbe0c7 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 18 Jan 2017 18:17:35 +0200 Subject: [PATCH 13/17] Add changelevel local confirm and banlist --- dlls/player.h | 5 +- dlls/triggers.cpp | 132 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 122 insertions(+), 15 deletions(-) diff --git a/dlls/player.h b/dlls/player.h index 0794cb44..a74757f6 100644 --- a/dlls/player.h +++ b/dlls/player.h @@ -99,7 +99,8 @@ enum PlayerMenuState MENUSTATE_COOPMENU, MENUSTATE_COOPMENU_SPEC, MENUSTATE_CHECKPOINT, - MENUSTATE_GLOBAL + MENUSTATE_GLOBAL, + MENUSTATE_LOCAL_CONFIRM }; #include "whandle.h" @@ -335,6 +336,8 @@ public: PlayerState m_state; bool m_fTouchMenu; int m_iMenuState; + int m_iLocalConfirm; + int m_iConfirmKey; virtual void Touch( CBaseEntity *pOther ); }; diff --git a/dlls/triggers.cpp b/dlls/triggers.cpp index 37715433..84d97142 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 ) @@ -1513,6 +1514,7 @@ struct checkpoint_s char str[32]; float time; Vector origin; + Vector angles; } g_checkpoints[4]; @@ -1546,12 +1548,54 @@ void ShowMenu( CBasePlayer *pPlayer, const char *title, int count, const char ** bool g_fSavedDuck; #define CoopPlayerName( pPlayer ) ( ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected" ) +char *badlist[100] = { +"player", // does not even can set own name +"talat", +"hmse", +"mhmd", +"aeman", +"famas", +"danek", +"ame syia", +"melih" +}; void CoopKickPlayer(CBaseEntity *pPlayer) { + int i; if( !pPlayer ) return; SERVER_COMMAND( UTIL_VarArgs( "kick %d\n", ENTINDEX(pPlayer->pev->pContainingEntity) - 1 ) ); + char *name = (char*) CoopPlayerName( pPlayer ); + if( strlen( name ) < 5 ) + return; + for( i = 0; badlist[i]; i++ ); + badlist[i] = strdup( name ); +} + +bool IsBadPlayer( CBaseEntity *plr ) +{ + if( !plr || !plr->IsPlayer() ) + return false; + for( int i = 0; badlist[i];i++ ) + if( strcasestr( (char*)CoopPlayerName( plr ), badlist[i] ) ) + return true; + return false; +} + +void CoopLocalConfirmMenu(CBasePlayer *pPlayer) +{ + const char *menu[] = { + "No", + "Cancel", + "Do not confirm", + "Don't confirm", + "Единая Россия" + }; + + menu[pPlayer->m_iConfirmKey = RANDOM_LONG(2,4)] = "Confirm"; + ShowMenu(pPlayer, "Confirm changing map BACK (NOT RECOMMENDED)?", ARRAYSIZE(menu), menu); + pPlayer->m_iMenuState = MENUSTATE_LOCAL_CONFIRM; } // Show to all spawned players: voting, etc.. @@ -1654,7 +1698,7 @@ public: { CBaseEntity *plr = UTIL_PlayerByIndex( i ); - if( plr && plr->IsPlayer() ) + if( plr && plr->IsPlayer() && !IsBadPlayer( plr ) ) { count2++; CBasePlayer *player = (CBasePlayer *) plr; @@ -1671,6 +1715,13 @@ public: { 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 ) + { + CoopLocalConfirmMenu( pPlayer ); + return; + } g_iMenu = 1; m_flTime = gpGlobals->time; m_pTrigger = trigger; @@ -1680,7 +1731,11 @@ public: "Cancel", "BAN" }; - ShowGlobalMenu(UTIL_VarArgs("Confirm changing map to %s?", mapname), ARRAYSIZE(menu), menu); + 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 VoteMenu( CBasePlayer *pPlayer ) @@ -1707,6 +1762,10 @@ public: 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", CoopPlayerName( pPlayer ) ), i, maps); } @@ -1715,8 +1774,6 @@ public: }; GlobalMenu g_GlobalMenu; - - void CChangeLevel::UpdateColor( void ) { Vector origin = VecBModelOrigin(pev); @@ -1745,7 +1802,7 @@ void CChangeLevel::UpdateColor( void ) void CoopCheckpointMenu( CBasePlayer *pPlayer ) { - if( pPlayer->m_state == STATE_SPAWNED ) + //if( pPlayer->m_state == STATE_SPAWNED ) { if( mp_coop_checkpoints.value ) @@ -1754,9 +1811,11 @@ void CoopCheckpointMenu( CBasePlayer *pPlayer ) "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; - ShowMenu( pPlayer, "Coop menu", i, menu ); + ShowMenu( pPlayer, "Select checkpoint", i, menu ); pPlayer->m_iMenuState = MENUSTATE_CHECKPOINT; } } @@ -1769,6 +1828,7 @@ void CoopNewCheckpoint( entvars_t *pevPlayer ) 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" ); @@ -1840,8 +1900,13 @@ void CoopProcessMenu( CBasePlayer *pPlayer, int imenu ) case MENUSTATE_COOPMENU_SPEC: if( imenu == 1 ) { - SpawnPlayer( pPlayer ); - pPlayer->m_state = STATE_SPAWNED; + if( g_checkpoints[0].time ) + CoopCheckpointMenu( pPlayer ); + else + { + SpawnPlayer( pPlayer ); + pPlayer->m_state = STATE_SPAWNED; + } } if( imenu == 2 ) { @@ -1877,12 +1942,16 @@ void CoopProcessMenu( CBasePlayer *pPlayer, int imenu ) } break; case MENUSTATE_GLOBAL: - g_GlobalMenu.Process( pPlayer, imenu ); + if( !IsBadPlayer( pPlayer ) ) + g_GlobalMenu.Process( pPlayer, imenu ); break; case MENUSTATE_CHECKPOINT: if( imenu == 1 ) { - CoopNewCheckpoint( pPlayer->pev ); + if( pPlayer->m_state == STATE_SPECTATOR_BEGIN ) + SpawnPlayer( pPlayer ); + else if( !IsBadPlayer( pPlayer ) ) + CoopNewCheckpoint( pPlayer->pev ); } else if( imenu > 1 && imenu < 5 ) { @@ -1891,6 +1960,13 @@ void CoopProcessMenu( CBasePlayer *pPlayer, int imenu ) pPlayer->pev->origin = g_checkpoints[imenu-2].origin; } 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; } @@ -2131,9 +2207,13 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) for( i = 1; i <= gpGlobals->maxClients; i++ ) { CBaseEntity *plr = UTIL_PlayerByIndex( i ); + CBaseEntity *pTrain = CoopGetPlayerTrain( plr ); + + if( !pTrain && IsBadPlayer( 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++; @@ -2161,6 +2241,17 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) { 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; +} + UTIL_HudMessageAll( params, "Cannot change level: Not enough players!\nWait 30 sec before you may changelevel!" ); return; } @@ -2171,7 +2262,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) i = 1; if( i ) - UTIL_HudMessageAll( params, UTIL_VarArgs( "%s touched end of map\nnext is %s %s, %d to go", + 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 ) @@ -2200,11 +2291,20 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) } if( g_iMenu != 1 ) { - g_GlobalMenu.ConfirmMenu( (CBasePlayer*)pActivator, this, m_szMapName ); + if( !IsBadPlayer( 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; + }*/ } } @@ -2288,6 +2388,10 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) }*/ + 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(); // shedule remove ke^w on first info_player_start /*edict_t *playerstart = FIND_ENTITY_BY_CLASSNAME( NULL, "info_player_start" ); From 6b575975c6b3508d1a3fe0c71dfd7175c5383036 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 18 Jan 2017 18:23:26 +0200 Subject: [PATCH 14/17] Fix blacklist --- dlls/triggers.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dlls/triggers.cpp b/dlls/triggers.cpp index 84d97142..715380dc 100644 --- a/dlls/triggers.cpp +++ b/dlls/triggers.cpp @@ -1548,7 +1548,7 @@ void ShowMenu( CBasePlayer *pPlayer, const char *title, int count, const char ** bool g_fSavedDuck; #define CoopPlayerName( pPlayer ) ( ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected" ) -char *badlist[100] = { +char *badlist[256] = { "player", // does not even can set own name "talat", "hmse", @@ -1557,7 +1557,9 @@ char *badlist[100] = { "famas", "danek", "ame syia", -"melih" +"melih", +"aliance", +"vladick" }; void CoopKickPlayer(CBaseEntity *pPlayer) @@ -1565,8 +1567,8 @@ void CoopKickPlayer(CBaseEntity *pPlayer) int i; if( !pPlayer ) return; - SERVER_COMMAND( UTIL_VarArgs( "kick %d\n", ENTINDEX(pPlayer->pev->pContainingEntity) - 1 ) ); char *name = (char*) CoopPlayerName( pPlayer ); + SERVER_COMMAND( UTIL_VarArgs( "kick %d\n", ENTINDEX(pPlayer->pev->pContainingEntity) - 1 ) ); if( strlen( name ) < 5 ) return; for( i = 0; badlist[i]; i++ ); @@ -1575,7 +1577,7 @@ void CoopKickPlayer(CBaseEntity *pPlayer) bool IsBadPlayer( CBaseEntity *plr ) { - if( !plr || !plr->IsPlayer() ) + if( !plr ) return false; for( int i = 0; badlist[i];i++ ) if( strcasestr( (char*)CoopPlayerName( plr ), badlist[i] ) ) From 578f3b93c1a0710e4f94ac75a7aa7caf3b88c732 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 18 Jan 2017 21:26:00 +0000 Subject: [PATCH 15/17] Big refactoring --- dlls/Android.mk | 3 +- dlls/client.cpp | 8 +- dlls/coop.cpp | 617 ++++++++++++++++++++++++++++++++ dlls/coop_util.h | 108 ++++++ dlls/game.h | 30 +- dlls/gamerules.cpp | 25 +- dlls/multiplay_gamerules.cpp | 49 +-- dlls/triggers.cpp | 663 +++-------------------------------- dlls/util.cpp | 15 - dlls/util.h | 1 - 10 files changed, 794 insertions(+), 725 deletions(-) create mode 100644 dlls/coop.cpp create mode 100644 dlls/coop_util.h 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..ca0c67da 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 @@ -710,7 +710,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..3ca7a8af --- /dev/null +++ b/dlls/coop.cpp @@ -0,0 +1,617 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "player.h" +#include "coop_util.h" + +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; + 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; + } + 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; +} + +GlobalMenu g_GlobalMenu; + + +struct SavedCoords g_SavedCoords, s_SavedCoords; 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/game.h b/dlls/game.h index d28f2779..9828a614 100644 --- a/dlls/game.h +++ b/dlls/game.h @@ -35,36 +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_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; +#include "coop_util.h" // Engine Cvars extern cvar_t *g_psv_gravity; diff --git a/dlls/gamerules.cpp b/dlls/gamerules.cpp index 74bc17e8..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 ) { @@ -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 ae52372b..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,13 +213,13 @@ BOOL CHalfLifeMultiplay::ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) { int imenu = atoi( CMD_ARGV( 1 ) ); - CoopProcessMenu( pPlayer, imenu ); + UTIL_CoopProcessMenu( pPlayer, imenu ); return TRUE; } if( FStrEq( pcmd, "coopmenu" ) ) { - CoopMenu( pPlayer ); + UTIL_CoopMenu( pPlayer ); return TRUE; } @@ -625,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 ); } } } @@ -703,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 ) { @@ -750,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; } diff --git a/dlls/triggers.cpp b/dlls/triggers.cpp index 715380dc..a05e3c93 100644 --- a/dlls/triggers.cpp +++ b/dlls/triggers.cpp @@ -1487,294 +1487,62 @@ 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; - int changeback; - bool trainsaved; - Vector trainoffset; - char trainglobal[256]; - int trainuser1; - bool fUsed; - bool fDuck; -} g_SavedCoords, s_SavedCoords; - -struct checkpoint_s -{ - char str[32]; - float time; - Vector origin; - Vector angles; -} g_checkpoints[4]; - - -void CoopClearData( void ) +void UTIL_CoopActivateChangeLevel( CBaseEntity *pTrigger ) { - // 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 ShowMenu( CBasePlayer *pPlayer, const char *title, int count, const char **slot, signed char time = -1 ); - -bool g_fSavedDuck; - -#define CoopPlayerName( pPlayer ) ( ( pPlayer->pev->netname && STRING( pPlayer->pev->netname )[0] != 0 ) ? STRING( pPlayer->pev->netname ) : "unconnected" ) -char *badlist[256] = { -"player", // does not even can set own name -"talat", -"hmse", -"mhmd", -"aeman", -"famas", -"danek", -"ame syia", -"melih", -"aliance", -"vladick" -}; + CChangeLevel *trigger = (CChangeLevel*) pTrigger; -void CoopKickPlayer(CBaseEntity *pPlayer) -{ - int i; - if( !pPlayer ) - return; - char *name = (char*) CoopPlayerName( pPlayer ); - SERVER_COMMAND( UTIL_VarArgs( "kick %d\n", ENTINDEX(pPlayer->pev->pContainingEntity) - 1 ) ); - if( strlen( name ) < 5 ) + if( !trigger ) return; - for( i = 0; badlist[i]; i++ ); - badlist[i] = strdup( name ); -} -bool IsBadPlayer( CBaseEntity *plr ) -{ - if( !plr ) - return false; - for( int i = 0; badlist[i];i++ ) - if( strcasestr( (char*)CoopPlayerName( plr ), badlist[i] ) ) - return true; - return false; + trigger->m_bUsed = true; + trigger->ChangeLevelNow( NULL ); } -void CoopLocalConfirmMenu(CBasePlayer *pPlayer) +void GlobalMenu::VoteMenu( CBasePlayer *pPlayer ) { - const char *menu[] = { - "No", - "Cancel", - "Do not confirm", - "Don't confirm", - "Единая Россия" - }; - - menu[pPlayer->m_iConfirmKey = RANDOM_LONG(2,4)] = "Confirm"; - ShowMenu(pPlayer, "Confirm changing map BACK (NOT RECOMMENDED)?", ARRAYSIZE(menu), menu); - pPlayer->m_iMenuState = MENUSTATE_LOCAL_CONFIRM; -} - -// 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 ) + 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) ) { - int count2 = 0; - for( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *plr = UTIL_PlayerByIndex( i ); + CChangeLevel *ent = (CChangeLevel *)pTrigger; + votes[i] = 0; + triggers[i] = ent; + maps[i++] = ent->m_szMapName; - if( plr && plr->IsPlayer() && !IsBadPlayer( plr ) ) - { - count2++; - CBasePlayer *player = (CBasePlayer *) plr; - ShowMenu( player, title, count, menu, 30 ); - player->m_iMenuState = MENUSTATE_GLOBAL; - } - } - m_iMaxCount = count2; - m_iBanCount = 0; } + 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 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 ) - { - 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 VoteMenu( CBasePlayer *pPlayer ) +} +void UTIL_CoopValidateOffset( void ) +{ + if( !g_SavedCoords.validoffset) { - 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; - 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", 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; void CChangeLevel::UpdateColor( void ) { @@ -1786,7 +1554,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; @@ -1802,342 +1570,7 @@ void CChangeLevel::UpdateColor( void ) } -void 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; - ShowMenu( pPlayer, "Select checkpoint", i, menu ); - pPlayer->m_iMenuState = MENUSTATE_CHECKPOINT; - } - } -} - - -void 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 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( 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++; - ShowMenu( 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" - }; - ShowMenu( pPlayer, "Spectator menu", ARRAYSIZE( menu ), menu ); - } - } -} - -void SpawnPlayer( CBasePlayer *pPlayer ); -void BecomeSpectator( CBasePlayer *pPlayer ); - -void CoopProcessMenu( CBasePlayer *pPlayer, int imenu ) -{ - switch( pPlayer->m_iMenuState ) - { - case MENUSTATE_COOPMENU_SPEC: - if( imenu == 1 ) - { - if( g_checkpoints[0].time ) - CoopCheckpointMenu( pPlayer ); - else - { - 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 ); - 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 ); - } - if( imenu == 5 ) - { - CoopCheckpointMenu( pPlayer ); - } - break; - case MENUSTATE_GLOBAL: - if( !IsBadPlayer( pPlayer ) ) - g_GlobalMenu.Process( pPlayer, imenu ); - break; - case MENUSTATE_CHECKPOINT: - if( imenu == 1 ) - { - if( pPlayer->m_state == STATE_SPECTATOR_BEGIN ) - SpawnPlayer( pPlayer ); - else if( !IsBadPlayer( pPlayer ) ) - CoopNewCheckpoint( pPlayer->pev ); - } - else if( imenu > 1 && imenu < 5 ) - { - pPlayer->RemoveAllItems( TRUE ); - SpawnPlayer( pPlayer ); - pPlayer->pev->origin = g_checkpoints[imenu-2].origin; - } - 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; -} - -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 ) { @@ -2199,7 +1632,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; @@ -2209,9 +1642,9 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) for( i = 1; i <= gpGlobals->maxClients; i++ ) { CBaseEntity *plr = UTIL_PlayerByIndex( i ); - CBaseEntity *pTrain = CoopGetPlayerTrain( plr ); + CBaseEntity *pTrain = UTIL_CoopGetPlayerTrain( plr ); - if( !pTrain && IsBadPlayer( plr ) ) + if( !pTrain && UTIL_CoopIsBadPlayer( plr ) ) continue; // count only players spawned more 30 seconds ago @@ -2226,7 +1659,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; @@ -2293,7 +1726,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) } if( g_iMenu != 1 ) { - if( !IsBadPlayer( pActivator ) ) + if( !UTIL_CoopIsBadPlayer( pActivator ) ) g_GlobalMenu.ConfirmMenu( (CBasePlayer*)pActivator, this, m_szMapName ); return; } @@ -2331,7 +1764,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) } } - CoopSaveTrain( pActivator, &l_SavedCoords ); + UTIL_CoopSaveTrain( pActivator, &l_SavedCoords ); s_SavedCoords = l_SavedCoords; @@ -2451,7 +1884,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) { plr->m_state = STATE_UNINITIALIZED; plr->RemoveAllItems( TRUE ); - BecomeSpectator( plr ); + UTIL_BecomeSpectator( plr ); //plr->SetThink( &CBasePlayer::Spawn ); //plr->pev->nextthink = gpGlobals->time + 1; // HACK: force perform reconnection 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 ); From 2f4f8090a7231ae762bf538cb2880d3880568848 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 18 Jan 2017 21:37:52 +0000 Subject: [PATCH 16/17] Remove wrong nickname changed message in coop --- dlls/client.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dlls/client.cpp b/dlls/client.cpp index ca0c67da..b9ade580 100644 --- a/dlls/client.cpp +++ b/dlls/client.cpp @@ -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 ); From dbf9a357f2907e3016be009c73f846d7bf8f458b Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 19 Jan 2017 21:04:44 +0000 Subject: [PATCH 17/17] tabs, comments, code style --- dlls/coop.cpp | 42 ++++++---- dlls/triggers.cpp | 195 +++++++++++++++++++++------------------------- 2 files changed, 117 insertions(+), 120 deletions(-) diff --git a/dlls/coop.cpp b/dlls/coop.cpp index 3ca7a8af..e532579e 100644 --- a/dlls/coop.cpp +++ b/dlls/coop.cpp @@ -4,6 +4,13 @@ #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; @@ -129,13 +136,19 @@ char *badlist[256] = { 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 ); } @@ -143,9 +156,11 @@ 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; } @@ -218,16 +233,17 @@ void GlobalMenu::Process( CBasePlayer *pPlayer, int imenu ) 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( 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 @@ -481,6 +497,7 @@ void UTIL_CoopProcessMenu( CBasePlayer *pPlayer, int imenu ) 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: @@ -610,8 +627,3 @@ CBaseEntity *UTIL_CoopGetPlayerTrain( CBaseEntity *pPlayer) return NULL; return train; } - -GlobalMenu g_GlobalMenu; - - -struct SavedCoords g_SavedCoords, s_SavedCoords; diff --git a/dlls/triggers.cpp b/dlls/triggers.cpp index a05e3c93..74ce68fd 100644 --- a/dlls/triggers.cpp +++ b/dlls/triggers.cpp @@ -1529,6 +1529,8 @@ void GlobalMenu::VoteMenu( CBasePlayer *pPlayer ) ShowGlobalMenu(UTIL_VarArgs("%s requested to force change map", UTIL_CoopPlayerName( pPlayer ) ), i, maps); } + + void UTIL_CoopValidateOffset( void ) { if( !g_SavedCoords.validoffset) @@ -1674,73 +1676,74 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) i = 0; if( !l_SavedCoords.trainsaved ) { - 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; -} - - UTIL_HudMessageAll( params, "Cannot change level: Not enough players!\nWait 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\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 ) + i = count1 - count1 < count2 / 3; + if( count1 > 1 && count1 < count2 / 3 ) + i = 1; + + 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; + } - ALERT( at_console, "^3CHANGELEVEL:^7 %d %d\n", count2, count1 ); + ALERT( at_console, "^3CHANGELEVEL:^7 %d %d\n", count2, count1 ); - if( count1 > 1 && count1 < count2 / 3 ) - return; + if( count1 > 1 && count1 < count2 / 3 ) + return; - //if( count1 <= 1 && count2 == 2 ) - // return; + //if( count1 <= 1 && count2 == 2 ) + // 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( m_fIsBack ) { - 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 ) + 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( count2 < 2 ) + } + 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( m_fSpawnSaved ) @@ -1790,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 ); @@ -1815,23 +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; - }*/ - - 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(); - - // 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 ); @@ -1875,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 ); - UTIL_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