So, jetzt habe ich folgendes:
Ich bekomme folgenden Stack:
Code:
template <class T>
T* FFreeListTrashArray<T>::getAt(int iID) const
{
int iIndex;
if ((iID == FFreeList::INVALID_INDEX) || (m_pArray == NULL))
{
return NULL;
}
iIndex = (iID & FLTA_INDEX_MASK);
assert(iIndex >= 0);
if ((iIndex <= m_iLastIndex) &&
(m_pArray[iIndex].pData != NULL))
{
if (((iID & FLTA_ID_MASK) == 0) || (m_pArray[iIndex].pData->getID() == iID))
{
return m_pArray[iIndex].pData;
}
}
return NULL;
}
In der roten Zeile eine unbehandelte Ausnahme
iID = 385035 (auch Zeile 2, sowie "unit" in Zeile 3)
iIndex =11
iLastIndex = 39
Zeile 2:
Code:
CvUnit* CvPlayer::getUnit(int iID) const
{
return (m_units.getAt(iID));
}
Zeile 3:
Code:
CvUnit* getUnit(IDInfo unit)
{
if ((unit.eOwner >= 0) && unit.eOwner < MAX_PLAYERS)
{
return (GET_PLAYER((PlayerTypes)unit.eOwner).getUnit(unit.iID));
}
return NULL;
}
eOwner = 5
Zeile 4:
Code:
CvUnit* CvUnit::getTransportUnit() const
{
return getUnit(m_transportUnit);
}
m_transportUnit = siehe ID
Zeile 5:
Code:
bool CvUnit::isCargo() const
{
return (getTransportUnit() != NULL);
}
Zeile 6:
Code:
bool CvUnit::isInvisible(TeamTypes eTeam, bool bDebug, bool bCheckCargo) const
{
if (bDebug && GC.getGameINLINE().isDebugMode())
{
return false;
}
if (getTeam() == eTeam)
{
return false;
}
if (alwaysInvisible())
{
return true;
}
if (bCheckCargo && isCargo())
{
return true;
}
if (getInvisibleType() == NO_INVISIBLE)
{
return false;
}
return !(plot()->isInvisibleVisible(eTeam, getInvisibleType()));
}
eTeam = 0, check Cargo = true
Code:
bool CvUnit::canCoexistWithEnemyUnit(TeamTypes eTeam) const
{
if (NO_TEAM == eTeam)
{
if(alwaysInvisible())
{
return true;
}
return false;
}
if(isInvisible(eTeam, false))
{
return true;
}
return false;
}
eTeam = 0
Code:
bool PUF_isEnemy(const CvUnit* pUnit, int iData1, int iData2)
{
FAssertMsg(iData1 != -1, "Invalid data argument, should be >= 0");
FAssertMsg(iData2 != -1, "Invalid data argument, should be >= 0");
TeamTypes eOtherTeam = GET_PLAYER((PlayerTypes)iData1).getTeam();
TeamTypes eOurTeam = GET_PLAYER(pUnit->getCombatOwner(eOtherTeam, pUnit->plot())).getTeam();
if (pUnit->canCoexistWithEnemyUnit(eOtherTeam))
{
return false;
}
return (iData2 ? eOtherTeam != eOurTeam : atWar(eOtherTeam, eOurTeam));
}
eOurTeam = 5
eOtherTeam = 0
iData1, iData2 = 0
pUnit ist Unitclass 29
Code:
CvUnit* CvPlot::plotCheck(ConstPlotUnitFunc funcA, int iData1A, int iData2A, PlayerTypes eOwner, TeamTypes eTeam, ConstPlotUnitFunc funcB, int iData1B, int iData2B) const
{
CLLNode<IDInfo>* pUnitNode;
CvUnit* pLoopUnit;
pUnitNode = headUnitNode();
while (pUnitNode != NULL)
{
pLoopUnit = ::getUnit(pUnitNode->m_data);
pUnitNode = nextUnitNode(pUnitNode);
if ((eOwner == NO_PLAYER) || (pLoopUnit->getOwnerINLINE() == eOwner))
{
if ((eTeam == NO_TEAM) || (pLoopUnit->getTeam() == eTeam))
{
if (funcA(pLoopUnit, iData1A, iData2A))
{
if ((funcB == NULL) || funcB(pLoopUnit, iData1B, iData2B))
{
return pLoopUnit;
}
}
}
}
}
return NULL;
}
eTeam und eOwner sind hier -1 
Code:
bool CvPlot::isVisibleEnemyUnit(const CvUnit* pUnit) const
{
return (plotCheck(PUF_isEnemy, pUnit->getOwnerINLINE(), pUnit->isAlwaysHostile(this), NO_PLAYER, NO_TEAM, PUF_isVisible, pUnit->getOwnerINLINE()) != NULL);
}
Code:
bool CvPlot::isFriendlyCity(const CvUnit& kUnit, bool bCheckImprovement) const
{
if (!isCity(bCheckImprovement, kUnit.getTeam()))
{
return false;
}
if (isVisibleEnemyUnit(&kUnit))
{
return false;
}
TeamTypes ePlotTeam = getTeam();
if (NO_TEAM != ePlotTeam)
{
if (kUnit.isEnemy(ePlotTeam))
{
return false;
}
TeamTypes eTeam = GET_PLAYER(kUnit.getCombatOwner(ePlotTeam, this)).getTeam();
if (eTeam == ePlotTeam)
{
return true;
}
if (GET_TEAM(eTeam).isOpenBorders(ePlotTeam))
{
return true;
}
if (GET_TEAM(ePlotTeam).isVassal(eTeam))
{
return true;
}
}
return false;
}
Code:
bool CvUnit::canMoveInto(const CvPlot* pPlot, bool bAttack, bool bDeclareWar, bool bIgnoreLoad) const
{
PROFILE_FUNC();
FAssertMsg(pPlot != NULL, "Plot is not assigned a valid value");
if (atPlot(pPlot))
{
return false;
}
if (pPlot->isImpassable())
{
if (!canMoveImpassable())
{
return false;
}
}
// Cannot move around in unrevealed land freely
if (m_pUnitInfo->isNoRevealMap() && willRevealByMove(pPlot))
{
return false;
}
if (GC.getUSE_SPIES_NO_ENTER_BORDERS())
{
if (isSpy() && NO_PLAYER != pPlot->getOwnerINLINE())
{
if (!GET_PLAYER(getOwnerINLINE()).canSpiesEnterBorders(pPlot->getOwnerINLINE()))
{
return false;
}
}
}
CvArea *pPlotArea = pPlot->area();
TeamTypes ePlotTeam = pPlot->getTeam();
bool bCanEnterArea = canEnterArea(ePlotTeam, pPlotArea);
if (bCanEnterArea)
{
if (pPlot->getFeatureType() != NO_FEATURE)
{
if (m_pUnitInfo->getFeatureImpassable(pPlot->getFeatureType()))
{
TechTypes eTech = (TechTypes)m_pUnitInfo->getFeaturePassableTech(pPlot->getFeatureType());
if (NO_TECH == eTech || !GET_TEAM(getTeam()).isHasTech(eTech))
{
if (DOMAIN_SEA != getDomainType() || pPlot->getTeam() != getTeam()) // sea units can enter impassable in own cultural borders
{
return false;
}
}
}
}
/************************************************************************************************/
/* UNOFFICIAL_PATCH 09/17/09 TC01 & jdog5000 */
/* */
/* Bugfix */
/************************************************************************************************/
/* original bts code
else
*/
// always check terrain also
/************************************************************************************************/
/* UNOFFICIAL_PATCH END */
/************************************************************************************************/
{
//Korrektur Terrain Impassable Kathy: Passable bei Städten
if (pPlot->isFriendlyCity(*this, true) == false )
{
//Korrektur Terrain Impassable Kathy: Passable bei Städten
if (m_pUnitInfo->getTerrainImpassable(pPlot->getTerrainType()))
{
TechTypes eTech = (TechTypes)m_pUnitInfo->getTerrainPassableTech(pPlot->getTerrainType());
if (NO_TECH == eTech || !GET_TEAM(getTeam()).isHasTech(eTech))
{
if (DOMAIN_SEA != getDomainType() || pPlot->getTeam() != getTeam()) // sea units can enter impassable in own cultural borders
{
if (bIgnoreLoad || !canLoad(pPlot))
{
return false;
}
}
}
}
}
}
}
Da taucht zum ersten mal eine Änderung von mit auf. Die besagt meiner Meinung nach nur, dass die TerrainImpassable-Funktion für befreundete Städte ausgeschaltet ist. Bautrupps können dann ohne die Technologie "Packtiere" ein Wüstenstädte reingehen.
Code:
bool CvUnit::jumpToNearestValidPlot()
{
CvCity* pNearestCity;
CvPlot* pLoopPlot;
CvPlot* pBestPlot;
int iValue;
int iBestValue;
int iI;
FAssertMsg(!isAttacking(), "isAttacking did not return false as expected");
FAssertMsg(!isFighting(), "isFighting did not return false as expected");
pNearestCity = GC.getMapINLINE().findCity(getX_INLINE(), getY_INLINE(), getOwnerINLINE());
iBestValue = MAX_INT;
pBestPlot = NULL;
for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
{
pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
if (pLoopPlot->isValidDomainForLocation(*this))
{
if (canMoveInto(pLoopPlot))
{
if (canEnterArea(pLoopPlot->getTeam(), pLoopPlot->area()) && !isEnemy(pLoopPlot->getTeam(), pLoopPlot))
{
FAssertMsg(!atPlot(pLoopPlot), "atPlot(pLoopPlot) did not return false as expected");
if ((getDomainType() != DOMAIN_AIR) || pLoopPlot->isFriendlyCity(*this, true))
{
if (pLoopPlot->isRevealed(getTeam(), false))
{
iValue = (plotDistance(getX_INLINE(), getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) * 2);
if (pNearestCity != NULL)
{
iValue += plotDistance(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE());
}
if (getDomainType() == DOMAIN_SEA && !plot()->isWater())
{
if (!pLoopPlot->isWater() || !pLoopPlot->isAdjacentToArea(area()))
{
iValue *= 3;
}
}
else
{
if (pLoopPlot->area() != area())
{
iValue *= 3;
}
}
if (iValue < iBestValue)
{
iBestValue = iValue;
pBestPlot = pLoopPlot;
}
}
}
}
}
}
}
bool bValid = true;
if (pBestPlot != NULL)
{
setXY(pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE());
}
else
{
bValid = jumpToNearestValidPlot();
}
return bValid;
}
Darunter wird scheinbar unendlich oft aufgerufen:
Code:
bool CvUnit::jumpToNearestValidPlot()
{
CvCity* pNearestCity;
CvPlot* pLoopPlot;
CvPlot* pBestPlot;
int iValue;
int iBestValue;
int iI;
FAssertMsg(!isAttacking(), "isAttacking did not return false as expected");
FAssertMsg(!isFighting(), "isFighting did not return false as expected");
pNearestCity = GC.getMapINLINE().findCity(getX_INLINE(), getY_INLINE(), getOwnerINLINE());
iBestValue = MAX_INT;
pBestPlot = NULL;
for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
{
pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
if (pLoopPlot->isValidDomainForLocation(*this))
{
if (canMoveInto(pLoopPlot))
{
if (canEnterArea(pLoopPlot->getTeam(), pLoopPlot->area()) && !isEnemy(pLoopPlot->getTeam(), pLoopPlot))
{
FAssertMsg(!atPlot(pLoopPlot), "atPlot(pLoopPlot) did not return false as expected");
if ((getDomainType() != DOMAIN_AIR) || pLoopPlot->isFriendlyCity(*this, true))
{
if (pLoopPlot->isRevealed(getTeam(), false))
{
iValue = (plotDistance(getX_INLINE(), getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) * 2);
if (pNearestCity != NULL)
{
iValue += plotDistance(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE());
}
if (getDomainType() == DOMAIN_SEA && !plot()->isWater())
{
if (!pLoopPlot->isWater() || !pLoopPlot->isAdjacentToArea(area()))
{
iValue *= 3;
}
}
else
{
if (pLoopPlot->area() != area())
{
iValue *= 3;
}
}
if (iValue < iBestValue)
{
iBestValue = iValue;
pBestPlot = pLoopPlot;
}
}
}
}
}
}
}
bool bValid = true;
if (pBestPlot != NULL)
{
setXY(pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE());
}
else
{
bValid = jumpToNearestValidPlot();
}
return bValid;
}
Verstehe ich das richtig, dass "jumpToNearestValidPlot" in der Funktion selbst aufgerufen wird? Das klingt für mich erst einmal komisch, weil dadurch tatsächlich nicht sichergestellt wird, dass die Schleife terminiert.