Hi guys. I'm trying to understand if there's a simple way to add in qc a way to make monsters search ALWAYS player (not only when they "see" him). I've look at this tutorial but here explains how to make monsters roaming along the map. I'm searching for something even (I hope) simpler: I'd only like that a fiend, an ogre or a dog could always know where's player and searching him.
Thanks in advance
Monsters searching player
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
-
- Posts: 2126
- Joined: Sat Nov 25, 2006 1:49 pm
Open ai.qc and find this:
Basically, it's a matter of removing the undesired checking steps in the function above (doesn't matter if the monster can see the player or not ? Fine, just skip these steps then). The code is self explanatory enough, I believe you can grasp the idea by yourself. Have fun.
Code: Select all
float() FindTarget =
{
local entity client;
local float r;
// if the first spawnflag bit is set, the monster will only wake up on
// really seeing the player, not another monster getting angry
// spawnflags & 3 is a big hack, because zombie crucified used the first
// spawn flag prior to the ambush flag, and I forgot about it, so the second
// spawn flag works as well
if (sight_entity_time >= time - 0.1 && !(self.spawnflags & 3) )
{
client = sight_entity;
if (client.enemy == self.enemy)
return;
}
else
{
client = checkclient ();
if (!client)
return FALSE; // current check entity isn't in PVS
}
if (client == self.enemy)
return FALSE;
if (client.flags & FL_NOTARGET)
return FALSE;
if (client.items & IT_INVISIBILITY)
return FALSE;
r = range (client);
if (r == RANGE_FAR)
return FALSE;
if (!visible (client))
return FALSE;
if (r == RANGE_NEAR)
{
if (client.show_hostile < time && !infront (client))
return FALSE;
}
else if (r == RANGE_MID)
{
if ( /* client.show_hostile < time || */ !infront (client))
return FALSE;
}
//
// got one
//
self.enemy = client;
if (self.enemy.classname != "player")
{
self.enemy = self.enemy.enemy;
if (self.enemy.classname != "player")
{
self.enemy = world;
return FALSE;
}
}
FoundTarget ();
return TRUE;
};
Basically, it's a matter of removing the undesired checking steps in the function above (doesn't matter if the monster can see the player or not ? Fine, just skip these steps then). The code is self explanatory enough, I believe you can grasp the idea by yourself. Have fun.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC (LordHavoc)
So you mean if you remove RANGE_, the monsters will virtually see the entire map and know exactly where you are? That's a bit scary!
This should be the same as changing the RANGE_ values to something really large. Or to add additional checks for dogs (for example), such as change
to
Although I'm pretty sure this holds a key, too:
Remove this and the PVS check will not be performed. This could be applied to some survival mod, where monsters come pouring in from every direction.
This should be the same as changing the RANGE_ values to something really large. Or to add additional checks for dogs (for example), such as change
Code: Select all
if (r == RANGE_FAR)
Code: Select all
if (r == 90000)
Code: Select all
client = checkclient ();
if (!client)
return FALSE; // current check entity isn't in PVS
QuakeWiki
getButterfly - WordPress Support Services
Roo Holidays
Fear not the dark, but what the dark hides.
getButterfly - WordPress Support Services
Roo Holidays
Fear not the dark, but what the dark hides.
-
- Posts: 2126
- Joined: Sat Nov 25, 2006 1:49 pm
Not exactly. Let's read the code, step by step:
Here, we check if there's a hint by other entity about an enemy. Basically, somebody is pointing, during some time (sight_entity_time) a potential enemy (sight_entity). If that's the case, the monster will accept that, otherwise a call to checkclient() will return a client (IIRC, every call cycles thru all clients, so monsters in coop won't all get mad at the same player). Note that checkclient() already culls out non-visible clients, so if you want to always have a valid target here, you'll need to write your own code to do so. Also, keep in mind that the returned entity in both cases MAY NOT BE A PLAYER, but instead, a monster mad at a player. We'll see this at the end of the function.
If the returned entity is the current enemy, then there's nothing to do, we can just return and keep chasing/attacking it.
These are the tests for the "notarget" cheat and the Ring of Shadows power-up. You can disable any of this just removing this code.
Here is the test to check if the monster is too far to notice the player. If the monster must be aware of the player regardless of their positions in the map, remove entirely this.
This code tests if the entity that we are testing is a player or actually a monster. In the later case, we change the reference to the actual player entity.
Code: Select all
if (sight_entity_time >= time - 0.1 && !(self.spawnflags & 3) )
{
client = sight_entity;
if (client.enemy == self.enemy)
return;
}
else
{
client = checkclient ();
if (!client)
return FALSE; // current check entity isn't in PVS
}
Code: Select all
if (client == self.enemy)
return FALSE;
Code: Select all
if (client.flags & FL_NOTARGET)
return FALSE;
if (client.items & IT_INVISIBILITY)
return FALSE;
Code: Select all
r = range (client);
if (r == RANGE_FAR)
return FALSE;
if (!visible (client))
return FALSE;
if (r == RANGE_NEAR)
{
if (client.show_hostile < time && !infront (client))
return FALSE;
}
else if (r == RANGE_MID)
{
if ( /* client.show_hostile < time || */ !infront (client))
return FALSE;
}
Code: Select all
//
// got one
//
self.enemy = client;
if (self.enemy.classname != "player")
{
self.enemy = self.enemy.enemy;
if (self.enemy.classname != "player")
{
self.enemy = world;
return FALSE;
}
}
Code: Select all
FoundTarget ();
return TRUE;
};
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC (LordHavoc)
-
- Posts: 1395
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Thank you guys for all your replies. I tried to remove all lines frag.machine told but, with no luck. Monsters seem stupids, even if I go closer to their noses, they stand still.
Thanks a lot
EDIT: I got worked. I removed some line and edited another one, like this:
now monsters seem to be alerted all the time and searching for the player. Thanks frag.machine!
That's exactly what I'd like to do! There was anyone who did an experiment like this to use the code? Because I've really no idea how to do it.Note that checkclient() already culls out non-visible clients, so if you want to always have a valid target here, you'll need to write your own code to do so
Thanks a lot
EDIT: I got worked. I removed some line and edited another one, like this:
Code: Select all
float() FindTarget =
{
local entity client;
local float r;
// if the first spawnflag bit is set, the monster will only wake up on
// really seeing the player, not another monster getting angry
// spawnflags & 3 is a big hack, because zombie crucified used the first
// spawn flag prior to the ambush flag, and I forgot about it, so the second
// spawn flag works as well
if (sight_entity_time >= time - 0.1 && !(self.spawnflags & 3) )
{
client = sight_entity;
if (client.enemy == self.enemy)
return;
}
else
{
client = checkclient ();
if (!client)
return FALSE; // current check entity isn't in PVS
}
if (client == self.enemy)
return FALSE;
if (client.flags & FL_NOTARGET)
return FALSE;
if (client.items & IT_INVISIBILITY)
return FALSE;
//
// got one
//
self.enemy = client;
if (self.enemy.classname == "player")
FoundTarget ();
return TRUE;
};
-
- Posts: 68
- Joined: Mon Oct 04, 2010 9:08 pm
- Location: Lincoln, California