Inside3D!
     

How to make a weapon shoot through walls?

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming
View previous topic :: View next topic  
Author Message
Orion



Joined: 12 Jan 2007
Posts: 414
Location: Brazil

PostPosted: Fri Feb 20, 2009 10:15 pm    Post subject: How to make a weapon shoot through walls? Reply with quote

Hi, I put a half-life style gauss gun to Quake, and I want to make it shoot through walls... How is this possible?
It's a hitscan weapon though.
Any help will be appreciated.

EDIT: I created a method where an entity is created at trace_endpos + v_forward*2 (inside the wall) and checks every frame if pointcontents is not CONTENT_EMPTY, but it's still... wrong. When I fire it at a very thick wall it takes about 3 seconds to "shoot" the beam at the other end of the wall.
Also, if I do a while loop I get a runaway loop error.
Screenshots and code below.


Shooting at wall:


The shoot-thru:



Here's the code.

Code:

void() ShootThrough =
{
   self.nextthink = time;
   
   makevectors (self.angles);
   
   if (pointcontents(self.origin) != CONTENT_EMPTY)
      self.origin = self.origin + v_forward*2;
   
   if (pointcontents(self.origin) == CONTENT_EMPTY)
   {
      dprint ("gauss succesfully fired through that wall!\n");
      traceline (self.origin, self.origin + v_forward*600, FALSE, self);
      ParseBeam ();
      
      if (trace_fraction == 1)
         return;
   
      if (trace_ent.takedamage)
      {
         particle (trace_endpos, '0 0 100', 225, self.health*4);
         trace_ent.deathtype = "gauss";
         T_Damage (trace_ent, self, self.owner, self.health);
      }
      
      remove(self);
   }
};

void() W_FireGauss =
{
   local vector org;
   local float damage;
   local entity e;
   
   sound (self, CHAN_WEAPON, "weapons/gauss2.wav", 1, ATTN_NORM);
   
   self.punchangle_x = -2;
   
   if (self.currentammo == 1)
   {
      self.currentammo = self.ammo_cells = self.ammo_cells - 1;   // that's just not to go to -1, but will do less damage
      damage = 10;
   }
   else
   {
      self.currentammo = self.ammo_cells = self.ammo_cells - 2;
      damage = 20;
   }
   
   makevectors (self.v_angle);
   org = self.origin + v_right*8 + '0 0 16';
   
   ParseBeam ();
   
   traceline (org, org + v_forward*1000, FALSE, self);
   if (trace_fraction == 1)
      return;
   
   if (trace_ent.takedamage)
   {
      particle (trace_endpos, '0 0 100', 225, damage*4);
      trace_ent.deathtype = "gauss";
      T_Damage (trace_ent, self, self, damage);
   }
   
   e = spawn ();
   e.owner = self;
   e.health = damage;
   e.origin = trace_endpos + v_forward*2;
   e.angles = vectoangles(v_forward);
   e.nextthink = time;
   e.think = ShootThrough;
};

_________________
There's no signature here. Stop looking for one.
Back to top
View user's profile Send private message
r00k



Joined: 13 Nov 2004
Posts: 483

PostPosted: Sat Feb 21, 2009 7:03 pm    Post subject: Reply with quote

I havent read thru your code atm in a hurry, but look at id software's original lg code in weapons.qc, as there was a bug that allowed the lg damage to transpose thru the wall. Razz
Back to top
View user's profile Send private message
Orion



Joined: 12 Jan 2007
Posts: 414
Location: Brazil

PostPosted: Sat Feb 21, 2009 11:34 pm    Post subject: Reply with quote

I'm sorry but the lightning gun can't do any damad ge through a wall...
I'm a bit druynk here.. sorry for mispelled worsds..
Afaiik the lg don't do amage through a wall.. unless if you can prove the contrary.
_________________
There's no signature here. Stop looking for one.
Back to top
View user's profile Send private message
MeTcHsteekle



Joined: 15 May 2008
Posts: 397
Location: its a secret

PostPosted: Sat Feb 21, 2009 11:41 pm    Post subject: Reply with quote

they do it in QDQ in shub's pit

edit: http://www.youtube.com/watch?v=h81irjuSweM around 3:40
_________________
bah
Back to top
View user's profile Send private message AIM Address
r00k



Joined: 13 Nov 2004
Posts: 483

PostPosted: Sun Feb 22, 2009 5:17 am    Post subject: Reply with quote

Ya its a bug but might help you figure out a method. Smile
unless its a collision bug with doors instead of just a normal wall.

I'll try to tweak something out in the morning Wink
Back to top
View user's profile Send private message
Wazat



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

PostPosted: Sun Feb 22, 2009 6:16 pm    Post subject: Reply with quote

