Forum

Nukes!

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

Nukes!

Postby redrum » Sat Dec 01, 2007 3:11 pm

Guys, I'm attempting to make a nuke launcher.
Basically you use the rocket launcher, when you have 12 or more rockets you can launch a "nuke".
I created W_FireNuke based on W_FireRocket and I made T_NukeTouch based on T_MissileTouch. I just changed the amount of damage.
In testing I got this error on the server:

IFNOT 12708(???) branch 2
client.qc : Frag
client.qc : ClientObituary
combat.qc : Killed
combat.qc : T_Damage
combat.qc : T_RadiusDamage
weapons.qc : T_NukeTouch
<NO FUNCTION>
runaway loop error
SV_Error: Program error


any help???
Welcome to the Overlook Hotel: The-Overlook-Hotel.game-server.cc
User avatar
redrum
 
Posts: 410
Joined: Wed Mar 28, 2007 11:35 pm
Location: Long Island, New York

Postby redrum » Sat Dec 01, 2007 4:57 pm

Code: Select all
void() T_NukeTouch =
{
   if (self.voided) {
      return;
   }
   self.voided = 1;
     
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");

   WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
   WriteByte (MSG_MULTICAST, TE_EXPLOSION);
   WriteCoord (MSG_MULTICAST, self.origin_x);
   WriteCoord (MSG_MULTICAST, self.origin_y);
   WriteCoord (MSG_MULTICAST, self.origin_z);
   multicast (self.origin, MULTICAST_PHS);

   remove (self);
};



Code: Select all
void() W_FireNuke =

{
   if (deathmatch != 4)
      self.currentammo = self.ammo_rockets = self.ammo_rockets - 12;
   
   sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);

        traceline (self.origin, self.origin + v_forward*40, FALSE, self);
        if (trace_fraction == 1)
        {
        makevectors (self.angles);
        self.velocity = self.velocity - v_forward * 2000;                                                 
        }
       
   msg_entity = self;
   WriteByte (MSG_ONE, SVC_BIGKICK);
       
   newmis = spawn ();
   newmis.owner = self;
   newmis.movetype = MOVETYPE_FLYMISSILE;
   newmis.solid = SOLID_BBOX;
   
// set newmis speed

   makevectors (self.v_angle);
   newmis.velocity = aim(self, 1000);
   newmis.velocity = newmis.velocity * 40;                                       
   newmis.angles = vectoangles(newmis.velocity);

   newmis.touch = T_NukeTouch;
   newmis.voided = 0;
       
   
// set newmis duration
   
        newmis.nextthink = time + 0.01;                                     
        newmis.think = RocketSpeedChange;                                   
   newmis.classname = "rocket";

   setmodel (newmis, "progs/missile.mdl");
   setsize (newmis, '8 8 8', '8 8 8');                                       
   setorigin (newmis, self.origin + v_forward*8 + '0 0 16');
};


Here are my 2 functions, any suggestions?
Welcome to the Overlook Hotel: The-Overlook-Hotel.game-server.cc
User avatar
redrum
 
Posts: 410
Joined: Wed Mar 28, 2007 11:35 pm
Location: Long Island, New York

Postby Orion » Sat Dec 01, 2007 5:07 pm

Why that bunch of radius damages?!?!?
Use only one.
User avatar
Orion
 
Posts: 476
Joined: Fri Jan 12, 2007 6:32 pm
Location: Brazil

Postby redrum » Sat Dec 01, 2007 5:12 pm

It didn't work right, only one entity would explode from a nuke?
Welcome to the Overlook Hotel: The-Overlook-Hotel.game-server.cc
User avatar
redrum
 
Posts: 410
Joined: Wed Mar 28, 2007 11:35 pm
Location: Long Island, New York

Postby daemon » Sat Dec 01, 2007 5:21 pm

Yea, my guess is that is has something to do with all those T_RadiusDamage()s being called at the same time. T_RadiusDamage has a findradius inside of it, which is a kind of loop, and running that many at the same time would probably cause that kind of error. But that's just my guess.
-daemon [ daemonforge.org ]
User avatar
daemon
 
