void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); if (m_EMState == CHASING) { CheckEventLostPlayer(); } else { CheckEventSeePlayer(); } if (m_Target == NULL) return; cTracer LineOfSight(GetWorld()); Vector3d AttackDirection(m_Target->GetPosition() - GetPosition()); if (ReachedFinalDestination() && !LineOfSight.Trace(GetPosition(), AttackDirection, (int)AttackDirection.Length())) { // Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls) Attack(a_Dt / 1000); } }
void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); if (m_EMState == CHASING) { CheckEventLostPlayer(); } else { CheckEventSeePlayer(); } if (m_Target == nullptr) { return; } cTracer LineOfSight(GetWorld()); Vector3d MyHeadPosition = GetPosition() + Vector3d(0, GetHeight(), 0); Vector3d AttackDirection(m_Target->GetPosition() + Vector3d(0, m_Target->GetHeight(), 0) - MyHeadPosition); if (TargetIsInRange() && !LineOfSight.Trace(MyHeadPosition, AttackDirection, static_cast<int>(AttackDirection.Length())) && (GetHealth() > 0.0)) { // Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls) StopMovingToPosition(); Attack(a_Dt); } }
void cPassiveMonster::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); if (m_EMState == ESCAPING) { CheckEventLostPlayer(); } cItem FollowedItem = GetFollowedItem(); if (FollowedItem.IsEmpty()) { return; } cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); if (a_Closest_Player != nullptr) { if (a_Closest_Player->GetEquippedItem().IsEqual(FollowedItem)) { Vector3d PlayerPos = a_Closest_Player->GetPosition(); MoveToPosition(PlayerPos); } } }
void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (m_EMState == CHASING) { CheckEventLostPlayer(); } else { CheckEventSeePlayer(a_Chunk); } auto target = GetTarget(); if (target == nullptr) { return; } // TODO: Currently all mobs see through lava, but only Nether-native mobs should be able to. Vector3d MyHeadPosition = GetPosition() + Vector3d(0, GetHeight(), 0); Vector3d TargetPosition = target->GetPosition() + Vector3d(0, target->GetHeight(), 0); if ( TargetIsInRange() && cLineBlockTracer::LineOfSightTrace(*GetWorld(), MyHeadPosition, TargetPosition, cLineBlockTracer::losAirWaterLava) && (GetHealth() > 0.0) ) { // Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls) Attack(a_Dt); } }
void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); m_SeePlayerInterval += a_Dt; if (m_SeePlayerInterval > 1) { int rem = m_World->GetTickRandomNumber(3) + 1; // Check most of the time but miss occasionally m_SeePlayerInterval = 0.0; if (rem >= 2) { if (m_EMState == CHASING) { CheckEventLostPlayer(); } else { CheckEventSeePlayer(); } } } }
void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (m_EMState == ESCAPING) { CheckEventLostPlayer(); } // if we have a partner, mate if (m_LovePartner != nullptr) { if (m_MatingTimer > 0) { // If we should still mate, keep bumping into them until baby is made Vector3d Pos = m_LovePartner->GetPosition(); MoveToPosition(Pos); } else { // Mating finished. Spawn baby Vector3f Pos = (GetPosition() + m_LovePartner->GetPosition()) * 0.5; UInt32 BabyID = m_World->SpawnMob(Pos.x, Pos.y, Pos.z, GetMobType(), true); cPassiveMonster * Baby = nullptr; m_World->DoWithEntityByID(BabyID, [&](cEntity & a_Entity) { Baby = static_cast<cPassiveMonster *>(&a_Entity); return true; } ); if (Baby != nullptr) { Baby->InheritFromParents(this, m_LovePartner); } m_World->SpawnExperienceOrb(Pos.x, Pos.y, Pos.z, GetRandomProvider().RandInt(1, 6)); m_LovePartner->ResetLoveMode(); ResetLoveMode(); } } else { // We have no partner, so we just chase the player if they have our breeding item cItems FollowedItems; GetFollowedItems(FollowedItems); if (FollowedItems.Size() > 0) { cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), static_cast<float>(m_SightDistance)); if (a_Closest_Player != nullptr) { cItem EquippedItem = a_Closest_Player->GetEquippedItem(); if (FollowedItems.ContainsType(EquippedItem)) { Vector3d PlayerPos = a_Closest_Player->GetPosition(); MoveToPosition(PlayerPos); } } } } // If we are in love mode but we have no partner, search for a partner neabry if (m_LoveTimer > 0) { if (m_LovePartner == nullptr) { m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8), [=](cEntity & a_Entity) { // If the entity is not a monster, don't breed with it // Also, do not self-breed if ((a_Entity.GetEntityType() != etMonster) || (&a_Entity == this)) { return false; } auto & Me = static_cast<cPassiveMonster&>(*this); auto & PotentialPartner = static_cast<cPassiveMonster&>(a_Entity); // If the potential partner is not of the same species, don't breed with it if (PotentialPartner.GetMobType() != Me.GetMobType()) { return false; } // If the potential partner is not in love // Or they already have a mate, do not breed with them if ((!PotentialPartner.IsInLove()) || (PotentialPartner.GetPartner() != nullptr)) { return false; } // All conditions met, let's breed! PotentialPartner.EngageLoveMode(&Me); Me.EngageLoveMode(&PotentialPartner); return true; } ); } m_LoveTimer--; } if (m_MatingTimer > 0) { m_MatingTimer--; } if (m_LoveCooldown > 0) { m_LoveCooldown--; } }