Universal "Action" Command
Moderator: InsideQC Admins
16 posts
• Page 1 of 2 • 1, 2
Universal "Action" Command
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
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.
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
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
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
-

Dr. Shadowborg - InsideQC Staff
- Posts: 1110
- Joined: Sat Oct 16, 2004 3:34 pm
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:
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
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.
-

Dr. Shadowborg - InsideQC Staff
- Posts: 1110
- Joined: Sat Oct 16, 2004 3:34 pm
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)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
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
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.
-

Dr. Shadowborg - InsideQC Staff
- Posts: 1110
- Joined: Sat Oct 16, 2004 3:34 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
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.
The bottom part of SUB_UseTargets might give you a hint.
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
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...
.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
16 posts
• Page 1 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 1 guest
