Skip to main content
Skip to main content

Pallet

Pallet

Description

Specialization for handling the content on the big bags

Functions

autoLoad

Description

Definition

autoLoad()

Arguments

anysuperFunc
anyautoLoader
anynode
anyposX
anyposZ
anysizeX
anysizeZ

Code

function Pallet:autoLoad(superFunc, autoLoader, node, posX, posZ, sizeX, sizeZ)
local mountPosX = posX + sizeX * 0.5
local mountPosY = 0
local mountPosZ = posZ + sizeZ * 0.5
local mountRotX = 0
local mountRotY = math.pi * 0.5
local mountRotZ = 0

self:mountKinematic(autoLoader, node, mountPosX, mountPosY, mountPosZ, mountRotX, mountRotY, mountRotZ)

return true
end

collectPalletTensionBeltNodes

Description

Definition

collectPalletTensionBeltNodes()

Arguments

anynodes

Code

function Pallet:collectPalletTensionBeltNodes(nodes)
local spec = self.spec_pallet
if #spec.tensionBeltNodes > 0 then
for _, node in ipairs(spec.tensionBeltNodes) do
table.insert(nodes, node)
end
end

for i = 1 , #spec.contents do
local content = spec.contents[i]
for j = 1 , #content.objects do
local object = content.objects[j]
if object.isActive and object.useAsTensionBeltMesh then
table.insert(nodes, object.tensionBeltNode or object.node)
end
end
end

-- add additional mesh nodes that are defined via xml
if self.spec_tensionBeltObject ~ = nil then
for _, meshNode in ipairs( self.spec_tensionBeltObject.meshNodes) do
table.insert(nodes, meshNode)
end
end
end

getAutoLoadSize

Description

Definition

getAutoLoadSize()

Arguments

anysuperFunc

Code

function Pallet:getAutoLoadSize(superFunc)
local size = self.size
-- pallets are rotated by 90°.so we need to switch length and width
local sizeX = size.length
local sizeY = size.height
local sizeZ = size.width

return sizeX, sizeY, sizeZ
end

getCanBeReset

Description

Definition

getCanBeReset()

Arguments

anysuperFunc

Code

function Pallet:getCanBeReset(superFunc)
return false
end

getFillUnitEmptyOnReset

Description

Definition

getFillUnitEmptyOnReset()

Arguments

anysuperFunc

Code

function Pallet:getFillUnitEmptyOnReset(superFunc)
return false
end

getInfoBoxTitle

Description

Definition

getInfoBoxTitle()

Code

function Pallet:getInfoBoxTitle()
return g_i18n:getText( "infohud_pallet" )
end

getIsMapHotspotVisible

Description

Definition

getIsMapHotspotVisible()

Arguments

anysuperFunc

Code

function Pallet:getIsMapHotspotVisible(superFunc)
return false
end

getMeshNodes

Description

Definition

getMeshNodes()

Arguments

anysuperFunc

Code

function Pallet:getMeshNodes(superFunc)
local spec = self.spec_pallet
if spec.tensionBeltMeshesDirty then
spec.tensionBeltMeshes = { }
self:collectPalletTensionBeltNodes(spec.tensionBeltMeshes)
spec.tensionBeltMeshesDirty = false
end

if #spec.tensionBeltMeshes > 0 then
return spec.tensionBeltMeshes
end

return superFunc( self )
end

getShowInVehiclesOverview

Description

Definition

getShowInVehiclesOverview()

Arguments

anysuperFunc

Code

function Pallet:getShowInVehiclesOverview(superFunc)
return false
end

initSpecialization

Description

Definition

initSpecialization()

Code

function Pallet.initSpecialization()
local schema = Vehicle.xmlSchema
schema:setXMLSpecializationType( "Pallet" )

schema:register(XMLValueType.INT, "vehicle.pallet#fillUnitIndex" , "Fill unit index" , 1 )
schema:register(XMLValueType.NODE_INDEX, "vehicle.pallet#node" , "Root visual pallet node" )
schema:register(XMLValueType.NODE_INDICES, "vehicle.pallet#linkNode" , "Link node for externally loaded visual pallet(can be multiple link nodes separated by space)" )
schema:register(XMLValueType.FILENAME, "vehicle.pallet#filename" , "Path to visual pallet i3d file to load" , "$data/objects/pallets/shared/euroPallet/euroPallet.i3d" )
schema:register(XMLValueType.FILENAME, "vehicle.pallet.texture(?)#diffuse" , "Path to the diffuse texture to use(if multiple are defined it will switch between them randomly)" )

