summaryrefslogtreecommitdiffstats
path: root/src/Items/ItemPumpkin.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Items/ItemPumpkin.h')
-rw-r--r--src/Items/ItemPumpkin.h83
1 files changed, 52 insertions, 31 deletions
diff --git a/src/Items/ItemPumpkin.h b/src/Items/ItemPumpkin.h
index b8038093c..33810b51f 100644
--- a/src/Items/ItemPumpkin.h
+++ b/src/Items/ItemPumpkin.h
@@ -20,44 +20,50 @@ public:
}
+
+
+
virtual bool OnPlayerPlace(
- cWorld & a_World, cPlayer & a_Player, const cItem & a_EquippedItem,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
- int a_CursorX, int a_CursorY, int a_CursorZ
+ cWorld & a_World,
+ cPlayer & a_Player,
+ const cItem & a_EquippedItem,
+ const Vector3i a_ClickedBlockPos,
+ eBlockFace a_ClickedBlockFace,
+ const Vector3i a_CursorPos
) override
{
// First try spawning a snow golem or an iron golem:
- int PlacedBlockX = a_BlockX;
- int PlacedBlockY = a_BlockY;
- int PlacedBlockZ = a_BlockZ;
- AddFaceDirection(PlacedBlockX, PlacedBlockY, PlacedBlockZ, a_BlockFace);
- if (TrySpawnGolem(a_World, a_Player, PlacedBlockX, PlacedBlockY, PlacedBlockZ))
+ auto PlacePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace);
+ if (TrySpawnGolem(a_World, a_Player, PlacePos))
{
// The client thinks that they placed the pumpkin, let them know it's been replaced:
- a_Player.SendBlocksAround(PlacedBlockX, PlacedBlockY, PlacedBlockZ);
+ a_Player.SendBlocksAround(PlacePos.x, PlacePos.y, PlacePos.z);
return true;
}
// No golem at these coords, place the block normally:
- return Super::OnPlayerPlace(a_World, a_Player, a_EquippedItem, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ);
+ return Super::OnPlayerPlace(a_World, a_Player, a_EquippedItem, a_ClickedBlockPos, a_ClickedBlockFace, a_CursorPos);
}
+
+
+
/** Spawns a snow / iron golem if the shape matches the recipe, supposing that the block placed at the specified coords is a pumpkin.
Returns true if the golem blocks are removed (for spawning), false if the recipe is not matched. */
- bool TrySpawnGolem(cWorld & a_World, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
+ bool TrySpawnGolem(cWorld & a_World, cPlayer & a_Player, const Vector3i a_PumpkinPos)
{
// A golem can't form with a pumpkin below level 2 or above level 255
- if ((a_BlockY < 2) || (a_BlockY >= cChunkDef::Height))
+ if ((a_PumpkinPos.y < 2) || (a_PumpkinPos.y >= cChunkDef::Height))
{
return false;
}
// Decide which golem to try spawning based on the block below the placed pumpkin:
- switch (a_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ))
+ switch (a_World.GetBlock(a_PumpkinPos.addedY(-1)))
{
- case E_BLOCK_SNOW_BLOCK: return TrySpawnSnowGolem(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ);
- case E_BLOCK_IRON_BLOCK: return TrySpawnIronGolem(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ);
+ case E_BLOCK_SNOW_BLOCK: return TrySpawnSnowGolem(a_World, a_Player, a_PumpkinPos);
+ case E_BLOCK_IRON_BLOCK: return TrySpawnIronGolem(a_World, a_Player, a_PumpkinPos);
default:
{
// No golem here
@@ -67,45 +73,59 @@ public:
}
+
+
+
/** Spawns a snow golem if the shape matches the recipe, supposing that the block placed at the specified coords is a pumpkin.
Returns true if the golem blocks are removed (for spawning), false if the recipe is not matched.
Assumes that the block below the specified block has already been checked and is a snow block. */
- bool TrySpawnSnowGolem(cWorld & a_World, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
+ bool TrySpawnSnowGolem(cWorld & a_World, cPlayer & a_Player, const Vector3i a_PumpkinPos)
{
+ ASSERT(a_PumpkinPos.y > 1);
+ ASSERT(a_World.GetBlock(a_PumpkinPos.addedY(-1)) == E_BLOCK_SNOW);
+
// Need one more snow block 2 blocks below the pumpkin:
- if (a_World.GetBlock(a_BlockX, a_BlockY - 2, a_BlockZ) != E_BLOCK_SNOW_BLOCK)
+ if (a_World.GetBlock(a_PumpkinPos.addedY(-2)) != E_BLOCK_SNOW_BLOCK)
{
return false;
}
// Try to place air blocks where the original recipe blocks were:
sSetBlockVector AirBlocks;
- AirBlocks.emplace_back(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); // Head
- AirBlocks.emplace_back(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0); // Torso
- AirBlocks.emplace_back(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0); // Legs
+ AirBlocks.emplace_back(a_PumpkinPos, E_BLOCK_AIR, 0); // Head
+ AirBlocks.emplace_back(a_PumpkinPos.addedY(-1), E_BLOCK_AIR, 0); // Torso
+ AirBlocks.emplace_back(a_PumpkinPos.addedY(-2), E_BLOCK_AIR, 0); // Legs
if (!a_Player.PlaceBlocks(AirBlocks))
{
return false;
}
// Spawn the golem:
- a_World.SpawnMob(static_cast<double>(a_BlockX) + 0.5, a_BlockY - 2, static_cast<double>(a_BlockZ) + 0.5, mtSnowGolem, false);
+ auto GolemPos = Vector3d(a_PumpkinPos) + Vector3d(0.5, -2, 0.5);
+ a_World.SpawnMob(GolemPos.x, GolemPos.y, GolemPos.z, mtSnowGolem, false);
return true;
}
+
+
+
/** Spawns an iron golem if the shape matches the recipe, supposing that the block placed at the specified coords is a pumpkin.
Returns true if the golem blocks are removed (for spawning), false if the recipe is not matched.
Assumes that the block below the specified block has already been checked and is an iron block. */
- bool TrySpawnIronGolem(cWorld & a_World, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
+ bool TrySpawnIronGolem(cWorld & a_World, cPlayer & a_Player, const Vector3i a_PumpkinPos)
{
+ ASSERT(a_PumpkinPos.y > 1);
+ ASSERT(a_World.GetBlock(a_PumpkinPos.addedY(-1)) == E_BLOCK_IRON_BLOCK);
+
// Need one more iron block 2 blocks below the pumpkin:
- if (a_World.GetBlock(a_BlockX, a_BlockY - 2, a_BlockZ) != E_BLOCK_IRON_BLOCK)
+ if (a_World.GetBlock(a_PumpkinPos.addedY(-2)) != E_BLOCK_IRON_BLOCK)
{
return false;
}
// Check the two arm directions (X, Z) using a loop over two sets of offset vectors:
+ auto BodyPos = a_PumpkinPos.addedY(-1);
static const Vector3i ArmOffsets[] =
{
{1, 0, 0},
@@ -115,8 +135,8 @@ public:
{
// If the arm blocks don't match, bail out of this loop repetition:
if (
- (a_World.GetBlock(a_BlockX + ArmOffsets[i].x, a_BlockY - 1, a_BlockZ + ArmOffsets[i].z) != E_BLOCK_IRON_BLOCK) ||
- (a_World.GetBlock(a_BlockX - ArmOffsets[i].x, a_BlockY - 1, a_BlockZ - ArmOffsets[i].z) != E_BLOCK_IRON_BLOCK)
+ (a_World.GetBlock(BodyPos + ArmOffsets[i]) != E_BLOCK_IRON_BLOCK) ||
+ (a_World.GetBlock(BodyPos - ArmOffsets[i]) != E_BLOCK_IRON_BLOCK)
)
{
continue;
@@ -124,18 +144,19 @@ public:
// Try to place air blocks where the original recipe blocks were:
sSetBlockVector AirBlocks;
- AirBlocks.emplace_back(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); // Head
- AirBlocks.emplace_back(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0); // Torso
- AirBlocks.emplace_back(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0); // Legs
- AirBlocks.emplace_back(a_BlockX + ArmOffsets[i].x, a_BlockY - 1, a_BlockZ + ArmOffsets[i].z, E_BLOCK_AIR, 0); // Arm
- AirBlocks.emplace_back(a_BlockX - ArmOffsets[i].x, a_BlockY - 1, a_BlockZ - ArmOffsets[i].z, E_BLOCK_AIR, 0); // Arm
+ AirBlocks.emplace_back(a_PumpkinPos, E_BLOCK_AIR, 0); // Head
+ AirBlocks.emplace_back(BodyPos, E_BLOCK_AIR, 0); // Torso
+ AirBlocks.emplace_back(BodyPos.addedY(-1), E_BLOCK_AIR, 0); // Legs
+ AirBlocks.emplace_back(BodyPos + ArmOffsets[i], E_BLOCK_AIR, 0); // Arm
+ AirBlocks.emplace_back(BodyPos - ArmOffsets[i], E_BLOCK_AIR, 0); // Arm
if (!a_Player.PlaceBlocks(AirBlocks))
{
return false;
}
// Spawn the golem:
- a_World.SpawnMob(static_cast<double>(a_BlockX) + 0.5, a_BlockY - 2, static_cast<double>(a_BlockZ) + 0.5, mtIronGolem, false);
+ auto GolemPos = Vector3d(a_PumpkinPos) + Vector3d(0.5, -2, 0.5);
+ a_World.SpawnMob(GolemPos.x, GolemPos.y, GolemPos.z, mtIronGolem, false);
return true;
} // for i - ArmOffsets[]