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

How to make a weapon shoot through walls?

| Inside3d Forums Forum Index -> QuakeC Programming

View previous topic :: View next topic
Author | Message
--- | ---
Orion Joined: 12 Jan 2007 Posts: 414 Location: Brazil |

Posted: Fri Feb 20, 2009 10:15 pm Post subject: How to make a weapon shoot through walls? |

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 |

r00k Joined: 13 Nov 2004 Posts: 483 |

Posted: Sat Feb 21, 2009 7:03 pm Post subject: |

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.

Back to top |

Orion Joined: 12 Jan 2007 Posts: 414 Location: Brazil |

Posted: Sat Feb 21, 2009 11:34 pm Post subject: |

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 |

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

Posted: Sat Feb 21, 2009 11:41 pm Post subject: |

they do it in QDQ in shub's pit edit: http://www.youtube.com/watch?v=h81irjuSweM around 3:40 _________________ bah

Back to top |

r00k Joined: 13 Nov 2004 Posts: 483 |

Posted: Sun Feb 22, 2009 5:17 am Post subject: |

Ya its a bug but might help you figure out a method. unless its a collision bug with doors instead of just a normal wall. I'll try to tweak something out in the morning

Back to top |

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

Posted: Sun Feb 22, 2009 6:16 pm Post subject: |

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.
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.
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 |

Orion Joined: 12 Jan 2007 Posts: 414 Location: Brazil |

Posted: Sun Feb 22, 2009 8:52 pm Post subject: |

Nice! Thank you Wazat! 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 |

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

Posted: Mon Feb 23, 2009 1:56 am Post subject: |

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 |

Spike Joined: 05 Nov 2004 Posts: 944 Location: UK |

Posted: Mon Feb 23, 2009 12:00 pm Post subject: |

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 |

Orion Joined: 12 Jan 2007 Posts: 414 Location: Brazil |

Posted: Mon Feb 23, 2009 10:38 pm Post subject: |

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 |

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

Posted: Tue Feb 24, 2009 1:36 am Post subject: |

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 |

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

Posted: Wed Mar 11, 2009 12:11 am Post subject: |

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.

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 |

Urre Joined: 05 Nov 2004 Posts: 1073 Location: Sweden |

Posted: Wed Mar 11, 2009 7:11 am Post subject: |

Hahah, cool clip _________________ Look out for Twigboy

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