////////////////////////////////////////////////////////////////////////// // findDistanceByAttenuation BcF32 ScnLightComponent::findDistanceByAttenuation( BcF32 Attenuation ) const { // If we want it at a low value, return max distance. if( Attenuation < 0.05f ) { Attenuation = 0.05f; } BcF32 A = AttnQ_; BcF32 B = AttnL_; BcF32 C = AttnC_ - ( 1.0f / Attenuation ); // 0 = Ax2 + Bx + C if( A > 0.0f ) { BcF32 Discriminant = ( ( B * B ) - ( 4.0f * A * C ) ); if( Discriminant < 0.0f ) { return 1e24f; } return BcAbs( ( -B + BcSqrt( Discriminant ) ) / ( 2.0f * A ) ); } // 0 = Bx + C else if( B > 0.0f ) { return BcAbs( -C / B ); } // 0 = C else { return 1e24f; } }
////////////////////////////////////////////////////////////////////////// // buildNormals void MdlMesh::buildNormals() { for ( BcU32 i = 0; i < ( aIndices_.size() / 3 ); ++i ) { BcU32 TA = aIndices_[ ( i * 3 ) + 0 ].iVertex_; BcU32 TB = aIndices_[ ( i * 3 ) + 1 ].iVertex_; BcU32 TC = aIndices_[ ( i * 3 ) + 2 ].iVertex_; MdlVertex& VertA = aVertices_[ TA ]; MdlVertex& VertB = aVertices_[ TB ]; MdlVertex& VertC = aVertices_[ TC ]; BcVec3d VertPosA( VertA.Position_.x(), VertA.Position_.y(), VertA.Position_.z() ); BcVec3d VertPosB( VertB.Position_.x(), VertB.Position_.y(), VertB.Position_.z() ); BcVec3d VertPosC( VertC.Position_.x(), VertC.Position_.y(), VertC.Position_.z() ); BcVec3d Normal = ( VertPosA - VertPosB ).cross( ( VertPosB - VertPosC ) ); VertA.Normal_ += Normal; VertB.Normal_ += Normal; VertC.Normal_ += Normal; } for ( BcU32 i = 0; i < aVertices_.size(); ++i ) { MdlVertex& Vert = aVertices_[ i ]; Vert.bNormal_ = BcTrue; Vert.Normal_.normalise(); BcReal Mag = Vert.Normal_.magnitude(); BcAssert( BcAbs( Mag - 1.0f ) < 0.00001f ); } }
//////////////////////////////////////////////////////////////////////////////// // pointOnNode BcBool MaBSPTree::pointOnNode( const MaVec3d& Point, MaBSPNode* pNode ) { // Check if point is coincident. if( pNode->Plane_.classify( Point, 1e-3f ) != MaPlane::bcPC_COINCIDING ) { return BcFalse; } // if( pNode->Vertices_.size() == 2 ) { // If we only have 2 verts, test we are on the defining line. MaVec3d Origin = pNode->Vertices_[ 0 ]; MaVec3d Direction = pNode->Vertices_[ 1 ] - pNode->Vertices_[ 0 ]; MaVec3d Vector = Point - Origin; BcF32 T = Direction.dot( Vector ); // Check its on the line. return ( T >= 0.0f ) && ( T <= 1.0f ); } else { BcS32 Sign = 0; for( BcU32 Idx = 0; Idx < pNode->Vertices_.size(); ++Idx ) { const MaVec3d& PointA = pNode->Vertices_[ Idx ]; const MaVec3d& PointB = pNode->Vertices_[ ( Idx + 1 ) % pNode->Vertices_.size() ]; const MaVec3d AffineSegment = PointB - PointA; const MaVec3d AffinePoint = Point - PointA; BcF32 K = AffineSegment.dot( AffinePoint ); BcS32 KSign = BcAbs( K ) > 1e-3f ? static_cast< BcS32 >( K / BcAbs( K ) ) : 0; if( Sign == 0 ) { Sign = KSign; } else if( KSign != Sign ) { return BcFalse; } } return BcTrue; } }
//////////////////////////////////////////////////////////////////////////////// // Ctor GaMatchmakingState::GaMatchmakingState() { name( "GaMatchmakingState" ); SocketFileDescriptor_ = 0; ClientID_ = BcErrorCode; RemoteHandshakeAddr_ = 0; RemoteHandshakePort_ = 0; LocalHandshakeAddr_ = 0; LocalHandshakePort_ = 0; //MappedHandshakeAddr_ = 0; //MappedHandshakePort_ = 0; LANHandshakeAddr_ = 0; LANHandshakePort_ = 0; HandshakeState_ = HSS_STUN; BcMemZero( &Callbacks_, sizeof( Callbacks_ ) ); Callbacks_.event_connect = event_connect; Callbacks_.event_nick = event_nick; Callbacks_.event_nick = event_quit; Callbacks_.event_join = event_join; Callbacks_.event_part = event_part; Callbacks_.event_mode = event_mode; Callbacks_.event_umode = event_umode; Callbacks_.event_topic = event_topic; Callbacks_.event_kick = event_kick; Callbacks_.event_channel = event_channel; Callbacks_.event_privmsg = event_privmsg; Callbacks_.event_notice = event_notice; Callbacks_.event_channel_notice = event_channel_notice; Callbacks_.event_invite = event_invite; Callbacks_.event_ctcp_req = event_ctcp_req; Callbacks_.event_ctcp_rep = event_ctcp_rep; Callbacks_.event_ctcp_action = event_ctcp_action; Callbacks_.event_unknown = event_unknown; Callbacks_.event_numeric = event_numeric; Callbacks_.event_dcc_chat_req = event_dcc_chat_req; Callbacks_.event_dcc_send_req = event_dcc_send_req; ConnectTimer_ = 0.0f; InviteTimer_ = BcAbs( BcRandom::Global.randReal() ) * 5.0f + 5.0f; HandshakeTimer_ = 0.0f; pSession_ = NULL; #if PLATFORM_WINDOWS BcRandom::Global = BcRandom( ::GetTickCount() ); #endif }
////////////////////////////////////////////////////////////////////////// // Ctor GaGameUnit::GaGameUnit( GaGameSimulator* pSimulator, const GaGameUnitDescriptor& Desc, BcU32 TeamID, BcU32 ID, const BcFixedVec2d& Position ): pSimulator_( pSimulator ), Desc_( Desc ), TeamID_( TeamID ), ID_( ID ), Behaviour_( BEHAVIOUR_IDLE ) { CurrState_.Position_ = Position; PrevState_ = CurrState_; NextState_ = CurrState_; Health_ = Desc_.Health_; IsAttackMove_ = BcFalse; TargetUnitID_ = BcErrorCode; WalkTimer_ = ( BcAbs( BcRandom::Global.randReal() ) * Desc_.MoveSpeed_ ) * 0.2f; }
//////////////////////////////////////////////////////////////////////////////// // update eSysStateReturn GaMatchmakingState::main() { BcScopedLock< BcMutex > Lock( Lock_ ); BcReal Delta = SysKernel::pImpl()->getFrameTime(); switch( HandshakeState_ ) { case HSS_STUN: { // Only do once. if( MappedHandshakeAddr_ == 0 ) { if( doSTUN() ) { SysID_ = static_cast< BcU32 >( BcHash( (BcU8*)&MappedHandshakeAddr_, sizeof( MappedHandshakeAddr_ ) ) ); // Hash the mapped address to we don't broadcast it. if( MappedHandshakeAddr_ != 0 ) { HandshakeState_ = HSS_IDLE; } } else { HandshakeState_ = HSS_STUN; } } else { HandshakeState_ = HSS_IDLE; } } break; case HSS_IDLE: { ConnectTimer_ -= Delta; if( ConnectTimer_ < 0.0f ) { if( pSession_ == NULL ) { pSession_ = irc_create_session( &Callbacks_ ); } if( pSession_ != NULL && !irc_is_connected( pSession_ ) ) { irc_set_ctx( pSession_, this ); std::string Channel = "#testchannel"; BcFile File; if( File.open( "config.json" ) ) { char* pData = new char[ File.size() ]; File.read( pData, File.size() ); Json::Reader Reader; Json::Value Root; if( Reader.parse( pData, pData + File.size(), Root ) ) { Channel = Root["channel"].asCString(); } delete [] pData; } BcSPrintf( ScreenName_, "%s_%x", "PSY", BcRandom::Global.rand() ); BcSPrintf( Channel_, Channel.c_str() ); // Connect to the server. int RetVal = irc_connect( pSession_, "www.neilo.gd", 8000, NULL, ScreenName_, ScreenName_, ScreenName_ ); if( RetVal == 0 ) { // Start the thread to tick the client. BcThread::start( "EvtBridgeIRC" ); ClientID_ = BcErrorCode; RemoteHandshakeAddr_ = 0; RemoteHandshakePort_ = 0; //LocalHandshakeAddr_ = 0; //LocalHandshakePort_ = 0; //MappedHandshakeAddr_ = 0; //MappedHandshakePort_ = 0; HandshakeState_ = HSS_WAIT_INVITE; } else { BcThread::join(); irc_destroy_session( pSession_ ); pSession_ = NULL; } } } } break; case HSS_WAIT_INVITE: { InviteTimer_ -= Delta; if( InviteTimer_ < 0.0f ) { InviteTimer_ = BcAbs( BcRandom::Global.randReal() ) * 5.0f + 5.0f; // Send play with me message to channel. BcChar PlayBuffer[256]; BcSPrintf( PlayBuffer, "REQ:%u", SysID_ ); irc_cmd_msg( pSession_, Channel_, PlayBuffer ); } } break; case HSS_WAIT_ADDR: { HandshakeTimer_ -= Delta; if( HandshakeTimer_ < 0.0f ) { HandshakeState_ = HSS_WAIT_INVITE; } } break; case HSS_COMPLETE: { BcPrintf("GaMatchmakingState: Complete! ClientID of ours is %u\n", ClientID_); return sysSR_FINISHED; } break; } if( HandshakeState_ != HSS_STUN ) { if( HandshakeState_ != HSS_IDLE && ( pSession_ == NULL || !irc_is_connected( pSession_ ) ) ) { BcSleep( 0.1f ); BcThread::join(); BcSleep( 0.1f ); if( pSession_ != NULL ) { irc_destroy_session( pSession_ ); pSession_ = NULL; } HandshakeState_ = HSS_IDLE; ConnectTimer_ = 10.0f; } } return sysSR_CONTINUE; }
////////////////////////////////////////////////////////////////////////// // tickState void GaGameUnit::tickState( BcFixed Delta ) { PrevState_ = CurrState_; NextState_ = CurrState_; //if( NextState_.Velocity_.magnitudeSquared() > 0.0f ) { NextState_.Position_ += NextState_.Velocity_ * Delta; if( Behaviour_ != BEHAVIOUR_DAMAGE ) { // Check new state is valid. BcFixedVec2d Min( NextState_.Position_ - ( Desc_.Size_ * 0.9f ) ); BcFixedVec2d Max( NextState_.Position_ + ( Desc_.Size_ * 0.9f ) ); GaGameUnitIDList FoundUnits; pSimulator_->findUnits( FoundUnits, Min, Max, ID_, 0x3 ); // Move unit away from it's nearest one. if( FoundUnits.size() != 0 ) { BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 0x3 ); GaGameUnit* pGameUnit = pSimulator_->getUnit( NearestUnit ); if( pGameUnit != NULL ) { BcFixedVec2d Direction = ( CurrState_.Position_ - pGameUnit->CurrState_.Position_ ).normal(); if( Direction.dot( NextState_.Velocity_.normal() ) > 0.0f || NextState_.Velocity_.magnitudeSquared() == 0.0f ) { BcFixedVec2d RandomOffset( (int)( pSimulator_->rand() % 64 ), (int)( pSimulator_->rand() % 64 ) ); NextState_ = CurrState_; NextState_.Velocity_ = NextState_.Velocity_ * 0.4f + ( Direction * Desc_.MoveSpeed_ ) * 0.6f; NextState_.Position_ += NextState_.Velocity_ * Delta + ( RandomOffset / 4096.0f ); } } else { NextState_ = CurrState_; } } } } // WalkTimer_ -= NextState_.Velocity_.magnitude() * Delta; if( WalkTimer_ < 0.0f ) { GaTopState::pImpl()->playSound( "Walk", getPosition() ); WalkTimer_ += ( Desc_.MoveSpeed_ + (BcAbs( BcRandom::Global.randReal() ) * 0.02f ) ) * 0.2f; } // Clamp position and move away. BcFixed HW = ( 1280.0f * 0.5f ) / 32.0f - 1.0f; BcFixed HH = ( 720.0f * 0.5f ) / 32.0f - 1.0f; BcFixedVec2d ClampedPosition; ClampedPosition.x( BcClamp( NextState_.Position_.x(), -HW, HW ) ); ClampedPosition.y( BcClamp( NextState_.Position_.y(), -HH, HH ) ); if( NextState_.Position_ != ClampedPosition ) { BcFixedVec2d RandomOffset( (int)( pSimulator_->rand() % 64 ), (int)( pSimulator_->rand() % 64 ) ); NextState_.Velocity_ += RandomOffset / 4096.0f; NextState_.Position_ = ClampedPosition; } }
////////////////////////////////////////////////////////////////////////// // buildTangents void MdlMesh::buildTangents() { MaVec3d* pTan1 = new MaVec3d[ aVertices_.size() * 2 ]; MaVec3d* pTan2 = pTan1 + aVertices_.size(); memset( pTan1, 0, sizeof( MaVec3d ) * aVertices_.size() * 2 ); for ( BcU32 i = 0; i < ( aIndices_.size() / 3 ); ++i ) { BcU32 TA = aIndices_[ ( i * 3 ) + 0 ].iVertex_; BcU32 TB = aIndices_[ ( i * 3 ) + 1 ].iVertex_; BcU32 TC = aIndices_[ ( i * 3 ) + 2 ].iVertex_; MdlVertex& VertA = aVertices_[ TA ]; MdlVertex& VertB = aVertices_[ TB ]; MdlVertex& VertC = aVertices_[ TC ]; MaVec3d VertPosA = VertA.Position_; MaVec3d VertPosB = VertB.Position_; MaVec3d VertPosC = VertC.Position_; MaVec2d VertUVA = VertA.UV_; MaVec2d VertUVB = VertB.UV_; MaVec2d VertUVC = VertC.UV_; BcF32 X1 = VertPosB.x() - VertPosA.x(); BcF32 X2 = VertPosC.x() - VertPosA.x(); BcF32 Y1 = VertPosB.y() - VertPosA.y(); BcF32 Y2 = VertPosC.y() - VertPosA.y(); BcF32 Z1 = VertPosB.z() - VertPosA.z(); BcF32 Z2 = VertPosC.z() - VertPosA.z(); BcF32 S1 = VertUVB.x() - VertUVA.x(); BcF32 S2 = VertUVC.x() - VertUVA.x(); BcF32 T1 = VertUVB.y() - VertUVA.y(); BcF32 T2 = VertUVC.y() - VertUVA.y(); BcF32 InvR = ( S1 * T2 - S2 * T1 ); BcF32 R = 1.0f / InvR; // Validation so it doesn't break everything, just set to a dummy value. if( BcAbs( InvR ) < 1e-6f ) { R = 0.0f; } MaVec3d SDir( ( T2 * X1 - T1 * X2 ) * R, ( T2 * Y1 - T1 * Y2 ) * R, ( T2 * Z1 - T1 * Z2 ) * R ); MaVec3d TDir( ( S1 * X2 - S2 * X1 ) * R, ( S1 * Y2 - S2 * Y1 ) * R, ( S1 * Z2 - S2 * Z1 ) * R ); pTan1[ TA ] += SDir; pTan1[ TB ] += SDir; pTan1[ TC ] += SDir; pTan2[ TA ] += TDir; pTan2[ TB ] += TDir; pTan2[ TC ] += TDir; } for ( BcU32 i = 0; i < aVertices_.size(); ++i ) { MdlVertex& Vert = aVertices_[ i ]; MaVec3d Tangent; const MaVec3d N = Vert.Normal_; const MaVec3d& T = pTan1[ i ]; Tangent = ( T - N * N.dot( T ) ); Tangent.normalise(); // Calculate handedness BcF32 W = ( N.cross( T ).dot( pTan2[ i ] ) < 0.0f ) ? -1.0f : 1.0f; if ( W < 0.0f ) { Tangent = -Tangent; } Vert.bTangent_ = BcTrue; Vert.Tangent_ = Tangent; // Validate, and create a dummy value. BcF32 Mag = Tangent.magnitude(); if( BcAbs( Mag - 1.0f ) > 0.0001f ) { Vert.Tangent_.set( 0.0f, 0.0f, 0.0f ); } } delete[] pTan1; }
////////////////////////////////////////////////////////////////////////// // initialise void GaGameComponent::initialise( BcU32 TeamID, BcBool Networked ) { Super::initialise(); if( TeamID == BcErrorCode ) { TeamID = 0; } MouseDown_ = BcFalse; BoxSelection_ = BcFalse; CtrlDown_ = BcFalse; AttackMove_ = BcFalse; TeamID_ = TeamID; Networked_ = Networked; GameState_ = GS_PLAYING; // Randomly decide for some variation. AITickTime_ = 0.0f; AITickMaxTime_ = BcAbs( BcRandom::Global.randReal() * 0.4f ) + 0.1f; // Setup control groups. for( BcU32 Idx = 0; Idx < 10; ++Idx ) { ControlGroups_.push_back( GaGameUnitIDList() ); } pSimulator_ = new GaGameSimulator( 1.0f / 15.0f, 1.0f, TeamID, Networked ); pSimulator_->addUnit( GGameUnit_Trebuchet, 0, BcFixedVec2d( -19.0f, 0.0f ) ); pSimulator_->addUnit( GGameUnit_Archer, 0, BcFixedVec2d( -17.0f, -2.0f ) ); pSimulator_->addUnit( GGameUnit_Archer, 0, BcFixedVec2d( -17.0f, -1.0f ) ); pSimulator_->addUnit( GGameUnit_Archer, 0, BcFixedVec2d( -17.0f, 0.0f ) ); pSimulator_->addUnit( GGameUnit_Archer, 0, BcFixedVec2d( -17.0f, 1.0f ) ); pSimulator_->addUnit( GGameUnit_Archer, 0, BcFixedVec2d( -17.0f, 2.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 0, BcFixedVec2d( -15.0f, -2.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 0, BcFixedVec2d( -15.0f, -1.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 0, BcFixedVec2d( -15.0f, 0.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 0, BcFixedVec2d( -15.0f, 1.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 0, BcFixedVec2d( -15.0f, 2.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 0, BcFixedVec2d( -14.0f, -2.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 0, BcFixedVec2d( -14.0f, -1.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 0, BcFixedVec2d( -14.0f, 0.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 0, BcFixedVec2d( -14.0f, 1.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 0, BcFixedVec2d( -14.0f, 2.0f ) ); pSimulator_->addUnit( GGameUnit_Trebuchet, 1, BcFixedVec2d( 19.0f, 0.0f ) ); pSimulator_->addUnit( GGameUnit_Archer, 1, BcFixedVec2d( 17.0f, -2.0f ) ); pSimulator_->addUnit( GGameUnit_Archer, 1, BcFixedVec2d( 17.0f, -1.0f ) ); pSimulator_->addUnit( GGameUnit_Archer, 1, BcFixedVec2d( 17.0f, 0.0f ) ); pSimulator_->addUnit( GGameUnit_Archer, 1, BcFixedVec2d( 17.0f, 1.0f ) ); pSimulator_->addUnit( GGameUnit_Archer, 1, BcFixedVec2d( 17.0f, 2.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 1, BcFixedVec2d( 15.0f, -2.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 1, BcFixedVec2d( 15.0f, -1.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 1, BcFixedVec2d( 15.0f, 0.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 1, BcFixedVec2d( 15.0f, 1.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 1, BcFixedVec2d( 15.0f, 2.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 1, BcFixedVec2d( 14.0f, -2.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 1, BcFixedVec2d( 14.0f, -1.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 1, BcFixedVec2d( 14.0f, 0.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 1, BcFixedVec2d( 14.0f, 1.0f ) ); pSimulator_->addUnit( GGameUnit_Soldier, 1, BcFixedVec2d( 14.0f, 2.0f ) ); }