PaulC's NML questions

Discussions about the technical aspects of graphics development, including NewGRF tools and utilities.

Moderator: Graphics Moderators

Post Reply
User avatar
PaulC
Director
Director
Posts: 616
Joined: 31 Jul 2006 12:40
Location: Lancs, England
Contact:

PaulC's NML questions

Post by PaulC »

Trying to improve my coding skills... I've never done much with vehicles in the past and I could never wrap my head around callbacks in NFO, but now I'm working in NML and it's time to have another go. Have taken my time working through the truck/tram/train tutorials and for the most part it seemed fairly straightforward(ish), so now I'm poking around with my own code and seeing if I can make stuff work the way I want it to.

What I'm struggling with at the moment is sound effects. I want to have a vehicle make a sound every now and then as it runs, kind of like how they do in the Generic Cars grf for example. Tried adding the soundeffect callback with the following switch:

Code: Select all

switch(FEAT_ROADVEHS, SELF, switchSoundEffect, getbits(extra_callback_info1, 0, 8)) {
	SOUND_EVENT_RUNNING: SOUND_CAR_HORN_2;
}
That sort of worked in the sense that it plays the desired sound, except it does so continually. Then I tried combining this with a random switch which I hoped woud at least make the sound intermittant:

Code: Select all

random_switch(FEAT_ROADVEHS, SELF, switch_sounds_random) {
	1: SOUND_CAR_HORN_2;
	5: CB_RESULT_NO_SOUND;
}
But that just results in no running sound. Not entirely sure what I'm meant to be doing and I couldn't find any examples to guide me, so I'd be most grateful for any help steering me in the right direction! Calling it a day for now, will take another stab at this tomorrow.
User avatar
supermop
Tycoon
Tycoon
Posts: 1104
Joined: 21 Feb 2010 00:15
Location: Fitzroy North - 96

Re: PaulC's NML questions

Post by supermop »

PaulC wrote:Code:random_switch(FEAT_ROADVEHS, SELF, switch_sounds_random) { 1: SOUND_CAR_HORN_2; 5: CB_RESULT_NO_SOUND;}But that just results in no running sound. Not entirely sure what I'm meant to be doing and I couldn't find any examples to guide me, so I'd be most grateful for any help steering me in the right direction! Calling it a day for now, will take another stab at this tomorrow.
As I understand it, such a switch would only be called once - maybe when the vehicle is built or maybe even when the game starts, I don't know. There would be nothing in the grf that would ask the switch again for a new random value, nor would it have a means to randomly be changing its value as it goes.

I would have thought there would be an in-built method for occasional sounds much like the electric arc visual effect, but maybe not - in that case you'll need something to occasionally trigger your switch and get a new value I assume.
Supercheese
Tycoon
Tycoon
Posts: 1660
Joined: 16 Dec 2007 22:24
Location: Idaho, USA

Re: PaulC's NML questions

Post by Supercheese »

You can make use of the animation_counter variable to trigger sound effects at set intervals.

For instance:

Code: Select all

switch (FEAT_ROADVEHS, SELF, sirenloop1_switch, animation_counter % 32) {
	0..15:			return sound("sirenloop1.wav");
	16..31:			return CB_RESULT_NO_SOUND;
	CB_FAILED;
}
Combine with a random switch, and you can make things a bit stochastic.
Eyecandy Road Vehicles | Fake Subways | Supercheese's NewObjects

"Fashions and cultures change, but steam trains shall always be majestic."
-Professor Hershel Layton
User avatar
PaulC
Director
Director
Posts: 616
Joined: 31 Jul 2006 12:40
Location: Lancs, England
Contact:

Re: PaulC's NML questions

Post by PaulC »

Thanks for the replies chaps, unfortunately I still haven't managed to crack it. I've adapted Supercheese's switch to make the vehicle play a sound at regular intervals, and I had no trouble combining it with my other switch. It all seems to come unstuck when I try and throw in a random switch. This is the switch combination I ended up with:

Code: Select all