schema:register(XMLValueType.INT, "vehicle.pallet.content(?)#fillUnitIndex" , "Fill unit index for this content" , "pallet#fillUnitIndex" )
schema:register(XMLValueType.NODE_INDEX, "vehicle.pallet.content(?).object(?)#node" , "Object node" )
schema:register(XMLValueType.NODE_INDEX, "vehicle.pallet.content(?).object(?)#tensionBeltNode" , "Object used for tension belt calculations" )
schema:register(XMLValueType.BOOL, "vehicle.pallet.content(?).object(?)#useAsTensionBeltMesh" , "Flag for toggling object node being used as tension belt node" , true )

schema:register(XMLValueType.NODE_INDEX, "vehicle.pallet.straps.strap(?)#startNode" , "Start node of the strap" )
schema:register(XMLValueType.NODE_INDEX, "vehicle.pallet.straps.strap(?)#endNode" , "End node of the strap" )
schema:register(XMLValueType.STRING, "vehicle.pallet.straps.strap(?)#tensionBeltType" , "Type of the tension belt to use" , "basic" )
schema:register(XMLValueType.NODE_INDEX, "vehicle.pallet.straps.strap(?).intersectionNode(?)#node" , "Intersection node" )

SoundManager.registerSampleXMLPaths(schema, "vehicle.pallet.sounds" , "unload" )

schema:setXMLSpecializationType()

local schemaSavegame = Vehicle.xmlSchemaSavegame
local key = "vehicles.vehicle(?).pallet"
schemaSavegame:register(XMLValueType.FLOAT, key .. "#age" , "Random age of the pallet [0-1]" )
end

loadComponentFromXML

Description

Definition

loadComponentFromXML()

Arguments

anysuperFunc
anycomponent
anyxmlFile
anykey
anyrootPosition
anyi

Code

function Pallet:loadComponentFromXML(superFunc, component, xmlFile, key, rootPosition, i)
if not Platform.gameplay.hasDynamicPallets then
if getRigidBodyType(component.node) = = RigidBodyType.DYNAMIC then
setRigidBodyType(component.node, RigidBodyType.KINEMATIC)
end
end

return superFunc( self , component, xmlFile, key, rootPosition, i)
end

onDelete

Description

Called on delete

Definition

onDelete()

Code

function Pallet:onDelete()
local spec = self.spec_pallet
if self.isClient then
g_soundManager:deleteSamples(spec.samples)
end

if spec.sharedLoadRequestId ~ = nil then
g_i3DManager:releaseSharedI3DFile(spec.sharedLoadRequestId)
spec.sharedLoadRequestId = nil
end

g_currentMission.slotSystem:removeLimitedObject(SlotSystem.LIMITED_OBJECT_PALLET, self )
end

onFillUnitFillLevelChanged

Description

Definition

onFillUnitFillLevelChanged()

Arguments

anyfillUnitIndex
anyfillLevelDelta
anyfillType
anytoolType
anyfillPositionData
anyappliedDelta

Code

function Pallet:onFillUnitFillLevelChanged(fillUnitIndex, fillLevelDelta, fillType, toolType, fillPositionData, appliedDelta)
local spec = self.spec_pallet
for i = 1 , #spec.contents do
local content = spec.contents[i]

if content.fillUnitIndex = = fillUnitIndex then
local fillLevelPct = self:getFillUnitFillLevelPercentage(fillUnitIndex)

local visibleIndex = math.floor(content.numObjects * fillLevelPct)
if visibleIndex = = 0 and fillLevelPct then
visibleIndex = 1 -- show at least one object if somethign is loaded
end

for j = 1 , #content.objects do
local object = content.objects[j]
local isActive = j < = visibleIndex
if object.isActive ~ = isActive then
local unloading = object.isActive and not isActive

if unloading then
if self.isClient then
g_soundManager:playSample(spec.samples.unload)
end
end

object.isActive = isActive
setVisibility(object.node, object.isActive)
self:setPalletTensionBeltNodesDirty()
end
end
end
end
end

onLoad

Description

Called on loading

Definition

onLoad(table savegame)

Arguments

tablesavegamesavegame

Code

function Pallet:onLoad(savegame)
local spec = self.spec_pallet

spec.fillUnitIndex = self.xmlFile:getValue( "vehicle.pallet#fillUnitIndex" , 1 )
spec.node = self.xmlFile:getValue( "vehicle.pallet#node" , nil , self.components, self.i3dMappings)
if spec.node ~ = nil then
if not getHasClassId(spec.node, ClassIds.SHAPE) then
Logging.xmlWarning( self.xmlFile, "Pallet node must be a shape in 'vehicle.pallet#node'" )
spec.node = nil
end
end

spec.nodes = { spec.node }
spec.tensionBeltNodes = { spec.node }

spec.linkNodes = self.xmlFile:getValue( "vehicle.pallet#linkNode" , nil , self.components, self.i3dMappings, true )
if #spec.linkNodes > 0 then
spec.filename = self.xmlFile:getValue( "vehicle.pallet#filename" , "$data/objects/pallets/shared/euroPallet/euroPallet.i3d" , self.baseDirectory)
if spec.filename ~ = nil then
spec.sharedLoadRequestId = self:loadSubSharedI3DFile(spec.filename, true , true , self.onPalletI3DFileLoaded, self )
end
end

