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

Improvement to standard backpack touch

| Inside3d Forums Forum Index -> QuakeC Programming

View previous topic :: View next topic
Author | Message
--- | ---
Cobalt Joined: 10 Jun 2009 Posts: 17 |

Posted: Thu Jun 18, 2009 12:15 am Post subject: Improvement to standard backpack touch |

I have been wanting to do this one for a long time, but the proper plan sort of eludes me. Lets say theres a backpack from a fragged player that has (40) shells , (64) nails and (100) cells. The player touches it, and he already has (90) shells (40) nails and (0) Cells.
The ID code merely gives the player (100) shells, (100) nails and (100) cells, and the backpack disappears. I want the player to get the same ammo, but leave the backpack there containing what he cannot carry: (30) shells, (4) nails. Heres the touch function Im using, which I think is pretty much standard. Any help with some good code, or if anyone knows existing code to do this, thanks.
void () BackpackTouch =
{
local string s;
local float best;
local float old;
local float new;
local float bbest;
local entity stemp;
local float acount;
if (((other.classname != "player") && (other.classname != "bot")))
{
return;
}
if ((other.health <= 0))
{
return;
}
if (((other == self.owner) && ((self.nextthink - time) > 118)))
{
return;
}
acount = 0;
if ((cvar ("temp1") < 65535))
{
if ((other.classname == "player"))
{
sprint (other, "You get ");
}
}
stemp = self;
self = other;
best = W_BestWeapon ();
if (self.classname == "bot")
{
if (stemp.altname == "tossedpack")
fBotSayTeam (": Thanks.\n");
else if ((stemp.ammo_shells + stemp.ammo_nails) > 175 || (stemp.ammo_rockets + stemp.ammo_cells) > 100)
{
bprint (self.talkname);
bprint ("º ");
BotSayMiddle ("Nice Pack ");
if (stemp.owner.team != self.team)
BotSayMiddle (stemp.owner.netname);
BotSayEnd ();
}
}
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;
old = other.items;
other.items = (other.items | new);
bound_other_ammo ();
if ((other.classname == "player"))
{
if ((cvar ("temp1") < 65535))
{
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");
stuffcmd (other, "bf\n");
}
}
if (((deathmatch & DM_START_SMALL) || (deathmatch & DM_START_BIG)))
{
other.health = (other.health + 5);
}
sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, SUB_Db());
remove (self);
self = other;
if ((other.classname == "player"))
{
if ((WeaponCode (new) <= other.best_wep))
{
if ((self.flags & FL_INWATER))
{
if ((new != IT_LIGHTNING))
{
Deathmatch_Weapon (old, new);
}
}
else
{
Deathmatch_Weapon (old, new);
}
}
}
else
{
Deathmatch_Weapon (old, new);
}
W_SetCurrentAmmo ();
};

Back to top |

Electro Joined: 29 Dec 2004 Posts: 241 Location: Brisbane, Australia |

Posted: Fri Jun 19, 2009 9:15 am Post subject: |

Sorry, the lack of formatting is making it impossible for me to even read. _________________ Unit reporting! http://www.bendarling.net/

Back to top |

Error Inside3D Staff Joined: 05 Nov 2004 Posts: 558 Location: VA, USA

Posted: Fri Jun 19, 2009 1:25 pm Post subject: |

doesn't using the [code] bbcode fix this? _________________ Inside3D : Knowledge Is Power Darkplaces Documentation Wiki

Back to top |

lurker Joined: 29 Jul 2006 Posts: 2 |

Posted: Fri Jun 19, 2009 4:46 pm Post subject: |

You will want to modify two different parts of the touch function to make the intended change possible. Part I:

Code:
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 ();

Part II:

Code:
remove(self); self = other;

Part I notes:
Imagine that the player had 90 shotgun shells and grabbed a large box (40 shells). The player's .ammo_shells would be 130. Id's BackpackTouch() already does this to the player and then uses bound_other_ammo() to cap it. Let's set the player's ammo the same way, but afterward shave the top off and assign it to the backpack. In this case, the backpack should be left with 30 shells (130 on player - 100 limit = 30).

Code:
other.ammo_shells = (other.ammo_shells + self.ammo_shells); if (other.ammo_shells > 100) self.ammo_shells = other.ammo_shells - 100;

As the player may have needed all ammo of a given type, remember to check for that and set the relevant ammo count on the backpack to 0. Otherwise the backpack will become an endless supply of ammo.

Code:
else self.ammo_shells = 0;