Posts: 63
Joined: Wed Nov 07, 2007 11:10 pm

Postby redrum » Sat Dec 01, 2007 11:46 pm

I get this error on the server, it repeats itself numerous times then it will stop. Then it starts again. When this is happening and I fire the nuke is when it crashes.

WARNING: ED_Alloc: no free edicts

What does this mean???
Welcome to the Overlook Hotel: The-Overlook-Hotel.game-server.cc
User avatar
redrum
 
Posts: 410
Joined: Wed Mar 28, 2007 11:35 pm
Location: Long Island, New York

Postby Sajt » Sun Dec 02, 2007 12:54 am

Set the fourth argument to T_RadiusDamage to 'self' instead of 'world'?
F. A. Špork, an enlightened nobleman and a great patron of art, had a stately Baroque spa complex built on the banks of the River Labe.
Sajt
 
Posts: 1215
Joined: Sat Oct 16, 2004 3:39 am

Postby redrum » Sun Dec 02, 2007 1:28 am

Sajt, can you explain that whole line of code for me so I can understand the whole thing please? Thanks.
Welcome to the Overlook Hotel: The-Overlook-Hotel.game-server.cc
User avatar
redrum
 
Posts: 410
Joined: Wed Mar 28, 2007 11:35 pm
Location: Long Island, New York

Postby Electro » Mon Dec 03, 2007 6:25 am

Code: Select all
T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");
        T_RadiusDamage (self, self.owner, 800, world, "rocket");


is the same as

Code: Select all
T_RadiusDamage (self, self.owner, 8800, world, "rocket"); // 8800 = 800 * 11



I think something you'd rather want, is an entity that gets spawned that does thinks every 0.02 seconds or something that does a T_RingDamage or something... and into that you'd put something like a min/max range for it to take effect, then each time move the ring out more and weaken the damage etc.
Anyway, that single line of code does the same as using a slab of T_RadiusDamage calls.
Benjamin Darling
http://www.bendarling.net/

Reflex - In development competitive arena fps combining modern tech with the speed, precision and freedom of 90's shooters.
http://www.reflexfps.net/
Electro
 
Posts: 312
Joined: Wed Dec 29, 2004 11:25 pm
Location: Brisbane, Australia

Postby Sajt » Mon Dec 03, 2007 8:19 am

Nevermind what I said, it probably won't change anything.

The fourth parameter to T_RadiusDamage is 'ignore', which you generally set to the thing that is exploding, but it only really matters if said thing has takedamage and a few other things set (IIRC).
F. A. Špork, an enlightened nobleman and a great patron of art, had a stately Baroque spa complex built on the banks of the River Labe.
Sajt
 
Posts: 1215
Joined: Sat Oct 16, 2004 3:39 am

Postby r00k » Mon Dec 03, 2007 8:56 am

I think your original crash
IFNOT 12708(???) branch 2
client.qc : Frag


was based on the bug in your frag() code ?
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Postby FrikaC » Mon Dec 03, 2007 2:45 pm

Electro wrote:is the same as

Code: Select all
T_RadiusDamage (self, self.owner, 8800, world, "rocket"); // 8800 = 800 * 11


I think something you'd rather want, is an entity that gets spawned that does thinks every 0.02 seconds or something that does a T_RingDamage or something... and into that you'd put something like a min/max range for it to take effect, then each time move the ring out more and weaken the damage etc.
Anyway, that single line of code does the same as using a slab of T_RadiusDamage calls.


Not quite. The radius in T_RadiusDamage is based on the damage amount, so repeat calls will therefore keep the radius low and accumulate a whole bunch of damage. A better option to have the same behavior, if indeed that's what is desired, would be to create a new version of T_RadiusDamage that takes damage and radius parameters.
FrikaC
Site Admin
 
Posts: 1026
Joined: Fri Oct 08, 2004 11:19 pm

Postby Orion » Mon Dec 03, 2007 2:53 pm

Yeah, that's right.
T_RadiusDamage() already does damage to various entities at the same time, and 8800 is, more or less, an infinite radius in Quake.