spec.textures = { }
for _, key in self.xmlFile:iterator( "vehicle.pallet.texture" ) do
local texture = { }
texture.diffuse = self.xmlFile:getValue(key .. "#diffuse" , nil , self.baseDirectory)
if texture.diffuse ~ = nil then
table.insert(spec.textures, texture)
end
end

if savegame ~ = nil then
spec.palletAge = savegame.xmlFile:getValue(savegame.key .. ".pallet#age" )
end

if spec.palletAge = = nil then
if self.propertyState ~ = VehiclePropertyState.SHOP_CONFIG then
spec.palletAge = math.random()
else
spec.palletAge = 0
end
end

spec.contents = { }
for _, contentKey in self.xmlFile:iterator( "vehicle.pallet.content" ) do
local content = { }
content.objects = { }
content.fillUnitIndex = self.xmlFile:getValue(contentKey .. "#fillUnitIndex" , spec.fillUnitIndex)

for index, key in self.xmlFile:iterator(contentKey .. ".object" ) do
local object = { }
object.node = self.xmlFile:getValue(key .. "#node" , nil , self.components, self.i3dMappings)
if object.node ~ = nil then
object.useAsTensionBeltMesh = self.xmlFile:getValue(key .. "#useAsTensionBeltMesh" , true )

if object.useAsTensionBeltMesh then
local tensionBeltNode = self.xmlFile:getValue(key .. "#tensionBeltNode" , nil , self.components, self.i3dMappings)

if tensionBeltNode ~ = nil then
if getShapeIsCPUMesh(tensionBeltNode) then
object.tensionBeltNode = tensionBeltNode
else
Logging.xmlWarning( self.xmlFile, "Shape '%s' defined in '%s' does not have 'CPU-Mesh' flag set.Ignoring this node" , getName(tensionBeltNode), key .. "#tensionBeltNode" )
end
else
-- node is default tension belt node if none is defined, check as well
if not getShapeIsCPUMesh(object.node) then
Logging.xmlWarning( self.xmlFile, "Shape '%s' defined in '%s' does not have 'CPU-Mesh' flag set.Either set the flag on the mesh or add a custom tension belt node using xml attribute '#tensionBeltNode'" , getName(object.node), key .. "#node" )
end
end
end

object.isActive = false
setVisibility(object.node, object.isActive)

table.insert(content.objects, object)
end
end

if #content.objects > 0 then
content.numObjects = #content.objects
table.insert(spec.contents, content)
end
end

spec.straps = { }
for _, key in self.xmlFile:iterator( "vehicle.pallet.straps.strap" ) do
local strap = { }
strap.startNode = self.xmlFile:getValue(key .. "#startNode" , nil , self.components, self.i3dMappings)
strap.endNode = self.xmlFile:getValue(key .. "#endNode" , nil , self.components, self.i3dMappings)
if strap.startNode ~ = nil and strap.endNode ~ = nil then
local tensionBeltType = self.xmlFile:getValue(key .. "#tensionBeltType" , "basic" )
strap.beltData = g_tensionBeltManager:getBeltData(tensionBeltType)
if strap.beltData ~ = nil then
strap.intersectionNodes = { }
for _, intersectionKey in self.xmlFile:iterator(key .. ".intersectionNode" ) do
local intersectionNode = self.xmlFile:getValue(intersectionKey .. "#node" , nil , self.components, self.i3dMappings)
if intersectionNode ~ = nil then
table.insert(strap.intersectionNodes, intersectionNode)
end
end

table.insert(spec.straps, strap)
else
Logging.xmlWarning( self.xmlFile, "Invalid tension belt type '%s' defined for strap" , tensionBeltType)
end
else
Logging.xmlWarning( self.xmlFile, "Invalid strap definition.Both start and end node must be defined" )
end
end
spec.strapMeshes = { }

spec.tensionBeltMeshes = { }
spec.tensionBeltMeshesDirty = true

if self.isClient then
spec.samples = { }
spec.samples.unload = g_soundManager:loadSampleFromXML( self.xmlFile, "vehicle.pallet.sounds" , "unload" , self.baseDirectory, self.components, 1 , AudioGroup.VEHICLE, self.i3dMappings, self )
end

g_currentMission.slotSystem:addLimitedObject(SlotSystem.LIMITED_OBJECT_PALLET, self )

