Questions for DarkGod (or others)

If you have a module that you'd like comments on or would like to know how to create your very own module, post here

Moderator: Moderator

Message
Author
Grey
Loremaster
Posts: 3517
Joined: Thu Sep 23, 2010 10:18 pm
Location: London, England
Contact:

Questions for DarkGod (or others)

#1 Post by Grey »

Planning my 7DRL and there's a few things that come to mind that I'm not sure how to do...

1. Play a sound. How ToME does it is a bit of a mystery - there seem to be weird files involved. What's the easiest way to trigger a sound to be played?

2. Trigger an action on moving onto a square.

3. Show a full screen image overlaid on the map with transparency (is this possible?) An animation would be good too.

4. Use the shader thingummies to make everything greyscale apart from the colour red, which would be upped in brightness. (Is this possible?) Alternatively just reshade everything red, but without making things darker.

5. Have randomised colours of map tiles, so for instance a load of #'s in a forest would all be slightly randomised colours of green. Can you set the numbers in the tile declarations to be slightly random?

6. Adding blood stains to the map on creature death - essentially just recolouring the tiles.

7. Effects across the whole level on boss death, such as recolouring all tiles, changing tiles (earthquake style effect) and killing all other creatures.

8. Have a door that only opens if a flag is set (such as a certain boss dead).

Also, apart from my 7DRL, there's a few other things I was wondering for Unstoppable:

9. How to have a looping map. Both spatially and visually if possible. Would look like an infinite plane, but with big enough screen you'd see yourself in all directions.

10. How to have a high score record that could be displayed on the main screen.

11. Online high scores? I know modules can use the profile system, but I'm guessing high scores might be another matter.

Edit: Oh, and one other Q... DarkGod, you told me once that there's a way of turning off the module asking for a name at the start?

Edit2: And another other Q... How do you make a graphical resource bar? I tried copying some code before from ToME and it didn't work. Is there a simple way?
http://www.gamesofgrey.com - My own T-Engine games!
Roguelike Radio - A podcast about roguelikes

yufra
Perspiring Physicist
Posts: 1332
Joined: Tue Jul 13, 2010 2:53 pm

Re: Questions for DarkGod (or others)

#2 Post by yufra »

A really good set of question! I am going to point you in what I feel is the right direction, usually by referring to things ToME is already doing. If you want me to give actual code then just say the word.
Grey wrote: 1. Play a sound. How ToME does it is a bit of a mystery - there seem to be weird files involved. What's the easiest way to trigger a sound to be played?
A bit of poking around and it looks like you need your game class in inherit from `engine.interface.GameSound` (and `engine.interface.GameMusic` for music). Then you can put a file `data/sound/deathcry.ogg` and play it with `game:playSound("deathcry")`. There appear to be some other tricks you can do, like use a lua file instead of an ogg or pass a table instead of the string "deathcry", but that should at least get you started.
2. Trigger an action on moving onto a square.
The tutorials do this by laying special traps. If you want to go that route, look at `tome/data/zones/tutorial/traps.lua` for inspiration. Alternatively you can create special terrains that do something special on `block_move` (tome/data/general/grids/basic.lua and look for BASIC_LEVER) or `on_stand` (tome/data/general/grids/water.lua and look for POISON_WATER_DEEP). For the `block_move` and lever example, just be sure to `return false` so that the player can move on to the tile.
5. Have randomised colours of map tiles, so for instance a load of #'s in a forest would all be slightly randomised colours of green. Can you set the numbers in the tile declarations to be slightly random?
The first thing that jumps to mind is how ToME handles trees. There is a single base TREE grid, but then if you look below it in `tome/data/general/grids/forest.lua` you will see a for loop creating TREE_1, TREE_2, ... TREE_30. Then DG uses the `nice_tiler` to replace them when actually generating the level. Be sure to grab `tome/class/NicerTiles.lua` if you decide to go that route. If you want something a more straight-forward you could skip the NicerTiles bit, but still use the for loop to generate TREE_1 through TREE_30 with varying colours (note the spelling!). Then in the zone's post_process function you could manually run through and every TREE tile you find replace it with a random choice of TREE_1 through TREE_30.
6. Adding blood stains to the map on creature death - essentially just recolouring the tiles.
This is surprisingly complicated, although DG may have an elegant solution to it. The obvious thing to do is add some special code to the NPC's `on_die` function. There are a few ways to handle the actual changing of the tile, though. First, you can have a BLOODIED_FLOOR and you simply swap out the old FLOOR with BLOODIED_FLOOR. That would look like this:

