void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); GET_AND_VERIFY_CURRENT_CHUNK(Chunk, POSX_TOINT, POSZ_TOINT); if (m_Health <= 0) { // The mob is dead, but we're still animating the "puff" they leave when they die. m_DestroyTimer += a_Dt; if (m_DestroyTimer > std::chrono::seconds(1)) { Destroy(true); } return; } if (m_TicksSinceLastDamaged < 100) { ++m_TicksSinceLastDamaged; } if ((m_Target != nullptr) && m_Target->IsDestroyed()) { m_Target = nullptr; } // Process the undead burning in daylight. HandleDaylightBurning(*Chunk, WouldBurnAt(GetPosition(), *Chunk)); if (TickPathFinding(*Chunk)) { /* If I burn in daylight, and I won't burn where I'm standing, and I'll burn in my next position, and at least one of those is true: 1. I am idle 2. I was not hurt by a player recently. Then STOP. */ if ( m_BurnsInDaylight && ((m_TicksSinceLastDamaged >= 100) || (m_EMState == IDLE)) && WouldBurnAt(m_NextWayPointPosition, *Chunk) && !WouldBurnAt(GetPosition(), *Chunk) ) { // If we burn in daylight, and we would burn at the next step, and we won't burn where we are right now, and we weren't provoked recently: StopMovingToPosition(); m_GiveUpCounter = 40; // This doesn't count as giving up, keep the giveup timer as is. } else { MoveToWayPoint(*Chunk); } } 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(); }
void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { std::vector<cEntityEffect *> EffectsToTick; // Iterate through this entity's applied effects for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();) { // Copies values to prevent pesky wrong accesses and erasures cEntityEffect::eType EffectType = iter->first; cEntityEffect * Effect = iter->second.get(); // Iterates (must be called before any possible erasure) ++iter; // Remove effect if duration has elapsed if (Effect->GetDuration() - Effect->GetTicks() <= 0) { RemoveEntityEffect(EffectType); } // Call OnTick later to make sure the iterator won't be invalid else { EffectsToTick.push_back(Effect); } // TODO: Check for discrepancies between client and server effect values } for (auto * Effect : EffectsToTick) { Effect->OnTick(*this); } // Spectators cannot push entities around if ((!IsPlayer()) || (!static_cast<cPlayer *>(this)->IsGameModeSpectator())) { m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), GetWidth(), GetHeight()), [=](cEntity & a_Entity) { if (a_Entity.GetUniqueID() == GetUniqueID()) { return false; } // we only push other mobs, boats and minecarts if ((a_Entity.GetEntityType() != etMonster) && (a_Entity.GetEntityType() != etMinecart) && (a_Entity.GetEntityType() != etBoat)) { return false; } // do not push a boat / minecart you're sitting in if (IsAttachedTo(&a_Entity)) { return false; } Vector3d v3Delta = a_Entity.GetPosition() - GetPosition(); v3Delta.y = 0.0; // we only push sideways v3Delta *= 1.0 / (v3Delta.Length() + 0.01); // we push harder if we're close // QUESTION: is there an additional multiplier for this? current shoving seems a bit weak a_Entity.AddSpeed(v3Delta); return false; } ); } super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } HandleFalling(); }
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 cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { // Iterate through this entity's applied effects for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();) { // Copies values to prevent pesky wrong accesses and erasures cEntityEffect::eType EffectType = iter->first; cEntityEffect * Effect = iter->second; Effect->OnTick(*this); // Iterates (must be called before any possible erasure) ++iter; // Remove effect if duration has elapsed if (Effect->GetDuration() - Effect->GetTicks() <= 0) { RemoveEntityEffect(EffectType); } // TODO: Check for discrepancies between client and server effect values } class Pusher : public cEntityCallback { public: cEntity * m_Pusher; Pusher(cEntity * a_Pusher) : m_Pusher(a_Pusher) { } virtual bool Item(cEntity * a_Entity) override { if (a_Entity->GetUniqueID() == m_Pusher->GetUniqueID()) { return false; } // we only push other mobs, boats and minecarts if ((a_Entity->GetEntityType() != etMonster) && (a_Entity->GetEntityType() != etMinecart) && (a_Entity->GetEntityType() != etBoat)) { return false; } // do not push a boat / minecart you're sitting in if (m_Pusher->IsAttachedTo(a_Entity)) { return false; } Vector3d v3Delta = a_Entity->GetPosition() - m_Pusher->GetPosition(); v3Delta.y = 0.0; // we only push sideways v3Delta *= 1.0 / (v3Delta.Length() + 0.01); // we push harder if we're close // QUESTION: is there an additional multiplier for this? current shoving seems a bit weak a_Entity->AddSpeed(v3Delta); return false; } } Callback(this); m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), GetWidth(), GetHeight()), Callback); super::Tick(a_Dt, a_Chunk); HandleFalling(); }
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(); }