You will also need to make some changes to the way the "You got ..." messages are generated, since the player can now trigger the touch function without it actually giving the player anything. This is a bit more complicated, so I have provided a full solution below.
Part II notes:
Backpacks are removed when they are touched by players. You will want to remove it only if it is empty. I suggest borrowing the line in DropBackPack() that checks this.

Code:
if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells)) remove(self);

Example / Spoilers
To fix the display, I defined 4 local variables to hold the precise ammo count given to the player. I added a check to see if the backpack would need to generate a message and to exit the touch if not. I moved the weapon check after the ammo stuff to make that check possible. Though I didn't add your new functions to it, feel free to do so!
Edit: the same logic now applies to weapons in backpacks (remove weapon if taken).
Edit 2: was exhausted when writing previous edit. My previous mistake has been corrected.

Code:
void() BackpackTouch = { local float old, new; local float acount; local float taken_shells, taken_nails, taken_rockets, taken_cells, taken_item;
if (other.classname != "player")
return;
if (other.health <= 0)
return;
acount = 0;
other.ammo_shells = (other.ammo_shells + self.ammo_shells);
taken_shells = self.ammo_shells;
if (other.ammo_shells > 100)
{
self.ammo_shells = other.ammo_shells - 100;
other.ammo_shells = 100;
}
else
self.ammo_shells = 0;
taken_shells = taken_shells - self.ammo_shells;
other.ammo_nails = (other.ammo_nails + self.ammo_nails);
taken_nails = self.ammo_nails;
if (other.ammo_nails > 200)
{
self.ammo_nails = other.ammo_nails - 200;
other.ammo_nails = 200;
}
else
self.ammo_nails = 0;
taken_nails = taken_nails - self.ammo_nails;
other.ammo_rockets = (other.ammo_rockets + self.ammo_rockets);
taken_rockets = self.ammo_rockets;
if (other.ammo_rockets > 100)
{
self.ammo_rockets = other.ammo_rockets - 100;
other.ammo_rockets = 100;
}
else
self.ammo_rockets = 0;
taken_rockets = taken_rockets - self.ammo_rockets;
other.ammo_cells = (other.ammo_cells + self.ammo_cells);
taken_cells = self.ammo_cells;
if (other.ammo_cells > 100)
{
self.ammo_cells = other.ammo_cells - 100;
other.ammo_cells = 100;
}
else
self.ammo_cells = 0;
taken_cells = taken_cells - self.ammo_cells;
old = other.weapon;
if (self.items)
{
if ((other.items & self.items) == 0)
{
new = self.items;
other.items = (other.items | new);
self.items = 0;
taken_item = 3;
}
}
if (!new)
new = other.weapon;
//don't do the screen flash or generate a message unless necessary
//Don't bother players with messages, sound, or screenflash when they choose to stand
//on a backpack.
if ((taken_shells + taken_nails + taken_rockets + taken_cells + taken_item) > 2)
{
sprint (other, "You get ");
if (taken_item)
{
acount = 1;
sprint (other, "the ");
sprint (other, self.netname);
}
if (taken_shells)
{
if (acount)
sprint(other, ", ");
acount = 1;
s = ftos(taken_shells);
sprint (other, s);
sprint (other, " shells");
}
if (taken_nails)
{
if (acount)
sprint(other, ", ");
acount = 1;
s = ftos(taken_nails);
sprint (other, s);
sprint (other, " nails");
}
if (taken_rockets)
{
if (acount)
sprint(other, ", ");
acount = 1;
s = ftos(taken_rockets);
sprint (other, s);
sprint (other, " rockets");
}
if (taken_cells)
{
if (acount)
sprint(other, ", ");
acount = 1;
s = ftos(taken_cells);
sprint (other, s);
sprint (other, " cells");
}
sprint (other, "\n");
// backpack touch sound and screen effect
sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
stuffcmd (other, "bf\n");
}
// remove the backpack if it has no ammo
if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells))
remove(self);
// change to the weapon if it was taken.
self = other;
if (!deathmatch)
self.weapon = new;
else
Deathmatch_Weapon (old, new);
if (old != self.weapon)
W_SetCurrentAmmo ();
else
{
//mini W_SetCurrentAmmo()
//previous weapon and current weapon are the same.
//Just update the HUD; don't do weapon switch pause.
if (self.weapon == IT_SHOTGUN)
self.currentammo = self.ammo_shells;
else if (self.weapon == IT_SUPER_SHOTGUN)
self.currentammo = self.ammo_shells;
else if (self.weapon == IT_NAILGUN)
self.currentammo = self.ammo_nails;
else if (self.weapon == IT_SUPER_NAILGUN)
self.currentammo = self.ammo_nails;
else if (self.weapon == IT_GRENADE_LAUNCHER)
self.currentammo = self.ammo_rockets;
else if (self.weapon == IT_ROCKET_LAUNCHER)
self.currentammo = self.ammo_rockets;
else if (self.weapon == IT_LIGHTNING)
self.currentammo = self.ammo_cells;
else
self.currentammo = 0;
}
};

Last edited by lurker on Sat Jun 20, 2009 11:29 pm; edited 1 time in total

Back to top |

Cobalt Joined: 10 Jun 2009 Posts: 17 |

Posted: Sat Jun 20, 2009 8:55 pm Post subject: |

Hey, thanks! I also worked on some new code of my own but had problems with the leftover ammo never dispensing. So I commented it all out and tried your code, which is a huge step forward. Its really nice, but one thing that needs fixing is if you stand over the backpack and are firing the shotgun with 100 shells in your gun, you hear the guncock from the pack and you take a shell from the pack every time. Im thinking self.attack_finished needs to be put in there to prevent this from happening.
Another thing is that when you get craning with alot of frags, you wind up with many of these 'lesser' value ammo packs with shells laying around. So Im thinking to shorten the time do remove(self) happens quicker when more than 1 touch happens.
Also I noticed that sometimes you can touch a pack and get its (extra) shells, and one time I got the grenade launcher , with no grenades....which is kool, but I want to check the code again and make sure its giving up the weapon and deducting it from the pack so when its touched again, the weapon is not given again. Maybe you can tell me if that is working?

Back to top |

lurker Joined: 29 Jul 2006 Posts: 2 |

Posted: Sun Jun 21, 2009 12:23 am Post subject: |

I was exhausted when adding the weapon check and I think I introduced a bug. I have rewritten the whole section while addressing another of your concerns. Due to its length, the updated version appears at the end of my previous post. The weapon pickup/guncock sound no longer plays if the player is standing on a backpack while attacking. The player's ammo count continues to be updated as long as he or she stands on the backpack. I chose this in favor of setting .attack_time in case two players were both attempting to grab a backpack at the same time: if there is spare ammo, it wouldn't be fair to prevent the second player from grabbing it since the backpack is still clearly present.
In standard progs.dat, grabbing backpacks interrupts the player's current attack. I modified this to only interrupt the attack if the player's weapon has been changed by the backpack.
I agree: this sort of backpack_touch does leave too many backpacks in play. The quickest way to address this is to lower the timer in the following line of DropBackpack() :

Code:
item.nextthink = time + 120; // remove after 2 minutes

Back to top |

Cobalt Joined: 10 Jun 2009 Posts: 17 |

Posted: Mon Jun 22, 2009 3:11 pm Post subject: |

Looks interesting, gonna try it. I noticed you got rid of stemp = self and stemp = self. I never knew why they did that in much of the original code, it seems precautionary. All the code I ever wrote, I never needed to do that. The timer deduction for remove(self) is clever...I am using a .specific to count up to 4 each time the pack is touched, then it removes self. I may add something that detects if the pack contains only shells at spawn, make the timer about half or less than the default, to help lessen the number of packs laying around on the map.

Back to top |

frag.machine Joined: 25 Nov 2006 Posts: 728 |

Posted: Mon Jun 22, 2009 11:57 pm Post subject: |

Setting the time according the content looks a good idea IMO. Backpacks holding only a few shells last 20 or 30 seconds, but one containing a rocket launcher deserves to survive for 2 minutes. _________________ frag.machine - Q2K4 Project http://fragmachine.quakedev.com/

Back to top |

Cobalt Joined: 10 Jun 2009 Posts: 17 |

Posted: Wed Jun 24, 2009 2:54 am Post subject: |

Ok, finally got your code working with mine ! I used your ammo calculations as they seem to be flawless. I redid the 'you get' sprint, and of course the bf and sound so that it happens only when we have 'taken' something. Still got a bug with the comma popping up when you get just nails, rockets or cells, but it ought to be easy to fix. I took your advise and shortened the nextthink time by 15 if all we have are shells. Lot less packs floating around now.
Its amazing how one change like this alters gameplay for the bots. They have a tendency to hang around the ammo packs now, which seems to make gameplay a little more smoother and fun. It felt like a real CTF game.

Back to top |

Display posts from previous:

| Inside3d Forums Forum Index -> QuakeC Programming | All times are GMT
Page 1 of 1

Jump to:

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

Powered by phpBB © 2004 phpBB Group