Пример #1
0
std::list<BlockingObject> World::LoS(const position &startingpos, const position &endingpos) const {
    std::list<BlockingObject> ret;
    ret.clear();
    bool steep = std::abs(startingpos.y - endingpos.y) > std::abs(startingpos.x - endingpos.x);
    short int startx=startingpos.x;
    short int starty=startingpos.y;
    short int endx=endingpos.x;
    short int endy=endingpos.y;

    if (steep) {
        //change x,y values for correct algorithm in negativ range
        short int change;
        change = startx;
        startx = starty;
        starty = change;
        change = endx;
        endx = endy;
        endy = change;
    }

    bool swapped = startx > endx;

    if (swapped) {
        short int change;
        change = startx;
        startx = endx;
        endx = change;
        change = starty;
        starty = endy;
        endy = change;

    }

    short int deltax = endx - startx;
    short int deltay = std::abs(endy - starty);
    short int error = 0;
    short int ystep=1;
    short int y = starty;

    if (starty > endy) {
        ystep = -1;
    }

    for (short int x = startx; x <= endx; ++x) {
        if (!(x == startx && y == starty) && !(x == endx && y == endy)) {
            BlockingObject bo;
            Field *temp;
            position pos{x, y, startingpos.z};

            if (steep) {
                pos.x = y;
                pos.y = x;
            }

            if (GetPToCFieldAt(temp, pos)) {
                if (temp->IsPlayerOnField()) {
                    bo.blockingType = BlockingObject::BT_CHARACTER;
                    bo.blockingChar = findCharacterOnField(pos);

                    if (swapped) {
                        ret.push_back(bo);
                    } else {
                        ret.push_front(bo);
                    }
                } else {
                    ScriptItem it;

                    for (size_t i = 0; i < temp->NumberOfItems(); ++i) {
                        auto testItem = temp->getStackItem(i);
                        
                        if (testItem.getVolume() > it.getVolume()) {
                            it = testItem;
                        }
                    }
                        
                    if (it.isLarge()) {
                        bo.blockingType = BlockingObject::BT_ITEM;
                        it.pos = pos;
                        it.type = ScriptItem::it_field;
                        bo.blockingItem = it;

                        if (swapped) {
                            ret.push_back(bo);
                        } else {
                            ret.push_front(bo);
                        }
                    }
                }
            }
        }

        error += deltay;

        if (2*error >= deltax) {
            y+=ystep;
            error -= deltax;
        }
    }

    return ret;
}