Placing Blocks (Voxels?)

MordicantMordicant Posts: 8
edited February 2015 in Code
Hi,

I am new to the modding world and have some ideas for a mod, but need some help understanding some of the calls. I am trying to figure out what is used by the player to place a block/material (Or whatever the correct term is). I found in the localplayer.lua where input events are hooked (made it so when the player moved forward it spawned a goat... so many goats), but I can't find the call for placing a material. What calls would I need to make to the API?

Eventually, I want to make it so a creature can replace blocks with a new material. If I am reading the code correctly I would need to do a NKTraceWorld to get the material in front of the creature but then how do I go about destroying and replace with new material?

Thanks.

Comments

  • Auti0Auti0 Posts: 277
    if you look in BasePlaceableMaterial.lua there are two functions called PlaceBlock() and RemoveBlock(). This contains all the functionality to add a block to an area so you can base your logic off of that.
    function BasePlaceableMaterial:PlaceBlock()
    	local terrain = Eternus.Terrain
    	local gameState = Eternus.GameStatePlaying
    	
    	local blockSize = gameState:NKGetBlockSize()
    	blockSize = blockSize + vec3.new(1,1,1)
    	
    	tpp = physics:NKTruncatedPositionPlacement()
    	
    	local cellID = tpp:div_scalar(DATASIZE)
    	
    	blockInCell = tpp:mod(DATASIZE) - vec3.new(1,1,1)
    	
    	local chunk = terrain:NKGetVoxelChunk(blockSize, blockInCell, cellID)
    	
    	local x = blockSize:x() - 1
    	local y = blockSize:y() - 1
    	local z = blockSize:z() - 1
    	
    	for i = 0, x, 1 do
    		for j = 0, y, 1 do
    			for k = 0, z, 1 do
    				--Grab the voxel in question.
    				voxel = chunk:getVoxel(i,j,k)
    				--voxel:setIsModified(true)
    				
    				--If we are NOT on the beginning edge of the cube
    				if i ~= 0 and j ~= 0 and k ~= 0 then
    					--modify the material
    					voxel:setMaterial(self.m_materialID)
    				end
    				
    				--If we ARE on the beginning or ending edge of the cube.
    				if( i == 0 or j == 0 or k == 0 or i == (x+1) or j == (y+1) or k == (z+1)) then
    					local rX = self.applyRandomRoughness(math.random(), 0.0)
    					local rY = self.applyRandomRoughness(math.random(), 0.0)
    					local rZ = self.applyRandomRoughness(math.random(), 0.0)
    					
    					voxel:setDeltas(rX, rY, rZ)
    				else
    					--Center!
    					v = 0x7f
    					voxel:setDeltas(v,v,v)
    				end
    			end
    		end
    	end
    	
    	--Apply changes to this block.
    	terrain:NKApplyFullVoxelChunk(chunk)
    end
    

    You'll need to adjust some things to get your desired result of simply replacing the current material. You will also need to specify the new material ID.

    Hope this helps!
  • Awesome! I will look into this tonight.
  • Okay,

    Starting to make progress. Was able to duplicate the code and tie it to the MoveForward on localplayer.lua. Used my own material too!

    Here is the code if anyone is interested. For the more knowledgeable two quick questions.

    function LocalPlayer:MoveForward(down)
    	if (not self.m_dying and not self.m_isSleeping) then
    		lastVec = self:NKGetPosition()
    		
    				
    		self:NKGetCharacterController():MoveForward()
    		Eternus.GameState:InterruptCrafting()
    		
    		local matObj = Eternus.MaterialSystem:NKGetMaterialIDByName("myMaterial")
    		local placeObj = Eternus.GameObjectSystem:NKGetPlaceableMaterialByID(matObj)
    		
    		self:TrailBlock(lastVec, placeObj)
    		
    		
    	end
    	--end			
    end
    
    function LocalPlayer:TrailBlock(lastPosition, block)
    	local DATASIZE = 32
    	local terrain = Eternus.Terrain
    	local gameState = Eternus.GameStatePlaying
    	
    	local blockSize = gameState:NKGetBlockSize()
    	
    	lastPosition = vec3.new(lastPosition:x() - 1, lastPosition:y() , lastPosition:z() - 1)
    	
    	blockSize = blockSize + vec3.new(1,1,1)
    	
    	local cellID = lastPosition:div_scalar(DATASIZE)
    	blockInCell = lastPosition:mod(DATASIZE) - vec3.new(1,1,1)
    	
    	local chunk = terrain:NKGetVoxelChunk(blockSize,blockInCell, cellID)
    	
    	local x = blockSize:x() - 1
    	local y = blockSize:y() - 1
    	local z = blockSize:z() - 1
    	
    	for i = 0, x, 1 do
    		for j = 0, y, 1 do
    			for k = 0, z, 1 do
    				voxel = chunk:getVoxel(i,j,k)
    				
    				if i ~= 0 and j ~= 0 and k ~= 0 then 
    					voxel:setMaterial(Eternus.MaterialSystem:NKGetMaterialIDByName("myMaterial"))
    				end
    				
    				if( i == 0 or j == 0 or k == 0 or i == (x+1) or j == (y+1) or k == (z+1)) then
    					local rX = self:applyRandomRoughness(math.random(), 0,0)
    					local rY = self:applyRandomRoughness(math.random(), 0,0)
    					local rZ = self:applyRandomRoughness(math.random(), 0,0)
    					
    					voxel:setDeltas(rX,rY,rZ)
    				else
    					v = 0x7f
    					voxel:setDeltas(v,v,v)
    				end	
    			end
    		end
    	end
    	
    	terrain:NKApplyFullVoxelChunk(chunk)
    	
    end
    
    function LocalPlayer:applyRandomRoughness(x, roughness)
    	x = x * roughness
    	x = x * 0.5
    	x = x + 0.5
    	x = x * 255.0
    	return x
    end
    
    
    

    Quick Questions:
    I tried to call the applyRandomRoughness from the BasePlaceableMaterial by block:applyRandomRoughness() and that didn't work so I had to add it to the localplayer. What did i do wrong or is that even possible.

    Also, at voxel:setMaterial(Eternus.MaterialSystem:NKGetMaterialIDByName("myMaterial")) I tried to use a block:NKGetPlaceableMaterial():NKGetMaterialRepID() call and it crashed. Again, why didn't that work. I thought it was a GameObject.

    Lastily, here's a video of the code in action!

    http://youtu.be/nfh964VNt_U
  • This is extremely decent and OK post....you shook posting it....thanks a great deal for posting it....!! :ugeek: :roll: :geek:
    Johni
Sign In or Register to comment.