#include <gWinZone.h>
Public Member Functions | |
gBaseZoneHack (eGrid *grid, const eCoord &pos) | |
local constructor | |
gBaseZoneHack (nMessage &m) | |
network constructor | |
~gBaseZoneHack () | |
destructor | |
Private Types | |
enum | State { State_Safe, State_Conquering, State_Conquered } |
possible states More... | |
typedef std::vector < tJUST_CONTROLLED_PTR< eTeam > > | TeamArray |
Private Member Functions | |
virtual bool | Timestep (REAL currentTime) |
simulates behaviour up to currentTime | |
virtual void | OnEnter (gCycle *target, REAL time) |
reacts on objects inside the zone | |
virtual void | OnVanish () |
called when the zone vanishes | |
virtual void | OnConquest () |
called when the zone gets conquered | |
virtual void | CheckSurvivor () |
checks for the only surviving zone | |
Static Private Member Functions | |
static void | CountZonesOfTeam (eGrid const *grid, eTeam *otherTeam, int &count, gBaseZoneHack *&farthest) |
counts the zones belonging to the given team. | |
Private Attributes | |
REAL | conquered_ |
conquest status; zero if it is free, 1 if it has been completely conquered by the enemy | |
int | enemiesInside_ |
count of enemies currently inside the zone | |
int | ownersInside_ |
count of owners currently inside the zone | |
bool | onlySurvivor_ |
flag set if this zone is the only survivor | |
TeamArray | enemies_ |
list of teams that currently have a player in the zone | |
REAL | lastEnemyContact_ |
last time an enemy player was in the zone | |
REAL | teamDistance_ |
distance to the closest member of the owning team | |
bool | touchy_ |
flag set when the zone is "touchy", which makes it get conquered on the slightest enemy touch | |
State | currentState_ |
the current state | |
REAL | lastSync_ |
time of the last sync request |
Definition at line 146 of file gWinZone.h.
typedef std::vector< tJUST_CONTROLLED_PTR< eTeam > > gBaseZoneHack::TeamArray [private] |
Definition at line 169 of file gWinZone.h.
enum gBaseZoneHack::State [private] |
possible states
State_Safe | not yet conquered |
State_Conquering | conquering in this frame |
State_Conquered | conquered |
Definition at line 178 of file gWinZone.h.
00179 { 00180 State_Safe, 00181 State_Conquering, 00182 State_Conquered 00183 };
gBaseZoneHack::gBaseZoneHack | ( | eGrid * | grid, | |
const eCoord & | pos | |||
) |
local constructor
grid | Grid to put the zone into | |
pos | Position to spawn the zone at |
Definition at line 729 of file gWinZone.cpp.
References conquered_, enemiesInside_, lastEnemyContact_, lastSync_, ownersInside_, se_GameTime(), and teamDistance_.
00730 :gZone( grid, pos), onlySurvivor_( false ), currentState_( State_Safe ) 00731 { 00732 enemiesInside_ = ownersInside_ = 0; 00733 conquered_ = 0; 00734 lastSync_ = -10; 00735 teamDistance_ = 0; 00736 lastEnemyContact_ = se_GameTime(); 00737 }
gBaseZoneHack::gBaseZoneHack | ( | nMessage & | m | ) |
network constructor
m | Message to read creation data from |
Definition at line 749 of file gWinZone.cpp.
References conquered_, enemiesInside_, lastEnemyContact_, lastSync_, ownersInside_, se_GameTime(), and teamDistance_.
00750 : gZone( m ), onlySurvivor_( false ), currentState_( State_Safe ) 00751 { 00752 enemiesInside_ = ownersInside_ = 0; 00753 conquered_ = 0; 00754 lastSync_ = -10; 00755 teamDistance_ = 0; 00756 lastEnemyContact_ = se_GameTime(); 00757 }
gBaseZoneHack::~gBaseZoneHack | ( | void | ) |
bool gBaseZoneHack::Timestep | ( | REAL | time | ) | [private, virtual] |
simulates behaviour up to currentTime
time | the current time |
Reimplemented from gZone.
Definition at line 837 of file gWinZone.cpp.
References tColor::b_, gZone::color_, conquered_, CountZonesOfTeam(), currentState_, ePlayerNetID::CurrentTeam(), gCycleMovement::distance, dt, eCoord, enemies_, enemiesInside_, tColor::g_, eGrid::GameObjects(), gZone::GetRadius(), gZone::GetRotationAcceleration(), gZone::GetRotationSpeed(), eGameObject::Grid(), lastEnemyContact_, lastSync_, eGameObject::lastTime, GrowingArrayBase::Len(), nCLIENT, nSERVER, NULL, OnConquest(), onlySurvivor_, ownersInside_, eNetGameObject::Player(), eGameObject::pos, eGameObject::Position(), tColor::r_, REAL, nNetObject::RequestSync(), gZone::SetExpansionSpeed(), gZone::SetReferenceTime(), gZone::SetRotationAcceleration(), gZone::SetRotationSpeed(), sg_baseZonesPerTeam, sg_conquestDecayRate, sg_conquestRate, sg_conquestTimeout, sg_DeclareWinner(), sg_defendRate, sg_onConquestScore, sg_segments, sn_ConsoleOut(), sn_GetNetState(), State_Conquered, State_Conquering, State_Safe, eGameObject::team, teamDistance_, eTeam::teams, and gZone::Timestep().
00838 { 00839 if ( currentState_ == State_Conquering ) 00840 { 00841 // let zone vanish 00842 SetReferenceTime(); 00843 SetExpansionSpeed( -GetRadius()*.5 ); 00844 SetRotationAcceleration( -GetRotationSpeed()*.4 ); 00845 RequestSync(); 00846 00847 currentState_ = State_Conquered; 00848 } 00849 00850 REAL dt = time - lastTime; 00851 00852 // conquest going on 00853 REAL conquest = sg_conquestRate * enemiesInside_ - sg_defendRate * ownersInside_ - sg_conquestDecayRate; 00854 conquered_ += dt * conquest; 00855 00856 // clamp 00857 if ( conquered_ < 0 ) 00858 { 00859 conquered_ = 0; 00860 conquest = 0; 00861 } 00862 if ( conquered_ > 1.01 ) 00863 { 00864 conquered_ = 1.01; 00865 conquest = 0; 00866 } 00867 00868 // set speed according to conquest status 00869 if ( currentState_ == State_Safe ) 00870 { 00871 REAL maxSpeed = 10 * ( 2 * 3.141 ) / sg_segments; 00872 REAL omega = .3 + conquered_ * conquered_ * maxSpeed; 00873 REAL omegaDot = 2 * conquered_ * conquest * maxSpeed; 00874 00875 // determine the time since the last sync (exaggerate for smoother motion in local games) 00876 REAL timeStep = lastTime - lastSync_; 00877 if ( sn_GetNetState() != nSERVER ) 00878 timeStep *= 100; 00879 00880 if ( sn_GetNetState() != nCLIENT && 00881 ( ( fabs( omega - GetRotationSpeed() ) + fabs( omegaDot - GetRotationAcceleration() ) ) * timeStep > .5 ) ) 00882 { 00883 SetRotationSpeed( omega ); 00884 SetRotationAcceleration( omegaDot ); 00885 SetReferenceTime(); 00886 RequestSync(); 00887 lastSync_ = lastTime; 00888 } 00889 00890 00891 // check for enemy contact timeout 00892 if ( sg_conquestTimeout > 0 && lastEnemyContact_ + sg_conquestTimeout < time ) 00893 { 00894 enemies_.clear(); 00895 00896 // if the zone would collapse without defenders, let it collapse now. A smart defender would 00897 // have left the zone to let it collapse anyway. 00898 if ( sg_conquestDecayRate < 0 ) 00899 { 00900 if ( team ) 00901 sn_ConsoleOut( tOutput( "$zone_collapse_harmless", team->Name() ) ); 00902 conquered_ = 1.0; 00903 } 00904 } 00905 00906 // check whether the zone got conquered 00907 if ( conquered_ >= 1 ) 00908 { 00909 currentState_ = State_Conquering; 00910 OnConquest(); 00911 } 00912 } 00913 00914 00915 // reset counts 00916 enemiesInside_ = ownersInside_ = 0; 00917 00918 // determine the owning team: the one that has a player spawned closest 00919 00920 // find the closest player 00921 if ( !team ) 00922 { 00923 teamDistance_ = 0; 00924 const tList<eGameObject>& gameObjects = Grid()->GameObjects(); 00925 gCycle * closest = NULL; 00926 REAL closestDistance = 0; 00927 for (int i=gameObjects.Len()-1;i>=0;i--) 00928 { 00929 gCycle *other=dynamic_cast<gCycle *>(gameObjects(i)); 00930 00931 if (other ) 00932 { 00933 eTeam * otherTeam = other->Player()->CurrentTeam(); 00934 eCoord otherpos = other->Position() - pos; 00935 REAL distance = otherpos.NormSquared(); 00936 if ( !closest || distance < closestDistance ) 00937 { 00938 // check whether other zones are already registered to that team 00939 gBaseZoneHack * farthest = NULL; 00940 int count = 0; 00941 if ( sg_baseZonesPerTeam > 0 ) 00942 CountZonesOfTeam( Grid(), otherTeam, count, farthest ); 00943 00944 // only set team if not too many closer other zones are registered 00945 if ( sg_baseZonesPerTeam == 0 || count < sg_baseZonesPerTeam || farthest->teamDistance_ > distance ) 00946 { 00947 closest = other; 00948 closestDistance = distance; 00949 } 00950 } 00951 } 00952 } 00953 00954 if ( closest ) 00955 { 00956 // take over team and color 00957 team = closest->Player()->CurrentTeam(); 00958 color_.r_ = team->R()/15.0; 00959 color_.g_ = team->G()/15.0; 00960 color_.b_ = team->B()/15.0; 00961 teamDistance_ = closestDistance; 00962 00963 RequestSync(); 00964 } 00965 00966 // if this zone does not belong to a team, discard it. 00967 if ( !team ) 00968 { 00969 return true; 00970 } 00971 00972 // check other zones owned by the same team. Discard the one farthest away 00973 // if the max count is exceeded 00974 if ( team && sg_baseZonesPerTeam > 0 ) 00975 { 00976 gBaseZoneHack * farthest = 0; 00977 int count = 0; 00978 CountZonesOfTeam( Grid(), team, count, farthest ); 00979 00980 // discard team of farthest zone 00981 if ( count > sg_baseZonesPerTeam ) 00982 farthest->team = NULL; 00983 } 00984 } 00985 00986 00987 // delegate 00988 bool ret = gZone::Timestep( time ); 00989 00990 // reward survival 00991 if ( !ret && onlySurvivor_ ) 00992 { 00993 const char* message= ( eTeam::teams.Len() > 2 || sg_onConquestScore ) ? "$player_win_survive" : "$player_win_conquest"; 00994 sg_DeclareWinner( team, message ); 00995 } 00996 00997 return ret; 00998 }
reacts on objects inside the zone
target | the cycle that has been found inside the zone | |
time | the current time |
Reimplemented from gZone.
Definition at line 1167 of file gWinZone.cpp.
References currentState_, ePlayerNetID::CurrentTeam(), enemies_, enemiesInside_, lastEnemyContact_, ownersInside_, eNetGameObject::Player(), State_Safe, tASSERT, and eGameObject::team.
01168 { 01169 // determine the team of the player 01170 tASSERT( target ); 01171 if ( !target->Player() ) 01172 return; 01173 tJUST_CONTROLLED_PTR< eTeam > otherTeam = target->Player()->CurrentTeam(); 01174 if (!otherTeam) 01175 return; 01176 if ( currentState_ != State_Safe ) 01177 return; 01178 01179 // remember who is inside 01180 if ( team == otherTeam ) 01181 { 01182 ++ ownersInside_; 01183 } 01184 else if ( team ) 01185 { 01186 if ( enemiesInside_ == 0 ) 01187 enemies_.clear(); 01188 01189 ++ enemiesInside_; 01190 if ( std::find( enemies_.begin(), enemies_.end(), otherTeam ) == enemies_.end() ) 01191 enemies_.push_back( otherTeam ); 01192 01193 lastEnemyContact_ = time; 01194 } 01195 }
void gBaseZoneHack::OnVanish | ( | void | ) | [private, virtual] |
called when the zone vanishes
Reimplemented from gZone.
Definition at line 1009 of file gWinZone.cpp.
References eGameObject::Alive(), CheckSurvivor(), currentState_, gCycleMovement::distance, eCoord, enemies_, ePlayerNetID::GetName(), eGameObject::Kill(), NULL, ePlayerNetID::Object(), eGameObject::pos, REAL, sg_defendRate, sg_onConquestKillMin, sg_onConquestKillRatio, sn_ConsoleOut(), State_Safe, and eGameObject::team.
01010 { 01011 if (!team) 01012 return; 01013 01014 CheckSurvivor(); 01015 01016 // kill the closest owners of the zone 01017 if ( currentState_ != State_Safe && ( enemies_.size() > 0 || sg_defendRate < 0 ) ) 01018 { 01019 int kills = int( sg_onConquestKillRatio * team->NumPlayers() ); 01020 kills = kills > sg_onConquestKillMin ? kills : sg_onConquestKillMin; 01021 01022 while ( kills > 0 ) 01023 { 01024 -- kills; 01025 01026 ePlayerNetID * closest = NULL; 01027 REAL closestDistance = 0; 01028 01029 // find the closest living owner 01030 for ( int i = team->NumPlayers()-1; i >= 0; --i ) 01031 { 01032 ePlayerNetID * player = team->Player(i); 01033 eNetGameObject * object = player->Object(); 01034 if ( object && object->Alive() ) 01035 { 01036 eCoord otherpos = object->Position() - pos; 01037 REAL distance = otherpos.NormSquared(); 01038 if ( !closest || distance < closestDistance ) 01039 { 01040 closest = player; 01041 closestDistance = distance; 01042 } 01043 } 01044 } 01045 01046 if ( closest ) 01047 { 01048 sn_ConsoleOut( tOutput("$player_kill_collapse", closest->GetName() ) ); 01049 closest->Object()->Kill(); 01050 } 01051 } 01052 } 01053 }
void gBaseZoneHack::OnConquest | ( | void | ) | [private, virtual] |
called when the zone gets conquered
Definition at line 1064 of file gWinZone.cpp.
References eTeam::Alive(), CheckSurvivor(), enemies_, enemiesInside_, score, tOutput::SetTemplateParameter(), sg_DeclareWinner(), sg_onConquestScore, sg_onConquestWin, and eGameObject::team.
Referenced by Timestep().
01065 { 01066 // calculate score. If nobody really was inside the zone any more, half it. 01067 int totalScore = sg_onConquestScore; 01068 if ( 0 == enemiesInside_ ) 01069 totalScore /= 2; 01070 01071 // eliminate dead enemies 01072 TeamArray enemiesAlive; 01073 for ( TeamArray::iterator iter = enemies_.begin(); iter != enemies_.end(); ++iter ) 01074 { 01075 eTeam* team = *iter; 01076 if ( team->Alive() ) 01077 enemiesAlive.push_back( team ); 01078 } 01079 enemies_ = enemiesAlive; 01080 01081 // add score for successful conquest, divided equally between the teams that are 01082 // inside the zone 01083 if ( totalScore && enemies_.size() > 0 ) 01084 { 01085 tOutput win; 01086 if ( team ) 01087 { 01088 win.SetTemplateParameter( 3, team->Name() ); 01089 win << "$player_win_conquest_specific"; 01090 } 01091 else 01092 { 01093 win << "$player_win_conquest"; 01094 } 01095 01096 int score = totalScore / enemies_.size(); 01097 for ( TeamArray::iterator iter = enemies_.begin(); iter != enemies_.end(); ++iter ) 01098 { 01099 (*iter)->AddScore( score, win, tOutput() ); 01100 } 01101 } 01102 01103 // trigger immediate win 01104 if ( sg_onConquestWin && enemies_.size() > 0 ) 01105 { 01106 static const char* message="$player_win_conquest"; 01107 sg_DeclareWinner( enemies_[0], message ); 01108 } 01109 01110 CheckSurvivor(); 01111 }
void gBaseZoneHack::CheckSurvivor | ( | void | ) | [private, virtual] |
checks for the only surviving zone
Definition at line 1126 of file gWinZone.cpp.
References currentState_, eGrid::GameObjects(), eGameObject::Grid(), GrowingArrayBase::Len(), onlySurvivor_, sg_onSurviveWin, State_Safe, and eGameObject::team.
Referenced by OnConquest(), and OnVanish().
01127 { 01128 // test if there is only one team with non-conquered zones left 01129 if ( sg_onSurviveWin ) 01130 { 01131 // find surviving team and test whether it is the only one 01132 gBaseZoneHack * survivor = 0; 01133 bool onlySurvivor = true; 01134 01135 const tList<eGameObject>& gameObjects = Grid()->GameObjects(); 01136 for (int i=gameObjects.Len()-1;i>=0 && onlySurvivor;i--){ 01137 gBaseZoneHack *other=dynamic_cast<gBaseZoneHack *>(gameObjects(i)); 01138 01139 if ( other && other->currentState_ == State_Safe && other->team ) 01140 { 01141 if ( survivor && survivor->team != other->team ) 01142 onlySurvivor = false; 01143 else 01144 survivor = other; 01145 } 01146 } 01147 01148 // reward it later 01149 if ( onlySurvivor && survivor ) 01150 { 01151 survivor->onlySurvivor_ = true; 01152 } 01153 } 01154 }
void gBaseZoneHack::CountZonesOfTeam | ( | eGrid const * | grid, | |
eTeam * | otherTeam, | |||
int & | count, | |||
gBaseZoneHack *& | farthest | |||
) | [static, private] |
counts the zones belonging to the given team.
Definition at line 806 of file gWinZone.cpp.
References eGrid::GameObjects(), GrowingArrayBase::Len(), NULL, eGameObject::Team(), and teamDistance_.
Referenced by Timestep().
00807 { 00808 count = 0; 00809 farthest = NULL; 00810 00811 // check whether other zones are already registered to that team 00812 const tList<eGameObject>& gameObjects = grid->GameObjects(); 00813 for (int j=gameObjects.Len()-1;j>=0;j--) 00814 { 00815 gBaseZoneHack *otherZone=dynamic_cast<gBaseZoneHack *>(gameObjects(j)); 00816 00817 if ( otherZone && otherTeam == otherZone->Team() ) 00818 { 00819 count++; 00820 if ( !farthest || otherZone->teamDistance_ > farthest->teamDistance_ ) 00821 farthest = otherZone; 00822 } 00823 } 00824 }
REAL gBaseZoneHack::conquered_ [private] |
conquest status; zero if it is free, 1 if it has been completely conquered by the enemy
Definition at line 163 of file gWinZone.h.
Referenced by gBaseZoneHack(), and Timestep().
int gBaseZoneHack::enemiesInside_ [private] |
count of enemies currently inside the zone
Definition at line 164 of file gWinZone.h.
Referenced by gBaseZoneHack(), OnConquest(), OnEnter(), and Timestep().
int gBaseZoneHack::ownersInside_ [private] |
count of owners currently inside the zone
Definition at line 165 of file gWinZone.h.
Referenced by gBaseZoneHack(), OnEnter(), and Timestep().
bool gBaseZoneHack::onlySurvivor_ [private] |
flag set if this zone is the only survivor
Definition at line 167 of file gWinZone.h.
Referenced by CheckSurvivor(), and Timestep().
TeamArray gBaseZoneHack::enemies_ [private] |
list of teams that currently have a player in the zone
Definition at line 170 of file gWinZone.h.
Referenced by OnConquest(), OnEnter(), OnVanish(), and Timestep().
REAL gBaseZoneHack::lastEnemyContact_ [private] |
last time an enemy player was in the zone
Definition at line 171 of file gWinZone.h.
Referenced by gBaseZoneHack(), OnEnter(), and Timestep().
REAL gBaseZoneHack::teamDistance_ [private] |
distance to the closest member of the owning team
Definition at line 173 of file gWinZone.h.
Referenced by CountZonesOfTeam(), gBaseZoneHack(), and Timestep().
bool gBaseZoneHack::touchy_ [private] |
flag set when the zone is "touchy", which makes it get conquered on the slightest enemy touch
Definition at line 175 of file gWinZone.h.
State gBaseZoneHack::currentState_ [private] |
the current state
Definition at line 184 of file gWinZone.h.
Referenced by CheckSurvivor(), OnEnter(), OnVanish(), and Timestep().
REAL gBaseZoneHack::lastSync_ [private] |
time of the last sync request
Definition at line 186 of file gWinZone.h.
Referenced by gBaseZoneHack(), and Timestep().