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
00029 #include "rSDL.h"
00030
00031 #include "gWall.h"
00032 #include "gStuff.h"
00033 #include "eGrid.h"
00034 #include "eWall.h"
00035 #include "math.h"
00036 #include "gCycle.h"
00037 #include "rTexture.h"
00038 #include "eTimer.h"
00039 #include "gGame.h"
00040 #include "rScreen.h"
00041 #include "rRender.h"
00042 #include "eCamera.h"
00043 #include "tConfiguration.h"
00044 #include "gExplosion.h"
00045 #include "tMath.h"
00046 #include "ePlayer.h"
00047 #include "eTess2.h"
00048 #include "nConfig.h"
00049
00050 #include <fstream>
00051
00052
00053
00054
00055
00056 #ifndef DEDICATED
00057
00058
00059 static bool sg_bugTransparency;
00060 static bool sg_bugTransparencyDemand;
00061 static tSettingItem< bool > sgc_bugTransparency( "BUG_TRANSPARENCY", sg_bugTransparency );
00062 static tSettingItem< bool > sgc_bugTransparencyDemand( "BUG_TRANSPARENCY_DEMAND", sg_bugTransparencyDemand );
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 static rFileTexture gWallRim_a(rTextureGroups::TEX_WALL,"moviepack/rim_wall_a.png",0,0);
00089 static rFileTexture gWallRim_b(rTextureGroups::TEX_WALL,"moviepack/rim_wall_b.png",0,0);
00090 static rFileTexture gWallRim_c(rTextureGroups::TEX_WALL,"moviepack/rim_wall_c.png",0,0);
00091 static rFileTexture gWallRim_d(rTextureGroups::TEX_WALL,"moviepack/rim_wall_d.png",0,0);
00092
00093 static rITexture *gWallRim_mp[4]={&gWallRim_a,&gWallRim_b,
00094 &gWallRim_c,&gWallRim_d};
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 #endif
00106
00107 static REAL sg_RimStretchX=100;
00108 static tSettingItem<REAL> sg_RimStretchXConf
00109 ("RIM_WALL_STRETCH_X",sg_RimStretchX);
00110 static REAL sg_RimStretchY=100;
00111 static tSettingItem<REAL> sg_RimStretchYConf
00112 ("RIM_WALL_STRETCH_Y",sg_RimStretchY);
00113
00114 static REAL sg_MPRimStretchX=50;
00115 static tSettingItem<REAL> sg_MPRimStretchXConf
00116 ("MOVIEPACK_RIM_WALL_STRETCH_X",sg_MPRimStretchX);
00117 static REAL sg_MPRimStretchY=50;
00118 static tSettingItem<REAL> sg_MPRimStretchYConf
00119 ("MOVIEPACK_RIM_WALL_STRETCH_Y",sg_MPRimStretchY);
00120
00121
00122
00123
00124
00125 gWallRim::gWallRim(eGrid *grid, REAL h)
00126 :eWallRim(grid, false, h), renderHeight_(h), lastUpdate_(-100), tBeg_( 0 ), tEnd_( 0 )
00127 {
00128
00129 }
00130
00131 gWallRim::gWallRim(eGrid *grid, REAL tBeg, REAL tEnd, REAL h)
00132 :eWallRim(grid, false, h), renderHeight_(h), lastUpdate_(-100), tBeg_( tBeg ), tEnd_( tEnd )
00133 {
00134
00135 }
00136
00137 gWallRim::~gWallRim()
00138 {
00139
00140 }
00141
00142 bool gWallRim::Splittable() const{return 1;}
00143 void gWallRim::Split(eWall *& w1,eWall *& w2,REAL ratio)
00144 {
00145
00146
00147 REAL tMid = tEnd_ * ratio + tBeg_ * ( 1 - ratio );
00148 w1=tNEW(gWallRim(grid, tBeg_, tMid, height));
00149 w2=tNEW(gWallRim(grid, tMid, tEnd_, height));
00150 }
00151
00152
00153 bool gWallRim::RunsParallelPassive( eWall* newWall )
00154 {
00155 return false;
00156 }
00157
00158
00159 extern REAL lower_height,upper_height;
00160
00161 #ifndef DEDICATED
00162
00163
00164 static void gWallRim_helper(eCoord p1,eCoord p2,REAL tBeg,REAL tEnd,REAL h,
00165 REAL Z_SCALE,bool sw){
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 if (sg_MoviePack()){
00183 int t=int(floor((tBeg+tEnd)/2));
00184 tBeg-=t;
00185 tEnd-=t;
00186 t=t%4;
00187 while (t<0)
00188 t+=4;
00189 gWallRim_mp[t]->Select();
00190 }
00191
00192 if (sw){
00193 Swap(p1,p2);
00194 Swap(tBeg,tEnd);
00195 }
00196
00197
00198 if (h>9000){
00199 if (sr_lowerSky || sg_MoviePack()) h=lower_height;
00200 if (sr_upperSky && !sg_MoviePack()) h=upper_height;
00201 }
00202
00203 BeginQuads();
00204
00205
00206 if (h<9000 || !sr_infinityPlane || rDisplayList::IsRecording() ){
00207 TexVertex(p1.x, p1.y, 0,
00208 tBeg , 1);
00209
00210 TexVertex(p1.x, p1.y, h,
00211 tBeg, 1-h/Z_SCALE);
00212
00213 TexVertex(p2.x, p2.y, h,
00214 tEnd, 1-h/Z_SCALE);
00215
00216 TexVertex(p2.x, p2.y, 0,
00217 tEnd , 1);
00218 }
00219
00220 else{
00221 TexVertex(p1.x, p1.y, 0,
00222 tBeg, 1);
00223
00224 TexCoord(0,-1/REAL(Z_SCALE),0,0);
00225
00226 #ifndef WIN32
00227 Vertex(0,0,1,0);
00228 Vertex(0,0,1,0);
00229 #else
00230 Vertex(0.001f,0.001f,1,0);
00231
00232 Vertex(0.001f,0.001f,1,0);
00233 #endif
00234
00235 TexVertex(p2.x, p2.y, 0,
00236 tEnd, 1);
00237 }
00238 }
00239
00240
00241 static REAL sg_arenaWallShadowSize = 0.1;
00242 static tSettingItem<REAL> sg_arenaWallShadowSizeConf("ARENA_WALL_SHADOW_SIZE",sg_arenaWallShadowSize);
00243
00244
00245 static REAL sg_arenaWallShadowSideDist = 10.0;
00246 static tSettingItem<REAL> sg_arenaWallShadowSideDistConf("ARENA_WALL_SHADOW_SIDEDIST",sg_arenaWallShadowSideDist);
00247
00248
00249 static REAL sg_arenaWallShadowNear = 1.0;
00250 static tSettingItem<REAL> sg_arenaWallShadowNearConf("ARENA_WALL_SHADOW_NEAR",sg_arenaWallShadowNear);
00251
00252
00253 static REAL sg_arenaWallShadowDist = 100.0;
00254 static tSettingItem<REAL> sg_arenaWallShadowDistConf("ARENA_WALL_SHADOW_DIST",sg_arenaWallShadowDist);
00255
00256 void gWallRim::RenderReal(const eCamera *cam){
00257 if ( Edge() ){
00258 const eCoord *p1=&EndPoint(0);
00259 const eCoord *p2=&EndPoint(1);
00260
00261 REAL X_SCALE=sg_RimStretchX;
00262 REAL Z_SCALE=sg_RimStretchY;
00263
00264
00265 bool transparency = sg_bugTransparency || ( sg_bugTransparencyDemand && renderHeight_ < height );
00266 REAL h = transparency ? height : renderHeight_;
00267 if ( transparency )
00268 glDisable( GL_DEPTH_TEST );
00269
00270 if (sg_MoviePack()){
00271 X_SCALE=sg_MPRimStretchX;
00272 Z_SCALE=sg_MPRimStretchY;
00273 }
00274
00275 if ( tBeg_ == tEnd_ )
00276 {
00277 tBeg_=(p1->x+p1->y);
00278 tEnd_=(p2->x+p2->y);
00279 }
00280 REAL tBeg = tBeg_/X_SCALE;
00281 REAL tEnd = tEnd_/X_SCALE;
00282 eCoord P1=*p1;
00283 eCoord P2=*p2;
00284
00285
00286 if ( cam )
00287 {
00288
00289 eCoord pos = cam->CenterPos();
00290
00291
00292
00293
00294
00295 eCoord normal = (P1 - P2).Turn(0,1);
00296 normal.Normalize();
00297
00298
00299 REAL side = -eCoord::F(normal, pos - P1);
00300
00301
00302 REAL scale = pos.Norm() + 10 + (P1-P2).Norm();
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 REAL abs = fabs(side);
00314 REAL sign = side/abs;
00315
00316
00317 if ( abs < EPS*scale*10 )
00318 {
00319
00320 eCoord facing = cam->CenterCamDir() * 2 + cam->CameraDir();
00321
00322 sign = eCoord::F( normal, facing );
00323 abs = fabs( sign );
00324 if ( abs > EPS )
00325 {
00326 sign/= fabs( sign );
00327 abs = EPS*scale;
00328 }
00329 else
00330 {
00331 abs = 0;
00332 sign = 0;
00333 }
00334 }
00335
00336
00337 eCoord dir = cam->CenterCamDir();
00338
00339
00340 REAL camSide = -eCoord::F(normal, cam->CameraGlancePos() - P1);
00341
00342
00343 if ( camSide * sign < -EPS*scale )
00344 sign = 0;
00345
00346
00347 if ( sign * eCoord::F( normal, dir ) > -EPS )
00348 {
00349 if ( camSide * sign >= 0 )
00350 {
00351 REAL camAbs = fabs( camSide );
00352 if ( camAbs < abs )
00353 abs = camAbs;
00354 }
00355 else
00356 {
00357
00358 abs = 0;
00359 }
00360 }
00361
00362
00363 {
00364 REAL d1 = dir * (pos - P1);
00365 REAL d2 = dir * (pos - P2);
00366 if ( d1 * d2 >= 0 )
00367 {
00368 REAL dist = fabs( d1 );
00369 d2 = fabs( d2 );
00370 if ( d2 < dist )
00371 dist = d2;
00372
00373 abs += dist * sg_arenaWallShadowSideDist/sg_arenaWallShadowDist;
00374 }
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 if ( sign != 0 && abs < sg_arenaWallShadowSideDist )
00390 {
00391
00392 REAL heightForShadow = cam->CameraZ()+10;
00393 if ( this->renderHeight_*4 < heightForShadow )
00394 heightForShadow = this->renderHeight_*4;
00395
00396
00397 REAL extension = heightForShadow*sg_arenaWallShadowSize * sign/( 1 + abs/sg_arenaWallShadowNear );
00398 extension *= ( 1 - abs/sg_arenaWallShadowSideDist );
00399
00400
00401 eCoord P3=P1+normal*extension;
00402 eCoord P4=P2+normal*extension;
00403
00404
00405 Color(0,0,0);
00406 BeginQuads();
00407 Vertex(P1.x, P1.y, 0);
00408 Vertex(P2.x, P2.y, 0);
00409 Vertex(P4.x, P4.y, 0);
00410 Vertex(P3.x, P3.y, 0);
00411 }
00412 }
00413
00414 {
00415 eCoord vec = P1-P2;
00416 REAL xs = vec.x*vec.x;
00417 REAL ys = vec.y*vec.y;
00418 REAL intensity = .7 + .3 * xs/(xs+ys);
00419 RenderEnd( true );
00420 Color(intensity, intensity, intensity);
00421 }
00422
00423 if (sg_MoviePack()){
00424 bool sw=false;
00425
00426 if (tBeg>tEnd){
00427 Swap(P1,P2);
00428 Swap(tBeg,tEnd);
00429
00430 }
00431
00432 REAL ta=tBeg;
00433 eCoord ca=P1;
00434 for (int i=int(ceil(tBeg));i<tEnd;i++){
00435 eCoord cb=P1+(P2-P1)*((i-tBeg)/(tEnd-tBeg));
00436 gWallRim_helper(ca,cb,ta,i,h,Z_SCALE,sw);
00437 ca=cb;
00438 ta=i;
00439 }
00440 gWallRim_helper(ca,P2,ta,tEnd,h,Z_SCALE,sw);
00441 }
00442 else{
00443
00444 REAL offset = 0;
00445 if (tBeg>tEnd)
00446 offset = -floor(tEnd);
00447 else
00448 offset = -floor(tBeg);
00449
00450 tBeg += offset;
00451 tEnd += offset;
00452
00453 gWallRim_helper(*p1,*p2,tBeg,tEnd,h,Z_SCALE,false);
00454 }
00455
00456
00457
00458 if ( transparency )
00459 glEnable( GL_DEPTH_TEST );
00460 }
00461
00462
00463 if ( se_mainGameTimer )
00464 {
00465 REAL time = se_mainGameTimer->Time();
00466 REAL ts = time - lastUpdate_;
00467 if ( ts > 0 )
00468 {
00469 lastUpdate_ = time;
00470
00471 if ( renderHeight_ < .25 )
00472 {
00473 renderHeight_ = .25;
00474 }
00475 renderHeight_ *= 1 + 10 * ts;
00476 renderHeight_ += 5 * ts;
00477 if ( renderHeight_ > height )
00478 {
00479 renderHeight_ = height;
00480 }
00481 }
00482
00483 if ( renderHeight_ < height )
00484 {
00485 DestroyDisplayList();
00486 }
00487 }
00488 }
00489
00490
00491
00492
00493
00494
00499
00500
00501 void gWallRim::OnBlocksCamera( eCamera * camera, REAL height ) const
00502 {
00503 DestroyDisplayList();
00504
00505
00506 if ( height < renderHeight_ )
00507 {
00508 renderHeight_ = height;
00509 }
00510 if ( renderHeight_ < .25 )
00511 renderHeight_ = .25;
00512 }
00513
00514 #endif
00515
00516
00517
00518
00519
00520
00524
00525
00526 REAL gWallRim::Height( void )
00527 {
00528 return renderHeight_;
00529 }
00530
00531
00532
00533
00534
00535
00539
00540
00541 REAL gWallRim::SeeHeight( void )
00542 {
00543 return renderHeight_ * 2;
00544 }
00545
00546
00547
00548
00549
00550 #ifdef DEBUG
00551 #define CHECKWALL this->Check();
00552 #else
00553 #define CHECKWALL
00554 #endif
00555
00556 gPlayerWall::gPlayerWall(gNetPlayerWall*w, gCycle *p)
00557 :eWall(p->grid),cycle_(p),netWall_(w),begDist_(w->Pos(0)),endDist_(w->Pos(1))
00558 {
00559 CHECKWALL;
00560
00561 if (cycle_)
00562 windingNumber_ = cycle_->WindingNumber();
00563
00564 #ifdef DEBUG
00565 if (!cycle_)
00566 {
00567
00568 }
00569 #endif
00570 }
00571
00572 gPlayerWall::~gPlayerWall(){
00573 CHECKWALL;
00574 }
00575
00576
00577
00578 void gPlayerWall::Flip(){
00579 CHECKWALL;
00580
00581 eWall::Flip();
00582 Swap( this->begDist_, this->endDist_ );
00583
00584 CHECKWALL;
00585 }
00586
00587 static void clamp01(REAL &c){
00588 if (!finite(c))
00589 c = 0.5;
00590
00591 if (c<0)
00592 c = 0;
00593
00594 if (c>1)
00595 c = 1;
00596 }
00597
00598
00599 void sg_TopologyPoliceKill( gCycle* cycle )
00600 {
00601 if ( sn_GetNetState() != nCLIENT && cycle->Alive() )
00602 {
00603 tOutput message;
00604 tString name;
00605 if ( cycle->Player() )
00606 name = cycle->Player()->GetName();
00607 else
00608 cycle->PrintName( name );
00609 message.SetTemplateParameter(1, name );
00610 message << "$player_topologypolice";
00611 sn_ConsoleOut( message );
00612
00613 cycle->Kill();
00614 }
00615 }
00616
00617 static short sg_topologyPolice = false;
00618 static tSettingItem< short > sg_topologyPoliceCofig( "TOPOLOGY_POLICE", sg_topologyPolice );
00619
00620 static short sg_topologyPoliceParallel = true;
00621 static tSettingItem< short > sg_topologyPoliceParallelCofig( "TOPOLOGY_POLICE_PARALLEL", sg_topologyPoliceParallel );
00622
00623 class gTopologyPoliceConsoleFiler: public tConsoleFilter
00624 {
00625 virtual void DoFilterLine( tString& line )
00626 {
00627 tString oldLine = line;
00628 tOutput message;
00629 message.SetTemplateParameter(1, oldLine );
00630 message << "$player_topologypolice";
00631 line = message;
00632 }
00633 };
00634
00635 extern bool sg_gnuplotDebug;
00636
00637
00638
00639
00640 void sg_TopologyPoliceCheck( gCycle* cycle, eWall* oldWall, gPlayerWall* newWall, const eCoord& point, bool split )
00641 {
00642
00643 if ( !sg_topologyPolice && !sg_gnuplotDebug )
00644 return;
00645
00646
00647 REAL oldAlpha = oldWall->Edge()->Ratio( point );
00648 REAL newAlpha = newWall->Edge()->Ratio( point );
00649 clamp01( newAlpha );
00650 clamp01( oldAlpha );
00651
00652
00653 REAL time = newWall->Time( newAlpha );
00654
00655
00656
00657
00658
00659 if ( !newWall->IsDangerous( newAlpha, se_GameTime() ) )
00660 return;
00661
00662
00663 gPlayerWall* oldPlayerWall = dynamic_cast< gPlayerWall* >( oldWall );
00664 if ( oldPlayerWall && !oldPlayerWall->IsDangerous( oldAlpha, se_GameTime() ) )
00665 return;
00666
00667
00668 #ifdef DEBUG
00669 if ( sg_gnuplotDebug )
00670 {
00671 std::stringstream filename;
00672 if ( cycle && cycle->Player() )
00673 {
00674 filename << cycle->Player()->GetUserName() << "_";
00675 }
00676 filename << "topology";
00677 std::ofstream f( filename.str().c_str(), std::ios::app );
00678 f << point.x << " " << point.y << "\n";
00679 }
00680 #endif
00681
00682
00683 if ( !sg_topologyPolice || ( !split && !sg_topologyPoliceParallel ) )
00684 return;
00685
00686 gTopologyPoliceConsoleFiler filter;
00687
00688
00689 try
00690 {
00691 cycle->PassEdge( oldWall, time, oldAlpha );
00692 }
00693 catch ( gCycleDeath const & death )
00694 {
00695 cycle->KillAt( death.pos_ );
00696 }
00697 }
00698
00699
00700 void gPlayerWall::SplitByActive( eWall * oldWall )
00701 {
00702 if ( oldWall )
00703 {
00704
00705 eCoord intersection = oldWall->Edge()->IntersectWithCareless( Edge() );
00706 sg_TopologyPoliceCheck( Cycle(), oldWall, this, intersection, true );
00707 }
00708 else
00709 {
00710 sg_TopologyPoliceKill( Cycle() );
00711 }
00712
00713 eWall::SplitByActive( oldWall );
00714 }
00715
00716
00717 bool gPlayerWall::RunsParallelActive( eWall* oldWall )
00718 {
00719 if ( oldWall )
00720 {
00721
00722
00723 eCoord collision = ( oldWall->Point(.5f) + this->Point(.5f) ) *.5f;
00724
00725 sg_TopologyPoliceCheck( Cycle(), oldWall, this, collision, false );
00726 }
00727 else
00728 {
00729 sg_TopologyPoliceKill( Cycle() );
00730 }
00731
00732 return eWall::RunsParallelPassive( oldWall );
00733 }
00734
00735 bool gPlayerWall::Splittable() const{return 1;}
00736
00737 bool gPlayerWall::Deletable() const{
00738 CHECKWALL;
00739
00740
00741 if ( !cycle_ )
00742 return true;
00743
00744 return !IsDangerousAnywhere( se_GameTime() - 1.0f );
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 void gPlayerWall::Split(eWall *& w1,eWall *& w2,REAL a){
00762 CHECKWALL;
00763
00764 gPlayerWall *W1, *W2;
00765
00766 W1=tNEW(gPlayerWall(netWall_,cycle_));
00767 W2=tNEW(gPlayerWall(netWall_,cycle_));
00768 W1->windingNumber_ = windingNumber_;
00769 W2->windingNumber_ = windingNumber_;
00770 W1->begDist_ = begDist_;
00771 W2->endDist_ = endDist_;
00772 W1->endDist_ = W2->begDist_ = begDist_ + ( endDist_ - begDist_ ) * a;
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 w1 = W1;
00800 w2 = W2;
00801
00802 #ifdef DEBUG
00803 W1->Check();
00804 W2->Check();
00805 #endif
00806
00807 CHECKWALL;
00808 }
00809
00810
00811
00812
00813
00814 #define gCYCLE_LEN 1.5
00815 #define gBEG_OFFSET .25
00816 #define gBEG_LEN 2
00817
00818
00819
00820 #ifndef DEDICATED
00821 void gPlayerWall::Render(const eCamera *cam){
00822 if (!cycle_)
00823 return;
00824 RenderList(true);
00825 }
00826
00827 void gNetPlayerWall::Render(const eCamera *cam ){
00828 if (!cycle_)
00829 return;
00830 RenderList(true);
00831 }
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 void gPlayerWall::RenderList(bool list)
00856 {
00857 netWall_->RenderList( list );
00858 }
00859
00860 void gNetPlayerWall::RenderList(bool list, gWallRenderMode renderMode ){
00861 if ( !cycle_ )
00862 {
00863 return;
00864 }
00865
00866 #ifdef DEBUG_X
00867 if ( cycle_->Player()->GetName().StartsWith("B") && dbegin < .1 )
00868 {
00869 int x;
00870 x = 1;
00871 }
00872 #endif
00873
00874
00875
00876 if ( gCycleWallsDisplayListManager::CannotHaveList( dbegin, cycle_ ) ||
00877 this == cycle_->currentWall )
00878 {
00879 ClearDisplayList(2);
00880 }
00881
00882 if ( !displayList_.Call() )
00883 {
00884
00885
00886
00887 rDisplayListFiller filler( displayList_ );
00888
00889 REAL r,g,b;
00890 if (cycle_){
00891 r=cycle_->trailColor_.r;
00892 g=cycle_->trailColor_.g;
00893 b=cycle_->trailColor_.b;
00894 }
00895 else
00896 r=g=b=1;
00897
00898 eCoord P1=EndPoint(0);
00899 eCoord P2=EndPoint(1);
00900
00901 {
00902 eCoord vec = P2-P1;
00903 REAL xs = vec.x*vec.x;
00904 REAL ys = vec.y*vec.y;
00905 REAL intensity = .7 + .3 * xs/(xs+ys);
00906 r *= intensity;
00907 g *= intensity;
00908 b *= intensity;
00909 }
00910
00911 REAL a=1;
00912
00913 #define SEGLEN 2.5
00914
00915
00916 for ( int i = coords_.Len()-2; i>=0; --i )
00917 {
00918 const gPlayerWallCoord* coord = &coords_(i);
00919
00920 if ( !coord[0].IsDangerous )
00921 continue;
00922
00923 REAL pa = coord[0].Pos;
00924 REAL pe = coord[1].Pos;
00925
00926 REAL aa = Alpha( pa );
00927 REAL ae = Alpha( pe );
00928
00929 eCoord p1 = P1 + ( P2 - P1 ) * aa;
00930 eCoord p2 = P1 + ( P2 - P1 ) * ae;
00931
00932 REAL ta=pa/SEGLEN;
00933 REAL te=pe/SEGLEN;
00934
00935
00936
00937 REAL time;
00938 if (cycle_)
00939 {
00940 if ( cycle_->currentWall )
00941 time = cycle_->currentWall->EndPos()/SEGLEN;
00942 else
00943 time=cycle_->GetDistance()/SEGLEN;
00944 if ( !cycle_->Alive() )
00945 time += se_GameTime() - cycle_->deathTime;
00946 }
00947 else
00948 time=0;
00949
00950
00951
00952
00953
00954 if (ta>te){
00955 Swap(ta,te);
00956 Swap(p1,p2);
00957 Swap(pa,pe);
00958 }
00959
00960
00961 if ( bool(cycle_) && gCycle::WallsLength() > 0 )
00962 {
00963 REAL cut = (cycle_->GetDistance() - cycle_->ThisWallsLength() - pe) / ( pa - pe );
00964 if ( cut < 0 )
00965 continue;
00966 if ( cut < 1 )
00967 {
00968 p1 = p2 + (p1-p2)*cut;
00969 ta = te + (ta-te)*cut;
00970 }
00971 }
00972
00973 if (te+gBEG_LEN<=time){
00974 RenderNormal(p1,p2,ta,te,r,g,b,a,renderMode);
00975 sr_CheckGLError();
00976 }
00977
00978 else{
00979
00980 ClearDisplayList();
00981
00982 if (ta+gBEG_LEN>=time){
00983 sr_CheckGLError();
00984 RenderBegin(p1,p2,ta,te,
00985 1+(ta-time)/gBEG_LEN,
00986 1+(te-time)/gBEG_LEN,
00987 r,g,b,a);
00988 sr_CheckGLError();
00989 }
00990 else{
00991 sr_CheckGLError();
00992 REAL s=((time-gBEG_LEN)-ta)/(te-ta);
00993 eCoord pm=p1+(p2-p1)*s;
00994 RenderBegin(pm,p2,
00995 ta+(te-ta)*s,te,0,
00996 1+(te-time)/gBEG_LEN,
00997 r,g,b,a);
00998 RenderNormal(p1,pm,ta,ta+(te-ta)*s,r,g,b,a, gWallRenderMode_All );
00999 sr_CheckGLError();
01000 }
01001 }
01002 }
01003 }
01004 }
01005
01006
01007 inline bool upperlinecolor(REAL r,REAL g,REAL b, REAL a){
01008 if (rTextureGroups::TextureMode[rTextureGroups::TEX_WALL]<0)
01009 glColor4f(1,1,1,a);
01010 else{
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021 glColor4f(r,g,b,a);
01022 }
01023
01024 return true;
01025 }
01026
01027 void gNetPlayerWall::RenderNormal(const eCoord &p1,const eCoord &p2,REAL ta,REAL te,REAL r,REAL g,REAL b,REAL a, gWallRenderMode mode ){
01028 REAL hfrac=1;
01029
01030 if (bool(cycle_) && !cycle_->Alive() && gCycle::WallsStayUpDelay() >= 0 ){
01031 REAL dt=(se_GameTime()-cycle_->deathTime-gCycle::WallsStayUpDelay())*2;
01032
01033 if (dt>1)
01034 {
01035
01036 Remove();
01037 return;
01038 }
01039
01040 if (dt>=0)
01041 {
01042 REAL ca=REAL(.5/(dt+.5));
01043 REAL alpha=1-dt;
01044 if (alpha>1) alpha=1;
01045 hfrac=1-dt;
01046
01047 r+=ca;
01048 b+=ca;
01049 g+=ca;
01050
01051 a*=alpha;
01052 }
01053 }
01054 REAL h=1;
01055
01056
01057 if (hfrac>0){
01058 if ( ( mode & gWallRenderMode_Lines ) ){
01059
01060
01061 if ( mode == gWallRenderMode_All )
01062 {
01063 sr_DepthOffset(true);
01064 if ( rTextureGroups::TextureMode[rTextureGroups::TEX_WALL] != 0 )
01065 {
01066 RenderEnd();
01067 glDisable(GL_TEXTURE_2D);
01068 }
01069 }
01070
01071 BeginLines();
01072 upperlinecolor(r,g,b,a);
01073 glVertex3f(p1.x,p1.y,h*hfrac);
01074 upperlinecolor(r,g,b,a);
01075 glVertex3f(p2.x,p2.y,h*hfrac);
01076
01077
01078
01079 if ( mode == gWallRenderMode_All )
01080 {
01081 RenderEnd();
01082 sr_DepthOffset(false);
01083 if ( rTextureGroups::TextureMode[rTextureGroups::TEX_WALL] != 0 )
01084 glEnable(GL_TEXTURE_2D);
01085 }
01086 }
01087
01088
01089
01090 #ifdef XDEBUG
01091 REAL extrarise = 0;
01092 if ( this->id >= 0 )
01093 {
01094 extrarise = 1;
01095 }
01096 #else
01097 static const REAL extrarise = 0;
01098 #endif
01099 if ( mode & gWallRenderMode_Quads )
01100 {
01101 BeginQuads();
01102
01103 glColor3f(r,g,b);
01104 glTexCoord2f(ta,hfrac);
01105 glVertex3f(p1.x,p1.y,extrarise);
01106
01107 glColor3f(r,g,b);
01108 glTexCoord2f(ta,0);
01109 glVertex3f(p1.x,p1.y,extrarise + h*hfrac);
01110
01111 glColor3f(r,g,b);
01112 glTexCoord2f(te,0);
01113 glVertex3f(p2.x,p2.y,extrarise + h*hfrac);
01114
01115 glColor3f(r,g,b);
01116 glTexCoord2f(te,hfrac);
01117 glVertex3f(p2.x,p2.y,extrarise);
01118
01119
01120
01121 if ( mode == gWallRenderMode_All )
01122 {
01123 RenderEnd();
01124 }
01125 }
01126 }
01127 }
01128
01129 static inline REAL hfunc(REAL x){return 1-(x*x)/2;}
01130
01131 static inline REAL cfunc(REAL x){return (x*x);}
01132
01133 static inline REAL afunc(REAL x){return 1-(x*x);}
01134 static inline REAL sfunc(REAL x){return (x*x);}
01135
01136 static inline REAL xfunc(REAL x){return REAL((x*.2+x*x)/2);}
01137
01138 void gNetPlayerWall::RenderBegin(const eCoord &p1,const eCoord &pp2,REAL ta,REAL te,REAL ra,REAL re,REAL r,REAL g,REAL b,REAL a){
01139 if ( !cycle_ )
01140 {
01141 return;
01142 }
01143
01144 REAL hfrac=1;
01145
01146 eCoord p2 = pp2;
01147
01148 if (re > 1){
01149 if (re > 2)
01150 return;
01151
01152 REAL ratio = (1-ra)/(re-ra);
01153 p2 = p1 + (pp2-p1)*ratio;
01154 te = ta + (te-ta)*ratio;
01155 re= 1;
01156 }
01157
01158 if (bool(cycle_) && !cycle_->Alive()){
01159 REAL dt=(se_GameTime()-cycle_->deathTime-gCycle::WallsStayUpDelay())*2;
01160 if (dt>1) dt=1;
01161 if (dt>0)
01162 {
01163 REAL ca=REAL(.5/(dt+.5));
01164 REAL alpha=1-dt;
01165 if (alpha>1) alpha=1;
01166 hfrac=1-dt;
01167
01168 r+=ca;
01169 b+=ca;
01170 g+=ca;
01171 }
01172
01173 }
01174
01175 REAL h=1;
01176
01177 eCoord ppos=cycle_->PredictPosition() - cycle_->dir*REAL(gCYCLE_LEN);
01178
01179 if ( hfrac>0 ){
01180 sr_DepthOffset(true);
01181
01182 #define segs 5
01183 upperlinecolor(r,g,b,a);
01184
01185 if ( rTextureGroups::TextureMode[rTextureGroups::TEX_WALL] != 0 )
01186 glDisable(GL_TEXTURE_2D);
01187
01188 BeginLineStrip();
01189
01190 for (int i=0;i<=segs;i++){
01191 REAL frag=i/float(segs);
01192 REAL rat=ra+frag*(re-ra);
01193 REAL x=(p1.x+frag*(p2.x-p1.x))*(1-xfunc(rat))+ppos.x*xfunc(rat);
01194 REAL y=(p1.y+frag*(p2.y-p1.y))*(1-xfunc(rat))+ppos.y*xfunc(rat);
01195
01196 REAL H=h*hfrac*hfunc(rat);
01197 upperlinecolor(r,g,b,a*afunc(rat));
01198 glVertex3f(x+H*cycle_->skew*sfunc(rat)*cycle_->dir.y,
01199 y-H*cycle_->skew*sfunc(rat)*cycle_->dir.x,
01200 H);
01201 }
01202 RenderEnd();
01203
01204 sr_DepthOffset(false);
01205 if ( rTextureGroups::TextureMode[rTextureGroups::TEX_WALL] != 0 )
01206 glEnable(GL_TEXTURE_2D);
01207 }
01208
01209 sr_CheckGLError();
01210 BeginQuadStrip();
01211
01212
01213
01214
01215
01216 for (int i=0;i<=segs;i++){
01217 REAL frag=i/float(segs);
01218 REAL rat=ra+frag*(re-ra);
01219 REAL x=(p1.x+frag*(p2.x-p1.x))*(1-xfunc(rat))+ppos.x*xfunc(rat);
01220 REAL y=(p1.y+frag*(p2.y-p1.y))*(1-xfunc(rat))+ppos.y*xfunc(rat);
01221
01222
01223 glColor4f(r+cfunc(rat),g+cfunc(rat),b+cfunc(rat),a*afunc(rat));
01224 glTexCoord2f(ta+(te-ta)*frag,hfrac);
01225 glVertex3f(x,y,0);
01226
01227
01228
01229
01230 glTexCoord2f(ta+(te-ta)*frag,0);
01231 REAL H=h*hfrac*hfunc(rat);
01232 glVertex3f(x+H*cycle_->skew*sfunc(rat)*cycle_->dir.y,
01233 y-H*cycle_->skew*sfunc(rat)*cycle_->dir.x,
01234 H);
01235 }
01236 RenderEnd();
01237 sr_CheckGLError();
01238 }
01239 #endif
01240
01241 void gNetPlayerWall::SetEndTime(REAL t){
01242 CHECKWALL;
01243
01244 REAL BegTime = coords_( coords_.Len() -2 ).Time;
01245 if ( t < BegTime )
01246 {
01247 t = BegTime;
01248 }
01249
01250 coords_(coords_.Len()-1).Time = t;
01251
01252 CHECKWALL;
01253
01254 }
01255
01256 void gNetPlayerWall::SetEndPos(REAL ep){
01257 CHECKWALL;
01258
01259 REAL BegPos = coords_( coords_.Len() -2 ).Pos;
01260 if ( ep < BegPos )
01261 {
01262 ep = BegPos;
01263 }
01264
01265 coords_(coords_.Len()-1).Pos = ep;
01266
01267 CHECKWALL;
01268 }
01269
01270 REAL gPlayerWall::BlockHeight() const{
01271 if (bool(cycle_) && cycle_->Alive()==1)
01272 return 1;
01273 else
01274 return 0;
01275 }
01276
01277 REAL gPlayerWall::SeeHeight() const{
01278 return BlockHeight();
01279 }
01280
01281
01282 gCycle *gPlayerWall::Cycle() const {return cycle_;}
01283 gCycleMovement *gPlayerWall::CycleMovement() const {return cycle_;}
01284 gNetPlayerWall *gPlayerWall::NetWall() const {return netWall_;}
01285
01286 void gPlayerWall::Insert()
01287 {
01288 CHECKWALL;
01289
01290 eWall::Insert();
01291 }
01292
01293 void gPlayerWall::Check() const
01294 {
01295 netWall_->Check();
01296 #ifdef DEBUG
01297 REAL range = 5 * fabs(begDist_) + fabs(endDist_) * EPS;
01298 tASSERT( begDist_ <= endDist_ + range );
01299 tASSERT( begDist_ >= netWall_->Pos( 0 ) - range );
01300 tASSERT( endDist_ <= netWall_->Pos( 1 ) + range );
01301 #endif
01302 }
01303
01304 REAL gPlayerWall::LocalToGlobal( REAL a ) const
01305 {
01306 CHECKWALL;
01307
01308 tASSERT( good( a ) );
01309
01310 REAL dist = begDist_ + a * ( endDist_ - begDist_ );
01311 REAL ret = netWall_->Alpha( dist );
01312
01313 tASSERT( good( ret ) );
01314
01315 return ret;
01316 }
01317
01318 void gNetPlayerWall::ClearDisplayList( int inhibitThis, int inhibitCycle )
01319 {
01320 #ifndef DEDICATED
01321 if ( CanHaveDisplayList() && cycle_ && inhibitCycle >= 0 )
01322 {
01323 cycle_->displayList_.Clear( inhibitCycle );
01324 }
01325 displayList_.Clear( inhibitThis );
01326 #endif
01327 }
01328
01329 REAL gPlayerWall::GlobalToLocal( REAL a ) const
01330 {
01331 CHECKWALL;
01332
01333 tASSERT( good( a ) );
01334
01335 REAL dist = netWall_->Pos( a );
01336
01337 REAL div = ( endDist_ - begDist_ );
01338 if ( div == 0 )
01339 {
01340 return .5f;
01341 }
01342 else
01343 {
01344 REAL ret = ( dist - begDist_ ) / div;
01345
01346 tASSERT( good( ret ) );
01347
01348 return ret;
01349 }
01350 }
01351
01352 REAL gPlayerWall::Time(REAL a) const
01353 {
01354 tASSERT( good( a ) );
01355
01356 return netWall_->Time( LocalToGlobal( a ) );
01357 }
01358
01359 REAL gPlayerWall::Pos(REAL a) const
01360 {
01361 CHECKWALL;
01362
01363 tASSERT( good( a ) );
01364
01365 return begDist_ + ( endDist_ - begDist_ ) * a;
01366 }
01367
01368 REAL gPlayerWall::Alpha(REAL pos) const
01369 {
01370 CHECKWALL;
01371
01372 REAL diff = ( endDist_ - begDist_ );
01373 REAL a = pos - begDist_;
01374
01375 if ( diff > 0 )
01376 a /= diff;
01377
01378 tASSERT ( -.001 < a );
01379 tASSERT ( 1.001 > a );
01380
01381 return a;
01382 }
01383
01384 bool gPlayerWall::IsDangerousAnywhere( REAL time ) const
01385 {
01386 CHECKWALL;
01387
01388 return netWall_->IsDangerousAnywhere( time );
01389 }
01390
01391 bool gPlayerWall::IsDangerous( REAL a, REAL time ) const
01392 {
01393 CHECKWALL;
01394
01395 return netWall_->IsDangerous( LocalToGlobal( a ), time );
01396 }
01397
01398
01399 gExplosion * gPlayerWall::Holer( REAL a, REAL time ) const
01400 {
01401 CHECKWALL;
01402
01403 return netWall_->Holer( LocalToGlobal( a ), time );
01404 }
01405
01406 REAL gPlayerWall::EndPos() const
01407 {
01408 CHECKWALL;
01409
01410 return this->endDist_;
01411 }
01412
01413 REAL gPlayerWall::BegPos() const
01414 {
01415 CHECKWALL;
01416
01417 return this->begDist_;
01418 }
01419
01420 REAL gPlayerWall::EndTime() const
01421 {
01422 CHECKWALL;
01423
01424 return netWall_->Time( netWall_->Alpha( this->endDist_ ) );
01425 }
01426
01427 REAL gPlayerWall::BegTime() const
01428 {
01429 CHECKWALL;
01430
01431 return netWall_->Time( netWall_->Alpha( this->begDist_ ) );
01432 }
01433
01434 void gPlayerWall::BlowHole ( REAL beg, REAL end, gExplosion * holer )
01435 {
01436 CHECKWALL;
01437
01438 this->netWall_->BlowHole( beg, end, holer );
01439 }
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474 tList<gNetPlayerWall> sg_netPlayerWalls;
01475 tList<gNetPlayerWall> sg_netPlayerWallsGridded;
01476
01477
01478 void gNetPlayerWall::CreateEdge()
01479 {
01480 if ( this->edge_ )
01481 return;
01482
01483 if (this->cycle_)
01484 {
01485 gPlayerWall* w = tNEW(gPlayerWall)(this,
01486 this->cycle_);
01487
01488 this->edge_=tNEW(eTempEdge)(beg,
01489 end,
01490 w );
01491 }
01492 else
01493 {
01494 this->edge_ = NULL;
01495 return;
01496 }
01497 }
01498
01499 void gNetPlayerWall::InitAfterCreation()
01500 {
01501 nNetObject::InitAfterCreation();
01502 MyInitAfterCreation();
01503 }
01504
01505 void gNetPlayerWall::InitArray()
01506 {
01507 REAL ep = dbegin+sqrt((beg-end).NormSquared());
01508 REAL sp = dbegin;
01509
01510 if ( ep < sp )
01511 {
01512 ep = sp;
01513 }
01514
01515 if ( tEnd < tBeg )
01516 {
01517 tEnd = tBeg;
01518 }
01519
01520 coords_.SetLen(2);
01521 coords_[0].Pos = sp;
01522 coords_[0].Time = tBeg;
01523 coords_[0].IsDangerous = true;
01524 coords_[1].Pos = ep;
01525 coords_[1].Time = tEnd;
01526 coords_[1].IsDangerous = true;
01527 }
01528
01529 void gNetPlayerWall::MyInitAfterCreation()
01530 {
01531 #ifndef DEDICATED
01532
01533 if ( cycle_ )
01534 {
01535 Insert( cycle_->displayList_.wallList_ );
01536 }
01537 #endif
01538
01539
01540 #ifdef DEBUG
01541 if (!finite(end.x) || !finite(end.y))
01542 st_Breakpoint();
01543
01544 if (!finite(beg.x) || !finite(beg.y))
01545 st_Breakpoint();
01546 #endif
01547
01548 if ( coords_.Len() < 2 )
01549 {
01550 InitArray();
01551 }
01552
01553 CreateEdge();
01554
01555 id=-1;
01556 griddedid=-1;
01557 sg_netPlayerWalls.Add(this,id);
01558
01559 if ( !Wall() )
01560 return;
01561 tASSERT( Wall()->Splittable() );
01562
01563 for (int i=MAX_VIEWERS-1;i>=0;i--)
01564 Wall()->SetVisHeight(i,0);
01565
01566 Wall()->Remove();
01567
01568 displayList_.Clear(2);
01569 }
01570
01571
01572
01573 gNetPlayerWall::gNetPlayerWall(gCycle *cyc,
01574 const eCoord &begi,const eCoord &d,
01575 REAL tBegi, REAL dbeg)
01576 :nNetObject(cyc->Owner()),
01577 id(-1),griddedid(-1),
01578 cycle_(cyc),lastWall_(NULL),dir(d),dbegin(dbeg),
01579 beg(begi),end(begi),tBeg(tBegi),tEnd(tBegi),
01580 inGrid(false){
01581 dir=dir;
01582 preliminary=(sn_GetNetState()==nCLIENT);
01583 obsoleted_=-100;
01584 gridding=1E+20;
01585 MyInitAfterCreation();
01586 }
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612 void gNetPlayerWall::Update(REAL Tend,const eCoord &pend)
01613 {
01614 CHECKWALL;
01615
01616 if (!inGrid && ( preliminary || sn_GetNetState() != nCLIENT ) )
01617 {
01618 real_Update( Tend, pend, false );
01619 }
01620
01621 CHECKWALL;
01622 }
01623
01624 void gNetPlayerWall::real_Update(REAL Tend,const eCoord &pend, bool force )
01625 {
01626
01627 if ( coords_.Len() >= 2 && coords_[ coords_.Len()-2 ].IsDangerous != coords_[ coords_.Len()-1 ].IsDangerous )
01628 {
01629 Checkpoint();
01630 }
01631
01632 tEnd=Tend;
01633 end=pend;
01634
01635
01636 REAL forward = eCoord::F( end-beg, dir )/dir.NormSquared();
01637 if ( forward < 0 )
01638 {
01639 end = beg;
01640 tEnd = tBeg;
01641 }
01642
01643 #ifdef DEBUG
01644 if (!finite(end.x) || !finite(end.y))
01645 st_Breakpoint();
01646 #endif
01647
01648 eCoord odir=dir.Turn(0,1);
01649 REAL x=eCoord::F(odir,(end-beg))/dir.NormSquared();
01650 beg=beg+odir*x;
01651
01652 if (bool( this->edge_ ) && this->edge_->Point(0) && this->edge_->Point(1)){
01653 this->edge_->Coord(1) = end;
01654 if ( !lastWall_ )
01655 this->edge_->Coord(0) = beg;
01656 }
01657
01658
01659 REAL endPos = 0;
01660
01661
01662
01663
01664
01665 {
01666 endPos = dbegin + eCoord::F(dir, end - beg )/dir.NormSquared();
01667 }
01668
01669
01670 {
01671 int len = coords_.Len();
01672 while ( len >= 3 && coords_[len-2].IsDangerous == coords_[len-1].IsDangerous && coords_[len-2].Pos > endPos )
01673 {
01674 coords_[len-2] = coords_[len-1];
01675 coords_.SetLen(len - 1);
01676 len = coords_.Len();
01677 }
01678 }
01679
01680
01681 SetEndTime(tEnd);
01682 SetEndPos(endPos);
01683
01684
01685 gPlayerWall *w = Wall();
01686
01687 if ( w )
01688 {
01689 w->CalcLen();
01690 if ( !lastWall_ )
01691 w->begDist_ = dbegin;
01692 w->endDist_ = EndPos();
01693 #ifdef DEBUG
01694 w->Check();
01695 #endif
01696 }
01697 }
01698
01699 void gNetPlayerWall::Checkpoint()
01700 {
01701 CHECKWALL;
01702
01703
01704 int len = coords_.Len();
01705
01706
01707 coords_[len] = gPlayerWallCoord( coords_[len-1] );
01708
01709 CHECKWALL;
01710 }
01711
01712 void gNetPlayerWall::CopyIntoGrid(eGrid * grid, bool force){
01713 tJUST_CONTROLLED_PTR< gNetPlayerWall > keep( this );
01714
01715 if (!inGrid && (force ||
01716 (sn_GetNetState()!=nCLIENT || preliminary))){
01717 inGrid=true;
01718 gridding=REAL(se_GameTime()+1.0);
01719 if (sn_GetNetState()==nCLIENT)
01720 {
01721
01722 gridding=se_GameTime()+40*sn_Connections[0].ping+10;
01723
01724
01725 if ( obsoleted_ > tEnd - .003f || !preliminary )
01726 {
01727 if ( grid )
01728 real_CopyIntoGrid( grid );
01729 else
01730 gridding=REAL(se_GameTime()+.000001);
01731 }
01732 }
01733 else
01734 {
01735
01736 RequestSync();
01737 if ( grid )
01738 real_CopyIntoGrid( grid );
01739 else
01740 gridding=REAL(se_GameTime()+.000001);
01741 }
01742 }
01743 }
01744
01745 void gNetPlayerWall::real_CopyIntoGrid(eGrid *grid){
01746
01747
01748
01749 tJUST_CONTROLLED_PTR< gNetPlayerWall > keep( this );
01750
01751 #ifdef DEBUG
01752 grid->Check();
01753 #endif
01754
01755 if (griddedid<0){
01756 if ( this->cycle_ )
01757 {
01758 tASSERT( static_cast< bool >(this->edge_) );
01759 tASSERT(Wall());
01760 tASSERT(Wall()->Splittable());
01761
01762 if (preliminary){
01763
01764 tControlledPTR< nNetObject > bounce( this );
01765
01766 sg_netPlayerWalls.Remove(this,id);
01767 sg_netPlayerWallsGridded.Add(this,griddedid);
01768 Wall()->Insert();
01769 this->ReleaseData();
01770 ClearDisplayList();
01771 }
01772 else{
01773 sg_netPlayerWallsGridded.Add(this,griddedid);
01774 sg_netPlayerWalls.Remove(this,id);
01775 if ( this->edge_ ){
01776 Wall()->Insert();
01777 this->edge_->CopyIntoGrid(this->cycle_->Grid());
01778 this->edge_ = NULL;
01779 }
01780 }
01781 }
01782 }
01783
01784 #ifdef DEBUG
01785 grid->Check();
01786 #endif
01787
01788 }
01789
01790 void gNetPlayerWall::PartialCopyIntoGrid(eGrid *grid){
01791
01792
01793
01794 tJUST_CONTROLLED_PTR< gNetPlayerWall > keep( this );
01795
01796 #ifdef DEBUG
01797 grid->Check();
01798 #endif
01799
01800 if (griddedid<0 && bool(this->cycle_) && !preliminary ){
01801
01802
01803 if ( this->edge_ ){
01804 lastWall_ = Wall();
01805 Wall()->Insert();
01806 this->edge_->CopyIntoGrid(grid);
01807 this->edge_ = NULL;
01808 }
01809
01810
01811 gPlayerWall* w = tNEW(gPlayerWall)(this,
01812 this->cycle_);
01813 this->edge_=tNEW(eTempEdge)(end,
01814 end,
01815 w );
01816
01817
01818 w->Remove();
01819
01820
01821 w->begDist_ = w->endDist_;
01822 }
01823
01824
01825
01826
01827
01828 #ifdef DEBUG
01829 grid->Check();
01830 #endif
01831
01832 }
01833
01834 void gNetPlayerWall::s_CopyIntoGrid()
01835 {
01836 #ifdef DEBUG
01837 static int maxw=20;
01838 if (sg_netPlayerWalls.Len()>maxw)
01839 con << "Many walls: " << (maxw=sg_netPlayerWalls.Len()) << '\n';
01840 #endif
01841
01842 for (int i=sg_netPlayerWalls.Len()-1;i>=0;i--){
01843 gNetPlayerWall *w=sg_netPlayerWalls(i);
01844 if (w->inGrid && w->griddedid<0 && se_GameTime()>w->gridding)
01845 w->real_CopyIntoGrid(w->cycle_->Grid());
01846 }
01847 }
01848
01849 void gNetPlayerWall::RealWallReceived( gNetPlayerWall* realWall )
01850 {
01851 if (this->cycle_ )
01852 {
01853 tASSERT( realWall );
01854 tASSERT( preliminary && !realWall->preliminary );
01855
01856
01857 if ( tBeg + tEnd < 2 * realWall->tEnd )
01858 {
01859 REAL maxGridding=se_GameTime() + 2*sn_Connections[0].ping;
01860 if ( gridding > maxGridding )
01861 gridding = maxGridding;
01862 }
01863
01864
01865 REAL overlap = 0;
01866 {
01867 REAL tEndThis = tEnd;
01868
01869 if ( sr_predictObjects && this->cycle_->currentWall == this && Owner() != sn_myNetID )
01870 {
01871 tEndThis -= this->cycle_->Lag();
01872 }
01873
01874 REAL tBegMin = tBeg;
01875 REAL tBegMax = realWall->tBeg;
01876 if ( tBegMin > tBegMax )
01877 {
01878 tBegMin = realWall->tBeg;
01879 tBegMax = tBeg;
01880 }
01881
01882 REAL tEndMin = tEndThis;
01883
01884 REAL tEndMax = realWall->tEnd;
01885 if ( tEndMin > tEndMax )
01886 {
01887 tEndMin = realWall->tEnd;
01888 tEndMax = tEndThis;
01889 }
01890
01891 REAL denominator = tEndMax - tBegMin;
01892 if ( denominator > 0 )
01893 overlap = ( tEndMin - tBegMax ) / denominator;
01894 }
01895
01896
01897 if ( overlap > 0 && fabs( dir * realWall->dir ) > 10 * EPS )
01898 overlap = 0;
01899
01900
01901 if ( overlap < .8 )
01902 return;
01903
01904
01905 obsoleted_ = realWall->tEnd;
01906
01907
01908 if (this->cycle_->currentWall!=this )
01909 {
01910
01911 if (this->cycle_->lastWall==this)
01912 {
01913 this->cycle_->lastWall=realWall;
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924 }
01925
01926
01927 this->real_CopyIntoGrid( this->cycle_->Grid() );
01928 }
01929 }
01930 }
01931
01932
01933 void gNetPlayerWall::WriteCreate(nMessage &m)
01934 {
01935 tASSERT( this->cycle_ );
01936
01937 nNetObject::WriteCreate(m);
01938 m.Write(this->cycle_->ID());
01939 m << beg;
01940 m << dir;
01941 m << dbegin;
01942 m << tBeg;
01943 m << static_cast<int>(preliminary);
01944 }
01945
01946 gNetPlayerWall::gNetPlayerWall(nMessage &m)
01947 :nNetObject(m),
01948 id(-1),griddedid(-1),
01949 cycle_(NULL),edge_(NULL), lastWall_(NULL),
01950 dir(0,0),dbegin(0),
01951 beg(0,0),end(0,0),
01952 tBeg(0),tEnd(0),
01953 inGrid(0)
01954 {
01955 unsigned short cid;
01956 gridding=1E+20;
01957 m.Read(cid);
01958 cycle_=static_cast<gCycle *>(Object(cid));
01959
01960 m >> beg;
01961 end=beg;
01962 m >> dir;
01963 m >> dbegin;
01964
01965 m >> tBeg;
01966 {
01967 int preliminary;
01968 m >> preliminary;
01969 this->preliminary = preliminary;
01970 }
01971
01972 obsoleted_=-100;
01973
01974 this->InitArray();
01975 }
01976
01977 eCoord gNetPlayerWall::Vec()
01978 {
01979 if ( edge_ ) return edge_->Vec();
01980 else return eCoord();
01981 }
01982
01983 gPlayerWall *gNetPlayerWall::Wall(){
01984 if (this->edge_)
01985 {
01986 eWall *w = this->edge_->Wall();
01987
01988 return reinterpret_cast<gPlayerWall *>(w);
01989 }
01990 else
01991 return NULL;
01992 }
01993
01994 void gNetPlayerWall::ReleaseData()
01995 {
01996 if (this->cycle_){
01997 if (this->cycle_->currentWall==this)
01998 this->cycle_->currentWall=NULL;
01999 if (this->cycle_->lastWall==this)
02000 this->cycle_->lastWall=NULL;
02001 if (this->cycle_->lastNetWall==this)
02002 this->cycle_->lastNetWall=NULL;
02003 }
02004
02005
02006
02007 if (this->edge_)
02008 {
02009 if ( this->edge_->Wall() )
02010 this->edge_->Wall()->Insert();
02011
02012 this->edge_ = NULL;
02013
02014
02015 }
02016
02017 this->cycle_=NULL;
02018 this->edge_=NULL;
02019
02020
02021 sg_netPlayerWalls.Remove(this,id);
02022 sg_netPlayerWallsGridded.Remove(this,griddedid);
02023 }
02024
02025 gNetPlayerWall::~gNetPlayerWall()
02026 {
02027 ReleaseData();
02028 ClearDisplayList();
02029 }
02030
02031 bool gNetPlayerWall::ActionOnQuit()
02032 {
02033 if ( sn_GetNetState() == nSERVER )
02034 {
02035 TakeOwnership();
02036 return false;
02037 }
02038 else
02039 {
02040 ReleaseData();
02041
02042 return true;
02043 }
02044 }
02045
02046 bool gNetPlayerWall::ClearToTransmit(int user) const{
02047 #ifdef DEBUG
02048 if (nNetObject::DoDebugPrint() && bool( this->cycle_ ) )
02049 {
02050 if (!GridIsReady(user))
02051 con << "Not transfering gNetPlayerWall " << ID()
02052 << " for user " << user << " because the grid is not ready yet.\n";
02053 else if (!this->cycle_)
02054 con << "Not transfering gNetPlayerWall " << ID()
02055 << " for user " << user << " because it has no cycle!\n";
02056 else if (!this->cycle_->HasBeenTransmitted(user))
02057 {
02058 tString s;
02059 s << "No transfering gNetPlayerWall " << ID()
02060 << " for user " << user << " because ";
02061 this->cycle_->PrintName(s);
02062 s << " has not been transmitted.\n";
02063 con << s;
02064 }
02065 }
02066 #endif
02067
02068 return GridIsReady(user) && nNetObject::ClearToTransmit(user)
02069 && bool(this->cycle_) && this->cycle_->HasBeenTransmitted(user) && inGrid;
02070 }
02071
02072 void gNetPlayerWall::WriteSync(nMessage &m){
02073 nNetObject::WriteSync(m);
02074
02075 if (inGrid){
02076 m << end;
02077 m << tEnd;
02078 }
02079 else{
02080 m << beg;
02081 m << tBeg;
02082 }
02083 m.Write(inGrid);
02084
02085 if ( coords_.Len() > 2 || !coords_(0).IsDangerous || !coords_(1).IsDangerous )
02086 {
02087 unsigned short len = coords_.Len();
02088 m.Write( len );
02089 for ( int i = len-1; i>=0; --i )
02090 {
02091 const gPlayerWallCoord& coord = coords_(i);
02092 m << coord.IsDangerous;
02093 m << coord.Pos;
02094 m << coord.Time;
02095 }
02096 }
02097 }
02098
02099 bool gNetPlayerWall::SyncIsNew(nMessage &m)
02100 {
02101
02102 return nNetObject::SyncIsNew(m);
02103 }
02104
02105 static bool sg_ServerSentHoles = false;
02106
02107 void gNetPlayerWall::ReadSync(nMessage &m){
02108 nNetObject::ReadSync(m);
02109
02110 ClearDisplayList();
02111
02112 REAL tEnd_new;
02113 eCoord end_new;
02114
02115 m >> end_new;
02116 m >> tEnd_new;
02117
02118 if ( tEnd_new < tBeg )
02119 {
02120 tEnd_new = tBeg;
02121 }
02122
02123 unsigned short new_inGrid;
02124 m.Read(new_inGrid);
02125
02126 if ( griddedid < 0 )
02127 CreateEdge();
02128
02129 if ( ! m.End() )
02130 {
02131 unsigned short len;
02132 m.Read( len );
02133
02134 coords_.SetLen( len );
02135
02136 for ( int i = len-1; i>=0; --i )
02137 {
02138 gPlayerWallCoord& coord = coords_(i);
02139 m >> coord.IsDangerous;
02140 m >> coord.Pos;
02141 m >> coord.Time;
02142 }
02143
02144 sg_ServerSentHoles = true;
02145 }
02146
02147 real_Update(tEnd_new,end_new, true);
02148
02149 if (Wall() && new_inGrid && !inGrid)
02150 {
02151
02152
02153
02154
02155
02156
02157
02158 CopyIntoGrid( NULL, true );
02159
02160 if (!preliminary)
02161 {
02162
02163 for (int i=sg_netPlayerWalls.Len()-1;i>=0;i--)
02164 {
02165 gNetPlayerWall *o=sg_netPlayerWalls[i];
02166 if ( o != this && o->preliminary && o->cycle_ == this->cycle_ )
02167 {
02168 o->RealWallReceived( this );
02169 }
02170 }
02171
02172
02173 if ( ( 0 != this->cycle_ ) && ( !this->cycle_->lastNetWall || this->cycle_->lastNetWall->tBeg < this->tBeg ) )
02174 {
02175 this->cycle_->lastNetWall = this;
02176 }
02177 }
02178 }
02179 else
02180 {
02181
02182 }
02183
02184 #ifdef DEBUG
02185 if ( Wall() )
02186 Wall()->Check();
02187 #endif
02188 }
02189
02190 static nNOInitialisator<gNetPlayerWall> gNetPlayerWall_init(300,"gNetPlayerWall");
02191
02192 nDescriptor &gNetPlayerWall::CreatorDescriptor() const
02193 {
02194 return gNetPlayerWall_init;
02195 }
02196
02197 void gNetPlayerWall::PrintName(tString &s) const
02198 {
02199 s << "gNetPlayerWall nr. " << id;
02200 if ( this->cycle_ )
02201 {
02202 s << " owned by ";
02203 this->cycle_->PrintName( s );
02204 }
02205 }
02206
02207 gCycleMovement *gNetPlayerWall::CycleMovement() const {
02208 return cycle_;
02209 }
02210
02211 void gNetPlayerWall::Clear()
02212 {
02213
02214
02215
02216 int i;
02217 for (i=sg_netPlayerWalls.Len()-1;i>=0;i--){
02218
02219
02220 gNetPlayerWall* w = sg_netPlayerWalls(i);
02221 tControlledPTR< nNetObject > bounce( w );
02222 w->ReleaseData();
02223
02224 sg_netPlayerWalls.Remove( w, w->id );
02225
02226 if ( w->edge_ )
02227 w->edge_->Wall()->Insert();
02228
02229 }
02230 for (i=sg_netPlayerWallsGridded.Len()-1;i>=0;i--){
02231
02232 gNetPlayerWall* w = sg_netPlayerWallsGridded(i);
02233 tControlledPTR< nNetObject > bounce( w );
02234 w->ReleaseData();
02235
02236 sg_netPlayerWallsGridded.Remove( w, w->griddedid );
02237 }
02238 }
02239
02240
02241 void gNetPlayerWall::Check() const
02242 {
02243 #ifdef DEBUG
02244 int i;
02245 for ( i = coords_.Len() -2 ; i>=0; --i )
02246 {
02247 gPlayerWallCoord* coords = &( coords_( i ) );
02248 tASSERT( coords[0].Pos <= coords[1].Pos );
02249 tASSERT( coords[0].Time <= coords[1].Time );
02250 }
02251
02252 for ( i = coords_.Len() -1 ; i>=0; --i )
02253 {
02254 gPlayerWallCoord* coords = &( coords_( i ) );
02255 tASSERT( finite( coords[0].Pos ) );
02256 tASSERT( finite( coords[0].Time ) );
02257 }
02258 #endif
02259 }
02260
02261 int gNetPlayerWall::IndexPos(REAL d) const
02262 {
02263 CHECKWALL;
02264
02265
02266
02267 int i = coords_.Len() - 2;
02268 while ( i >= 1 && coords_(i).Pos >= d)
02269 --i;
02270
02271 #ifdef DEBUG
02272 if (!( i >= 0 && i < coords_.Len() - 1 ))
02273 {
02274 st_Breakpoint();
02275 }
02276 #endif
02277
02278 return i;
02279 }
02280
02281 int gNetPlayerWall::IndexAlpha(REAL a) const
02282 {
02283 CHECKWALL;
02284
02285 REAL d = Pos( a );
02286
02287 return IndexPos( d );
02288 }
02289
02290 REAL gNetPlayerWall::Time(REAL a) const
02291 {
02292 tASSERT( good( a ) );
02293
02294 CHECKWALL;
02295
02296 const gPlayerWallCoord* coord = &coords_(IndexAlpha(a));
02297 REAL div = ( coord[1].Pos - coord[0].Pos );
02298 REAL alpha = 0.0f;
02299 if ( div > 0 )
02300 {
02301 alpha = ( Pos(a) - coord[0].Pos ) / div;
02302 }
02303
02304 REAL ret = coord[0].Time + alpha*(coord[1].Time-coord[0].Time);
02305
02306 tASSERT( good( ret ) );
02307
02308 return ret;
02309 }
02310
02311 REAL gNetPlayerWall::Pos(REAL a) const
02312 {
02313 CHECKWALL;
02314
02315 tASSERT( good( a ) );
02316
02317 REAL ret = BegPos() + a * ( EndPos() - BegPos() );
02318
02319 tASSERT( good( ret ) );
02320
02321 return ret;
02322 }
02323
02324 REAL gNetPlayerWall::Alpha(REAL pos) const
02325 {
02326 CHECKWALL;
02327
02328 REAL diff = ( EndPos() - BegPos() );
02329 REAL a = pos - BegPos();
02330
02331 if ( diff > 0 )
02332 a /= diff;
02333
02334 tASSERT ( -.001 < a );
02335 tASSERT ( 1.001 > a );
02336
02337 return a;
02338 }
02339
02340 bool gNetPlayerWall::IsDangerousAnywhere( REAL time ) const
02341 {
02342 CHECKWALL;
02343
02344 if ( !cycle_ )
02345 return false;
02346
02347
02348 if ( gCycle::WallsStayUpDelay() >= 0 )
02349 {
02350 if ( !cycle_->Alive() && time - cycle_->deathTime > .2f + gCycle::WallsStayUpDelay() )
02351 return false;
02352 }
02353
02354
02355 if ( gCycle::WallsLength() > 0 )
02356 {
02357 tASSERT( cycle_->MaxWallsLength() >= cycle_->ThisWallsLength() );
02358 REAL maxDist = cycle_->GetDistance() - cycle_->MaxWallsLength();
02359 if ( maxDist > EndPos() && maxDist > BegPos() )
02360 {
02361 return false;
02362 }
02363 }
02364
02365 return true;
02366 }
02367
02368 bool gNetPlayerWall::IsDangerousApartFromHoles( REAL a, REAL time ) const
02369 {
02370 CHECKWALL;
02371
02372
02373 if ( gCycle::WallsStayUpDelay() >= 0.0f )
02374 {
02375
02376 if (!cycle_ || !cycle_->Alive() && cycle_->deathTime+ gCycle::WallsStayUpDelay()+0.2f<=time)
02377 return false;
02378 }
02379
02380
02381
02382 REAL dt = ( time - cycle_->lastTime );
02383
02384
02385 REAL wallDistance = Pos( a );
02386
02387
02388 if ( gCycle::WallsLength() > 0 )
02389 {
02390
02391 REAL cycleDistance = cycle_->GetDistance();
02392
02393
02394 if ( cycle_->Alive() )
02395 {
02396
02397 cycleDistance += cycle_->WallEndSpeed() * dt;
02398 }
02399
02400 if ( wallDistance + cycle_->ThisWallsLength() < cycleDistance )
02401 return false;
02402 }
02403
02404
02405 {
02406
02407 REAL cycleDistance = cycle_->GetDistance();
02408
02409
02410 if ( cycle_->Alive() && dt > 0 )
02411 {
02412
02413 cycleDistance += cycle_->Speed() * cycle_->rubberSpeedFactor * dt;
02414 }
02415
02416
02417 if ( wallDistance > cycleDistance )
02418 return false;
02419 }
02420
02421 return true;
02422 }
02423
02424 bool gNetPlayerWall::IsDangerous( REAL a, REAL time ) const
02425 {
02426 CHECKWALL;
02427
02428 if ( !IsDangerousApartFromHoles( a, time ) )
02429 {
02430 return false;
02431 }
02432
02433 const gPlayerWallCoord* coord = &coords_(IndexAlpha(a));
02434 return coord->IsDangerous;
02435 }
02436
02437
02438 gExplosion * gNetPlayerWall::Holer( REAL a, REAL time ) const
02439 {
02440 CHECKWALL;
02441
02442
02443
02444 if ( !IsDangerousApartFromHoles( a, time ) )
02445 {
02446 return false;
02447 }
02448
02449 const gPlayerWallCoord* coord = &coords_(IndexAlpha(a));
02450 return coord->holer;
02451 }
02452
02453 REAL gNetPlayerWall::EndPos() const
02454 {
02455 CHECKWALL;
02456
02457 return coords_(coords_.Len()-1).Pos;
02458 }
02459
02460 REAL gNetPlayerWall::BegPos() const
02461 {
02462 CHECKWALL;
02463
02464 return coords_(0).Pos;
02465 }
02466
02467 REAL gNetPlayerWall::EndTime() const
02468 {
02469 CHECKWALL;
02470
02471 return coords_(coords_.Len()-1).Time;
02472 }
02473
02474 REAL gNetPlayerWall::BegTime() const
02475 {
02476 CHECKWALL;
02477
02478 return coords_(0).Time;
02479 }
02480
02481 void gNetPlayerWall::BlowHole ( REAL beg, REAL end, gExplosion * holer )
02482 {
02483 CHECKWALL;
02484
02485 #ifndef DEDICATED
02486 ClearDisplayList(60);
02487 #endif
02488
02489 #ifdef DEBUG
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501 #endif
02502
02503
02504 if ( sn_GetNetState() != nSERVER && sg_ServerSentHoles && !preliminary )
02505 {
02506 return;
02507 }
02508
02509 #ifdef DEBUG
02510 tASSERT (coords_.Len() < 1000 );
02511 #endif
02512
02513
02514 int begind = IndexPos( beg );
02515
02516
02517 while ( begind >= 1 && !coords_[begind].IsDangerous )
02518 {
02519 beg = coords_[begind].Pos;
02520 begind--;
02521 }
02522
02523
02524 int endind = IndexPos( end );
02525
02526
02527 while ( endind < coords_.Len() - 2 && !coords_[endind].IsDangerous )
02528 {
02529 endind++;
02530 end = coords_[endind].Pos;
02531 }
02532
02533 if ( beg < BegPos() )
02534 {
02535 begind = -1;
02536
02537 beg = BegPos();
02538 }
02539
02540 if ( end > EndPos() )
02541 {
02542 if ( bool(cycle_) && ( EndPos() < cycle_->GetDistance()-10 || this != cycle_->currentWall ) )
02543 endind = coords_.Len() - 1;
02544
02545 end = EndPos();
02546 }
02547
02548
02549 if ( end < beg )
02550 {
02551 return;
02552 }
02553
02554 if ( sn_GetNetState() != nCLIENT )
02555 {
02556 this->RequestSync();
02557 }
02558
02559
02560 REAL begalph = Alpha( beg );
02561 REAL endalph = Alpha( end );
02562
02563
02564 REAL begtime = Time( begalph );
02565 REAL endtime = Time( endalph );
02566
02567 int insert = begind + 2 - endind;
02568
02569 #ifdef DEBUG
02570 tASSERT (insert < 40 );
02571 #endif
02572
02573
02574 if ( insert < 0 )
02575 {
02576 for ( int i = begind+1; i - insert < coords_.Len(); ++i )
02577 coords_(i) = coords_( i - insert );
02578 coords_.SetLen( coords_.Len() + insert );
02579 }
02580
02581
02582 else if ( insert > 0 )
02583 {
02584 coords_.SetLen( coords_.Len() + insert );
02585
02586 for ( int i = coords_.Len() - 1; i >= begind + insert && i >= insert ; --i )
02587 coords_( i ) = coords_( i - insert );
02588 }
02589
02590
02591 {
02592 if ( begind >= 0 )
02593 {
02594 REAL beforetime = coords_(begind).Time;
02595 if ( begtime < beforetime )
02596 {
02597 begtime = beforetime;
02598 }
02599 }
02600
02601 if ( begind +3 < coords_.Len() )
02602 {
02603 REAL afttime = coords_(begind + 3).Time;
02604 if ( endtime > afttime )
02605 {
02606 endtime = afttime;
02607 }
02608 }
02609 }
02610
02611
02612 coords_(begind+1).IsDangerous = false;
02613 coords_(begind+1).Time = begtime;
02614 coords_(begind+1).holer = holer;
02615 coords_(begind+1).Pos = beg;
02616 coords_(begind+2).Time = endtime;
02617 coords_(begind+2).Pos = end;
02618
02619 #ifdef DEBUG
02620
02621
02622
02623
02624
02625
02626
02627 #endif
02628
02629 CHECKWALL;
02630 }
02631
02632 static void login_callback(){
02633 sg_ServerSentHoles = false;
02634 }
02635
02636 static nCallbackLoginLogout sg_LoginLogout(&login_callback);
02637
02638