src/tron/gWinZone.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023   
00024 ***************************************************************************
00025 
00026 */
00027 
00028 #include "rSDL.h"
00029 
00030 #include "gWinZone.h"
00031 #include "eFloor.h"
00032 #include "eTimer.h"
00033 #include "eGrid.h"
00034 #include "gCycle.h"
00035 #include "gGame.h"
00036 #include "eTeam.h"
00037 #include "ePlayer.h"
00038 #include "rRender.h"
00039 #include "nConfig.h"
00040 #include "tString.h"
00041 #include "rScreen.h"
00042 #include "eSoundMixer.h"
00043 
00044 #include <time.h>
00045 #include <algorithm>
00046 #include <functional>
00047 #include <deque>
00048 
00049 std::deque<gZone *> sg_Zones;
00050 
00051 static int sg_zoneDeath = 1;
00052 static tSettingItem<int> sg_zoneDeathConf( "WIN_ZONE_DEATHS", sg_zoneDeath );
00053 
00054 REAL sg_expansionSpeed = 1.0f;
00055 REAL sg_initialSize = 5.0f;
00056 
00057 static nSettingItem< REAL > sg_expansionSpeedConf( "WIN_ZONE_EXPANSION", sg_expansionSpeed );
00058 static nSettingItem< REAL > sg_initialSizeConf( "WIN_ZONE_INITIAL_SIZE", sg_initialSize );
00059 
00061 gZone * sg_CreateWinDeathZone( eGrid * grid, const eCoord & pos )
00062 {
00063     gZone * ret = NULL;
00064     if ( sg_zoneDeath )
00065     {
00066         ret = tNEW( gDeathZoneHack( grid, pos ) );
00067         sn_ConsoleOut( "$instant_death_activated" );
00068     }
00069     else
00070     {
00071         ret = tNEW( gWinZoneHack( grid, pos ) );
00072         sn_ConsoleOut( "$instant_win_activated" );
00073     }
00074 
00075     // initialize radius and expansion speed
00076     static_cast<eGameObject*>(ret)->Timestep( se_GameTime() );
00077     ret->SetReferenceTime();
00078     ret->SetRadius( sg_initialSize );
00079     ret->SetExpansionSpeed( sg_expansionSpeed );
00080     ret->SetRotationSpeed( .3f );
00081 
00082     return ret;
00083 }
00084 
00085 // number of segments to render a zone with
00086 static const int sg_segments = 11;
00087 
00088 // *******************************************************************************
00089 // *
00090 // *   EvaluateFunctionNow
00091 // *
00092 // *******************************************************************************
00097 // *******************************************************************************
00098 
00099 inline REAL gZone::EvaluateFunctionNow( tFunction const & f ) const
00100 {
00101     return f( lastTime - referenceTime_ );
00102 }
00103 
00104 // *******************************************************************************
00105 // *
00106 // *   SetFunctionNow
00107 // *
00108 // *******************************************************************************
00113 // *******************************************************************************
00114 
00115 inline void gZone::SetFunctionNow( tFunction & f, REAL value ) const
00116 {
00117     f.SetOffset( value + f.GetSlope() * ( referenceTime_ - lastTime ) );
00118 }
00119 
00120 // *******************************************************************************
00121 // *
00122 // *    gZone
00123 // *
00124 // *******************************************************************************
00129 // *******************************************************************************
00130 
00131 gZone::gZone( eGrid * grid, const eCoord & pos )
00132         :eNetGameObject( grid, pos, eCoord( 0,0 ), NULL, true ), rotation_(1,0)
00133 {
00134     // store creation time
00135     referenceTime_ = createTime_ = lastTime = 0;
00136 
00137     // add to game grid
00138     this->AddToList();
00139 
00140     sg_Zones.push_back(this);
00141 
00142     // initialize position functions
00143     SetPosition( pos );
00144     eSoundMixer* mixer = eSoundMixer::GetMixer();
00145     mixer->PushButton(ZONE_SPAWN, pos);
00146 }
00147 
00148 // *******************************************************************************
00149 // *
00150 // *    gZone
00151 // *
00152 // *******************************************************************************
00156 // *******************************************************************************
00157 
00158 gZone::gZone( nMessage & m )
00159         :eNetGameObject( m ), rotation_(1,0)
00160 {
00161     // read creation time
00162     m >> createTime_;
00163     referenceTime_ = lastTime = createTime_;
00164 
00165     // initialize color to white, ReadSync will fill in the true value if available
00166     color_.r_ = color_.g_ = color_.b_ = 1.0f;
00167 
00168     // add to game grid
00169     this->AddToList();
00170 
00171     sg_Zones.push_back(this);
00172 
00173     // initialize position functions
00174     SetPosition( pos );
00175     eSoundMixer* mixer = eSoundMixer::GetMixer();
00176     mixer->PushButton(ZONE_SPAWN, pos);
00177 }
00178 
00179 // *******************************************************************************
00180 // *
00181 // *    ~gZone
00182 // *
00183 // *******************************************************************************
00186 // *******************************************************************************
00187 
00188 gZone::~gZone( void )
00189 {
00190     sg_Zones.erase(
00191         std::find_if(
00192             sg_Zones.begin(),
00193             sg_Zones.end(),
00194             std::bind2nd(
00195                 std::equal_to<gZone *>(),
00196                 this)
00197         )
00198     );
00199 }
00200 
00201 // *******************************************************************************
00202 // *
00203 // *    WriteCreate
00204 // *
00205 // *******************************************************************************
00209 // *******************************************************************************
00210 
00211 void gZone::WriteCreate( nMessage & m )
00212 {
00213     // delegate
00214     eNetGameObject::WriteCreate( m );
00215 
00216     m << createTime_;
00217 }
00218 
00219 // *******************************************************************************
00220 // *
00221 // *    WriteSync
00222 // *
00223 // *******************************************************************************
00227 // *******************************************************************************
00228 
00229 void gZone::WriteSync( nMessage & m )
00230 {
00231     // delegate
00232     eNetGameObject::WriteSync( m );
00233 
00234     // write color
00235     m << color_.r_;
00236     m << color_.g_;
00237     m << color_.b_;
00238 
00239     // write reference time and functions
00240     m << referenceTime_;
00241     m << posx_;
00242     m << posy_;
00243     m << radius_;
00244 
00245     // write rotation speed
00246     m << rotationSpeed_;
00247 }
00248 
00249 // *******************************************************************************
00250 // *
00251 // *    ReadSync
00252 // *
00253 // *******************************************************************************
00257 // *******************************************************************************
00258 
00259 void gZone::ReadSync( nMessage & m )
00260 {
00261     // delegage
00262     eNetGameObject::ReadSync( m );
00263 
00264     // read color
00265     if (!m.End())
00266     {
00267         m >> color_.r_;
00268         m >> color_.g_;
00269         m >> color_.b_;
00270         se_MakeColorValid(color_.r_, color_.g_, color_.b_, 1.0f);
00271     }
00272 
00273     // read reference time and functions
00274     if (!m.End())
00275     {
00276         m >> referenceTime_;
00277         m >> posx_;
00278         m >> posy_;
00279         m >> radius_;
00280     }
00281     else
00282     {
00283         referenceTime_ = createTime_;
00284 
00285         // take old default values
00286         this->radius_.SetOffset( sg_initialSize );
00287         this->radius_.SetSlope( sg_expansionSpeed );
00288         SetPosition( pos );
00289         SetVelocity( eCoord() );
00290     }
00291 
00292     // read rotation speed
00293     if (!m.End())
00294     {
00295         m >> rotationSpeed_;
00296     }
00297     else
00298     {
00299         // set fixed values
00300         SetRotationSpeed( .3f );
00301         SetRotationAcceleration( 0.0f );
00302     }
00303 }
00304 
00305 // *******************************************************************************
00306 // *
00307 // *    Timestep
00308 // *
00309 // *******************************************************************************
00313 // *******************************************************************************
00314 
00315 bool gZone::Timestep( REAL time )
00316 {
00317     // rotate
00318     REAL speed = GetRotationSpeed();
00319     REAL angle = ( time - lastTime ) * speed;
00320     // angle /= ( 1 + 2 * 3.14159 * angle/sg_segments );
00321     rotation_ = rotation_.Turn( cos( angle ), sin( angle ) );
00322 
00323     // move to new position
00324     REAL dt = time - referenceTime_;
00325     Move( eCoord( posx_( dt ), posy_( dt ) ), lastTime, time );
00326 
00327     // update time
00328     lastTime = time;
00329 
00330     // kill this zone if it shrunk down to zero radius
00331     if ( GetExpansionSpeed() < 0 && GetRadius() <= 0 )
00332     {
00333         OnVanish();
00334         return true;
00335     }
00336 
00337     return false;
00338 }
00339 
00340 // *******************************************************************************
00341 // *
00342 // *    OnVanish
00343 // *
00344 // *******************************************************************************
00347 // *******************************************************************************
00348 
00349 void gZone::OnVanish( void )
00350 {
00351 }
00352 
00353 // *******************************************************************************
00354 // *
00355 // *    InteractWith
00356 // *
00357 // *******************************************************************************
00363 // *******************************************************************************
00364 
00365 void gZone::InteractWith( eGameObject * target, REAL time, int recursion )
00366 {
00367     gCycle* prey = dynamic_cast< gCycle* >( target );
00368     if ( prey )
00369     {
00370         REAL r = this->Radius();
00371         if ( ( prey->Position() - this->Position() ).NormSquared() < r*r )
00372         {
00373             if ( prey->Player() && prey->Alive() )
00374             {
00375                 OnEnter( prey, time );
00376             }
00377         }
00378     }
00379 }
00380 
00381 // *******************************************************************************
00382 // *
00383 // *    OnEnter
00384 // *
00385 // *******************************************************************************
00390 // *******************************************************************************
00391 
00392 void gZone::OnEnter( gCycle * target, REAL time )
00393 {
00394 }
00395 
00396 // the zone's network initializator
00397 static nNOInitialisator<gZone> zone_init(340,"zone");
00398 
00399 // *******************************************************************************
00400 // *
00401 // *    CreatorDescriptor
00402 // *
00403 // *******************************************************************************
00407 // *******************************************************************************
00408 
00409 nDescriptor & gZone::CreatorDescriptor( void ) const
00410 {
00411     return zone_init;
00412 }
00413 
00414 // *******************************************************************************
00415 // *
00416 // *    Radius
00417 // *
00418 // *******************************************************************************
00422 // *******************************************************************************
00423 
00424 REAL gZone::Radius( void ) const
00425 {
00426     return GetRadius();
00427 }
00428 
00429 // *******************************************************************************
00430 // *
00431 // *    Render
00432 // *
00433 // *******************************************************************************
00437 // *******************************************************************************
00438 
00439 void gZone::Render( const eCamera * cam )
00440 {
00441 #ifndef DEDICATED
00442 
00443     color_.a_ = ( lastTime - createTime_ ) * .2f;
00444     if ( color_.a_ > .7f )
00445         color_.a_ = .7f;
00446     if ( color_.a_ <= 0 )
00447         return;
00448 
00449     GLfloat m[4][4]={{rotation_.x,rotation_.y,0,0},
00450                      {-rotation_.y,rotation_.x,0,0},
00451                      {0,0,1,0},
00452                      {pos.x,pos.y,0,1}};
00453 
00454     ModelMatrix();
00455     glPushMatrix();
00456 
00457     glDisable(GL_LIGHT0);
00458     glDisable(GL_LIGHT1);
00459     glDisable(GL_LIGHTING);
00460     glDisable(GL_CULL_FACE);
00461     glDepthMask(GL_FALSE);
00462     glBlendFunc( GL_SRC_ALPHA, GL_ONE );
00463 
00464     //glDisable(GL_TEXTURE);
00465     glDisable(GL_TEXTURE_2D);
00466 
00467     //  glTranslatef(pos.x,pos.y,0);
00468 
00469     glMultMatrixf(&m[0][0]);
00470     //  glScalef(.5,.5,.5);
00471 
00472     if ( sr_alphaBlend )
00473         BeginQuads();
00474     else
00475         BeginLineStrip();
00476 
00477     const REAL seglen = .2f;
00478     const REAL bot = 0.0f;
00479     const REAL top = 5.0f; // + ( lastTime - createTime_ ) * .1f;
00480 
00481     color_.Apply();
00482 
00483     REAL r = Radius();
00484     for ( int i = sg_segments - 1; i>=0; --i )
00485     {
00486         REAL a = i * 2 * 3.14159 / REAL( sg_segments );
00487         REAL b = a + seglen;
00488 
00489         REAL sa = r * sin(a);
00490         REAL ca = r * cos(a);
00491         REAL sb = r * sin(b);
00492         REAL cb = r * cos(b);
00493 
00494         glVertex3f(sa, ca, bot);
00495         glVertex3f(sa, ca, top);
00496         glVertex3f(sb, cb, top);
00497         glVertex3f(sb, cb, bot);
00498 
00499         if ( !sr_alphaBlend )
00500         {
00501             glVertex3f(sa, ca, bot);
00502             RenderEnd();
00503             BeginLineStrip();
00504         }
00505     }
00506 
00507     RenderEnd();
00508 
00509     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00510     glDepthMask(GL_TRUE);
00511 
00512     glPopMatrix();
00513 #endif
00514 }
00515 
00516 void gZone::Render2D(tCoord) const {
00517 #ifndef DEDICATED
00518     if ( color_.a_ <= 0 )
00519         return;
00520 
00521     GLfloat m[4][4]={{rotation_.x,rotation_.y,0,0},
00522                      {-rotation_.y,rotation_.x,0,0},
00523                      {0,0,1,0},
00524                      {pos.x,pos.y,0,1}};
00525 
00526     ModelMatrix();
00527     glPushMatrix();
00528 
00529     glMultMatrixf(&m[0][0]);
00530     //  glScalef(.5,.5,.5);
00531 
00532     BeginLines();
00533 
00534     const REAL seglen = .2f;
00535 
00536     color_.Apply();
00537 
00538     REAL r = Radius();
00539     for ( int i = sg_segments - 1; i>=0; --i )
00540     {
00541         REAL a = i * 2 * 3.14159 / REAL( sg_segments );
00542         REAL b = a + seglen;
00543 
00544         REAL sa = r * sin(a);
00545         REAL ca = r * cos(a);
00546         REAL sb = r * sin(b);
00547         REAL cb = r * cos(b);
00548 
00549         glVertex2f(sa, ca);
00550         glVertex2f(sb, cb);
00551     }
00552 
00553     RenderEnd();
00554 
00555     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00556     glDepthMask(GL_TRUE);
00557 
00558     glPopMatrix();
00559 #endif
00560 }
00561 
00562 
00563 // *******************************************************************************
00564 // *
00565 // *    RendersAlpha
00566 // *
00567 // *******************************************************************************
00571 // *******************************************************************************
00572 bool gZone::RendersAlpha() const
00573 {
00574         return sr_alphaBlend;
00575 }
00576 
00577 // *******************************************************************************
00578 // *
00579 // *    gWinZoneHack
00580 // *
00581 // *******************************************************************************
00586 // *******************************************************************************
00587 
00588 gWinZoneHack::gWinZoneHack( eGrid * grid, const eCoord & pos )
00589         :gZone( grid, pos )
00590 {
00591     color_.r_ = 0.0f;
00592     color_.g_ = 1.0f;
00593     color_.b_ = 0.0f;
00594 }
00595 
00596 // *******************************************************************************
00597 // *
00598 // *    gWinZoneHack
00599 // *
00600 // *******************************************************************************
00605 // *******************************************************************************
00606 
00607 gWinZoneHack::gWinZoneHack( nMessage & m )
00608         : gZone( m )
00609 {
00610 }
00611 
00612 // *******************************************************************************
00613 // *
00614 // *    ~gWinZoneHack
00615 // *
00616 // *******************************************************************************
00619 // *******************************************************************************
00620 
00621 gWinZoneHack::~gWinZoneHack( void )
00622 {
00623 }
00624 
00625 // *******************************************************************************
00626 // *
00627 // *    OnEnter
00628 // *
00629 // *******************************************************************************
00634 // *******************************************************************************
00635 
00636 void gWinZoneHack::OnEnter( gCycle * target, REAL time )
00637 {
00638     static const char* message="$player_win_instant";
00639     sg_DeclareWinner( target->Player()->CurrentTeam(), message );
00640 
00641     // let zone vanish
00642     if ( GetExpansionSpeed() >= 0 )
00643     {
00644         SetReferenceTime();
00645         SetExpansionSpeed( -GetRadius()*.5 );
00646         RequestSync();
00647     }
00648 }
00649 
00650 // *******************************************************************************
00651 // *
00652 // *    gDeathZoneHack
00653 // *
00654 // *******************************************************************************
00659 // *******************************************************************************
00660 
00661 gDeathZoneHack::gDeathZoneHack( eGrid * grid, const eCoord & pos )
00662         :gZone( grid, pos )
00663 {
00664     color_.r_ = 1.0f;
00665     color_.g_ = 0.0f;
00666     color_.b_ = 0.0f;
00667 }
00668 
00669 // *******************************************************************************
00670 // *
00671 // *    gDeathZoneHack
00672 // *
00673 // *******************************************************************************
00678 // *******************************************************************************
00679 
00680 gDeathZoneHack::gDeathZoneHack( nMessage & m )
00681         : gZone( m )
00682 {
00683 }
00684 
00685 // *******************************************************************************
00686 // *
00687 // *    ~gDeathZoneHack
00688 // *
00689 // *******************************************************************************
00692 // *******************************************************************************
00693 
00694 gDeathZoneHack::~gDeathZoneHack( void )
00695 {
00696 }
00697 
00698 static int score_deathzone=-1;
00699 static tSettingItem<int> s_dz("SCORE_DEATHZONE",score_deathzone);
00700 
00701 // *******************************************************************************
00702 // *
00703 // *    OnEnter
00704 // *
00705 // *******************************************************************************
00710 // *******************************************************************************
00711 
00712 void gDeathZoneHack::OnEnter( gCycle * target, REAL time )
00713 {
00714     target->Player()->AddScore(score_deathzone, tOutput(), "$player_lose_suicide");
00715     target->Kill();
00716 }
00717 
00718 // *******************************************************************************
00719 // *
00720 // *    gBaseZoneHack
00721 // *
00722 // *******************************************************************************
00727 // *******************************************************************************
00728 
00729 gBaseZoneHack::gBaseZoneHack( eGrid * grid, const eCoord & pos )
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 }
00738 
00739 // *******************************************************************************
00740 // *
00741 // *    gBaseZoneHack
00742 // *
00743 // *******************************************************************************
00747 // *******************************************************************************
00748 
00749 gBaseZoneHack::gBaseZoneHack( nMessage & m )
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 }
00758 
00759 // *******************************************************************************
00760 // *
00761 // *    ~gBaseZoneHack
00762 // *
00763 // *******************************************************************************
00766 // *******************************************************************************
00767 
00768 gBaseZoneHack::~gBaseZoneHack( void )
00769 {
00770 }
00771 
00772 REAL sg_conquestRate = .5;
00773 REAL sg_defendRate = .25;
00774 REAL sg_conquestDecayRate = .1;
00775 
00776 static tSettingItem< REAL > sg_conquestRateConf( "FORTRESS_CONQUEST_RATE", sg_conquestRate );
00777 static tSettingItem< REAL > sg_defendRateConf( "FORTRESS_DEFEND_RATE", sg_defendRate );
00778 static tSettingItem< REAL > sg_conquestDecayRateConf( "FORTRESS_CONQUEST_DECAY_RATE", sg_conquestDecayRate );
00779 
00780 // time with no enemy inside a zone before it collapses harmlessly
00781 static REAL sg_conquestTimeout = 0;
00782 static tSettingItem< REAL > sg_conquestTimeoutConf( "FORTRESS_CONQUEST_TIMEOUT", sg_conquestTimeout );
00783 
00784 // kill at least than many players from the team that just got its zone conquered
00785 static int sg_onConquestKillMin = 0;
00786 static tSettingItem< int > sg_onConquestKillMinConfig( "FORTRESS_CONQUERED_KILL_MIN", sg_onConquestKillMin );
00787 
00788 // and at least this ratio
00789 static REAL sg_onConquestKillRatio = 0;
00790 static tSettingItem< REAL > sg_onConquestKillRationConfig( "FORTRESS_CONQUERED_KILL_RATIO", sg_onConquestKillRatio );
00791 
00792 // score you get for conquering a zone
00793 static int sg_onConquestScore = 0;
00794 static tSettingItem< int > sg_onConquestConquestScoreConfig( "FORTRESS_CONQUERED_SCORE", sg_onConquestScore );
00795 
00796 // flag indicating whether the team conquering the first zone wins (good for one on one matches)
00797 static int sg_onConquestWin = 1;
00798 static tSettingItem< int > sg_onConquestConquestWinConfig( "FORTRESS_CONQUERED_WIN", sg_onConquestWin );
00799 
00800 // maximal number of base zones ownable by a team
00801 static int sg_baseZonesPerTeam = 0;
00802 static tSettingItem< int > sg_baseZonesPerTeamConfig( "FORTRESS_MAX_PER_TEAM", sg_baseZonesPerTeam );
00803 
00804 // count zones belonging to the given team.
00805 // fill in count and the zone that is farthest to the team.
00806 void gBaseZoneHack::CountZonesOfTeam( eGrid const * grid, eTeam * otherTeam, int & count, gBaseZoneHack * & farthest )
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 }
00825 
00826 
00827 // *******************************************************************************
00828 // *
00829 // *    Timestep
00830 // *
00831 // *******************************************************************************
00835 // *******************************************************************************
00836 
00837 bool gBaseZoneHack::Timestep( REAL time )
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 }
00999 
01000 // *******************************************************************************
01001 // *
01002 // *    OnVanish
01003 // *
01004 // *******************************************************************************
01007 // *******************************************************************************
01008 
01009 void gBaseZoneHack::OnVanish( void )
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 }
01054 
01055 // *******************************************************************************
01056 // *
01057 // *    OnConquest
01058 // *
01059 // *******************************************************************************
01062 // *******************************************************************************
01063 
01064 void gBaseZoneHack::OnConquest( void )
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 }
01112 
01113 // if this flag is enabled, the last team with a non-conquered zone wins the round.
01114 static int sg_onSurviveWin = 1;
01115 static tSettingItem< int > sg_onSurviveWinConfig( "FORTRESS_SURVIVE_WIN", sg_onSurviveWin );
01116 
01117 // *******************************************************************************
01118 // *
01119 // *    CheckSurvivor
01120 // *
01121 // *******************************************************************************
01124 // *******************************************************************************
01125 
01126 void gBaseZoneHack::CheckSurvivor( void )
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 }
01155 
01156 // *******************************************************************************
01157 // *
01158 // *    OnEnter
01159 // *
01160 // *******************************************************************************
01165 // *******************************************************************************
01166 
01167 void gBaseZoneHack::OnEnter( gCycle * target, REAL time )
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 }
01196 
01197 // *******************************************************************************
01198 // *
01199 // *    GetPosition
01200 // *
01201 // *******************************************************************************
01205 // *******************************************************************************
01206 
01207 eCoord gZone::GetPosition( void ) const
01208 {
01209     eCoord ret;
01210     GetPosition( ret );
01211     return ret;
01212 }
01213 
01214 // *******************************************************************************
01215 // *
01216 // *    GetPosition
01217 // *
01218 // *******************************************************************************
01223 // *******************************************************************************
01224 
01225 gZone const & gZone::GetPosition( eCoord & position ) const
01226 {
01227     position.x = EvaluateFunctionNow( posx_ );
01228     position.y = EvaluateFunctionNow( posy_ );
01229     return *this;
01230 }
01231 
01232 // *******************************************************************************
01233 // *
01234 // *    SetPosition
01235 // *
01236 // *******************************************************************************
01241 // *******************************************************************************
01242 
01243 gZone & gZone::SetPosition( eCoord const & position )
01244 {
01245     SetFunctionNow( posx_, position.x );
01246     SetFunctionNow( posy_, position.y );
01247     return *this;
01248 }
01249 
01250 // *******************************************************************************
01251 // *
01252 // *    GetVelocity
01253 // *
01254 // *******************************************************************************
01258 // *******************************************************************************
01259 
01260 eCoord gZone::GetVelocity( void ) const
01261 {
01262     eCoord ret;
01263     GetVelocity( ret );
01264 
01265     return ret;
01266 }
01267 
01268 // *******************************************************************************
01269 // *
01270 // *    GetVelocity
01271 // *
01272 // *******************************************************************************
01277 // *******************************************************************************
01278 
01279 gZone const & gZone::GetVelocity( eCoord & velocity ) const
01280 {
01281     velocity.x = posx_.GetSlope();
01282     velocity.y = posy_.GetSlope();
01283 
01284     return *this;
01285 }
01286 
01287 // *******************************************************************************
01288 // *
01289 // *    SetVelocity
01290 // *
01291 // *******************************************************************************
01296 // *******************************************************************************
01297 
01298 gZone & gZone::SetVelocity( eCoord const & velocity )
01299 {
01300     // backup position
01301     eCoord pos;
01302     GetPosition( pos );
01303 
01304     posx_.SetSlope( velocity.x );
01305     posy_.SetSlope( velocity.y );
01306 
01307     // restore position
01308     SetPosition( pos );
01309 
01310     return *this;
01311 }
01312 
01313 // *******************************************************************************
01314 // *
01315 // *    GetRadius
01316 // *
01317 // *******************************************************************************
01321 // *******************************************************************************
01322 
01323 REAL gZone::GetRadius( void ) const
01324 {
01325     REAL ret = EvaluateFunctionNow( this->radius_ );
01326     ret = ret > 0 ? ret : 0;
01327 
01328     return ret;
01329 }
01330 
01331 // *******************************************************************************
01332 // *
01333 // *    GetRadius
01334 // *
01335 // *******************************************************************************
01340 // *******************************************************************************
01341 
01342 gZone const & gZone::GetRadius( REAL & radius ) const
01343 {
01344     radius = GetRadius();
01345 
01346     return *this;
01347 }
01348 
01349 // *******************************************************************************
01350 // *
01351 // *    SetRadius
01352 // *
01353 // *******************************************************************************
01358 // *******************************************************************************
01359 
01360 gZone & gZone::SetRadius( REAL radius )
01361 {
01362     SetFunctionNow( this->radius_, radius );
01363 
01364     return *this;
01365 }
01366 
01367 // *******************************************************************************
01368 // *
01369 // *    GetExpansionSpeed
01370 // *
01371 // *******************************************************************************
01375 // *******************************************************************************
01376 
01377 REAL gZone::GetExpansionSpeed( void ) const
01378 {
01379     return this->radius_.GetSlope();
01380 }
01381 
01382 // *******************************************************************************
01383 // *
01384 // *    GetExpansionSpeed
01385 // *
01386 // *******************************************************************************
01391 // *******************************************************************************
01392 
01393 gZone const & gZone::GetExpansionSpeed( REAL & expansionSpeed ) const
01394 {
01395     expansionSpeed = this->radius_.GetSlope();
01396 
01397     return *this;
01398 }
01399 
01400 // *******************************************************************************
01401 // *
01402 // *    SetExpansionSpeed
01403 // *
01404 // *******************************************************************************
01409 // *******************************************************************************
01410 
01411 gZone & gZone::SetExpansionSpeed( REAL expansionSpeed )
01412 {
01413     REAL r = EvaluateFunctionNow( this->radius_ );
01414     this->radius_.SetSlope( expansionSpeed );
01415     SetRadius( r );
01416 
01417     return *this;
01418 }
01419 
01420 // *******************************************************************************
01421 // *
01422 // *    SetReferenceTime
01423 // *
01424 // *******************************************************************************
01427 // *******************************************************************************
01428 
01429 void gZone::SetReferenceTime( void )
01430 {
01431     // set offsets to current values
01432     this->posx_.SetOffset( EvaluateFunctionNow( this->posx_ ) );
01433     this->posy_.SetOffset( EvaluateFunctionNow( this->posy_ ) );
01434     this->radius_.SetOffset( EvaluateFunctionNow( this->radius_ ) );
01435     this->rotationSpeed_.SetOffset( EvaluateFunctionNow( this->rotationSpeed_ ) );
01436 
01437     // reset time
01438     this->referenceTime_ = lastTime;
01439 }
01440 
01441 // *******************************************************************************
01442 // *
01443 // *    GetRotationSpeed
01444 // *
01445 // *******************************************************************************
01449 // *******************************************************************************
01450 
01451 REAL gZone::GetRotationSpeed( void ) const
01452 {
01453     return EvaluateFunctionNow( rotationSpeed_ );
01454 }
01455 
01456 // *******************************************************************************
01457 // *
01458 // *    GetRotation
01459 // *
01460 // *******************************************************************************
01464 // *******************************************************************************
01465 
01466 tCoord const &gZone::GetRotation( void ) const
01467 {
01468     return rotation_;
01469 }
01470 
01471 // *******************************************************************************
01472 // *
01473 // *    GetRotationSpeed
01474 // *
01475 // *******************************************************************************
01480 // *******************************************************************************
01481 
01482 gZone const & gZone::GetRotationSpeed( REAL & rotationSpeed ) const
01483 {
01484     rotationSpeed = this->GetRotationSpeed();
01485     return *this;
01486 }
01487 
01488 // *******************************************************************************
01489 // *
01490 // *    SetRotationSpeed
01491 // *
01492 // *******************************************************************************
01497 // *******************************************************************************
01498 
01499 gZone & gZone::SetRotationSpeed( REAL rotationSpeed )
01500 {
01501     SetFunctionNow( this->rotationSpeed_, rotationSpeed );
01502     return *this;
01503 }
01504 
01505 // *******************************************************************************
01506 // *
01507 // *    GetRotationAcceleration
01508 // *
01509 // *******************************************************************************
01513 // *******************************************************************************
01514 
01515 REAL gZone::GetRotationAcceleration( void ) const
01516 {
01517     return this->rotationSpeed_.GetSlope();
01518 }
01519 
01520 // *******************************************************************************
01521 // *
01522 // *    GetRotationAcceleration
01523 // *
01524 // *******************************************************************************
01529 // *******************************************************************************
01530 
01531 gZone const & gZone::GetRotationAcceleration( REAL & rotationAcceleration ) const
01532 {
01533     rotationAcceleration = this->GetRotationAcceleration();
01534     return *this;
01535 }
01536 
01537 // *******************************************************************************
01538 // *
01539 // *    GetColor
01540 // *
01541 // *******************************************************************************
01545 // *******************************************************************************
01546 
01547 rColor const & gZone::GetColor( void ) const
01548 {
01549     return color_;
01550 }
01551 
01552 // *******************************************************************************
01553 // *
01554 // *    SetRotationAcceleration
01555 // *
01556 // *******************************************************************************
01561 // *******************************************************************************
01562 
01563 gZone & gZone::SetRotationAcceleration( REAL rotationAcceleration )
01564 {
01565     REAL omega = this->GetRotationSpeed();
01566     this->rotationSpeed_.SetSlope( rotationAcceleration );
01567     SetRotationSpeed( omega );
01568 
01569     return *this;
01570 }
01571 
01572 
01573 

Generated on Sat Mar 15 22:56:11 2008 for Armagetron Advanced by  doxygen 1.5.4