Page 1 of 2

altar clickable from 1 direction only

Posted: Sun May 31, 2015 10:02 pm
by Granamir
Hi everyone,
for my flying bookshelf i had to use altar (click max distance = 1) but now, that it's almost complete, i realized that i can reach it from his back side too, turning it in a complete sh...
So, anyone has an easy way to make it clickable only when party is in front of it?
My actual solution (still an idea) is to check party position and enable clickable component only when champions are in front of bookshelf, but it's a bit tricky, i'd prefer a cleaner solution.
Any help?!
Ty

Re: altar clickable from 1 direction only

Posted: Sun May 31, 2015 10:52 pm
by minmay
frontFacing = true on the ClickableComponent will only allow it to be clicked if the party is facing the same direction as the object.

Re: altar clickable from 1 direction only

Posted: Mon Jun 01, 2015 11:34 am
by Granamir
:-) TY minmay, u saved 2 weeks of my work

...but unfortunatelly it works for taking items, if i try to put them nothing happens (except i throw item)

Re: altar clickable from 1 direction only

Posted: Mon Jun 01, 2015 1:41 pm
by Isaac
Granamir wrote::-) TY minmay, u saved 2 weeks of my work

...but unfortunatelly it works for taking items, if i try to put them nothing happens (except i throw item)
Do you have it placed on the floor, or on the wall?

Re: altar clickable from 1 direction only

Posted: Mon Jun 01, 2015 2:04 pm
by Granamir
floor

Re: altar clickable from 1 direction only

