Index | FAQ | Search | Memberlist | Usergroups | Profile | Log in to check your private messages | Log in | Register

Charge Shot Goto page 1, 2 Next

| Inside3d Forums Forum Index -> QuakeC Programming

View previous topic :: View next topic
Author | Message
--- | ---
Ghost_Fang Joined: 12 Nov 2009 Posts: 162 |

Posted: Sat Jan 30, 2010 6:15 am Post subject: Charge Shot |

I decided to make a new topic on this cause i want to be mroe specific. Lets keep it basic, lets say i have the rocket launcher. and i press mouse1 to fire. just like normal. I also want to be able to hold down mouse1 to charge, and depending on how long i hold it it shoots a bigger rocket. Like maybe 3 levels. hold down for 1 second, is a little bigger, 3 seconds bigger, 5 seconds biggest. How would i go about doing that?

Back to top |

Wazat Joined: 15 Oct 2004 Posts: 732 Location: Middle 'o the desert, USA |

Posted: Sat Jan 30, 2010 7:29 am Post subject: |

I do this for the E-Rifle's primary fire in Conquest. The basic idea is this: In player.qc, set up some new frames for your weapon to charge. The first frame sets up your charging stuff. The second frame is called repeatedly while you charge. The rest of the frames are to animate firing the weapon once the player lets go (i.e. the rocket firing frames for your code). Here's my e-rifle code:

Code:
void() player_e_rifle =[$nailatt2, player_e_riflecharging ] { StartE_Rifle(); self.attack_finished = gametime + 0.2; };
void() player_e_riflecharging =[$nailatt2, player_e_riflefire1 ]
{
self.attack_finished = gametime + 0.2;
if(!self.button0 || self.t_width)
return; // go to firing frames
self.think = player_e_riflecharging; // otherwise keep charging
ChargeE_Rifle();
};
void() player_e_riflefire1 =[$nailatt2, player_e_riflefire2 ]
{
self.weaponframe = 0;
self.frame = $shotatt1 + self.weaponframe;
W_FireE_Rifle();
};
void() player_e_riflefire2 =[$nailatt2, player_e_riflefire2 ]
{
self.weaponframe = self.weaponframe + 1;
self.frame = $shotatt1 + self.weaponframe;
if(self.frame > $shotatt6)
self.frame = $shotatt6;
if(self.weaponframe >= 6)
self.think = player_run;
};

My e-rifle only uses 2 frames to animate the firing, and it's a little complex. Rest-assured, you can just call player_rocket1() and do just fine (and W_FireRocket()).
Now that you have the player frames for animating, the player will stay in the charging frame until he releases the button or reaches maximum charge (if self.t_width is set to TRUE by the charging function, then the weapon fires itself without permission; you can omit that feature if you like).
The next step is to write the functions that start the charge and manage building the charge. In this code, the start function initializes the variables we're using, and the charge function increases the charge by 1 every 0.2 seconds.
.float chargeLevel should, of course, be in your defs.qc at the bottom.

Code:
void() StartE_Rifle = { self.weaponframe = 0; self.chargeLevel = 1; // always start at 1 self.t_length = gametime + 0.2; // wait this long before increasing charge
self.t_width = 0; // not done yet
};
void() ChargeE_Rifle =
{
// if the charge is below our ammo (we have enough ammo to charge more) and the charge level is less than 5, our max charge, go ahead and charge more
if(self.chargeLevel < self.ammo_cells && self.chargeLevel < 5)
{
// self.t_length is our timer for charging weapons. Don't charge every frame, just every 0.2 seconds.
if(self.t_length < time)
{
self.t_length = time + 0.2;
self.chargeLevel = self.chargeLevel + 1;
}
}
else // if we're at max charge or out of ammo, go ahead and fire
self.t_width = 1;
};

Not so bad so far, I hope. These two functions are called by the frames in player.qc. I'd recommend sticking them in weapons.qc by your weapon fire code (W_FireRocket in your case).
The final step is to modify your firing function to use extra ammo and do extra damage based on the charge. Now, Conquest's ammo and weapon system is *very* different from normal Quake, so I'll be paraphrasing here and writing partial code.

Code:
void() W_FireE_Rifle = { float am, pwr; am = self.ammo_cells; // Only fire if we have ammo and not a zero or negative charge for some reason
if(am <= 0 || self.chargeLevel < 1)
return;
// only use as much ammo as we have
if(self.chargeLevel > am)
self.chargeLevel = am;
// Take ammo
self.currentammo = self.ammo_cells = self.ammo_cells - self.chargeLevel;
// Determine power
pwr = 1.0 + ((self.chargeLevel-1)*0.5); // our rocket's damage will range from 100% to 300% with a charge of 1-5
// fire missile
..... blah blah blah .....
// Set a variable on the missile so we can know, when it's time to explode, how powerful it is
missile.dmg = 120*pwr;
missile.scale = pwr; // make the missile bigger; remove this line if you don't want to include new engine effects etc in your mod
// Note that you could also make the missile move faster/slower based on power.
// Reset charge level, since we're done with it now
self.chargeLevel = 0;
}

Then use self.dmg in the missile's explode function instead of 120. The missile should be more powerful, physically bigger (in new engines with .scale support), and take more ammo when charged.
I hope that's all correct! Like I said, the fire function is all paraphrasing and uncompiled/tested. It works for my e-rifle but I had to change the code to be more like normal quake.
Have fun!
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.

Back to top |

Junrall Joined: 21 Sep 2009 Posts: 136 Location: North West Oregon, USA |

Posted: Sat Jan 30, 2010 8:47 am Post subject: |

Here is my quick and dirty rocket charging code... Open up defs.qc and put the following at the bottom:

Code:
float rockettime; float rocketdamage;

We're going to use "rockettime" to keep track of when the fire button was pressed and we will use rocketdamage to determine how much damage the rocket will do depending on how long the fire button was held.
Open up weapons.qc and find the T_MissileTouch function and replace:

Code:
T_RadiusDamage (self, self.owner, 120, other);

with:

Code:
T_RadiusDamage (self, self.owner, rocketdamage, other);

The rocket will now do "rocketdamage" instead of 120 damage.
Now locate the W_WeaponFrame function. Replace:

Code:
if (self.button0) { SuperDamageSound (); W_Attack (); }

with:

Code:
if (self.button0) //Are we pressing the fire button? { if (rockettime == 0) rockettime = time; //Put game time into rockettime if (self.weapon == IT_ROCKET_LAUNCHER) //If we have the rocket launcher check the stuff below
{
if (rockettime + 2 <= time) //If two seconds passed we now have the maximum strength rocket
{
centerprint(self, "Giant Rocket");
rocketdamage = 360;
}
else if (rockettime + 1 <= time) //If one second passed we now have a medium strength rocket
{
centerprint(self, "Big Rocket");
rocketdamage = 240;
}
else //If less than one second has passed we now have a normal strength rocket
{
centerprint(self, "Normal Rocket");
rocketdamage = 120;
}
return;
}
}
if (rockettime > 0)
{
SuperDamageSound ();
W_Attack ();
rockettime = 0;
}

What we are doing here is checking to see if the fire button is being pressed. If it is, record the current game time into rockettime.
If we are holding the rocket launcher and still holding the fire button then check to see if the game time has gone 1 or 2 seconds past rockettime. If it has then load the the appropriate damage into rocketdamage. Fire weapon after fire button has been released.
rockettime + 1 = slightly more than a second
rockettime + 2 = slightly more than two seconds
You could try something less to get it closer to one and two seconds... I actually enjoyed the effect when I had the numbers set to 5 and 10. At these settings you would have to go hide somewhere to fully charge!
Like I said, this a quick and dirty way to do this. Personally, I like Wazats method as it allows you to use some of the player frames... this will give other players a visual que of someone charging their weapon!
_________________
Good God! You shot my leg off!

Back to top |

LonePossum. Joined: 02 Nov 2009 Posts: 38 |

Posted: Sat Jan 30, 2010 10:34 am Post subject: |

Either of the above should work rather well to to tie in with what he has coded previously from my understanding. Though Wazats E-Rifle Code includes animation frames in which you need to have it look like it is charging so I'd vouce for Wazats if you are going to learn from them. Though Dunralls Code seems easier to merge in with what you have at the moment (I haven't looked through your QCs Ghost).

Back to top |

Wazat Joined: 15 Oct 2004 Posts: 732 Location: Middle 'o the desert, USA |

Posted: Sat Jan 30, 2010 10:04 pm Post subject: |

Junrall's method will work too. I do recommend you make those into .floats instead of floats though, or two players will interfere with each other. Also, if the player fires a rocket and starts charging another before the rocket explodes, that will weaken the rocket in flight. However, this is solved by making "rocketdamage" into a .float. Then it's local to the player, and when you fire the rocket you can copy the damage from the player into the rocket.
// in the fire function, "self" is the player
missile.rockettime = self.rockettime;
...
// in the explode function, "self" is now the rocket
T_RadiusDamage (self, self.owner, self.rocketdamage, other);
Animation frames are a great way to show that you're charging. You could also attach a model or sprite to the weapon muzzle to show the charging effect, if you're using a newer engine & model format. In addition to .scale, good ways to show that the rocket is super-powerful include using a different model for each charge level, changing the projectile's .colormod (change the color w/ new engine feature), doing custom explosion effects (either with a new sprite, or spawning more explosion effects/sprites in random locations around the boom to make it more fantastic looking, or by using new engine effects), and firing multiple rockets with a spread instead of 1 powerful one.
You could even do cool stuff like make the rocket bounce off walls, exploding each time, and/or split into more rockets on bounce. Charging ricochet rockets FTW!
Have fun! And let us know when you have it working, or if you get stuck somewhere.
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.

Back to top |

Junrall Joined: 21 Sep 2009 Posts: 136 Location: North West Oregon, USA |

Posted: Sat Jan 30, 2010 10:12 pm Post subject: |

Wazat wrote:
// in the fire function, "self" is the player missile.rockettime = self.rockettime; ... // in the explode function, "self" is now the rocket T_RadiusDamage (self, self.owner, self.rocketdamage, other);

Lol! That's exactly what I just now did... Wazat, are you spying on my computer screen!? (now nervously looking around my office for spy cameras... wait a second... did I just see some "floaty" eyes run out of the door!?)
_________________
Good God! You shot my leg off!

Back to top |

LonePossum. Joined: 02 Nov 2009 Posts: 38 |

Posted: Sun Jan 31, 2010 3:58 am Post subject: |

There shall be a video of it working some time soon. In this game all of the guns "Charge" and one of the guns that charges happens to shoot ricocheting bullets but as for now he is just working on getting the basics of it sorted. .

Back to top |

Wazat Joined: 15 Oct 2004 Posts: 732 Location: Middle 'o the desert, USA |

Posted: Sun Jan 31, 2010 7:39 pm Post subject: |

Junrall: Of course! I spy on all the members of this forum just in case they come up with a good idea worth stealing. Then I kill them and make it look like an accident (Officer: "It looks like the walrus fell from the floor above and crushed him. Happens all the time."), and steal their ideas for my own. 95% of my modding ideas come from other people, and the remaining 5% come from the voices in my head who claim to be the real me.
Bwahahahaha...
LonePossum: Sounds good. When you get to the ricochet part, let us know. We're happy to help!
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.

Back to top |

redrum Joined: 28 Mar 2007 Posts: 367 Location: Long Island, New York |

Posted: Mon Jun 28, 2010 8:18 pm Post subject: |

I had created the same type of thing for a crossbow in my mod, the arrow flies farther the longer you "pull". Also has exploding tips. _________________ Welcome to the Overlook Hotel 69.113.123.178:27500

Back to top |

Ghost_Fang Joined: 12 Nov 2009 Posts: 162 |

Posted: Mon Jun 28, 2010 8:36 pm Post subject: |

I gave up on it, but now that i think of it, i could easily do it like the nailgun, except like 10 of the functions. player_charge1();..... and on the 10th one actually shoot something. Not really "charging" just giving the illusion.

Back to top |

redrum Joined: 28 Mar 2007 Posts: 367 Location: Long Island, New York |

Posted: Tue Jun 29, 2010 1:51 am Post subject: |

Well here's my code anyway, it may or may not help:

Code:
if (self.button0) // if you're holding the button if (self.weapon == IT_BOW) { if (self.pull < 10) {
self.pull = self.pull + 1;
centerprint (self, "λεεπ πυμμιξη‘\n\n\n\n");
}
if (self.pull >= 10)
if (self.pull < 20)
{
self.pull = self.pull + 1;
centerprint (self, "** keep pulling! **\n\n\n\n");
}
if (self.pull >= 20)
if (self.pull < 30)
{
self.pull = self.pull + 1;
centerprint (self, "*** keep pulling! ***\n\n\n\n");
}
if (self.pull >= 30)
if (self.pull < 40)
{
self.pull = self.pull + 1;
centerprint (self, "**** keep pulling! ****\n\n\n\n");
}
if (self.pull >= 40)
if (self.pull < 50)
{
self.pull = self.pull + 1;
centerprint (self, "***** keep pulling! *****\n\n\n\n");
}
if (self.pull >= 50)
if (self.pull < 60)
{
self.pull = self.pull + 1;
centerprint (self, "****** keep pulling! ******\n\n\n\n");
}
if (self.pull >= 60)
if (self.pull < 70)
{
self.pull = self.pull + 1;
centerprint (self, "******* keep pulling! *******\n\n\n\n");
}
if (self.pull >= 70)
{
self.pull = self.pull + 1;
centerprint (self, "******** ναψινυν ποχες‘ ********\n\n\n\n");
}
}
if (self.pull < 10 && !self.button0)
if (self.pull >= 1 && !self.button0) // no rapid fire
{
self.pull = 0;
}
if (self.pull >= 10 && !self.button0) // you released the button
{
Crossbow();
player_shot1 (); // crossbow shooting animation
}

