Forum

The Floor Is Eating My Spikes!

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

The Floor Is Eating My Spikes!

Postby Junrall » Sat Feb 20, 2010 8:10 am

Playing around with ricocheting spikes... they work great, however when they hit the floor they disappear. I've gone through my code from one end to the other and can't seem to figure it out. Would someone mind looking through the code? Maybe a fresh set of eyes will see what I don't.
Also, they don't seem to like doors and switches and when they touch the sky they do not remove themselves. Any ideas?

Code: Select all
void() RicoThink =
{
   if (self.attack_finished < time)
   {
      remove(self);
      return;
   }

   if (self.flags & FL_ONGROUND)
      self.flags = self.flags - FL_ONGROUND;

   self.velocity = self.oldspikevel;
   self.angles = vectoangles(self.velocity);
   self.nextthink = time + 0.1;
};

void() RicoSpikeTouch =
{
   if (other.solid == SOLID_TRIGGER)
      return;
   if (pointcontents(self.origin) == CONTENT_SKY)
   {
      remove(self);
      return;
   }

   if (other.takedamage)
   {
      spawn_touchblood (9);
      T_Damage (other, self, self.owner, 9);
      if (other.health <= 0 && other != world)
         other.solid = SOLID_NOT;
      remove(self);
   }
   else
   {
      WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
      WriteByte (MSG_BROADCAST, TE_GUNSHOT);
      WriteCoord (MSG_BROADCAST, self.origin_x);
      WriteCoord (MSG_BROADCAST, self.origin_y);
      WriteCoord (MSG_BROADCAST, self.origin_z);
      
      self.velocity = ReboVec(self.origin, self.oldspikevel, FALSE);
      self.velocity = 1000 * self.velocity;
      self.angles = vectoangles(self.velocity);
      self.oldspikevel = self.velocity;

      if (self.flags & FL_ONGROUND)
         self.flags = self.flags - FL_ONGROUND;

      self.owner = self;
   }
};

void(vector org, vector dir) LaunchRicoSpike =
{
   newmis = spawn ();
   newmis.owner = self;
   newmis.movetype = MOVETYPE_FLYMISSILE;
   newmis.solid = SOLID_BBOX;

   newmis.touch = RicoSpikeTouch;
   newmis.classname = "spike";
   newmis.think = RicoThink;
   newmis.nextthink = time + 6;
   newmis.attack_finished = time + 5;
   setmodel (newmis, "progs/spike.mdl");
   setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
   setorigin (newmis, org);

   newmis.angles = vectoangles(dir);
   newmis.velocity = dir * 1000;
   newmis.oldspikevel = newmis.velocity;

};

void(float ox) W_FireRicoSpikes =
{
   local vector   dir;

   makevectors (self.v_angle);

   if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
   {
      sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
      self.attack_finished = time + 0.2;
      self.currentammo = self.ammo_nails = self.ammo_nails - 2;
      dir = aim (self, 1000);
      LaunchRicoSpike (self.origin + '0 0 16', dir);
      setmodel (newmis, "progs/s_spike.mdl");
      setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
      self.punchangle_x = -2;
      return;
   }

   if (self.ammo_nails < 1)
   {
      self.weapon = W_BestWeapon ();
      W_SetCurrentAmmo ();
      return;
   }

   sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
   self.attack_finished = time + 0.2;
   self.currentammo = self.ammo_nails = self.ammo_nails - 1;
   dir = aim (self, 1000);
   LaunchRicoSpike (self.origin + '0 0 16' + v_right*ox, dir);

   self.punchangle_x = -2;
};


Eventually I'll have the code set up so that some spikes will stick and others will ricochet or bounce of solids. Maybe not an original, but sure is fun to do!
Good God! You shot my leg off!
User avatar
Junrall
 
Posts: 191
Joined: Mon Sep 21, 2009 12:27 am
Location: North West Oregon, USA

Postby Teiman » Sat Feb 20, 2010 9:48 am

ricochet spikes are the fun (specially with proper ricochets wavs).

the subject for the thread is also a win :-)


I don't know much about modding, other people can help much more than me.. I am looking at this anyway.

humm...
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);

where is the real origin of the model? could be that the model of the spikes end underground?
Teiman
 
Posts: 309
Joined: Sun Jun 03, 2007 9:39 am

Postby Error » Sat Feb 20, 2010 10:03 am

oh god, Darkplaces makes everything so much easier :o

