[Tutorial]Extra Ammo Types I have seen countless requests for tutorials for different ammo types, and although BrotherTank and Paal has released one, I think many people are thrown off by the screen dumps and extra code (as in BT's WWW tutorial). Here is my code for Seperate Ammo. It seems a bit unnecessary to do the first part, but I find this makes the code easier to edit. In this tutorial, I present code for pistol, chaingun, and machinegun ammo, and extra code should you want to add more weapons with seperate ammo.
First, open WL_DEF.H and search for 'ammo':
#define STARTAMMO 8
Change it to look like:
#define STARTAMMO 8
#define STARTAMMO2 0
#define STARTAMMO3 0
//#define STARTAMMO4 0
//#define STARTAMMO5 0
//#define STARTAMMO6 0
Once again, search for 'ammo'. Your code should look something like:
typedef struct
{
byte difficulty;
byte mapon,oldmap;
long oldscore,score,nextextra;
char lives;
int health;
byte count;
char ammo:
char keys;
char guardweapon;
weapontype bestweapon,weapon,chosenweapon;
char faceframe;
int attackframe,attackcount,weaponframe;
char episode,secretcount,treasurecount,killcount,
secrettotal,treasuretotal,killtotal;
long TimeCount;
long killx,killy;
boolean victoryflag; // set during victory animations
} gametype;
Delete the 'char ammo' line, and underneath the entire structure add:
//--------------
//
// ammo structure
//
//--------------
typedef struct
{
char ammo1;
char ammo2;
char ammo3;
// char ammo4;
// char ammo5;
// char ammo6;
} ammo_t;
Next, search for 'gamestate'. Your hit should look like:
extern gametype gamestate;
Add the following line underneath:
extern ammo_t ammotype;
Now, go through the WL_****.C files, and change all occurances of gamestate.ammo into ammotype.ammo1.
That might have seemed unnecessary, and if you don't want to do that last bit, just add the ammo variables into the gamestate structure. I did this because it made the code easier to edit.
Now, open WL_MAIN.C and find the NewGame function:
void NewGame (int difficulty,int episode)
{
memset (&gamestate,0,sizeof(gamestate));
gamestate.difficulty = difficulty;
gamestate.weapon = gamestate.bestweapon = gamestate.chosenweapon = wp_pistol;
gamestate.health = 100;
ammotype.ammo1 = STARTAMMO;
gamestate.lives = 3;
gamestate.nextextra = EXTRAPOINTS;
gamestate.episode=episode;
startgame = true;
}
Add the following lines underneath the ammotype.ammo1 line:
ammotype.ammo2 = STARTAMMO2;
ammotype.ammo3 = STARTAMMO3;
//ammotype.ammo4 = STARTAMMO4;
//ammotype.ammo5 = STARTAMMO5;
//ammotype.ammo6 = STARTAMMO6;
And do the same thing in the Died function. That bit of code decides how much ammo for each weapon at the beginning of the game and after you die.
Now, onto WL_AGENT.C, where all the weapon action occurs. Replace the CheckWeaponChange function with:
/*==
==== CheckWeaponChange/ChkAtkAmmo
==== Editted by BrotherTank
====
==== Number Keys 1-10 select Weapon.
==== ChkAtkAmmo checks to see if player
==== has any ammo for the weapon, if not,
==== switch to knife.
==*/
// Checks to make sure you have ammo for weapon
// returns "true" if yes and "false" if no
int ChkAtkAmmo (int weapon)
{
switch (weapon)
{
case wp_knife: return 1;
case wp_pistol:
if (ammotype.ammo1 > 0 ) return 1;
case wp_machinegun:
if (ammotype.ammo2 > 0 ) return 1;
case wp_chaingun:
if (ammotype.ammo3 > 0 ) return 1;
break;
}
return 0;
}
void CheckWeaponChange (void)
{
int i,kbuttons[10]={sc_1,sc_2,sc_3,sc_4,sc_5,sc_6,sc_7,sc_8,sc_9,sc_0};
for (i=0;i<NUMWEAPONS;i++)
if ((Keyboard[kbuttons[i]]) && (i != gamestate.weapon))
{
if (buttonstate[bt_readyknife+i-wp_knife])
{
gamestate.weapon = gamestate.chosenweapon = i;
DrawWeapon ();
DrawAmmo ();
return;
}
}
}
ChkAtkAmmo checks to see if you have any ammo for a weapon. If yes, it returns true, if no, it returns false. Now, scroll down to the GiveWeapon function. Make it look like:
/*==
==== GiveWeapon
==== Editted by BrotherTank/Deathshead
====
==== Gives Player a weapon, with 6 ammo for that
==== weapon.
==*/
void GiveWeapon (int weapon)
{
switch (weapon)
{
case wp_pistol:
GiveAmmo (wp_pistol,6);
break;
case wp_machinegun:
GiveAmmo (wp_machinegun,6);
break;
case wp_chaingun:
GiveAmmo (wp_chaingun,6);
break;
}
if (gamestate.bestweapon<weapon)
gamestate.bestweapon = gamestate.weapon = gamestate.chosenweapon = weapon;
DrawWeapon ();
DrawAmmo ();
}
You will notice the extra parameters called in GiveAmmo. This will be explained in a second. Now, replace the DrawAmmo routine with this variation:
/*==
==== DrawAmmo
==== Editted by Deathshead
====
==== This is another variation of the original DrawAmmo
==== routine. For each weapon, the ammo variable becomes
==== the amount of ammo for the weapon. It then displays
==== the ammo onn te statusbar
==*/
void DrawAmmo (void)
{
char ammo;
switch (gamestate.weapon)
{
case wp_knife:
ammo=0;
break;
case wp_pistol:
ammo = ammotype.ammo1;
break;
case wp_machinegun:
ammo = ammotype.ammo2;
break;
case wp_chaingun:
ammo = ammotype.ammo3;
break;
}
LatchNumber (27,16,3,ammo);
}
This checks what ammo the weapon uses, then displays that amount on the statusbar. Now for the GiveAmmo routine. This is BrotherTanks version, which allows for multiple ammotypes and weapons. Examine it, and you will understand:
/*==
==== GiveAmmo
==== Editted by BrotherTank/Deathshead
====
==== This variation of GiveAmmo, will give
==== the player ammo for a weapon
==*/
void GiveAmmo (int weapon,char ammo)
{
if (!ammotype.ammo1 && !ammotype.ammo2 && !ammotype.ammo3) // knife was out
{
if (!gamestate.attackframe)
{
gamestate.weapon = gamestate.chosenweapon;
DrawWeapon ();
}
}
switch (weapon)
{
case wp_pistol:
ammotype.ammo1 += ammo;
if (ammotype.ammo1 > 50) ammotype.ammo1 = 50;
break;
case wp_machinegun:
ammotype.ammo2 += ammo;
if (ammotype.ammo2 > 100) ammotype.ammo2 = 100;
break;
case wp_chaingun:
ammotype.ammo3 += ammo;
if (ammotype.ammo3 > 200) ammotype.ammo3 = 200;
break;
}
DrawAmmo ();
}
For that function to work though, you have to go back to the top of the file and change:
void GiveAmmo (int ammo);
to:
void GiveAmmo (int weapon,char ammo);
And do the same thing in WL_DEF.H . Now change all occurances of:
GiveAmmo (Number);
to Read:
[code]
GiveAmmo (wp_pistol,Number);
[/code]
Where Number is how much ammo is given. Now go down to the T_Attack function. Look for the following slabs of code and change accordingly:
[code]
case -1:
ob->state = &s_player;
if (!ammotype.ammo1)
{
gamestate.weapon = wp_knife;
DrawWeapon ();
}
else
{
if (gamestate.weapon != gamestate.chosenweapon)
{
gamestate.weapon = gamestate.chosenweapon;
DrawWeapon ();
}
};
gamestate.attackframe = gamestate.weaponframe = 0;
return;
[/code]
to:
[code]
case -1:
ob->state = &s_player;
if (!ChkAtkAmmo (gamestate.weapon) && gamestate.chosenweapon != wp_knife)
{
gamestate.weapon = wp_knife;
for (i=wp_pistol; i<NUMWEAPONS; i++)
{
if (ChkAtkAmmo (i) && gamestate.bestweapon >= i)
{
gamestate.weapon = i;
}
}
DrawWeapon ();
DrawAmmo ();
}
else
{
if (gamestate.weapon != gamestate.chosenweapon)
{
if (ChkAtkAmmo(gamestate.chosenweapon))
gamestate.weapon = gamestate.chosenweapon;
DrawWeapon ();
}
}
gamestate.attackframe = gamestate.weaponframe = 0;
return;
[/code]
[code]
case 4:
if (!ammotype.ammo1)
break;
if (buttonstate)
gamestate.attackframe -= 2;
[/code]
to:
[code]
case 4: // Chaingun - Fall back 2 frames and fire again if button Pressed
if (!ChkAtkAmmo(gamestate.weapon)) break;
if (buttonstate) gamestate.attackframe -= 2;
[/code]
[code]
case 1:
if (!gamestate.ammo)
{ // can only happen with chain gun
gamestate.attackframe++;
break;
}
GunAttack (ob);
ammotype.ammo1--;
DrawAmmo ();
break;
[/code]
to:
[code]
case 1:
if (!ChkAtkAmmo(wp_chaingun) && gamestate.weapon == wp_chaingun)
{ gamestate.attackframe++; break; }
if (ChkAtkAmmo(gamestate.weapon))
{
GunAttack (ob);
switch (gamestate.weapon)
{
case wp_pistol:
ammotype.ammo1--;
break;
case wp_machinegun:
ammotype.ammo2--;
break;
case wp_chaingun:
ammotype.ammo3--;
break;
}
DrawAmmo ();
break;
}
else
{ return; }
[/code]
[code]
case 3:
if (ammotype.ammo2 && buttonstate)
gamestate.attackframe -= 2;
break;
[/code]
to:
[code]
case 3:
if (ChkAtkAmmo(gamestate.weapon) && buttonstate)
gamestate.attackframe -= 2;
break;
[/code]
That concludes my tutorial. Please tell me if there are problems, as this is almost directly from my source.
If you use this, please include me and BrotherTank in your credits, and send me an email at deathshead.frozenfire@gmail.com , as I would like to see your project!
There you go
-Deathshead
Flamer46- 04-06-2005
Why did you add a new struct in WL_DEF.h? It`s a waste of memory. I know that idea has been around for some time but why do it? I did multiple ammo`s for Operation supernatural in a lot easier way.
Deathshead- 04-07-2005
Because, looking for 'ammotype' is alot easier for me. It doesn't take up too much, and what I do later saves that memory, and more. Also, I said you can skip that step and just add it in gamestate if you can't be bothered. It's up to you. OK?
Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.