-- allow some movement of the joint in Y, otherwise the pallet will be pushed down to the fork permanently
-- this can cause issues in various situations and make the pallet and fork flying away(issue #50871)
-- joint is not fully free otherwise the pallet can fly away when the fork is raised fast
self.dynamicMountForkXLimit = 0.01
self.dynamicMountForkYLimit = 0.10
end

onPostLoad

Description

Called on post load

Definition

onPostLoad()

Arguments

anysavegame

Code

function Pallet:onPostLoad(savegame)
local spec = self.spec_pallet

if #spec.nodes > 0 then
for _, node in ipairs(spec.nodes) do
local materialId = getMaterial(node, 0 )
local numTextures = #spec.textures
if numTextures > 0 then
if numTextures = = 1 then
materialId = setMaterialDiffuseMapFromFile(materialId, spec.textures[ 1 ].diffuse, true , true , false )
else
local alpha = spec.palletAge * (numTextures - 1 )
local index1 = math.floor(alpha)
local index2 = math.ceil(alpha)

materialId = setMaterialDiffuseMapFromFile(materialId, spec.textures[index1 + 1 ].diffuse, true , true , false )
materialId = setMaterialCustomMapFromFile(materialId, spec.textures[index2 + 1 ].diffuse, "mCustomDiffuse" , true , true , false )
materialId = setMaterialCustomParameter(materialId, "blendScale" , alpha - index1, 0 , 0 , 0 , false )
end

setMaterial(node, materialId, 0 )
end
end
end
end

onPreLoad

Description

Definition

onPreLoad()

Arguments

anysavegame

Code

function Pallet:onPreLoad(savegame)
self.isPallet = true
self.allowsInput = false
end

prerequisitesPresent

Description

Checks if all prerequisite specializations are loaded

Definition

prerequisitesPresent(table specializations)

Arguments

tablespecializationsspecializations

Return Values

tablehasPrerequisitetrue if all prerequisite specializations are loaded

Code

function Pallet.prerequisitesPresent(specializations)
return true
end

registerEventListeners

Description

Definition

registerEventListeners()

Arguments

anyvehicleType

Code

function Pallet.registerEventListeners(vehicleType)
SpecializationUtil.registerEventListener(vehicleType, "onPreLoad" , Pallet )
SpecializationUtil.registerEventListener(vehicleType, "onLoad" , Pallet )
SpecializationUtil.registerEventListener(vehicleType, "onPostLoad" , Pallet )
SpecializationUtil.registerEventListener(vehicleType, "onDelete" , Pallet )
SpecializationUtil.registerEventListener(vehicleType, "onFillUnitFillLevelChanged" , Pallet )
end

registerFunctions

Description

Definition

registerFunctions()

Arguments

anyvehicleType

Code

function Pallet.registerFunctions(vehicleType)
SpecializationUtil.registerFunction(vehicleType, "onPalletI3DFileLoaded" , Pallet.onPalletI3DFileLoaded)
SpecializationUtil.registerFunction(vehicleType, "getInfoBoxTitle" , Pallet.getInfoBoxTitle)
SpecializationUtil.registerFunction(vehicleType, "collectPalletTensionBeltNodes" , Pallet.collectPalletTensionBeltNodes)
SpecializationUtil.registerFunction(vehicleType, "setPalletTensionBeltNodesDirty" , Pallet.setPalletTensionBeltNodesDirty)
SpecializationUtil.registerFunction(vehicleType, "updatePalletStraps" , Pallet.updatePalletStraps)
end

registerOverwrittenFunctions

Description

Definition

registerOverwrittenFunctions()

Arguments

anyvehicleType

Code

function Pallet.registerOverwrittenFunctions(vehicleType)
SpecializationUtil.registerOverwrittenFunction(vehicleType, "getMeshNodes" , Pallet.getMeshNodes)
SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadComponentFromXML" , Pallet.loadComponentFromXML)
SpecializationUtil.registerOverwrittenFunction(vehicleType, "getAutoLoadSize" , Pallet.getAutoLoadSize)
SpecializationUtil.registerOverwrittenFunction(vehicleType, "autoLoad" , Pallet.autoLoad)
SpecializationUtil.registerOverwrittenFunction(vehicleType, "getShowInVehiclesOverview" , Pallet.getShowInVehiclesOverview)
SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeReset" , Pallet.getCanBeReset)
SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsMapHotspotVisible" , Pallet.getIsMapHotspotVisible)
SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillUnitEmptyOnReset" , Pallet.getFillUnitEmptyOnReset)
end

saveToXMLFile

Description

Definition

saveToXMLFile()

Arguments

anyxmlFile
anykey
anyusedModNames

Code

function Pallet:saveToXMLFile(xmlFile, key, usedModNames)
local spec = self.spec_pallet
xmlFile:setValue(key .. "#age" , spec.palletAge)
end

setPalletTensionBeltNodesDirty

Description

Definition

setPalletTensionBeltNodesDirty()

Code

function Pallet:setPalletTensionBeltNodesDirty()
self.spec_pallet.tensionBeltMeshesDirty = true
end