void cArrowEntity::CollectedBy(cPlayer * a_Dest) { if (m_IsInGround && !m_bIsCollected && CanPickup(*a_Dest)) { // Do not add the arrow to the inventory when the player is in creative: if (!a_Dest->IsGameModeCreative()) { int NumAdded = a_Dest->GetInventory().AddItem(E_ITEM_ARROW); if (NumAdded == 0) { // No space in the inventory return; } } // TODO: BroadcastCollectPickup needs a cPickup, which we don't have // m_World->BroadcastCollectPickup(*this, *a_Dest); m_bIsCollected = true; cFastRandom Random; m_World->BroadcastSoundEffect( "random.pop", (int)std::floor(GetPosX() * 8.0), (int)std::floor(GetPosY() * 8), (int)std::floor(GetPosZ() * 8), 0.2F, ((Random.NextFloat(1.0F) - Random.NextFloat(1.0F)) * 0.7F + 1.0F) * 2.0F ); } }
void cArrowEntity::CollectedBy(cPlayer * a_Dest) { if ((m_IsInGround) && (!m_bIsCollected) && (CanPickup(*a_Dest))) { int NumAdded = a_Dest->GetInventory().AddItem(E_ITEM_ARROW); if (NumAdded > 0) // Only play effects if there was space in inventory { m_World->BroadcastCollectPickup((const cPickup &)*this, *a_Dest); // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;) m_World->BroadcastSoundEffect("random.pop", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); m_bIsCollected = true; } } }
bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return) { TObjPtr<AInventory> Invstack = Inventory; // A pointer of the inventories item stack. // unmorphed versions of a currently morphed actor cannot pick up anything. if (toucher->flags & MF_UNMORPHED) return false; bool res; if (CanPickup(toucher)) res = TryPickup(toucher); else if (!(ItemFlags & IF_RESTRICTABSOLUTELY)) res = TryPickupRestricted(toucher); // let an item decide for itself how it will handle this else return false; // Morph items can change the toucher so we need an option to return this info. if (toucher_return != NULL) *toucher_return = toucher; if (!res && (ItemFlags & IF_ALWAYSPICKUP) && !ShouldStay()) { res = true; GoAwayAndDie(); } if (res) { GiveQuest(toucher); // Transfer all inventory accross that the old object had, if requested. if ((ItemFlags & IF_TRANSFER)) { while (Invstack) { AInventory* titem = Invstack; Invstack = titem->Inventory; if (titem->Owner == this) { if (!titem->CallTryPickup(toucher)) // The object no longer can exist { titem->Destroy(); } } } } } return res; }
void cArrowEntity::CollectedBy(cPlayer & a_Dest) { if (m_IsInGround && !m_bIsCollected && CanPickup(a_Dest)) { // Do not add the arrow to the inventory when the player is in creative: if (!a_Dest.IsGameModeCreative()) { int NumAdded = a_Dest.GetInventory().AddItem(E_ITEM_ARROW); if (NumAdded == 0) { // No space in the inventory return; } } GetWorld()->BroadcastCollectEntity(*this, a_Dest); GetWorld()->BroadcastSoundEffect("random.pop", GetPosX(), GetPosY(), GetPosZ(), 0.5, static_cast<float>(0.75 + (static_cast<float>((GetUniqueID() * 23) % 32)) / 64)); m_bIsCollected = true; } }
void cFloater::Tick(float a_Dt, cChunk & a_Chunk) { HandlePhysics(a_Dt, a_Chunk); if (IsBlockWater(m_World->GetBlock((int) GetPosX(), (int) GetPosY(), (int) GetPosZ())) && m_World->GetBlockMeta((int) GetPosX(), (int) GetPosY(), (int) GetPosZ()) == 0) { if ((!m_CanPickupItem) && (m_AttachedMobID == -1)) // Check if you can't already pickup a fish and if the floater isn't attached to a mob. { if (m_CountDownTime <= 0) { m_World->BroadcastSoundEffect("random.splash", GetPosX(), GetPosY(), GetPosZ(), 1, 1); SetPosY(GetPosY() - 1); m_CanPickupItem = true; m_PickupCountDown = 20; m_CountDownTime = 100 + m_World->GetTickRandomNumber(800); LOGD("Floater %i can be picked up", GetUniqueID()); } else if (m_CountDownTime == 20) // Calculate the position where the particles should spawn and start producing them. { LOGD("Started producing particles for floater %i", GetUniqueID()); m_ParticlePos.Set(GetPosX() + (-4 + m_World->GetTickRandomNumber(8)), GetPosY(), GetPosZ() + (-4 + m_World->GetTickRandomNumber(8))); m_World->BroadcastParticleEffect("splash", (float) m_ParticlePos.x, (float) m_ParticlePos.y, (float) m_ParticlePos.z, 0, 0, 0, 0, 15); } else if (m_CountDownTime < 20) { m_ParticlePos = (m_ParticlePos + (GetPosition() - m_ParticlePos) / 6); m_World->BroadcastParticleEffect("splash", (float) m_ParticlePos.x, (float) m_ParticlePos.y, (float) m_ParticlePos.z, 0, 0, 0, 0, 15); } m_CountDownTime--; if (m_World->GetHeight((int) GetPosX(), (int) GetPosZ()) == (int) GetPosY()) { if (m_World->IsWeatherWet() && m_World->GetTickRandomNumber(3) == 0) // 25% chance of an extra countdown when being rained on. { m_CountDownTime--; } } else // if the floater is underground it has a 50% chance of not decreasing the countdown. { if (m_World->GetTickRandomNumber(1) == 0) { m_CountDownTime++; } } } SetSpeedY(0.7); } if (CanPickup()) // Make sure the floater "loses its fish" { m_PickupCountDown--; if (m_PickupCountDown == 0) { m_CanPickupItem = false; LOGD("The fish is gone. Floater %i can not pick an item up.", GetUniqueID()); } } if ((GetSpeed().Length() > 4) && (m_AttachedMobID == -1)) { cFloaterEntityCollisionCallback Callback(this, GetPosition(), GetPosition() + GetSpeed() / 20); a_Chunk.ForEachEntity(Callback); if (Callback.HasHit()) { AttachTo(Callback.GetHitEntity()); Callback.GetHitEntity()->TakeDamage(*this); // TODO: the player attacked the mob not the floater. m_AttachedMobID = Callback.GetHitEntity()->GetUniqueID(); } } cFloaterCheckEntityExist EntityCallback; m_World->DoWithEntityByID(m_PlayerID, EntityCallback); if (!EntityCallback.DoesExist()) // The owner doesn't exist anymore. Destroy the floater entity. { Destroy(true); } if (m_AttachedMobID != -1) { m_World->DoWithEntityByID(m_AttachedMobID, EntityCallback); // The mob the floater was attached to doesn't exist anymore. if (!EntityCallback.DoesExist()) { m_AttachedMobID = -1; } } SetSpeedX(GetSpeedX() * 0.95); SetSpeedZ(GetSpeedZ() * 0.95); BroadcastMovementUpdate(); }