Posted: Mon Jun 01, 2015 6:04 pm
by minmay
I'm pretty sure ClickableComponent won't change taking items at all - items in surfaces are picked up normally (since they're on the map) except that the player must be on the same square as the surface. ClickableComponent is for adding items to the surface.
It's really hard to tell what you're actually trying to do, I think you'd have to share your model at this point.

Re: altar clickable from 1 direction only

Posted: Mon Jun 01, 2015 6:38 pm
by Granamir
Sure.
Here is my files: https://onedrive.live.com/redir?resid=d ... file%2czip
Unzip, put models in mod_assets/models and objects.lua file in mod_assets\scripts (or rename it if u don't want to overwrite your file).

btw i made a bookshelf with castle walls, with 2 surfaces and clickable components, so i can't stay in same square of object, that's why i used maxDistance = 1, but this makes clickable components reachable from all 4 sides, so i added frontFacing = true but seems clickable is not more reachable from any position.
With model and code it would be more clear i guess.

if u just want to see my code without downloading anything here it is:

Code: Select all

defineObject{
	name = "prova_alcova",
	components = {
		{
			class = "Model",
			model = "mod_assets/models/flying_bookshelf.fbx",
			offset = vec(0, 4, 0),
			staticShadow = true,
		},
		--[[
		{
			class = "Occluder",
			offset = vec(0, 4, 0),
			model = "mod_assets/models/flying_bookshelf_occluder.fbx",
		},
		]]
		{
			class = "Particle",
			particleSystem = "mine_support_ceiling_lantern",
			offset = vec(0, -0.2, 0),
		},
		{
			class = "Light",
			offset = vec(0, -0.2, 0),
			range = 8,
			color = vec(1.1, 0.7, 0.4),
			brightness = 10,
			castShadow = true,
			staticShadows = true,
		},
		{
			class = "Obstacle",
			hitSound = "impact_blunt",
		},
		{
			class = "ItemConstrainBox",
			name = "cbox1",
			size = vec(3.7, 4, 3.7),
			offset = vec(0, 2, 0),
			-- debugDraw = true,
		},
		{
			class = "ProjectileCollider",
			size = vec(3.4, 4, 3.4),
			offset = vec(0, 2, 0),
			-- debugDraw = true,
		},
		{
			class = "Surface",
			name = "alcoveSurface",
			offset = vec(0, 0.82, 1.3),
			size = vec(1.3, 0.65),
			-- debugDraw = true,
			onAcceptItem = function(self,item)
				local surf = GameMode.tempSurface
				GameMode.tempSurface = nil
				if surf == 2 then return false end 
			end,
		},
		{
			class = "Clickable",
			name = "alcoveClickable",
			offset = vec(0, 0.82+0.4, 1.3),
			size = vec(1.3, 0.8, 0.65),
			maxDistance = 1,
			--frontFacing = true,
			-- debugDraw = true,
			onClick = function(self)
				if getMouseItem() then GameMode.tempSurface = 1 end
			end,
		},
		
		{
			class = "Surface",
			name = "bookshelfSurface",
			offset = vec(-1.2, 0.55, 0.75),
			size = vec(0.4, 0.3),
			-- debugDraw = true,
			onAcceptItem = function(self,item)
				local surf = GameMode.tempSurface
				GameMode.tempSurface = nil
				if surf == 1 then return false end 
			end,
		},
		{
			class = "Clickable",
			name = "bookshelfClickable",
			offset = vec(-1.2, 0.5+0.3, 0.75),
			size = vec(0.4, 0.5, 0.3),
			maxDistance = 1,
			frontFacing = true,
			-- debugDraw = true,
			onClick = function(self)
				if getMouseItem() then GameMode.tempSurface = 2 end
			end,
		},
		{
			class = "Timer",
			name = "rotationTimer",
			timerInterval = 0.0001,
			onActivate = function(self)
				local deltaAngle = 2.5
				local angleIncrement = math.rad(deltaAngle)
				local bookshelfPosition = self.go:getWorldPosition()
				local bookshelfRotation = self.go:getWorldRotation()
				local bookshelfAngle
				
				----- checking angle for bookshelf
				if bookshelfRotation.z.x >= 0 then
					bookshelfAngle = math.acos(bookshelfRotation.x.x)
				elseif bookshelfRotation.z.x <= 0 then
					bookshelfAngle = (math.pi-math.acos(bookshelfRotation.x.x)) + math.pi
				end
				
				----- calculating new matrix values
				bookshelfRotation.x.x = math.cos(bookshelfAngle-angleIncrement)
				bookshelfRotation.x.z = -math.sin(bookshelfAngle-angleIncrement)
				bookshelfRotation.z.x = math.sin(bookshelfAngle-angleIncrement)
				bookshelfRotation.z.z = math.cos(bookshelfAngle-angleIncrement)
				
				----- setting new matrix
				self.go:setWorldRotation(bookshelfRotation)
				
				----- items in alcove
				for _, i in self.go.alcoveSurface:contents() do
					local itemRotation = i.go:getWorldRotation()
					local itemRotationAngle
					
					----- checking rotation angle for items in alcove
					if itemRotation.z.x >= 0 then
						itemRotationAngle = math.acos(itemRotation.x.x)
					elseif itemRotation.z.x <= 0 then
						itemRotationAngle = (math.pi-math.acos(itemRotation.x.x)) + math.pi
					end
					
					----- calculating new matrix values
					itemRotation.x.x = math.cos(itemRotationAngle-angleIncrement)
					itemRotation.x.z = -math.sin(itemRotationAngle-angleIncrement)
					itemRotation.z.x = math.sin(itemRotationAngle-angleIncrement)
					itemRotation.z.z = math.cos(itemRotationAngle-angleIncrement)
					
					----- setting new matrix
					i.go:setWorldRotation(itemRotation)
					
					----- checking items revolution
					local itemPosition = i.go:getWorldPosition()
					local deltaY = itemPosition[3]-bookshelfPosition[3]
					local deltaX = itemPosition[1]-bookshelfPosition[1]
					local revolutionRadius = math.sqrt(math.abs(deltaX)^2 + math.abs(deltaY)^2) -- distance between items and bookshelf center
					local itemRevolutionAngle = (math.atan2( deltaY, deltaX) * 180 / math.pi)*-1
							
					----- setting new items position
					i.go:setWorldPosition(revolutionRadius*math.cos(math.rad(-itemRevolutionAngle+deltaAngle))+bookshelfPosition[1], 0.82, revolutionRadius*math.sin(math.rad(-itemRevolutionAngle+deltaAngle))+bookshelfPosition[3], 0)
					
				end
				
				----- items in bookshelf
				for _, i in self.go.bookshelfSurface:contents() do
					local itemRotation = i.go:getWorldRotation()
					local itemRotationAngle
					
					----- checking rotation angle for items in bookshelf
					if itemRotation.z.x >= 0 then
						itemRotationAngle = math.acos(itemRotation.x.x)
					elseif itemRotation.z.x <= 0 then
						itemRotationAngle = (math.pi-math.acos(itemRotation.x.x)) + math.pi
					end
					
					----- calculating new matrix values
					itemRotation.x.x = math.cos(itemRotationAngle-angleIncrement)
					itemRotation.x.z = -math.sin(itemRotationAngle-angleIncrement)
					itemRotation.z.x = math.sin(itemRotationAngle-angleIncrement)
					itemRotation.z.z = math.cos(itemRotationAngle-angleIncrement)
					
					----- setting new matrix
					i.go:setWorldRotation(itemRotation)
					
					----- checking items revolution
					local itemPosition = i.go:getWorldPosition()
					local deltaY = itemPosition[3]-bookshelfPosition[3]
					local deltaX = itemPosition[1]-bookshelfPosition[1]
					local revolutionRadius = math.sqrt(math.abs(deltaX)^2 + math.abs(deltaY)^2) -- distance between items and bookshelf center
					local itemRevolutionAngle = (math.atan2( deltaY, deltaX) * 180 / math.pi)*-1
							
					----- setting new items position
					i.go:setWorldPosition(revolutionRadius*math.cos(math.rad(-itemRevolutionAngle+deltaAngle))+bookshelfPosition[1], 0.55, revolutionRadius*math.sin(math.rad(-itemRevolutionAngle+deltaAngle))+bookshelfPosition[3], 0)
					
				end
				
				local cleanAngle = math.floor(math.deg(bookshelfAngle))
				if cleanAngle == 0 or cleanAngle == 90 or cleanAngle == 180 or cleanAngle == 270 or cleanAngle == 360 then
					playSoundAt("bookshelf_rotation", self.go.level, self.go.x, self.go.y)
				end
				
			end,
		},
		{
			class = "Controller",
			onStart = function(self)
				self.go.rotationTimer:start()
			end,
			onStop = function(self)
				self.go.rotationTimer:stop()
			end,
			onPause = function(self)
				self.go.rotationTimer:pause()
			end,
		},
		
	},
	placement = "floor",
	editorIcon = 276,
	tags = { "obstacle" },
	automapTile = "wall"
}

Re: altar clickable from 1 direction only

Posted: Mon Jun 01, 2015 6:46 pm
by minmay
Okay, I see what you're trying to do now. Since you already have the onAcceptItem hooks, the easiest way to fix this issue would be to just return false from both if the party isn't facing the correct direction.
The throwing behaviour is inherent to obstacles. The only things that prevent throwing are solid tiles and secret doors. You can always throw items directly at adjacent obstacles, and always will throw the item if it doesn't go into a surface.

Re: altar clickable from 1 direction only

Posted: Tue Jun 02, 2015 12:17 pm
by Granamir
Ok working on it. TY minmay.
Btw why frontFacing doesn't works?

Re: altar clickable from 1 direction only

Posted: Tue Jun 02, 2015 5:54 pm
by minmay
It does work, it does exactly what I told you it does. But it won't help for your case because you have two clickable components that you want to be clickable from different directions.