random_switch(FEAT_ROADVEHS, SELF, switch_random_sound, TRIGGER_VEHICLE_32_CALLBACK) {
	1: SOUND_CAR_HORN_2;
	7: CB_RESULT_NO_SOUND;
}

switch(FEAT_ROADVEHS, SELF, switch_car_horn_2, animation_counter % 64) {
	0..1:		return switch_random_sound;
	2..63:	return CB_RESULT_NO_SOUND;
	CB_FAILED;
}

switch(FEAT_ROADVEHS, SELF, switch_sound_effect, getbits(extra_callback_info1, 0, 8)) {
	SOUND_EVENT_START: SOUND_CAR_HORN;
	SOUND_EVENT_RUNNING: switch_car_horn_2;
}
Which is clearly wrong as the vehicle makes no sound when running. It's a non-essential feature though so I'm tempted to skip it and move on, there's only so long I can spend bashing my head against a wall. :?
User avatar
Gwyd
Chief Executive
Chief Executive
Posts: 721
Joined: 17 Apr 2017 16:52
Location: Western Ile-de-France Region

Re: PaulC's NML questions

Post by Gwyd »

Try playing with parent/self
User avatar
PaulC
Director
Director
Posts: 616
Joined: 31 Jul 2006 12:40
Location: Lancs, England
Contact:

Re: PaulC's NML questions

Post by PaulC »

Thanks for the tip. I've played around with it a bit more but still can't crack it so I'm going to set it aside for now, hopefully I can come back to it when I have a better idea of what I'm doing. I do appreciate the help though, it's all been very useful! :)

Some more questions:

1) I've coded up the disaster ufos as playable vehicles, which is rather fun! Currently I've done this by reusing the sprites from the base set, but is there any way I can leave out the sprites and just reference sprite numbers instead? Or is that not possible with vehicles?

2) I've set the following properties:

Code: Select all

misc_flags:	bitmask(AIRCRAFT_FLAG_NO_BREAKDOWN_SMOKE);
sound_effect:	SOUND_MAGLEV;
I think I've done this right but neither works: I still get breakdown smoke and the default helicopter sound. I can change the sound by using the callback instead (though the property should work, yes?) but otherwise this has me stumped. Am I missing something?

3) Is it not possible to reference a switch from a spritegroup? I'm guessing not since NML didn't like it but this seems rather limiting.
User avatar
Gwyd
Chief Executive
Chief Executive
Posts: 721
Joined: 17 Apr 2017 16:52
Location: Western Ile-de-France Region

Re: PaulC's NML questions

Post by Gwyd »

1: I don't know.
2: Try doing visual_effect: return 0 in callbacks for the no breakdown smoke.
I'd call sounds through the callbacks.
3: Explain more.
User avatar
PaulC
Director
Director
Posts: 616
Joined: 31 Jul 2006 12:40
Location: Lancs, England
Contact:

Re: PaulC's NML questions

Post by PaulC »

Gwyd wrote:2: Try doing visual_effect: return 0 in callbacks for the no breakdown smoke.
Hmm, visual_effect callback is only available for rvs and ships, there doesn't seem to be an equivalent for aircraft...
3: Explain more.
I have a switch which I'm using to show an alternative spriteset when the vehicle is broken down:

Code: Select all

switch(FEAT_AIRCRAFT, SELF, switch_small_ufo_bd, vehicle_is_broken) {
	0:	spriteset_small_ufo_mv;
	1:	spriteset_small_ufo_bd;
}
This works fine when I reference it from the graphics block. But then I tried throwing in a third spriteset for when the vehicle is loading which (so far as I can tell) requires a spritegroup, hence:

Code: Select all

spritegroup spritegroup_small_ufo {
	loading:	spriteset_large_ufo_st;
	loaded:	switch_small_ufo_bd;
}
But nml didn't like that, it says:

Code: Select all