Code: Select all

on_die = function(self, src, death_note)
    local bloodied = game.zone:makeEntityByName(game.level, "terrain", "BLOODIED_FLOOR")
    game.level.map(self.x, self.x, engine.Map.TERRAIN, bloodied)
end
If you would rather toss a specific image down on top of a tile instead of overwriting the terrain every time you could create a BLOODSTAIN object and place it on the map in one of the unused locations (locations are TERRAIN, TRAP, ACTOR, PROJECTILE, and OBJECT). You could even add a new location if you wanted by making a `mod.class.Map` and tweaking some of the code, but I'll leave that explanation for later and only if you want it.
7. Effects across the whole level on boss death, such as recolouring all tiles, changing tiles (earthquake style effect) and killing all other creatures.
This is a special case of the above answer. Again we would put an `on_die` function on the boss and then iterate through all of the x/y coordinates of `game.level.map` and do something.
8. Have a door that only opens if a flag is set (such as a certain boss dead).
You want to add some special checks in your Grid's `block_move` function. You can derive inspiration from ToME's vault doors (`tome/class/Grid.lua`), particularly the `if self.door_player_check` section. You can use something similar to check a flag, perhaps using a quest.
<DarkGod> lets say it's intended

Zonk
Sher'Tul
Posts: 1067
Joined: Sat Mar 01, 2003 4:01 pm

Re: Questions for DarkGod (or others)

#3 Post by Zonk »

Grey wrote:
6. Adding blood stains to the map on creature death - essentially just recolouring the tiles.
Check BloodyDeath.lua in /engine/interface.lua
Might take some tweaking for what you want to do, though, but I did get it to work time ago.
ToME online profile: http://te4.org/users/zonk
Addons (most likely obsolete): Wights, Trolls, Starting prodigy, Alternate save/resistance system

bricks
Sher'Tul
Posts: 1262
Joined: Mon Jun 13, 2011 4:10 pm

Re: Questions for DarkGod (or others)

#4 Post by bricks »

Grey, if you are just looking for a very simple resource bar display, check out the Gene Revolution code. I did some slash-and-burn coding to display life and energy values. If you'd like I could find the specific commit.
Sorry about all the parentheses (sometimes I like to clarify things).

Grey
Loremaster
Posts: 3517
Joined: Thu Sep 23, 2010 10:18 pm
Location: London, England
Contact:

Re: Questions for DarkGod (or others)

#5 Post by Grey »

Thanks, guys! Just to check, what does the BloodyDeath thing do, Zonk?

bricks: Slash and burn is my style of coding :D If you've got the code handy it would be nice to see (or I had check with someone on IRC how to peek at it).
http://www.gamesofgrey.com - My own T-Engine games!
Roguelike Radio - A podcast about roguelikes

bricks
Sher'Tul
Posts: 1262
Joined: Mon Jun 13, 2011 4:10 pm

Re: Questions for DarkGod (or others)

#6 Post by bricks »

The bulk of the code:
https://github.com/TE4-Module-Developer ... 9f9598589c

Yufra's fix for display on first turn:
https://github.com/TE4-Module-Developer ... 0316d5c550

There's a lot of junk in there for resources we had earlier but dropped. Honestly, I don't know how I made that code work :D.
Sorry about all the parentheses (sometimes I like to clarify things).

Zonk
Sher'Tul
Posts: 1067
Joined: Sat Mar 01, 2003 4:01 pm

Re: Questions for DarkGod (or others)

#7 Post by Zonk »

Grey wrote:Thanks, guys! Just to check, what does the BloodyDeath thing do, Zonk?
When a monster dies, it's supposed to color a few tiles a round it based on its has_blood field.
ToME online profile: http://te4.org/users/zonk
Addons (most likely obsolete): Wights, Trolls, Starting prodigy, Alternate save/resistance system

eliotn
Wyrmic
Posts: 244
Joined: Mon Sep 26, 2011 1:49 pm

Re: Questions for DarkGod (or others)

#8 Post by eliotn »

Also planning my 7drl, here is what I am not sure about how to do either:

1. Temporarily light up particular squares. Do I just convert those squares into Lit squares and set a timer on them, and convert them to unlit squares when the timer expires?

2. Have allies that follow the player around (do I just have to have the allies treat the player as a "target"?)

3. Set the amount of time a particular action takes (possibly based on various calculations). For example, faster movement in a particular situation, or faster casting of spells.

4. Have the monsters wander around the level, instead of staying put. Do I just need to change the AI?

yufra
Perspiring Physicist
Posts: 1332
Joined: Tue Jul 13, 2010 2:53 pm

