Forum

Universal "Action" Command

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

Universal "Action" Command

Postby Ghost_Fang » Tue Feb 09, 2010 3:47 am

is it possible to add a function (bound to an impulse command) that will give a simple command action = 1 in a certain distance from the player view? Something i can implement on anything? such as a door, or weapon pickup, or a button? Like i said the action the player gives off will be universal, just everything interactive i will change accordingly.
Ghost_Fang
 
Posts: 336
Joined: Thu Nov 12, 2009 4:37 am

Postby Spike » Tue Feb 09, 2010 3:58 am

yes. a traceline in your impulse handler that traces a fixed distance forward to find interactable entities is easy, so long as your entities can be hit by tracelines.
Weapon pickups probably can't be found that way (they'd need to be solid!). You'd need to do a findradius for those, presumably, which isn't too awkward.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby Dr. Shadowborg » Tue Feb 09, 2010 4:11 am

Some good starting material to look at for this:

http://forums.inside3d.com/viewtopic.php?t=1831
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Postby Ghost_Fang » Tue Feb 09, 2010 4:26 am

would it work if i derived it from the axe weapon, and have the traceline do action() instead of attack or something? (minus the models and anims etc)
Ghost_Fang
 
Posts: 336
Joined: Thu Nov 12, 2009 4:37 am

Postby Dr. Shadowborg » Tue Feb 09, 2010 5:06 am

It should, that's what I did for the interaction in that NPC code. Note however that you may have to do different things to get the same result on different objects. e.g. doors and buttons vs. NPCs
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Postby Ghost_Fang » Tue Feb 09, 2010 5:55 am

well my idea is to have the action send out a generic "action = 1" command, and each interactive entity will have a simple:
if (self.action == 1)
{
do all the stuff i want etc.
}

But i really have no idea how to SEND a command to another entity within a given range. And editing the axe didnt work.
Here is my work of fail:

Code: Select all
/*
======
Action
======
*/

void(entity targ) Action =
{
targ.action = 1;
};

void() ActionCommand =
{
   local   vector   source;
   local   vector   org;

   makevectors (self.v_angle);
   source = self.origin + '0 0 16';
   traceline (source, source + v_forward*64, FALSE, self);
   if (trace_fraction == 1.0)
      return;
   
   org = trace_endpos - v_forward*4;

   if (trace_ent.takedamage)
   {
      trace_ent.axhitme = 1;
      Action (trace_ent);
   }
};
Ghost_Fang
 
Posts: 336
Joined: Thu Nov 12, 2009 4:37 am

Postby r00k » Tue Feb 09, 2010 6:04 am

org has no purpose and axehitme just makes the player yelp.
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Postby Dr. Shadowborg » Tue Feb 09, 2010 4:19 pm

Ghost_Fang wrote:But i really have no idea how to SEND a command to another entity within a given range. And editing the axe didnt work.
Here is my work of fail:

Code: Select all
/*
======
Action
======
*/

void(entity targ) Action =
{
targ.action = 1;
};

void() ActionCommand =
{
   local   vector   source;
   local   vector   org;

   makevectors (self.v_angle);
   source = self.origin + '0 0 16';
   traceline (source, source + v_forward*64, FALSE, self);
   if (trace_fraction == 1.0)
      return;
   
   org = trace_endpos - v_forward*4;

   if (trace_ent.takedamage)
   {
      trace_ent.axhitme = 1;
      Action (trace_ent);
   }
};


This won't work because most doors and buttons aren't damagable.

Change it so that it's like this or something:

Code: Select all
/*
======
Action
======
*/

void(entity targ) Action =
{
targ.action = 1;
};

void() ActionCommand =
{
   local   vector   source;

   makevectors (self.v_angle);
   source = self.origin + '0 0 16';
   traceline (source, source + v_forward*64, FALSE, self);
   if (trace_fraction == 1.0)
      return;
   
                 if (trace_ent != world)
                   Action (trace_ent);
};


That should work I think.
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Postby frag.machine » Wed Feb 10, 2010 2:30 am

