2017-12-12, 22:39 *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
Pages: [1] 2 3
  Print  
Author Topic: Modifying the shotgun  (Read 3010 times)
0 Members and 1 Guest are viewing this topic.
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« on: 2016-02-29, 02:25 »

I would like to changed the spread of the shotgun. I would like to do something similar to com/cq3 where the spread is consistent and circular. How can I achieve this

Thanks!
Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
Phoenix
Bird of Fire
 

Team Member
Elite (7.5k+)
*********
Posts: 8353

WWW
« Reply #1 on: 2016-02-29, 20:17 »

I'm not familiar with what com/cq3 is... however, you can change the spread of the shotgun to be non-random pretty easily.  You'll want to look at this function in g_weapon.c:

Code:
// this should match CG_ShotgunPattern
void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *ent ) {
int i;
float r, u;
vec3_t end;
vec3_t forward, right, up;
int oldScore;
qboolean hitClient = qfalse;

// derive the right and up vectors from the forward vector, because
// the client won't have any other information
VectorNormalize2( origin2, forward );
PerpendicularVector( right, forward );
CrossProduct( forward, right, up );

oldScore = ent->client->ps.persistant[PERS_SCORE];

// generate the "random" spread pattern
for ( i = 0 ; i < DEFAULT_SHOTGUN_COUNT ; i++ ) {
r = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * 16;
u = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * 16;
VectorMA( origin, 8192 * 16, forward, end);
VectorMA (end, r, right, end);
VectorMA (end, u, up, end);
if( ShotgunPellet( origin, end, ent ) && !hitClient ) {
hitClient = qtrue;
ent->client->accuracy_hits++;
}
}
}

You'll notice the value DEFAULT_SHOTGUN_SPREAD.  That's a defined constant that's set in bg_public.h:

Code:
#define DEFAULT_SHOTGUN_SPREAD 700

The r and u values stand for "right" and "up".  A shot in Q3 is calculated forward from the player by 8192 units, then right and up perpendicular to that line by the values "r" and "u"  What the current shotgun code does is takes a seeded random and multiplies it by the spread value, and then by 16.  The seeded random is not a true random, it's a pattern determined by the "seed" number.  This calculation is duplicated on the client-side to save on network code.  This was done because Q3 was written when dialup modems were the norm, so bandwidth savings was important then.  The thing to remember now is that the same math has to be run on the client and server.  More on that later.  For now, what you need to do is figure out the size you want the pattern, and then replace the "r" and "u" calculations with fixed distances from the forward line.  Since this function is running a loop from 0 to DEFAULT_SHOTGUN_COUNT (defined in bg_public.h as 11), you have 11 pellets to distribute, though if you want to change that you can.  Just change the 11 to another value, but be mindful of the damage increase since damage is calculated per-pellet.  Anyway, what you want to do is use the loop counter "i" to determine where each pellet is going to be.  There's two ways to do this.  You can calculate the r and u values (think X and Y on a graph) in horizontal and vertical lines, or you can calculate them radially from a center point using sin and cos functions.  For the first method, just graph out your pattern, then set hard values for r and u based on what i is.  Example:

Code:
if (i == 0)
{
  r = -18;
  u = 350;
}
if (i == 1)
{
 r = 18
 u = 350;
}
// etc...
For the second method, use i to determine which pellet number you're on, calculate a degree value (remember that sin and cos are in RADIANS, so if you're using degrees you'll need to use DEG2RAD to convert them), then multiply from the center point by a fixed distance, where dist is your distance value, angle = (desired degrees) * i, and r = dist * cos(DEG2RAD(angle)), and u = dist * sin(DEG2RAD(angle)).  I might have cos and sin backward, but you get the idea.  So if you want 6 pellets that will be adding 60 degrees every time i increments, and then you'll have to multiply by a distance - however far you want - from center up until i == 6.  Remember, we're starting at 0, so 0 to 5 is 6 pellets.  After that, assuming you're still using 11 pellets total, you'll need to calculate 72 degrees every time i increments, then calculate out however far out you want your second ring to be.

Just remember that whatever changes you do to ShotgunPattern in g_weapon.c need to be mirrored in CG_ShotgunPattern in cg_weapons.c or the visual representation of the server-side damage traces will be out of sync.  You will need to compile both qagame.qvm and cgame.qvm any time you change these or if you change any file beginning with bg_.