Re: Questions for DarkGod (or others)

#9 Post by yufra »

Zonk wrote: When a monster dies, it's supposed to color a few tiles a round it based on its has_blood field.
It actually clones the grid that was originally there and then tweaks the color to look "bloodied". This would probably work for ASCII tiles quite well. Thanks for remembering that one Zonk!
<DarkGod> lets say it's intended

yufra
Perspiring Physicist
Posts: 1332
Joined: Tue Jul 13, 2010 2:53 pm

Re: Questions for DarkGod (or others)

#10 Post by yufra »

eliotn wrote: 1. Temporarily light up particular squares. Do I just convert those squares into Lit squares and set a timer on them, and convert them to unlit squares when the timer expires?
Yes, you use the `game.level.map.lites` function call (actually called `maplite` in `engine/Map.lua`).
2. Have allies that follow the player around (do I just have to have the allies treat the player as a "target"?)
That is the easiest way to handle this.
3. Set the amount of time a particular action takes (possibly based on various calculations). For example, faster movement in a particular situation, or faster casting of spells.
The turn-based game operates on a concept of `energy`. An actor will be able to `act` once it has accumulated 1000 energy, and when it acts it calls its `useEnergy` function. By default that function call will use up the entire 1000 energy, but you can pass in an argument saying exactly how much energy you want to use. Look at `tome/class/Actor.lua` and search for `self:useEnergy` to see how it is handled there.
4. Have the monsters wander around the level, instead of staying put. Do I just need to change the AI?
Yes just change the AI. The easiest think would be to do a random walk (no target the pick random direction and move in it) although more "interesting" approaches would be to pick a direction and travel in it, with a chance every turn to choose a different direction to travel in.

EDIT: Fixed some formatting.
<DarkGod> lets say it's intended

eliotn
Wyrmic
Posts: 244
Joined: Mon Sep 26, 2011 1:49 pm

Re: Questions for DarkGod (or others)

#11 Post by eliotn »

Thanks for the help. Other things I would like to do:

1. How do I make items that have an effect on another item when used on another item? Like the spellblaze crystal?

2. How do I generate a dungeon that can randomly place a fixed map (like a vault)? I tried using some of the vault functions in the example code, but it didn't work.

darkgod
Master of Eyal
Posts: 10750
Joined: Wed Jul 24, 2002 9:26 pm
Location: Angolwen
Contact:

Re: Questions for DarkGod (or others)

#12 Post by darkgod »

3. Show a full screen image overlaid on the map with transparency (is this possible?) An animation would be good too.
You load your image in your Game:run() code, something like that:

Code: Select all

self.foo = {core.display.loadImage("/data/gfx/foo.png"):glTexture()}
Then in your Game:display(), right after the map is drawn to draw it:
* streched:

Code: Select all

self.foo[1]:toScreenFull(map.display_x, map.display_y, map.viewport.width, map.viewport.height, map.viewport.width * self.foo[2] / self.foo[7], map.viewport.height * self.foo[3] / self.foo[7], 1, 1, 1, 0.6)
* tiled:

Code: Select all

self.foo[1]:toScreenFull(map.display_x, map.display_y, map.viewport.width, map.viewport.height, self.foo[2], self.foo[3], 1, 1, 1, 0.6)
Each time the 1, 1, 1, 0.6 is the "color" to draw as. Use 1,1,1 to draw the image with normal colors and the 0.6 is the alpha transparency to apply.
Edit: Oh, and one other Q... DarkGod, you told me once that there's a way of turning off the module asking for a name at the start?
Easy, in init.lua you add:

Code: Select all

no_get_name = true
10. How to have a high score record that could be displayed on the main screen.
Simply have a "score_formatter" in init.lua like tome does and then look for "highscore" in time's Game.lua, there are very few lines required.
11. Online high scores? I know modules can use the profile system, but I'm guessing high scores might be another matter.
Unsupported yet
9. How to have a looping map. Both spatially and visually if possible. Would look like an infinite plane, but with big enough screen you'd see yourself in all directions.
Hum C core support would be needed, I can add it on the todo list :)
4. Use the shader thingummies to make everything greyscale apart from the colour red, which would be upped in brightness. (Is this possible?) Alternatively just reshade everything red, but without making things darker.
Hum shaders ... :) You need to understand one thing about how this all works.
To use a fullscreen or fullmap shader the game makes a FBO (framebuffer object, like a virtual screen that outputs to a texture), displays the map inside it and then displays the FBO's texture through the shader. The shader is applied to each and every pixel drawn from the texture.

