Making a concussion grenade: Difference between revisions
No edit summary |
Thunder4ik (talk | contribs) |
||
(11 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
{{Multiple issues| | |||
== | {{Dead end|date=January 2024}} | ||
{{Orphan|date=January 2024}} | |||
{{cleanup}} | |||
}} | |||
Creating a grenade that will blind someone. | |||
= | <source lang=cpp>void CGrenadeConc::Detonate( void ) | ||
{ | { | ||
// An array for all the player pointers to chill | |||
CBaseEntity *list[1024]; | |||
// grab all of them within 400 units | |||
int count = UTIL_EntitiesInSphere(list,1024,GetAbsOrigin()+Vector(0,10,0),400,MASK_PLAYERSOLID); | |||
// for each of them | |||
for ( int i = 0; i < count; i++ ) | |||
{ | |||
// make sure its a player | |||
if (list[i]->IsPlayer()) | |||
{ | |||
// trace line to make | |||
trace_t tr; | |||
UTIL_TraceLine(list[i]->GetAbsOrigin(),GetAbsOrigin()+Vector(0,10,0),MASK_PLAYERSOLID, NULL, COLLISION_GROUP_NONE, &tr ); | |||
CBasePlayer *pPlayer = ToBasePlayer(list[i]); | |||
color32 white = { 255,255,255,255 }; | |||
if(tr.fraction == 1.0f) {UTIL_ScreenFade(pPlayer,white,CONC_FALLOFF_TIME,CONC_FADEHOLD, FFADE_IN);} | |||
} | |||
} | |||
BaseClass::Detonate(); | |||
}</source> | |||
}</ | |||
Drop that in your grenade .cpp and add this to the class definition | Drop that in your grenade .cpp and add this to the class definition | ||
< | <source lang=cpp>virtual void Detonate( void );</source> | ||
and these defines into up top | and these defines into up top | ||
< | <source lang=cpp>#define CONC_FALLOFF_TIME 20.0f | ||
#define CONC_FADEHOLD 3.0f</ | #define CONC_FADEHOLD 3.0f</source> | ||
There was a bug in the original code | <div style="padding:.5em;background:#DF6F6F;border:2px solid red;">There was a bug in the original code I posted here, where the grenade was actually blocking the flash. the fix is added here. | ||
< | <source lang=cpp>GetAbsOrigin()+Vector(0,10,0)</source> | ||
</div> | |||
<div style="padding:.5em;background:#DF6F6F;border:2px solid red;">There was a problem with the concussion effect not working when using it in the crossbow "BoltTouch" function and jumping while firing downwards. The problem was that the mask wasn't working properly. Fixed it by replacing MASK_SOLID with MASK_PLAYERSOLID. This fix has been implemented into the code on this page already. | |||
<source lang=cpp>MASK_SOLID replaced with MASK_PLAYERSOLID</source> | |||
</div> | |||
==Update 1== | ==Update 1== | ||
The question was posed... " | The question was posed... "How do you get the flash to deminish with distance?" | ||
The answer is simple | The answer is simple in theory... | ||
in | |||
#Find the distance the player is from the grenade | #Find the distance the player is from the grenade | ||
# | #Consider.. | ||
#*the 100% flash distance | #*..the 100% flash distance | ||
#*the 0% distance | #*..the 0% distance | ||
# | #Calculate and set alpha | ||
So let's do it really quick | |||
1 | ===Step 1=== | ||
We are going to tweak '''CGrenadeConc::Detonate( void )''' a bit. | |||
Basically, since we are changing the alpha of the fade, all calculations will be added at the marked location | |||
< | <source lang=cpp>CBasePlayer *pPlayer = ToBasePlayer(list[i]); | ||
// here is where our code will be going | // here is where our code will be going | ||
color32 white = { 255,255,255,255 };</ | color32 white = { 255,255,255,255 };</source> | ||
A simple line will take care of finding the distance... | |||
float distancesq = (pPlayer->GetAbsOrigin() - GetAbsOrigin()+Vector(0,10,0)).LengthSqr() | |||
===Step 2=== | |||
====Part A==== | |||
Considering the 100% flash distance is the next step. At what distance do we still want the character to be flashed? For this tutorial, the chosen distance is 200 inches. The sphere above makes that work out pretty well because 200 inches is about half the sphere's range. | |||
===Part B=== | |||
Consider the 0% distance. If 200 inches is 100%, a good 0% distance may be 400 inches. | |||
3 | ===Step 3=== | ||
For simplicitys sake, and code shortening, we start percent with 100%: | |||
float | float ratio = 1.0; | ||
Since we decided that 200 inches would be a good distance for 100%, let's make sure the distance is above or at that. We have a simple calculation to know what percentage of the flash to show. The distance is left squared to possibly avoid an unneeded square root... | |||
if ( | if (distancesq >= 40000) | ||
ratio = (200-(vec_t)FastSqrt(distancesq))/200.0; | |||
Distance is taken between the point of explosion and the character's location. | |||
We want a proportion of this flash, so we will use a ratio of a 100% opaque flash. | |||
color32 white = { 255,255,255,(255*ratio) }; | |||
color32 white = { 255,255,255,(255* | |||
==Update 2== | ==Update 2== | ||
It might also be better to have the flash hold change as well via the ratio. Here is the finished detonate function for comparison. | |||
< | <source lang=cpp>void CGrenadeConc::Detonate( void ) | ||
{ | { | ||
// An array for all the player pointers to chill | |||
CBaseEntity *list[1024]; | |||
// grab all of them within 350 units | |||
int count = UTIL_EntitiesInSphere(list,1024,GetAbsOrigin()+Vector(0,10,0),350,MASK_PLAYERSOLID); | |||
// for each of them | |||
for ( int i = 0; i < count; i++ ) | |||
{ | |||
// make sure its a player | |||
if (list[i]->IsPlayer()) | |||
{ | |||
// trace line to make | |||
trace_t tr; | |||
UTIL_TraceLine(list[i]->GetAbsOrigin(),GetAbsOrigin()+Vector(0,10,0),MASK_PLAYERSOLID, NULL, COLLISION_GROUP_NONE, &tr ); | |||
CBasePlayer *pPlayer = ToBasePlayer(list[i]); | |||
float distancesq = (pPlayer->GetAbsOrigin() - GetAbsOrigin()+Vector(0,10,0)).LengthSqr() | |||
float ratio = 1.0; | |||
if (distancesq >= 40000) | |||
ratio = (200-(vec_t)FastSqrt(distancesq))/200.0; | |||
color32 white = { 255,255,255,(255*ratio) }; | |||
int fadehold = random->RandomInt( 0, 4 ); | |||
if(tr.fraction == 1.0f) | |||
{ | |||
UTIL_ScreenFade(pPlayer, white, CONC_FALLOFF_TIME+(.5f*fadehold*ratio), fadehold*ratio, FFADE_IN); | |||
int effect = 0 ? random->RandomInt( 35, 37 ) : random->RandomInt( 32, 34 ); | |||
CSingleUserRecipientFilter user( pPlayer ); | |||
enginesound->SetPlayerDSP( user, effect, false ); | |||
} | |||
} | |||
} | |||
}</ | BaseClass::Detonate(); | ||
}</source> | |||
==Update 3== | ==Update 3== | ||
< | <source lang=cpp>if(tr.fraction == 1.0f) | ||
{ | { | ||
if ( pPlayer->FInViewCone( this ) ) | |||
UTIL_ScreenFade(pPlayer, white, CONC_FALLOFF_TIME+(.5f*fadehold*ratio), fadehold*ratio, FFADE_IN); | |||
int effect = 0 ? random->RandomInt( 35, 37 ) : random->RandomInt( 32, 34 ); | |||
CSingleUserRecipientFilter user( pPlayer ); | |||
enginesound->SetPlayerDSP( user, effect, false ); | |||
}</source> | |||
The above shows how to skip the screenfade if the player can't actually see the grenade. | |||
[[Category:Weapons programming]] |
Latest revision as of 22:48, 21 January 2024




January 2024

You can help by

January 2024

For help, see the VDC Editing Help and Wikipedia cleanup process. Also, remember to check for any notes left by the tagger at this article's talk page.
Creating a grenade that will blind someone.
void CGrenadeConc::Detonate( void )
{
// An array for all the player pointers to chill
CBaseEntity *list[1024];
// grab all of them within 400 units
int count = UTIL_EntitiesInSphere(list,1024,GetAbsOrigin()+Vector(0,10,0),400,MASK_PLAYERSOLID);
// for each of them
for ( int i = 0; i < count; i++ )
{
// make sure its a player
if (list[i]->IsPlayer())
{
// trace line to make
trace_t tr;
UTIL_TraceLine(list[i]->GetAbsOrigin(),GetAbsOrigin()+Vector(0,10,0),MASK_PLAYERSOLID, NULL, COLLISION_GROUP_NONE, &tr );
CBasePlayer *pPlayer = ToBasePlayer(list[i]);
color32 white = { 255,255,255,255 };
if(tr.fraction == 1.0f) {UTIL_ScreenFade(pPlayer,white,CONC_FALLOFF_TIME,CONC_FADEHOLD, FFADE_IN);}
}
}
BaseClass::Detonate();
}
Drop that in your grenade .cpp and add this to the class definition
virtual void Detonate( void );
and these defines into up top
#define CONC_FALLOFF_TIME 20.0f
#define CONC_FADEHOLD 3.0f
GetAbsOrigin()+Vector(0,10,0)
MASK_SOLID replaced with MASK_PLAYERSOLID
Update 1
The question was posed... "How do you get the flash to deminish with distance?" The answer is simple in theory...
- Find the distance the player is from the grenade
- Consider..
- ..the 100% flash distance
- ..the 0% distance
- Calculate and set alpha
So let's do it really quick
Step 1
We are going to tweak CGrenadeConc::Detonate( void ) a bit.
Basically, since we are changing the alpha of the fade, all calculations will be added at the marked location
CBasePlayer *pPlayer = ToBasePlayer(list[i]);
// here is where our code will be going
color32 white = { 255,255,255,255 };
A simple line will take care of finding the distance...
float distancesq = (pPlayer->GetAbsOrigin() - GetAbsOrigin()+Vector(0,10,0)).LengthSqr()
Step 2
Part A
Considering the 100% flash distance is the next step. At what distance do we still want the character to be flashed? For this tutorial, the chosen distance is 200 inches. The sphere above makes that work out pretty well because 200 inches is about half the sphere's range.
Part B
Consider the 0% distance. If 200 inches is 100%, a good 0% distance may be 400 inches.
Step 3
For simplicitys sake, and code shortening, we start percent with 100%:
float ratio = 1.0;
Since we decided that 200 inches would be a good distance for 100%, let's make sure the distance is above or at that. We have a simple calculation to know what percentage of the flash to show. The distance is left squared to possibly avoid an unneeded square root...
if (distancesq >= 40000)
ratio = (200-(vec_t)FastSqrt(distancesq))/200.0;
Distance is taken between the point of explosion and the character's location.
We want a proportion of this flash, so we will use a ratio of a 100% opaque flash.
color32 white = { 255,255,255,(255*ratio) };
Update 2
It might also be better to have the flash hold change as well via the ratio. Here is the finished detonate function for comparison.
void CGrenadeConc::Detonate( void )
{
// An array for all the player pointers to chill
CBaseEntity *list[1024];
// grab all of them within 350 units
int count = UTIL_EntitiesInSphere(list,1024,GetAbsOrigin()+Vector(0,10,0),350,MASK_PLAYERSOLID);
// for each of them
for ( int i = 0; i < count; i++ )
{
// make sure its a player
if (list[i]->IsPlayer())
{
// trace line to make
trace_t tr;
UTIL_TraceLine(list[i]->GetAbsOrigin(),GetAbsOrigin()+Vector(0,10,0),MASK_PLAYERSOLID, NULL, COLLISION_GROUP_NONE, &tr );
CBasePlayer *pPlayer = ToBasePlayer(list[i]);
float distancesq = (pPlayer->GetAbsOrigin() - GetAbsOrigin()+Vector(0,10,0)).LengthSqr()
float ratio = 1.0;
if (distancesq >= 40000)
ratio = (200-(vec_t)FastSqrt(distancesq))/200.0;
color32 white = { 255,255,255,(255*ratio) };
int fadehold = random->RandomInt( 0, 4 );
if(tr.fraction == 1.0f)
{
UTIL_ScreenFade(pPlayer, white, CONC_FALLOFF_TIME+(.5f*fadehold*ratio), fadehold*ratio, FFADE_IN);
int effect = 0 ? random->RandomInt( 35, 37 ) : random->RandomInt( 32, 34 );
CSingleUserRecipientFilter user( pPlayer );
enginesound->SetPlayerDSP( user, effect, false );
}
}
}
BaseClass::Detonate();
}
Update 3
if(tr.fraction == 1.0f)
{
if ( pPlayer->FInViewCone( this ) )
UTIL_ScreenFade(pPlayer, white, CONC_FALLOFF_TIME+(.5f*fadehold*ratio), fadehold*ratio, FFADE_IN);
int effect = 0 ? random->RandomInt( 35, 37 ) : random->RandomInt( 32, 34 );
CSingleUserRecipientFilter user( pPlayer );
enginesound->SetPlayerDSP( user, effect, false );
}
The above shows how to skip the screenfade if the player can't actually see the grenade.