Creating new types of gaseous clouds

We were thinking about creating a new chemical sprayer type weapon to combat the fungus with sprayable fungicide or other chemicals.

How difficult would it be to implement new gases? I picture the weapon working similar to the flame thrower in that it creates a 3x3 aoe of ‘fungicide gas’ which then spreads like toxic gas or smoke would, albeit not dissipating as fast and only affecting fungus-type enemies and terrain. So it would, for example, remove fungal beds and kill off fungal entities.

I haven’t really coded in the last couple of years and seeing how well the process is documented, I’m actually quite eager to get my hands on contributing. Would this endeavour be too hard for a ‘beginner project’? :wink:

Lastly, where would the changes have to be made? Can this be done via JSONs only or would it require a deeper modification of the code?

Pretty simple.

You’d need to declare the gas itself in field.h, then implement it in field.cpp. Somewhere on the top of field.cpp there are definitions of different fields (gases are fields). You’d need to add your gas there. Then add handling for it in the “big switch” around the middle of the file. For handling, you’ll want just the spread_gas with parameters, like toxic gas has. You can just search for fd_toxic and copy the code.
Then in player/monster_in_field you’d implement the appropriate effects on creatures.

That’s for gas itself. For the weapon, you have two different ways of handling it: one would be to create a grenade-type item by copying acid bomb code (in iuse.h, iuse.cpp and item_factory.cpp), the other would be to implement an on-hit effect in damage.cpp.
Then create a new weapon/grenade that uses the appropriate functions. For grenade, you’d want to copy (and adjust, of course) the acid bomb. For flamethrower, you’d want to copy the flamethrower, gasoline and gasoline ammo type. Set the damage on the thrower and ammo to 0 - all guns are hardcoded to deal piercing damage now.

Oh wow, thanks <3

Can’t wait to try it out, once I find some spare time!

Been fiddling around with this for the last hour and so far I managed to create the gas and make it only damage monsters with the FUNGUS-species. I took the dmg and slowdown calculations from other fields :>

Now I also want to make the fungal beds and trees go away and replace the tile below with the original one if there is any value for that? Otherwise it would just have to be a random value for dirt or grass (or snow, I guess depending on the season?).

How do I access the terain on the tile? I thought I’d be able to get it via submap getters but I dont even know the corresponding IDs for the fungus infected terrain. Where would I get those?

Have not compiled anything yet.

	[...]
	fd_hot_air3,
	fd_hot_air4,
	fd_fungicidal_gas,
	num_fields
};
{
	"fd_fungicidal_gas",
	{_("hazy cloud"),_("fungicidal gas"),_("thick fungicidal gas")}, '8', 8,
	{c_white, c_ltgray, c_dkgray}, {true, true, false}, {false, true, true}, MINUTES(30),
	{0,0,0}
}

[...]

case fd_fungicidal_gas:
	dirty_transparency_cache = true;
	spread_gas( cur, p, curtype, 50, 30 );
break;

[...]

case fd_fungicidal_gas:
	// Fungicidal gas makes you cough.
	// Thick fungicidal gas has a chance to poison you.
	{
                bool inhaled = false;
                if( cur->getFieldDensity() == 3 && !inside ) {
                    inhaled = u.add_env_effect("poison", bp_mouth, 5, 30);
		} else if( cur->getFieldDensity() == 2 && !inside ) {
                    inhaled = u.add_env_effect("smoke", bp_mouth, 2, 7);
                } 
                if( inhaled ) {
                    // player does not know how the npc feels, so no message.
                    u.add_msg_if_player(m_bad, _("You feel sick from inhaling the %s"), cur->name().c_str());
                } 
            }
            break;

[...]

case fd_fungicidal_gas:
	if( z.type->in_species("FUNGUS") ) {
		const int density = cur->getFieldDensity();
		z.moves -= rng( 10 * density, 30 * density );
		dam += rng( 10, 15 * density );
	}

[quote=“skYman, post:4, topic:9910”]Now I also want to make the fungal beds and trees go away and replace the tile below with the original one if there is any value for that? Otherwise it would just have to be a random value for dirt or grass (or snow, I guess depending on the season?).

How do I access the terain on the tile? I thought I’d be able to get it via submap getters but I dont even know the corresponding IDs for the fungus infected terrain. Where would I get those?[/quote]

There is no way to get the original terrain - it isn’t really stored anywhere. Just changing it to dirt should be fine in most cases. Don’t set to grass or tree - the fungus kills plant life.

You can see flags being checked in fd_fire processing code. On the top of the fire processing code, you have terrain and furniture being accessed. Later you’ve got them being checked for FLAMMABLE flag. They are always checked with a helper function, which is declared in the same file.
In your case you want to check fungal terrain and furniture separately, because one of those can easily be non-fungal while the other one is.

Don’t check for terrain ids until you need exact ids. Check for flags where possible.

Okay I managed to make that work as well, thank you again.

Now where is the behaviour for the flamethrower defined? Ideally I would just copy the item and make it spit fungicidal gas instead of fire or an explosion.

Flamethrower works through ammo effects of the NAPALM ammo type. You need to create a fungicide ammo type and add a process for it to handle it that creates the field. I think the ammo type processing is in ranged.cpp

Found the ammo effects in map.cpp

I’m having trouble with the terrain conversion, though. How do I set the terrain/furniture of the current tile? There are getters but no setters as far as I have seen. Also, I found no flag for fungal terrain or furniture so I’d have to compare IDs. Or would it be easier to add a flag?

There’s ter_set, furn_set, and just plain set for settings terrain and furniture. Fungal terrain and furniture have the “FUNGUS” tag. It looks like you want damage.cpp for the ammo effect processing, I’m not sure if map.cpp is the right place for it.

The way I planned on implementing it, is that the gas doesnt do damage itself. It is more of a utilitarian appraoch so that only the field effects of the spreading gas take effect.

I therefore created a new ammo effect called STREAM_GAS in map.cpp that creates a certain amount of fungicidal-gas-fields at the target location and gave that effect to a new ammo type called gas_fungicidal which in turn is used by he new weapon chemical_thrower.

As I said: for gas explosion, you want to define the tag in damage.cpp

Stream effect should probably be in ranged.cpp, in the Creature::projectile_attack function.

I’m getting an (unrelated?) error when trying to compile with Code::Blocks13.12 using MinGW:

Did you change anything in item.cpp? I don’t think you need to touch that file at all. item_factory.cpp yes, but not item.cpp

If not, then you must have changed some header included by item.cpp. Probably a badly placed brace or a lack of comma.

Nope, didn’t touch item.cpp.

But the GitHub GUI thingy shows me several deletions and additions of the same line in field.cpp. Never touched them, though.

Should I just try and re-fork it and add my changes in again?

It’s probably better to keep going.

You could PR the whole deal with [WiP] in title. That way we could see the code and correct it way more easily.

Ok I think I managed to create a PR.

I’m currently at a dead end. I don’t know enough C++ to decipher the code without breaking my head.

The basic framework for the terrain alteration is in I’d say, unless there is a really smart way how one would go about that :wink:

I find this thread’s lack of fart jokes disturbing.

Now you know how i felt, everytime I came across ‘toxic_gas’ :>