FlameThrower: Proposed Modification

FlameThrower: Proposed Modification

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

FlameThrower: Proposed Modification

Post by Argh »

I'm going to go ahead and post this here, to get some feedback before I write a patch (now that I can do that).

Basically, I'm thinking that I'll do a very gentle change to the current FlameProjectile code, used for flamethrowers.

Right now, it's pretty cool- it uses Texture1, so we can actually have pretty nice-looking flames. However, I still think it can be improved more. Here's what I'm proposing to do.

After looking at the code, I think it would be very easy to have FlameProjectiles use RGBColor and RGBColor2. These two variables already have default values, so any WeaponProjectile can use them already, and not defining them won't cause problems.

Basically, here's what the current code for color, that changes it from almost-white to almost black red looks like. Forgive the paraphrasing- I'm at work, so I don't have the source in front of me:

Code: Select all

PSEUDOCODE
If TicksAlive<=33
Then Color = (1, 1, 0.8)

If TicksAlive>33 && TicksAlive <67
Then Color = (1, 0.5, 0.3)

If TicksAlive>=67
Then Color = (0.3, 0.1, 0)
As you can (hopefully) see, this makes the color go from bright near-white to a strong orange-red to a very dark red, in three steps.

What I'd like to do is make it like this:

Code: Select all

PSEUDOCODE
If TicksAlive<=33
Then Color = RGBColor

If TicksAlive>33 && TicksAlive <67
Then Color = ((RGBColor + RGBColor2) / 2)

If TicksAlive>=67
Then Color = RGBColor2
As you can (again, hopefully) see, this would allow for user-controlled colors for the FlameThrower, and it would average RGBColor and RGBColor2 during the "mid-phase", meaning it would dynamically change color.

Why do I want this?

1. You could have a shotgun that acted true to physics, because the FlameProjectile already grows and has a hitsphere that grows also. It'd be simple- just make a graphic with alpha channel depicting the spray, and then don't do a lot of color-shifting between RGBColor and RGBColor2.

2. You could have "acid sprays", "freeze guns", and other things that need different colors than, er... fire.

3. If we ever get to the point where we can call these Projectiles as part of scripting events or custom ExplosionGenerators... hmm... we have a pretty decent particle spray-cone right here, waiting to happen. Blood, anybody? Oil spurting from ruptured hydraulics? Splashes of bright white metallic sparks? Hmm... yeah, that sounds good to me, too ;)