Code: Select all
//DP_MOVETYPEBOUNCEMISSILE
//idea: id Software
//darkplaces implementation: id Software
//movetype definitions:
//float MOVETYPE_BOUNCEMISSILE = 11; // already in defs.qc
//description:
//MOVETYPE_BOUNCE but without gravity, and with full reflection (no speed loss like grenades have), in other words - bouncing laser bolts.
User avatar
Error
InsideQC Staff
 
Posts: 865
Joined: Fri Nov 05, 2004 5:15 am
Location: VA, USA

Postby Junrall » Sat Feb 20, 2010 8:24 pm

Error wrote:oh god, Darkplaces makes everything so much easier :o

Lol... I'm sure it does:)
I've seen many similar answers for other QC questions... makes me wonder if I should spend time learning how to code for Darkplaces :P Can I do a check in QC to see if DP is being used or not and create code for DP and standard Quake?
Which creates more questions to pop into my head... which I'll post in another index and discussion :)

Teiman wrote:humm...
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);

where is the real origin of the model? could be that the model of the spikes end underground?

The setsize is directly from Quake's launch_spike function, so I'm not sure if that is the issue or not. Though, you may be right about the spikes ending below ground. Wouldn't the following code take care of that?
Code: Select all
   if (self.flags & FL_ONGROUND)
      self.flags = self.flags - FL_ONGROUND;


Teiman wrote:ricochet spikes are the fun (specially with proper ricochets wavs).

I have some cool ricochets wavs and bullet zings! In some rough ricochet code I was testing, you can hear the ricochets sounds then a zing/whir as the spike flies by! Very cool :D
Good God! You shot my leg off!
User avatar
Junrall
 
Posts: 191
Joined: Mon Sep 21, 2009 12:27 am
Location: North West Oregon, USA

Postby Supa » Sat Feb 20, 2010 9:15 pm

LaunchRicoSpike wrote:newmis.nextthink = time + 6;

Is there a reason that the spike's .think function is called so late? I remember from working with rebounding projectiles earlier that the server will mangle the velocity of projectiles on collision, but I can't be sure if that's causing your floor problem with just this. Anyway, so long as you're working on this you should invoke the spike's velocity correction one frame after every touch by adding self.nextthink = time to your touch code.

Code: Select all
      if (other.health <= 0 && other != world)
         other.solid = SOLID_NOT;

You do understand that this will break things like shootable buttons that reset after each trigger, right?

Can I do a check in QC to see if DP is being used or not and create code for DP and standard Quake?

All you need to do is check for the pr_checkextension cvar to see if you can use engine-specific extensions or not. Everything you need to know is right here, there's an example right at the beginning to get you started.
User avatar
Supa
 
Posts: 164
Joined: Tue Oct 26, 2004 8:10 am

Postby ceriux » Sat Feb 20, 2010 9:38 pm

just make them not solid instead of disappearing and have them remove themselfs if they hit a door or player. thats what i did. worked great.
User avatar
ceriux
 
Posts: 2223
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Postby Junrall » Sun Feb 21, 2010 1:52 am

Supa wrote:
LaunchRicoSpike wrote:newmis.nextthink = time + 6;

Is there a reason that the spike's .think function is called so late?... you should invoke the spike's velocity correction one frame after every touch by adding self.nextthink = time to your touch code.

Yep, I see what you mean. I'll fix that right away.

Supa wrote:
Code: Select all
      if (other.health <= 0 && other != world)
         other.solid = SOLID_NOT;

You do understand that this will break things like shootable buttons that reset after each trigger, right?

Nope, didn't know that... I'll try to correct that and take ceriux's suggestion.

Thanks to you both... still have to tackle spike eating floor thing... lol, won't be satisfied till I do!
Good God! You shot my leg off!
User avatar
Junrall
 
Posts: 191
Joined: Mon Sep 21, 2009 12:27 am
Location: North West Oregon, USA

Postby Junrall » Sun Feb 21, 2010 6:08 am

Ok... I figured it out. The problem was in the ReboVec function... I'm not saying that there is an error in ReboVec... maybe I'm using an older version that hadn't been updated yet? Here is where I got it:
http://forums.inside3d.com/viewtopic.php?t=1146
And here is the fix. Hopefully it doesn't cause problems elsewhere!
In ReboVec change
Code: Select all
spot1 = org - (16*dir);
spot2 = org + (16*dir);


