Page 1 of 1

PaulC's NML questions

Posted: 28 Jan 2018 03:25
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.

Re: PaulC's NML questions

Posted: 28 Jan 2018 03:31
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.

Re: PaulC's NML questions

Posted: 28 Jan 2018 07:18
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.

Re: PaulC's NML questions

Posted: 31 Jan 2018 09:03
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. :?

Re: PaulC's NML questions

Posted: 31 Jan 2018 15:50
by Gwyd
Try playing with parent/self

Re: PaulC's NML questions

Posted: 03 Feb 2018 17:58
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.

Re: PaulC's NML questions

Posted: 03 Feb 2018 18:55
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.

Re: PaulC's NML questions

Posted: 03 Feb 2018 19:32
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?

Re: PaulC's NML questions

Posted: 03 Feb 2018 21:19
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;
}

Re: PaulC's NML questions

Posted: 04 Feb 2018 00:52
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! :)

Re: PaulC's NML questions

Posted: 11 Feb 2018 11:16
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.

Re: PaulC's NML questions

Posted: 11 Feb 2018 16:05
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.

Re: PaulC's NML questions

Posted: 13 Feb 2018 23:01
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...

Re: PaulC's NML questions

Posted: 13 Apr 2018 16:28
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

Re: PaulC's NML questions

Posted: 13 Apr 2018 16:37
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