4. If we simply stated a SizeGrowth of 0, or nearly 0(one of the new values we have to play with, specifically for FlameThrowers, and it's pwawesome) then we could have things like "plasma beams", where the shots changed color over time/distance but didn't change size much, if at all- or even... shrank! The value is a float, so I don't see why it couldn't shrink just offhand...

At any rate, I'm posting this here before I write a patch. This should be a very simple, lightweight addition to the current FlameProjectile code- it'll add just a couple more math steps. The variables are already there, and the values are already in memory (thank goodness for all that modder-friendly default value code!) so I do not foresee this will be a performance problem at all.

But there is one small hitch: all current mods using flamethrowers would need to set up RGBColor and RGBColor2, to still keep their flames looking "right". The default values for these things would look very weird. Is anybody really convinced that adding these two lines would be a big, hairy deal, or can I write this patch, show it working, and submit it to Spring's developers for commit- probably not in 0.73b, as it's technically a new feature, not a bugfix, but meh, we're talking teenie-weenie code here, for big results.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

I am hoping that the lack of replies means nobody is, ah, "flaming mad" at this proposed change? Heh, couldn't resist.

Here's the code. Yes, I'm so nerdy that even though I'm at work, I figured how to get to the current source, find this and write a patch ;) It's really bloody simple, though- I changed very few lines of the current code.

Code: Select all

#include "StdAfx.h"
#include "FlameProjectile.h"
#include "Rendering/GL/VertexArray.h"
#include "Game/Camera.h"
#include "Map/Ground.h"
#include "mmgr.h"
#include "ProjectileHandler.h"
#include "Sim/Weapons/WeaponDefHandler.h"

CFlameProjectile::CFlameProjectile(const float3& pos,const float3& speed,const float3& spread,CUnit* owner,const DamageArray& damages, WeaponDef *weaponDef, int ttl)
: CWeaponProjectile(pos,speed,owner,0,ZeroVector,weaponDef,damages,0),
	spread(spread),
	curTime(0)
{
	invttl=1.0/ttl;

	//SetRadius(speed.Length()*0.9);
	SetRadius(weaponDef->size);
}

CFlameProjectile::~CFlameProjectile(void)
{
}

void CFlameProjectile::Collision(void)
{
	float3 norm=ground->GetNormal(pos.x,pos.z);
	float ns=speed.dot(norm);
	speed-=norm*ns*1;
	pos.y+=0.05;
	curTime+=0.05;
}

void CFlameProjectile::Collision(CUnit* unit)
{
//	unit->DoDamage(damages*(1-curTime*curTime),owner);
	CWeaponProjectile::Collision(unit);
}

void CFlameProjectile::Update(void)
{
	pos+=speed;
	speed+=spread;

	SetRadius(radius+weaponDef->sizeGrowth);

	curTime+=invttl;
	if(curTime>1){
		curTime=1;
		deleteMe=true;
	}
}

void CFlameProjectile::Draw(void)
{
	inArray=true;
	unsigned char col[4];
	if(curTime<0.33333){
		col[0]=(unsigned char) (color.x);
		col[1]=(unsigned char) (color.y);
		col[2]=(unsigned char) (color.z);
	} else if(curTime<0.66666){
		col[0]=(unsigned char) ((color.x+color2.x)/2);
		col[1]=(unsigned char) ((color.y+color2.y)/2);
		col[2]=(unsigned char) ((color.z+color2.z)/2);
	} else {
		col[0]=(unsigned char) (color.x);
		col[1]=(unsigned char) (color.y);
		col[2]=(unsigned char) (color.z);
	}
	col[3]=1;//(0.3-curTime*0.3)*255;

	float3 interPos=pos+speed*gu->timeOffset;
		va->AddVertexTC(interPos-camera->right*radius-camera->up*radius,weaponDef->visuals.texture1->xstart ,weaponDef->visuals.texture1->ystart ,col);
		va->AddVertexTC(interPos+camera->right*radius-camera->up*radius,weaponDef->visuals.texture1->xend ,weaponDef->visuals.texture1->ystart ,col);
		va->AddVertexTC(interPos+camera->right*radius+camera->up*radius,weaponDef->visuals.texture1->xend ,weaponDef->visuals.texture1->yend ,col);
		va->AddVertexTC(interPos-camera->right*radius+camera->up*radius,weaponDef->visuals.texture1->xstart ,weaponDef->visuals.texture1->yend ,col);
}
Last edited by Argh on 04 Sep 2006, 21:57, edited 1 time in total.
User avatar
Decimator
Posts: 1118
Joined: 24 Jul 2005, 04:15

Post by Decimator »

Frankly, as long as the modders are notified that their flamethrowers are going to be broken, I see no reason why this shouldn't be implemented. Flexibility is goooood.
User avatar
Snipawolf
Posts: 4357
Joined: 12 Dec 2005, 01:49

Post by Snipawolf »

Acid sprays
Argh, you continue to amaze me... I am going to have aliens spit some kinda acid out at close range, this kinda finalized the idea :-)
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Okie doke, I'll do it then. I see no reason to worry about breaking mods on this one, the benefits are so large, and fixing it is so trivial...
User avatar
Maelstrom
Posts: 1950
Joined: 23 Jul 2005, 14:52

Post by Maelstrom »

If i read this right, does the colour change in three steps? RGB1, half way between RGB1 and 2, then RGB2? Why not have a nice smooth transition?

Code: Select all

col[0]=(unsigned char) (((color2.x - color.x)*curTime)+color.x);
col[1]=(unsigned char) (((color2.y - color.y)*curTime)+color.y);
col[2]=(unsigned char) (((color2.z - color.z)*curTime)+color.z);
Makes more sense to me...
User avatar
ILMTitan
Spring Developer
Posts: 410
Joined: 13 Nov 2004, 08:35

Post by ILMTitan »

I was thinking about the same thing as Maelstrom. Also,

Code: Select all


      col[0]=(unsigned char) ((color.x*color2.x)/2);
      col[1]=(unsigned char) ((color.y*color2.y)/2);
      col[2]=(unsigned char) ((color.z*color2.z)/2); 
should be

Code: Select all


      col[0]=(unsigned char) ((color.x+color2.x)/2);
      col[1]=(unsigned char) ((color.y+color2.y)/2);
      col[2]=(unsigned char) ((color.z+color2.z)/2); 
