Inside3D!
     

Charge Shot
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming
View previous topic :: View next topic  
Author Message
Ghost_Fang



Joined: 12 Nov 2009
Posts: 162

PostPosted: Sat Jan 30, 2010 6:15 am    Post subject: Charge Shot Reply with quote

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
View user's profile Send private message
Wazat



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

PostPosted: Sat Jan 30, 2010 7:29 am    Post subject: Reply with quote

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. Wink

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
View user's profile Send private message MSN Messenger
Junrall



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

PostPosted: Sat Jan 30, 2010 8:47 am    Post subject: Reply with quote

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
View user's profile Send private message
LonePossum.



Joined: 02 Nov 2009
Posts: 38

PostPosted: Sat Jan 30, 2010 10:34 am    Post subject: Reply with quote

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
View user's profile Send private message
Wazat



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

PostPosted: Sat Jan 30, 2010 10:04 pm    Post subject: Reply with quote

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! Wink

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
View user's profile Send private message MSN Messenger
Junrall



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

PostPosted: Sat Jan 30, 2010 10:12 pm    Post subject: Reply with quote

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! Laughing 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
View user's profile Send private message
LonePossum.



Joined: 02 Nov 2009
Posts: 38

PostPosted: Sun Jan 31, 2010 3:58 am    Post subject: Reply with quote

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. Very Happy.
Back to top
View user's profile Send private message
Wazat



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

PostPosted: Sun Jan 31, 2010 7:39 pm    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
redrum



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

PostPosted: Mon Jun 28, 2010 8:18 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
Ghost_Fang



Joined: 12 Nov 2009
Posts: 162

PostPosted: Mon Jun 28, 2010 8:36 pm    Post subject: Reply with quote

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
View user's profile Send private message
redrum



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

PostPosted: Tue Jun 29, 2010 1:51 am    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
Mexicouger



Joined: 01 May 2010
Posts: 129

PostPosted: Tue Jun 29, 2010 5:43 am    Post subject: Reply with quote

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
View user's profile Send private message Yahoo Messenger MSN Messenger
Ghost_Fang



Joined: 12 Nov 2009
Posts: 162

PostPosted: Tue Jun 29, 2010 10:45 pm    Post subject: Reply with quote

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
View user's profile Send private message
Mexicouger



Joined: 01 May 2010
Posts: 129

PostPosted: Tue Jun 29, 2010 11:38 pm    Post subject: Reply with quote

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
View user's profile Send private message Yahoo Messenger MSN Messenger
Ghost_Fang



Joined: 12 Nov 2009
Posts: 162

PostPosted: Wed Jun 30, 2010 12:30 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    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