@[Knmlc ERROR: "ogfx_ufo.nml", line 68: Expected a sprite set reference
Maybe I'm just going about it wrong?
User avatar
Kaaskroket
Engineer
Engineer
Posts: 10
Joined: 14 Sep 2017 11:59

Re: PaulC's NML questions

Post by Kaaskroket »

PaulC wrote:Thanks for the tip. I've played around with it a bit more but still can't crack it so I'm going to set it aside for now, hopefully I can come back to it when I have a better idea of what I'm doing. I do appreciate the help though, it's all been very useful! :)

Some more questions:

1) I've coded up the disaster ufos as playable vehicles, which is rather fun! Currently I've done this by reusing the sprites from the base set, but is there any way I can leave out the sprites and just reference sprite numbers instead? Or is that not possible with vehicles?

2) I've set the following properties:

Code: Select all

misc_flags:	bitmask(AIRCRAFT_FLAG_NO_BREAKDOWN_SMOKE);
sound_effect:	SOUND_MAGLEV;
I think I've done this right but neither works: I still get breakdown smoke and the default helicopter sound. I can change the sound by using the callback instead (though the property should work, yes?) but otherwise this has me stumped. Am I missing something?

3) Is it not possible to reference a switch from a spritegroup? I'm guessing not since NML didn't like it but this seems rather limiting.
Maybe there are different ways to replace the default sound for helicopter-type vehicles which I don't know about but I've managed to do it by setting the sound property to a sound switch in the vehicle's graphics block instead of the property block. Example:

Code: Select all

switch(FEAT_AIRCRAFT, SELF, switch_hot_air_balloon_sound, getbits(extra_callback_info1, 0, 8)) {
    SOUND_EVENT_START: sound("sfx/balloon.wav");
}
...
...
...
item(FEAT_AIRCRAFT, item_fire_nation_balloon) {
	property {
	...
	}
	graphics {
 	default: spriteset_fire_nation_balloon;
		additional_text:	string(STR_ORIGIN, string(STR_ORIGIN_AVATAR), string(STR_INSPIRATION), string(STR_LEEG));
		sound_effect:		switch_hot_air_balloon_sound;
		rotor: 				no_rotor; //empty spriteset
}
Afaik it isn't possible to use a switch in a spritegroup. Haven't tried this snippet yet but it might solve your problem:

Code: Select all

switch(FEAT_AIRCRAFT, SELF, switch_small_ufo_bd, vehicle_is_broken) {
   0:   spritegroup_small_ufo;
   1:   spriteset_small_ufo_bd;
}

spritegroup spritegroup_small_ufo {
   loading:   spriteset_small_ufo_st;
   loaded:   spriteset_small_ufo_mv;
}
User avatar
PaulC
Director
Director
Posts: 616
Joined: 31 Jul 2006 12:40
Location: Lancs, England
Contact:

Re: PaulC's NML questions

Post by PaulC »

Kaaskroket wrote:Afaik it isn't possible to use a switch in a spritegroup. Haven't tried this snippet yet but it might solve your problem:
Worked a treat, thanks for the tip! :)
User avatar
PaulC
Director
Director
Posts: 616
Joined: 31 Jul 2006 12:40
Location: Lancs, England
Contact:

Re: PaulC's NML questions

Post by PaulC »

Right, I have another question... :) What's the best way to go about refitting? I have a vehicle which I want to carry goods (by default) but also be refittable to mail, food and alcohol. These are the relevant bits of code I'm using to do that:

Code: Select all

cargotable {
	BEER, // Beer
	FISH, // Fish
	FRUT, // Fruit
	GOOD // Goods
}

	refittable_cargo_classes:	bitmask(CC_EXPRESS, CC_MAIL, CC_REFRIGERATED);
	non_refittable_cargo_classes:	bitmask(CC_BULK, CC_LIQUID, CC_OVERSIZED, CC_PASSENGERS, CC_PIECE_GOODS);
	cargo_allow_refit:		[BEER];
	cargo_disallow_refit:		[FISH, FRUT];
	default_cargo_type:		GOOD;
