Announcement

Collapse
No announcement yet.

Playing with monster hunting player

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Playing with monster hunting player

    I'm basically tinkering with Find Target. The objectives are to do the following; on finding an enemy (the player) the monster does some checks before being able to pursue it.
    1. Is it behind a wall (does the monster have line of sight) if no, then go after it, if yes, then check 2.
    2. Is the player moving (therefore making noise) if yes, and after then checking distance (prob if MID or NEAR, not decided yet) then pursue it, if no then check 3.
    3. Is the player's torch on (therefore giving away position, potentially) if yes, and after checking distance, then pursue, if no, then continue patrolling.

    So far, and this, although possibly not complicated for some, is stuff I've not attempted before, I've done the following.
    1. I've taken out the distance check, so now the monster knows where the player is at all times and pursues them, and
    2. Started to build in a "is the player behind a wall, and therefore not visible to me" check. How I've attempted this is by trying to send a traceline from the monster to it's enemy (the player) and then, as a starting point, if it hits a wall, then telling the monster to ignore it's enemy. Which works, except that it doesn't, it ignores the player when it's stood right in front of it!

    Anyway, my 'changes to find target:
    float() FindTarget =
    {
    local entity client;
    local float r;

    // earthQuake AI changes ------------------------

    local vector test1, test2;
    local entity option;

    // ---------------------------------------------

    // 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")

    // earthQuake AI changes ---------------------------------

    option = self.enemy;

    // see if any walls are in the way
    test1 = self.origin + self.view_ofs;
    test2 = option.origin + option.view_ofs;

    traceline (test1, test2, FALSE, self);

    if (trace_fraction != 1.0)
    return FALSE;
    else
    FoundTarget ();
    // --------------------------------------------------------------
    return TRUE;
    };


    I've obviously am not trying to achieve everything (as listed above), just the allowing player to hide behind a wall bit. I'm guessing, it's either a simple error, or I'm going about it a silly way.
    Thanks for reading

  • #2
    Hello ajay,

    I want to *try* to help. My skills are not good, but maybe it helps to find the right direction...

    It is quite hard to read your code without the tabs.
    Please use "code" instead of "quote" or pure text for qc codes.

    You left out the brackets after your line:
    if (self.enemy.classname == "player")
    That means, that only the next code-line is affected by this check.
    All the further next lines will be used independent to your "if" check.

    The reason why the code doesnt work if the player and monster are standing directly to each other *might* be the usage of reversed trace_fraction check.

    This is what I would change (keeping your condition 1.)
    Please also read my comments:

    Code:
    float () FindTarget = 
    { 
    local entity client; 
    local float r; 
    
    // EarthQuake AI changes ------------------------ 
    
    local vector test1, test2; 
    local entity option; 
    
    // --------------------------------------------- 
    
    // 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") 
    	{
    // EarthQuake AI changes --------------------------------- 
    
    		option = self.enemy; 
    
    		// See if any walls are in the way 
    		test1 = self.origin + self.view_ofs; 
    		test2 = option.origin + option.view_ofs; 
    
    		traceline (test1, test2, FALSE, self); 
    
    		if (trace_fraction == 1.0)  	// ATTENTION: Be aware, that the monster will also see players behind it !!
    		{				//            to avoid it, use a check-function like:  infront ()
    			FoundTarget (); 
    			return TRUE; 
    		}
    // ------------------------------------------------ -------------- 
    	}
    
    	return FALSE;	// if its not a player, or hidden behind a wall -->  return FALSE
    };


    Didnt test/compile the code but it *should* work.

    Next, are your further restriction points 2.) and 3.) from your opening post.
    Please reconsider point 3.) because it might not be realistic:
    If the player is hidden behind a wall, his torchloght will most probably also be not visible. But of course, if the wall is low or a corner is near, the flashlight gets visible, yes.

    Anyhow, here is how you could code your points 1.) , 2.) and 3.)
    Please also read my comments:

    Code:
    float () FindTarget = 
    { 
    local entity client; 
    local float r; 
    
    // EarthQuake AI changes ------------------------ 
    
    local vector test1, test2; 
    local entity option; 
    
    // --------------------------------------------- 
    
    // 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") 
    	{
    // EarthQuake AI changes --------------------------------- 
    
    		option = self.enemy; 
    
    		// See if any walls are in the way 
    		test1 = self.origin + self.view_ofs; 
    		test2 = option.origin + option.view_ofs; 
    
    		traceline (test1, test2, FALSE, self); 
    
    		if (trace_fraction == 1.0) 	// ATTENTION: Be aware, that the monster will also see players behind it !!
    		{				//            to avoid it, use a check-function like:  infront ()
    			FoundTarget (); 
    			return TRUE; 
    		}
    		else
    		{
    			if (option.velocity != '0 0 0')		// checks for movement
    			{
    				r = range (client);
    				if ((r == RANGE_MID) || (r == RANGE_NEAR))	// checks for distance
    				{
    					FoundTarget (); 
    					return TRUE; 
    				}
    			
    			}
    			if (option.torch_flag_on == 1)		// set your correct torch .float or flag here. This is just a sample.
    			{
    				r = range (client);
    				if ((r == RANGE_MELEE) || (r == RANGE_NEAR) || (r == RANGE_MID))   // checks for distance
    				{
    					FoundTarget (); 
    					return TRUE; 
    				}
    			}
    		}
    // ------------------------------------------------ -------------- 
    	}
    
    	return FALSE;	// if its not a player, or doesnt match with above situations -->  always return FALSE
    };
    As you can see, checks for point 2.) and 3.) are depending on point 1.).
    That is how I have understood your opening post. But my poor english fools me sometimes.
    If their dependencies are different, please rearrange the code.

    Best of luck.

    Comment


    • #3
      About line of sight you can check the flashlight code in iq, it is implemented so that if the monster see the light get angry. But it happens only if from the shoulders very near or in front quite far away.
      Contradiction is truth. Fear is freedom. Rights are privileges. Job is a commodity. Ignorance is strength.

      Comment


      • #4
        Thanks a lot Seven; that#s really helpful. The monsters still completely ignore the player though. I've tried it with just a simple test map; the player, a big wall and a monster, just to be sure it's not a map thing. Can't work out why it doesn't work; problems are cool tho'

        Comment


        • #5
          What is the "setsize" of your player? Maybe it is too small and not detected with traceline? I don't know why but in my game (using darkplaces) if I set a size smaller than: setsize (self, '-8 -8 -24', '8 8 21'); it is not detected anymore by the traceline.

          Use this code instead:
          Code:
          ...
          	option = self.enemy;
          	// See if any walls are in the way 
          	test1 = self.origin + self.view_ofs; 
          	test2 = option.origin + option.view_ofs; 
          	
          	local vector dir = normalize((test2-test1));
          	traceline (test1, test2 + dir*8, MOVE_MISSILE, self);
          ...
          MOVE_MISSILE gives you a better chance to hit the traced entity.

          The code above is the same used for shooting, and I don't know why but it works better (the traceline appears to be more straight).

          Anyway, a common practice in QC is checking and return (is it more faster?):
          Code:
          ...
          	if (self.enemy.classname != "player") 
          		return FALSE;
          ...
          I checked the code that Seven provided you and it appears to be OK and what you expected.

          Comment

          Working...
          X