So first you setup your FBOs, for that just copy ToME's Game:createFBOs() method and call it as tome does (in setupDisplayMode).
Now your fbos are created and your shaders are loaded. You need to use them now. Not all displays can do shaders or FBO though, so you need two versions of your map display code:
Where your module probably just does (if you copied example module):

Code: Select all

		self.level.map:display(nil, nil, nb_keyframe)
		self.target:display()
You instead do:

Code: Select all

		-- Display using Framebuffer, so that we can use shaders and all
		local map = game.level.map
		if self.fbo then
			self.fbo:use(true)
				map:display(0, 0, nb_keyframes)
			self.fbo:use(false, self.full_fbo)
			self.fbo:toScreen(map.display_x, map.display_y, map.viewport.width, map.viewport.height, self.fbo_shader.shad)

			if self.target then self.target:display() end

		-- Basic display; no FBOs
		else
			map:display(nil, nil, nb_keyframes)
			if self.target then self.target:display() end
		end
This will make the map display in its own texture and then use the fbo shader on it.
ToME uses two fbos, one for the map and one for the whole screen.
The fullscreen one must thus also be used:
At the top of Game:display() right after the "if self.change_res_dialog" you add a line:

Code: Select all

	if self.full_fbo then self.full_fbo:use(true) end
And then at the very bottom of Game:display() you do:

Code: Select all

	if self.full_fbo then
		self.full_fbo:use(false)
		self.full_fbo:toScreen(0, 0, self.w, self.h, self.full_fbo_shader.shad)
	end
This will display all the game inside a fbo and then display it with the given shader.

Now shaders themselves. They live in data/gfx/shaders/ There must usualy be two file per shaders, a .lua file that describes it and a .frag one that is the shader code to run on the GPU. Try to see how main_fbo and full_fbo shaders in ToME work. They probably are enough for your needs but you can play with them as you need (or ask more specific questions).

Now if you did it all right your game should display .. just as before!
So we need to tell the shaders to do stuff. First tell the full_fbo shader to handle gamme correction instead of the OS (it usualy looks better):
define

Code: Select all

support_shader_gamma = true
in Game.lua, before the init method (like ToME does).
If at that point you get a fully dark screen, try to add

Code: Select all

self:setGamma(config.settings.gamma_correction / 100)
right at the end of createFBOs.

Now the fun part!
Say you want to colorize your game in red, you simply do:

Code: Select all

game.fbo_shader:setUniform("colorize", {1,0.2,0,1})
Somewhere in your code. To restore default you do:

Code: Select all

game.fbo_shader:setUniform("colorize", {0,0,0,0})
ToME's relevant code for that is in Player:updateMainShader()

Go play with those :)
[tome] joylove: You can't just release an expansion like one would release a Kraken XD
--
[tome] phantomfrettchen: your ability not to tease anyone is simply stunning ;)

Grey
Loremaster
Posts: 3517
Joined: Thu Sep 23, 2010 10:18 pm
Location: London, England
Contact:

Re: Questions for DarkGod (or others)

#13 Post by Grey »

Thanks for answers, DG!

I got the shaders thing working as you describe in Run from the Shadow, and it can make some snazzy effects. But colorize doesn't do what I want - it just passes everything through a colour filter. It makes the white stuff turn whatever colour you put in and tones everything else down. Ultimately I want white to stay white, red to stay red (or turn redder) and everything else to appear greyed. Is this possible?
http://www.gamesofgrey.com - My own T-Engine games!
Roguelike Radio - A podcast about roguelikes

darkgod
Master of Eyal
Posts: 10750
Joined: Wed Jul 24, 2002 9:26 pm
Location: Angolwen
Contact:

Re: Questions for DarkGod (or others)

#14 Post by darkgod »

Is this what you wish ?
Image

If so you can take ToME's main_fbo.frag file from svn and use instead of "colorize" "intensify".
The above result is done with an intensify of {1.1, 0, 0, 1}
[tome] joylove: You can't just release an expansion like one would release a Kraken XD
--
[tome] phantomfrettchen: your ability not to tease anyone is simply stunning ;)

Grey
Loremaster
Posts: 3517
Joined: Thu Sep 23, 2010 10:18 pm
Location: London, England
Contact:

Re: Questions for DarkGod (or others)

#15 Post by Grey »

That's getting close to what I'm after - I'll have a fiddle and find the snazziest setting. Thanks, DarkGod!
http://www.gamesofgrey.com - My own T-Engine games!
Roguelike Radio - A podcast about roguelikes

Post Reply