I know you knew that, but if you pasted from you code, it was wrong there.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

Sounds like a useful addition.

If we really don't want to break existing mods it could be an idea to have different default rgbcolor & rgbcolor2 for flamethrower weapons, but that would be yet another hack in the WeaponDefHandler...

Could you make a 'real' patch tho, Argh? ie. in e.g. TortoiseSVN right click->Tortoise->Create patch.
User avatar
krogothe
AI Developer
Posts: 1050
Joined: 14 Nov 2005, 17:07

Post by krogothe »

Argh becomes more and more awesome each day!
Tbh breaking mods is a necessary step for evolution. I know a release is good when it breaks the AI interface, meaning lots of new goodies, instead of some hacky HandleCommand stuff...
Now if only someone would work on a generic scripting system that integrated upgrades, construction, LOS etc...
Crampman
Posts: 117
Joined: 22 Dec 2005, 12:17

Post by Crampman »

I'm probably wrong, but I think that a fully-customizable particle-based system should allow max flexibility.

I've studied a particle engine, and modified it : we should need such tags

Code: Select all

lifetime=1; // Life time of particles
sprite=flame01.tga; // Particles picture
startsize=1; // Initial size of the particles
endsize=0; // Final size of the particles
startalpha=1; // Initial transparency of the particles
endalpha=0; // Final transparency of the particles
speed=1 0 0; // Initial speed of the particles (x y z)
acceleration=0 0 0; // Acceleration of the particle (x y z)
sprayrate=0.1; // Rate of paticle spray (Interval between two particle emissions)
sprayduration=2; // Duration of the spray
startangle=0; //Initial rotation of the particles
angledelta=5: // rotation speed of the particles

startred=1; /More colors control
endred=0;
startgreen=1;
endgreen=1;
startblue=0;
endblue=0;

With such tags, used in tds files like the custom explosions, we could do lots of fx effects, not only flamethrowers or acid spray. If they could be also used by scripts, that would be also better.
User avatar
Caydr
Omnidouche
Posts: 7179
Joined: 16 Oct 2004, 19:40

Post by Caydr »

Decimator wrote:Frankly, as long as the modders are notified that their flamethrowers are going to be broken, I see no reason why this shouldn't be implemented. Flexibility is goooood.
Flamethrowers are already "broken" by the new version. Without modder adjustment, they look pretty nasty, at least in the dev build I've got.
User avatar
jcnossen
Former Engine Dev
Posts: 2440
Joined: 05 Jun 2005, 19:13

Post by jcnossen »

Someone could make a projectile class that supports what Crampman posted...
If you register it with CR_DECLARE it automatically becomes avaiable for use in an explosion generator.
User avatar
krogothe
AI Developer
Posts: 1050
Joined: 14 Nov 2005, 17:07

Post by krogothe »

Dont forget to add a bool to say if its affected by gravity! (or even better, a float, so things can sink fast, slow or float towards the sky!), though thats more for smoke effects etc
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

@Tobi: Yes, I'll make a real patch, like I did for the other stuff...
User avatar
Weaver
Posts: 644
Joined: 07 Jul 2005, 21:15

Post by Weaver »

krogothe wrote:Dont forget to add a bool to say if its affected by gravity! (or even better, a float, so things can sink fast, slow or float towards the sky!), though thats more for smoke effects etc
Buoyancy?

1 = Normally buoyant ie. as buoyant (in air) as a rock!

0 = Neutral bouyancy , nicely floaty

-1 = Helium balloon.


Low density things that float well also tend to have low terminal velocity, moving with the wind.

10,000m high smoke stacks over burning bases anyone?

Am I making sense, is any of this possible?
Crampman
Posts: 117
Joined: 22 Dec 2005, 12:17

Post by Crampman »

The particle engine I've studied, long ago, was a part of 'Spirit', a Half-life mod. I've still the source, but I couldn't adapt it to Spring.

Concerning the tags : indeed, some tags to control wind/gravity effects should de added, using multipliers parameters, like :

Code: Select all

windeffect=0;
gravityeffect=0.5;
Another point that should be nice would to add a random possibility.
A good way to include it is to use two dots, '..', to define a range, wich will be used to generate the value :

Code: Select all

tag=0..10; // Tag is a random value, and will be choosen between 0 and 10
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