Code:
void() Crossbow = { msg_entity = self; newmis = spawn (); newmis.voided=0;
newmis.owner = self;
newmis.movetype = MOVETYPE_BOUNCE;
newmis.solid = SOLID_BBOX;
newmis.classname = "arrow";
makevectors (self.v_angle);
if (self.v_angle_x)
{
if (self.pull >= 10)
if (self.pull < 20)
newmis.velocity = v_forward*600 + v_up * 300 + crandom()*v_right*15 + crandom()*v_up*15;
if (self.pull >= 20)
if (self.pull < 30)
newmis.velocity = v_forward*800 + v_up * 275 + crandom()*v_right*13 + crandom()*v_up*13;
if (self.pull >= 30)
if (self.pull < 40)
newmis.velocity = v_forward*1000 + v_up * 250 + crandom()*v_right*11 + crandom()*v_up*11;
if (self.pull >= 40)
if (self.pull < 50)
newmis.velocity = v_forward*1200 + v_up * 225 + crandom()*v_right*9 + crandom()*v_up*9;
if (self.pull >= 50)
if (self.pull < 60)
newmis.velocity = v_forward*1500 + v_up * 200 + crandom()*v_right*7 + crandom()*v_up*7;
if (self.pull >= 60)
if (self.pull < 70)
newmis.velocity = v_forward*2000 + v_up * 175 + crandom()*v_right*5 + crandom()*v_up*5;
if (self.pull >= 70)
newmis.velocity = v_forward*2500 + v_up * 150 + crandom()*v_right*2.5 + crandom()*v_up*2.5;
}
newmis.avelocity = '-50 0 5000'; // pitch & rotation
newmis.angles = vectoangles(newmis.velocity);
newmis.touch = ArrowTouch;
setmodel (newmis, "progs/arrow.mdl");
setsize (newmis, '-1 -1 -1', '-1 -1 -1');
setorigin (newmis, self.origin);
newmis.nextthink = time + 5;
newmis.think = SUB_Remove;
self.pull = 0;
};

_________________
Welcome to the Overlook Hotel 69.113.123.178:27500

Back to top |

Mexicouger Joined: 01 May 2010 Posts: 129 |

Posted: Tue Jun 29, 2010 5:43 am Post subject: |

This is Pure luck I tell ya. I was just about to start the Charging code for my mod, And Now I can just look at this topic! Thanks alot guys. I will now implement charging into Prime!

Back to top |

Ghost_Fang Joined: 12 Nov 2009 Posts: 162 |

Posted: Tue Jun 29, 2010 10:45 pm Post subject: |

Yea, it would have helped back then if i knew "self.button0" is the code to see if the fire button is help down *facepalm*

Back to top |

Mexicouger Joined: 01 May 2010 Posts: 129 |

Posted: Tue Jun 29, 2010 11:38 pm Post subject: |

Don't facepalm yourself for that. We are always learning. You and I have learned alot from that Point and this point. I turned jumping into an impulse command because I didn't know what happened and how the game knew to jump. Now I know

Back to top |

Ghost_Fang Joined: 12 Nov 2009 Posts: 162 |

Posted: Wed Jun 30, 2010 12:30 am Post subject: |

yea but its something really simple as taking a closer look at the code. what makes shotgun different from nialgun and lightning as far as the button press and hold. Not something like AI coding or something (which i still dont fully understand)

Back to top |

Display posts from previous:

| Inside3d Forums Forum Index -> QuakeC Programming | All times are GMT Goto page 1, 2 Next
Page 1 of 2

Jump to:

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Powered by phpBB © 2004 phpBB Group