There was once a mod -- and I do not remember what it was -- that had a black hole gun. Basically you shot it at a wall and it would search through until it found the wall on the other side (if there was an opposite side). Upon success, it would open a portal on both ends, and any player that stepped into the portal on one side would teleport to the other side. It was a very clever weapon.

I examined the code and this is what I remember about how it worked:

1. Traceline from your gun to the wall. If you hit a target, do damage to it (actually I think the portal didn't do damage but whatever), step forward 8 units, set the trace_ignore to that entity, and traceline again. Repeat until you find a wall.
2. Step forward fifty or a hundred or so units and perform a pointcontents check. Repeat this step until you find non-solid area OR you hit your loop limit (say, 10-15 attempts).
3. If your loop never found open air, quit. Otherwise, traceline backwards (ignoring entities) to find the other side of the wall, and move forwards 1-4 or so units to get slightly away from the wall.
4. Because we're making a portal, we need to make sure there's enough space in the open area for a player to teleport to it. Perform a bunch of tracelines in several directions to figure out how to place the portal sufficiently far away from the floor and other walls so that a player can fit inside. If you determine that there isn't enough space or that something else is wrong, quit.
5. If successful, spawn a visual portal on both sides of the wall and give them a touch function for teleporting players.

Obviously, steps 4 and 5 do not apply to a gun that only needs to shoot through one or many walls. You would want to replace these steps with this:

4. Spawn an entity that will think next frame. Set its owner to the player and give it the damage amount, direction fired, and a count of how many walls it's plowed through (it will increase this count and give it to any entities it spawns).
5. Upon its think, begin again at step 1 with the traceline to hit a wall. Damage entities as normal until it hits a wall. When it does hit a wall, only try to bore through it if your "bullet" hasn't hit its wall limit (say, 5 walls).


I should note that step 1 is a potential problem in a rare, freak case when the player fires through 50 entities. I used to make maps where the player fought hundreds of dogs all lined up in neat little rows. The chain lightning gun and railgun were AWESOME on that map. Very Happy

If you want to account for such a case and avoid the dreaded infinite loop trigger, you can have each segment of step 1 and 2 separated by a frame by spawning an entity like in our revised steps 4 and 5. Thus, every time it hits a monster it spawns a new entity and waits to go through it. (note: this code is simpler than the loop, and safer, and after reading your code I've concluded that this is exactly what you're doing).

This may be unnecessary though. If you limit your wall digging code to 15 tries at 50 units each, you can go through a wall up to 750 units in length. 15 loop iterations ain't so bad if your loop isn't doing a ton of work. Likewise, there usually won't be more than, say, 15 enemies in a row (though that loop is doing a lot more work for damaging and killing the enemies, so this is a potential weak point). Split it up as you see necessary.




BTW, I just read your code. Your code is already very close to what I'm talking about and could be modified in the following ways:

If you hit a damagable entity, go through it the same way you're doing.
If you hit a wall, step forward by 50 instead of 2. Continue to do this until you hit empty air or you run out of tries (see below).
If this gets you into empty air, traceline (ignoring ents) backwards to find the wall again so you don't jump too far. Now you can traceline forward again 600 or 2000 units, hitting ents as normal. Do damage to entities and set up for the next adventure (nextthink).
Add a counter to test how many times it's ended up in a solid without finding an air gap (or far it's traveled). Once it goes too long, remove the entity so it doesn't fly forever after leaving the level. You might also add a limit for how many walls it will go through total.
Remember to set the entity you last hit as the ignore/owner entity for the traceline (I think if you start the traceline inside the entity but don't say to ignore it, the traceline will ignore it and all other entities instead of hitting the entities past it).

There, that's simpler than my earlier explanation, is immune to infinite loops triggering, and you don't even need to change your code much. Very Happy

I hope that helps!
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
Back to top
View user's profile Send private message MSN Messenger
Orion



Joined: 12 Jan 2007
Posts: 414
Location: Brazil

PostPosted: Sun Feb 22, 2009 8:52 pm    Post subject: Reply with quote

Nice! Smile
Thank you Wazat! Very Happy

But my code was heavily modified... I had a little trouble at the beginning.
Also, the gauss gun will only go through one wall.

It's all at the fire function:

Code:

void() W_FireGauss =
{
   local vector org, tendpos;
   local float damage, fwd, tries;
   local entity tent, e;
   
   sound (self, CHAN_WEAPON, "weapons/gauss2.wav", 1, ATTN_NORM);
   
   self.punchangle_x = -2;
   
   if (self.currentammo == 1)
   {
      self.currentammo = self.ammo_cells = self.ammo_cells - 1;   // that's just not to go to -1, but will do less damage
      damage = 10;
   }
   else
   {
      self.currentammo = self.ammo_cells = self.ammo_cells - 2;
      damage = 20;
   }
   
   makevectors (self.v_angle);
   org = self.origin + v_right*8 + '0 0 16';
   
   ParseBeam (org);
   
   traceline (org, org + v_forward*1000, FALSE, self);
   if (trace_fraction == 1)
      return;
   
   tendpos = trace_endpos;
   
   if (trace_ent.takedamage)
   {
      particle (trace_endpos, '0 0 100', 225, damage*4);
      trace_ent.deathtype = "gauss";
      T_Damage (trace_ent, self, self, damage);
      
      org = tendpos + v_forward*8;
      tent = trace_ent;
      ParseBeam (org);
      traceline (org, org + v_forward*600, FALSE, tent);
      if (trace_fraction == 1)
         return;
      
      if (trace_ent.takedamage)
      {
         particle (trace_endpos, '0 0 100', 225, damage*4);
         trace_ent.deathtype = "gauss";
         T_Damage (trace_ent, self, self, damage);   
      }
      return;
   }
   
   fwd = 0;
   while (tries < 15)
   {
      fwd = fwd + 50;
      tries = tries + 1;
      if (pointcontents(tendpos + v_forward*fwd) == CONTENT_EMPTY)
         tries = 15;
   }
   
   if (pointcontents(tendpos + v_forward*fwd) == CONTENT_EMPTY)
   {
      dprint ("shoot-through successfull!\n");
      e = spawn ();
      e.origin = tendpos + v_forward*fwd;
      
      traceline (e.origin, e.origin - v_forward*300, TRUE, e);
      
      e.origin = trace_endpos + v_forward*4;
      ParseBeam (e.origin);
      traceline (e.origin, e.origin + v_forward*600, FALSE, e);
      if (trace_fraction == 1)
      {
         remove(e);
         return;
      }
      
      if (trace_ent.takedamage)
      {
         particle (trace_endpos, '0 0 100', 225, damage*4);
         trace_ent.deathtype = "gauss";
         T_Damage (trace_ent, self, self, damage);   
      }
      
      remove(e);
   }
};

_________________
There's no signature here. Stop looking for one.
Back to top
View user's profile Send private message
xaGe



Joined: 01 Mar 2006
Posts: 329
Location: Upstate, New York

PostPosted: Mon Feb 23, 2009 1:56 am    Post subject: Reply with quote

Sounds like some thing similar to this portal mod or this one or even this newer one that seems as a rip off of previous ones..

Wazat wrote:
There was once a mod -- and I do not remember what it was -- that had a black hole gun. Basically you shot it at a wall and it would search through until it found the wall on the other side (if there was an opposite side). Upon success, it would open a portal on both ends, and any player that stepped into the portal on one side would teleport to the other side. It was a very clever weapon.
Back to top
View user's profile Send private message Send e-mail Visit poster's website MSN Messenger
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Mon Feb 23, 2009 12:00 pm    Post subject: Reply with quote

if your trace hits a wall, try a new trace just on the other side of that wall.
if the trace starts solid, the trace fraction is often 1. if the trace fraction is 1, then it didn't hit anything, and the trace will continue through to hit monsters.
I'm not sure if it'll still hit the world surfaces when it started solid or not.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
Orion



Joined: 12 Jan 2007
Posts: 414
Location: Brazil

PostPosted: Mon Feb 23, 2009 10:38 pm    Post subject: Reply with quote

The gauss gun is now working perfectly.

I also made a hole gun which makes you teleport through walls.
I uploaded a video doing a speedrun using the gun on e2m5.

I wasted a little time because of misplaced holes.

http://www.youtube.com/watch?v=EsEbYybWAgk
_________________
There's no signature here. Stop looking for one.
Back to top
View user's profile Send private message
Wazat



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

PostPosted: Tue Feb 24, 2009 1:36 am    Post subject: Reply with quote

LOL, awesome vid. I'm glad you got it working!
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
Back to top
View user's profile Send private message MSN Messenger
Lardarse



Joined: 05 Nov 2005
Posts: 243
Location: Bristol, UK

PostPosted: Wed Mar 11, 2009 12:11 am    Post subject: Reply with quote

r00k wrote:
I havent read thru your code atm in a hurry, but look at id software's original lg code in weapons.qc, as there was a bug that allowed the lg damage to transpose thru the wall. Razz

MeTcHsteekle wrote:
they do it in QDQ in shub's pit

That's actually a different bug. The lightning beam that kills the monsters actually starts on the other side of the wall...
Back to top
View user's profile Send private message
Urre



Joined: 05 Nov 2004
Posts: 1073
Location: Sweden

PostPosted: Wed Mar 11, 2009 7:11 am    Post subject: Reply with quote

Hahah, cool clip
_________________
Look out for Twigboy
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    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