Announcement

Collapse
No announcement yet.

Enemies dropping items?

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

  • Enemies dropping items?

    I want to make the monsters have a chance of dropping a new item that gives the player a small amount of health. Similar to the hearts in Blood.

    I can easily figure out how to make the backpacks drop health, but not how to make the enemies have a chance of dropping a separate new item with it's own model/sound etc.

    I would probably have it be a random chance to drop the life pickup or possibly every time if the player does enough damage to gib the enemies.

    Thanks.

    ***
    on a side note, I'm trying to get this tutorial working, but it doesn't wanna compile. http://www.inside3d.com/showtutorial.php?id=230

    I keep getting an error:

    fight.qc: 149: error: Unknown Value "ideal_pitch"
    fight.qc: 149: error: "." - not a name
    Last edited by Legend; 08-12-2014, 10:46 PM.

  • #2
    i was also recently thinking, like how modern zombie games drop items on death...i always wanted this in Quake... kill the orgre get his GL!!!

    u need to drop the item when the monster is killed (combat.qc)
    then spawn an item and create a touch function for that item.

    start with what you can then i will help you, ...

    i could post code but that will only create confusion.
    Last edited by R00k; 08-12-2014, 11:35 PM.
    www.quakeone.com/qrack | www.quakeone.com/cax| http://en.twitch.tv/sputnikutah

    Comment


    • #3
      ok here's confusion.

      anything that is not defined isnt for your mod,
      hopefully u can see some syntax and learn.. this is relevant but not usefull.

      Code:
      void () BackpackTouch =
      {
      	local string s;
      	local float best;
      	local float new;
      	local entity stemp;
      	local float acount;
      
      	if (((clanring_playmode & CLANRING_MATCH_MODE) && !(clanring_state & CLANRING_MATCH_STARTED)))
      	{
      		return;
      	}
      	if (clanring_state & CLANRING_MATCH_PAUSED)
      	{
      		return;
      	}
      	if ((other.classname != "player"))
      	{
      		return;
      	}
      	if ((other.health <= 0))
      	{
      		return;
      	}
      	acount = 0;
      	sprint (other, "You get ");
      	if (self.items)
      	{
      		if (((other.items & self.items) == 0))
      		{
      			acount = WEAPON_SHOTGUN;
      			sprint (other, "the ");
      			sprint (other, self.netname);
      			if ((self.items == IT_ROCKET_LAUNCHER))
      			{
      				if (((teamplay && (clanring_playmode & CLANRING_MATCH_MODE)) && (other.team != self.owner.team)))
      				{
      					quaketv_announce4 (other.netname, " got ", self.owner.netname, "'s RL");
      					quaketv_sound ("misc/talk.wav");
      					self.owner.clanring_badstats_x = (self.owner.clanring_badstats_x + WEAPON_SHOTGUN);
      					other.next_team.mangle_y = (other.next_team.mangle_y + WEAPON_SHOTGUN);
      				}
      				quaketv_obtained_rl (other);
      			}
      		}
      	}
      	stemp = self;
      	self = other;
      	best = W_BestWeapon ();
      	self = stemp;
      	other.ammo_shells = (other.ammo_shells + self.ammo_shells);
      	other.ammo_nails = (other.ammo_nails + self.ammo_nails);
      	other.ammo_rockets = (other.ammo_rockets + self.ammo_rockets);
      	other.ammo_cells = (other.ammo_cells + self.ammo_cells);
      	new = self.items;
      	if (!new)
      	{
      		new = other.weapon;
      	}
      	other.items = (other.items | new);
      	bound_other_ammo ();
      	if (self.ammo_shells)
      	{
      		if (acount)
      		{
      			sprint (other, ", ");
      		}
      		acount = WEAPON_SHOTGUN;
      		s = ftos (self.ammo_shells);
      		sprint (other, s);
      		sprint (other, " shells");
      	}
      	if (self.ammo_nails)
      	{
      		if (acount)
      		{
      			sprint (other, ", ");
      		}
      		acount = WEAPON_SHOTGUN;
      		s = ftos (self.ammo_nails);
      		sprint (other, s);
      		sprint (other, " nails");
      	}
      	if (self.ammo_rockets)
      	{
      		if (acount)
      		{
      			sprint (other, ", ");
      		}
      		acount = WEAPON_SHOTGUN;
      		s = ftos (self.ammo_rockets);
      		sprint (other, s);
      		sprint (other, " rockets");
      	}
      	if (self.ammo_cells)
      	{
      		if (acount)
      		{
      			sprint (other, ", ");
      		}
      		acount = WEAPON_SHOTGUN;
      		s = ftos (self.ammo_cells);
      		sprint (other, s);
      		sprint (other, " cells");
      	}
      	sprint (other, "\n");
      	sound (other, CHAN_ITEM, "weapons/lock4.wav", WEAPON_SHOTGUN, ATTN_NORM);
      	stuffcmd (other, "bf\n");
      	remove (self);
      	self = other;
      
      	if (self.style & CLANRING_SMART_WEAPON)
      	{
      		Deathmatch_Weapon (other, new);
      	}
      	else
      	{
      		if (((new != IT_GRENADE_LAUNCHER) && (new != IT_ROCKET_LAUNCHER)))
      		{
      			Deathmatch_Weapon (other, new);
      		}
      	}
      	
      	W_SetCurrentAmmo ();
      };
      
      void () DropBackpack =
      {
      	local entity item;
      
      	if (!(((self.ammo_shells + self.ammo_nails) + self.ammo_rockets) + self.ammo_cells))
      	{
      		return;
      	}
      	
      	item 		= spawn ();
      	item.origin 	= (self.origin - '0 0 24');
      	item.classname 	= "item_backpack";
      	item.owner 	= self;
      	item.items 	= self.weapon;
      	
      	if ((item.items == IT_AXE))
      	{
      		item.netname = "Axe";
      	}
      	else
      	{
      		if ((item.items == IT_SHOTGUN))
      		{
      			item.netname = "Shotgun";
      		}
      		else
      		{
      			if ((item.items == IT_SUPER_SHOTGUN))
      			{
      				item.netname = "Double-barrelled Shotgun";
      			}
      			else
      			{
      				if ((item.items == IT_NAILGUN))
      				{
      					item.netname = "Nailgun";
      				}
      				else
      				{
      					if ((item.items == IT_SUPER_NAILGUN))
      					{
      						item.netname = "Super Nailgun";
      					}
      					else
      					{
      						if ((item.items == IT_GRENADE_LAUNCHER))
      						{
      							item.netname = "Grenade Launcher";
      						}
      						else
      						{
      							if ((item.items == IT_ROCKET_LAUNCHER))
      							{
      								item.netname = "Rocket Launcher";
      								if ((teamplay && (clanring_playmode & CLANRING_MATCH_MODE)))
      								{
      									self.next_team.mangle_z = (self.next_team.mangle_z + 1);
      								}
      							}
      							else
      							{
      								if ((item.items == IT_LIGHTNING))
      								{
      									item.netname = "Thunderbolt";
      								}
      								else
      								{
      									item.netname = "";
      								}
      							}
      						}
      					}
      				}
      			}
      		}
      	}
      	
      	item.ammo_shells 	= self.ammo_shells;
      	item.ammo_nails 	= self.ammo_nails;
      	item.ammo_rockets 	= self.ammo_rockets;
      	item.ammo_cells 	= self.ammo_cells;
      	
      	item.velocity_z = 300;
      	item.velocity_x = (-100 + (random () * 200));
      	item.velocity_y = (-100 + (random () * 200));
      	
      	item.flags = FL_ITEM;
      	item.solid = SOLID_TRIGGER;
      	item.movetype = MOVETYPE_TOSS;
      	setmodel (item, "progs/backpack.mdl");
      	setsize (item, '-16 -16 0', '16 16 56');
      	item.touch = BackpackTouch;
      	item.nextthink = (time + 60);
      	item.think = SUB_Remove;
      };
      so u could insert a random item there so it drops random inventory in that backpack...
      www.quakeone.com/qrack | www.quakeone.com/cax| http://en.twitch.tv/sputnikutah

      Comment


      • #4
        Thanks R00k. I think I figured where I have to put what.

        Any idea what I'm doing wrong in that tutorial btw?

        Comment


        • #5
          Just a quick note but Kleshik Coop mod already does this to an extend tho i believe it's randomized. You can check out the src for it over here

          Nothing is under file but just click code and it's right there and download a snapshot. It's worth a look. It does basically exactly what you are describing here. It drops weapons, ammo, health, etc.

          This is a small sample of some of the relevant code from the monster_enforcer.qc

          Code:
          void enf_die()
          {
          	// DRESK
          	// Check for Powerup Drop
          	CheckMonsterDropPowerup(0.15, POWERUPTYPE_ENVIROSUIT, 0);
          	// Check for Potential Armor Drop
          	CheckMonsterDropArmor(0.10, ARMORTYPE_GREEN);
          	
          	if(self.nEnforcerGunType == WEAPON_ROCKET_LAUNCHER)
          	{
          		if( random() > 0.80)
          			self.nCSQCStat_Weapons = WEAPON_ROCKET_LAUNCHER;
          	}
          	else
          	if(self.nEnforcerGunType == WEAPON_GRENADE_LAUNCHER)
          	{
          		if( random() > 0.80)
          			self.nCSQCStat_Weapons = WEAPON_GRENADE_LAUNCHER;
          	}
          	else
          	{
          		// Check for Laser Gun Drop
          		if( GetWeaponIsAvailable(WEAPON_LASER_GUN) && random() > 0.70)
          			self.nCSQCStat_Weapons = WEAPON_LASER_GUN;
          You can see here that they apply chances for these items to drop depending on the weapon the enforcer already has on him. This mod allows some enemies to have multiple weapons for variation so that is why it checks for specific weapon type first before deciding on what to drop so it matches.Try the mod so you can see the results in game. You'll need to change a lot of code to implement this because it uses Kleshik specific parameters to accomplish this but its a start.

          Also check Dresk_Weapons.qc and Dresk_Powerups.qc for more info on this.
          Last edited by PrimalLove; 08-13-2014, 01:49 AM.

          Comment


          • #6
            as r00k said, you want to hack up drop_backpack, and backpack_touch.

            In drop_backpack, a new item is being created named item. And the enemies inventory is being shoved into it. if you have any new types of ammo or stats that need to be recovered when you pick up the backpack, here is where you need to set them
            Code:
            item = spawn();
            	item.origin = self.origin - '0 0 24';
            	item.items = self.weapon;
            
            	item.ammo_shells = self.ammo_shells;
            	item.ammo_nails = self.ammo_nails;
            	item.ammo_rockets = self.ammo_rockets;
            	item.ammo_cells = self.ammo_cells;
            then various fields are set, and the item is given a model, and its self.touch field is set to backpack_touch

            Code:
            	setmodel (item, "progs/backpack.mdl");
            	setsize (item, '-16 -16 0', '16 16 56');
            	item.touch = BackpackTouch;
            So if you want a different model for your item, you'll need to set up some if()'s and put in some other calls to setmodel.

            next we look at backpack_touch, which is called when the player touches the backpack.
            backpack_touch first reads in all the ammo and weapon fields on the backpack item (self) and adds it to those stats for the player (other).

            Code:
            	// change weapons
            	other.ammo_shells = other.ammo_shells + self.ammo_shells;
            	other.ammo_nails = other.ammo_nails + self.ammo_nails;
            	other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
            	other.ammo_cells = other.ammo_cells + self.ammo_cells;
            so you'll need to read in any custom fields you added in backpack_drop there.

            next backpack_touch checks to see which weapon you picked up (if any) to finish the "you got the " print message it setup earlier

            Code:
            	if (self.ammo_shells)
            	{
            		if (acount)
            			sprint(other, ", ");	
            
            		acount = 1;
            		s = ftos(self.ammo_shells);
            		sprint (other, s);
            		sprint (other, " shells");
            	}
            
            	if (self.ammo_nails)
            	{
            		if (acount)
            			sprint(other, ", ");
            
            		acount = 1;
            		s = ftos(self.ammo_nails);
            		sprint (other, s);
            		sprint (other, " nails");
            	}
            so you'll have to add one of those in if you want it to print correctly.

            then it plays the gun**** sound, flashes the screen, removes the backpack from the map, and cleans up the finnagling with the self field

            Code:
            	// backpack touch sound
            	sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
            	stuffcmd (other, "bf\n");
            
            	remove(self);
            	self = other;
            do note, some understanding of quakec and familiarity with the codebase is required to follow the above. I'm not sure how helpful this writeup was, because if you have that familiarity, you dont need this writeup. yay catch22.
            Last edited by gnounc; 08-13-2014, 09:14 AM.
            Gnounc's Project Graveyard Gnounc's git repo

            Comment


            • #7
              Reread, I see the problem you're having is with % chance to drop (which i did not address) as well as custom sound and model (which i did).

              in w_attack in weapons.qc id covers random % chance to do something.

              Code:
              	r = random();
              		if (r < 0.25)
              			player_axe1 ();
              that means if r is less than .25, then do player_axe1(). thats 24.9 all the way to 0.
              or 1/4 chance.

              so shove something similar above your custom sound and custom model in drop_backpack

              the other part to this, is when an enemy dies, drop_backpack checks their self.weapon
              so you need to set the enemies self.weapon to whatever you want them to drop before they die. also bear in mind only a few enemies drop a backpack at all, so you'll have to add a call to dropbackpack into the dying animation macros (check grunts for how to do this). You can put the random() call in here instead of in drop_backpack for when you set the enemies self.weapon if you want to change what drops before the enemy even dies.

              alternatively, you could fudge something into throw_head or throw_gib since you said you wanted it to happen when an enemy is gibbed.
              Gnounc's Project Graveyard Gnounc's git repo

              Comment


              • #8
                basically, make it spawn a new entity with the model of the thing that's about to be dropped, and make the new entity have that item in its inventory (self.items.)

                The new entity needs a touch function; when touched, transfer self.items to the player. Done.
                Scout's Journey
                Rune of Earth Magic

                Comment


                • #9
                  Here's how I figure I will do it (haven't actually tried yet though)

                  Was planning on adding this to items.qc

                  Code:
                     
                  void() DropHeart =
                  {
                          local entity item;
                  	item = spawn();
                  	
                        item.netname = "Life Heart\n";
                        setmodel(item, "progs/items/Heart.mdl");
                          item.velocity_z = 300;
                          item.velocity_x = -100 + (random() * 200);
                          item.velocity_y = -100 + (random() * 200);
                  
                      item.classname = "heart";
                      
                          item.flags = FL_ITEM;
                          item.solid = SOLID_TRIGGER;
                          item.movetype = MOVETYPE_TOSS;
                  
                      item.noise = "items/beat.wav";
                  
                  	setsize (item, '-16 -16 0', '16 16 56');
                      setorigin(item, self.origin);
                      item.touch = heart_touch;
                  };
                  STill trying to figure out how to do the Heart_touch exactly.

                  I don't really want to touch the backpack stuff cause I still want the backpacks to drop as normal.

                  As far as making the enemies actually drop the hearts, I figured I could put that in the "Killed" section of combat.qc and it would work for all enemies. I'm assuming so anyways.

                  Something like

                  Code:
                  r = random();
                  		if (r < 0.33)
                  			DropHeart ()
                  As said, haven't gotten to try it yet though.

                  Comment


                  • #10
                    If you do drop items instead of backpacks make sure u precache the models
                    As not all maps have certain items
                    www.quakeone.com/qrack | www.quakeone.com/cax| http://en.twitch.tv/sputnikutah

                    Comment


                    • #11
                      Originally posted by R00k View Post
                      If you do drop items instead of backpacks make sure u precache the models
                      As not all maps have certain items
                      Thanks. I got that. I would precache the model and sound in the items.qc. I believe I would anyways. Or actually inside the DropHeart function?

                      Does the rest of it seem ok though? And I would actually add the part which adds health to the player in the Touch item function correct?

                      Comment


                      • #12
                        Ok I figured I'd do this for a bit of fun and to maybe help out a bit.

                        It kind of just depends on what you want the heart to do. Will it just add health? If so they already have touch.function you can use called health_touch which is in items.qc also.

                        So I decided I'd put something fun together that will show you an example of adding something to drop along side a backpack drop. So I chose to let certain enemies drop weapons. Specifically the enforcer, grunt, and orge. The grunt drops a super shotgun (only because I don't have a model of the single barrel shotgun) the enforcer drops a nail gun, and the orge of course, GRENADE LAUNCHER! Lets go through the process:


                        First go to items.qc that you are already familiar with. So now lets go to the very bottom and place this whole function:

                        Code:
                        void() DropWeapon =
                        {
                        	local entity	item;
                        
                        	if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells))
                        		return;	// nothing in it (Primallove: Technically you don't need this if statement but I left it in anyway )
                        
                        	item = spawn();
                        	item.origin = self.origin - '0 0 24';
                        	
                        	item.items = self.weapon;
                        	if (item.items == IT_AXE)
                        	{
                        		return;		
                        	}
                        	else if (item.items == IT_SUPER_SHOTGUN)
                        	{	
                        		setmodel (item, "progs/g_shot.mdl");
                        		setsize (item, '-16 -16 0', '16 16 56');
                        		item.ammo_shells = 10;
                        		item.netname = "Double-barrelled Shotgun";
                        	}
                        	else if (item.items == IT_NAILGUN)
                        	{	
                        		setmodel (item, "progs/g_nail.mdl");
                        		setsize (item, '-16 -16 0', '16 16 56');	
                        		item.ammo_nails = 25;
                        		item.netname = "Nailgun";
                        	}
                        	else if (item.items == IT_SUPER_NAILGUN)
                        	{
                        		setmodel (item, "progs/g_nail2.mdl");
                        		setsize (item, '-16 -16 0', '16 16 56');
                        		item.ammo_nails = 25;
                        		item.netname = "Super Nailgun";
                        	}
                        	else if (item.items == IT_GRENADE_LAUNCHER)
                        	{	
                        	
                        		setmodel (item, "progs/g_rock.mdl");
                        		setsize (item, '-16 -16 0', '16 16 56');
                        		item.ammo_rockets = 10;
                        		item.netname = "Grenade Launcher";
                        	}
                        	else if (item.items == IT_ROCKET_LAUNCHER)
                        	{
                        		setmodel (item, "progs/g_rock2.mdl");
                        		setsize (item, '-16 -16 0', '16 16 56');
                        		item.ammo_rockets = 10;
                        		item.netname = "Rocket Launcher";
                        	}
                        	else if (item.items == IT_LIGHTNING)
                        	{
                        		setmodel (item, "progs/g_light.mdl");
                        		setsize (item, '-16 -16 0', '16 16 56');
                        		item.ammo_cells = 15;
                        		item.netname = "Thunderbolt";
                        	}
                        
                        
                        	item.velocity_z = 300;
                        	item.velocity_x = -100 + (random() * 200);
                        	item.velocity_y = -100 + (random() * 200);
                        	
                        	item.flags = FL_ITEM;
                        	item.solid = SOLID_TRIGGER;
                        	item.movetype = MOVETYPE_TOSS;
                        	item.touch = BackpackTouch;
                        	
                        	item.nextthink = time + 60;	// remove after 2 minutes
                        	item.think = SUB_Remove;
                        };
                        You'll notice this is very similar to the function just above it called DropBackpack(). Basically I took heavily from it! And why not? id has already done the hard work. So you can see that I added multiple possibilities for weapon drops using the self.weapon function as the identifier. This is exactly how backpacks in multiplayer know which weapons to place in fallen backpacks when you die. You'll notice for item.touch i used BackpackTouch. Why? Because the code to handle dropping weapons is already included in that function so no need to recreate the wheel or add additional spokes it doesn't need. Errmm... LOL! Anyway, that is what I was getting at when i mentioned what you want your item to do for you. That will determine if you need to write your own function and/or modify an existing one. For instance, dropping a heart sounds to me like health so you'd simply use the health_touch function and could define it accordingly to which ever health pack that currently exist in the game or add additional code to support something slightly different. If you do need to make your own function just use an existing one that is close to your goal as a template and there you can define your sounds. I just used what was already in the backpack. You can either define the sound in your HeartDrop function if you plan to use an existing Touch function or just define it in your newly created touch function.

                        Thanks. I got that. I would precache the model and sound in the items.qc. I believe I would anyways. Or actually inside the DropHeart function?
                        You can go ahead a define the sound in the function and then precache it much like I do below.

                        If you want your heart to add some sort of stat i'd suggest looking into CSQC which is another whole ball of wax. Ok back to it.

                        I also defined models for them all. You can use this same method and location to precache the sounds. Luckily for me, these models already are included with quake. Hehe. . Don't precache them in the function. Lets do it at the top of items.qc. Right above void() SUB_regen =

                        Code:
                        void() I_Precache =
                        {
                        	precache_model ("progs/shotgun.mdl");
                        	precache_model ("progs/g_shot.mdl");
                        	precache_model ("progs/g_nail.mdl");
                        	precache_model ("progs/g_nail2.mdl");
                        	precache_model ("progs/g_rock.mdl");
                        	precache_model ("progs/g_rock2.mdl");
                        	precache_model ("progs/g_light.mdl");
                        };
                        That's it for items.qc for now.

                        You'll need to define I_Precache in world.qc under worldspawn to make this work without error. Place it under player precaches like this.

                        Code:
                        // player precaches	
                        	W_Precache ();			// get weapon precaches
                        
                        I_Precache ();
                        That is it for world.qc

                        Now you have two options. You can try and make this thing global by adding the function drop to combat.qc Killed. But I customized mine to each monster so I needed to open up each monster qc file. For example, the soldier.qc

                        Scrolls down to the death animations and we are looking specifically for army_die and army_cdie.

                        You'll see two lines of code of interest to us for separate death animations:

                        Code:
                        {self.solid = SOLID_NOT;self.ammo_shells = 5;DropBackpack();};
                        
                        
                        {self.solid = SOLID_NOT;self.ammo_shells = 5;DropBackpack();ai_back(4);};
                        Change both of them to this:

                        Code:
                        {self.solid = SOLID_NOT;self.ammo_shells = 5;DropBackpack();self.weapon = IT_SUPER_SHOTGUN;DropWeapon();};
                        
                        {self.solid = SOLID_NOT;self.ammo_shells = 5;DropBackpack();self.weapon = IT_SUPER_SHOTGUN;DropWeapon();ai_back(4);};
                        This basically defines the weapon the monster has and then tells it to drop the weapon item in addition to the backpack which I believe is how you want your hearts to come out. This just makes sure it happens regardless of which death animation is used. I used super shotgun because I don't have a shotgun weapon model handy but if I did I could have precached it and included it in the mod folder but eh.

                        You'll follow this same process for each monster you want to drop the item. I should note that only certain monsters drop backpacks so you'll need to follow the same steps from the soldier.qc to add that ability to say a fiend or shambler, etc. Its only one line to add usually so its not a big deal and you can leave out the backpack for them and just use your heart drop.

                        That's it for soldier.qc. You'd just compile and go. You'll get several warnings but I didn't bother to clean up anything. They don't result in any crashes and it works great. Check the youtube video below to see it in game.

                        Notice I didn't mention the random chance code. You got me. This one is easy. If you plan to do this globally you can just add it to combat.qc killed. But for me, I need to add it to each monster qc file I edit. Basically the line would look like this instead of what is up above:

                        Code:
                        {self.solid = SOLID_NOT;self.ammo_shells = 5;DropBackpack();self.weapon = IT_SUPER_SHOTGUN;local float r;r = random();if (r < 0.33) DropWeapon();};
                        
                        {self.solid = SOLID_NOT;self.ammo_shells = 5;DropBackpack();self.weapon = IT_SUPER_SHOTGUN; local float r;r = random();if (r < 0.33) DropWeapon();ai_back(4);};
                        Note, if you want to use the code they suggested to randomize you'll need to remember to define local float r; before r=random(); or you'll get an error compiling me thinks. The code above includes that. I utilized a local float but you can use a global float at the top of the file to eliminate the need to use it multiple times. Otherwise your code:

                        Code:
                        local float r; //include this!!!
                        r = random();
                        		if (r < 0.33)
                        			DropHeart ()
                        Should work just fine!
                        Anyway hope this helps a bit more! if not, it was fun to do anyway. This method doesn't require you to touch the dropbackpack function or backpacktouch function at all because we created a completely new function for weapondrop which i think was your goal. The video took much longer to upload than to implement the code. :/ Youtube....

                        Will post video link as soon as done uploading... Geez... :/


                        EDIT: WeaponDrop() function addition to items.qc for Quake Example - YouTube
                        Last edited by PrimalLove; 08-14-2014, 06:09 AM.

                        Comment


                        • #13
                          Ok. I'm getting an error while compiling.

                          "Combat.qc: 78: error: unknown value: "Drop_essence"

                          Here is the code I did:

                          in Items.cq at the very top:
                          Code:
                          void() E_Precache =
                          {
                          	precache_model ("progs/items/essence.mdl");  // heart model
                          	
                          	precache_sound ("items/beat.wav");           // heart beat sound
                          };
                          At the bottom below dropbackpack:
                          Code:
                          /*
                          ===============
                          Drop Life Essence
                          ===============
                          */
                          
                          void() essence_Touch =
                          {
                          	local string	s;
                          	local	float	best, old, new;
                          	local		entity	stemp;
                          	local	float	acount;
                          	
                          	if (other.classname != "player")
                          		return;
                          	if (other.health <= 0)
                          		return;
                          
                          	acount = 0;
                          	sprint (other, "You get ");
                          
                          	if (self.items)
                          		if ((other.items & self.items) == 0)
                          		{
                          			acount = 1;
                          			sprint (other, "the ");
                          			sprint (other, self.netname);
                          		}
                          
                          // if the player was using his best weapon, change up to the new one if better		
                          //	stemp = self;
                          //	self = other;
                          //	best = W_BestWeapon();
                          //	self = stemp;
                          
                          // change weapons
                          	other.ammo_shells = other.ammo_shells + self.ammo_shells;
                          	other.ammo_nails = other.ammo_nails + self.ammo_nails;
                          	other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
                          	other.ammo_cells = other.ammo_cells + self.ammo_cells;
                          	
                          
                          	new = self.items;
                          	if (!new)
                          		new = other.weapon;
                          	old = other.items;
                          	other.items = other.items | new;
                          	
                          	bound_other_ammo ();
                          
                          	if (self.health)
                          	{
                          	if (acount)
                          		sprint(other, ", ");
                          	acount = 1;
                          	s = ftos(self.health);
                          	sprint (other, s);
                                  sprint (other, " health");
                          	}
                          	sprint (other, "\n");
                          // backpack touch sound
                          	sound (other, CHAN_ITEM, "items/beat.wav", 1, ATTN_NORM);
                          	stuffcmd (other, "bf\n");
                          
                          // remove the backpack, change self to the player
                          	remove(self);
                          	self = other;
                          
                          // change to the weapon
                          //	if (!deathmatch)
                          //		self.weapon = new;
                          //	else
                          //		Deathmatch_Weapon (old, new);
                          
                          	W_SetCurrentAmmo ();
                          };
                          
                          // particle effect
                          void() essence_effect =
                          {
                           particle (self.origin, '0 0 20', 235, 4);
                           self.think = essence_effect;
                           self.nextthink = time + 0.2;
                          };
                          // Drop the life essence
                          void() Drop_Essence =
                          {
                              local entity item;
                          	item = spawn();
                          	
                                item.netname = "Life Essence\n";
                          	  
                          	  item.health = 6 + 20*random();
                          	  
                                setmodel(item, "progs/items/essence.mdl");
                                  item.velocity_z = 300;
                                  item.velocity_x = -100 + (random() * 200);
                                  item.velocity_y = -100 + (random() * 200);
                          
                              item.classname = "essence";
                              
                                  item.flags = FL_ITEM;
                                  item.solid = SOLID_TRIGGER;
                                  item.movetype = MOVETYPE_TOSS;
                          
                              item.noise = "items/beat.wav";
                          
                          	setsize (item, '-16 -16 0', '16 16 56');
                              setorigin(item, self.origin);
                              item.think = essence_effect;
                          	item.nextthink = time + 0.2;
                              item.touch = essence_touch;
                          };
                          In world.cq under worldspawn -player precaches:
                          Code:
                          // player precaches	
                          	W_Precache ();			// get weapon precaches
                          
                          	E_Precache ();			// get life essence precaches
                          And finally, in combat.cq under "Killed" right below "self.enemy = attacker;"

                          Code:
                          	
                          // All enemies have a chance to drop life essence
                          	local float r; //include this!!!
                          r = random();
                          		if (r < 0.33)
                          			Drop_Essence ();
                          Is there something else I missed? Did I need to define the Drop_essence somewhere else?

                          Thanks guys.

                          Comment


                          • #14
                            Ok. Maybe we got a bit off track here. It seems you kinda took my advice by taking from a template but you left alot of unecessary code, etc and used the wrong example for your template which lead to the confusion and errors if you tried to compile it... :/ Its time to clean up this mess. hehe.

                            Ok firstly items.qc this code:

                            Code:
                            void() E_Precache =
                            {
                            	precache_model ("progs/items/essence.mdl");  // heart model
                            	
                            	precache_sound ("items/beat.wav");           // heart beat sound
                            };
                            is correct. No problems here.

                            Now this:


                            Code:
                            /*
                            ===============
                            Drop Life Essence
                            ===============
                            */
                            
                            void() essence_Touch =
                            {
                            	local string	s;
                            	local	float	best, old, new;
                            	local		entity	stemp;
                            	local	float	acount;
                            	
                            	if (other.classname != "player")
                            		return;
                            	if (other.health <= 0)
                            		return;
                            
                            	acount = 0;
                            	sprint (other, "You get ");
                            
                            	if (self.items)
                            		if ((other.items & self.items) == 0)
                            		{
                            			acount = 1;
                            			sprint (other, "the ");
                            			sprint (other, self.netname);
                            		}
                            
                            // if the player was using his best weapon, change up to the new one if better		
                            //	stemp = self;
                            //	self = other;
                            //	best = W_BestWeapon();
                            //	self = stemp;
                            
                            // change weapons
                            	other.ammo_shells = other.ammo_shells + self.ammo_shells;
                            	other.ammo_nails = other.ammo_nails + self.ammo_nails;
                            	other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
                            	other.ammo_cells = other.ammo_cells + self.ammo_cells;
                            	
                            
                            	new = self.items;
                            	if (!new)
                            		new = other.weapon;
                            	old = other.items;
                            	other.items = other.items | new;
                            	
                            	bound_other_ammo ();
                            
                            	if (self.health)
                            	{
                            	if (acount)
                            		sprint(other, ", ");
                            	acount = 1;
                            	s = ftos(self.health);
                            	sprint (other, s);
                                    sprint (other, " health");
                            	}
                            	sprint (other, "\n");
                            // backpack touch sound
                            	sound (other, CHAN_ITEM, "items/beat.wav", 1, ATTN_NORM);
                            	stuffcmd (other, "bf\n");
                            
                            // remove the backpack, change self to the player
                            	remove(self);
                            	self = other;
                            
                            // change to the weapon
                            //	if (!deathmatch)
                            //		self.weapon = new;
                            //	else
                            //		Deathmatch_Weapon (old, new);
                            
                            	W_SetCurrentAmmo ();
                            };
                            
                            // particle effect
                            void() essence_effect =
                            {
                             particle (self.origin, '0 0 20', 235, 4);
                             self.think = essence_effect;
                             self.nextthink = time + 0.2;
                            };
                            // Drop the life essence
                            void() Drop_Essence =
                            {
                                local entity item;
                            	item = spawn();
                            	
                                  item.netname = "Life Essence\n";
                            	  
                            	  item.health = 6 + 20*random();
                            	  
                                  setmodel(item, "progs/items/essence.mdl");
                                    item.velocity_z = 300;
                                    item.velocity_x = -100 + (random() * 200);
                                    item.velocity_y = -100 + (random() * 200);
                            
                                item.classname = "essence";
                                
                                    item.flags = FL_ITEM;
                                    item.solid = SOLID_TRIGGER;
                                    item.movetype = MOVETYPE_TOSS;
                            
                                item.noise = "items/beat.wav";
                            
                            	setsize (item, '-16 -16 0', '16 16 56');
                                setorigin(item, self.origin);
                                item.think = essence_effect;
                            	item.nextthink = time + 0.2;
                                item.touch = essence_touch;
                            };
                            Well its jacked up. LOL. So lets fix it. First get rid of what you have at the end of item.qc now and replace it with this.


                            Code:
                            // particle effect
                            void() essence_effect =
                            {
                             particle (self.origin, '0 0 20', 235, 4);
                             self.think = essence_effect;
                             self.nextthink = time + 0.2;
                            };
                            
                            void() essence_Touch =
                            {
                            	local string	s;
                            	local	float	acount;
                            	
                            	if (other.classname != "player")
                            		return;
                            	if (other.health >= 150)
                            			return;
                            		if (!T_Heal(other, self.health))
                            			return;
                            
                            	acount = 0;
                            	sprint (other, "You devour ");
                            
                            	if (self.health)
                            		if ((other.items & self.items) == 0)
                            		{
                            			acount = 1;
                            			sprint (other, "it's ");
                            			sprint (other, self.netname);
                            		}
                            	sprint (other, "\n");
                            	
                            //touch sound
                            	sound (other, CHAN_ITEM, "items/beat.wav", 1, ATTN_NORM);
                            	stuffcmd (other, "bf\n");
                            	remove(self);
                            	self = other;
                            };
                            
                            // Drop the life essence
                            void() Drop_Essence =
                            {
                                local entity item;
                            	item = spawn();
                            	
                                  item.netname = "Life Essence\n";
                            	  
                            	  item.health = 6 + 20*random();
                            	  
                            	  
                            	  setmodel(item, "progs/items/essence.mdl");
                                    item.velocity_z = 300;
                                    item.velocity_x = -100 + (random() * 200);
                                    item.velocity_y = -100 + (random() * 200);
                            
                                item.classname = "essence";
                                
                                    item.flags = FL_ITEM;
                                    item.solid = SOLID_TRIGGER;
                                    item.movetype = MOVETYPE_TOSS;
                            	setsize (item, '-16 -16 0', '16 16 56');
                                setorigin(item, self.origin);
                                item.think = essence_effect;
                            	item.nextthink = time + 0.2;
                                item.touch = essence_Touch;
                            };
                            Where to begin. You had alot of unnecessary code that just needed to be cleaned up. Most of it was harmless but if it shouldn't be there so we should try to get rid of it. So I cleaned up the code to remove most of these problems and annoyances. Firstly your call to sprint the item.netname was not working and it defaulted to "you get (random #) health" which was always in a decimal. I figure what's the point in even having that message? So I got rid of the health message altogether (it was conflicting with the first message anyway) and when you pick up the item it simply says "You devour it's Life Essence" Cool, eh? Now lets say you want to keep the information about health but don't want the decimals? Ok, fair enough. Luckily Quake C has a function built in to fix this problem much like C. We can use floor to round the integer down or use ceil. Here is an example from your code:

                            Code:
                            item.health = 6 + 20*random();
                            
                            //change it to
                            
                            item.health = floor(6 + 20*random());
                            
                            //if you decide to define this you'll need to set a float much like you did with  r=random ().
                            While I was at it, I decided why be limited to 100 health anyway? Hell you are devouring life essence for crying outloud! LOL! So I added this line of code:

                            Code:
                            if (other.health >= 150)
                            			return;
                            		if (!T_Heal(other, self.health))
                            in place of:

                            Code:
                            if (other.health <= 0)
                            		return;

                            This basically allows you to keep picking up life essence up to 150 health and of course the amount you get varies each time because of this code:

                            Code:
                             item.health = 6 + 20*random();
                            Which I think is pretty cool. Could even make an exception to get larger amounts when it's say a fiend or shambler. Just a suggestion.
                            If you want to add a flash effect when picking up this heart Inside3d has a good tut on making a custom qc file that produces a function you can set specific parameters into to get the specific effect you want. Go over here to check it out. I recommend it. Word of caution when using tuts from Inside3d. They often have lots of typos :/ So quite a few of the examples and tuts won't work if you simply copy and paste them. So check the syntax first.

                            I think everything else stayed the same so that file can be saved. items.qc

                            Now moving on to world.qc:

                            Code:
                            // player precaches	
                            	W_Precache ();			// get weapon precaches
                            
                            	E_Precache ();			// get life essence precaches
                            The above is correct so no problems. Save world.qc

                            Now to combat.qc:

                            Code:
                            // All enemies have a chance to drop life essence
                            	local float r; //include this!!!
                            r = random();
                            		if (r < 0.33)
                            			Drop_Essence ();
                            The above code is correct. So why did you get that error? It's simple. combat.qc is complied BEFORE items.qc which is where you defined Drop_Essence. But since it will get defined later all we need to do is add this to the top of the file.

                            Code:
                            void() Drop_Essence;
                            LoL! That's it! Simple eh? This just keeps the compiler happy its defined. That should get you past that error and I fixed the problems that would have gotten you many more.


                            Now this is far from done and you'll need to continue tweaking this to change how the items fall, maybe give monster specific parameters, etc. But I made a video showing the effect in game using some borrowed assets from Seven's SMC just to quicky show you what it looks like in game. Obviously your assets will be different. You'll notice the pick up message and my health going up beyond 100. The added bonus here is it is not like the megahealth and slowly go away over time. It stays Currently I have the chance up to 75% just for testing to show you in video so that is why it happens so often. you could even limit it to specific monsters using the method I told you about before calling the function in the death animation in the monster's qc file. If any of this was unclear let me know. Oh... Compile and Play You're done. Atleast I am. Hehe. The video is processing so you may not be able to watch if depending on when you see this post. Cheers.

                            Youtube: Quake C Example of Drop_Essence ()


                            BTW: I'm a newbie at Quake C so I am sure some of the things I am showing could be done better or maybe be wrong so do your research and ask questions to others too. But for me, if it compiles and plays I'm solid. Script Kiddie coders like me make a bad name for guys like r00k and Seven. hehe.
                            Last edited by PrimalLove; 08-14-2014, 10:55 PM.

                            Comment


                            • #15
                              If you wanna do some wicked effects beyond what is normally possible in terms of flash effects I mentioned before you can look into CSQC. For an example of this in action check out Kleshik. My fav mod! CSQC makes that kind of stuff possible. Anyway, that's my two cents. I hope you get everything working well. Upload the source and some screenies when you get done! I love to play with this stuff! It's a pretty cool idea!

                              Comment

                              Working...
                              X