Try this instead, it will have 800 radius (or whatever you want) and 8000 damage (or whatever too).

Copy and paste this code at combat.qc just after T_RadiusDamage():

Code: Select all
void(entity inflictor, entity attacker, float damage, float radius, entity ignore, string dtype) NewRadiusDamage =
{
   local   float    points;
   local   entity   head;
   local   vector   org, v;

   head = findradius(inflictor.origin, radius);
   
   while (head)
   {
      if (head != ignore)
      {
         if (head.takedamage)
         {
            org = head.origin + (head.mins + head.maxs)*0.5;
            points = 0.5*vlen (inflictor.origin - org);
            if (points < 0)
               points = 0;
            points = damage - points;
            if (head == attacker)
               points = points * 0.5;
            if (points > 0)
            {
               if (CanDamage (head, inflictor))
               {   
                  head.deathtype = dtype;
                  // shambler takes half damage from all explosions
                  if (head.classname == "monster_shambler")                  
                     T_Damage (head, inflictor, attacker, points*0.5);
                  else
                     T_Damage (head, inflictor, attacker, points);
               }
            }
         }
      }
      head = head.chain;
   }
};



Then, at your nuke touch function use this instead:

Code: Select all
NewRadiusDamage (self, self.owner, 8000, 800, world, "rocket");


That should work.
User avatar
Orion
 
Posts: 476
Joined: Fri Jan 12, 2007 6:32 pm
Location: Brazil

Postby redrum » Mon Dec 03, 2007 3:31 pm

WOW!!!
You guys are blowing my mind!
Thanks for all the feedback :)

Can someone explain the T_RadiusDamage code to me with all the arguments and what they do?
Welcome to the Overlook Hotel: The-Overlook-Hotel.game-server.cc
User avatar
redrum
 
Posts: 410
Joined: Wed Mar 28, 2007 11:35 pm
Location: Long Island, New York

Postby daemon » Tue Dec 04, 2007 5:37 am

Code: Select all
void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
{
   local   float    points;
   local   entity   head;
   local   vector   org;


   head = findradius(inflictor.origin, damage+40); //makes head equal to the first entity in a radius based upon damage + 40 quake units around the origin of the thing inflicting the damage, and temporarily assigns a .chain on all entities within that radius. .chain being the next entity inside the radius.
   
   while (head) // loop inside the following brackets until head equals world. (head will eventually equal world because the last entity inside the radius will have a .chain pointing to world)

   {
      if (head != ignore) // if head is not the entity set to be ignored, then do the following code inside the brackets.

      {
         if (head.takedamage) // if head is flagged to be able to take damage do the following code.

         {
            org = head.origin + (head.mins + head.maxs)*0.5; // sets org to a position at or slightly above head's origin depending on the head's bbox paramaters.

            points = 0.5*vlen (inflictor.origin - org); // sets points to a value equal to half of the distance from the inflictor's origin to org at impact.

            if (points < 0)
               points = 0; // if points are negative, set to 0.

            points = damage - points; // since points previoulsy represented distance from impact, subtract points from damage to get the minimized damage.

            if (head == attacker)
               points = points * 0.5; // if the attacker ends up damaging themself, half the damage to them

            if (points > 0) // if there are any points left after subtracting from damage, then do the code in the following brackets.

            {
               if (CanDamage (head, inflictor)) // if there are no walls in between the inflictor and the head...

               {   // shambler takes half damage from all explosions
                  if (head.classname == "monster_shambler")                  
                     T_Damage (head, inflictor, attacker, points*0.5); // shamblers take half radius damage

                  else
                     T_Damage (head, inflictor, attacker, points); // everyone else takes full damage

               }
            }
         }
      }
      head = head.chain; // apply damage to the next entity in the radius.

   }
};
Last edited by daemon on Sat Dec 08, 2007 7:44 pm, edited 1 time in total.
-daemon [ daemonforge.org ]
User avatar
daemon
 
Posts: 63
Joined: Wed Nov 07, 2007 11:10 pm

Next

Return to QuakeC Programming

Who is online

Users browsing this forum: Bing [Bot] and 1 guest