As is, this code can call Action() even for dead entities. Dunno if it's desirable, if not a simple "&& (trace_ent.health > 0)" fixes the issue.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2090
Joined: Sat Nov 25, 2006 1:49 pm

Postby Ghost_Fang » Wed Feb 10, 2010 3:37 am

I understand how you said how somethings arent damageable, but i tested on a enemy, i made the enemy code, if (self.action == 1) self.health == 0 and it didnt do anything. So im doing something else wrong i think ... :\
Ghost_Fang
 
Posts: 336
Joined: Thu Nov 12, 2009 4:37 am

Postby ceriux » Wed Feb 10, 2010 3:52 am

in the entite code did you set self.action = 0; ?
User avatar
ceriux
 
Posts: 2223
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Postby Dr. Shadowborg » Wed Feb 10, 2010 5:21 am

Ghost_Fang wrote:I understand how you said how somethings arent damageable, but i tested on a enemy, i made the enemy code, if (self.action == 1) self.health == 0 and it didnt do anything. So im doing something else wrong i think ... :\


That's because enemies (monsters) don't function normally enough for that to work. (unless you're calling that every stand, walk, attack, etc. frame) Also, if that's the case, and you were expecting it to die, you should know that if you want it to die you need to use T_Damage to do all that. (they don't check to see if they are supposed to die otherwise...)

Someday I am going to have to make a tutorial that will help to alleviate this issue so that you can add an all-in-one monster_subthink where you can do stuff like this... (I've already done partial monster_subthink stuff for Hellsmash and RemakeQuake's Enforcer Overwatch ability. Unless they've taken that stuff out after I'd left...)

Needless to say the proper procedure for getting a door or button to do the same thing is going to be different.


frag.machine wrote:As is, this code can call Action() even for dead entities. Dunno if it's desirable, if not a simple "&& (trace_ent.health > 0)" fixes the issue.


That defeats the whole purpose of using this for doors and buttons that aren't damagable normally.

Also, most (assuming that he's following standard quake style) fully dead entities won't be touchable with this because most dead entities are by this point SOLID_NOT. Even if this wasn't the case though, the way Ghost_Fang is implimenting this it would only work if he added code for interaction.
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Postby Ghost_Fang » Wed Feb 10, 2010 5:26 pm

So how would i "send" commands through a trace? All it would be for is for helping a player up from being incapped, weapon pickup, and MAYBE opening doors if its possible.
Ghost_Fang
 
Posts: 336
Joined: Thu Nov 12, 2009 4:37 am

Postby Spike » Wed Feb 10, 2010 5:59 pm

You can "send" commands the same way pain or death is "sent", or the same way as regular triggers.
The bottom part of SUB_UseTargets might give you a hint.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby Sajt » Wed Feb 10, 2010 6:01 pm

The proper thing is to create a new function pointer called "th_activate" or something.

.void() th_activate;

And set it for every entity that is supposed to be interacted with.

Then the player has an impulse command which traces forward, and if it hits something:

local entity oldself;
...
if (trace_ent.th_activate)
{
oldself = self;
other = self;
self = trace_ent;
self.th_activate();
self = oldself;
}

Note the setting of 'other' which lets the th_activate function do something differently based on who activates it. (If you need that.) You could also use 'activator', or even a function argument to th_activate. But using other will make a certain something easier to do for lazy programming helpers like me... (see later)

Note: Picking up weapons with this will be a little more difficult because weapons are SOLID_TRIGGER. Traces won't hit SOLID_TRIGGER items. If they were SOLID_CORPSE (a common extension not in vanilla Quake) it would be easier. If you need to support all engines though, say so and I'll tell you how to "hack" it for SOLID_TRIGGER items...

So if you want to make a door use this, simply go to the func_door function in doors.qc, and replace "self.touch = door_touch" with "self.th_activate = door_touch". That SHOULD do it. Since we set "other" when calling th_activate, everything should already be taken care of.

I haven't tested any of this though, I may have forgotten something...
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

Next

Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest