2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
#include <cstdlib>
|
|
|
|
#endif
|
|
|
|
|
2012-09-23 18:09:57 -04:00
|
|
|
#include "Pickup.h"
|
2013-08-19 05:39:13 -04:00
|
|
|
#include "../ClientHandle.h"
|
|
|
|
#include "../Inventory.h"
|
|
|
|
#include "../World.h"
|
|
|
|
#include "../Simulator/FluidSimulator.h"
|
|
|
|
#include "../Server.h"
|
2012-09-23 18:09:57 -04:00
|
|
|
#include "Player.h"
|
2013-08-19 05:39:13 -04:00
|
|
|
#include "../PluginManager.h"
|
|
|
|
#include "../Item.h"
|
|
|
|
#include "../Root.h"
|
|
|
|
#include "../Chunk.h"
|
|
|
|
|
|
|
|
#include "../Vector3d.h"
|
|
|
|
#include "../Vector3f.h"
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-12-27 21:45:20 -05:00
|
|
|
cPickup::cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem & a_Item, float a_SpeedX /* = 0.f */, float a_SpeedY /* = 0.f */, float a_SpeedZ /* = 0.f */)
|
2013-07-01 06:39:56 -04:00
|
|
|
: cEntity(etPickup, ((double)(a_MicroPosX)) / 32, ((double)(a_MicroPosY)) / 32, ((double)(a_MicroPosZ)) / 32, 0.2, 0.2)
|
2012-06-14 09:06:06 -04:00
|
|
|
, m_Timer( 0.f )
|
2012-12-27 21:45:20 -05:00
|
|
|
, m_Item(a_Item)
|
2012-06-14 09:06:06 -04:00
|
|
|
, m_bCollected( false )
|
|
|
|
{
|
2013-07-08 03:23:44 -04:00
|
|
|
m_MaxHealth = 5;
|
|
|
|
m_Health = 5;
|
2013-03-22 02:33:10 -04:00
|
|
|
SetSpeed(a_SpeedX, a_SpeedY, a_SpeedZ);
|
2013-04-22 03:18:03 -04:00
|
|
|
m_Gravity = -3.0;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-08-24 03:58:26 -04:00
|
|
|
void cPickup::SpawnOn(cClientHandle & a_Client)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2012-08-24 03:58:26 -04:00
|
|
|
a_Client.SendPickupSpawn(*this);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-04-13 17:02:10 -04:00
|
|
|
super::Tick(a_Dt, a_Chunk);
|
2013-04-22 03:18:03 -04:00
|
|
|
BroadcastMovementUpdate(); //Notify clients of position
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
m_Timer += a_Dt;
|
2013-04-22 03:18:03 -04:00
|
|
|
|
|
|
|
if (!m_bCollected)
|
|
|
|
{
|
|
|
|
int BlockY = (int) floor(GetPosY());
|
2013-08-24 15:34:42 -04:00
|
|
|
if ((BlockY >= 0) && (BlockY < cChunkDef::Height)) // Don't do anything except for falling when outside the world
|
2013-04-22 03:18:03 -04:00
|
|
|
{
|
2013-04-28 11:30:06 -04:00
|
|
|
int BlockX = (int) floor(GetPosX());
|
|
|
|
int BlockZ = (int) floor(GetPosZ());
|
2013-08-24 15:34:42 -04:00
|
|
|
// Position might have changed due to physics. So we have to make sure we have the correct chunk.
|
2013-04-28 11:30:06 -04:00
|
|
|
cChunk * CurrentChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
|
|
|
|
if (CurrentChunk != NULL) // Make sure the chunk is loaded
|
2013-04-22 03:18:03 -04:00
|
|
|
{
|
2013-04-28 11:30:06 -04:00
|
|
|
int RelBlockX = BlockX - (CurrentChunk->GetPosX() * cChunkDef::Width);
|
|
|
|
int RelBlockZ = BlockZ - (CurrentChunk->GetPosZ() * cChunkDef::Width);
|
|
|
|
|
2013-08-24 15:34:42 -04:00
|
|
|
// If the pickup is on the bottommost block position, make it think the void is made of air: (#131)
|
|
|
|
BLOCKTYPE BlockBelow = (BlockY > 0) ? CurrentChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
|
2013-04-28 11:30:06 -04:00
|
|
|
BLOCKTYPE BlockIn = CurrentChunk->GetBlock(RelBlockX, BlockY, RelBlockZ);
|
|
|
|
|
|
|
|
if (
|
|
|
|
IsBlockLava(BlockBelow) || (BlockBelow == E_BLOCK_FIRE) ||
|
|
|
|
IsBlockLava(BlockIn) || (BlockIn == E_BLOCK_FIRE)
|
|
|
|
)
|
|
|
|
{
|
2013-04-22 03:18:03 -04:00
|
|
|
m_bCollected = true;
|
2013-04-28 11:30:06 -04:00
|
|
|
m_Timer = 0; // We have to reset the timer.
|
|
|
|
m_Timer += a_Dt; // In case we have to destroy the pickup in the same tick.
|
2013-04-22 03:18:03 -04:00
|
|
|
if (m_Timer > 500.f)
|
|
|
|
{
|
2013-06-25 02:36:59 -04:00
|
|
|
Destroy(true);
|
2013-04-22 03:18:03 -04:00
|
|
|
return;
|
|
|
|
}
|
2013-04-28 11:30:06 -04:00
|
|
|
}
|
2013-04-22 03:18:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2012-12-22 05:15:53 -05:00
|
|
|
if (m_Timer > 500.f) // 0.5 second
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-06-25 02:36:59 -04:00
|
|
|
Destroy(true);
|
2012-06-14 09:06:06 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-22 05:15:53 -05:00
|
|
|
if (m_Timer > 1000 * 60 * 5) // 5 minutes
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-06-25 02:36:59 -04:00
|
|
|
Destroy(true);
|
2012-06-14 09:06:06 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-03-22 02:33:10 -04:00
|
|
|
if (GetPosY() < -8) // Out of this world and no more visible!
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-06-25 02:36:59 -04:00
|
|
|
Destroy(true);
|
2012-06-14 09:06:06 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-12-22 05:15:53 -05:00
|
|
|
bool cPickup::CollectedBy(cPlayer * a_Dest)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-13 16:29:52 -04:00
|
|
|
ASSERT(a_Dest != NULL);
|
|
|
|
|
2012-08-24 05:49:00 -04:00
|
|
|
if (m_bCollected)
|
|
|
|
{
|
2013-05-17 10:30:18 -04:00
|
|
|
// LOG("Pickup %d cannot be collected by \"%s\", because it has already been collected.", m_UniqueID, a_Dest->GetName().c_str());
|
2012-08-24 05:49:00 -04:00
|
|
|
return false; // It's already collected!
|
|
|
|
}
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
// 800 is to long
|
2012-08-24 05:49:00 -04:00
|
|
|
if (m_Timer < 500.f)
|
|
|
|
{
|
2013-05-17 10:30:18 -04:00
|
|
|
// LOG("Pickup %d cannot be collected by \"%s\", because it is not old enough.", m_UniqueID, a_Dest->GetName().c_str());
|
2012-08-24 05:49:00 -04:00
|
|
|
return false; // Not old enough
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2013-01-28 11:17:26 -05:00
|
|
|
if (cRoot::Get()->GetPluginManager()->CallHookCollectingPickup(a_Dest, *this))
|
2012-08-24 05:49:00 -04:00
|
|
|
{
|
2013-05-17 10:30:18 -04:00
|
|
|
// LOG("Pickup %d cannot be collected by \"%s\", because a plugin has said no.", m_UniqueID, a_Dest->GetName().c_str());
|
2012-08-24 05:49:00 -04:00
|
|
|
return false;
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
int NumAdded = a_Dest->GetInventory().AddItem(m_Item);
|
|
|
|
if (NumAdded > 0)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
m_Item.m_ItemCount -= NumAdded;
|
2012-08-24 05:49:00 -04:00
|
|
|
m_World->BroadcastCollectPickup(*this, *a_Dest);
|
2013-05-24 03:30:39 -04:00
|
|
|
if (m_Item.m_ItemCount == 0)
|
2012-12-22 05:15:53 -05:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
// All of the pickup has been collected, schedule the pickup for destroying
|
|
|
|
m_bCollected = true;
|
2012-10-24 08:48:25 -04:00
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
m_Timer = 0;
|
2012-06-14 09:06:06 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-05-17 10:30:18 -04:00
|
|
|
// LOG("Pickup %d cannot be collected by \"%s\", because there's no space in the inventory.", a_Dest->GetName().c_str(), m_UniqueID);
|
2012-06-14 09:06:06 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|