Hope that helps!
Logged


I fly into the night, on wings of fire burning bright...
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« Reply #2 on: 2016-02-29, 22:26 »

AWESOME! You are the man!

I mean CPM/CQ3 by the way. Challenge ProMode and Challenge Quake 3 from Challenge ProMode Arena.

here is a pic of cpma shotgun blast.
Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
~Va^^pyrA~
 

Beta Tester
Spider Mastermind
*********
Posts: 463

Do These Fangs Make My Butt Look Big?

WWW
« Reply #3 on: 2016-03-01, 01:39 »

That spread pattern is very aesthetically pleasing. Though now, I really want it to look like a star, or a heart, or something. LOL Slipgate - Smile
Logged
Phoenix
Bird of Fire
 

Team Member
Elite (7.5k+)
*********
Posts: 8353

WWW
« Reply #4 on: 2016-03-01, 18:06 »

Technically I am the bird, but that looks like a radial calculation alright.  Doom - Thumbs Up!
Logged


I fly into the night, on wings of fire burning bright...
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« Reply #5 on: 2016-03-01, 18:23 »

Trying to figure it out is not very awesome.

Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« Reply #6 on: 2016-03-01, 21:38 »

My head popped... I never liked plotting points.

GAH!!!
Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
Phoenix
Bird of Fire
 

Team Member
Elite (7.5k+)
*********
Posts: 8353

WWW
« Reply #7 on: 2016-03-01, 22:05 »

I am not too fond of mathematics myself.  It's necessary for programming, yes, but I find it to be the most frustrating of obstacles.  Still, if you want it enough you'll find a way to make it work.  My programming efforts for Generations consist of 99% answered prayer, 0.9999% pure stubbornness, and 0.00001% actual ability on my part.  The remaining 0.00009% I attribute to quantum fluctuations of dark energy interacting with Heisenberg's uncertainty principle to create pure and utter BS that for some reason results in functioning code that I don't understand why it even works, yet somehow it does.

Or for a visual reference, my programming process ends up being something like this (though not as cute):


https://i.chzbgr.com/full/8752820480/h213BA74D/
Logged


I fly into the night, on wings of fire burning bright...
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« Reply #8 on: 2016-03-01, 22:39 »

I do better when I have something to go on. if you could give me an example of what im trying to do then im good.... otherwise I sit and stare and say duh. Slipgate - Smile

I think there is something in the CPM docs. I should put those up for sharing too... Slipgate - Tongue
Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
Phoenix
Bird of Fire
 

Team Member
Elite (7.5k+)
*********
Posts: 8353

WWW
« Reply #9 on: 2016-03-01, 23:37 »

I don't have time to tinker tonight, but I think I might be able to whip up an example calculation in the next day or two.
Logged


I fly into the night, on wings of fire burning bright...
Phoenix
Bird of Fire
 

Team Member
Elite (7.5k+)
*********
Posts: 8353

WWW
« Reply #10 on: 2016-03-02, 19:28 »

Here, try this:

In g_weapon.c, change ShotgunPattern to this:


Code:
// this should match CG_ShotgunPattern
void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *ent ) {
int i;
float r, u;
vec3_t end;
vec3_t forward, right, up;
int oldScore;
qboolean hitClient = qfalse;

float range;


// derive the right and up vectors from the forward vector, because
// the client won't have any other information
VectorNormalize2( origin2, forward );
PerpendicularVector( right, forward );
CrossProduct( forward, right, up );

oldScore = ent->client->ps.persistant[PERS_SCORE];

// generate the "random" spread pattern
for ( i = 0 ; i < 16 ; i++ ) {

r = sin(DEG2RAD(22.5 + (45 * i)) );
u = cos(DEG2RAD(22.5 + (45 * i)) );

if (i < 8){
range = 175;
} else {
range = 350;
}

r *= range * 16;
u *= range * 16;

VectorMA( origin, 8192 * 16, forward, end);
VectorMA (end, r, right, end);
VectorMA (end, u, up, end);
if( ShotgunPellet( origin, end, ent ) && !hitClient ) {
hitClient = qtrue;
ent->client->accuracy_hits++;
}
}
}

In cg_weapon.c, change CG_ShotgunPattern to this:

Code:
/*
================
CG_ShotgunPattern

Perform the same traces the server did to locate the
hit splashes
================
*/
static void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, int otherEntNum ) {
int i;
float r, u;
vec3_t end;
vec3_t forward, right, up;

float range;

// derive the right and up vectors from the forward vector, because
// the client won't have any other information
VectorNormalize2( origin2, forward );
PerpendicularVector( right, forward );
CrossProduct( forward, right, up );

// generate the "random" spread pattern
for ( i = 0 ; i < 16; i++ ) {

r = sin(DEG2RAD(22.5 + (45 * i)) );
u = cos(DEG2RAD(22.5 + (45 * i)) );

if (i < 8){
range = 175;
} else {
range = 350;
}

r *= range * 16;
u *= range * 16;
VectorMA( origin, 8192 * 16, forward, end);
VectorMA (end, r, right, end);
VectorMA (end, u, up, end);

CG_ShotgunPellet( origin, end, otherEntNum );
}
}

That should produce a pattern like what you're looking for.  I've hard coded in "16" for the count and the two range values for the rings, but you can modify those however you like.  If you prefer to use DEFAULT_SHOTGUN_COUNT and DEFAULT_SHOTGUN_SPREAD #define statements, by all means do so.  I just hard coded the values to make it easier to interpret here.

Note that the sin/cos calculations use 45 degrees.  That's 360/8 since we're doing 8 pellets per ring, and I've rotated it by 22.5 degrees so that the top and sides are flat instead of points.  Since we're making a full circle once i == 8, I change the range calculation based on whether i is between 0 and 7, and between 8 and 15 so that one circle is twice the distance from center.  If you change the count, say, to 12 and want 6 pellets per ring, you'd use 60 degrees (360/6), and 30 degrees for the offset, and your range would be based on 0 to 5, and 6 to 11.  Also, if you want a "dead center" pellet, you can start with a special case for i == 0, then just offset your range loop calculations by 1.

One thing to note:  just be aware of how Q3 handles CrossProduct calculations... if you have an asymmetrical pattern, aiming up and down can cause the pattern to flip because the "right" and "up" vectors become inverted.  For example, if you had pellets in a flat line from left to right, similar to how Doom's shotgun works, then aim at the ceiling, it will flip to running the pellets top to bottom.  I had to ditch CrossProduct and calculate the angles differently for Doom's weapons in Generations, so try to stick with even pellet counts - 4, 6, 8, 10, etc, so that any flipping of the pattern is irrelevant.
Logged


I fly into the night, on wings of fire burning bright...
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« Reply #11 on: 2016-03-02, 23:34 »

If i kept
DEFAULT_SHOTGUN_COUNT
but changed it to 16
and remove the
DEFAULT_SHOTGUN_SPREAD above it in bg_public.h

then for ( i = 0 ; i < 16; i++ ) would need to be changed to

for ( i = 0 ; i < DEFAULT_SHOTGUN_COUNT; i++ )

? or did i just completely miss the boat Slipgate - Tongue
Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
Phoenix
Bird of Fire
 

Team Member
Elite (7.5k+)
*********
Posts: 8353

WWW
« Reply #12 on: 2016-03-03, 00:11 »

You can certainly do it that way.  In fact, you could still use both the #defined values.  If you went into bg_public.h, you could do something like this:

in bg_public.h:


Code:
#define DEFAULT_SHOTGUN_COUNT 16;  // MAKE SURE THIS IS AN EVEN NUMBER!!
#define DEFAULT_SHOTGUN_SPREAD 700;

Then change your shotgun gun code to work like this:

Code:
// this should match CG_ShotgunPattern
void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *ent ) {
int i;
float r, u;
vec3_t end;
vec3_t forward, right, up;
int oldScore;
qboolean hitClient = qfalse;

        float range;  // How far away from center we're placing our pellets.
        int interval;  // How many times we're incrementing.
        float deg;  // How many degrees we're rotating by.  This should be half the total count.

        interval = DEFAULT_SHOTGUN_COUNT;
        if (interval <= 0){   // I always sanity check for divide by zero when doing a divide by any variable.
                interval = 16;
        }
        deg = 360 / 0.5f * interval;

// derive the right and up vectors from the forward vector, because
// the client won't have any other information
VectorNormalize2( origin2, forward );
PerpendicularVector( right, forward );
CrossProduct( forward, right, up );

oldScore = ent->client->ps.persistant[PERS_SCORE];

// generate the "random" spread pattern
for ( i = 0 ; i < interval ; i++ ) {

r = sin(DEG2RAD( (0.5f * deg) + (deg * i)) );
u = cos(DEG2RAD( (0.5f * deg ) + (deg * i)) );

if (i < interval * 0.5){
range = 0.5f * DEFAULT_SHOTGUN_SPREAD;
} else {
range = DEFAULT_SHOTGUN_SPREAD;
}

r *= range * 16;
u *= range * 16;

VectorMA( origin, 8192 *16, forward, end);
VectorMA (end, r, right, end);
VectorMA (end, u, up, end);
if( ShotgunPellet( origin, end, ent ) && !hitClient ) {
hitClient = qtrue;
ent->client->accuracy_hits++;
}
}
}

Mirror those changes in CG_ShotgunPattern and Then all you have to do is edit DEFAULT_SHOTGUN_COUNT to determine how many pellets you want, and DEFAULT_SHOTGUN_SPREAD to determine the size of the pattern.  The degree calculations and how many pellets per ring are completely automated at this point, so you can grow or shrink your pattern size by changing one number, and increase or decrease your pellet count by changing one number.  Pretty nifty, eh?
Logged


I fly into the night, on wings of fire burning bright...
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« Reply #13 on: 2016-03-03, 00:46 »

Ah yes.. then we need to be concerned about  define_shotgun_damage

10 is default which means that 110 dmg is dealt at point blank with original shotgun
16 pellets with 10 dmg would be 160 dmg at pointblank.

so if i changed def_sg_count to 20
and changed def_sg_dmg too 5.5
that would keep the dmg at the q3 default.

and 20 would be an even number >Slipgate - Smile oooh this could get fun :>

You know what would be really cool and unique if the inside of the outer ring were randomized hah.

I cannot test the code yet because in a turn of shxtty events my cpu fan just died... so next week i will be up and running. i wanted an excuse to upgrade my cpu from an i5 to an i7 anyway. im going to also add another 8gigs of ram.

Im so greatful for you help phoe... thanks
Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« Reply #14 on: 2016-03-03, 01:50 »

Just to verify because i am going to use unlagged Slipgate - Smile

Code:
// this should match CG_ShotgunPattern
void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *ent ) {
int i;
float r, u;
vec3_t end;
vec3_t forward, right, up;
int oldScore;
qboolean hitClient = qfalse;


//Phoenix/Orb —— Shotgun
        float range;  // How far away from center we're placing our pellets.
        int interval;  // How many times we're incrementing.
        float deg;  // How many degrees we're rotating by.  This should be half the total count.

        interval = DEFAULT_SHOTGUN_COUNT;
        if (interval <= 0){   // I always sanity check for divide by zero when doing a divide by any variable.
                interval = 16;
        }
        deg = 360 / 0.5f * interval;
//Phoenix/Orb — — Shotgun

//unlagged - attack prediction #2
// use this for testing
//Com_Printf( "Server seed: %d\n", seed );
//unlagged - attack prediction #2

// derive the right and up vectors from the forward vector, because
// the client won't have any other information
VectorNormalize2( origin2, forward );
PerpendicularVector( right, forward );
CrossProduct( forward, right, up );

oldScore = ent->client->ps.persistant[PERS_SCORE];

//unlagged - backward reconciliation #2
// backward-reconcile the other clients
G_DoTimeShiftFor( ent );
//unlagged - backward reconciliation #2

// generate the “Phoenix/Orb” spread pattern
for ( i = 0 ; i < interval ; i++ ) {

r = sin(DEG2RAD( (0.5f * deg) + (deg * i)) );
u = cos(DEG2RAD( (0.5f * deg ) + (deg * i)) );

if (i < interval * 0.5){
range = 0.5f * DEFAULT_SHOTGUN_SPREAD;
} else {
range = DEFAULT_SHOTGUN_SPREAD;
}

r *= range * 16;
u *= range * 16;

VectorMA( origin, 8192 *16, forward, end);
VectorMA (end, r, right, end);
VectorMA (end, u, up, end);
if( ShotgunPellet( origin, end, ent ) && !hitClient ) {
hitClient = qtrue;
ent->client->accuracy_hits++;
}
}

//unlagged - backward reconciliation #2
// put them back
G_UndoTimeShiftFor( ent );
//unlagged - backward reconciliation #2
}

Look good?

PEW PEW PEW
Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
Phoenix
Bird of Fire
 

Team Member
Elite (7.5k+)
*********
Posts: 8353

WWW
« Reply #15 on: 2016-03-03, 17:51 »

Looks good to me!  Doom - Thumbs Up!
Logged


I fly into the night, on wings of fire burning bright...
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« Reply #16 on: 2016-03-11, 06:06 »

Code: (cg_weapons.c)
/*
================
CG_ShotgunPattern

Perform the same traces the server did to locate the
hit splashes
================
*/
static void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *ent ) {
int i;
float r, u;
vec3_t end;
vec3_t forward, right, up;

        float range;  // How far away from center we're placing our pellets.
        int interval;  // How many times we're incrementing.
        float deg;  // How many degrees we're rotating by.  This should be half the total count.

        interval = DEFAULT_SHOTGUN_COUNT;
        if (interval <= 0){   // I always sanity check for divide by zero when doing a divide by any variable.
                interval = 16;
        }
        deg = 360 / 0.5f * interval;

// derive the right and up vectors from the forward vector, because
// the client won't have any other information
VectorNormalize2( origin2, forward );
PerpendicularVector( right, forward );
CrossProduct( forward, right, up );

// generate the "random" spread pattern
for ( i = 0 ; i < interval ; i++ ) {

r = sin(DEG2RAD( (0.5f * deg) + (deg * i)) );
u = cos(DEG2RAD( (0.5f * deg ) + (deg * i)) );

if (i < interval * 0.5){
range = 0.5f * DEFAULT_SHOTGUN_SPREAD;
} else {
range = DEFAULT_SHOTGUN_SPREAD;
}

r *= range * 16;
u *= range * 16;

VectorMA( origin, 8192 *16, forward, end);
VectorMA (end, r, right, end);
VectorMA (end, u, up, end);

CG_ShotgunPellet( origin, end, otherEntNum );
}
}
}

whad i miss?

Code:
XPMUser@xxxxxxxxxxxx-xxxxxxxx ~/q3req
$ make
D:/Mingw/msys/1.0/home/q3dev/q3req/misc/q3lcc.exe -DCGAME -o D:/Mingw/msys/1.0/home/q3dev/q3req/build/win32/baseq3/cgame/cg_weapons.asm D:/Mingw/msys/1.0/home/q3dev/q3req/code/cgame/cg_weapons.c
D:/Mingw/msys/1.0/home/q3dev/q3req/code/cgame/cg_weapons.c:2392: missing parameter type
D:/Mingw/msys/1.0/home/q3dev/q3req/code/cgame/cg_weapons.c:2392: syntax error; found `*' expecting `)'
D:/Mingw/msys/1.0/home/q3dev/q3req/code/cgame/cg_weapons.c:2392: skipping `*' `ent'
D:/Mingw/msys/1.0/home/q3dev/q3req/code/cgame/cg_weapons.c:2433: undeclared identifier `otherEntNum'
D:/Mingw/msys/1.0/home/q3dev/q3req/code/cgame/cg_weapons.c:2436: unrecognized declaration
make: *** [D:/Mingw/msys/1.0/home/q3dev/q3req/build/win32/baseq3/cgame/cg_weapons.asm] Error 1

XPMUser@VirtualXP-42519 ~/q3req
Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
Phoenix
Bird of Fire
 

Team Member
Elite (7.5k+)
*********
Posts: 8353

WWW
« Reply #17 on: 2016-03-11, 18:46 »

You have an extra close bracket directly under CG_ShotgunPellet( origin, end, otherEntNum );.  Remove that bracket and it should compile.
Logged


I fly into the night, on wings of fire burning bright...
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« Reply #18 on: 2016-03-11, 18:57 »

 Banging Head against Wall Banging Head against Wall Banging Head against Wall Banging Head against Wall Banging Head against Wall

omg..........Well in my defence it was 12am... I was excited because I just had gotten my computer back up and running.. I have 16gb of ram now Slipgate - Smile
Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
Orbital-S2D
 

Pain Elemental
****
Posts: 83

RnR Boss

WWW
« Reply #19 on: 2016-03-11, 22:38 »

Hmm strange I must have missed something

I can see that it is wanting to turn around the center of the screen ...
these are all separate shots
Logged

GET THAT GUY GET THAT GUY, PEW PEW PEW!
Pages: [1] 2 3
  Print  
 
Jump to: