Skip to content

Commit

Permalink
Fixed defect 220.
Browse files Browse the repository at this point in the history
- Air transporters were able to unload land units onto the sea surface.
- Air transporters were able to unload units on top of each other.
- Personnel carriers used too restrictive caution levels.
- Unified finish transport event handling in TaskTransport and
TaskAssistMove tasks.
- Renamed an API function.
  • Loading branch information
klei1984 committed Nov 10, 2024
1 parent 6954cb8 commit 12a95e1
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 81 deletions.
21 changes: 20 additions & 1 deletion src/paths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ static void Paths_FinishMove(UnitInfo* unit);
static void Paths_TakeStep(UnitInfo* unit, int32_t cost);
static bool Paths_CalculateStep(UnitInfo* unit, int32_t cost, bool is_diagonal_step);

SmartObjectArray<Point> Paths_SiteReservations;

static uint16_t Paths_AirPath_TypeIndex;
static RegisterClass Paths_AirPath_ClassRegister("AirPath", &Paths_AirPath_TypeIndex, &AirPath::Allocate);

Expand Down Expand Up @@ -586,7 +588,8 @@ int32_t GroundPath::GetMovementCost(UnitInfo* unit) {
grid_x += step->x;
grid_y += step->y;

step_cost = Access_IsAccessible(unit->GetUnitType(), unit->team, grid_x, grid_y, AccessModifier_NoModifiers);
step_cost =
Access_IsAccessible(unit->GetUnitType(), unit->team, grid_x, grid_y, AccessModifier_NoModifiers);

if (step->x && step->y) {
step_cost = (step_cost * 3) / 2;
Expand Down Expand Up @@ -1626,3 +1629,19 @@ bool Paths_IsOccupied(int32_t grid_x, int32_t grid_y, int32_t angle, int32_t tea

return false;
}

void Paths_ReserveSite(const Point site) noexcept { Paths_SiteReservations.PushBack(&site); }

void Paths_RemoveSiteReservation(const Point site) noexcept {
const int32_t position{Paths_SiteReservations->Find(&site)};

SDL_assert(position != -1);

if (position != -1) {
Paths_SiteReservations.Remove(position);
}
}

void Paths_ClearSiteReservations() noexcept { Paths_SiteReservations.Clear(); }

[[nodiscard]] bool Paths_IsSiteReserved(const Point site) noexcept { return Paths_SiteReservations->Find(&site) != -1; }
5 changes: 5 additions & 0 deletions src/paths.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ void Paths_DrawMarker(WindowInfo* window, int32_t angle, int32_t grid_x, int32_t
void Paths_DrawShots(WindowInfo* window, int32_t grid_x, int32_t grid_y, int32_t shots);
bool Paths_IsOccupied(int32_t grid_x, int32_t grid_y, int32_t angle, int32_t team);

void Paths_ReserveSite(const Point site) noexcept;
void Paths_RemoveSiteReservation(const Point site) noexcept;
void Paths_ClearSiteReservations() noexcept;
[[nodiscard]] bool Paths_IsSiteReserved(const Point site) noexcept;

extern const Point Paths_8DirPointsArray[8];
extern const int16_t Paths_8DirPointsArrayX[8];
extern const int16_t Paths_8DirPointsArrayY[8];
Expand Down
5 changes: 4 additions & 1 deletion src/paths_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,10 @@ void PathsManager_PushFront(PathRequest &object) { PathsManager_Instance.PushFro

void PathsManager_EvaluateTiles() { PathsManager_Instance.EvaluateTiles(); }

void PathsManager_Clear() { PathsManager_Instance.Clear(); }
void PathsManager_Clear() {
PathsManager_Instance.Clear();
Paths_ClearSiteReservations();
}

bool PathsManager_HasRequest(UnitInfo *unit) { return PathsManager_Instance.HasRequest(unit); }

Expand Down
23 changes: 1 addition & 22 deletions src/taskassistmove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,28 +67,7 @@ void TaskAssistMove::RequestTransport(UnitInfo* transporter, UnitInfo* client) {
}

void TaskAssistMove::CompleteTransport(UnitInfo* transporter, UnitInfo* client, Point site) {
if (GameManager_IsActiveTurn(team)) {
if (Access_GetTeamUnit(site.x, site.y, team, MOBILE_SEA_UNIT | MOBILE_LAND_UNIT)) {
SmartPointer<Zone> zone = new (std::nothrow) Zone(client, this);

zone->Add(&site);

AiPlayer_Teams[team].ClearZone(&*zone);

} else {
transporter->target_grid_x = site.x;
transporter->target_grid_y = site.y;

transporter->SetParent(client);

if (transporter->GetUnitType() == AIRTRANS) {
UnitsManager_SetNewOrder(transporter, ORDER_UNLOAD, ORDER_STATE_INIT);

} else {
UnitsManager_SetNewOrder(transporter, ORDER_ACTIVATE, ORDER_STATE_EXECUTING_ORDER);
}
}
}
TaskTransport_FinishTransport(this, transporter, client, site);
}

bool TaskAssistMove::Task_vfunc1(UnitInfo& unit) { return unit.storage == 0; }
Expand Down
109 changes: 53 additions & 56 deletions src/tasktransport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,30 +489,24 @@ bool TaskTransport::Execute(UnitInfo& unit) {
result = true;

} else if (ChooseNewTask()) {
int32_t distance;

if (transporter_unit_type == AIRTRANS) {
distance = 0;

} else {
distance = 3;
}
int32_t distance = (transporter_unit_type == AIRTRANS) ? 0 : 3;

if (task_move->GetPassenger()->GetOrder() == ORDER_IDLE) {
if (unit.storage > 0) {
Point destination = task_move->GetDestination();
const Point destination = task_move->GetDestination();

if (destination.x >= 0) {
if (TaskManager_GetDistance(Point(unit_transporter->grid_x, unit_transporter->grid_y),
task_move->GetDestination()) > distance) {
SmartPointer<Task> move = new (std::nothrow)
TaskMove(&*unit_transporter, this, distance, CAUTION_LEVEL_AVOID_ALL_DAMAGE,
task_move->GetDestination(), &MoveFinishedCallback2);

TaskManager.AppendTask(*move);
if (destination.x >= 0 && destination.y >= 0) {
if (Access_GetDistance(unit_transporter.Get(), destination) <= distance) {
UnloadUnit(task_move->GetPassenger());

} else {
UnloadUnit(task_move->GetPassenger());
SmartPointer<Task> move = new (std::nothrow) TaskMove(
&*unit_transporter, this, distance,
unit_transporter->GetUnitType() == CLNTRANS ? CAUTION_LEVEL_AVOID_NEXT_TURNS_FIRE
: CAUTION_LEVEL_AVOID_ALL_DAMAGE,
destination, &MoveFinishedCallback2);

TaskManager.AppendTask(*move);
}

result = true;
Expand Down Expand Up @@ -706,6 +700,45 @@ void TaskTransport_MoveFinishedCallback(Task* task, UnitInfo* unit, char result)
}
}

void TaskTransport_FinishTransport(Task* const task, UnitInfo* const transporter, UnitInfo* const client, Point site) {
if (GameManager_IsActiveTurn(task->GetTeam())) {
AiLog log("TaskAssistMove: Unload %s.", UnitsManager_BaseUnits[client->GetUnitType()].singular_name);

auto unit_in_the_way = Access_GetTeamUnit(site.x, site.y, task->GetTeam(), MOBILE_SEA_UNIT | MOBILE_LAND_UNIT);

if (unit_in_the_way) {
if (Task_IsReadyToTakeOrders(unit_in_the_way)) {
SmartPointer<Zone> zone = new (std::nothrow) Zone(client, task);

log.Log("Must clear landing zone first.");

zone->Add(&site);

AiPlayer_Teams[task->GetTeam()].ClearZone(zone.Get());
}

} else if (Access_IsAccessible(client->GetUnitType(), task->GetTeam(), site.x, site.y,
AccessModifier_SameClassBlocks)) {
transporter->target_grid_x = site.x;
transporter->target_grid_y = site.y;

transporter->SetParent(client);

if (transporter->GetUnitType() == AIRTRANS) {
UnitsManager_SetNewOrder(transporter, ORDER_UNLOAD, ORDER_STATE_INIT);

} else {
UnitsManager_SetNewOrder(transporter, ORDER_ACTIVATE, ORDER_STATE_EXECUTING_ORDER);
}

} else {
SDL_assert(client->GetTask()->GetType() == TaskType_TaskMove);

dynamic_cast<TaskMove*>(client->GetTask())->SetDestination(Point(-1, -1));
}
}
}

bool TaskTransport::LoadUnit(UnitInfo* unit) {
bool result;

Expand Down Expand Up @@ -776,44 +809,8 @@ bool TaskTransport::LoadUnit(UnitInfo* unit) {
return result;
}

void TaskTransport::UnloadUnit(UnitInfo* unit) {
AiLog log("Transport: Unload %s.", UnitsManager_BaseUnits[unit->GetUnitType()].singular_name);

if (GameManager_IsActiveTurn(team)) {
Point destination = task_move->GetDestination();

if (destination.x >= 0 && unit_transporter == unit->GetParent()) {
UnitInfo* unit_in_the_way =
Access_GetTeamUnit(destination.x, destination.y, team, MOBILE_SEA_UNIT | MOBILE_LAND_UNIT);

if (unit_in_the_way) {
SmartPointer<Zone> zone = new (std::nothrow) Zone(unit, this);

log.Log("Must clear landing zone first.");

zone->Add(&destination);

if (Task_IsReadyToTakeOrders(unit_in_the_way)) {
AiPlayer_Teams[team].ClearZone(&*zone);
}

} else {
unit_transporter->target_grid_x = destination.x;
unit_transporter->target_grid_y = destination.y;

unit_transporter->SetParent(unit);

SDL_assert(GameManager_IsActiveTurn(team));

if (unit_transporter->GetUnitType() == AIRTRANS) {
UnitsManager_SetNewOrder(&*unit_transporter, ORDER_UNLOAD, ORDER_STATE_INIT);

} else {
UnitsManager_SetNewOrder(&*unit_transporter, ORDER_ACTIVATE, ORDER_STATE_EXECUTING_ORDER);
}
}
}
}
void TaskTransport::UnloadUnit(UnitInfo* client) {
TaskTransport_FinishTransport(this, unit_transporter.Get(), client, task_move->GetDestination());
}

ResourceID TaskTransport::GetTransporterType() const { return transporter_unit_type; }
1 change: 1 addition & 0 deletions src/tasktransport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,6 @@ class TaskTransport : public Task {

bool TaskTransport_Search(UnitInfo* transporter, UnitInfo* client, TransporterMap* map);
void TaskTransport_MoveFinishedCallback(Task* task, UnitInfo* unit, char result);
void TaskTransport_FinishTransport(Task* const task, UnitInfo* const transporter, UnitInfo* const client, Point site);

#endif /* TASKTRANSPORT_HPP */
9 changes: 8 additions & 1 deletion src/units_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4701,11 +4701,14 @@ void UnitsManager_ProcessOrderUnload(UnitInfo* unit) {
unit->moved = 0;
unit->SetOrderState(ORDER_STATE_UNLOADING_IN_PROGRESS);

if (Paths_IsOccupied(unit->grid_x, unit->grid_y, 0, unit->team)) {
const Point site{unit->grid_x, unit->grid_y};

if (Paths_IsSiteReserved(site) || Paths_IsOccupied(unit->grid_x, unit->grid_y, 0, unit->team)) {
unit->SetOrder(ORDER_AWAIT);
unit->SetOrderState(ORDER_STATE_EXECUTING_ORDER);

} else {
Paths_ReserveSite(site);
UnitsManager_ProgressUnloading(unit);
}
} break;
Expand Down Expand Up @@ -5934,6 +5937,10 @@ void UnitsManager_ProgressUnloading(UnitInfo* unit) {

unit->SetOrderState(ORDER_STATE_FINISH_UNLOADING);

const Point site{client->grid_x, client->grid_y};

Paths_RemoveSiteReservation(site);

if (GameManager_SelectedUnit == unit) {
GameManager_UpdateInfoDisplay(unit);
}
Expand Down

0 comments on commit 12a95e1

Please sign in to comment.