diff --git a/releases/3.2.0/listenserver.cfg b/releases/3.2.0/listenserver.cfg index 35d7cb16..18812e71 100644 --- a/releases/3.2.0/listenserver.cfg +++ b/releases/3.2.0/listenserver.cfg @@ -72,6 +72,9 @@ sv_clienttrace 3.5 /////////////////////////////// sv_lan 0 +// Forces a limit on structures on the server +sv_structurelimit 300 + // disable clients' ability to pause the server pausable 0 diff --git a/releases/3.2.0/server.cfg b/releases/3.2.0/server.cfg index 82244143..659a0337 100644 --- a/releases/3.2.0/server.cfg +++ b/releases/3.2.0/server.cfg @@ -84,6 +84,9 @@ mp_timelimit 60 /////////////////////////////// sv_lan 0 +// Forces a limit on structures on the server +sv_structurelimit 300 + // disable clients' ability to pause the server pausable 0 diff --git a/releases/3.2.0/source/dlls/game.cpp b/releases/3.2.0/source/dlls/game.cpp index 03dda7ab..7ce5440c 100644 --- a/releases/3.2.0/source/dlls/game.cpp +++ b/releases/3.2.0/source/dlls/game.cpp @@ -110,6 +110,7 @@ cvar_t avh_team1damagepercent = {kvTeam1DamagePercent, "100", FCVAR_SERVER} cvar_t avh_team2damagepercent = {kvTeam2DamagePercent, "100", FCVAR_SERVER}; cvar_t avh_team3damagepercent = {kvTeam3DamagePercent, "100", FCVAR_SERVER}; cvar_t avh_team4damagepercent = {kvTeam4DamagePercent, "100", FCVAR_SERVER}; +cvar_t avh_structurelimit = {kvStructureLimit, "300", FCVAR_SERVER}; cvar_t avh_votecasttime = {kvVoteCastTime, "2", FCVAR_SERVER}; cvar_t avh_votedowntime = {kvVoteDownTime, "180", FCVAR_SERVER}; cvar_t avh_minvotesneeded = {kvMinVotesNeeded, "2", FCVAR_SERVER}; @@ -602,6 +603,7 @@ void GameDLLInit( void ) CVAR_REGISTER (&avh_team2damagepercent); CVAR_REGISTER (&avh_team3damagepercent); CVAR_REGISTER (&avh_team4damagepercent); + CVAR_REGISTER (&avh_structurelimit); CVAR_REGISTER (&avh_votecasttime); CVAR_REGISTER (&avh_votedowntime); CVAR_REGISTER (&avh_minvotesneeded); diff --git a/releases/3.2.0/source/mod/AvHGamerules.cpp b/releases/3.2.0/source/mod/AvHGamerules.cpp index b62d422d..b786ea9b 100644 --- a/releases/3.2.0/source/mod/AvHGamerules.cpp +++ b/releases/3.2.0/source/mod/AvHGamerules.cpp @@ -332,6 +332,7 @@ AvHGamerules::AvHGamerules() : mTeamA(TEAM_ONE), mTeamB(TEAM_TWO) RegisterServerVariable(kvTeam3DamagePercent); RegisterServerVariable(kvTeam4DamagePercent); RegisterServerVariable("sv_cheats"); + RegisterServerVariable(kvStructureLimit); g_VoiceGameMgr.Init(&gVoiceHelper, gpGlobals->maxClients); diff --git a/releases/3.2.0/source/mod/AvHPlayer.cpp b/releases/3.2.0/source/mod/AvHPlayer.cpp index 4e176be7..7ac2dfd2 100644 --- a/releases/3.2.0/source/mod/AvHPlayer.cpp +++ b/releases/3.2.0/source/mod/AvHPlayer.cpp @@ -236,6 +236,7 @@ #include "mod/AvHSelectionHelper.h" #include "mod/AvHPlayerUpgrade.h" #include "mod/AvHSharedUtil.h" +#include "mod/AvHServerUtil.h" #include "mod/AvHDramaticPriority.h" #include "mod/AvHHulls.h" #include "mod/AvHMovementUtil.h" @@ -269,6 +270,8 @@ extern int gWeaponAnimationEventID; extern int gMetabolizeSuccessEventID; extern int gPhaseInEventID; +extern cvar_t avh_structurelimit; + // Yucky globals extern AvHParticleTemplateListServer gParticleTemplateList; extern AvHSoundListManager gSoundListManager; @@ -470,16 +473,10 @@ bool AvHPlayer::AttemptToBuildAlienStructure(AvHMessageID inMessageID) char* theClassName = NULL; if(AvHSHUGetBuildTechClassName(inMessageID, theClassName)) { - // Make sure we haven't exceeded the limit - int theNumBuildings = 0; - FOR_ALL_ENTITIES(theClassName, CBaseEntity*) - if(theEntity->pev->team == this->pev->team) - { - theNumBuildings++; - } - END_FOR_ALL_ENTITIES(theClassName); - - // Now check to make sure the space is big enough to hold the building + // Make sure we haven't exceeded the structure limit + int theNumBuildings = AvHSUGetStructureCount(inMessageID); + + // Now check to make sure the space is big enough to hold the building UTIL_MakeVectors(this->pev->v_angle); const int kAimRange = 48; @@ -495,36 +492,43 @@ bool AvHPlayer::AttemptToBuildAlienStructure(AvHMessageID inMessageID) // Check if collision point is valid for building if(AvHSHUGetIsSiteValidForBuild(inMessageID, &theLocation)) { - // Make sure there aren't too many buildings in this area already - int theNumBuildingsNearby = UTIL_CountEntitiesInSphere(theLocation, BALANCE_VAR(kBuildingVisibilityRadius), theClassName); - if(theNumBuildingsNearby < BALANCE_VAR(kNumSameAlienStructuresAllowedInRadius) || FStrEq(theClassName, kwsAlienResourceTower))//voogru: allow the building of rt's regardless of how many may be close by (for maps that have a lot of nodes close to each other) - { - // Create the new building - CBaseEntity* theEntity = CBaseEntity::Create(theClassName, theLocation, AvHSUGetRandomBuildingAngles()); - - // Set building's team - theEntity->pev->team = this->pev->team; - - AvHSUBuildingJustCreated(inMessageID, theEntity, this); - - // Set owner (this prevents collisions between the entity and it's owner though) - //theEntity->pev->owner = ENT(this->pev); + if (theNumBuildings < avh_structurelimit.value) + { + // Make sure there aren't too many buildings in this area already + int theNumBuildingsNearby = UTIL_CountEntitiesInSphere(theLocation, BALANCE_VAR(kBuildingVisibilityRadius), theClassName); + if(theNumBuildingsNearby < BALANCE_VAR(kNumSameAlienStructuresAllowedInRadius) || FStrEq(theClassName, kwsAlienResourceTower))//voogru: allow the building of rt's regardless of how many may be close by (for maps that have a lot of nodes close to each other) + { + // Create the new building + CBaseEntity* theEntity = CBaseEntity::Create(theClassName, theLocation, AvHSUGetRandomBuildingAngles()); + + // Set building's team + theEntity->pev->team = this->pev->team; + + AvHSUBuildingJustCreated(inMessageID, theEntity, this); + + // Set owner (this prevents collisions between the entity and it's owner though) + //theEntity->pev->owner = ENT(this->pev); - //voogru: I've moved this here because whats the point of playing the sound if the building didnt get placed? (it was after " Vector theLocation = theTR.vecEndPos;") - // Play sound - char* theSoundEffect = kAlienBuildingSound1; + //voogru: I've moved this here because whats the point of playing the sound if the building didnt get placed? (it was after " Vector theLocation = theTR.vecEndPos;") + // Play sound + char* theSoundEffect = kAlienBuildingSound1; - if(RANDOM_LONG(0, 1) == 1) - theSoundEffect = kAlienBuildingSound2; + if(RANDOM_LONG(0, 1) == 1) + theSoundEffect = kAlienBuildingSound2; - EMIT_SOUND(this->edict(), CHAN_AUTO, theSoundEffect, this->GetAlienAdjustedEventVolume(), ATTN_NORM); - - theSuccess = true; - } - else - { - this->SendMessage(kTooManyStructuresOfThisTypeNearby); - } + EMIT_SOUND(this->edict(), CHAN_AUTO, theSoundEffect, this->GetAlienAdjustedEventVolume(), ATTN_NORM); + + theSuccess = true; + } + else + { + this->SendMessage(kTooManyStructuresOfThisTypeNearby); + } + } + else + { + this->SendMessage(kTooManyStructuresOnServer); + } } else { @@ -597,32 +601,42 @@ bool AvHPlayer::BuildTech(AvHMessageID inBuildID, const Vector& inPickRay) } } - if(theNumFriendlyEntitiesInArea < BALANCE_VAR(kMaxMarineEntitiesAllowedInRadius)) - { - // Build it! - theSuccess = (AvHSUBuildTechForPlayer(inBuildID, theLocation, this) != NULL); - - // Inform structure about build if possible - if(theSuccess) - { - if(this->mSelected.size() > 0) - { - // Get selected structure and inform - int theFirstEntitySelected = *this->mSelected.begin(); - AvHBaseBuildable* theBaseBuildable = dynamic_cast(CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theFirstEntitySelected))); - if(theBaseBuildable) - { - theBaseBuildable->TechnologyBuilt(inBuildID); - } - } + // Make sure we haven't exceeded the structure limit + int theNumBuildings = AvHSUGetStructureCount(inBuildID); - this->PayPurchaseCost(theCost); - } - } - else - { - this->SendMessage(kTooManyStructuresInArea); - } + if(theNumBuildings < avh_structurelimit.value) + { + if(theNumFriendlyEntitiesInArea < BALANCE_VAR(kMaxMarineEntitiesAllowedInRadius)) + { + // Build it! + theSuccess = (AvHSUBuildTechForPlayer(inBuildID, theLocation, this) != NULL); + + // Inform structure about build if possible + if(theSuccess) + { + if(this->mSelected.size() > 0) + { + // Get selected structure and inform + int theFirstEntitySelected = *this->mSelected.begin(); + AvHBaseBuildable* theBaseBuildable = dynamic_cast(CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theFirstEntitySelected))); + if(theBaseBuildable) + { + theBaseBuildable->TechnologyBuilt(inBuildID); + } + } + + this->PayPurchaseCost(theCost); + } + } + else + { + this->SendMessage(kTooManyStructuresInArea); + } + } + else + { + this->SendMessage(kTooManyStructuresOnServer); + } } else { diff --git a/releases/3.2.0/source/mod/AvHServerUtil.cpp b/releases/3.2.0/source/mod/AvHServerUtil.cpp index 4558af8c..4252adb9 100644 --- a/releases/3.2.0/source/mod/AvHServerUtil.cpp +++ b/releases/3.2.0/source/mod/AvHServerUtil.cpp @@ -389,6 +389,51 @@ void AvHSUBuildingJustCreated(AvHMessageID inBuildID, CBaseEntity* theBuilding, } } +// Gets the build count for the given message +int AvHSUGetStructureCount(AvHMessageID inMessageID) +{ + int theNumBuildings = 0; + switch (inMessageID) + { + case ALIEN_BUILD_OFFENSE_CHAMBER: + case ALIEN_BUILD_DEFENSE_CHAMBER: + case ALIEN_BUILD_SENSORY_CHAMBER: + case ALIEN_BUILD_MOVEMENT_CHAMBER: + case BUILD_INFANTRYPORTAL: + case BUILD_TURRET_FACTORY: + case BUILD_TURRET: + case BUILD_SIEGE: + case BUILD_ARMORY: + case BUILD_ARMSLAB: + case BUILD_PROTOTYPE_LAB: + case BUILD_OBSERVATORY: + case BUILD_PHASEGATE: + FOR_ALL_BASEENTITIES() + switch(theBaseEntity->pev->iuser3) + { + case AVH_USER3_DEFENSE_CHAMBER: + case AVH_USER3_MOVEMENT_CHAMBER: + case AVH_USER3_OFFENSE_CHAMBER: + case AVH_USER3_SENSORY_CHAMBER: + case AVH_USER3_INFANTRYPORTAL: + case AVH_USER3_TURRET_FACTORY: + case AVH_USER3_ADVANCED_TURRET_FACTORY: + case AVH_USER3_SIEGETURRET: + case AVH_USER3_TURRET: + case AVH_USER3_ARMORY: + case AVH_USER3_ADVANCED_ARMORY: + case AVH_USER3_ARMSLAB: + case AVH_USER3_PROTOTYPE_LAB: + case AVH_USER3_OBSERVATORY: + case AVH_USER3_PHASEGATE: + theNumBuildings++; + break; + } + END_FOR_ALL_BASEENTITIES(); + } + return theNumBuildings; +} + CBaseEntity* AvHSUBuildTechForPlayer(AvHMessageID inBuildID, const Vector& inLocation, AvHPlayer* inPlayer) { CBaseEntity* theEntity = NULL; diff --git a/releases/3.2.0/source/mod/AvHServerUtil.h b/releases/3.2.0/source/mod/AvHServerUtil.h index b26fec29..43121ad6 100644 --- a/releases/3.2.0/source/mod/AvHServerUtil.h +++ b/releases/3.2.0/source/mod/AvHServerUtil.h @@ -140,6 +140,7 @@ void AvHSUPushbackPlayersTouchingPlayer(AvHPlayer* inPlayer, entvars_t* inInflic void AvHSUKillPlayersTouchingPlayer(AvHPlayer* inPlayer, entvars_t* inInflictor); void AvHSUKillBuildablesTouchingPlayer(AvHPlayer* inPlayer, entvars_t* inInflictor); void AvHSUBuildingJustCreated(AvHMessageID inBuildID, CBaseEntity* theBuilding, AvHPlayer* inPlayer); +int AvHSUGetStructureCount(AvHMessageID inMessageID); CBaseEntity* AvHSUBuildTechForPlayer(AvHMessageID inBuildID, const Vector& inLocation, AvHPlayer* inPlayer); diff --git a/releases/3.2.0/source/mod/AvHServerVariables.h b/releases/3.2.0/source/mod/AvHServerVariables.h index 83bf4561..ba6cdb39 100644 --- a/releases/3.2.0/source/mod/AvHServerVariables.h +++ b/releases/3.2.0/source/mod/AvHServerVariables.h @@ -86,6 +86,7 @@ extern cvar_t avh_tournamentmode; #define kvTeam2DamagePercent "mp_team2damagepercent" #define kvTeam3DamagePercent "mp_team3damagepercent" #define kvTeam4DamagePercent "mp_team4damagepercent" +#define kvStructureLimit "sv_structurelimit" #define kvSpawnInvulnerableTime "mp_spawninvulnerabletime" #define kvVoteCastTime "mp_votecasttime" #define kvVoteDownTime "mp_votedowntime" diff --git a/releases/3.2.0/source/mod/AvHTitles.h b/releases/3.2.0/source/mod/AvHTitles.h index df162663..a37bdf64 100644 --- a/releases/3.2.0/source/mod/AvHTitles.h +++ b/releases/3.2.0/source/mod/AvHTitles.h @@ -94,6 +94,7 @@ #define kUpgradeNotAvailable "UpgradeNotAvailable" #define kTooManyStructuresInArea "TooManyStructuresInArea" #define kTooManyStructuresOfThisTypeNearby "TooManyStructuresOfThisTypeNearby" +#define kTooManyStructuresOnServer "TooManyStructuresOnServer" #define kTooManyWebs "TooManyWebs" #define kTooManyWebsNearby "TooManyWebsNearby" diff --git a/releases/3.2.0/titles.txt b/releases/3.2.0/titles.txt index 68e95d5b..862ab4a8 100644 --- a/releases/3.2.0/titles.txt +++ b/releases/3.2.0/titles.txt @@ -1576,6 +1576,11 @@ TooManyStructuresOfThisTypeNearby There are too many structures of this type nearby. } +TooManyStructuresOnServer +{ +Server's structure limit exceeded. +} + TooManyStructuresInArea { There are too many structures nearby.