to this
Code: Select all
spot1 = org - (16*olddir);
spot2 = org + (16*olddir);

I'm not sure why, but the above code now lets the spikes bounce off doors, lifts, and switches without any checks!

To be honest, I can't take credit for this. I found the fix in Orion's tutorial, Ricocheting Laser Cannon... which my code is based off... well, heavily so!
What a great tutorial for learning how to tie together vectors, velocity, origin, and angles.
Now that I have a functional ricocheting spike (and finished breaking Orion's code!) I can add my sticky spikes and bouncing spikes to it. And then I'm off to try this with the DP's extensions... hopefully I won't break anything there! :lol:
Good God! You shot my leg off!
User avatar
Junrall
 
Posts: 191
Joined: Mon Sep 21, 2009 12:27 am
Location: North West Oregon, USA

Postby Lardarse » Sun Feb 21, 2010 6:17 am

Strange why that might be the issue...
Roaming status: Testing and documentation
User avatar
Lardarse
 
Posts: 266
Joined: Sat Nov 05, 2005 1:58 pm
Location: Bristol, UK

Postby Wazat » Mon Feb 22, 2010 1:39 am

At that point in the code the only thing that appears to be different between dir and olddir is olddir is normalized, while dir isn't [i]necessarily[/dir] normalized (it's left up to the function that calls ReboVec).

If the calling function is passing a non-normalized direction (i.e. self.velocity), that would probably do it. Dir might be so large that the traceline is starting very far away, behind another wall or inside a solid (i.e. the ceiling or a wall behind, or whatever is 16,000 units away). The fix given is appropriate, since ReboVel doesn't specify in the comment above it that dir should be normalized (other than the variable being named dir, and directions are typically understood to be normalized; not everyone knows that though). It might also be appropriate to move this line:

olddir = normalize(dir);

to above the if statement so olddir can be used instead of dir in the if statement's traceline too.


I'm just not sure why only the floor had the problem. O_o
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.
Wazat
 
Posts: 771
Joined: Fri Oct 15, 2004 9:50 pm
Location: Middle 'o the desert, USA

Postby Junrall » Mon Feb 22, 2010 2:59 am

Wazat wrote:...(it's left up to the function that calls ReboVec).

I went back and changed ReboVec back to the way it was and then passed a normalized dir to it (which I hadn't done before)... it worked like a charm! You are right... normalizing a direction is and was intended to be left up to the function that calls ReboVec.

Wazat wrote:The fix given is appropriate, since ReboVel doesn't specify in the comment above it that dir should be normalized (other than the variable being named dir, and directions are typically understood to be normalized; not everyone knows that though)..

Right again... I WAS one of those people who didn't know. I still don't know what normalize means or what it does... please enlighten me. :)

Wazat wrote:It might also be appropriate to move this line:

olddir = normalize(dir);

to above the if statement so olddir can be used instead of dir in the if statement's traceline too.


I'm just not sure why only the floor had the problem. O_o


Just moved olddir = normalize(dir); to above the if statement... works as you said it would.

Lol, so, with the above changes does this mean that ReboVec is at version 2 now! Just kidding!
Good God! You shot my leg off!
User avatar
Junrall
 
Posts: 191
Joined: Mon Sep 21, 2009 12:27 am
Location: North West Oregon, USA

Postby Dr. Shadowborg » Mon Feb 22, 2010 3:13 am

Junrall wrote:Just moved olddir = normalize(dir); to above the if statement... works as you said it would.

Lol, so, with the above changes does this mean that ReboVec is at version 2 now! Just kidding!


I can't remember the full details regarding that stuff (other than the fact that I'm pretty sure I had a reason for it), but I DO remember that I made that function to do double duty so that you could get just the trace_plane_normal of a surface (I believe this was useful for mines that attached to walls), or if justnorm was set to FALSE the proper ricochet angle. (for flak, and whatnot)

ReboVec hasn't actually changed at all since that was released, so I dunno. (it seems to work properly in Hellsmash, as you will see if you get a ring of power, turn it on and use the machine gun...)

Anyhow, glad you got it working!
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Postby Lardarse » Mon Feb 22, 2010 6:27 am

Normalizing a vector scales it so that its length is 1. This is a technique that's often used to obtain just the direction of the vector, without its length.
Roaming status: Testing and documentation
User avatar
Lardarse
 
Posts: 266
Joined: Sat Nov 05, 2005 1:58 pm
Location: Bristol, UK


Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest