Announcement

Collapse
No announcement yet.

I am Legend (The Code Chronicles)

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • I am Legend (The Code Chronicles)

    Legend! Place all your code related questions here! That way I don't have to go to multiple forum threads. hehe! Also check all of the previous threads as I have answered all your questions up to this point I believe. Also, lemme see some reps for all the effort.


    Bon App�tit
    Last edited by PrimalLove; 08-20-2014, 10:43 AM.

  • #2
    Bump

    Comment


    • #3
      Lol. Thanks Primal. I checked all your answers. I see where I messed up in most of them. STill a little fuzzy on the reload code.

      I see where I screwed up on the weapon adding code. I forgot to add the line you mentioned and just copied and pasted the regular call to the Riot shotgun.

      I did use your recoil code and now it works as intended for the rc. I just upped the force a bit. I kept it the same for the ssg though cause I intended for the player to be able to do a mini rocket jump with the ssg. It's pretty fun, but not game breaking due to the firing time for the ssg and you have to work it just right in order to get the most height out of it. I also added proportional fall damage so if you go to high, it's gonna sting when you land.

      As for the riot shotgun calling W_firerc twice in the player.cq, it was intentional. If you look close, it was so that it lines up with the animations of the gun. That's why the fire command itself is set to only use one ammo. And if you watch the ammo counter, you'll see that the first shot uses two ammo for some reason, and the second uses one. If it's called twice, and it's only set to use 1 shell, shouldn't it use a total of 2 each time it's fired? And if it was because it's called twice, why would it use 3 shells instead of 4? That is what really baffles me and has me convinced that I must have screwed something up somewhere else that I can't find.

      I had it so the shell usage is only set to -1, but it still does this for some reason, and not sure where I did something wrong. If I take out the second call, then it will screw with the knock back working the way I want and although, it will probably only use 2 ammo like I want, it won't work quite right. Basically, I want the player to commit to using two shells, but also want each shot to fire separate, if that makes sense.

      This is where I'm pulling my hair out.

      ImpulseCommands (); //This allows for additional Impulse commands to be used like switching weapons
      If I remove this, will it make it so the player cannot switch weapons while reloading?

      if (time < self.attack_finished)
      {
      if (self.weapon == IT_GRENADE_LAUNCHER && !self.button0 && self.ammo_rockets > 0)
      self.attack_finished = time;
      else if (self.weapon == IT_SHOTGUN && !self.button0 && self.ammo_shells > 0)
      self.attack_finished = time;
      return;

      Basically it looks for the weapon in question first, and if you do not have the fire button pressed, and you are not out of ammo/clip is not empty, then the function will end because you don't want to reload yet. You already have something else in store for it. This goes for Grenade Launcher and the basic Shotty.
      Ok, so I want to add the rc here, but I want the reload to work a bit differently. I'm getting stumped on that. I'm guessing I will need to write a completely different reload function? This code doesn't reload only when the ammo is equal to zero. It reloads as long as the ammo is less than the clip size. I already got the 12 clip drum size for the rc working how I want, but only want it to reload when the ammo is equal to 0.

      self.currentammo = self.currentammo + 1;
      self.attack_finished = time;sound (self, CHAN_ITEM, "weapons/grenade_load.wav", 1, ATTN_NORM);
      I figured I could just do: "self.currentammo = self.currentammo + 12;
      self.attack_finished = time;sound (self, CHAN_ITEM, "weapons/rcreload.wav", 1, ATTN_NORM);" To reload the whole drum. But how do I make it so it only does this when the current ammo is = 0? But how do I define the reload time as well?

      Also, will there be a way to keep track of how much ammo is left in the drum at a given time? I am also implementing gun jamming on this one to make up for how powerful it is, but want the player to lose the remainder of the whole drum when un-jamming instead of just a single shell.

      Thanks again for the ton of help Primal.

      Nice title for the thread btw.
      Last edited by Legend; 08-19-2014, 12:51 PM.

      Comment


      • #4
        OK. I'm taking a quickie break from the riot gun since it's driving me batty. Now I got something else.

        Here is my code for the Axe:

        Code:
        ================
        W_FireAxe
        ================
        */
        void() W_FireAxe =
        {
        	local	vector	source;
        	local	vector	org;
        	local	float	r, strikespeed;
        
        	strikespeed = self.attack_finished - time;
        	
        	makevectors (self.v_angle);
        	source = self.origin + '0 0 16';
        	if (strikespeed <= 0.35) // first strike!
        		traceline (source, source + v_forward*100, FALSE, self);
        	else
        		traceline (source, source + v_forward*64, FALSE, self);
        		
        	if (trace_fraction == 1.0)
        		return;
        		
        	org = trace_endpos - v_forward*4;
        	
        	if (self.button0) // rebound axe
        	{
        		sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
        		r = random();
        		if (r < 0.25)
        			player_axe1 ();
        		else if (r<0.5)
        			player_axeb1 ();
        		else if (r<0.75)
        			player_axec1 ();
        		else
        			player_axed1 ();
        		self.attack_finished = time + 0.6;		
        	}
        		
        	if (trace_ent.takedamage)
        	{
        		trace_ent.axhitme = 1;
        		if (!(trace_ent.flags & FL_MONSTER) && !(trace_ent.flags & FL_CLIENT))
        		{
        			T_Damage (trace_ent, self, self, 20);
        			sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
        			WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
        			WriteByte (MSG_BROADCAST, TE_GUNSHOT);
        			WriteCoord (MSG_BROADCAST, org_x);
        			WriteCoord (MSG_BROADCAST, org_y);
        			WriteCoord (MSG_BROADCAST, org_z);
        		}
        		else if (strikespeed <= 0.35) // first strike!
        		{
        			SpawnBlood (org, '0 0 0', 50);
        			sound (self, CHAN_WEAPON, "zombie/z_miss.wav", 1, ATTN_NORM);
        			sound (trace_ent, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NORM);
        			SpawnMeatSpray (self.origin + v_forward*16, crandom() * v_right * 8);
        			T_Damage (trace_ent, self, self, 15);
        			
        			if(trace_ent.classname == "door")      
                            return;                         //Don't give life for secret doors.
                    if (self.health >= 75)
                            return;                         //Don't give life over 75.
                    else
                            self.health = self.health + 3; [COLOR="DarkOrange"]// I want to give random health instead of consistent[/COLOR]
                    if (self.health > 75)
                                self.health = 75;              //Make sure they don't go above 75 health.
        		}
        		else
        		{
        			SpawnBlood (org, '0 0 0', 10);
        			sound (self, CHAN_WEAPON, "zombie/z_miss.wav", 0.8, ATTN_NORM);
        			T_Damage (trace_ent, self, self, 10);
        		}
        	}
        	else
        	{	// hit wall
        		sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
        		WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
        		WriteByte (MSG_BROADCAST, TE_GUNSHOT);
        		WriteCoord (MSG_BROADCAST, org_x);
        		WriteCoord (MSG_BROADCAST, org_y);
        		WriteCoord (MSG_BROADCAST, org_z);
        	}
        };
        I'm not going off the original axe code obviously. I'm going off the one found in the moattdd video. So I got the life sucking axe to work, but I nerfed the damage. But I can't get it to give a small amount of random health, like 5 or 6 tops, instead of a consistent amount.

        I tried using "self.health = self.health = 1 + 2*random;" in the line above, but I get an error when compiling.

        I would also like it to only add health on the killing blow and not each single hit. And to gib zombies but not actually gain health from zombies. I have the feeling, this is something I will have to do in the actual enemy code and not the weapons.qc?

        On a side note, is there a way to do a trace function that goes in the opposite direction that the player moves their view?
        Last edited by Legend; 08-19-2014, 01:03 PM.

        Comment


        • #5
          Woot! I fixed the problem with the riot shotgun using too much ammo! On my own too!

          it was here:
          Code:
          	else if (self.weapon == IT_RSHOT)  //  Riot Shotgun
          	{
          		player_rc1 ();
          		self.attack_finished = time + 0.5;
                          W_FireRC ();  [COLOR="DarkOrange"]// This didn't need to be there[/COLOR]
          	}
          	else if (self.weapon == IT_NAILGUN)
          I just needed to take out that last "W_FireRC ();"

          I kept over looking it cause I thought it was needed.

          Now on to reloading, then jamming!

          Though I am having an issue with picking up the rc. Pressing 3 doesn't seem to select it. and it doesn't cycle forward correctly at first until after I pick up the nail gun as well. It will cycle backwards to it, but not forward until after I pick up the nail gun.

          ***EDIT***
          Tried to get the reloading done. I used this code at the bottom:

          Code:
          ============
          W_WeaponFrame
          
          Called every frame so impulse events can be handled as well as possible
          ============
          */
          void() W_WeaponFrame =
          {
          	
          	if (time < self.attack_finished)
          	{
          		if (self.weapon == IT_GRENADE_LAUNCHER && !self.button0 && self.ammo_rockets > 0)
          			self.attack_finished = time;
          		else if (self.weapon == IT_SHOTGUN && !self.button0 && self.ammo_shells > 0)
          			self.attack_finished = time;
          		else if (self.weapon == IT_RSHOT && !self.button0 && self.ammo_shells > 0)
          			self.attack_finished = time;	
          		return;
          	}
          		
          	ImpulseCommands ();
          	
          // check for attack
          	if (self.button0)
          	{
          		SuperDamageSound ();
          		W_Attack ();
          	}
          	else if (self.weapon == IT_GRENADE_LAUNCHER)
          	{ // autoload nade launcher
          		if (self.currentammo < 3 && self.currentammo < self.ammo_rockets)
          		{
          			if (self.currentammo < 1 && self.cnt != 1)
          			{
          				self.currentammo = 0;
          				self.cnt = 1;
          				sound (self, CHAN_ITEM, "weapons/grenade_open.wav", 1, ATTN_NORM);
          			}
          			if ((time > self.attack_finished + 0.41 && self.currentammo > 0) || time > self.attack_finished + 0.56)
          			{
          				self.currentammo = self.currentammo + 1;
          				self.attack_finished = time;
          				sound (self, CHAN_ITEM, "weapons/grenade_load.wav", 1, ATTN_NORM);
          			}
          		}
          		else if (self.cnt == 1 && time > self.attack_finished + 0.41)
          		{
          			sound (self, CHAN_ITEM, "weapons/grenade_close.wav", 1, ATTN_NORM);
          			self.cnt = 0;
          		}
          	}
          	else if (self.weapon == IT_SHOTGUN)
          	{ // autoload shotgun
          		if (self.currentammo < 6 && self.currentammo < self.ammo_shells)
          		{
          			if (self.currentammo < 1 && self.cnt != 1)
          			{
          				self.currentammo = 0;
          				self.cnt = 1;
          			}
          			if ((time > self.attack_finished + 0.41 && self.currentammo > 0) || time > self.attack_finished + 0.56)
          			{
          				self.enemy = world;
          				self.currentammo = self.currentammo + 1;
          				self.attack_finished = time;
          				sound (self, CHAN_ITEM, "weapons/sgload.wav", 1, ATTN_NORM);
          			}
          		}
          		else if (self.cnt == 1 && time > self.attack_finished + 0.41)
          		{
          			sound (self, CHAN_ITEM, "weapons/sgpump.wav", 1, ATTN_NORM);
          			self.cnt = 0;
          		}
          	}
          	else if (self.weapon == IT_RSHOT)
          	{ // autoload Riot Shotgun
          		if (self.currentammo = 0 && self.currentammo < self.ammo_shells)
          		{
          			if (self.currentammo < 1 && self.cnt != 1)
          			{
          				self.currentammo = 0;
          				self.cnt = 1;
          			}
          			if ((time > self.attack_finished + 0.41 && self.currentammo > 0) || time > self.attack_finished + 0.56)
          			{
          				self.enemy = world;
          				self.currentammo = self.currentammo + 12;
          				self.attack_finished = time + 0.8;
          				sound (self, CHAN_ITEM, "weapons/newdsdbload.wav", 1, ATTN_NORM);
          			}
          		}
          		else if (self.cnt == 1 && time > self.attack_finished + 0.41)
          		{
          			sound (self, CHAN_ITEM, "weapons/sgpump.wav", 1, ATTN_NORM);
          			self.cnt = 0;
          		}
          	}
          
          };
          I thought this could get it to where this would reload all 12 shells and only when the current ammo was equal to 0 and make a semi-long reload time. Apparently, I was wrong. When I play, the rc is always at 0 ammo. I also configured the corresponding functions higher in the code to reflect the ammo usage already similar to the others.
          Last edited by Legend; 08-19-2014, 02:11 PM.

          Comment


          • #6
            Woot! I fixed the problem with the riot shotgun using too much ammo! On my own too!

            it was here:
            Code:
            else if (self.weapon == IT_RSHOT) // Riot Shotgun
            {
            player_rc1 ();
            self.attack_finished = time + 0.5;
            W_FireRC (); // This didn't need to be there
            }
            else if (self.weapon == IT_NAILGUN)
            Yes I should have taken it away from here as well. My bad. The point was you needed to lose one of them. This one isn't needed and works anyway because player_rc1() at the beginning tells the animation to begin here. So since you already defined it twice in the animations it's not needed here. That will allow for a slight delay and to match your animations correctly. Nice work.

            This is where I'm pulling my hair out.

            ImpulseCommands (); //This allows for additional Impulse commands to be used like switching weapons
            If I remove this, will it make it so the player cannot switch weapons while reloading?
            LOL! Don't take that out or you can't change weapons, or any of the impulses defined in the Impulse Command function. NO bueno.

            Ok maybe I should explain more about the reloading.

            Code:
            else if (self.weapon == IT_RSHOT)
            	{ // autoload Riot Shotgun
            		if (self.currentammo = 0 && self.currentammo < self.ammo_shells) [COLOR="Red"]//You can't have self.currentammo = 0 here. This is what determines the amount of ammo to give back during the reload process. [/COLOR]
            		{
            			if (self.currentammo < 1 && self.cnt != 1)[COLOR="red"] //This is saying if ammo is less than 1 do the next instructions which is to set ammo to 0 and make yourself busy[/COLOR]
            			{
            				self.currentammo = 0;
            				self.cnt = 1;
            			}
            			if ((time > self.attack_finished + 0.41 && self.currentammo > 0) || time > self.attack_finished + 0.56)[COLOR="red"] //This part is actually setting it up so that reload happen during the animation process or in between assuming you are not holding the button down.  That is why it's an auto reloader. It reloads even if you haven't completely run out of ammo.  All of your guns currently do this. But on this gun I suppose it makes less sense because it has a drum. [/COLOR]
            			{
            				self.enemy = world;
            				self.currentammo = self.currentammo + 12; [COLOR="red"]//This cannot be set to 12 because it will just auto load to 12 between shots. You don't want that. [/COLOR]
            				self.attack_finished = time + 0.8;
            				sound (self, CHAN_ITEM, "weapons/newdsdbload.wav", 1, ATTN_NORM);
            			}
            		}
            		else if (self.cnt == 1 && time > self.attack_finished + 0.41)
            		{
            			sound (self, CHAN_ITEM, "weapons/sgpump.wav", 1, ATTN_NORM);
            			self.cnt = 0;
            So how can we fix this? Well a hack solution to this problem without needing to rewrite anything is simply do this:


            Code:
            else if (self.weapon == IT_RSHOT)
            	{ // autoload Riot Shotgun
            		if (self.currentammo [COLOR="Yellow"]< 12[/COLOR] && self.currentammo < self.ammo_shells)
            		{
            			if (self.currentammo < 1 && self.cnt != 1)
            			{
            				self.currentammo = 0;
            				self.cnt = 1;
            			}
            		
            		}
            		else if (self.cnt == 1 && time > self.attack_finished + 0.41)
            		{
            			sound (self, CHAN_ITEM, "weapons/sgpump.wav", 1, ATTN_NORM);
            			self.cnt = 0;
            		}
            You can see I just simply removed that section and changed the yellow highlighted code to that instead of =0. Now when you get to the end of your clip it will wait til you press the button to fire again and will set you back to 12 as long as you set your current ammo to 12 in W_SetCurrentAmmo and play the reload sound. Note you may have to adjust timing so the animations and sound match up. If you want it so you can reload like the shotgun then just uncomment that line and it will work provided you have Fire_RC and other functions set up correctly.

            As for the Axe. Have we forgotten random()? Just use this:

            Code:
            self.health = self.health + 10*random();


            Bon App�tit
            Last edited by PrimalLove; 08-19-2014, 11:43 PM.

            Comment


            • #7
              Here are a few more suggestions to doing reload that you might find intriguing and get some inspiration.

              THIS is a basic Tut for reloading that can be easily advanced upon that uses a different method than you are currently using and is pretty versatile. You'll need to add sound effects to the code but it works quite nice and like I said is pretty easily modifiable. The code currently doesn't display the clip ammo correctly in the HUD but that is easily fixed with some additional code.

              Next I highly recommend taking a look at Navy Seal mod. They have a pretty no nonsense version of this too. It looks more complex than it really is. Mostly it looks complicated because they have each weapon in its own qc but its well put together and might give you some inspiration. Check out the src here. Good luck!

              Comment


              • #8
                Thanks for the link to the tutorial. I think I will go that route for handling the riot shotgun reloading and clip instead of adapting the existing one for the shotty and gl. I think it will work better and allow me to implement the jamming the way I want.

                Doh! on the random. but how does defining the range work? I want it to add between 1 and 6 health when the enemy is killed. Also any ideas on how to make it not work on zombies, but gib zombies instead of leaching life?

                I'm still trying to figure out how to define time exactly in qc. As in how seconds are defined.

                And how do I determine a 1 in 36 chance for something?

                ***Edit***
                Bollocks! can't get the new code to compile now. I'm guessing the tutorial may not be indented correctly?


                I get one error that I'm pretty sure has to do with indentation because it says unknown value "void".

                The other is "error type mismatch for = (pointer and fieldfloat)"

                this error corresponds to:

                Code:
                else if (self.weapon == IT_RSHOT)  //  Riot shotgun
                	{
                		self.currentammo = rcdrum;  [COLOR="DarkOrange"]// this line[/COLOR]
                		self.weaponmodel = "progs/v_rshot.mdl";
                		self.weaponframe = 0;
                		self.items = self.items | IT_SHELLS;
                	}
                under w_setcurrentammo. rcdrum is the float that I defined in defs.cq.

                ***edit2***
                nm about the rcdrum issue. I should have made it "self.rcdrum".

                Still trying to fix the void issue though. I think I got something off in here:
                Code:
                	else if (self.weapon == IT_RSHOT)  //  Riot Shotgun
                	{
                	if (self.rcdrum > 0) // are there shells in the drum?
                	{
                		player_rc1 ();
                		self.attack_finished = time + 0.4;
                	}
                	if (self.rcdrum == 0) // If the drum is empty
                	{
                	reloadrc (); // reload riot shotgun drum
                	}
                Last edited by Legend; 08-20-2014, 04:34 AM.

                Comment


                • #9
                  Originally posted by Legend View Post
                  Doh! on the random. but how does defining the range work? I want it to add between 1 and 6 health when the enemy is killed. Also any ideas on how to make it not work on zombies, but gib zombies instead of leaching life?

                  I'm still trying to figure out how to define time exactly in qc. As in how seconds are defined.

                  And how do I determine a 1 in 36 chance for something?
                  Ok a little explanation of random(). This is a built in function in Quake C and Also C programming language (rand() in C). It essential returns a "random" number. By itself it's pretty pointless. But add/subtract/divide/multiple a number along with it and you get some variety. You already have some experience with this if you remember back to your Drop_Essence code in item.qc. Specifically this:

                  Code:
                  item.health = 6 + 3*random();
                  So what exactly does the above mean? It means this item has 6 health plus a random number between 1 and 3. You can actually write this several different ways to mean the same thing but lets just use this as our basic framework to apply what you need.

                  So when i gave you this code below for your axe:

                  Code:
                  self.health + 10*random();
                  This literally means plus a random number between 1 and 10.

                  So for the example you gave of 1 and 36 it would simply be

                  Code:
                  36*random()
                  Now like I said it can be written differently than this and still mean the same thing so you may see this in Quake C in different formats but just make sure to pay attention to the syntax.

                  For instance:

                  Code:
                  random()*100 + 1
                  This is a random number between 1 and 100.

                  If you want to round the number up or down (remember random() does not return whole numbers) you'll need to either use ceil or floor. Floor rounds down and ceil rounds up. It makes sense because floor is on the ground and ceiling is up LOL

                  Example:

                  Code:
                  floor(random()*10 + 6)
                  This should give you the basic understanding to apply this to your Quake C code. If any other questions let me know.

                  Now lets move on to your axe question.. This one is interesting....

                  Ah I have something for you. And we'll get you some more exposure to using the random() function. Hehe! This will be a learning experience.

                  We could just add the whole thing into the existing W_FireAxe function but lets give it some style!

                  Right above the W_FireAxe and after crandom() put this new little gem of a function:

                  Code:
                  void(float chance) KillZombie =
                  {
                     if (trace_ent.classname != "monster_zombie")  return;
                     chance = chance * 0.01;
                        if (random() < chance)
                        T_Damage (trace_ent, self, self, 500);
                  	else	
                        T_Damage (trace_ent, self, self, 20);
                  };
                  So what does this do? Simple, if you run this function, if the monster isn't a zombie end the function now. Otherwise, setup a random chance out of some defined number (more on this later) and if the chance is greater the random number do 500 damage to the monster (zombie) Basically 500 damage will gib the zombie. Instagib Else, if random is greater then do 20 damage (default damage amount of an axe hit). If it doesn't make the random chance you just hit the zombie with the same damage you always would.

                  What's cool about having this in its own function is you could use this theoretically with any additional weapon you decide to make or if you want to add a random chance of gibbing/killing a zombie with the regular weapons like the super shotgun. It all becomes possible now.

                  Ok so where do you call this in the W_FireAxe?

                  I'm gonna throw the code up that you had in this post to show you where to put it and why:


                  Code:
                  /*
                  ================
                  W_FireAxe
                  ================
                  */
                  void() W_FireAxe =
                  {
                  	local	vector	source;
                  	local	vector	org;
                  	local	float	r, strikespeed;
                  
                  	strikespeed = self.attack_finished - time;
                  	
                  	makevectors (self.v_angle);
                  	source = self.origin + '0 0 16';
                  	if (strikespeed <= 0.35) // first strike!
                  		traceline (source, source + v_forward*100, FALSE, self);
                  	else
                  		traceline (source, source + v_forward*64, FALSE, self);
                  		
                  	if (trace_fraction == 1.0)
                  		return;
                  		
                  	org = trace_endpos - v_forward*4;
                  	
                  	if (self.button0) // rebound axe
                  	{
                  		sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
                  		r = random();
                  		if (r < 0.25)
                  			player_axe1 ();
                  		else if (r<0.5)
                  			player_axeb1 ();
                  		else if (r<0.75)
                  			player_axec1 ();
                  		else
                  			player_axed1 ();
                  		self.attack_finished = time + 0.6;		
                  	}
                  		
                  	if (trace_ent.takedamage)
                  	{
                  		trace_ent.axhitme = 1;
                  		
                  		[COLOR="Yellow"]if (trace_ent.classname == "monster_zombie")   
                  					
                  			KillZombie (30);[/COLOR]
                  		
                  		if (!(trace_ent.flags & FL_MONSTER) && !(trace_ent.flags & FL_CLIENT))
                  		{
                  			T_Damage (trace_ent, self, self, 20);
                  			sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
                  			WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
                  			WriteByte (MSG_BROADCAST, TE_GUNSHOT);
                  			WriteCoord (MSG_BROADCAST, org_x);
                  			WriteCoord (MSG_BROADCAST, org_y);
                  			WriteCoord (MSG_BROADCAST, org_z);
                  		}
                  		else if (strikespeed <= 0.35) // first strike!
                  		{
                  			SpawnBlood (org, '0 0 0', 50);
                  			sound (self, CHAN_WEAPON, "zombie/z_miss.wav", 1, ATTN_NORM);
                  			sound (trace_ent, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NORM);
                  			SpawnMeatSpray (self.origin + v_forward*16, crandom() * v_right * 8);
                  			T_Damage (trace_ent, self, self, 15);
                  			
                  			if(trace_ent.classname == "door")      
                                      return; 					//Don't give life for secret doors.
                  			[COLOR="orange"]if (trace_ent.classname == "monster_zombie")
                  			        return;[/COLOR]
                              if (self.health >= 100)
                                      return;                         //Don't give life over 100.
                              else
                  			
                                      self.health = self.health + 3; // I want to give random health instead of consistent
                              if (self.health > 100)
                                          self.health = 100;              //Make sure they don't go above 100 health.
                  		}
                  		else
                  		{
                  			SpawnBlood (org, '0 0 0', 10);
                  			sound (self, CHAN_WEAPON, "zombie/z_miss.wav", 0.8, ATTN_NORM);
                  			T_Damage (trace_ent, self, self, 10);
                  		}
                  	}
                  	else
                  	{	// hit wall
                  		sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
                  		WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
                  		WriteByte (MSG_BROADCAST, TE_GUNSHOT);
                  		WriteCoord (MSG_BROADCAST, org_x);
                  		WriteCoord (MSG_BROADCAST, org_y);
                  		WriteCoord (MSG_BROADCAST, org_z);
                  	}
                  };
                  Ok lets talk about the yellow highlighted code first. It goes here because this is the beginning of the code that tells what happens when the axe hits something and needs to do damage.

                  Basically it is saying if the monster I hit is a zombie, then run the zombie kill function. Notice inside of the () i placed the number 30. Why? If you go back to the original function it needs a number to be defined as the chance value. This is where you define it. 30 is a 30% chance from each hit. Not each time you press the button, but each axe swing. So this takes care of gibbing/killing zombies. You can adjust the chance number to your liking.

                  Now we gotta fix it so they don't give you health. Not a problem. Check out the orange code. Much like the above lines for the door, this simply says if the target is a zombie, end the function here. Thus it will not do the health code.


                  Voila! Bon App�tit!
                  Last edited by PrimalLove; 08-20-2014, 06:02 AM.

                  Comment


                  • #10
                    Code:
                    else if (self.weapon == IT_RSHOT)  //  Riot Shotgun
                    	{
                    	if (self.rcdrum > 0) // are there shells in the drum?
                    	{
                    		player_rc1 ();
                    		self.attack_finished = time + 0.4;
                    	}
                    	if (self.rcdrum == 0) // If the drum is empty
                    	{
                    	reloadrc (); // reload riot shotgun drum
                    	}
                            } [COLOR="Red"]//This needs to be added :)[/COLOR]
                    It's hard to tell without seeing all the code in context but looking at the tutorial they left out a } at the end of this code and it looks like you did too. Try that and it should fix it. Cheers.


                    This might make it easier to see why...

                    Code:
                    else if (self.weapon == IT_RSHOT)  //  Riot Shotgun
                    	[COLOR="Red"]{[/COLOR]
                    	    if (self.rcdrum > 0) // are there shells in the drum?
                    	       [COLOR="yellow"]{[/COLOR]
                    		player_rc1 ();
                    		self.attack_finished = time + 0.4;
                    	       [COLOR="Yellow"]}[/COLOR]
                    	   if (self.rcdrum == 0) // If the drum is empty
                    	       [COLOR="orange"]{[/COLOR]
                    	   reloadrc (); // reload riot shotgun drum
                    	       [COLOR="Orange"]}[/COLOR]
                            [COLOR="red"]}[/COLOR]
                    Last edited by PrimalLove; 08-20-2014, 09:53 AM.

                    Comment


                    • #11
                      If you don't currently use one of these I recommend Scite or Notepad++ for editing. If you want you could also use Qcide which I use most of the time myself for Quake C.

                      All of these will make it easier to catch these little things like missing },{,;, etc. Qcide is basically Scite just customized for quake C.


                      EDIT:

                      I missed this quote:

                      I'm still trying to figure out how to define time exactly in qc. As in how seconds are defined.
                      Ah.... time... so illusive.... :/ LOL! Here is a good reference to look at to get familiar with Quake C Global Variables Although they aren't very descriptive, they can help you identify things you see in code that you are less familiar with and need some background in it's function and purpose.

                      from the website:

                      float time; // in seconds
                      The current game time, a floating point value in seconds. Note that because the entities in the world are simulated sequentially, time is NOT strictly increasing. An impact late in one entity's time slice may set time higher than the think function of the next entity. The difference is limited to 0.1 seconds.

                      So what does this mean? All values are done in seconds. Time is counted in seconds. That is it. Also no "time" is being kept by the engine. It simply "counts" the time you define for it and then after that time is over, it will go to the next line. So lets go to an example you have dealt with recently.

                      Code:
                      if (self.currentammo < 1 && self.cnt != 1)
                      			{
                      				self.currentammo = 0;
                      				self.cnt = 1;
                      			}
                      			[COLOR="Red"]if ((time > self.attack_finished + 0.41 && self.currentammo > 0) || time > self.attack_finished + 0.56)[/COLOR]
                      			{
                      				self.enemy = world;
                      				self.currentammo = self.currentammo + 1;
                      				self.attack_finished = time;
                      				sound (self, CHAN_ITEM, "weapons/sgload.wav", 1, ATTN_NORM);
                      			}
                      		}
                      		else if (self.cnt == 1 && time > self.attack_finished + 0.41)
                      		{
                      			sound (self, CHAN_ITEM, "weapons/sgpump.wav", 1, ATTN_NORM);
                      			self.cnt = 0;
                      		}

                      Red: This says if time is greater than when attack routine is finished plus 2/5 of a second has gone by and your current ammo is greater than 0 or time is greater than 1/2 a second then move to next instructions.
                      This routine gets run over and over as long as you have more than 0 in your clip. The time is used here to delay when it happens so that it looks natural with the animations, etc. You can easily increase or decrease this time to try and get the look and feel right. In this case, time delay is used to smooth out transitions in animations and determine when routines should be run.

                      Each time this part of the code repeats it will run the routine defined within it. Which is this:

                      Code:
                                            self.enemy = world;
                      				self.currentammo = self.currentammo + 1;
                      				self.attack_finished = time;
                      				sound (self, CHAN_ITEM, "weapons/sgload.wav", 1, ATTN_NORM);
                      This repeats until you run out of ammo in the clip. Basically it changes it to having no enemies (briefly spoke of why before) and then the next line is the heart and soul of your autoloader. This says each time you run this routine add 1 to current ammo. That's how it knows to keep loading assuming you aren't holding the button down. Next it is setting the finished attack to time which was defined in the red code. Basically it is resetting it for the next time it is used. This has to happen or the time will keep adding on. Next it plays the the reload sound.

                      Next:

                      Code:
                      else if (self.cnt == 1 && time > self.attack_finished + 0.41)
                      		{
                      	sound (self, CHAN_ITEM, "weapons/sgpump.wav", 1,
                      Ok here it is saying if you are busy and time is greater than 2/5 of a second after you finished your attack routine, then play the pump sound. So earlier in the code this was defined:

                      Code:
                      if (self.currentammo < 1 && self.cnt != 1)
                      		{
                      		self.currentammo = 0;
                      		self.cnt = 1;
                      		}
                      This means if your current ammo is less than 1 and you aren't busy then your clip is out and you are now busy (ready to reload).

                      So getting back to this:

                      Code:
                      else if (self.cnt == 1 && time > self.attack_finished + 0.41)
                      		{
                      			sound (self, CHAN_ITEM, "weapons/sgpump.wav", 1, ATTN_NORM);
                      			self.cnt = 0;
                      		}
                      We can see if that other code routine ran then it defined the gun to have no ammo in clip and made it ready to receive ammo. Once it has done so then if still busy and time is greater than 2/5 a second after your finished your attack then use pump action (play sound) and set yourself to not busy.

                      Why does it do this? This gets called once you have finished reloading after you beginning to receive ammo into your clip. This just makes sure the pump action sound matches with around the same time as the load sound would. Thus once you have finished loading you should hear the pump action right at the point that you finished reloading. (Hopefully that's not confusing)

                      Another example of time usage that is most common:

                      Code:
                      void() item_megahealth_rot =
                      {
                      	other = self.owner;
                      	
                      	if (other.health > other.max_health)
                      	{
                      		other.health = other.health - 1;
                      		self.nextthink = time + 1;
                      		return;
                      	}
                      As you can see here, it is often used in nextthink. So in this case, megahealth will give you alot of health but slowly makes it go away over time. This is the function that does the taking. hehe So basically once this function runs it will take one health from your additional health (other.health) and then wait 1 second before moving to the end of the function. That gives a 1 second delay between when this routine will run again.

                      And finally:


                      Code:
                      if (deathmatch != 2)		// deathmatch 2 is the silly old rules
                      		{
                      			if (deathmatch)
                      				self.nextthink = time + 20;
                      			self.think = SUB_regen;
                      		}
                      This is an example from an item in death match. Basically, if the rules/game type is deathmatch wait 20 seconds before this item regenerates. So if you picked this item up in multiplayer it would regenerate/respawn in 20 seconds. I hope this gives you some prespective on using time in Quake C. Cheers.
                      Last edited by PrimalLove; 08-20-2014, 09:29 AM.

                      Comment


                      • #12
                        Edited above.

                        Comment


                        • #13
                          Ok, I got it to compile. But now when I switch to the riot gun, it has 0 ammo and won't fire. I removed all the old reload code based on the shotty and gl already. I'm not sure where I screwed the pooch this time.

                          reload code:
                          Code:
                          =====================
                          Reload Riot Shotgun
                          =====================
                          */
                          
                          void() reloadrc
                          {
                          
                          local .float shots_fired; // A float that will only be used in this function and cant be called by others
                          
                          if (self.weapon == IT_RSHOT) // Checks if the current weapon is the Riot Shotgun
                          {
                          self.shots_fired = 12 - self.rcdrum; // calculate the shots fired from drum
                          if (self.ammo_shells > self.shots_fired) // If we have more shells in our inventory then those that need to be reload then its easy.)
                          {
                          self.ammo_shells = self.ammo_shells - self.shots_fired; // We take the shots fired and take that away from out inventory.
                          self.rcdrum = 12; // refill the drum.
                          }
                          else
                          {
                          self.rcdrum = self.rcdrum + self.ammo_shells; // Since the ammo in ammo_shells is less than the shots fired we can add that to the drum
                          self.ammo_shells = 0; // set the shells to zero because there are none left.
                          }
                          }
                          self.currentammo = self.rcdrum; // Update the current ammo (shown on the Quake hud) to show how many bullets are left in the inventory
                          self.attack_finished = time + 4; // Set the next attack four seconds from now, you cant shoot for four seconds.
                          };
                          Fire code:
                          Code:
                          ================
                          W_FireRC
                          ================
                          */
                          
                          //fire riot shotgun
                          void() W_FireRC =
                          {
                          	local vector dir,kickback,dir2;
                          
                          	if (self.currentammo < 1)
                          	{
                          		sound (self, CHAN_WEAPON, "weapons/dryfire.wav", 1, ATTN_NORM);	
                          		return;
                          	}
                          		
                          	if (self.weaponframe < 2)
                          		sound (self ,CHAN_WEAPON, "weapons/rshotgn.wav", 1, ATTN_NORM);	
                          
                          	self.punchangle_x = -4;
                          	
                          	var float kickback_push = 250;    // set to amount of kickback you want
                          			dir2 = aim (self, 100);
                          			traceline (self.origin, self.origin + dir2*kickback_push, FALSE, self);
                          			kickback = (trace_endpos - self.origin); // + (normalize(dir2) * 80);
                          			self.velocity = self.velocity - kickback;
                          		
                          	self.rcdrum = self.rcdrum -1; // take away 1 from the drum count
                          	makevectors(self.v_angle);
                          	dir = v_forward; //aim (self, 100000);
                          	
                          	FireBullets (20, dir, '0.20 0.15 0');
                          	
                          };
                          w_setcurrentammo code:
                          Code:
                          	else if (self.weapon == IT_RSHOT)  //  Riot shotgun
                          	{
                          		self.currentammo = self.rcdrum;
                          		self.weaponmodel = "progs/v_rshot.mdl";
                          		self.weaponframe = 0;
                          		self.items = self.items | IT_SHELLS;
                          	}
                          w_attack code:
                          Code:
                          	else if (self.weapon == IT_RSHOT)  //  Riot Shotgun
                          		{
                          			if (self.rcdrum > 0) // are there shells in the drum?
                          			{
                          			player_rc1 ();
                          			self.attack_finished = time + 0.4;
                          			}
                          		if (self.rcdrum == 0) // If the drum is empty
                          			{
                          		reloadrc (); // reload riot shotgun drum
                          			}
                          		}
                          The .float in defs.cq:
                          Code:
                          .float rcdrum; // riot shotgun drum
                          I can;t figure what I did wrong where.

                          Comment


                          • #14
                            Ok lets start with this....

                            Code:
                            =====================
                            Reload Riot Shotgun
                            =====================
                            */
                            
                            void() reloadrc
                            {
                            
                            local .float shots_fired; // A float that will only be used in this function and cant be called by others
                            
                            if (self.weapon == IT_RSHOT) // Checks if the current weapon is the Riot Shotgun
                            {
                            self.shots_fired = 12 - self.rcdrum; // calculate the shots fired from drum
                            if (self.ammo_shells > self.shots_fired) // If we have more shells in our inventory then those that need to be reload then its easy.)
                            {
                            self.ammo_shells = self.ammo_shells - self.shots_fired; // We take the shots fired and take that away from out inventory.
                            self.rcdrum = 12; // refill the drum.
                            }
                            else
                            {
                            self.rcdrum = self.rcdrum + self.ammo_shells; // Since the ammo in ammo_shells is less than the shots fired we can add that to the drum
                            self.ammo_shells = 0; // set the shells to zero because there are none left.
                            }
                            }
                            self.currentammo = self.rcdrum; // Update the current ammo (shown on the Quake hud) to show how many bullets are left in the inventory
                            [COLOR="Yellow"]self.attack_finished = time + 4;[/COLOR] // Set the next attack four seconds from now, you cant shoot for four seconds.
                            };
                            you code is fine for the most part here but I changed it up a bit.

                            Code:
                            /*
                            =====================
                            Reload Riot Shotgun
                            =====================
                            */
                            
                            void() reloadrc
                            {
                            
                            local .float shots_fired; // A float that will only be used in this function and cant be called by others
                            
                            if (self.weapon == IT_RSHOT) // Checks if the current weapon is the Riot Shotgun
                            {
                            self.shots_fired = 12 - self.rcdrum; // calculate the shots fired from drum
                            if (self.ammo_shells > self.shots_fired) // If we have more shells in our inventory then those that need to be reload then its easy.)
                            {
                            self.ammo_shells = self.ammo_shells - self.shots_fired; // We take the shots fired and take that away from out inventory.
                            [COLOR="Lime"]self.attack_finished = time + 1.5;[/COLOR] // Set the next attack four seconds from now, you cant shoot for four seconds.
                            [COLOR="Lime"]sound (self, CHAN_ITEM, "weapons/yourclipsound.wav", 1, ATTN_NORM);[/COLOR]
                            self.rcdrum = 12; // refill the drum.
                            }
                            else
                            {
                            self.rcdrum = self.rcdrum + self.ammo_shells; // Since the ammo in ammo_shells is less than the shots fired we can add that to the drum
                            self.ammo_shells = 0; // set the shells to zero because there are none left.
                            }
                            }
                            self.currentammo = self.ammo_shells; // Update the current ammo (shown on the Quake hud) to show how many bullets are left in the inventory
                            
                            };

                            The yellow highlighted code is what I moved to it's new location and changed it to 1.5 seconds as 4 is a really long time. So after that I also added the code you need right under it in orange to play your clip being loaded sound. Those are both in green. You can make this sound pretty long as you have 1.5 seconds to play with though you can play around with the time here for whatever sound you will be using. This is just a place holder. Of course remember to precache it like your other weapon sounds.

                            Now this code:

                            Code:
                            ================
                            W_FireRC
                            ================
                            */
                            
                            //fire riot shotgun
                            void() W_FireRC =
                            {
                            	local vector dir,kickback,dir2;
                            
                            	if (self.currentammo < 1)
                            	{
                            		sound (self, CHAN_WEAPON, "weapons/dryfire.wav", 1, ATTN_NORM);	
                            		return;
                            	}
                            		
                            	if (self.weaponframe < 2)
                            		sound (self ,CHAN_WEAPON, "weapons/rshotgn.wav", 1, ATTN_NORM);	
                            
                            	self.punchangle_x = -4;
                            	
                            	var float kickback_push = 250;    // set to amount of kickback you want
                            			dir2 = aim (self, 100);
                            			traceline (self.origin, self.origin + dir2*kickback_push, FALSE, self);
                            			kickback = (trace_endpos - self.origin); // + (normalize(dir2) * 80);
                            			self.velocity = self.velocity - kickback;
                            		
                            	[COLOR="Red"]self.rcdrum = self.rcdrum -1;[/COLOR] // take away 1 from the drum count
                            	makevectors(self.v_angle);
                            	dir = v_forward; //aim (self, 100000);
                            	
                            	FireBullets (20, dir, '0.20 0.15 0');
                            	
                            };
                            You just got plain wrong. Specifically look at the red highlighted code. Firstly you have it defined as self.rcdrum. This really doesn't make sense here because the drum amount will not tell it how much currentammo it has and thus it will not update your inventory correctly Basically you'll have infinite ammo . Besides, we need to be using self.currentammo here anyway. Using currentammo first tells this gun that the currentammo for this gun will be equal whatever is in my clip minus 1 shell. This routine will run each time you fire the weapon and remove one each time until you are empty. Make sense? I know from the tutorial it appears it wanted you to do the above, but this is where understanding syntax comes into play. Here you will ALWAYS need to define currentammo first. Also you have a -1 instead of a - 1. You left out a space. That will effectively kill this from working. So now here is what it should look like.

                            Code:
                            /*
                            ================
                            W_FireRC
                            ================
                            */
                            
                            //fire riot shotgun
                            void() W_FireRC =
                            {
                            	local vector dir,kickback,dir2;
                            
                            	if (self.currentammo < 1)
                            	{
                            		sound (self, CHAN_WEAPON, "weapons/dryfire.wav", 1, ATTN_NORM);	
                            		return;
                            	}
                            		
                            	if (self.weaponframe < 2)
                            		sound (self ,CHAN_WEAPON, "weapons/rshotgn.wav", 1, ATTN_NORM);	
                            
                            	self.punchangle_x = -4;
                            	
                            	var float kickback_push = 250;    // set to amount of kickback you want
                            			dir2 = aim (self, 100);
                            			traceline (self.origin, self.origin + dir2*kickback_push, FALSE, self);
                            			kickback = (trace_endpos - self.origin); // + (normalize(dir2) * 80);
                            			self.velocity = self.velocity - kickback;
                            		
                            	[COLOR="Lime"]self.currentammo = self.rcdrum = self.rcdrum - 1;[/COLOR] // take away 1 from the drum count
                            	makevectors(self.v_angle);
                            	dir = v_forward; //aim (self, 100000);
                            	
                            	FireBullets (20, dir, '0.20 0.15 0');
                            	
                            };

                            Next this code:

                            Code:
                            else if (self.weapon == IT_RSHOT)  //  Riot shotgun
                            	{
                            		[COLOR="Red"]self.currentammo = self.rcdrum;[/COLOR]
                            		self.weaponmodel = "progs/v_rshot.mdl";
                            		self.weaponframe = 0;
                            		self.items = self.items | IT_SHELLS;
                            	}
                            Ok this doesn't make sense either. In self.currentammo you set it to self.rcdrum. No bueno. This code runs whenever it needs to set current ammo. You've basically set it to nothing. So much like before you'll need to set this to shells as that will be the ammo type this gun will use.

                            Code:
                            else if (self.weapon == IT_RSHOT)  //  Riot shotgun
                            	{
                            		[COLOR="Lime"]self.currentammo = self.ammo_shells;[/COLOR]
                            		self.weaponmodel = "progs/v_rshot.mdl";
                            		self.weaponframe = 0;
                            		self.items = self.items | IT_SHELLS;
                            	}
                            So this is how it should look.

                            EDIT(ERASED)

                            Ok that should fix you up. Let me know. I tested it myself and compiled. Worked fine. Now if you want you can also implement that impulse command so you can reload manually otherwise the way it works now is you'll have to press fire at least once to make the reload action happen and then the ammo will update accordingly. This is also important to note if you do an impulse 9 to get all weapons. This one will not be loaded at the start so when you pull it out you will need to load a drum first. You can write some code to fix this but I don't see a major problem with it at this time. Enjoy
                            Last edited by PrimalLove; 08-20-2014, 09:54 PM.

                            Comment


                            • #15
                              thanks again. I'm going to try it out shortly.

                              Is there a way to make it load automatically without having to press the fire button?

                              I don't intend to use the impulse to reload anytime.

                              I thought "self.attack_finished = time + 4;" would equal out to 4 seconds? Granted 4 seconds is a bit of a long time, but I intend it to be that way in order to balance things out a bit since the weapon is quite powerful. The ssg currently takes about 2 seconds to reload so I wanted this one to be twice as long.

                              "self.currentammo = self.rcdrum; I figured that's what I needed in order to display the amount of shells left in the drum on the hud?

                              It would be nice to get around the starting with no ammo when using impulse 9 since that is how I test it. Not a biggie though.

                              Comment

                              Working...
                              X