Example #1
0
void noFigure::StartWalking(const unsigned char newDir)
{
    assert(!(GetGOT() == GOT_NOF_PASSIVESOLDIER && fs == FS_JOB));

    assert(newDir <= 5);
    if(newDir > 5)
    {
        LOG.lprintf("Achtung: Bug im Spiel entdeckt! noFigure::StartWalking: dir = %d\n", unsigned(newDir));
        return;
    }

    // Gehen wir in ein Gebäude?
    if(newDir == 1 && gwg->GetNO(gwg->GetNeighbour(pos, 1))->GetType() == NOP_BUILDING)
        gwg->GetSpecObj<noBuilding>(gwg->GetNeighbour(pos, 1))->OpenDoor(); // Dann die Tür aufmachen
    // oder aus einem raus?
    if(newDir == 4 && gwg->GetNO(pos)->GetType() == NOP_BUILDING)
        gwg->GetSpecObj<noBuilding>(pos)->OpenDoor(); // Dann die Tür aufmachen

    // Ist der Platz schon besetzt, wo wir hinlaufen wollen und laufen wir auf Straßen?
    if(!gwg->IsRoadNodeForFigures(gwg->GetNeighbour(pos, newDir), newDir) && cur_rs)
    {
        // Dann stehen bleiben!
        FaceDir(newDir);
        waiting_for_free_node = true;
        // Andere Figuren stoppen
        gwg->StopOnRoads(pos, newDir);
    }
    else
    {
        // Normal hinlaufen
        StartMoving(newDir, 20);
    }
}
Example #2
0
void nofBuilder::StartFreewalk()
{
    std::vector<unsigned char> possible_directions;

    unsigned char waiting_walk = ((state == STATE_WAITINGFREEWALK) ? 0 : 1);

    // Wohin kann der Bauarbeiter noch laufen?

    // Nach links
    if(rel_x - FREEWALK_LENGTH[waiting_walk] >= LEFT_MAX)
        possible_directions.push_back(0);
    // Nach rechts
    if(rel_x + FREEWALK_LENGTH[waiting_walk] <= RIGHT_MAX)
        possible_directions.push_back(3);
    // Nach links/oben
    if(rel_x - FREEWALK_LENGTH_SLANTWISE[waiting_walk] >= LEFT_MAX && rel_y - FREEWALK_LENGTH_SLANTWISE[waiting_walk] >= UP_MAX)
        possible_directions.push_back(1);
    // Nach links/unten
    if(rel_x - FREEWALK_LENGTH_SLANTWISE[waiting_walk] >= LEFT_MAX && rel_y + FREEWALK_LENGTH_SLANTWISE[waiting_walk] <= DOWN_MAX)
        possible_directions.push_back(5);
    // Nach rechts/oben
    if(rel_x + FREEWALK_LENGTH_SLANTWISE[waiting_walk] <= RIGHT_MAX && rel_y - FREEWALK_LENGTH_SLANTWISE[waiting_walk] >= UP_MAX)
        possible_directions.push_back(2);
    // Nach rechts/unten
    if(rel_x + FREEWALK_LENGTH_SLANTWISE[waiting_walk] <= RIGHT_MAX && rel_y + FREEWALK_LENGTH_SLANTWISE[waiting_walk] <= DOWN_MAX)
        possible_directions.push_back(4);

    assert(possible_directions.size() > 0);
    // Zufällige Richtung von diesen auswählen
    FaceDir(possible_directions[RANDOM.Rand(__FILE__, __LINE__, GetObjId(), possible_directions.size())]);

    // Und dort auch hinlaufen
    current_ev = em->AddEvent(this, (state == STATE_WAITINGFREEWALK) ? 24 : 17, 1);

    // Zukünftigen Platz berechnen
    next_rel_x = rel_x;
    next_rel_y = rel_y;

    switch(GetCurMoveDir())
    {
        case 0: next_rel_x -= FREEWALK_LENGTH[waiting_walk]; break;
        case 1: next_rel_x -= FREEWALK_LENGTH_SLANTWISE[waiting_walk]; next_rel_y -= FREEWALK_LENGTH_SLANTWISE[waiting_walk]; break;
        case 2: next_rel_x += FREEWALK_LENGTH_SLANTWISE[waiting_walk]; next_rel_y -= FREEWALK_LENGTH_SLANTWISE[waiting_walk]; break;
        case 3: next_rel_x += FREEWALK_LENGTH[waiting_walk]; break;
        case 4: next_rel_x += FREEWALK_LENGTH_SLANTWISE[waiting_walk]; next_rel_y += FREEWALK_LENGTH_SLANTWISE[waiting_walk]; break;
        case 5: next_rel_x -= FREEWALK_LENGTH_SLANTWISE[waiting_walk]; next_rel_y += FREEWALK_LENGTH_SLANTWISE[waiting_walk]; break;
    }
}
/// Ist am Militärgebäude angekommen
void nofAttacker::ReachedDestination()
{
    // Sind wir direkt an der Flagge?
    if(pos == attacked_goal->GetFlag()->GetPos())
    {
        // Building already captured? Continue capturing
        // This can only be a far away attacker
        if(attacked_goal->GetPlayer() == player)
        {
            state = STATE_ATTACKING_CAPTURINGNEXT;
            RTTR_Assert(dynamic_cast<nobMilitary*>(attacked_goal));
            auto* goal = static_cast<nobMilitary*>(attacked_goal);
            RTTR_Assert(goal->IsFarAwayCapturer(this));
            // Start walking first so the flag is free
            StartWalking(Direction::NORTHWEST);
            // Then tell the building
            goal->FarAwayCapturerReachedGoal(this);
            return;
        }

        // Post schicken "Wir werden angegriffen" TODO evtl. unschön, da jeder Attacker das dann aufruft
        SendPostMessage(attacked_goal->GetPlayer(), new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), _("We are under attack!"),
                                                                            PostCategory::Military, *attacked_goal));

        // Dann Verteidiger rufen
        if(attacked_goal->CallDefender(this))
        {
            // Verteidiger gefunden --> hinstellen und auf ihn warten
            SwitchStateAttackingWaitingForDefender();
        } else
        {
            // kein Verteidiger gefunden --> ins Gebäude laufen und es erobern
            state = STATE_ATTACKING_CAPTURINGFIRST;
            StartWalking(Direction::NORTHWEST);
            // Normalen Militärgebäuden schonmal Bescheid sagen
            if(attacked_goal->GetGOT() == GOT_NOB_MILITARY)
                static_cast<nobMilitary*>(attacked_goal)->PrepareCapturing();
        }
    } else
    {
        // dann hinstellen und warten, bis wir an die Reihe kommmen mit Kämpfen und außerdem diesen Platz
        // reservieren, damit sich kein anderer noch hier hinstellt
        state = STATE_ATTACKING_WAITINGAROUNDBUILDING;
        // zur Flagge hin ausrichten
        Direction dir(Direction::WEST);
        MapPoint attFlagPos = attacked_goal->GetFlag()->GetPos();
        if(pos.y == attFlagPos.y && pos.x <= attFlagPos.x)
            dir = Direction::EAST;
        else if(pos.y == attFlagPos.y && pos.x > attFlagPos.x)
            dir = Direction::WEST;
        else if(pos.y < attFlagPos.y && pos.x < attFlagPos.x)
            dir = Direction::SOUTHEAST;
        else if(pos.y < attFlagPos.y && pos.x > attFlagPos.x)
            dir = Direction::SOUTHWEST;
        else if(pos.y > attFlagPos.y && pos.x < attFlagPos.x)
            dir = Direction::NORTHEAST;
        else if(pos.y > attFlagPos.y && pos.x > attFlagPos.x)
            dir = Direction::NORTHWEST;
        else /* (pos.x ==  attFlagPos.x)*/
        {
            if(pos.y < attFlagPos.y && !(safeDiff(pos.y, attFlagPos.y) & 1))
                dir = Direction::SOUTHEAST;
            else if(pos.y < attFlagPos.y && (safeDiff(pos.y, attFlagPos.y) & 1))
            {
                if(pos.y & 1)
                    dir = Direction::SOUTHWEST;
                else
                    dir = Direction::SOUTHEAST;
            } else if(pos.y > attFlagPos.y && !(safeDiff(pos.y, attFlagPos.y) & 1))
                dir = Direction::NORTHEAST;
            else /* (pos.y > attFlagPos.y && (safeDiff(pos.y, attFlagPos.y) & 1))*/
            {
                if(pos.y & 1)
                    dir = Direction::NORTHWEST;
                else
                    dir = Direction::NORTHEAST;
            }
        }
        FaceDir(dir);
        if(attacked_goal->GetPlayer() == player)
        {
            // Building already captured? -> Then we might be a far-away-capturer
            // -> Tell the building, that we are here
            RTTR_Assert(dynamic_cast<nobMilitary*>(attacked_goal));
            auto* goal = static_cast<nobMilitary*>(attacked_goal);
            if(goal->IsFarAwayCapturer(this))
                goal->FarAwayCapturerReachedGoal(this);
        }
    }
}
Example #4
0
/**
 *
 *
 *  @author OLiver
 */
