void cMonster::MoveToWayPoint(cChunk & a_Chunk) { if ((m_NextWayPointPosition - GetPosition()).SqrLength() < WAYPOINT_RADIUS * WAYPOINT_RADIUS) { return; } if (m_JumpCoolDown == 0) { if (DoesPosYRequireJump(FloorC(m_NextWayPointPosition.y))) { if (((IsOnGround()) && (GetSpeed().SqrLength() == 0.0f)) || (IsSwimming())) { m_bOnGround = false; m_JumpCoolDown = 20; // TODO: Change to AddSpeedY once collision detection is fixed - currently, mobs will go into blocks attempting to jump without a teleport AddPosY(1.6); // Jump!! SetSpeedX(3.2 * (m_NextWayPointPosition.x - GetPosition().x)); // Move forward in a preset speed. SetSpeedZ(3.2 * (m_NextWayPointPosition.z - GetPosition().z)); // The numbers were picked based on trial and error and 1.6 and 3.2 are perfect. } } } else { --m_JumpCoolDown; } Vector3d Distance = m_NextWayPointPosition - GetPosition(); if ((Distance.x != 0.0f) || (Distance.z != 0.0f)) { Distance.y = 0; Distance.Normalize(); if (m_bOnGround) { Distance *= 2.5f; } else if (IsSwimming()) { Distance *= 1.3f; } else { // Don't let the mob move too much if he's falling. Distance *= 0.25f; } // Apply walk speed: Distance *= m_RelativeWalkSpeed; /* Reduced default speed. Close to Vanilla, easier for mobs to follow m_NextWayPointPositions, hence better pathfinding. */ Distance *= 0.5; AddSpeedX(Distance.x); AddSpeedZ(Distance.z); } }
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(); }
void cMonster::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); if (m_Health <= 0) { // The mob is dead, but we're still animating the "puff" they leave when they die m_DestroyTimer += a_Dt / 1000; if (m_DestroyTimer > 1) { Destroy(true); } return; } if ((m_Target != NULL) && m_Target->IsDestroyed()) m_Target = NULL; // Burning in daylight HandleDaylightBurning(a_Chunk); a_Dt /= 1000; if (m_bMovingToDestination) { if (m_bOnGround) { m_Destination.y = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); if (DoesPosYRequireJump((int)floor(m_Destination.y))) { m_bOnGround = false; AddPosY(1.5); // Jump!! } } Vector3f Distance = m_Destination - GetPosition(); if(!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move { Distance.y = 0; Distance.Normalize(); Distance *= 5; SetSpeedX(Distance.x); SetSpeedZ(Distance.z); if (m_EMState == ESCAPING) { //Runs Faster when escaping :D otherwise they just walk away SetSpeedX (GetSpeedX() * 2.f); SetSpeedZ (GetSpeedZ() * 2.f); } } else { if (ReachedFinalDestination()) // If we have reached the ultimate, final destination, stop pathfinding and attack if appropriate { FinishPathFinding(); } else { TickPathFinding(); // We have reached the next point in our path, calculate another point } } } SetPitchAndYawFromDestination(); HandleFalling(); switch (m_EMState) { case IDLE: { // If enemy passive we ignore checks for player visibility InStateIdle(a_Dt); break; } case CHASING: { // If we do not see a player anymore skip chasing action InStateChasing(a_Dt); break; } case ESCAPING: { InStateEscaping(a_Dt); break; } } // switch (m_EMState) BroadcastMovementUpdate(); }
void cMonster::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); if (m_Health <= 0) { // The mob is dead, but we're still animating the "puff" they leave when they die m_DestroyTimer += a_Dt / 1000; if (m_DestroyTimer > 1) { Destroy(true); } return; } if ((m_Target != NULL) && m_Target->IsDestroyed()) m_Target = NULL; // Burning in daylight HandleDaylightBurning(a_Chunk); a_Dt /= 1000; if (m_bMovingToDestination) { if (m_bOnGround) { if (DoesPosYRequireJump((int)floor(m_Destination.y))) { m_bOnGround = false; // TODO: Change to AddSpeedY once collision detection is fixed - currently, mobs will go into blocks attempting to jump without a teleport AddPosY(1.2); // Jump!! } } Vector3d Distance = m_Destination - GetPosition(); if (!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move { Distance.y = 0; Distance.Normalize(); if (m_bOnGround) { Distance *= 2.5f; } else if (IsSwimming()) { Distance *= 1.3f; } else { // Don't let the mob move too much if he's falling. Distance *= 0.25f; } // Apply walk speed: Distance *= m_RelativeWalkSpeed; AddSpeedX(Distance.x); AddSpeedZ(Distance.z); // It's too buggy! /* if (m_EMState == ESCAPING) { // Runs Faster when escaping :D otherwise they just walk away SetSpeedX (GetSpeedX() * 2.f); SetSpeedZ (GetSpeedZ() * 2.f); } */ } else { if (ReachedFinalDestination()) // If we have reached the ultimate, final destination, stop pathfinding and attack if appropriate { FinishPathFinding(); } else { TickPathFinding(); // We have reached the next point in our path, calculate another point } } } SetPitchAndYawFromDestination(); HandleFalling(); switch (m_EMState) { case IDLE: { // If enemy passive we ignore checks for player visibility InStateIdle(a_Dt); break; } case CHASING: { // If we do not see a player anymore skip chasing action InStateChasing(a_Dt); break; } case ESCAPING: { InStateEscaping(a_Dt); break; } case ATTACKING: break; } // switch (m_EMState) BroadcastMovementUpdate(); }