Inside3D!
     

Death messages

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



Joined: 28 Mar 2007
Posts: 367
Location: Long Island, New York

PostPosted: Mon Dec 10, 2007 3:08 am    Post subject: Death messages Reply with quote

Guys, got a problem that I need help with.
I changed the lightning gun to a lava launcher.
You can catch on fire from the lavaball and then die well after the shots have been fired.
If I am using a different weapon when the target dies, the death message displays for the current weapon and not the lava launcher Sad
Here is my death message code:
Code:
            else if (rnum == IT_LIGHTNING)
            {
               deathstring = " gets torched ";
               deathstring2 = "'s lava launcher!\n";
            }

So, I tried to do this instead:
Code:
            else if (targ.deathtype == "lava")
                  {
                     bprint (PRINT_MEDIUM, attacker.netname);
                     bprint (PRINT_MEDIUM, " torches ");
                     bprint (PRINT_MEDIUM, targ.netname);
                     bprint (PRINT_MEDIUM, " with the lava launcher!\n");
                     return;
                  }

Problem is that I can't get the compiler to recognize "lava".
How can I associate "lava" so that it works correctly?
Here is the rest of the code:
Code:
void(vector org) Flame_Burn =
{
        flame = spawn ();
        flame.owner = self;
        flame.classname = "lava";
        flame.movetype = MOVETYPE_FLYMISSILE;
        flame.solid = SOLID_NOT;
        flame.origin = org;
        flame.velocity = '0 0 75';
        setmodel (flame, "progs/flame2.mdl");
        setsize (flame, '0 0 0', '0 0 0');
        flame.nextthink = time + .01;
        flame.think = s_explode1;
};

void() Flame_Think =
{
        local float r;

        if (self.enemy.waterlevel == 3 || self.enemy.health <= 0)
        {
                BecomeExplosion ();
                return;
        }
        self.origin = self.enemy.origin + '0 0 25';
        if (r < 0.5)                                                       
                  T_Damage (self.enemy, self, self.owner, 1);               
        self.nextthink = time + 0.01;
        self.classname = "lava";                         
};

void(vector org, entity e) Flame_Onfire =
{
        flame = spawn ();
        flame.owner = self.owner;
        flame.enemy = e;
        flame.classname = "lava";
        flame.movetype = MOVETYPE_NONE;
        flame.solid = SOLID_NOT;
        flame.origin = org;
        flame.velocity = '0 0 0';
        setmodel (flame, "progs/flame2.mdl");             
        setsize (flame, '0 0 -15', '0 0 0');
        flame.nextthink = time + 0.01;
        flame.think = Flame_Think;
        flame.effects = flame.effects | EF_DIMLIGHT;
};

void() Flame_Touch =
{
        local float r;
        local vector org;

        if (other.takedamage)
        {
                org = other.origin;
                org_z = self.origin_z;
                Flame_Burn (org);
                T_Damage (other, self, self.owner, 8);                                                 
                remove (self);
                r = random ();
                if (r < 0.2)                                                                             
                {
                        if ((other.classname == "player"))
                        {
                                centerprint (other,"You are on fire!\n\nFind WATER fast");
                                stuffcmd (other,"bf\n");
                        }
                        Flame_Onfire (org, other);
                }
        }
};