@ILMTitan: LOL... was at work, not paying sufficient attention to my math. I've corrected the patch code above. I will be submitting this as a patch tonight.


@Crampman, etc.:

1. I do not understand Spring well enough, nor am I a skilled-enough C++ coder (I mean, gosh, I just learned how to compile on Saturday, lol) to expect much from me. So don't get your hopes up- aside from these two patches, I may not do anything else- there's a lot've Spring that's incomprehensible to me still.

Plus I have a mod to maintain and a few features I want to get tightened down before 0.73's release, if at all possible. I don't really have any intention of joining Spring's team as a serious member- I really lack the qualifications to tackle any of the serious coding, and my knowledge of C++ is extremely rudimentary (at least it's a lot like BOS, which was based on C... so it's not completely foreign).

In short, I'm just nibbling at areas of particular interest to me, that aren't too hard to code- I am in no way qualified to build us a new scripting engine, put a new collision system into place, or any of the other things that might be very cool, but also require a great deal of very hard math or knowledge of the coding side of 3D game engines. I'm pretty smart, but... this really isn't my area of expertise!

2. That said, I am thinking, fairly seriously, about re-arranging the weapon code and finally making it rational. This is something that I think I can handle- the code here is fairly easy to read, contains very little math that is really complex, and is somewhat organized already.

Right now, it contains multiple scenarios that are not clearly mutually-exclusive... and other irrationalities that can and should be corrected.

Adding whole new Projectiles that can be used for weapons should be very easy but it's not, right now, due to the way that things were coded. Most of the existing code is very efficient (don't get me wrong, I'm not knocking SJ here) but it's arranged in ways that aren't best for future features, and I personally think there are some sections that should be seperated out into their own Functions and called through weapon's class definition, instead of being in the default code. This is about 50% done, and I'm not even sure how much of it was done on purpose, and how much was just pure need at the time.

Doing so would have very serious implications for mods, and would need to be debated, publically. Basically, we need to have mods use a uniform identifier for all of their weapons. Instead of having mutually-exclusive cases and scenarios, and a whole lot of "checker" code that determines what a weapon is, based on its properties... we need to have simple, straightforward declarations (and, of course, a modder-safe default value).

So, instead of the mess of conditions that are currently used, we'd just have a declaration like this:

WeaponType=BeamWeapon;

... and after that, only certain conditions would be applied- anything that was outside the scope of the weapon's definition would be ignored, right away. The code we have right now achieves this goal, but it is very messy, because previous folks have been trying to maintain backwards-compatibility.

I think it's time to move on, and to use something cleaner, that will be easier to add new weapon classes to. There are a lot of weapons that aren't currently in Spring, and I feel that it'd be better to clean this mess up now, rather than just keep adding new junk to the code that currently checks through a weapon's class.

But moving to what I'm proposing will basically break the vast majority of mods, until they're repaired by modders. It's a necessary-but-painful thing. Before I even start putting this together, I feel that we should get input on all of this, and see whether the benefits (being able to code new weapon types into Spring very easily, transparency of new code additions, ease of maintenance, and clearer standards) will outweigh the obvious problem of modders having to go through their lists of weapons for a few hours and fix things. Personally, I don't think it's much of a price to pay for the benefits down the road.
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

I like that but then again I'm not one of the people running a 300+ units mod.
User avatar
Acidd_UK
Posts: 963
Joined: 23 Apr 2006, 02:15

Post by Acidd_UK »

Good work Argh :-)
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Post by Argh »

Drat and befuddlement! I can't get the FlameProjectile code to work! I keep getting following error message when trying to compile:
..\..\Sim\Weapons\FlameThrower.cpp(27) : error C2661: 'CFlameProjectile::CFlameProjectile' : no overloaded function takes 7 arguments
None of the things on MSDN or that I could look up on Google helped me out with this. I am apparantly too much of a C++ newbie to understand what an "overloaded function" is, or why it won't take "7 arguments". <sighs> I thought this would be pretty simple, but noooooooo.

Anyways... I figured that maybe someone here would probably see the problem immediately, because it's almost certainly something dumb. If anybody would be kind enough to fix this code, I would be ever-so-thankful, as this patch really would add a lot've new functionality... oh, and I might get a better explanation as to what went wrong, too, by seeing the solution :P

Here's my header:

Code: Select all

