Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 71 additions & 51 deletions src/Ext/Team/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1612,7 +1612,17 @@ void FakeTeamClass::_Coordinate_Do(ScriptActionNode* pNode, CellStruct unused) {
&& ((Mission)value != Mission::Guard || i->GetCurrentMission() != Mission::Unload))
{
i->ArchiveTarget = nullptr;
i->QueueMission((Mission)value,false);
// Integrated from Team_DoMission_Harvest hook (0x6EDA50):
// Harvest mission should use EnterIdleMode instead of direct mission queue
if ((Mission)value == Mission::Harvest)
{
i->EnterIdleMode(false, true);
}
else
{
i->QueueMission((Mission)value, false);
}

i->SetTarget(nullptr);
i->SetDestination(nullptr, true);
}
Expand Down Expand Up @@ -2049,6 +2059,9 @@ void FakeTeamClass::_AssignMissionTarget(AbstractClass* new_target)
if (new_target != this->QueuedFocus) {
FootClass* unit = this->FirstUnit;

// Only clear nav/tar if there was a previous mission target
// (pseudocode: the loop only runs when MissionTarget is non-null)
// But boss Otamaa removed it for a reason, so maybe it's needed to prevent unnecessary clearing when there was no previous target?
//if (this->QueuedFocus)
{
while (unit)
Expand Down Expand Up @@ -4452,9 +4465,28 @@ void FakeTeamClass::ExecuteTMissions(bool missionChanged)
}
case TeamMissionType::Wait_till_fully_loaded:
{
if (!this->FirstUnit)
// Pseudocode: loop through members. If any transport has room (MaxPassengers > Quantity),
// keep waiting (just return). If all transports are full or no members, advance.
FootClass* pMember = this->FirstUnit;
if (!pMember)
{
this->StepCompleted = true;
return;
}

while (pMember)
{
TechnoTypeClass* pType = GET_TECHNOTYPE(pMember);
// If this member is a transport and has room for more passengers, keep waiting
if (pType->Passengers > pMember->Passengers.NumPassengers)
{
return; // Still waiting for loading to complete
}
pMember = pMember->NextTeamMember;
}

// All transports are full (or no transports found)
this->StepCompleted = true;
return;
}
case TeamMissionType::Force_facing:
Expand Down Expand Up @@ -4533,32 +4565,14 @@ void FakeTeamClass::ExecuteTMissions(bool missionChanged)
}
case TeamMissionType::Delete_team_members:
{
FootClass* pCur = nullptr;
if (auto pFirst = this->FirstUnit)
// Pseudocode: unconditionally Limbo + UnInit each member
FootClass* pMember = this->FirstUnit;
while (pMember)
{
auto pNext = pFirst->NextTeamMember;
do
{

if (pFirst->Health > 0
&& pFirst->IsAlive
&& !pFirst->IsCrashing
&& !pFirst->IsSinking
&& !pFirst->InLimbo)
{
pFirst->Limbo();
pFirst->UnInit();
}

pCur = pNext;

if (pNext)
pNext = pNext->NextTeamMember;

pFirst = pCur;

}
while (pCur);
FootClass* pNext = pMember->NextTeamMember;
pMember->Limbo();
pMember->UnInit();
pMember = pNext;
}

this->StepCompleted = true;
Expand Down Expand Up @@ -4603,8 +4617,13 @@ void FakeTeamClass::ExecuteTMissions(bool missionChanged)
if (this->Zone)
{
CoordStruct place = this->Zone->GetCoords();
// Pseudocode: Z = MapClass::Get_Z_Pos(coords), then add bridge height if on bridge
place.Z = MapClass::Instance->GetZPos(&place);
auto pCell = MapClass::Instance->GetCellAt(place);
place.Z = pCell->ContainsBridgeEx() ? place.Z + CellClass::BridgeHeight : 0;
if (pCell->ContainsBridgeEx())
{
place.Z += CellClass::BridgeHeight;
}

TacticalClass::Instance->FocusOn(&place, node.Argument);
}
Expand All @@ -4614,33 +4633,30 @@ void FakeTeamClass::ExecuteTMissions(bool missionChanged)
}
case TeamMissionType::Self_destruct:
{
FootClass* pCur = nullptr;
if (auto pFirst = this->FirstUnit)
// Pseudocode: outer do-while loop repeats until no member was damaged in a pass.
// This ensures units that survive the first C4 hit get hit again.
//Debug::Log("[FakeTeam] %s: Self_destruct starting\n", this->Type->ID);
bool anyDamaged;
int passCount = 0;
do
{
auto pNext = pFirst->NextTeamMember;
do
anyDamaged = false;
passCount++;
for (FootClass* pMember = this->FirstUnit; pMember; pMember = pMember->NextTeamMember)
{
if (pFirst->Health > 0
&& pFirst->IsAlive
&& !pFirst->IsCrashing
&& !pFirst->IsSinking
&& !pFirst->InLimbo
)
if (pMember->Health > 0 && pMember->IsAlive && pMember->IsOnMap && !pMember->InLimbo)
{
int damage = pFirst->Health;
pFirst->ReceiveDamage(&damage, 0, RulesClass::Instance->C4Warhead, nullptr, true, false, nullptr);
int damage = pMember->Health;
pMember->ReceiveDamage(&damage, 0, RulesClass::Instance->C4Warhead, nullptr, true, false, nullptr);
anyDamaged = true;
}

pCur = pNext;

if (pNext)
pNext = pNext->NextTeamMember;

pFirst = pCur;

}
while (pCur);

if (!this->FirstUnit)
break;
}
while (anyDamaged);

this->StepCompleted = true;
return;
}
Expand All @@ -4658,9 +4674,13 @@ void FakeTeamClass::ExecuteTMissions(bool missionChanged)
}
case TeamMissionType::Reduce_tiberium:
{
if (this->FirstUnit)
// Pseudocode: iterate ALL team members and reduce tiberium at each location
for (FootClass* pMember = this->FirstUnit; pMember; pMember = pMember->NextTeamMember)
{
this->FirstUnit->GetCell()->ReduceTiberiumWithinCircularArea();
if (CellClass* pCell = pMember->GetCell())
{
pCell->ReduceTiberiumWithinCircularArea();
}
}

this->StepCompleted = true;
Expand Down
2 changes: 1 addition & 1 deletion src/Ext/WeaponType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ bool WeaponTypeExtData::LoadFromINI(CCINIClass* pINI, bool parseFailAddr)

bool WeaponTypeExtData::IsVeterancyInThreshold(TechnoClass* pTarget) const
{
return !EnumFunctions::CanTargetVeterancy(this->CanTargetVeterancy, pTarget);
return EnumFunctions::CanTargetVeterancy(this->CanTargetVeterancy, pTarget);
}

int WeaponTypeExtData::GetRangeWithModifiers(WeaponTypeClass* pThis, TechnoClass* pFirer, std::optional<int> fallback)
Expand Down
4 changes: 4 additions & 0 deletions src/Misc/Hooks.BugFixes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2664,6 +2664,10 @@ DEFINE_PATCH(0x42A7FA, 0x02);

// AStarClass::FindHierarchicalPath
// Replace sign-extend to zero-extend
// NOTE: These patches are inside the original Find_Path_Hierarchical (0x42C290) which is
// completely replaced by FakeAStarPathFinderClass::__Find_Path_Hierarchical via LJMP.
// They are dead code. The fix (using unsigned short for zone indices) is incorporated
// directly in the backported function.

// 42C34A: 0F BF 1C 70
// To avoid incorrect negative int index
Expand Down
Loading