void() W_FireLightning =                                                                         
{

   if (self.ammo_cells < 1)
   {
      self.weapon = W_BestWeapon ();
      W_SetCurrentAmmo ();
      return;
   }
   
   if (deathmatch != 4)
      self.currentammo = self.ammo_cells = self.ammo_cells - 1;
   
   sound (self, CHAN_WEAPON, "hknight/hit.wav", .8, ATTN_NORM);

        makevectors (self.angles);
        self.velocity = self.velocity - v_forward * 50;                                           
         
        if (self.health >= 1 && self.health <= 25)
        {
        makevectors (self.angles);
        self.velocity = self.velocity - v_forward * 100;                                               
        } 

   msg_entity = self;

   flame = spawn ();
   flame.voided=0;
   flame.owner = self;
   flame.movetype = MOVETYPE_BOUNCE;
   flame.solid = SOLID_BBOX;
   flame.classname = "lava";   

   makevectors (self.v_angle);

   if (self.v_angle_x)
      flame.velocity = v_forward*500 + v_up * 225 + crandom()*v_right*25 + crandom()*v_up*25;
   else
   {
      flame.velocity = aim(self, 10000);
      flame.velocity = flame.velocity * 400;
      flame.velocity_z = 100;
   }

   flame.avelocity = '300 300 300';
   flame.angles = vectoangles(newmis.velocity);
   
   flame.touch = Flame_Touch;
   flame.nextthink = time + 1.0;
   flame.think = s_explode1;
        setmodel (flame, "progs/lavaball.mdl");
   setsize (flame, '0 0 0', '0 0 0');             
   setorigin (flame, self.origin);
};

_________________
Welcome to the Overlook Hotel 69.113.123.178:27500
Back to top
View user's profile Send private message Send e-mail
Dr. Shadowborg
Inside3D Staff


Joined: 16 Oct 2004
Posts: 726

PostPosted: Mon Dec 10, 2007 5:05 pm    Post subject: Reply with quote

Open combat.qc, then go into the T_Damage function.

Look for where the code looks like this:
Code:

if(targ.health <= 0)
{
  Killed(targ, attacker);
  return;
}


Put inside the same if check just before Killed() is called so that the above looks like this:

Code:

if(targ.health <= 0)
{
  if(inflictor.classname == "lava")
   targ.deathtype = "lava";

  Killed(targ, attacker);
  return;
}


That should do the trick.
_________________
"Roboto suggests Plasma Bazooka."
Back to top
View user's profile Send private message
Orion



Joined: 12 Jan 2007
Posts: 414
Location: Brazil

PostPosted: Mon Dec 10, 2007 11:30 pm    Post subject: Reply with quote

An easier way to do that is:

Go to Flame_Touch(), and before T_Damage(), add:

Code:

other.deathtype = "lava";


And in Flame_Think(), before T_Damage() too, add:

Code:

self.enemy.deathtype = "lava";


I did that with the code that contained my bots.
Don't forget to put brackets between (if (r < 0.5)) and the 2 lines of code.
You can use an if() without brackets only if there's only 1 line of code. otherwise you should put brackets between the lines.

BUT, if you use more than 1 if(), you don't need to use brackets. Here's an example:

Code:

if()
if()
if()
{
    code
    code
    code
}


This won't have any problems, if you use:

Code:

if()
{
   if()
   {
       if()
       {
           code
           code
           code
       }
   }
}


It will work exactly the same, but will have an increased size of code.

But the better of bests ways is using AND (&&) and/or OR (||) inside an if().

Example:

Code:

if(something && something && something)
{
   code
   code
   code
}


This might work exactly the same as the 2 codes above.

Now I'll show you a better example. It's a code that searches for damageable entities, and I'll show the if() differences.

Code:

local entity ent;
ent = findradius(self.origin, 1000);
while (ent)
{
   if (ent != self)
   if (ent.health > 0)
   if (ent.takedamage == DAMAGE_AIM)
   if (visible(ent))
      self.enemy = ent;
   ent = ent.chain;
}


Notice that if you don't use brackets between a while(), it will cause problems too.

Here's another way:

Code:

local entity ent;
ent = findradius(self.origin, 1000);
while (ent)
{
   if (ent != self && ent.takedamage == DAMAGE_AIM && ent.health > 0 && visible(ent))
      self.enemy = ent;
   ent = ent.chain;
}


This is a shorter way, better use and (&&) and/or or (||) instead of creating many ifs.

This gone a bit off-topic, but it's ok.
_________________
There's no signature here. Stop looking for one.
Back to top
View user's profile Send private message
redrum



