Problem with spawning (fx), Earthquake, dust

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
J. Trudel
Posts: 117
Joined: Tue Aug 28, 2012 3:05 pm
Location: Montreal, Canada

Problem with spawning (fx), Earthquake, dust

Post by J. Trudel »

I'm trying to achieve an effect similar to the earthquake in the original Grimrock dungeon. I have no problem with the camera shake, however when I try to spawn earthquake dust, it only spawn an effect that last for like 5 seconds and that cover only one square (and that doesn't looks like the original effect at all). The script I use is the one from the useful script repository. If I try to spawn it at multiples places it gives an error.

spawn("fx", level, x, y, face, "dust")
dust:setParticleSystem("earthquake_dust")

Also is there a way to have the original sound to fade instead of ending abruptly without using a custom sound ?
The Lurker
User avatar
petri
Posts: 1917
Joined: Thu Mar 01, 2012 4:58 pm
Location: Finland

Re: Problem with spawning (fx)

Post by petri »

You can spawn more than one dust like this (omitting the id parameter for spawn creates an unique id for each entity automatically):

local dust = spawn("fx", level, x, y, face)
dust:setParticleSystem("earthquake_dust")

local dust = spawn("fx", level, x, y, face)
dust:setParticleSystem("earthquake_dust")

...
User avatar
Komag
Posts: 3658
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Problem with spawning (fx)

Post by Komag »

You can only spawn one instance of the specifically named "dust"

Code: Select all

try spawn("fx", level, x, y, face):setParticleSystem("earthquake_dust")
maybe try setting up an area around the player, such as

Code: Select all

function quake()
  for i = -5,5 do
    for j = -5,5 do
        spawn("fx", party.level, party.x+i, party.y+j, 0):setParticleSystem("earthquake_dust")
    end
  end
end
Finished Dungeons - complete mods to play
User avatar
J. Trudel
Posts: 117
Joined: Tue Aug 28, 2012 3:05 pm
Location: Montreal, Canada

Re: Problem with spawning (fx) [Resolved]

Post by J. Trudel »

petri wrote:You can spawn more than one dust like this (omitting the id parameter for spawn creates an unique id for each entity automatically):

local dust = spawn("fx", level, x, y, face)
dust:setParticleSystem("earthquake_dust")

local dust = spawn("fx", level, x, y, face)
dust:setParticleSystem("earthquake_dust")

...
Many thanks Petri ! I now realize I was trying to spawn the same id and this is why it was problematic.
The Lurker
User avatar
J. Trudel
Posts: 117
Joined: Tue Aug 28, 2012 3:05 pm
Location: Montreal, Canada

Re: Problem with spawning (fx)

Post by J. Trudel »

Komag wrote:You can only spawn one instance of the specifically named "dust"

Code: Select all

try spawn("fx", level, x, y, face):setParticleSystem("earthquake_dust")
maybe try setting up an area around the player, such as

Code: Select all

function quake()
  for i = -5,5 do
    for j = -5,5 do
        spawn("fx", party.level, party.x+i, party.y+j, 0):setParticleSystem("earthquake_dust")
    end
  end
end
Seems like a great idea, I'm not sure exactly how your script works it set a loop to spawn the fx but how long does it last ?

Edit : Many thanks Komag, you are of great help, you have good scripting skills. Any idea of where should I start to learn that ?
The Lurker
User avatar
Komag
Posts: 3658
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Problem with spawning (fx)

Post by Komag »

That just spawns one dust fx in each of 121 squares all at once, a big 'ol one-shot.

Really what you want is for some random spawning in the more immediate area of the player, with a timer ticking and picking random spawn points very quickly, say, every 0.2 seconds or something, so they aren't the same, and continue as long as you set up the script to tick-count up to

Code: Select all