void nofCarrier::Walked()
{
    // Bootssounds ggf. löschen
    if(ct == CT_BOAT && state != CARRS_FIGUREWORK)
        SOUNDMANAGER.WorkingFinished(this);

    switch(state)
    {
        default:
            break;
        case CARRS_GOTOMIDDLEOFROAD:
        {
            // Gibts an der Flagge in der entgegengesetzten Richtung, in die ich laufe, evtl Waren zu tragen
            // (da wir darüber nicht unmittelbar informiert werden!)
            if(workplace->AreWareJobs(rs_dir, ct, false))
            {
                // Dann umdrehen und holen
                rs_dir = !rs_dir;
                rs_pos = workplace->GetLength() - rs_pos;
                state = CARRS_FETCHWARE;

                StartWalking(cur_rs->GetDir(rs_dir, rs_pos));
            }
            else if(rs_pos == cur_rs->GetLength() / 2 || rs_pos == cur_rs->GetLength() / 2 + cur_rs->GetLength() % 2)
            {
                // Wir sind in der Mitte angekommen
                state = CARRS_WAITFORWARE;
                if(GetCurMoveDir() == 0 || GetCurMoveDir() == 1 || GetCurMoveDir() == 5)
                    FaceDir(5);
                else
                    FaceDir(4);

                current_ev = 0;

                // Jetzt wird wieder nur rumgegammelt, dann kriegen wir aber evtl keinen schönen IH-AH!
                StopWorking();

                // Animation auf später verschieben, damit die nicht mittendrin startet
                SetNewAnimationMoment();
            }
            else
            {
                // Eventuell laufen wir in die falsche Richtung?
                if(rs_pos > cur_rs->GetLength() / 2)
                {
                    rs_dir = !rs_dir;
                    rs_pos = cur_rs->GetLength() - rs_pos;
                }

                StartWalking(cur_rs->GetDir(rs_dir, rs_pos));
            }
        } break;
        case CARRS_FETCHWARE:
        {
            // Zur Flagge laufen, um die Ware zu holen

            // Sind wir schon da?
            if(rs_pos == cur_rs->GetLength())
                // Dann Ware aufnehmnen
                FetchWare(false);
            else
                StartWalking(cur_rs->GetDir(rs_dir, rs_pos));


        } break;
        case CARRS_CARRYWARE:
        {
            // Sind wir schon da?
            if(rs_pos == cur_rs->GetLength())
            {

                // Flagge, an der wir gerade stehen
                noFlag* this_flag  = static_cast<noFlag*>(((rs_dir) ? workplace->GetF1() : workplace->GetF2()));

                bool calculated = false;

                // Will die Waren jetzt gleich zur Baustelle neben der Flagge?
                if(WantInBuilding(&calculated))
                {
                    // Erst noch zur Baustelle bzw Gebäude laufen
                    state = CARRS_CARRYWARETOBUILDING;
                    StartWalking(1);
                    cur_rs = this_flag->routes[1];
                    // location wird immer auf nächste Flagge gesetzt --> in dem Fall aktualisieren
                    carried_ware->Carry((cur_rs->GetF1() == this_flag) ? cur_rs->GetF2() : cur_rs->GetF1());
                }
                else
                {
                    // Ist an der Flagge noch genügend Platz (wenn wir wieder eine Ware mitnehmen, kann sie auch voll sein)
                    if(this_flag->IsSpaceForWare())
                    {
                        carried_ware->LieAtFlag(this_flag);

                        // Ware soll ihren weiteren Weg berechnen
                        if (!calculated)
                        {
                            carried_ware->RecalcRoute();
                        }

                        // Ware ablegen
                        this_flag->AddWare(carried_ware);
                        // Wir tragen erstmal keine Ware mehr
                        carried_ware = 0;
                        // Gibts an den Flaggen etwas, was ich tragen muss, ansonsten wieder in die Mitte gehen und warten
                        LookForWares();
                    }
                    else if(workplace->AreWareJobs(!rs_dir, ct, true))
                    {
                        // die Flagge ist voll, aber wir können eine Ware mitnehmen, daher erst Ware nehmen und dann erst ablegen

                        // Ware "merken"
                        Ware* tmp_ware = carried_ware;
                        // neue Ware aufnehmen
                        FetchWare(true);

                        // alte Ware ablegen
                        tmp_ware->LieAtFlag(this_flag);

                        if (!calculated)
                        {
                            tmp_ware->RecalcRoute();
                        }
                        this_flag->AddWare(tmp_ware);
                    }
                    else
                    {
                        // wenn kein Platz mehr ist --> wieder umdrehen und zurückgehen
                        state = CARRS_GOBACKFROMFLAG;
                        rs_dir = !rs_dir;
                        rs_pos = cur_rs->GetLength() - rs_pos;
                        StartWalking((GetCurMoveDir() + 3) % 6);
                    }
                }
            }
            else if(rs_pos == cur_rs->GetLength() - 1)
            {
                // Wenn wir fast da sind, gucken, ob an der Flagge noch ein freier Platz ist
                noFlag* this_flag  = static_cast<noFlag*>(((rs_dir) ? workplace->GetF1() : workplace->GetF2()));

                if(this_flag->IsSpaceForWare() || WantInBuilding(NULL) || cur_rs->AreWareJobs(!rs_dir, ct, true))
                {
                    // Es ist Platz, dann zur Flagge laufen
                    StartWalking(cur_rs->GetDir(rs_dir, rs_pos));
                }
                else
                {
                    // Wenn kein Platz ist, stehenbleiben und warten!
                    state = CARRS_WAITFORWARESPACE;
                    FaceDir(cur_rs->GetDir(rs_dir, rs_pos));
                }
            }
            else
            {
                StartWalking(cur_rs->GetDir(rs_dir, rs_pos));
            }

        } break;
        case CARRS_CARRYWARETOBUILDING:
        {
            // Ware ablegen
            gwg->GetSpecObj<noRoadNode>(pos)->AddWare(carried_ware);
            // Ich trag' keine Ware mehr
            carried_ware = 0;
            // Wieder zurück zu meinem Weg laufen
            state = CARRS_LEAVEBUILDING;
            StartWalking(4);
        } break;
        case CARRS_LEAVEBUILDING:
        {
            // So tun, als ob der Träger gerade vom anderen Ende des Weges kommt, damit alles korrekt funktioniert
            cur_rs = workplace;
            FaceDir(workplace->GetDir(rs_dir, workplace->GetLength() - 1));
            LookForWares();
        } break;
        case CARRS_GOBACKFROMFLAG:
        {
            // Wieder umdrehen und so tun, als wären wir gerade normal angekommen
            rs_dir = !rs_dir;
            rs_pos = cur_rs->GetLength() - rs_pos;
            state = CARRS_CARRYWARE;
            Walked();
        } break;
        case CARRS_BOATCARRIER_WANDERONWATER:
        {
            WanderOnWater();
        } break;
    }
}