Object Placement System for RedM โ
A flexible and reusable object placement system for RedM, allowing for precise object preview and placement with rotation and height adjustment.
Features โ
- Preview-based placement system
- Precise position control with intuitive movement
- Multi-axis rotation support
- Height adjustment
- Customizable placement settings
- Custom placement handlers
- Built-in UI control display
- Player state management during placement
- Automatic resource cleanup
Usage โ
Basic Usage โ
lua
local Placer = exports.bln_lib:ObjPlacer()
-- Simple object placement with creation
RegisterCommand('placeobject', function()
Placer.StartPlacement('p_beechers_ladder01x', {
handlers = {
afterPlace = function(placementData)
-- Create the actual object after placement is confirmed
local object = CreateObject(
placementData.model,
placementData.position.x,
placementData.position.y,
placementData.position.z,
true, true, false
)
-- Set rotation
SetEntityRotation(object,
placementData.rotation.x,
placementData.rotation.y,
placementData.rotation.z,
2, true
)
end
}
})
end)
Custom Settings โ
lua
local settings = {
moveSpeed = 0.05, -- Movement speed
rotationSpeed = 3.0, -- Rotation speed
heightSpeed = 0.05, -- Height adjustment speed
spawnDistance = 1.0, -- Initial spawn distance from player
spawnHeight = 0.0, -- Initial spawn height offset
placingAlpha = 128, -- Preview transparency (0-255)
}
Placer.StartPlacement('p_beechers_ladder01x', settings)
Using Handlers โ
The placement system supports four types of handlers:
beforePlace
: Runs before placement confirmation, can prevent placementonPlace
: Runs during placement confirmation, can prevent placementafterPlace
: Runs after placement is confirmed, used for creating the actual objectonCancel
: Runs when placement is cancelled or cleaning up
lua
local settings = {
handlers = {
beforePlace = function(placementData)
-- Check conditions before placing
local hasRequiredItems = exports.inventory:HasItems('required_item', 1)
if not hasRequiredItems then
Print("You need required items!")
return false -- Prevents placement
end
return true -- Allows placement to continue
end,
onPlace = function(placementData)
-- Run a minigame or skill check
local success = exports.minigame:Start()
return success -- Returns true/false to allow/prevent placement
end,
afterPlace = function(placementData)
-- Create and setup the actual object
local object = CreateObject(
placementData.model,
placementData.position,
true, true, false
)
-- Additional setup...
TriggerServerEvent('saveObject', placementData.position, placementData.rotation)
end,
onCancel = function(placementData)
-- Handle cleanup or cancellation
Print("Placement cancelled")
end
}
}
Placer.StartPlacement('p_beechers_ladder01x', settings)
Example: Placement with Animation โ
lua
local settings = {
handlers = {
beforePlace = function(placementData)
local ped = PlayerPedId()
TaskStartScenarioInPlace(ped, "WORLD_HUMAN_HAMMER_WORK", 0, true)
Wait(2000)
ClearPedTasks(ped)
return true
end,
afterPlace = function(placementData)
-- Create the actual object here
local object = CreateObject(placementData.model, placementData.position, true, true, false)
SetEntityRotation(object, placementData.rotation.x, 0.0, placementData.rotation.z, 2, true)
end
}
}
Placer.StartPlacement('p_beechers_ladder01x', settings)
API Reference โ
Exports โ
ObjPlacer โ
Returns the placement handler with the following methods:
StartPlacement(objectModel, settings) โ
Starts the placement preview mode for the specified object.
objectModel
: String - The model name of the object to placesettings
: Table (optional) - Custom settings and handlers
CancelPlacement() โ
Cancels the current placement and cleans up.
IsPlacing() โ
Checks if placement mode is active.
- Returns: boolean
GetPreviewData() โ
Gets the current preview object data.
- Returns: Table containing model, position, and rotation
Handler Data โ
All handlers receive a placementData
table containing:
lua
{
model = hash, -- Model hash of the object
position = vector3, -- Final position
rotation = vector3 -- Final rotation
}
Notes โ
- The system uses a preview object during placement
- Preview objects are semi-transparent and non-colliding
- Actual object creation is handled in the afterPlace handler
- Player movement is restricted during placement
- Resource automatically cleans up on stop
- Multiple handlers can be used together
- Handler return values control placement flow
Example Implementation โ
Here's a complete example of a ladder placement system:
lua
local Placer = exports.bln_lib:ObjPlacer()
local ladderEntity = nil
local Settings = {
moveSpeed = 0.05,
rotationSpeed = 3.0,
heightSpeed = 0.05,
spawnDistance = 1.0,
spawnHeight = 0.0,
placingAlpha = 128,
handlers = {
afterPlace = function(placementData)
-- Create the actual ladder
local object = CreateObject(
placementData.model,
placementData.position.x,
placementData.position.y,
placementData.position.z,
true, true, false
)
SetEntityRotation(object,
placementData.rotation.x,
placementData.rotation.y,
placementData.rotation.z,
2, true
)
ladderEntity = object
FreezeEntityPosition(object, true)
end,
onCancel = function(placementData)
if ladderEntity then
DeleteObject(ladderEntity)
ladderEntity = nil
end
end
}
}
RegisterCommand('ladder', function()
if ladderEntity or Placer.IsPlacing() then
if ladderEntity then
DeleteObject(ladderEntity)
ladderEntity = nil
end
Placer.CancelPlacement()
return
end
Placer.StartPlacement('p_beechers_ladder01x', Settings)
end)