quakeTick = 1
function bigQuake()
  local dustTargY = {-3, -2, -1, 0, 1, 2, 3}
  dY = dustTargY[math.random(1, #dustTargY)]
  local dustTargX = {-3, -2, -1, 0, 1, 2, 3}
  dX = dustTargX[math.random(1, #dustTargX)]
  if quakeTick < 50 then
     spawn("fx", party.level, party.x+dX, party.y+dY, 0):setParticleSystem("earthquake_dust")
    else
     quakeTimer:deactivate()
     quakeTick = 1
     return
  end
  quakeTick = quakeTick + 1
end
In this case you need to set up a timer called quakeTimer and you trigger the TIMER, not the function. Set the timer so IT triggers the function every 0.2sec, and when the function counts up to 50 it will then deactivate the timer.

Each time the timer triggers the script, the script picks a random X,Y to spawn a new dust at (an it will always be near the party, so the party can move along the dungeon while it's occuring), and it also increases the quakeTick number by 1. When quakeTick gets to 50 the timer will be deactivated and the dust will stop spawning. The last action will also reset quakeTick back to 1 and will "return" the function (stop processing the rest of the function) so it doesn't increase the tick by 1 again.

If you want the quake to last longer just raise the 50 to whatever you want. If you want the dust to spawn more densely, you can shorten the timer down to 0.15 or 0.1 seconds (but don't forget to increase the quakeTick to make up for a shorter time in-between ticks)
Finished Dungeons - complete mods to play
User avatar
J. Trudel
Posts: 117
Joined: Tue Aug 28, 2012 3:05 pm
Location: Montreal, Canada

Re: Problem with spawning (fx)

Post by J. Trudel »

Komag wrote:That just spawns one dust fx in each of 121 squares all at once, a big 'ol one-shot.

Really what you want is for some random spawning in the more immediate area of the player, with a timer ticking and picking random spawn points very quickly, say, every 0.2 seconds or something, so they aren't the same, and continue as long as you set up the script to tick-count up to

Code: Select all

quakeTick = 1
function bigQuake()
  local dustTargY = {-3, -2, -1, 0, 1, 2, 3}
  dY = dustTargY[math.random(1, #dustTargY)]
  local dustTargX = {-3, -2, -1, 0, 1, 2, 3}
  dX = dustTargX[math.random(1, #dustTargX)]
  if quakeTick < 50 then
     spawn("fx", party.level, party.x+dX, party.y+dY, 0):setParticleSystem("earthquake_dust")
    else
     quakeTimer:deactivate()
     quakeTick = 1
     return
  end
  quakeTick = quakeTick + 1
end
In this case you need to set up a timer called quakeTimer and you trigger the TIMER, not the function. Set the timer so IT triggers the function every 0.2sec, and when the function counts up to 50 it will then deactivate the timer.

Each time the timer triggers the script, the script picks a random X,Y to spawn a new dust at (an it will always be near the party, so the party can move along the dungeon while it's occuring), and it also increases the quakeTick number by 1. When quakeTick gets to 50 the timer will be deactivated and the dust will stop spawning. The last action will also reset quakeTick back to 1 and will "return" the function (stop processing the rest of the function) so it doesn't increase the tick by 1 again.

If you want the quake to last longer just raise the 50 to whatever you want. If you want the dust to spawn more densely, you can shorten the timer down to 0.15 or 0.1 seconds (but don't forget to increase the quakeTick to make up for a shorter time in-between ticks)
Many many thanks ! So if I understand correctly, the function select a random point (near the party) to spawn the dust every time the timer activate the function, and then the function deactivate the timer when a certain amount of times it was run (in this case 50. So I set a timer so it activate the function bigQuake() right ?
The Lurker
User avatar
Komag
Posts: 3658
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Problem with spawning (fx)

Post by Komag »

yeah. So, for example, you want stepping on a certain pressure plate to cause the earthquake, you connect the plate to the timer, and the timer will then start ticking the function very fast.

if you are going to have other quake stuff happening (shaking, sound), then that would probably all be in a different function, and you could connect the plate to just that function and have that function start the timer instead.

Code: Select all

function quakeStart()
  party:shakeCamera(0.3, 8)
  playSound("earthquake_stop")
  quakeDustTimer:activate()
end

quakeTick = 1
function quakeDust()
  local dustTargY = {-3, -2, -1, 0, 1, 2, 3}
  dY = dustTargY[math.random(1, #dustTargY)]
  local dustTargX = {-3, -2, -1, 0, 1, 2, 3}
  dX = dustTargX[math.random(1, #dustTargX)]
  if quakeTick < 40 then
     spawn("fx", party.level, party.x+dX, party.y+dY, 0):setParticleSystem("earthquake_dust")
     print(quakeTick)
    else
     quakeDustTimer:deactivate()
     quakeTick = 1
     return
  end
  quakeTick = quakeTick + 1
end
You would just connect the plate to quakeStart(), and make sure your names match up (I changed it to quakeDust() and quakeDustTimer)
of course for it to work you need to define that sound:

Code: Select all

defineSound{
   name = "earthquake_stop",
   filename = "assets/samples/env/earthquake_01.wav",
   loop = false,
   volume = 1,
   minDistance = 1,
   maxDistance = 6,
}
and you need to put that code in one of the mod_asset folder scripts and reload your dungeon for it to work.
Finished Dungeons - complete mods to play
User avatar
akroma222
Posts: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: Problem with spawning (fx), Earthquake, dust

Post by akroma222 »

Very cool scripting! I feel an Earthquake spell is in order ;)
User avatar
Roman42
Posts: 42
Joined: Tue Dec 11, 2012 11:38 am

Re: Problem with spawning (fx), Earthquake, dust

Post by Roman42 »

Sorry for digging up this old thread.

I've included your script in my mod and it works great.
I want it to be like in the main game, sometimes the earthquake gets triggered just for atmospheric reasons. But the cut-off sound is poison for the atmosphere, so if tried some things:

I'm simply fading it out by using more silent versions of earthquake_stop:

Code: Select all

defineSound{
   name = "earthquake_stop",
   filename = "assets/samples/env/earthquake_01.wav",
   loop = false,
   volume = 1,
   minDistance = 1,
   maxDistance = 6,
}

defineSound{
   name = "earthquake_stop1",
   filename = "assets/samples/env/earthquake_01.wav",
   loop = false,
   volume = 0.7,
   minDistance = 1,
   maxDistance = 6,
}

defineSound{
   name = "earthquake_stop2",
   filename = "assets/samples/env/earthquake_01.wav",
   loop = false,
   volume = 0.4,
   minDistance = 1,
   maxDistance = 6,
}

defineSound{
   name = "earthquake_stop3",
   filename = "assets/samples/env/earthquake_01.wav",
   loop = false,
   volume = 0.2,
   minDistance = 1,
   maxDistance = 6,
}

defineSound{
   name = "earthquake_stop4",
   filename = "assets/samples/env/earthquake_01.wav",
   loop = false,
   volume = 0.1,
   minDistance = 1,
   maxDistance = 6,
}
And triggering them inside your script to generate a echo or fake fadeout:

Code: Select all

    function quakeStart()
	 spawn ("timer",party.level,0,0,0,"quakeDustTimer"):setTimerInterval(0.2):addConnector("activate","random_Earthquake","quakeDust"):activate()
     party:shakeCamera(math.random(0.2)+0.1, 10)
     playSound("earthquake_stop")
    end

    quakeTick = 1

    function quakeDust()
     local dustTargY = {-3, -2, -1, 0, 0, 1, 2, 3}
     local dY = dustTargY[math.random(1, #dustTargY)]
     local dustTargX = {-3, -2, -1, 0, 0, 1, 2, 3}
     local dX = dustTargX[math.random(1, #dustTargX)]
     if quakeTick < 40 then
      spawn("fx", party.level, party.x+dX, party.y+dY, 0):setParticleSystem("earthquake_dust")
      if quakeTick==10 then playSound("earthquake_stop1") end
      if quakeTick==14 then playSound("earthquake_stop2") end
      if quakeTick==21 then playSound("earthquake_stop3") end
      if quakeTick==29 then playSound("earthquake_stop4") end
     else
      quakeDustTimer:deactivate()
	  quakeDustTimer:destroy()
      quakeTick = 1
      return
     end
     quakeTick = quakeTick + 1
    end
Sounds good so far, perhaps it can be optimized with less versions of earthquake_stop.
Last edited by Roman42 on Sun Jan 06, 2013 4:16 am, edited 2 times in total.
Post Reply