[Sort of solved] Hitscan won't hit pillar

M

MegaJim73

Guest
I'm trying to implement a hitscan system in an FPS I'm making. It creates the appropriate impact when the gun hits an enemy (obj_enemy_basic) or wall (obj_wall_basic), but simply passes through when it hits a destructible pillar (obj_pillar). Help would be gladly appreciated.
Code:
{
  // check whether you can shoot
  if (not can_shoot) exit;
  can_shoot = false;
  // show the animation and play the sound
  image_speed = 0.5;
  image_index = 0;
  sound_play(snd_pstl);
  global.ammo-=1;
  var xx, yy, ii;
  xx = global.camx;
  yy = global.camy;
  repeat (256)
  {
    xx += 4*global.camcos;
    yy -= 4*global.camsin;
    with (obj_monster_basic)
    if ((id != other.id) && collision_circle(global.camx,global.camy,128,id,1,0))
    {
    with (id) alert=1;
    }
    ii = collision_line(global.camx,global.camy,xx,yy,obj_wall_basic,1,0);
    if (ii == noone)
    {
      ii = instance_position(xx,yy,obj_monster_basic);
      if (ii == noone) continue;
      with (ii)
      {
      mhealth-=1;
      hurt=1;
      t=instance_create(xx,yy,blood_type);
      t.z1=ii.z1*0.75;
      }
      break;
      ii = instance_position(xx,yy,obj_pillar1);
      if (ii == noone) continue;
        with (ii)
        {
        if (indestructible==0)
        {
          mhealth-=1;
          t=instance_create(xx,yy,blood_type);
          t.z1=ii.z1*0.75;
        };
        else
        t=instance_create(xx,yy,blood_type);
        t.z1=ii.z1*0.75;
        }
        break;
    }
    else
    {
        ii = instance_position(xx,yy,obj_wall_basic);
        if (ii == noone) continue;
        with (ii)
        {
        t=instance_create(xx,yy,obj_ricochet);
        t.direction=obj_player.direction;
        }
        break;
    }
  }
}
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
No offence intended, but your code is a bit of a mess... :p First issue I see is that you have a "with (obj_monster_basic)" call near the beginning but no {} after it, so that means that only the very next line will be run on that instance, and nothing else which I'm not sure if is intended or not (you really should always use {} to explicitly set scope)... Second thing is the way you are using break/continue. The breaks are badly placed and will cause the code to ALWAYS exit after the check for obj_monster_basic, which is why the pillar object isn't being detected. You need to rethink the game logic here (possibly setting a variable that if "true" will break the loop).
 

TheouAegis

Member
break;
ii = instance_position(xx,yy,obj_pillar1);
if (ii == noone) continue;
That break I quoted, as Nocturne said, is actually breaking out of your repeat(256) loop, since it's not placed within the scope of any other kind of loop. So your code looks for a wall and then stops, even if it didn't find a wall. You probably don't even need that break there at all, or at least not used in the way you're using it. I mean, your code checks if there's a wall in the way of the monster, but it doesn't actually check if there's a pillar in the way of the wall.

And what if there's a wall AND a pillar in the way? Or what if there's 2 walls in the way? How do you know which wall or which pillar is taking the bullet? Although if your camcos and camsin are small enough, that scenario likely won't occur. lol

Suggestion: Run the loop from a script, then instead of trying to get break to behave however you want it to, just use return 1 to end the loop immediately.
 
Last edited:
M

MegaJim73

Guest
That break I quoted, as Nocturne said, is actually breaking out of your repeat(256) loop, since it's not placed within the scope of any other kind of loop. So your code looks for a wall and then stops, even if it didn't find a wall. You probably don't even need that break there at all, or at least not used in the way you're using it. I mean, your code checks if there's a wall in the way of the monster, but it doesn't actually check if there's a pillar in the way of the wall.
I thought the break was supposed to end the with statement and continue the rest of the code. Should I move the breaks somewhere or remove them?

And what if there's a wall AND a pillar in the way? Or what if there's 2 walls in the way? How do you know which wall or which pillar is taking the bullet? Although if your camcos and camsin are small enough, that scenario likely won't occur. lol
The idea was to check if a wall is hit, and if not check if the object hit is a monster or pillar.
I considered and tried using a switch to determine if there is an object blocking the path between the player and the wall, but it didn't work.
 
Last edited by a moderator:
M

MegaJim73

Guest
After a couple days, I've eventually gotten it to work somehow by replacing the repeat with a for-loop.
Code:
{
  // check whether you can shoot
  if (not can_shoot) exit;
  can_shoot = false;
  // show the animation and play the sound
  image_speed = 0.5;
  image_index = 0;
  sound_play(snd_pstl);
  global.ammo-=1;
  var xx, yy, ii;
  xx = global.camx;
  yy = global.camy;
  for (i=0; i<256;i+=2)
  {
    xx += 4*global.camcos;
    yy -= 4*global.camsin;
    if (position_meeting(xx,yy,obj_wall_basic))
    {   ///You hit a wall, ricochet.
        t=instance_create(xx,yy,obj_ricochet);
        t.direction=obj_player.direction;
        t.z1=ii.z1*0.75;
    break;
    }
    else
    if (position_meeting(xx,yy,obj_monster_basic))
    {   ///You hit an enemy, deal damage.
      ii = instance_position(xx,yy,obj_monster_basic);
      if (ii == noone) continue;
      with (ii)
      {
      mhealth-=1;
      hurt=1;
      t=instance_create(xx,yy,blood_type);
      t.z1=ii.z1*0.75;
      break;
      }
    }
    else
    if (position_meeting(xx,yy,obj_pillar1))
    {   ///You hit a column, ricochet.
      ii = instance_position(xx,yy,obj_pillar1);
      if (ii == noone) continue;
      with (ii)
      {
      if (indestructible==0)
        {
          mhealth-=1;
          t=instance_create(xx,yy,blood_type);
          t.z1=ii.z1*0.75;
        };
        else
        t=instance_create(xx,yy,blood_type);
        t.z1=ii.z1*0.75;
        break;
      }
    }
    //alert other enemies within radius
    with (obj_monster_basic)
    {
    if ((id != other.id) && collision_circle(global.camx,global.camy,128,id,1,0))
    {
    with (id) alert=1;
    }
    }  
  };
}
It's not very efficient, but at least it works like it should for now. The bullets hit what they should be hitting and making the corresponding impacts.
 
Top