The above does what I want but I don't know if it looks good, there seem to be a number of different ways to go about doing the same thing. If I'm reading it right, NMLTutorial/Cargotable seems to be suggesting that I include all known cargo labels in my table and specify each one individually with the allow/disallow properties. Is that right? It seems a bit longwinded.
User avatar
supermop
Tycoon
Tycoon
Posts: 1104
Joined: 21 Feb 2010 00:15
Location: Fitzroy North - 96

Re: PaulC's NML questions

Post by supermop »

PaulC wrote:Right, I have another question... :) What's the best way to go about refitting? I have a vehicle which I want to carry goods (by default) but also be refittable to mail, food and alcohol. These are the relevant bits of code I'm using to do that:

Code: Select all

cargotable {
	BEER, // Beer
	FISH, // Fish
	FRUT, // Fruit
	GOOD // Goods
}

	refittable_cargo_classes:	bitmask(CC_EXPRESS, CC_MAIL, CC_REFRIGERATED);
	non_refittable_cargo_classes:	bitmask(CC_BULK, CC_LIQUID, CC_OVERSIZED, CC_PASSENGERS, CC_PIECE_GOODS);
	cargo_allow_refit:		[BEER];
	cargo_disallow_refit:		[FISH, FRUT];
	default_cargo_type:		GOOD;
The above does what I want but I don't know if it looks good, there seem to be a number of different ways to go about doing the same thing. If I'm reading it right, NMLTutorial/Cargotable seems to be suggesting that I include all known cargo labels in my table and specify each one individually with the allow/disallow properties. Is that right? It seems a bit longwinded.

My approach is to specify the classes that I want to allow and disallow, and then only use the specific labels for exceptions, or cases where a cargo might have some confusing classes assigned to it.
User avatar
PaulC
Director
Director
Posts: 616
Joined: 31 Jul 2006 12:40
Location: Lancs, England
Contact:

Re: PaulC's NML questions

Post by PaulC »

supermop wrote:My approach is to specify the classes that I want to allow and disallow, and then only use the specific labels for exceptions, or cases where a cargo might have some confusing classes assigned to it.
I guess that's more or less what I'm already doing. I'll probably just stick with it then...
Eddi
Tycoon
Tycoon
Posts: 8254
Joined: 17 Jan 2007 00:14

Re: PaulC's NML questions

Post by Eddi »

PaulC wrote:Then I tried combining this with a random switch which I hoped woud at least make the sound intermittant:

Code: Select all

random_switch(FEAT_ROADVEHS, SELF, switch_sounds_random) {
	1: SOUND_CAR_HORN_2;
	5: CB_RESULT_NO_SOUND;
}
But that just results in no running sound.
Just chiming in to explain why this doesn't work:

a random switch is based upon random bits which are stored in the vehicle and initialized at vehicle construction, and then always result in the same choice. this is meant for example for picking a random colour. so what this switch does is you have a 1 in 6 chance that a vehicle makes sound all the time, or 5 in 6 that it does no sound, ever. there are also "triggers" to reinitialize the random bits, but those are a bit tricky to use if your random switch is not in the default graphics chain. (there's a special callback for that). even then, that will result in periods of making sound all the time and making no sound, depending on how often this trigger callaback is called, so the other method with using the motion counter is probably also needed
Eddi
Tycoon
Tycoon
Posts: 8254
Joined: 17 Jan 2007 00:14

Re: PaulC's NML questions

Post by Eddi »

PaulC wrote:Right, I have another question... :) What's the best way to go about refitting? I have a vehicle which I want to carry goods (by default) but also be refittable to mail, food and alcohol. These are the relevant bits of code I'm using to do that:

Code: Select all

	non_refittable_cargo_classes:	bitmask(CC_BULK, CC_LIQUID, CC_OVERSIZED, CC_PASSENGERS, CC_PIECE_GOODS);
you should be a bit careful with explicitly listing classes that are not refittable, because you easily run into cases where a cargo with two classes cannot be transported with any vehicle. most of the times you can get away with leaving this property empty
Post Reply

Return to “NewGRF Technical Discussions”

Who is online

Users browsing this forum: No registered users and 1 guest