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); } }
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); } } }
/** * * * @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; } }