#ifndef __FLAME_PROJECTILE_H__
#define __FLAME_PROJECTILE_H__

#include "WeaponProjectile.h"
#include "Sim/Misc/DamageArray.h"

class CFlameProjectile :
	public CWeaponProjectile
{
public:
	CFlameProjectile(const float3& pos,const float3& speed,const float3& spread,CUnit* owner,const DamageArray& damages,const float3& color,const float3& color2,WeaponDef *weaponDef,int ttl=50);
	~CFlameProjectile(void);
	float3 color;
	float3 color2;
	float3 spread;
	float curTime;
	float invttl;
	void Update(void);
	void Draw(void);
	void Collision(CUnit* unit);
	void Collision(void);
	int ShieldRepulse(CPlasmaRepulser* shield, float3 shieldPos, float shieldForce, float shieldMaxSpeed);
};

#endif // __FLAME_PROJECTILE_H__

And here's the main source:

Code: Select all

#include "StdAfx.h"
#include "FlameProjectile.h"
#include "Rendering/GL/VertexArray.h"
#include "Game/Camera.h"
#include "Map/Ground.h"
#include "mmgr.h"
#include "ProjectileHandler.h"
#include "Sim/Weapons/WeaponDefHandler.h"

CFlameProjectile::CFlameProjectile(const float3& pos,const float3& speed,const float3& spread,CUnit* owner,const DamageArray& damages,const float3& color,const float3& color2,WeaponDef *weaponDef,int ttl)
: CWeaponProjectile(pos,speed,owner,0,ZeroVector,weaponDef,damages,0),
color(color),
color2(color2),
spread(spread),
curTime(0)
{
	invttl=1.0/ttl;
	SetRadius(weaponDef->size);
}

CFlameProjectile::~CFlameProjectile()
{
                                     
}

void CFlameProjectile::Collision(void)
{
	float3 norm=ground->GetNormal(pos.x,pos.z);
	float ns=speed.dot(norm);
	speed-=norm*ns*1;
	pos.y+=0.05;
	curTime+=0.05;
}

void CFlameProjectile::Collision(CUnit* unit)
{
	CWeaponProjectile::Collision(unit);
}

void CFlameProjectile::Update(void)
{
	pos+=speed;
	speed+=spread;

	SetRadius(radius+weaponDef->sizeGrowth);

	curTime+=invttl;
	if(curTime>1){
		curTime=1;
		deleteMe=true;
	}
}

void CFlameProjectile::Draw(void)
{
   inArray=true;
   unsigned char col[4];
   if(curTime<0.33333){
      col[0]=(unsigned char) (color.x*255);
      col[1]=(unsigned char) (color.y*255);
      col[2]=(unsigned char) (color.z*255);
   } else if(curTime<0.66666){
      col[0]=(unsigned char) (((color.x+color2.x)/2)*255);
      col[1]=(unsigned char) (((color.y+color2.y)/2)*255);
      col[2]=(unsigned char) (((color.z+color2.z)/2)*255);
   } else {
      col[0]=(unsigned char) (color2.x*255);
      col[1]=(unsigned char) (color2.y*255);
      col[2]=(unsigned char) (color2.z*255);
   }
   col[3]=1;

   float3 interPos=pos+speed*gu->timeOffset;
   va->AddVertexTC(interPos-camera->right*radius-camera->up*radius,weaponDef->visuals.texture1->xstart ,weaponDef->visuals.texture1->ystart ,col);
   va->AddVertexTC(interPos+camera->right*radius-camera->up*radius,weaponDef->visuals.texture1->xend ,weaponDef->visuals.texture1->ystart ,col);
   va->AddVertexTC(interPos+camera->right*radius+camera->up*radius,weaponDef->visuals.texture1->xend ,weaponDef->visuals.texture1->yend ,col);
   va->AddVertexTC(interPos-camera->right*radius+camera->up*radius,weaponDef->visuals.texture1->xstart ,weaponDef->visuals.texture1->yend ,col);
}

int CFlameProjectile::ShieldRepulse(CPlasmaRepulser* shield,float3 shieldPos, float shieldForce, float shieldMaxSpeed)
{
	float3 dir=pos-shieldPos;
	dir.Normalize();
	if(dir.dot(speed)<shieldMaxSpeed){
		speed+=dir*shieldForce;
		return 2;
	}
	return 0;
}
Post Reply

Return to “Engine”