00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00086 static const int sg_segments = 11;
00087
00088
00089
00090
00091
00092
00097
00098
00099 inline REAL gZone::EvaluateFunctionNow( tFunction const & f ) const
00100 {
00101 return f( lastTime - referenceTime_ );
00102 }
00103
00104
00105
00106
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
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
00135 referenceTime_ = createTime_ = lastTime = 0;
00136
00137
00138 this->AddToList();
00139
00140 sg_Zones.push_back(this);
00141
00142
00143 SetPosition( pos );
00144 eSoundMixer* mixer = eSoundMixer::GetMixer();
00145 mixer->PushButton(ZONE_SPAWN, pos);
00146 }
00147
00148
00149
00150
00151
00152
00156
00157
00158 gZone::gZone( nMessage & m )
00159 :eNetGameObject( m ), rotation_(1,0)
00160 {
00161
00162 m >> createTime_;
00163 referenceTime_ = lastTime = createTime_;
00164
00165
00166 color_.r_ = color_.g_ = color_.b_ = 1.0f;
00167
00168
00169 this->AddToList();
00170
00171 sg_Zones.push_back(this);
00172
00173
00174 SetPosition( pos );
00175 eSoundMixer* mixer = eSoundMixer::GetMixer();
00176 mixer->PushButton(ZONE_SPAWN, pos);
00177 }
00178
00179
00180
00181
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
00204
00205
00209
00210
00211 void gZone::WriteCreate( nMessage & m )
00212 {
00213
00214 eNetGameObject::WriteCreate( m );
00215
00216 m << createTime_;
00217 }
00218
00219
00220
00221
00222
00223
00227
00228
00229 void gZone::WriteSync( nMessage & m )
00230 {
00231
00232 eNetGameObject::WriteSync( m );
00233
00234
00235 m << color_.r_;
00236 m << color_.g_;
00237 m << color_.b_;
00238
00239
00240 m << referenceTime_;
00241 m << posx_;
00242 m << posy_;
00243 m << radius_;
00244
00245
00246 m << rotationSpeed_;
00247 }
00248
00249
00250
00251
00252
00253
00257
00258
00259 void gZone::ReadSync( nMessage & m )
00260 {
00261
00262 eNetGameObject::ReadSync( m );
00263
00264
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
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
00286 this->radius_.SetOffset( sg_initialSize );
00287 this->radius_.SetSlope( sg_expansionSpeed );
00288 SetPosition( pos );
00289 SetVelocity( eCoord() );
00290 }
00291
00292
00293 if (!m.End())
00294 {
00295 m >> rotationSpeed_;
00296 }
00297 else
00298 {
00299
00300 SetRotationSpeed( .3f );
00301 SetRotationAcceleration( 0.0f );
00302 }
00303 }
00304
00305
00306
00307
00308
00309
00313
00314
00315 bool gZone::Timestep( REAL time )
00316 {
00317
00318 REAL speed = GetRotationSpeed();
00319 REAL angle = ( time - lastTime ) * speed;
00320
00321 rotation_ = rotation_.Turn( cos( angle ), sin( angle ) );
00322
00323
00324 REAL dt = time - referenceTime_;
00325 Move( eCoord( posx_( dt ), posy_( dt ) ), lastTime, time );
00326
00327
00328 lastTime = time;
00329
00330
00331 if ( GetExpansionSpeed() < 0 && GetRadius() <= 0 )
00332 {
00333 OnVanish();
00334 return true;
00335 }
00336
00337 return false;
00338 }
00339
00340
00341
00342
00343
00344
00347
00348
00349 void gZone::OnVanish( void )
00350 {
00351 }
00352
00353
00354
00355
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
00384
00385
00390
00391
00392 void gZone::OnEnter( gCycle * target, REAL time )
00393 {
00394 }
00395
00396
00397 static nNOInitialisator<gZone> zone_init(340,"zone");
00398
00399
00400
00401
00402
00403
00407
00408
00409 nDescriptor & gZone::CreatorDescriptor( void ) const
00410 {
00411 return zone_init;
00412 }
00413
00414
00415
00416
00417
00418
00422
00423
00424 REAL gZone::Radius( void ) const
00425 {
00426 return GetRadius();
00427 }
00428
00429
00430
00431
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
00465 glDisable(GL_TEXTURE_2D);
00466
00467
00468
00469 glMultMatrixf(&m[0][0]);
00470
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;
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
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
00566
00567
00571
00572 bool gZone::RendersAlpha() const
00573 {
00574 return sr_alphaBlend;
00575 }
00576
00577
00578
00579
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
00599
00600
00605
00606
00607 gWinZoneHack::gWinZoneHack( nMessage & m )
00608 : gZone( m )
00609 {
00610 }
00611
00612
00613
00614
00615
00616
00619
00620
00621 gWinZoneHack::~gWinZoneHack( void )
00622 {
00623 }
00624
00625
00626
00627
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
00642 if ( GetExpansionSpeed() >= 0 )
00643 {
00644 SetReferenceTime();
00645 SetExpansionSpeed( -GetRadius()*.5 );
00646 RequestSync();
00647 }
00648 }
00649
00650
00651
00652
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
00672
00673
00678
00679
00680 gDeathZoneHack::gDeathZoneHack( nMessage & m )
00681 : gZone( m )
00682 {
00683 }
00684
00685
00686
00687
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
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
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
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
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
00781 static REAL sg_conquestTimeout = 0;
00782 static tSettingItem< REAL > sg_conquestTimeoutConf( "FORTRESS_CONQUEST_TIMEOUT", sg_conquestTimeout );
00783
00784
00785 static int sg_onConquestKillMin = 0;
00786 static tSettingItem< int > sg_onConquestKillMinConfig( "FORTRESS_CONQUERED_KILL_MIN", sg_onConquestKillMin );
00787
00788
00789 static REAL sg_onConquestKillRatio = 0;
00790 static tSettingItem< REAL > sg_onConquestKillRationConfig( "FORTRESS_CONQUERED_KILL_RATIO", sg_onConquestKillRatio );
00791
00792
00793 static int sg_onConquestScore = 0;
00794 static tSettingItem< int > sg_onConquestConquestScoreConfig( "FORTRESS_CONQUERED_SCORE", sg_onConquestScore );
00795
00796
00797 static int sg_onConquestWin = 1;
00798 static tSettingItem< int > sg_onConquestConquestWinConfig( "FORTRESS_CONQUERED_WIN", sg_onConquestWin );
00799
00800
00801 static int sg_baseZonesPerTeam = 0;
00802 static tSettingItem< int > sg_baseZonesPerTeamConfig( "FORTRESS_MAX_PER_TEAM", sg_baseZonesPerTeam );
00803
00804
00805
00806 void gBaseZoneHack::CountZonesOfTeam( eGrid const * grid, eTeam * otherTeam, int & count, gBaseZoneHack * & farthest )
00807 {
00808 count = 0;
00809 farthest = NULL;
00810
00811
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
00830
00831
00835
00836
00837 bool gBaseZoneHack::Timestep( REAL time )
00838 {
00839 if ( currentState_ == State_Conquering )
00840 {
00841
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
00853 REAL conquest = sg_conquestRate * enemiesInside_ - sg_defendRate * ownersInside_ - sg_conquestDecayRate;
00854 conquered_ += dt * conquest;
00855
00856
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
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
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
00892 if ( sg_conquestTimeout > 0 && lastEnemyContact_ + sg_conquestTimeout < time )
00893 {
00894 enemies_.clear();
00895
00896
00897
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
00907 if ( conquered_ >= 1 )
00908 {
00909 currentState_ = State_Conquering;
00910 OnConquest();
00911 }
00912 }
00913
00914
00915
00916 enemiesInside_ = ownersInside_ = 0;
00917
00918
00919
00920
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
00939 gBaseZoneHack * farthest = NULL;
00940 int count = 0;
00941 if ( sg_baseZonesPerTeam > 0 )
00942 CountZonesOfTeam( Grid(), otherTeam, count, farthest );
00943
00944
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
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
00967 if ( !team )
00968 {
00969 return true;
00970 }
00971
00972
00973
00974 if ( team && sg_baseZonesPerTeam > 0 )
00975 {
00976 gBaseZoneHack * farthest = 0;
00977 int count = 0;
00978 CountZonesOfTeam( Grid(), team, count, farthest );
00979
00980
00981 if ( count > sg_baseZonesPerTeam )
00982 farthest->team = NULL;
00983 }
00984 }
00985
00986
00987
00988 bool ret = gZone::Timestep( time );
00989
00990
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
01003
01004
01007
01008
01009 void gBaseZoneHack::OnVanish( void )
01010 {
01011 if (!team)
01012 return;
01013
01014 CheckSurvivor();
01015
01016
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
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
01058
01059
01062
01063
01064 void gBaseZoneHack::OnConquest( void )
01065 {
01066
01067 int totalScore = sg_onConquestScore;
01068 if ( 0 == enemiesInside_ )
01069 totalScore /= 2;
01070
01071
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
01082
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
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
01114 static int sg_onSurviveWin = 1;
01115 static tSettingItem< int > sg_onSurviveWinConfig( "FORTRESS_SURVIVE_WIN", sg_onSurviveWin );
01116
01117
01118
01119
01120
01121
01124
01125
01126 void gBaseZoneHack::CheckSurvivor( void )
01127 {
01128
01129 if ( sg_onSurviveWin )
01130 {
01131
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
01149 if ( onlySurvivor && survivor )
01150 {
01151 survivor->onlySurvivor_ = true;
01152 }
01153 }
01154 }
01155
01156
01157
01158
01159
01160
01165
01166
01167 void gBaseZoneHack::OnEnter( gCycle * target, REAL time )
01168 {
01169
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
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
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
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
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
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
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
01290
01291
01296
01297
01298 gZone & gZone::SetVelocity( eCoord const & velocity )
01299 {
01300
01301 eCoord pos;
01302 GetPosition( pos );
01303
01304 posx_.SetSlope( velocity.x );
01305 posy_.SetSlope( velocity.y );
01306
01307
01308 SetPosition( pos );
01309
01310 return *this;
01311 }
01312
01313
01314
01315
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
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
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
01370
01371
01375
01376
01377 REAL gZone::GetExpansionSpeed( void ) const
01378 {
01379 return this->radius_.GetSlope();
01380 }
01381
01382
01383
01384
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
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
01423
01424
01427
01428
01429 void gZone::SetReferenceTime( void )
01430 {
01431
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
01438 this->referenceTime_ = lastTime;
01439 }
01440
01441
01442
01443
01444
01445
01449
01450
01451 REAL gZone::GetRotationSpeed( void ) const
01452 {
01453 return EvaluateFunctionNow( rotationSpeed_ );
01454 }
01455
01456
01457
01458
01459
01460
01464
01465
01466 tCoord const &gZone::GetRotation( void ) const
01467 {
01468 return rotation_;
01469 }
01470
01471
01472
01473
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
01491
01492
01497
01498
01499 gZone & gZone::SetRotationSpeed( REAL rotationSpeed )
01500 {
01501 SetFunctionNow( this->rotationSpeed_, rotationSpeed );
01502 return *this;
01503 }
01504
01505
01506
01507
01508
01509
01513
01514
01515 REAL gZone::GetRotationAcceleration( void ) const
01516 {
01517 return this->rotationSpeed_.GetSlope();
01518 }
01519
01520
01521
01522
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
01540
01541
01545
01546
01547 rColor const & gZone::GetColor( void ) const
01548 {
01549 return color_;
01550 }
01551
01552
01553
01554
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