.qc (dot qc) - the group for quake c coders of all denominations. If you make quake one mods and write code in quake c, join our group! I'll try to answer any quake c questions - please post your inquiry in the forums...

Forum Thread
  Posts  
Gatling gun (Groups : qc : Forum : discuss() : Gatling gun) Locked
Thread Options
Sep 21 2011 Anchor

I Have my "IT_SUPER_NAILGUN" here, already coded with a "fake overhating" effect (overheats after 80 shots for 2 seconds, just a modified reloading code based on Reload Quake xD)..
And now i want to add the following and i want to know a good and efficient way to do the following:

- if you press you shootbutton, the nailgun doesnt start shooting for 2 seconds, only the barrel animations starts and a "warmup sound plays"
- after that the gun shoots normally (W_FireMiniGun)
- when yo stop shooting the barrel still rolls for 9 frames (cooldown)

And ideas? :D

numbersix
numbersix quake-c coder++
Sep 27 2011 Anchor

Yep, already found, modified and rewrote thiis code. And this forum didnt tell me about this post. Dur.
I'll dig this up an post it in a little while.

Here we go. My code samples are a bit more complex because I use pointer vars for all add on guns.
You should realize the supernailgun (and most gatling / minigun addons) are fired from frames.
That means player frames are called (usually found in player.qc) and the gun is fired from there for appearance sake.

The sequence goes like this -
Weapon selected (by impulse or cycle function)
Fire button pressed
Variable (firecontrol) indicates spinup, so that is started
When spin up is done, gun starts firing
Ammo runs out or fire button is released - start spin down sequence
Spin down done - fire control is released

You need a control var defined in defs.qc somewhere near the end:

.float firecontrol;
.float ammo_bullets;

In weapons.qc where you fire this gun -

else if (self.weapon == IT_SUPER_NAILGUN)
{
if (!self.firecontrol) player_gun_spinup(); // this starts spinup
else
player_gun1(); // this fires the gun when the function is entered again
}

In another part of weapons (or even better a separate qc file for extra weapons):

// fn(set_spindown) - start spin down seq.
// tr - release time calculated in frames

void (float tr) set_spindown =
{
local float r;

self.think = player_gun_sd1;
self.nextthink = (time + 0.01);
if (!self.currentammo) self.weaponframe = 7;
r = tr + rint(random() * tr);
self.attack_finished = time + (r * 0.03) + tr * 0.01;
self.firecontrol = 0; // clear var for next shot - var should also be cleared when any weapon is selected
};

// start gun spin up, play sound, setup vars

void () player_gun_spinup = [ 17, player_gun_su2 ]
{
local float r;

if (!self.firecontrol)
{
self.weaponframe = 40;
self.nextthink = (time + 0.01);
sound (self,CHAN_WEAPON,"gatling/engine1.wav",1,ATTN_NORM); // start sound
r = 31 + rint(random() * 15);
self.attack_finished = time + (r * 0.01) + 0.2; // time to run spin up
self.firecontrol = 1; // allow firing once time is up
}
};

// run spinup frames until ready to fire - timing is controlled by value in attack_finished

void () player_gun_su2 = [ 18, player_gun_su2 ]
{
self.weaponframe = self.weaponframe + 1;
if (self.weaponframe == 52) self.weaponframe = 34;
self.nextthink = (time + 0.01);
if (self.attack_finished < time) if (!self.button0) // when time is done if button is released go to spindown
{
set_spindown(15);
return;
}
};

// my fire function - yours might vary a bit

void () W_FireMiniGun =
{
local vector dir;

// use ammo - you have to define bullets, and make an ammo box. or you could use ammo_nails
self.currentammo = self.ammo_bullets = self.ammo_bullets - 1;

sound (self,CHAN_VOICE,"gatling/fire.wav",1,ATTN_NORM);
makevectors(self.v_angle); // 3 vectors for where aim is pointing. we use v_forward
dir = v_forward; // points where player view is aimed - no stinky auto aim
FireBullets (1,dir,' 0.08 0.08 0'); // qc function already exists in weapons.qc - 2nd vector is bullet spread around aim point
self.effects = (self.effects | EF_MUZZLEFLASH);

// this is a brass eject function - not absolutely necessary
eject (((self.origin + (v_forward * VWX_GATLING)) + (v_right * VWY_GATLING)),
((v_forward * crandom() * VWX_GATLING_VEL) + v_right * (VWY_GATLING_VEL + 10 * crandom())),SHELL_CASING, FR_SHELL50CAL);

if (self.currentammo <= 0)
{
self.currentammo = self.ammo_bullets = 0;
set_spindown(20); // ran out of ammo, longer spindown
return;
}

};

