Code: Select all
defineObject{
baseObject = "base_item",
name = "third_eye",
components = {
{
class = "Model",
model = "mod_assets/MinAssets/items/tools/third_eye/third_eye.fbx",
},
{
class = "Item",
weight = 0.2,
uiName = "The Third Eye",
description = [[This emerald seems to emit its own light.]],
gameEffect = "Detects secret buttons",
gfxAtlas = "mod_assets/MinAssets/items/icons.dds",
gfxIndex = 30,
traits = {"tool"},
onEquipItem = function(self, champion, slot)
party.thirdeyetimer:enable()
end,
onUnequipItem = function(self, champion, slot)
-- Don't disable the timer if the party still has a second third eye in open inventory
for c = 1,4 do
local champ = party.party:getChampion(c)
if champ:getEnabled() then
for _,itm in champ:carriedItems() do
if itm and itm.go.name == self.go.name and itm ~= self then return end
end
end
end
party.thirdeyetimer:disable()
end,
},
{
class = "Model",
name = "beam1",
model = "mod_assets/MinAssets/items/tools/third_eye/item_beam.fbx",
offset = vec(0, 0.05, 0),
},
{
class = "Model",
name = "beam2",
model = "mod_assets/MinAssets/items/tools/third_eye/item_beam.fbx",
offset = vec(0, 0.05, 0),
},
{
class = "Model",
name = "beam3",
model = "mod_assets/MinAssets/items/tools/third_eye/item_beam.fbx",
offset = vec(0, 0.05, 0),
},
{
class = "Model",
name = "beam4",
model = "mod_assets/MinAssets/items/tools/third_eye/item_beam.fbx",
offset = vec(0, 0.05, 0),
},
{
class = "Model",
name = "beam5",
model = "mod_assets/MinAssets/items/tools/third_eye/item_beam.fbx",
offset = vec(0, 0.05, 0),
},
{
class = "Model",
name = "beam6",
model = "mod_assets/MinAssets/items/tools/third_eye/item_beam.fbx",
offset = vec(0, 0.05, 0),
},
{
class = "Light",
offset = vec(0, 0.1, 0),
range = 5,
color = vec(0.7, 1, 0.3),
brightness = 10,
castShadow = false,
fillLight = true,
onUpdate = function(self)
local time = Time.currentTime()
self.go.beam1:setRotationAngles(time*-66.7332%360,time*30.731%360,time*-52.07%360)
self.go.beam2:setRotationAngles(time*74.04%360,time*-70.75%360,time*43.4%360)
self.go.beam3:setRotationAngles(time*87.74%360,time*34.15%360,time*-76.038%360)
self.go.beam4:setRotationAngles(180+time*-66.7332%360,180+time*30.731%360,180+time*-52.07%360)
self.go.beam5:setRotationAngles(180+time*74.04%360,180+time*-70.75%360,180+time*43.4%360)
self.go.beam6:setRotationAngles(180+time*87.74%360,180+time*34.15%360,180+time*-76.038%360)
end,
},
}
}
defineObject{
name = "thirdeye",
components = {
{
class = "Light",
type = "spot",
spotAngle = 4,
spotSharpness = 0.01,
rotation = vec(0, 0, 0),
range = 15,
color = vec(0.7, 1, 0.3),
brightness = 30,
castShadow = false,
onUpdate = function(self)
if party.party:isCarrying("third_eye") then
-- Keep at party's position
local wpos = party:getWorldPosition()
wpos[2] = wpos[2]+2
self.go:setWorldPosition(wpos)
-- Find the closest button on this level
local minDist = party.thirdeyescript.MAX_DISTANCE
local closestButton = nil
for i,button in ipairs(party.thirdeyescript.getSecretButtons(party.level)) do
local e = findEntity(button)
if e and not (e.facing == 0 and e.y > party.y or -- Only check buttons that the party could POTENTIALLY have line of sight to
e.facing == 1 and e.x < party.x or
e.facing == 2 and e.y < party.y or
e.facing == 3 and e.x > party.x) then
-- We are not concerned about the offset here
local ewpos = e:getWorldPosition()
local dist = ((wpos[1]-ewpos[1])^2+(wpos[2]-ewpos[2])^2+(wpos[3]-ewpos[3])^2)^(1/2)
if dist <= minDist then
minDist = dist
closestButton = e
end
end
end
-- Point at the closest button, or turn off if no buttons
if closestButton then
local posb = closestButton:getWorldPosition()
local off = party.thirdeyescript.getButtonOffset(closestButton.name)
posb[1] = posb[1]+(closestButton.facing == 0 and off[1] or closestButton.facing == 1 and off[3] or closestButton.facing == 2 and -off[1] or -off[3])
posb[2] = posb[2]+off[2]
posb[3] = posb[3]+(closestButton.facing == 0 and off[3] or closestButton.facing == 1 and -off[1] or closestButton.facing == 2 and -off[3] or off[1])
local xDistance = posb[1] - wpos[1]
local zDistance = posb[3] - wpos[3]
local yDistance = posb[2] - wpos[2]
local xzDistance = math.sqrt(xDistance*xDistance+zDistance*zDistance)
local pitch = -math.pi/2
local yaw = math.pi/2
if xzDistance ~= 0 then
pitch = math.atan(yDistance/xzDistance)
elseif yDistance > 0 then
pitch = math.pi/2
end
if zDistance > 0 then
yaw = -math.atan(xDistance/zDistance)
elseif zDistance ~= 0 then
yaw = -math.atan(xDistance/zDistance)+math.pi
elseif xDistance > 0 then
yaw = -math.pi/2
end
self:setRange(minDist+2.2)
self:setBrightness((party.thirdeyescript.MAX_DISTANCE-minDist)/party.thirdeyescript.MAX_DISTANCE*party.thirdeyescript.BRIGHTNESS)
--self:setRotationAngles(math.deg(pitch),math.deg(yaw),0)
-- Rotate entire object for convenience
self.go:setWorldRotationAngles(math.deg(pitch),math.deg(yaw),0)
if not thirdEyeBeam then spawn("thirdeye_beam",self.go.level,self.go.x,self.go.y,0,self.go.elevation,"thirdEyeBeam") end
thirdEyeBeam:setPosition(self.go.x,self.go.y,0,self.go.elevation,self.go.level)
thirdEyeBeam:setWorldPosition(wpos)
-- Now scale the beam's z so that the beam is the right length
local mat = self.go:getWorldRotation()
local zscale = minDist/3 -- model is 3m long
-- approximate lesser scaling factor for x and y, so that the beam
-- is close to the right width. Making it the exact right width actually
-- looks bad on the edges
local xyscale = zscale * 0.3
for i=1,4 do
mat.z[i] = mat.z[i] * zscale
mat.x[i] = mat.x[i] * xyscale
mat.y[i] = mat.y[i] * xyscale
end
thirdEyeBeam:setWorldRotation(mat)
thirdEyeBeam.model:enable()
else
self:setRange(0)
if thirdEyeBeam then thirdEyeBeam.model:disable() end
end
else
self.go:destroyDelayed()
if thirdEyeBeam then thirdEyeBeam:destroy() end
end
end,
},
},
placement = "floor",
}
defineObject{
name = "thirdeye_beam",
components = {
{
class = "Model",
model = "mod_assets/MinAssets/items/tools/third_eye/beam.fbx",
},
},
placement = "floor",
}
--[[defineParticleSystem{
name = "thirdeye",
emitters = {
-- fog1
{
emissionRate = 256,
emissionTime = 0,
maxParticles = 1000,
boxMin = {-0.01, -0.01, 0},
boxMax = {0.01, 0.01, 6},
sprayAngle = {0,0},
velocity = {0.01,0.01},
objectSpace = true,
texture = "assets/textures/particles/dust_particle_dif.tga",
lifetime = {0.5,2},
color0 = { 0, 1, 0},
opacity = 2,
fadeIn = 0.5,
fadeOut = 2,
size = {0.04, 0.08},
gravity = {0,0,0},
airResistance = 0.1,
rotationSpeed = 0.1,
blendMode = "Additive",
},
}
}]]
defineMaterial{
name = "thirdeye_beam",
diffuseMap = "mod_assets/MinAssets/items/tools/third_eye/beam.tga",
doubleSided = true,
lighting = false,
alphaTest = false,
blendMode = "Additive",
textureAddressMode = "Clamp",
glossiness = 0,
depthBias = 0,
onUpdate = function(self, time)
-- fade out at long distance
if thirdEyeLight then
self:setTexcoordScaleOffset(1, 1, 0, math.min(0,-0.5+(thirdEyeLight.light:getBrightness()/party.thirdeyescript.BRIGHTNESS)^(1/2)))
end
end,
}
defineMaterial{
name = "thirdeye_beam_item",
diffuseMap = "mod_assets/MinAssets/items/tools/third_eye/beam.tga",
doubleSided = true,
lighting = false,
alphaTest = false,
blendMode = "Additive",
textureAddressMode = "Clamp",
glossiness = 0,
depthBias = 0,
}
defineMaterial{
name = "third_eye",
diffuseMap = "mod_assets/MinAssets/items/tools/third_eye/third_eye_dif.tga",
specularMap = "mod_assets/MinAssets/items/tools/third_eye/third_eye_dif.tga",
normalMap = "assets/textures/env/healing_crystal_normal.tga",
doubleSided = false,
lighting = false,
ambientOcclusion = false,
alphaTest = false,
blendMode = "Opaque",
textureAddressMode = "Wrap",
glossiness = 20,
depthBias = 0,
-- custom shader
shader = "crystal",
shadeTex = "mod_assets/MinAssets/items/tools/third_eye/third_eye_dif.tga",
shadeTexAngle = 0,
crystalIntensity = 2,
onUpdate = function(self, time)
self:setParam("shadeTexAngle", time*0.8)
end,
}
defineObject{
name = "party",
baseObject = "party",
components = {
{
class = "Timer",
name = "thirdeyetimer",
timerInterval = 0.00001,
onActivate = function(self)
if not findEntity("thirdEyeLight") then
spawn("thirdeye",self.go.level,self.go.x,self.go.y,self.go.facing,self.go.elevation,"thirdEyeLight")
end
if thirdEyeLight and thirdEyeLight.level ~= party.level then
thirdEyeLight:setPosition(party.x,party.y,0,party.elevation,party.level)
end
end,
enabled = false,
},
{
class = "Script",
name = "thirdeyescript",
source = [[
-- The maximum allowed distance from the party for a detected button, in meters.
MAX_DISTANCE = 15
-- Brightness of the light if it is right on top of the button. Will decrease
-- linearly as distance from the button increases, ending at 0 brightness (light
-- is removed) at MAX_DISTANCE.
BRIGHTNESS = 64
do
-- offsets used for multiple objects
local g1dsblarge = {0,1.86697,0.06029}
local g1dsbsmall = {0.312,1.91593,-0.005}
local g1psbsmall = {0,1.70663,-0.071}
local g1tsblarge = {0.40781,1.73694,0.025}
local g1tsbsmall = {-0.08450,1.97,-0.005}
local g1tsbtiny = {-0.13955,1.39222,-0.005}
-- permanent variable
buttons = {
dungeon_secret_button_small = {-0.355,1.03484,0},
dungeon_secret_button_large = {-0.409,1.375,-0.0157},
mine_support_secret_button = {-0.5084,1.75266,-0.05846},
tomb_secret_button_small = {-0.371,1.30075,-0.002},
forest_ruins_secret_button_small = {0.47917,1.02165,-0.14998},
forest_ruins_secret_button_big = {0.05694,1.62365,-0.17098},
dm_secret_button_big = {0,1.9895,-0.03613},
dm_secret_button_midbottom = {0.00287,0.92838,-0.06473},
dm_secret_button_crack = {0.66989,0.7803,0.09607},
dm_secret_button_mini = {0.74954,2.11307,-0.05127},
g1_dungeon_secret_button_large = g1dsblarge,
g1_dungeon_secret_button_small = g1dsbsmall,
g1_deep_dungeon_secret_button_large = g1dsblarge,
g1_deep_dungeon_secret_button_small = g1dsbsmall,
g1_northern_dungeon_secret_button_large = g1dsblarge,
g1_northern_dungeon_secret_button_small = g1dsbsmall,
g1_prison_secret_button = g1psbsmall,
g1_solaris_prison_secret_button = g1psbsmall,
g1_temple_secret_button_large = g1tsblarge,
g1_temple_secret_button_small = g1tsbsmall,
g1_temple_secret_button_tiny = g1tsbtiny,
g1_dark_temple_secret_button_large = g1tsblarge,
g1_dark_temple_secret_button_small = g1tsbsmall,
g1_dark_temple_secret_button_tiny = g1tsbtiny,
g1_darkelf_temple_secret_button_large = g1tsblarge,
g1_darkelf_temple_secret_button_small = g1tsbsmall,
g1_darkelf_temple_secret_button_tiny = g1tsbtiny,
g1_deep_temple_secret_button_large = g1tsblarge,
g1_deep_temple_secret_button_small = g1tsbsmall,
g1_deep_temple_secret_button_tiny = g1tsbtiny,
g1_frozen_temple_secret_button_large = g1tsblarge,
g1_frozen_temple_secret_button_small = g1tsbsmall,
g1_frozen_temple_secret_button_tiny = g1tsbtiny,
g1_high_temple_secret_button_large = g1tsblarge,
g1_high_temple_secret_button_small = g1tsbsmall,
g1_high_temple_secret_button_tiny = g1tsbtiny,
g1_highelf_temple_secret_button_large = g1tsblarge,
g1_highelf_temple_secret_button_small = g1tsbsmall,
g1_highelf_temple_secret_button_tiny = g1tsbtiny,
g1_southern_temple_secret_button_large = g1tsblarge,
g1_southern_temple_secret_button_small = g1tsbsmall,
g1_southern_temple_secret_button_tiny = g1tsbtiny,
g1_mine_secret_button_large = {0.39,1.74,0},
g1_mine_secret_button_small = {-0.24,1.95,0},
g1_town_secret_button_large = g1dsblarge,
g1_town_secret_button_small = g1dsbsmall,
}
end
cache = {}
function getSecretButtons(level)
if not cache[level] then
updateCache(level)
end
return cache[level]
end
-- a button that once existed is gone, remove it from cache
function deadButton(level,index)
table.remove(cache[level],index)
end
function updateCache(level)
cache[level] = {}
for e in Dungeon.getMap(level):allEntities() do
if buttons[e.name] then
table.insert(cache[level],e.id)
end
end
end
function getButtonOffset(button)
return buttons[button]
end]]
},
},
}