void AirsideFollowMeCarInSim::ServicingFlight() { double dDist = m_pServiceFlight->GetDistInResource() + m_pServiceFlight->GetLogEntry().GetAirsideDescStruct().dLength; CPoint2008 CarPos = m_pServiceFlight->GetResource()->GetDistancePoint(dDist); SetMode(OnService); SetSpeed(m_pServiceFlight->GetSpeed()); ElapsedTime tTime = ElapsedTime(2.0*CarPos.distance(GetPosition())/GetSpeed()) + GetTime(); SetTime(tTime); if(GetResource() != m_pServiceFlight->GetResource()) GetResource()->SetExitTime(this,tTime); SetResource(m_pServiceFlight->GetResource()); SetPosition(CarPos); SetDistInResource(dDist); WirteLog(CarPos,GetSpeed(),tTime); m_pServiceFlight->SetBeginFollowMeCarService(); AirsideFollowMeCarServiceEvent* pEvent = new AirsideFollowMeCarServiceEvent(m_pServiceFlight); pEvent->setTime(tTime); pEvent->addEvent(); }
void Asserv::stop(bool emergency) { float actualSpeed = GetSpeed(); /* distance theorique (temps continu) pour annuler la vitesse avec un freinage maximum et constant*/ if (emergency){ d_freinage = (actualSpeed*actualSpeed) * .5 / decEmergency; } else { d_freinage = (actualSpeed*actualSpeed) * .5 / dec; } setTarget(initialSens * d_freinage, 0.0); emergencyStop = emergency; }
void CVideoReferenceClock::SetSpeed(double Speed) { CSingleLock SingleLock(m_CritSection); //dvdplayer can change the speed to fit the rereshrate if (m_UseVblank) { if (Speed != m_ClockSpeed) { m_ClockSpeed = Speed; CLog::Log(LOGDEBUG, "CVideoReferenceClock: Clock speed %f%%", GetSpeed() * 100.0); } } }
void PathBehavior::SerializeTo(gd::SerializerElement & element) const { SerializePathsTo(element.AddChild("paths")); element.SetAttribute("currentPath", GetCurrentPathName()); element.SetAttribute("speed", GetSpeed()); element.SetAttribute("offsetX", GetOffsetX()); element.SetAttribute("offsetY", GetOffsetY()); element.SetAttribute("angleOffset", angleOffset); element.SetAttribute("reverseAtEnd", ReverseAtEnd()); element.SetAttribute("stopAtEnd", StopAtEnd()); element.SetAttribute("followAngle", FollowAngle()); }
void PhysicalObj::Collide(collision_t collision, PhysicalObj* collided_obj, const Point2d& position) { Point2d contactPos; Double contactAngle; switch (collision) { case NO_COLLISION: // Nothing more to do! return; case COLLISION_ON_GROUND: ContactPointAngleOnGround(position, contactPos, contactAngle); ASSERT(!collided_obj); break; case COLLISION_ON_OBJECT: contactPos = position; contactAngle = - GetSpeedAngle(); // Compute the new speed norm of this and collided_obj, new speed angle will be set // thanks to Rebound() // Get the current speed Double v1, v2, mass1, angle1, angle2, mass2; collided_obj->GetSpeed(v1, angle1); GetSpeed(v2, angle2); mass1 = GetMass(); mass2 = collided_obj->GetMass(); // Give speed to the other object // thanks to physic and calculations about chocs, we know that : // // v'1 = ((m1 - m2) * v1 + 2m1 *v2) / (m1 + m2) // v'2 = ((m2 - m1) * v2 + 2m1 *v1) / (m1 + m2) collided_obj->SetSpeed(abs(((mass1 - mass2) * v1 + 2 * mass1 *v2 * m_cfg.m_rebound_factor) / (mass1 + mass2)), angle1); SetSpeed(abs(((mass2 - mass1) * v2 + 2 * mass1 *v1 * m_cfg.m_rebound_factor) / (mass1 + mass2)), angle2); break; } // Mark it as last collided object m_last_collided_object = collided_obj; // Make it rebound!! MSG_DEBUG("physic.state", "%s rebounds at %.3f,%.3f", GetName().c_str(), contactPos.x.tofloat(), contactPos.y.tofloat()); Rebound(contactPos, contactAngle); CheckRebound(); }
void CBubbling::Spawn( void ) { Precache(); SetModel( GetModelName() ); // Set size SetSolidType( SOLID_NOT ); // Remove model & collisions SetRenderAmount( 0 ); // The engine won't draw this model if this is set to 0 and blending is on SetRenderMode( kRenderTransTexture ); int speed = fabs( GetSpeed() ); // HACKHACK!!! - Speed in rendercolor SetRenderColor( Vector( speed >> 8, speed & 255, ( GetSpeed() < 0 ) ? 1 : 0 ) ); if( !GetSpawnFlags().Any( SF_BUBBLES_STARTOFF ) ) { SetThink( &CBubbling::FizzThink ); SetNextThink( gpGlobals->time + 2.0 ); m_state = true; } else m_state = false; }
void CTriggerPush::Touch( CBaseEntity *pOther ) { // UNDONE: Is there a better way than health to detect things that have physics? (clients/monsters) switch( pOther->GetMoveType() ) { case MOVETYPE_NONE: case MOVETYPE_PUSH: case MOVETYPE_NOCLIP: case MOVETYPE_FOLLOW: return; default: break; } if( pOther->GetSolidType() != SOLID_NOT && pOther->GetSolidType() != SOLID_BSP ) { // Instant trigger, just transfer velocity and remove if( GetSpawnFlags().Any( SF_TRIG_PUSH_ONCE ) ) { pOther->SetAbsVelocity( pOther->GetAbsVelocity() + ( GetSpeed() * GetMoveDir() ) ); if( pOther->GetAbsVelocity().z > 0 ) pOther->GetFlags().ClearFlags( FL_ONGROUND ); UTIL_Remove( this ); } else { // Push field, transfer to base velocity Vector vecPush = ( GetSpeed() * GetMoveDir() ); if( pOther->GetFlags().Any( FL_BASEVELOCITY ) ) vecPush = vecPush + pOther->GetBaseVelocity(); pOther->SetBaseVelocity( vecPush ); pOther->GetFlags() |= FL_BASEVELOCITY; // ALERT( at_console, "Vel %f, base %f\n", pevToucher->velocity.z, pevToucher->basevelocity.z ); } } }
// 添加到CByteArray bool CShape::CodeToDataBlock(DBWriteSet& setWriteDB, bool bExData) { CBaseObject::CodeToDataBlock(setWriteDB,bExData); setWriteDB.AddToByteArray((BYTE)GetCurRgnType()); setWriteDB.AddToByteArray(GetRegionID()); setWriteDB.AddToByteArray(GetRegionExID()); setWriteDB.AddToByteArray(GetPosX()); setWriteDB.AddToByteArray(GetPosY()); setWriteDB.AddToByteArray(GetDir()); setWriteDB.AddToByteArray(GetPos()); setWriteDB.AddToByteArray(GetSpeed()); setWriteDB.AddToByteArray(GetState()); setWriteDB.AddToByteArray(GetAction()); return true; }
void CRock_Fall::Update(float fElapsedTime) { AnimationManager::GetInstance()->Update(fElapsedTime, *GetAnimInfo()); //CEntity::Update(fElapsedTime); SetPosX(GetPosX()); SetPosY(GetPosY() + GetSpeed() * fElapsedTime); CCamera* Game_Camera = CCamera::GetInstance(); if(this->GetPosY() > Game_Camera->GetPosY() + Game_Camera->GetHeight()) { CRemoveEntityMessage* pMsg = new CRemoveEntityMessage(this); CSGD_MessageSystem::GetInstance()->SendMsg(pMsg); pMsg = nullptr; } }
// 添加到CByteArray bool CShape::AddShapeToByteArray(vector<BYTE>* pByteArray) { _AddToByteArray(pByteArray,(CGUID&)GetExID()); _AddToByteArray(pByteArray, (long)GetCurRgnType()); _AddToByteArray(pByteArray, GetRegionID()); _AddToByteArray(pByteArray, GetRegionExID()); _AddToByteArray(pByteArray, GetPosX()); _AddToByteArray(pByteArray, GetPosY()); _AddToByteArray(pByteArray, GetDir()); _AddToByteArray(pByteArray, GetPos()); _AddToByteArray(pByteArray, GetSpeed()); _AddToByteArray(pByteArray, GetState()); _AddToByteArray(pByteArray, GetAction()); return true; }
//发送变化的速度值到客户端 void CMoveShape::SendChangedSpeedToClients() { //if(m_bSpeedLvlChanged) { m_bSpeedLvlChanged = false; CMessage msg(MSG_S2C_SHAPE_CHANGEMOVEMODE); msg.Add(GetType()); msg.Add(GetExID()); //移动模式 msg.Add(static_cast<char>(GetIsRun()==false?0:1)); //当前速度 msg.Add( GetSpeed()); //变化比率 msg.Add(GetSpeedChangedRatio()); msg.SendToAround(this); } }
void CBaseDoor::Spawn() { Precache(); SetMovedir( this ); if( GetSkin() == 0 ) {//normal door if( GetSpawnFlags().Any( SF_DOOR_PASSABLE ) ) SetSolidType( SOLID_NOT ); else SetSolidType( SOLID_BSP ); } else {// special contents SetSolidType( SOLID_NOT ); GetSpawnFlags().AddFlags( SF_DOOR_SILENT ); // water is silent for now } SetMoveType( MOVETYPE_PUSH ); SetAbsOrigin( GetAbsOrigin() ); SetModel( GetModelName() ); if( GetSpeed() == 0 ) SetSpeed( 100 ); m_vecPosition1 = GetAbsOrigin(); // Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big m_vecPosition2 = m_vecPosition1 + ( GetMoveDir() * ( fabs( GetMoveDir().x * ( GetBounds().x - 2 ) ) + fabs( GetMoveDir().y * ( GetBounds().y - 2 ) ) + fabs( GetMoveDir().z * ( GetBounds().z - 2 ) ) - m_flLip ) ); ASSERTSZ( m_vecPosition1 != m_vecPosition2, "door start/end positions are equal" ); if( GetSpawnFlags().Any( SF_DOOR_START_OPEN ) ) { // swap pos1 and pos2, put door at pos2 SetAbsOrigin( m_vecPosition2 ); m_vecPosition2 = m_vecPosition1; m_vecPosition1 = GetAbsOrigin(); } m_toggle_state = TS_AT_BOTTOM; // if the door is flagged for USE button activation only, use NULL touch function if( GetSpawnFlags().Any( SF_DOOR_USE_ONLY ) ) { SetTouch( NULL ); } else // touchable button SetTouch( &CBaseDoor::DoorTouch ); }
void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) { if (!a_EntityHit.IsMob() && !a_EntityHit.IsMinecart() && !a_EntityHit.IsPlayer()) { // Not an entity that interacts with an arrow return; } int Damage = (int)(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5); if (m_IsCritical) { Damage += m_World->GetTickRandomNumber(Damage / 2 + 2); } a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1); Destroy(); }
void clRailPositioner::Update( float dt ) { float S = GetSpeed( dt ); // move to properties float PitchRate = 90.0f * dt; float PanRate = 90.0f * dt; PitchRate *= Env->Console->IsKeyPressed( LK_SHIFT ) ? 3.0f : 1.0f; PanRate *= Env->Console->IsKeyPressed( LK_SHIFT ) ? 3.0f : 1.0f; if ( Env->Console->IsKeyPressed( LK_LEFT ) ) { FPitch -= PitchRate; } if ( Env->Console->IsKeyPressed( LK_RIGHT ) ) { FPitch += PitchRate; } if ( Env->Console->IsKeyPressed( LK_E ) ) { FPan -= PanRate; } if ( Env->Console->IsKeyPressed( LK_C ) ) { FPan += PanRate; } FPitch = Math::ClipAngleTo0_360( FPitch ); FPan = Math::ClipAngleTo0_360( FPan ); LMatrix4 PitchMtx; PitchMtx.IdentityMatrix(); PitchMtx.RotateMatrixAxis( Linderdaum::Math::DegToRad( -FPitch ), FUpVector ); LVector3 ViewDir = -( PitchMtx * FDirVector ); LVector3 SideDir = -( FUpVector.Cross( ViewDir ) ); if ( Env->Console->IsKeyPressed( LK_Q ) || Env->Console->IsKeyPressed( LK_1 ) ) { FPosition += S * FUpVector; } if ( Env->Console->IsKeyPressed( LK_Z ) || Env->Console->IsKeyPressed( LK_2 ) ) { FPosition -= S * FUpVector; } if ( Env->Console->IsKeyPressed( LK_W ) || Env->Console->IsKeyPressed( LK_UP ) ) { FPosition += -ViewDir * S; } if ( Env->Console->IsKeyPressed( LK_S ) || Env->Console->IsKeyPressed( LK_DOWN ) ) { FPosition += ViewDir * S; } if ( Env->Console->IsKeyPressed( LK_A ) ) { FPosition += SideDir * S; } if ( Env->Console->IsKeyPressed( LK_D ) ) { FPosition += -SideDir * S; } LMatrix4 Rotation = LMatrix4::GetRotateMatrixAxis( Math::DegToRad( FPan ), SideDir ) * LMatrix4::GetRotateMatrixAxis( Math::DegToRad( FPitch ), FUpVector ); FCurrentTransform = LMatrix4::GetTranslateMatrix( -FPosition ) * Rotation; }
void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) { super::OnHitEntity(a_EntityHit, a_HitPos); int Damage = static_cast<int>(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5); if (m_IsCritical) { Damage += m_World->GetTickRandomNumber(Damage / 2 + 2); } unsigned int PowerLevel = m_CreatorData.m_Enchantments.GetLevel(cEnchantments::enchPower); if (PowerLevel > 0) { int ExtraDamage = static_cast<int>(ceil(0.25 * (PowerLevel + 1))); Damage += ExtraDamage; } // int KnockbackAmount = 1; unsigned int PunchLevel = m_CreatorData.m_Enchantments.GetLevel(cEnchantments::enchPunch); if (PunchLevel > 0) { Vector3d LookVector = GetLookVector(); Vector3f FinalSpeed = Vector3f(0, 0, 0); switch (PunchLevel) { case 1: FinalSpeed = LookVector * Vector3d(5, 0.3, 5); break; case 2: FinalSpeed = LookVector * Vector3d(8, 0.3, 8); break; default: break; } a_EntityHit.SetSpeed(FinalSpeed); } // a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, KnockbackAmount); // TODO fix knockback. a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 0); // Until knockback is fixed. if (IsOnFire() && !a_EntityHit.IsSubmerged() && !a_EntityHit.IsSwimming()) { a_EntityHit.StartBurning(100); } // Broadcast successful hit sound GetWorld()->BroadcastSoundEffect("random.successful_hit", GetPosX(), GetPosY(), GetPosZ(), 0.5, static_cast<float>(0.75 + (static_cast<float>((GetUniqueID() * 23) % 32)) / 64)); Destroy(); }
static IOReturn PrintSpeedForBSDNode ( const char * bsdNode ) { IOReturn error = kIOReturnError; int fileDescriptor = 0; UInt16 speed = 0; char deviceName[MAXPATHLEN]; if ( strncmp ( bsdNode, "/dev/rdisk", 10 ) == 0 ) { sprintf ( deviceName, "%s", bsdNode ); } else if ( strncmp ( bsdNode, "/dev/disk", 9 ) == 0 ) { sprintf ( deviceName, "%s", bsdNode ); } else if ( strncmp ( bsdNode, "disk", 4 ) == 0 ) { sprintf ( deviceName, "%s%s", "/dev/", bsdNode ); } else { goto ErrorExit; } fileDescriptor = OpenMedia ( deviceName ); require ( ( fileDescriptor > 0 ), ErrorExit ); speed = GetSpeed ( fileDescriptor ); printf ( "%s: speed = %d KB/s\n", deviceName, speed ); CloseMedia ( fileDescriptor ); ErrorExit: return error; }
void CluzookaCluster::DoSpawn() { const uint fragments = 2; Double angle; Double speed; GetSpeed( speed, angle ); speed = 25;// always Point2i parent_position = GetPosition(); Double angle_range = QUARTER_PI; uint rec_depth = 0; #ifdef CLUSTERS_SPAWN_CLUSTERS rec_depth = m_recursion_depth - 1; #endif ClusterSpawner< CluzookaCluster >::SpawnClusters( fragments, rec_depth, parent_position, speed, angle, angle_range, cfg, launcher ); }
void cBoat::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); BroadcastMovementUpdate(); SetSpeed(GetSpeed() * 0.97); // Slowly decrease the speed if ((POSY_TOINT < 0) || (POSY_TOINT >= cChunkDef::Height)) { return; } if (IsBlockWater(m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT))) { if (GetSpeedY() < 2) { AddSpeedY(0.2); } } }
void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) { if (!a_EntityHit.IsMob() && !a_EntityHit.IsMinecart() && !a_EntityHit.IsPlayer() && !a_EntityHit.IsBoat()) { // Not an entity that interacts with an arrow return; } int Damage = (int)(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5); if (m_IsCritical) { Damage += m_World->GetTickRandomNumber(Damage / 2 + 2); } a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1); // Broadcast successful hit sound m_World->BroadcastSoundEffect("random.successful_hit", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); Destroy(); }
dFloat CustomDGRayCastCar::GenerateTiresSteerForce (dFloat value) { dFloat speed, relspeed; relspeed = dAbs ( GetSpeed() ); speed = relspeed; speed *= m_maxSteerForceRate; dFloat value2 = value; if ( speed > m_maxSteerSpeedRestriction ) { speed = m_maxSteerSpeedRestriction; } if ( value2 > 0.0f ) { value2 = -( m_maxSteerForce * speed ) * ( 1.0f - relspeed / m_engineSteerDiv ); } else if ( value < 0.0f ) { value2 = ( m_maxSteerForce * speed ) * ( 1.0f - relspeed / m_engineSteerDiv ); } else { value2 = 0.0f; } return value2; }
void CluzookaRocket::DoSpawn() { const uint fragments = static_cast<CluzookaConfig &>(cfg).m_fragments; const Double angle_range = static_cast<CluzookaConfig &>(cfg).m_angle_dispersion * PI / (Double)180; const uint recursion_depth = 0; #ifndef CLUSTERS_SPAWN_CLUSTERS ASSERT( recursion_depth == 0 ); #endif Double angle; Double speed; GetSpeed( speed, angle ); speed = 25;// always Point2i parent_position = GetPosition(); ClusterSpawner< CluzookaCluster >::SpawnClusters( fragments, recursion_depth, parent_position, speed, angle, angle_range, cfg, launcher ); }
void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) { Vector3d Hit = a_HitPos; Hit += GetSpeed().NormalizeCopy() / 100000; // Make arrow sink into block a bit so it lodges (TODO: investigate how to stop them going so far so that they become black clientside) super::OnHitSolidBlock(Hit, a_HitFace); Vector3i BlockHit = Hit.Floor(); int X = BlockHit.x, Y = BlockHit.y, Z = BlockHit.z; m_HitBlockPos = Vector3i(X, Y, Z); // Broadcast arrow hit sound m_World->BroadcastSoundEffect("random.bowhit", static_cast<double>(X), static_cast<double>(Y), static_cast<double>(Z), 0.5f, static_cast<float>(0.75 + (static_cast<float>((GetUniqueID() * 23) % 32)) / 64)); if ((m_World->GetBlock(Hit) == E_BLOCK_TNT) && IsOnFire()) { m_World->SetBlock(X, Y, Z, E_BLOCK_AIR, 0); m_World->SpawnPrimedTNT(X, Y, Z); } }
bool CCar::SetSpeed(int speed) { if (!IsEngineOn()) { std::cout << "Couldn't change speed(Engine is off)." << std::endl; return false; } if (GetGear() == 0 && speed > GetSpeed()) { std::cout << "Couldn't change speed(can't increase speed on 0-gear)." << std::endl; return false; } std::array<int, 2> speedRange = GetSpeedRange(GetGear()); if (speed >= speedRange[0] && speed <= speedRange[1]) { m_speed = speed; return true; } std::cout << "Couldn't change speed(Your gear does not support this speed)." << std::endl; return false; }
u32 Army::Troop::GetStrength(void) const { float res = (GetDamageMin() + GetDamageMax()) >> 1; // increase strength if(isFly()) res += res * 0.5; if(isArchers()) res += res * 0.5; if(isTwiceAttack()) res += res * 0.5; if(isHideAttack()) res += res * 0.5; // slowly: decrease strength if((!isFly() && !isArchers()) && Speed::AVERAGE > GetSpeed()) res -= res * 0.5; switch(GetID()) { case Monster::GHOST: res *= 2; break; default: break; } return static_cast<u32>(res); }
void LocationDlg::UpdateEnabling() { GetAnimPos()->Enable(m_iAnim != -1); GetSaveAnim()->Enable(m_iAnim != -1); GetActive()->Enable(m_iAnim != -1); GetSpeed()->Enable(m_iAnim != -1); GetReset()->Enable(m_iAnim != -1); GetPlay()->Enable(m_iAnim != -1); GetRecord1()->Enable(m_iAnim != -1); GetStop()->Enable(m_iAnim != -1); GetLoop()->Enable(m_iAnim != -1); GetContinuous()->Enable(m_iAnim != -1); GetSmooth()->Enable(m_iAnim != -1 && GetAnim(m_iAnim)->NumPoints() > 2); GetPosOnly()->Enable(m_iAnim != -1); GetRecordInterval()->Enable(m_iAnim != -1); GetRecordLinear()->Enable(m_iAnim != -1); GetRecordSpacing()->Enable(m_bRecordInterval); GetPlayToDisk()->Enable(m_iAnim != -1); }
void CTriggerPush::Spawn() { Vector vecAngles = GetAbsAngles(); if( vecAngles == g_vecZero ) { vecAngles.y = 360; SetAbsAngles( vecAngles ); } InitTrigger(); if( GetSpeed() == 0 ) SetSpeed( 100 ); if( GetSpawnFlags().Any( SF_TRIGGER_PUSH_START_OFF ) )// if flagged to Start Turned Off, make trigger nonsolid. SetSolidType( SOLID_NOT ); SetUse( &CTriggerPush::ToggleUse ); SetAbsOrigin( GetAbsOrigin() ); // Link into the list }
Real SingleCurve3<Real>::GetTime (Real fLength, int iIterations, Real fTolerance) const { if (fLength <= (Real)0.0) { return m_fTMin; } if (fLength >= GetTotalLength()) { return m_fTMax; } // initial guess for Newton's method Real fRatio = fLength/GetTotalLength(); Real fOmRatio = (Real)1.0 - fRatio; Real fTime = fOmRatio*m_fTMin + fRatio*m_fTMax; for (int i = 0; i < iIterations; i++) { Real fDifference = GetLength(m_fTMin,fTime) - fLength; if (Math<Real>::FAbs(fDifference) < fTolerance) { return fTime; } fTime -= fDifference/GetSpeed(fTime); } // Newton's method failed. You might want to increase iterations or // tolerance or integration accuracy. However, in this application it // is likely that the time values are oscillating, due to the limited // numerical precision of 32-bit floats. It is safe to use the last // computed time. return fTime; }
void CCruiser::Move(float delta) { switch (mState) { case State::Enter: //Move downwards mModel->MoveZ(GetSpeed() * -delta); if (AREA_BOUNDS_TOP - (2.0f * GetRadius()) > mModel->GetZ()) { mState = State::Rotate; } break; case State::Attack: break; case State::Rotate: { RotateTowards((*mpPlayers)[0]->GetCenterPoint(), delta * kRotateSpeed); float bearingToTarget = BearingTowards((*mpPlayers)[0]->GetCenterPoint()); float rotation = GetRotation(); float rotDif = bearingToTarget > rotation ? bearingToTarget - rotation : rotation - bearingToTarget; if (rotDif < kRotationMargin) { mState = State::Attack; mWeapon->SetFiring(true); mStateTimer = 0.0f; } } break; default: break; } }
void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk) { if (IsDestroyed()) // Mainly to stop detector rails triggering again after minecart is dead { return; } int PosY = POSY_TOINT; if ((PosY <= 0) || (PosY >= cChunkDef::Height)) { // Outside the world, just process normal falling physics super::HandlePhysics(a_Dt, a_Chunk); BroadcastMovementUpdate(); return; } int RelPosX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width; int RelPosZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width; cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ); if (Chunk == NULL) { // Inside an unloaded chunk, bail out all processing return; } BLOCKTYPE InsideType; NIBBLETYPE InsideMeta; Chunk->GetBlockTypeMeta(RelPosX, PosY, RelPosZ, InsideType, InsideMeta); if (!IsBlockRail(InsideType)) { Chunk->GetBlockTypeMeta(RelPosX, PosY + 1, RelPosZ, InsideType, InsideMeta); // When an descending minecart hits a flat rail, it goes through the ground; check for this if (IsBlockRail(InsideType)) AddPosY(1); // Push cart upwards } bool WasDetectorRail = false; if (IsBlockRail(InsideType)) { if (InsideType == E_BLOCK_RAIL) { SnapToRail(InsideMeta); } else { SnapToRail(InsideMeta & 0x07); } switch (InsideType) { case E_BLOCK_RAIL: HandleRailPhysics(InsideMeta, a_Dt); break; case E_BLOCK_ACTIVATOR_RAIL: break; case E_BLOCK_POWERED_RAIL: HandlePoweredRailPhysics(InsideMeta); break; case E_BLOCK_DETECTOR_RAIL: { HandleDetectorRailPhysics(InsideMeta, a_Dt); WasDetectorRail = true; break; } default: VERIFY(!"Unhandled rail type despite checking if block was rail!"); break; } AddPosition(GetSpeed() * (a_Dt / 1000)); // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp } else { // Not on rail, default physics SetPosY(floor(GetPosY()) + 0.35); // HandlePhysics overrides this if minecart can fall, else, it is to stop ground clipping minecart bottom when off-rail super::HandlePhysics(a_Dt, *Chunk); } if (m_bIsOnDetectorRail && !Vector3i(POSX_TOINT, POSY_TOINT, POSZ_TOINT).Equals(m_DetectorRailPosition)) { m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07); m_bIsOnDetectorRail = false; } else if (WasDetectorRail) { m_bIsOnDetectorRail = true; m_DetectorRailPosition = Vector3i(POSX_TOINT, POSY_TOINT, POSZ_TOINT); } // Broadcast positioning changes to client BroadcastMovementUpdate(); }
// Move to a point with collision test collision_t PhysicalObj::NotifyMove(Point2d oldPos, Point2d newPos) { if (IsGhost()) return NO_COLLISION; Point2d contactPos; Double contactAngle; Point2d pos, offset; PhysicalObj* collided_obj = NULL; collision_t collision = NO_COLLISION; // Convert meters to pixels. oldPos *= PIXEL_PER_METER; newPos *= PIXEL_PER_METER; // Compute distance between old and new position. Double lg = oldPos.SquareDistance(newPos); MSG_DEBUG("physic.move", "%s moves (%s, %s) -> (%s, %s), square distance: %s", GetName().c_str(), Double2str(oldPos.x).c_str(), Double2str(oldPos.y).c_str(), Double2str(newPos.x).c_str(), Double2str(newPos.y).c_str(), Double2str(lg).c_str()); if (!lg.IsNotZero()) return NO_COLLISION; // Compute increments to move the object step by step from the old // to the new position. lg = sqrt(lg); offset = (newPos - oldPos) / lg; // First iteration position. pos = oldPos + offset; if (!m_collides_with_ground || IsInWater()) { MSG_DEBUG("physic.move", "%s moves (%s, %s) -> (%s, %s), collides ground:%d, water:%d", GetName().c_str(), Double2str(oldPos.x).c_str(), Double2str(oldPos.y).c_str(), Double2str(newPos.x).c_str(), Double2str(newPos.y).c_str(), m_collides_with_ground, IsInWater()); SetXY(newPos); return NO_COLLISION; } do { Point2i tmpPos(uround(pos.x), uround(pos.y)); // Check if we exit the GetWorld(). If so, we stop moving and return. if (IsOutsideWorldXY(tmpPos)) { if (!GetWorld().IsOpen()) { tmpPos.x = InRange_Long(tmpPos.x, 0, GetWorld().GetWidth() - GetWidth() - 1); tmpPos.y = InRange_Long(tmpPos.y, 0, GetWorld().GetHeight() - GetHeight() - 1); MSG_DEBUG("physic.state", "%s - DeplaceTestCollision touche un bord : %d, %d", GetName().c_str(), tmpPos.x, tmpPos.y); collision = COLLISION_ON_GROUND; break; } SetXY(pos); MSG_DEBUG("physic.move", "%s moves (%f, %f) -> (%f, %f) : OUTSIDE WORLD", GetName().c_str(), oldPos.x.tofloat(), oldPos.y.tofloat(), newPos.x.tofloat(), newPos.y.tofloat()); return NO_COLLISION; } // Test if we collide... collided_obj = CollidedObjectXY(tmpPos); if (collided_obj) { if (!m_go_through_objects || m_last_collided_object != collided_obj) { MSG_DEBUG("physic.state", "%s collide on %s", GetName().c_str(), collided_obj->GetName().c_str()); if (m_go_through_objects) { SignalObjectCollision(GetSpeed(), collided_obj, collided_obj->GetSpeed()); collision = NO_COLLISION; } else { collision = COLLISION_ON_OBJECT; } m_last_collided_object = collided_obj; } else { collided_obj = NULL; collision = NO_COLLISION; } } else if (!IsInVacuumXY(tmpPos, false)) { collision = COLLISION_ON_GROUND; m_last_collided_object = NULL; } if (collision != NO_COLLISION) { // Nothing more to do! MSG_DEBUG("physic.state", "%s - Collision at %d,%d : on %s", GetName().c_str(), tmpPos.x, tmpPos.y, collision == COLLISION_ON_GROUND ? "ground" : "an object"); // Set the object position to the current position. SetXY(Point2d(pos.x - offset.x, pos.y - offset.y)); break; } // Next motion step pos += offset; lg -= ONE; } while (ZERO < lg); Point2d speed_before_collision = GetSpeed(); Point2d speed_collided_obj; if (collided_obj) { speed_collided_obj = collided_obj->GetSpeed(); } ContactPointAngleOnGround(pos, contactPos, contactAngle); Collide(collision, collided_obj, pos); // =================================== // it's time to signal object(s) about collision! // WARNING: the following calls can send Action(s) over the network (cf bug #11232) // Be sure to keep it isolated here // =================================== ActiveTeam().AccessWeapon().NotifyMove(!!collision); switch (collision) { case NO_COLLISION: // Nothing more to do! break; case COLLISION_ON_GROUND: SignalGroundCollision(speed_before_collision, contactAngle); break; case COLLISION_ON_OBJECT: SignalObjectCollision(speed_before_collision, collided_obj, speed_collided_obj); collided_obj->SignalObjectCollision(speed_collided_obj, this, speed_before_collision); break; } // =================================== return collision; }