Joined: 28 Mar 2007
Posts: 367
Location: Long Island, New York

PostPosted: Tue Dec 11, 2007 12:11 am    Post subject: Reply with quote

Awesome! Thanks guys! Very Happy
_________________
Welcome to the Overlook Hotel 69.113.123.178:27500
Back to top
View user's profile Send private message Send e-mail
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Tue Dec 11, 2007 2:22 am    Post subject: Reply with quote

if (blah)
if (blah)
if (blah)
blah();

results in more efficient code than

if (blah && blah && blah)
blah();


Its a pain to read, but multiple conditions is more efficient. This is especially important when you're itterating over a lot of entities.
QuakeC does not typically early-out like C does. The entire statement is evallulated (including function calls!) before the result is compared.
Both FrikQCC and FTEQCC can do it, but doing so is not always advised, and can break some code (admittedly such code is arguably poorly written).

in the above example, the line:

if (ent != self && ent.takedamage == DAMAGE_AIM && ent.health > 0 && visible(ent))

is exactly identical to (except that it would break else statements):
temp = (ent != self);
temp2 = ent.takedamage;
temp2 = (temp2 == DAMAGE_AIM);
temp = (temp && temp2);
temp2 = ent.health;
temp2 = temp2 > 0;
temp = temp && temp2;
arg0 = ent;
temp2 = visible(arg0);
temp = temp && temp2;
if (temp)
{
...
}
Yes, the entire thing is executed for every ent within those 1000 units.
Note that earlier qc compilers will use new temps for each line, instead of reusing them.

The multiple-if form goes:

temp = (ent != self);
if (temp)
{
temp = ent.takedamage;
temp = (temp == DAMAGE_AIM);
if (temp)
{
temp = ent.health;
temp = temp > 0;
if (temp)
{
arg0 = ent;
temp = visible(arg0);
if (temp)
{
...
}
}
}
}

In both examples, each line (baring braces) is a single qc instruction.
Due to the comparisons instead of logic operators, the second form will run more efficiently. The function call can be particuarly nasty, depending on the length of the function - ranging from mearly inefficient to downright nasty.
Consider that visible is a qc function containing 18 instructions, one of them a call to a builtin which recurses down the bsp tree, using floating point maths, followed by a quick run through all the entities in the block and a recursion down any bsp trees within the region, and you'll realise how important that seperating your conditions into seperate if statements can be in quakec.

But yes, the logical 'and' (&&) and 'or' (||) operators are more readable.

I suspect I might be overcomplicating the issue, and going slightly off topic.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
redrum



Joined: 28 Mar 2007
Posts: 367
Location: Long Island, New York

PostPosted: Tue Dec 11, 2007 12:30 pm    Post subject: Reply with quote

Didn't grasp all of that but I get the jist of it!
I have a lot to learn.
Where/how did you guys acquire all of this knowledge?
_________________
Welcome to the Overlook Hotel 69.113.123.178:27500
Back to top
View user's profile Send private message Send e-mail
Urre



Joined: 05 Nov 2004
Posts: 1073
Location: Sweden

PostPosted: Tue Dec 11, 2007 3:31 pm    Post subject: Reply with quote

No lives?
_________________
Look out for Twigboy
Back to top
View user's profile Send private message Visit poster's website
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Tue Dec 11, 2007 5:07 pm    Post subject: Reply with quote

redrum wrote:
Where/how did you guys acquire all of this knowledge?


As Urre said. I need to get out more.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
Dr. Shadowborg
Inside3D Staff


Joined: 16 Oct 2004
Posts: 726

PostPosted: Tue Dec 11, 2007 6:49 pm    Post subject: Reply with quote

Off and on, endless amounts of tinkering, abandoning, restarting, recoding mods.

(What Urre said.)

The more you work with quakec the better you will become over time.
_________________
"Roboto suggests Plasma Bazooka."
Back to top
View user's profile Send private message
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