// fn(player_gat1,2) - gatling main fire sequence

void () player_gun1 = [ 17, player_gun2 ]
{
if (!self.button0) // spin down short
{
set_spindown(15);
self.weaponframe = 33 + self.weaponframe;
return;
}

if (self.t_width < time)
{
sound (self,CHAN_WEAPON,"gatling/engine2.wav",1,ATTN_NORM);
self.t_width = (time + 1);
}
if (self.weaponframe > 6) self.weaponframe = 1;
self.weaponframe = self.weaponframe + 1;
self.nextthink = (time + self.eweapon.attack_finished);
self.attack_finished = (time + self.eweapon.attack_finished);
W_FireMiniGun (); // shoot bullets, muzzleflash, play sound, eject brass in this function
};

void () player_gun2 = [ 18, player_gun1 ]
{
self.weaponframe = self.weaponframe + 1;
if (self.weaponframe == 7) self.weaponframe = 1;
self.nextthink = (time + self.eweapon.attack_finished);
self.attack_finished = (time + self.eweapon.attack_finished);
};

// fn(player_gun_sd1) - ammo empty or trigger release, spin gatling down
// runs for time set in attack_finished - then another wep can be selected and fired

void () player_gun_sd1 = [ 19, player_gun_sd1 ]
{
self.weaponframe = self.weaponframe + 1;
if (self.weaponframe < 30) {if (self.weaponframe == 13) self.weaponframe = 7;}
else {if (self.weaponframe == 52) self.weaponframe = 34;}
if (self.weaponframe & 1) W_FireNoAmmo ();
self.nextthink = (time + 0.03);
if (self.attack_finished < time)
{
sound (self,CHAN_WEAPON,"misc/null.wav",1,ATTN_NORM);
player_run();
}
};

This came from my gatling gun code, so I renamed a few things, and put your values in where I could.
Since this is a sample its likely it wont compile and will need a few changes to work for you.
I can already see the audio file strings will need changed.
The weapon frame numbers and player frame numbers are from a massive gatling gun model and custom player model and wont match any normal model as well.
And there are a few self.eweapon references - this is an pointer entity I use for extended guns that stores all kinds of data like attack_finished values.

It is also likely you will need to prototype some of those functions - add them to the end of defs.qc like this:

void () player_gun_sd1;
void () player_gun2;
void () player_gun1;
void () player_gun_su2;
void () player_gun_spinup;
void (float tr) set_spindown;

In general if the compiler says this:

weapons.qc(209): error: Unknown value "player_gun_spinup"

and the function is in a qc file (that is called by progs.src) you will need to prototype the function before it gets called.

Edited by: numbersix

--

\|/
-*- Support free code: Patreon.com
/|\

Dec 29 2011 Anchor

Well, this did not work for me...
GIves me tons of compile errors... Is there a easier way to simulate spinup at least??

numbersix
numbersix quake-c coder++
Jan 9 2012 Anchor

If you just did a cut and paste, you prob. dont have all the variables defined.

You could animate spin up through a frame sequence. Due to the repetitive nature of spins though you will still likely want a countdown variable or time limit on the loop.

What ever way you do it from a code perspective the process is the same -

(weapon selected by any method)
1. Fire button pressed - run spinup frames
a. Handle no ammo situation by weapon switch or other method
b. Run spin frames, count down to mode switch
2. Switch mode to firing, fire gun, run fire frames
a. Run spin down frames if fire button released (before or during firing)
b. Run spin down frames if ammo runs out while firing
(c. possibility of handling misfire / overheat - not really necessary, this is an extra)
3. Run spindown frames
a. Count down - set idle frame / mode when spindown complete

I could provide you with all my gatling code, but you will be in the same boat with it needing to be integrated before it can be compiled.

The best thing to do might just be to get a working gatlinq with qc and merge that into your code.

--

\|/
-*- Support free code: Patreon.com
/|\

Jan 9 2012 Anchor

np, got it to work, made a misstake with my defined stuff... xD

Reply to thread
click to sign in and post

Only registered members can share their thoughts. So come on! Join the community today (totally free - or sign in with your social account on the right) and join in the conversation.