a nice cavern filled with lava

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
User avatar
AndakRainor
Posts: 674
Joined: Thu Nov 20, 2014 5:18 pm

Re: a nice cavern filled with lava

Post by AndakRainor »

I think water tiles with a surface elevation different from 0 (-0.4) can cause some problems, i did not test. Perhaps breath, sounds problems or other unwanted behaviors if you walk over them but not over elevation -1.

So I think you should use the "lava_surface" object, for this map, and also everywhere it is possible. Use the water tiles only if it is mandatory in the situation. You can just set the elevation of the "lava_surface" object freely, you don't need to define a new object for that.

If you really need the water tiles version, make sure nothing wrong happens when you walk over the surface, it may need some new code if it is possible at all.
minmay
Posts: 2768
Joined: Mon Sep 23, 2013 2:24 am

Re: a nice cavern filled with lava

Post by minmay »

Whether the party (or a monster or item) is considered underwater or not actually has nothing to do with the water surface or water surface mesh object. It is tied solely to whether they are in a tile with the "underwater" flag and at a low enough world y position at the same time. You can even use the heightmap to let the party wade slowly into water (although the water shader looks incredibly bad when camera y is close to the plane y, so you don't want to do that).
What often trips people up is that the planeY value in the WaterSurfaceComponent determines the y position of the reflection plane. Generally you want this to be the same as the y position of the water plane, since objects are supposed to appear to reflect off the water, but I can imagine exceptions.
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.
User avatar
AndakRainor
Posts: 674
Joined: Thu Nov 20, 2014 5:18 pm

Re: a nice cavern filled with lava

Post by AndakRainor »

For those who did not follow all the discussion, here is the final code I use for lava in my mod, including eruptions:
SpoilerShow

Code: Select all

-- lava

defineObject{
  name = "eruption",
  components = {
    {
      class = "Light",
      offset = vec(0, -0.5, 0),
      range = 10,
      color = vec(2.8, 1.2, 0.7),
      brightness = 1,
      fadeOut = 6,
      castShadow = false,
      destroyObject = true,
    },
    {
      class = "Particle",
      particleSystem = "eruption",
    },
    {
      class = "Projectile",
      spawnOffsetY = 0,
      velocity = 1,
      radius = 0.1,
      gravity = 4,
      fallingVelocity = 4,
      destroyOnImpact = false,
      onProjectileHit = function(self, what, entity)
        self.go.particle:stop()
      end,
      onInit = function(self)
        self.go:setSubtileOffset(math.random()-0.5, math.random()-0.5)
        self:setFallingVelocity(math.random()*2+3)
        self:setVelocity(math.random()*2)
      end,
    },
  },
  placement = "floor",
  editorIcon = 88,
}

defineParticleSystem{
  name = "eruption",
  emitters = {
    -- star
    {
      --spawnBurst = true,
      emissionRate = 200,
      emissionTime = 3,
      maxParticles = 700,
      boxMin = {0,0,0},
      boxMax = {0,0,0},
      sprayAngle = {0,0},
      velocity = {0,0},
      objectSpace = false,
      texture = "assets/textures/particles/candle_glow.tga",
      lifetime = {1,1},
      color0 = {4, 0.4, 0.2},
      opacity = 1,
      fadeIn = 0,
      fadeOut = 1,
      size = {0.05, 0.1},
      gravity = {0,0,0},
      airResistance = 0.1,
      rotationSpeed = 5,
      blendMode = "Additive",
    },
  }
}

defineObject{
  name = "lava_effects",
  components = {
    { class = "Light",
      offset = vec(0, -0.5, 0),
      range = 6,
      color = vec(2.8, 1.2, 0.7),
      brightness = 10,
      castShadow = true,
      shadowMapSize = 64,
      staticShadows = true,
      staticShadowDistance = 0,   -- use static shadows always
    },
    { class = "Particle",
      particleSystem = "lava_effects",
      offset = vec(0, -0.4, 0),
    },
    {
      class = "TileDamager",
      attackPower = 3,
      damageType = "fire",
      repeatCount = math.huge,
      repeatDelay = 1,
      onInit = function(self)
        if self.go.map:getElevation(self.go.x, self.go.y) < self.go.elevation then
          spawn("under_lava_effects", self.go.level, self.go.x, self.go.y, self.go.facing, self.go.elevation-1)
        end
      end,
    },
    { class = "Timer",
      timerInterval = 1,
      triggerOnStart = true,
      onActivate = function(self)
        local l,x,y,f,e = self.go.level, self.go.x, self.go.y, self.go.facing, self.go.elevation
        for i in self.go.map:entitiesAt(x, y) do
          if i.item and i.elevation < e then
            local m = self.go:spawn("fire_elemental")
            m.monster:addItem(i.item)
          end
        end
        self.go:playSound("magma_explosion")
        spawn("magma_golem_meteor_impact_ground", l, x, y, f, e-1)
        for f = 0,3 do spawn("eruption", l, x, y, f, e) end
        self:setTimerInterval(300*(0.1+0.9*math.random()))
      end,
      onInit = function(self)
        self:setTimerInterval(300*math.random())
      end,
    },
    { class = "Sound",
      sound = "fire_pit",
      volume = 0.5,
    },
  },
  placement = "floor",
  editorIcon = 88,
}

defineObject{
  name = "under_lava_effects",
  components = {
    { class = "Particle",
      particleSystem = "under_lava_effects",
    },
    {
      class = "TileDamager",
      attackPower = 1000,
      damageType = "fire",
      repeatCount = math.huge,
      repeatDelay = 1,
      onInit = function(self)
        if self.go.map:getElevation(self.go.x, self.go.y) < self.go.elevation then
          spawn("under_lava_effects", self.go.level, self.go.x, self.go.y, self.go.facing, self.go.elevation-1)
        end
      end,
    },
  },
  placement = "floor",
  editorIcon = 88,
}

defineObject{
  name = "lava_surface",
  components = {
    {
      class = "Model",
      model = "assets/models/env/ocean_water.fbx",
      material = "lava_surface",
      offset = vec(0, -0.4, 0),
    },
  },
  placement = "floor",
  dontAdjustHeight = true,
  editorIcon = 264,
  color = {250,140,50,255},
  reflectionMode = "never",
}

defineObject{
  name = "lava_surface_tiles",
  baseObject = "base_floor_decoration",
  components = {
    {
      -- updates global reflection and refraction maps
      class = "WaterSurface",
      planeY = -0.4,
      fogColor = math.saturation(vec(0.26, 0.09, 0.042), 0.5) * 0.5,
      fogDensity = 0.4,
      reflectionColor = vec(1.5, 0.9, 0.27) * 0.9,
      refractionColor = vec(1.5,1.0,0.5),
    },
    {
      -- builds a continuous mesh from underwater tiles
      class = "WaterSurfaceMesh",
      material = "lava_surface_tiles",
      underwaterMaterial = "lava_surface_tiles",
      offset = vec(0, -0.4, 0),
    },
  },
  dontAdjustHeight = true,
  editorIcon = 264,
  color = {250,140,50,255},
}

defineMaterial{
  name = "lava_surface",
  diffuseMap = "mod_assets/textures/env/lava_dif.tga",
  normalMap = "assets/textures/env/beach_ground_normal.tga",
  emissiveMap = "mod_assets/textures/env/lava_emissive.tga",
  displacementMap = "assets/textures/env/ocean_disp.tga",
  doubleSided = true,
  lighting = true,
  alphaTest = false,
  castShadow = false,
  blendMode = "Opaque",
  textureAddressMode = "Wrap",
  glossiness = 60,
  depthBias = 0,
  onUpdate = function(self, time)
    self:setTexcoordScaleOffset(0.5, 0.5, math.cos(time*0.0625)*0.0625, math.sin(time*0.0625)*0.0625)
  end,
}

defineMaterial{
  name = "lava_surface_tiles",
  diffuseMap = "mod_assets/textures/env/lava_dif.tga",
  normalMap = "assets/textures/env/beach_ground_normal.tga",
  emissiveMap = "mod_assets/textures/env/lava_emissive.tga",
  displacementMap = "assets/textures/env/ocean_disp.tga",
  doubleSided = true,
  lighting = true,
  alphaTest = false,
  castShadow = false,
  blendMode = "Opaque",
  textureAddressMode = "Wrap",
  glossiness = 60,
  depthBias = 0,
  onUpdate = function(self, time)
    self:setTexcoordScaleOffset(0.5, 0.5, math.cos(time*0.0625)*0.0625, math.sin(time*0.0625)*0.0625)
  end,
}

defineParticleSystem{
  name = "lava_effects",
  emitters = {
    -- stars
    {
      emissionRate = 40,
      emissionTime = 0,
      maxParticles = 200,
      boxMin = {-1.3, 0.0,-1.3},
      boxMax = { 1.3, 0.5, 1.3},
      sprayAngle = {0,360},
      velocity = {0,0},
      objectSpace = true,
      texture = "assets/textures/particles/firefly_dif.tga",
      lifetime = {0.5,5.0},
      color0 = {4, 0.4, 0.2},
      opacity = 1,
      fadeIn = 0.1,
      fadeOut = 1.0,
      size = {0.05, 0.1},
      gravity = {0,0.5,0},
      airResistance = 0.1,
      rotationSpeed = 5,
      blendMode = "Additive",
    },
    -- flames 1
    {
      emissionRate = 5,
      emissionTime = 0,
      maxParticles = 5,
      boxMin = {-1.5, -0.1,-1.5},
      boxMax = { 1.5, -0.1, 1.5},
      sprayAngle = {0,360},
      velocity = {0,0},
      objectSpace = false,
      texture = "assets/textures/particles/flame.tga",
      frameSize = 32,
      frameCount = 40,
      frameRate = 60,
      lifetime = {0.5,1.0},
      color0 = {4, 0.4, 0.2},
      opacity = 0.5,
      fadeIn = 0.5,
      fadeOut = 0.5,
      size = {0.5, 0.5},
      gravity = {0,0.02,0},
      airResistance = 0.1,
      rotationSpeed = 1,
      blendMode = "Additive",
    },
    -- flames 2
    {
      emissionRate = 5,
      emissionTime = 0,
      maxParticles = 5,
      boxMin = {-1.5, -0.1,-1.5},
      boxMax = { 1.5, -0.1, 1.5},
      sprayAngle = {0,360},
      velocity = {0,0},
      objectSpace = false,
      texture = "assets/textures/particles/flame.tga",
      frameSize = 32,
      frameCount = 40,
      frameRate = 60,
      lifetime = {0.5,1.0},
      color0 = {4, 0.4, 0.2},
      opacity = 0.5,
      fadeIn = 0.5,
      fadeOut = 0.5,
      size = {0.5, 0.5},
      gravity = {0,0.02,0},
      airResistance = 0.1,
      rotationSpeed = -1,
      blendMode = "Additive",
    },
    -- smoke
    {
      emissionRate = 4,
      emissionTime = 0,
      maxParticles = 40,
      boxMin = {-1.3, 0, -1.3},
      boxMax = { 1.3, 1.0, 1.3},
      sprayAngle = {0,20},
      velocity = {0.4, 0.8},
      texture = "assets/textures/particles/smoke_01.tga",
      lifetime = {1,5},
      color0 = {0.25, 0.20, 0.17},
      opacity = 0.5,
      fadeIn = 0.3,
      fadeOut = 0.9,
      size = {1.5, 2},
      gravity = {0,0.3,0},
      airResistance = 0.1,
      rotationSpeed = 0.5,
      blendMode = "Translucent",
    },
  }
}

defineParticleSystem{
  name = "under_lava_effects",
  emitters = {
    -- fog under 1
    {
      emissionRate = 1,
      emissionTime = 0,
      maxParticles = 10,
      boxMin = {-1.5, -1.0, -1.5},
      boxMax = { 1.5,  2.0,  1.5},
      sprayAngle = {0,360},
      velocity = {0,0},
      objectSpace = true,
      texture = "assets/textures/particles/fog.tga",
      lifetime = {10,10},
      color0 = {1.75,0.6,0.2},
      opacity = 1,
      fadeIn = 2.5,
      fadeOut = 2.5,
      size = {5, 5},
      gravity = {0,0,0},
      airResistance = 0.5,
      rotationSpeed = -0.3,
      blendMode = "Translucent",
    },
    -- fog under 2
    {
      emissionRate = 1,
      emissionTime = 0,
      maxParticles = 10,
      boxMin = {-1.5, -1.0, -1.5},
      boxMax = { 1.5,  2.0,  1.5},
      sprayAngle = {0,360},
      velocity = {0,0},
      objectSpace = true,
      texture = "assets/textures/particles/fog.tga",
      lifetime = {10,10},
      color0 = {1.75,0.6,0.2},
      opacity = 1,
      fadeIn = 2.5,
      fadeOut = 2.5,
      size = {5, 5},
      gravity = {0,0,0},
      airResistance = 0.5,
      rotationSpeed = 0.3,
      blendMode = "Translucent",
    },
  }
}

defineSound{
	name = "magma_explosion",
	filename = "assets/samples/monsters/magma_golem_meteor_fall_01.wav",
	loop = false,
	volume = 2.5,
	minDistance = 1,
	maxDistance = 10,
}
and here you can find the 2 textures : http://ge.tt/9HPTdWE2

Again; you have two ways to put lava in a map :
- The "lava_surface" object is similar to the ocean object, so you place it anywhere and you get a giant surface totally independent from water tiles.
- The "lava_surface_tiles" is used as you use the water surface tiles object, you place it anywhere in a map and it alters all your water tiles.

So if you want both lava and water in a map, you should not use "lava_surface_tiles" but instead place manually your "lava_surface" object where it will not overlap your normal water. I recommend avoiding "lava_surface_tiles" whenever possible as using "lava_surface" is more flexible in most situations.

You also need to place manually the "lava_effects" objects on each tile at the elevation of the surface to get the smoke, light, tiny flames and eruptions.

bonus : as falling in the lava is deadly unless you have insane fire resistance, if you throw something in the lava, the next eruption at this tile will spawn a nice fire elemental who will bring the item back :D
User avatar
Eleven Warrior
Posts: 736
Joined: Thu Apr 18, 2013 2:32 pm
Location: Australia

Re: a nice cavern filled with lava

Post by Eleven Warrior »

This is awesome thxs :)
bongobeat
Posts: 1076
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: a nice cavern filled with lava

Post by bongobeat »

Hello,
I saw some trouble with the lava surface and the wave amplitude (specially the wave). I don't rememberif that was discussed on the forum, as this subject is old.
It seems that on a long time of playing, the amplitude goes crazy. Even if the parameters of the wave are set to a very low amplitude.

Here is a screenshot from the people that is currently testing my mod. I had to give him a command to destroy the surface, or he couldn't play this level.

Image

(here are the waves that come trough the ground, I don't have a screenshot from the lava pits, but there is the same probleme, everywhere there is the lava surface, according to my tester.

Just to be sure. Does this come from the wave amplitude only? So if I disable the amplitude, and have a "flat" lava surface, nothing like this can happen ?

here are my parameters: Please can you look at it, if I've done anything wrong?
The wave amplitude is quoted actually. For testing without waves. It's only the material.
SpoilerShow

Code: Select all

    defineMaterial{
      name = "lava_surface",
      shader = "ocean_water",
      diffuseMap = "mod_assets/lava/lavatest.tga",
      normalMap = "assets/textures/env/beach_ground_normal.tga",
	emissiveMap = "mod_assets/textures/fire512.tga",
      displacementMap = "assets/textures/env/ocean_disp.tga",
      doubleSided = true,
      lighting = true,
      alphaTest = false,
      castShadow = false,
      blendMode = "Opaque",
      textureAddressMode = "Wrap",
      glossiness = 0,
      depthBias = 0,
      texOffset = 0,
      foamOffset = 0,
      foamAmount = 0,
	waveAmplitude = 0,
      onUpdate = function(self, time)
        self:setTexcoordScaleOffset(4, 4, math.cos(time*0.0125)*0.5, math.sin(time*0.0125)*0.5)
--        self:setParam("waveAmplitude", 0.00625*time) -- I've removed this line at the moment, and hope that this disable definetely amplitude and that nothing can goes wrong with the scalling and moving of the texture only.
      end,
    }
Here is a screenshot what it currently looks like, without wave amplitude:
SpoilerShow
Image
My asset pack: viewtopic.php?f=22&t=9320

Log1 mod : Toorum Manor: viewtopic.php?f=14&t=5505
minmay
Posts: 2768
Joined: Mon Sep 23, 2013 2:24 am

Re: a nice cavern filled with lava

Post by minmay »

bongobeat wrote:

Code: Select all

self:setParam("waveAmplitude", 0.00625*time)
So after 10 seconds the wave amplitude is 0.0625, and after 10 minutes the wave amplitude is 3.75, and after an hour the wave amplitude is 22.5.
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.
bongobeat
Posts: 1076
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: a nice cavern filled with lava

Post by bongobeat »

Hu? Why is this posted on the thread? I've sent a pm to AndakRainor, not post a reply to this thread! Strange!

minmay wrote:
bongobeat wrote:

Code: Select all

self:setParam("waveAmplitude", 0.00625*time)
So after 10 seconds the wave amplitude is 0.0625, and after 10 minutes the wave amplitude is 3.75, and after an hour the wave amplitude is 22.5.
thanks for the explanation. It's not surprising that the waves get tall then!
My asset pack: viewtopic.php?f=22&t=9320

Log1 mod : Toorum Manor: viewtopic.php?f=14&t=5505
Post Reply