Block line dont actually return blocking line

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Block line dont actually return blocking line

Postby Apeirogon » Mon Nov 25, 2019 6:23 pm

Is it okay that blocking line actor pointer left null if actor was blocked by one sided line?

Because my function cant detect one sided lines until I make it show what actually line actor hit.
Have function
Code: Select allExpand view
private void rotate_kitten(line l)
{
    if(l)
    {
        vector2 offset;
       
        double ang;

        if(l.delta.x == 0)
            offset = (0, 1);

        else
        {
            ang = atan(l.delta.y/l.delta.x);

            if(ang == 90 || ang == -90)
                offset = (0, 1);

            else
                offset = (cos(ang), sin(ang) );
        }

        vector2 a, b;

        if(ang > 90 || ang < -90)
        {
            a = (l.v1.p) + offset;
            b = (l.v2.p) - offset;
        }

        else
        {
            a = (l.v1.p) - offset;
            b = (l.v2.p) + offset;
        }

        actor.spawn("healthbonus", pos: (a, 0));
        actor.spawn("healthbonus", pos: (b, 0));
}
}

which I constantly loop in thinker attached to actor.
So blocking line sets only after actor actually cross that line by its center, not when hit it.

What I can do to get last one sided line which block actor movement, which is what I actually want to get? Or this is bug of 4.2.4 version?
Last edited by Apeirogon on Wed Nov 27, 2019 6:15 am, edited 1 time in total.
Apeirogon
I have a strange sense of humour
 
Joined: 12 Jun 2017

Block line dont actually return blocking line

Postby Apeirogon » Wed Nov 27, 2019 6:07 am

Okay, after some investigation and deduction, I have this conclusions

If actor cross line between two sectors, and both sectors have same floor/ceiling height line dont set as actor blocking line
If actor cross line between two sectors, and there are any difference between sectors floor and/or ceiling height it sets as actor blocking line, regardless of actor flags (flying/bouncing/etc)
If line have any "impassable" flag on it and there are no difference between sectors ceiling/floor dont set as actor blocking line
If line between lift and default sectors it dont sets as blockin line, unless lift moves
If line connect closed door and default sector it dont set as actor blocking line

So now my question is why its work in such way on zscript side? It dont connect with pointer name, blocking line, because it sets only at specific conditions, which not always really block actor, and miss much of cases where it really block actor, like impassable line flags or one sided lines.
Apeirogon
I have a strange sense of humour
 
Joined: 12 Jun 2017

Re: Block line dont actually return blocking line

Postby Apeirogon » Mon Dec 02, 2019 4:37 pm

In case someone have same problem, here how I do so.
It return all lines which actor possibly can hit. For some cases, like kilometer long line, it return that line even if this line very far away from actor. But its cheap function.
Code: Select allExpand view
//check is actor hit/near some line
private void check_line_crashing(actor it)
{
    if(!it) return;
   
    for(uint i = 0; i < it.cursector.lines.size(); i++)
    {
        let l = it.cursector.lines[i];

        if(is_inside_line_bbox(it, l) )
        {
          //do something
        }
    }
}

//check line bbox and return true if actor, near/in it
//check line bbox and return true if actor, near/in it
private line is_inside_line_bbox(actor t, line l)
{
    //for some weird reason bbox[0] and [1] are y coordinates, instead of x

    double x_max, y_max, x_min, y_min;

    x_max = max(l.bbox[2], l.bbox[3]);
    y_max = max(l.bbox[0], l.bbox[1]);
    x_min = min(l.bbox[2], l.bbox[3]);
    y_min = min(l.bbox[0], l.bbox[1]);

    //is inside line bounding rectangle
    //radius and - 5 to extend bbox of vertical/horizontal lines
    //which have zero width/height of bbox
    if(t.pos.y > y_min - t.radius - 5 && t.pos.y < y_max - t.radius - 5 )
    {
        if(t.pos.x > x_min - t.radius - 5 && t.pos.x < x_max - t.radius - 5 )
        {
            //yes
            return l;
        }
    }

    //same, but now with +
    if(t.pos.y > y_min + t.radius + 5 && t.pos.y < y_max + t.radius + 5 )
    {
        if(t.pos.x > x_min + t.radius + 5 && t.pos.x < x_max + t.radius + 5 )
        {
            //yes
            return l;
        }
    }
    return null;
}


I do all check which I need in "//do something" block, so if you need return all lines actor can/already touch you must create wrapper for line arrays and return it.

Fix function, because previous version only work on third quarter of coordinate plane (where x < 0 and y < 0)
Apeirogon
I have a strange sense of humour
 
Joined: 12 Jun 2017


Return to Scripting

Who is online

Users browsing this forum: No registered users and 1 guest