It is, because it means the range of zone effects is effectively longer on diagonals than in compass directions (although the problem does not appear until ranges greater than 2 are used).AndakRainor wrote:Oh the aliased Euclidean circle shape was intended then! Is it a problem?
[Open / Signup] One Room Round Robin 3 - Calling All Modders
Re: [Open / Signup] One Room Round Robin 3 - Calling All Mod
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
- AndakRainor
- Posts: 674
- Joined: Thu Nov 20, 2014 5:18 pm
Re: [Open / Signup] One Room Round Robin 3 - Calling All Mod
Would you say this geometry should be used for a spell such as Oracle? (It hudPrints the distance from the party to nearby secrets in its range). For damage zone effects, monsters on diagonals will take more time to reach the party... But this geometry is not very natural, I would say tile based movements do not need additional taxicab features. arcane_nova would feel weird with this. I can't think about a situation where euclidean range would feel as weird as taxicab.
Re: [Open / Signup] One Room Round Robin 3 - Calling All Mod
No idea. Oracle is a strange spell in the first place because secrets are often not placed in the same location as whatever triggers them, for example all the secrets in Xanathar's room are inside walls. I think I'll just drop this issue.AndakRainor wrote:Would you say this geometry should be used for a spell such as Oracle? (It hudPrints the distance from the party to nearby secrets in its range).
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
- AndakRainor
- Posts: 674
- Joined: Thu Nov 20, 2014 5:18 pm
Re: [Open / Signup] One Room Round Robin 3 - Calling All Mod
Good point. It could detect secret buttons instead, what do you think about that? (or do you plan on using third eye in the mod?)
- AndakRainor
- Posts: 674
- Joined: Thu Nov 20, 2014 5:18 pm
Re: [Open / Signup] One Room Round Robin 3 - Calling All Mod
work in progress: down to 63 total spells...
Re: [Open / Signup] One Room Round Robin 3 - Calling All Mod
I don't plan to include the Third Eye, though of course someone else can if they want to. (If someone else does add it, they should use the current version of third_eye.lua in this spoiler:)AndakRainor wrote:Good point. It could detect secret buttons instead, what do you think about that? (or do you plan on using third eye in the mod?)
SpoilerShow
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]]
},
},
}
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
Re: [Open / Signup] One Room Round Robin 3 - Calling All Mod
Secrets are also scripted; as when the correct item is placed upon the altar... I think to really work, the spell would require a dedicated listing of what secrets it can detect in the specific dungeon [mod] where it is used. The list [table] could include the location of the secret, and a suitable '8-ball' style cryptic hint ~specific to the secret.AndakRainor wrote:Good point. It could detect secret buttons instead, what do you think about that? (or do you plan on using third eye in the mod?)
In "Lands of Lore", party members could spot a secret, and mention it aloud. The same could be done for the casting mage; perhaps even have a duration of effect, where the mage makes comments if they pass near a detectable secret. [Comments, but not the outright answer.]
- AndakRainor
- Posts: 674
- Joined: Thu Nov 20, 2014 5:18 pm
Re: [Open / Signup] One Room Round Robin 3 - Calling All Mod
Yes, definitely. Cut any spells you want.
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
- AndakRainor
- Posts: 674
- Joined: Thu Nov 20, 2014 5:18 pm
Re: [Open / Signup] One Room Round Robin 3 - Calling All Mod
I have a list of 49 spells now, versus 20 in Isle of Nex. Do you want me to continue?