/// Wenn ein Kampf gewonnen wurde void nofAttacker::WonFighting() { // addon BattlefieldPromotion active? -> increase rank! if(gwg->GetGGS().isEnabled(AddonId::BATTLEFIELD_PROMOTION)) IncreaseRank(); // Ist evtl. unser Heimatgebäude zerstört? if(!building && state != STATE_ATTACKING_FIGHTINGVSDEFENDER) { // Dann dem Ziel Bescheid sagen, falls es existiert (evtl. wurdes zufällig zur selben Zeit zerstört) InformTargetsAboutCancelling(); // Ggf. Schiff Bescheid sagen (Schiffs-Angreifer) if(ship_obj_id) CancelAtShip(); // Rumirren state = STATE_FIGUREWORK; StartWandering(); Wander(); return; } // Ist evtl. unser Ziel-Gebäude zerstört? if(!attacked_goal) { // Nach Hause gehen ReturnHomeMissionAttacking(); return; } ContinueAtFlag(); }
void nofAttacker::CapturedBuildingFull() { // No need to notify the goal attacked_goal = nullptr; switch(state) { default: break; case STATE_ATTACKING_WAITINGAROUNDBUILDING: { // nach Hause gehen ReturnHomeMissionAttacking(); } break; case STATE_ATTACKING_WALKINGTOGOAL: case STATE_ATTACKING_WAITINGFORDEFENDER: case STATE_ATTACKING_ATTACKINGFLAG: case STATE_WAITINGFORFIGHT: case STATE_MEETENEMY: case STATE_FIGHTING: case STATE_SEAATTACKING_GOTOHARBOR: // geht von seinem Heimatmilitärgebäude zum Starthafen case STATE_SEAATTACKING_WAITINHARBOR: // wartet im Hafen auf das ankommende Schiff case STATE_SEAATTACKING_ONSHIP: // befindet sich auf dem Schiff auf dem Weg zum Zielpunkt { // Bei allem anderen läuft man oder kämpft --> auf 0 setzen und wenn man fertig // mit der jetzigen Aktion ist, entsprechend handeln (nicht die Einnehmer darüber benachrichten, sonst // gehen die nicht rein) attacked_goal = nullptr; } break; } }
void nofAttacker::AttackedGoalDestroyed() { attacked_goal = nullptr; bool was_waiting_for_defender = (state == STATE_ATTACKING_WAITINGFORDEFENDER); // Wenn man gerade rumsteht, muss man sich bewegen if(state == STATE_ATTACKING_WAITINGFORDEFENDER || state == STATE_ATTACKING_WAITINGAROUNDBUILDING || state == STATE_WAITINGFORFIGHT) ReturnHomeMissionAttacking(); else if(state == STATE_SEAATTACKING_WAITINHARBOR) { // We don't need to wait anymore, target was destroyed auto* harbor = gwg->GetSpecObj<nobHarborBuilding>(harborPos); RTTR_Assert(harbor); // go home goal_ = building; state = STATE_FIGUREWORK; fs = FS_GOTOGOAL; harbor->CancelSeaAttacker(this); return; } if(was_waiting_for_defender) { // Block-Event ggf abmelden GetEvMgr().RemoveEvent(blocking_event); gwg->RoadNodeAvailable(pos); } }
void nofAttacker::AttackedGoalDestroyed() { attacked_goal = 0; bool was_waiting_for_defender = (state == STATE_ATTACKING_WAITINGFORDEFENDER); // Wenn man gerade rumsteht, muss man sich bewegen if(state == STATE_ATTACKING_WAITINGFORDEFENDER || state == STATE_ATTACKING_WAITINGAROUNDBUILDING || state == STATE_WAITINGFORFIGHT) ReturnHomeMissionAttacking(); if(was_waiting_for_defender) { // Block-Event ggf abmelden em->RemoveEvent(blocking_event); blocking_event = 0; gwg->RoadNodeAvailable(pos); } }
void nofAttacker::CapturingWalking() { // Ist evtl. das Zielgebäude zerstört? if(!attacked_goal) { // Nach Hause gehen ReturnHomeMissionAttacking(); return; } RTTR_Assert(dynamic_cast<nobMilitary*>(attacked_goal)); MapPoint attFlagPos = attacked_goal->GetFlag()->GetPos(); // Sind wir schon im Gebäude? if(pos == attacked_goal->GetPos()) { // Meinem alten Heimatgebäude Bescheid sagen (falls es noch existiert) if(building) building->SoldierLost(this); CancelAtHuntingDefender(); if(ship_obj_id) CancelAtShip(); // mich von der Karte tilgen- gwg->RemoveFigure(pos, this); // Das ist nun mein neues zu Hause building = attacked_goal; // und zum Gebäude hinzufügen attacked_goal->AddActiveSoldier(this); // Ein erobernder Soldat weniger if(BuildingProperties::IsMilitary(attacked_goal->GetBuildingType())) { RTTR_Assert(dynamic_cast<nobMilitary*>(attacked_goal)); auto* goal = static_cast<nobMilitary*>(attacked_goal); // If we are still a far-away-capturer at this point, then the building belongs to us and capturing was already finished if(!goal->IsFarAwayCapturer(this)) { RemoveFromAttackedGoal(); goal->CapturingSoldierArrived(); } else { RemoveFromAttackedGoal(); RTTR_Assert(goal->GetPlayer() == player); } } else RemoveFromAttackedGoal(); } // oder zumindest schonmal an der Flagge? else if(pos == attFlagPos) { // ins Gebäude laufen StartWalking(Direction::NORTHWEST); // nächsten Angreifer ggf. rufen, der auch reingehen soll RTTR_Assert(attacked_goal->GetPlayer() == player); // Assumed by the call below static_cast<nobMilitary*>(attacked_goal)->NeedOccupyingTroops(); } else { // Ist evtl. unser Heimatgebäude zerstört? if(!building) { // Wenn noch das Ziel existiert (könnte ja zeitgleich abgebrannt worden sein) if(attacked_goal) { auto* attackedBld = static_cast<nobMilitary*>(attacked_goal); RemoveFromAttackedGoal(); // Evtl. neue Besatzer rufen RTTR_Assert(attackedBld->GetPlayer() == player); attackedBld->NeedOccupyingTroops(); } // Ggf. Schiff Bescheid sagen (Schiffs-Angreifer) if(ship_obj_id) CancelAtShip(); // Rumirren state = STATE_FIGUREWORK; StartWandering(); Wander(); return; } // weiter zur Flagge laufen unsigned char dir = gwg->FindHumanPath(pos, attFlagPos, 10, true); if(dir == 0xFF) { // auweia, es wurde kein Weg mehr gefunden // Evtl. neue Besatzer rufen RTTR_Assert(attacked_goal->GetPlayer() == player); // Assumed by the call below static_cast<nobMilitary*>(attacked_goal)->NeedOccupyingTroops(); // Nach Hause gehen ReturnHomeMissionAttacking(); } else StartWalking(Direction(dir)); } }
void nofAttacker::MissAttackingWalk() { // Ist evtl. unser Heimatgebäude zerstört? if(!building) { // Dann dem Ziel Bescheid sagen, falls es existiert (evtl. wurdes zufällig zur selben Zeit zerstört) InformTargetsAboutCancelling(); // Ggf. Schiff Bescheid sagen (Schiffs-Angreifer) if(ship_obj_id) CancelAtShip(); // Rumirren state = STATE_FIGUREWORK; StartWandering(); Wander(); return; } // Gibts das Ziel überhaupt noch? if(!attacked_goal) { ReturnHomeMissionAttacking(); return; } /*// Is it still a hostile destination? // (Could be captured in the meantime) if(!players->getElement(player)->IsPlayerAttackable(attacked_goal->GetPlayer())) { ReturnHomeMissionAttacking(); return; }*/ // Eine Position rund um das Militärgebäude suchen MapPoint goal = attacked_goal->FindAnAttackerPlace(radius, this); // Keinen Platz mehr gefunden? if(!goal.isValid()) { // Dann nach Haus gehen ReturnHomeMissionAttacking(); return; } // Sind wir evtl schon da? if(pos == goal) { ReachedDestination(); return; } // Find all sorts of enemies (attackers, aggressive defenders..) nearby if(FindEnemiesNearby()) // Enemy found -> abort, because nofActiveSoldier handles all things now return; // Haben wir noch keinen Feind? // Könnte mir noch ein neuer Verteidiger entgegenlaufen? TryToOrderAggressiveDefender(); // Ansonsten Weg zum Ziel suchen unsigned char dir = gwg->FindHumanPath(pos, goal, MAX_ATTACKING_RUN_DISTANCE, true); // Keiner gefunden? Nach Hause gehen if(dir == 0xff) { ReturnHomeMissionAttacking(); return; } // Start walking StartWalking(Direction(dir)); }
void nofAttacker::Walked() { ExpelEnemies(); // Was bestimmtes machen, je nachdem welchen Status wir gerade haben switch(state) { default: nofActiveSoldier::Walked(); break; case STATE_ATTACKING_WALKINGTOGOAL: { MissAttackingWalk(); } break; case STATE_ATTACKING_ATTACKINGFLAG: { // Ist evtl. das Zielgebäude zerstört? if(!attacked_goal) { // Nach Hause gehen ReturnHomeMissionAttacking(); return; } MapPoint goalFlagPos = attacked_goal->GetFlag()->GetPos(); // RTTR_Assert(enemy->GetGOT() == GOT_NOF_DEFENDER); // Are we at the flag? nofDefender* defender = nullptr; // Look for defenders at this position const std::list<noBase*>& figures = gwg->GetFigures(goalFlagPos); for(auto figure : figures) { if(figure->GetGOT() == GOT_NOF_DEFENDER) { // Is the defender waiting at the flag? // (could be wandering around or something) if(static_cast<nofDefender*>(figure)->IsWaitingAtFlag()) { defender = static_cast<nofDefender*>(figure); } } } if(pos == goalFlagPos) { if(defender) { // Start fight with the defender gwg->AddFigure(pos, new noFighting(this, defender)); // Set the appropriate states state = STATE_ATTACKING_FIGHTINGVSDEFENDER; defender->FightStarted(); } else // No defender at the flag? // -> Order new defenders or capture the building ContinueAtFlag(); } else { unsigned char dir = gwg->FindHumanPath(pos, goalFlagPos, 5, true); if(dir == 0xFF) { // es wurde kein Weg mehr gefunden --> neues Plätzchen suchen und warten state = STATE_ATTACKING_WALKINGTOGOAL; MissAttackingWalk(); // der Verteidiger muss darüber informiert werden if(defender) defender->AttackerArrested(); } else { // Hinlaufen StartWalking(Direction(dir)); } } } break; case STATE_ATTACKING_CAPTURINGFIRST: { // Ist evtl. das Zielgebäude zerstört? if(!attacked_goal) { // Nach Hause gehen ReturnHomeMissionAttacking(); return; } // Wenn schon welche drin sind, ist wieder ein feindlicher reingegangen if(attacked_goal->DefendersAvailable()) { // Wieder rausgehen, Platz reservieren if(attacked_goal->GetGOT() == GOT_NOB_MILITARY) static_cast<nobMilitary*>(attacked_goal)->StopCapturing(); state = STATE_ATTACKING_WALKINGTOGOAL; StartWalking(Direction::SOUTHEAST); return; } else { // Ist das Gebäude ein "normales Militärgebäude", das wir da erobert haben? if(BuildingProperties::IsMilitary(attacked_goal->GetBuildingType())) { RTTR_Assert(dynamic_cast<nobMilitary*>(attacked_goal)); // Meinem Heimatgebäude Bescheid sagen, dass ich nicht mehr komme (falls es noch eins gibt) if(building) building->SoldierLost(this); CancelAtHuntingDefender(); // Ggf. Schiff Bescheid sagen (Schiffs-Angreifer) if(ship_obj_id) CancelAtShip(); // Gebäude einnehmen auto* goal = static_cast<nobMilitary*>(attacked_goal); goal->Capture(player); // This is the new home building = attacked_goal; // mich zum Gebäude hinzufügen und von der Karte entfernen attacked_goal->AddActiveSoldier(this); RemoveFromAttackedGoal(); // Tell that we arrived and probably call other capturers goal->CapturingSoldierArrived(); gwg->RemoveFigure(pos, this); } // oder ein Hauptquartier oder Hafen? else { // Inform the owner of the building const std::string msg = (attacked_goal->GetGOT() == GOT_NOB_HQ) ? _("Our headquarters was destroyed!") : _("This harbor building was destroyed"); SendPostMessage(attacked_goal->GetPlayer(), new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), msg, PostCategory::Military, *attacked_goal)); // abreißen nobBaseMilitary* tmp_goal = attacked_goal; // attacked_goal wird evtl auf 0 gesetzt! tmp_goal->Destroy(); delete tmp_goal; attacked_goal = nullptr; ReturnHomeMissionAttacking(); } } } break; case STATE_ATTACKING_CAPTURINGNEXT: { CapturingWalking(); } break; case STATE_SEAATTACKING_GOTOHARBOR: // geht von seinem Heimatmilitärgebäude zum Starthafen { // Gucken, ob der Abflughafen auch noch steht und sich in unserer Hand befindet bool valid_harbor = true; noBase* hb = gwg->GetNO(harborPos); if(hb->GetGOT() != GOT_NOB_HARBORBUILDING) valid_harbor = false; else if(static_cast<nobHarborBuilding*>(hb)->GetPlayer() != player) valid_harbor = false; // Nicht mehr oder das angegriffene Gebäude kaputt? Dann müssen wir die ganze Aktion abbrechen if(!valid_harbor || !attacked_goal) { // Dann gehen wir halt wieder nach Hause ReturnHomeMissionAttacking(); return; } // Sind wir schon da? if(pos == harborPos) { // Uns zum Hafen hinzufügen state = STATE_SEAATTACKING_WAITINHARBOR; gwg->RemoveFigure(pos, this); gwg->GetSpecObj<nobHarborBuilding>(pos)->AddSeaAttacker(this); return; } // Erstmal Flagge ansteuern MapPoint harborFlagPos = gwg->GetNeighbour(harborPos, Direction::SOUTHEAST); // Wenn wir an der Flagge bereits sind, in den Hafen eintreten if(pos == harborFlagPos) StartWalking(Direction::NORTHWEST); else { // Weg zum Hafen suchen unsigned char dir = gwg->FindHumanPath(pos, harborFlagPos, MAX_ATTACKING_RUN_DISTANCE, false, nullptr); if(dir == 0xff) { // Kein Weg gefunden? Dann auch abbrechen! ReturnHomeMissionAttacking(); return; } // Und schön weiterlaufen StartWalking(Direction(dir)); } } break; case STATE_SEAATTACKING_WAITINHARBOR: // wartet im Hafen auf das ankommende Schiff { } break; case STATE_SEAATTACKING_ONSHIP: // befindet sich auf dem Schiff auf dem Weg zum Zielpunkt { // Auweia, das darf nicht passieren RTTR_Assert(false); } break; case STATE_SEAATTACKING_RETURNTOSHIP: // befindet sich an der Zielposition auf dem Weg zurück zum Schiff { HandleState_SeaAttack_ReturnToShip(); } break; } }
void nofAttacker::CapturingWalking() { // Ist evtl. das Zielgebäude zerstört? if(!attacked_goal) { // Nach Hause gehen ReturnHomeMissionAttacking(); return; } MapPoint attFlagPos = attacked_goal->GetFlag()->GetPos(); // Sind wir schon im Gebäude? if(pos == attacked_goal->GetPos()) { // Meinem alten Heimatgebäude Bescheid sagen (falls es noch existiert) if(building) building->SoldierLost(this); if(ship_obj_id) CancelAtShip(); // mich von der Karte tilgen- gwg->RemoveFigure(this, pos); // Das ist nun mein neues zu Hause building = attacked_goal; // und zum Gebäude hinzufügen attacked_goal->AddActiveSoldier(this); // Ein erobernder Soldat weniger if(attacked_goal->GetBuildingType() >= BLD_BARRACKS && attacked_goal->GetBuildingType() <= BLD_FORTRESS) static_cast<nobMilitary*>(attacked_goal)->CapturingSoldierArrived(); // außerdem aus der Angreiferliste entfernen attacked_goal->UnlinkAggressor(this); attacked_goal = 0; } // oder zumindest schonmal an der Flagge? else if(pos == attFlagPos) { // ins Gebäude laufen StartWalking(1); // nächsten Angreifer ggf. rufen, der auch reingehen soll static_cast<nobMilitary*>(attacked_goal)->NeedOccupyingTroops(player); } else { // Ist evtl. unser Heimatgebäude zerstört? if(!building) { // Wenn noch das Ziel existiert (könnte ja zeitgleich abgebrannt worden sein) if(attacked_goal) { // Ziel Bescheid sagen attacked_goal->UnlinkAggressor(this); // Evtl. neue Besatzer rufen static_cast<nobMilitary*>(attacked_goal)->NeedOccupyingTroops(0xFF); attacked_goal = 0; } // Ggf. Schiff Bescheid sagen (Schiffs-Angreifer) if(ship_obj_id) CancelAtShip(); // Rumirren state = STATE_FIGUREWORK; StartWandering(); Wander(); return; } // weiter zur Flagge laufen if((dir = gwg->FindHumanPath(pos, attFlagPos, 10, true)) == 0xFF) { // auweia, es wurde kein Weg mehr gefunden // Evtl. neue Besatzer rufen static_cast<nobMilitary*>(attacked_goal)->NeedOccupyingTroops(0xFF); // Nach Hause gehen ReturnHomeMissionAttacking(); } else StartWalking(dir); } }
void nofAttacker::Walked() { ExpelEnemies(); // Was bestimmtes machen, je nachdem welchen Status wir gerade haben switch(state) { default: nofActiveSoldier::Walked(); break; case STATE_ATTACKING_WALKINGTOGOAL: { MissAttackingWalk(); } break; case STATE_ATTACKING_ATTACKINGFLAG: { // Ist evtl. das Zielgebäude zerstört? if(!attacked_goal) { // Nach Hause gehen ReturnHomeMissionAttacking(); return; } MapPoint flagPos = attacked_goal->GetFlag()->GetPos(); //assert(enemy->GetGOT() == GOT_NOF_DEFENDER); // Are we at the flag? nofDefender* defender = NULL; // Look for defenders at this position const std::list<noBase*>& figures = gwg->GetFigures(flagPos); for(std::list<noBase*>::const_iterator it = figures.begin(); it != figures.end(); ++it) { if((*it)->GetGOT() == GOT_NOF_DEFENDER) { // Is the defender waiting at the flag? // (could be wandering around or something) if(static_cast<nofDefender*>(*it)->IsWaitingAtFlag()) { defender = static_cast<nofDefender*>(*it); } } } if(pos == flagPos) { if(defender) { // Start fight with the defender gwg->AddFigure(new noFighting(this, defender), pos); // Set the appropriate states state = STATE_ATTACKING_FIGHTINGVSDEFENDER; defender->FightStarted(); } else // No defender at the flag? // -> Order new defenders or capture the building ContinueAtFlag(); } else { if( (dir = gwg->FindHumanPath(pos, flagPos, 5, true)) == 0xFF) { // es wurde kein Weg mehr gefunden --> neues Plätzchen suchen und warten state = STATE_ATTACKING_WALKINGTOGOAL; MissAttackingWalk(); // der Verteidiger muss darüber informiert werden if(defender) defender->AttackerArrested(); } else { // Hinlaufen StartWalking(dir); } } } break; case STATE_ATTACKING_CAPTURINGFIRST: { // Ist evtl. das Zielgebäude zerstört? if(!attacked_goal) { // Nach Hause gehen ReturnHomeMissionAttacking(); return; } // Wenn schon welche drin sind, ist wieder ein feindlicher reingegangen if(attacked_goal->DefendersAvailable()) { // Wieder rausgehen, Platz reservieren if(attacked_goal->GetGOT() == GOT_NOB_MILITARY) static_cast<nobMilitary*>(attacked_goal)->StopCapturing(); state = STATE_ATTACKING_WALKINGTOGOAL; StartWalking(4); return; } else { // Ist das Gebäude ein "normales Militärgebäude", das wir da erobert haben? if(attacked_goal->GetBuildingType() >= BLD_BARRACKS && attacked_goal->GetBuildingType() <= BLD_FORTRESS) { // Meinem Heimatgebäude Bescheid sagen, dass ich nicht mehr komme (falls es noch eins gibt) if(building) building->SoldierLost(this); // Ggf. Schiff Bescheid sagen (Schiffs-Angreifer) if(ship_obj_id) CancelAtShip(); // Gebäude einnehmen static_cast<nobMilitary*>(attacked_goal)->Capture(player); // Bin nun kein Angreifer mehr attacked_goal->UnlinkAggressor(this); // Das ist nun mein neues zu Hause building = attacked_goal; // mich zum Gebäude hinzufügen und von der Karte entfernen attacked_goal->AddActiveSoldier(this); gwg->RemoveFigure(this, pos); // ggf. weitere Soldaten rufen, damit das Gebäude voll wird static_cast<nobMilitary*>(attacked_goal)->NeedOccupyingTroops(player); } // oder ein Hauptquartier oder Hafen? else { // Inform the owner of the building if(GAMECLIENT.GetPlayerID() == attacked_goal->GetPlayer()) { if(attacked_goal->GetGOT() == GOT_NOB_HQ) GAMECLIENT.SendPostMessage(new ImagePostMsgWithLocation(_("Our headquarters was destroyed!"), PMC_MILITARY, pos, attacked_goal->GetBuildingType(), attacked_goal->GetNation())); else GAMECLIENT.SendPostMessage(new ImagePostMsgWithLocation(_("This harbor building was destroyed"), PMC_MILITARY, pos, attacked_goal->GetBuildingType(), attacked_goal->GetNation())); } // abreißen nobBaseMilitary* tmp_goal = attacked_goal; // attacked_goal wird evtl auf 0 gesetzt! tmp_goal->Destroy(); delete tmp_goal; attacked_goal = NULL; ReturnHomeMissionAttacking(); } } } break; case STATE_ATTACKING_CAPTURINGNEXT: { CapturingWalking(); } break; case STATE_SEAATTACKING_GOTOHARBOR: // geht von seinem Heimatmilitärgebäude zum Starthafen { // Gucken, ob der Abflughafen auch noch steht und sich in unserer Hand befindet bool valid_harbor = true; noBase* hb = gwg->GetNO(harborPos); if(hb->GetGOT() != GOT_NOB_HARBORBUILDING) valid_harbor = false; else if(static_cast<nobHarborBuilding*>(hb)->GetPlayer() != player) valid_harbor = false; // Nicht mehr oder das angegriffene Gebäude kaputt? Dann müssen wir die ganze Aktion abbrechen if(!valid_harbor || !attacked_goal) { // Dann gehen wir halt wieder nach Hause ReturnHomeMissionAttacking(); return; } // Sind wir schon da? if(pos == harborPos) { // Uns zum Hafen hinzufügen state = STATE_SEAATTACKING_WAITINHARBOR; gwg->RemoveFigure(this, pos); gwg->GetSpecObj<nobHarborBuilding>(pos)->AddSeaAttacker(this); return; } // Erstmal Flagge ansteuern MapPoint harborFlagPos = gwg->GetNeighbour(harborPos, 4); // Wenn wir an der Flagge bereits sind, in den Hafen eintreten if(pos == harborFlagPos) StartWalking(1); else { // Weg zum Hafen suchen unsigned char dir = gwg->FindHumanPath(pos, harborFlagPos, MAX_ATTACKING_RUN_DISTANCE, false, NULL); if(dir == 0xff) { // Kein Weg gefunden? Dann auch abbrechen! ReturnHomeMissionAttacking(); return; } // Und schön weiterlaufen StartWalking(dir); } } break; case STATE_SEAATTACKING_WAITINHARBOR: // wartet im Hafen auf das ankommende Schiff { } break; case STATE_SEAATTACKING_ONSHIP: // befindet sich auf dem Schiff auf dem Weg zum Zielpunkt { // Auweia, das darf nicht passieren assert(false); } break; case STATE_SEAATTACKING_RETURNTOSHIP: // befindet sich an der Zielposition auf dem Weg zurück zum Schiff { HandleState_SeaAttack_ReturnToShip(); } break; } }