Also den Text-Parameter hast du in den Aufrufen noch drin. Den würd ich auch mal mit Inhalt befüllen und loggen, dann sehen wir nämlich im Log gleich, welcher Aufruf OOS verursacht.
Bzw. würd ich tatsächlich nochmal myRandom als Wrapper für's SorenRandNum nehmen und keinen eigenen Seed setzen. Wenn das kill nur lokal ist, dürften wir den Übeltäter ja an anderer Stelle gefunden haben. Klar, dass dann alle weiteren Entscheidungen OOS sind, wenn ne Einheit mal da ist und mal nicht.
@ruciv: wie kill ich denn ne Einheit richtig? Ich seh in der DLL immer nur pUnit->kill(false)
€: hier wird doch das ganze Gerappel mit EventReporter und so abgehandelt?
PHP-Code:
void CvUnit::kill(bool bDelay, PlayerTypes ePlayer)
{
PROFILE_FUNC();
CLLNode<IDInfo>* pUnitNode;
CvUnit* pTransportUnit;
CvUnit* pLoopUnit;
CvPlot* pPlot;
CvWString szBuffer;
PlayerTypes eOwner;
PlayerTypes eCapturingPlayer;
UnitTypes eCaptureUnitType;
pPlot = plot();
FAssertMsg(pPlot != NULL, "Plot is not assigned a valid value");
static std::vector<IDInfo> oldUnits;
oldUnits.clear();
pUnitNode = pPlot->headUnitNode();
while (pUnitNode != NULL)
{
oldUnits.push_back(pUnitNode->m_data);
pUnitNode = pPlot->nextUnitNode(pUnitNode);
}
for (uint i = 0; i < oldUnits.size(); i++)
{
pLoopUnit = ::getUnit(oldUnits[i]);
if (pLoopUnit != NULL)
{
if (pLoopUnit->getTransportUnit() == this)
{
//save old units because kill will clear the static list
std::vector<IDInfo> tempUnits = oldUnits;
if (pPlot->isValidDomainForLocation(*pLoopUnit))
{
pLoopUnit->setCapturingPlayer(NO_PLAYER);
}
pLoopUnit->kill(false, ePlayer);
oldUnits = tempUnits;
}
}
}
if (ePlayer != NO_PLAYER)
{
CvEventReporter::getInstance().unitKilled(this, ePlayer);
if (NO_UNIT != getLeaderUnitType())
{
for (int iI = 0; iI < MAX_PLAYERS; iI++)
{
if (GET_PLAYER((PlayerTypes)iI).isAlive())
{
szBuffer = gDLL->getText("TXT_KEY_MISC_GENERAL_KILLED", getNameKey());
gDLL->getInterfaceIFace()->addMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, GC.getEraInfo(GC.getGameINLINE().getCurrentEra()).getAudioUnitDefeatScript(), MESSAGE_TYPE_MAJOR_EVENT);
}
}
}
}
if (bDelay)
{
startDelayedDeath();
return;
}
if (isMadeAttack() && nukeRange() != -1)
{
CvPlot* pTarget = getAttackPlot();
if (pTarget)
{
pTarget->nukeExplosion(nukeRange(), this);
setAttackPlot(NULL, false);
}
}
finishMoves();
if (IsSelected())
{
if (gDLL->getInterfaceIFace()->getLengthSelectionList() == 1)
{
if (!(gDLL->getInterfaceIFace()->isFocused()) && !(gDLL->getInterfaceIFace()->isCitySelection()) && !(gDLL->getInterfaceIFace()->isDiploOrPopupWaiting()))
{
GC.getGameINLINE().updateSelectionList();
}
if (IsSelected())
{
gDLL->getInterfaceIFace()->setCycleSelectionCounter(1);
}
else
{
gDLL->getInterfaceIFace()->setDirty(SelectionCamera_DIRTY_BIT, true);
}
}
}
gDLL->getInterfaceIFace()->removeFromSelectionList(this);
// XXX this is NOT a hack, without it, the game crashes.
gDLL->getEntityIFace()->RemoveUnitFromBattle(this);
FAssertMsg(!isCombat(), "isCombat did not return false as expected");
pTransportUnit = getTransportUnit();
if (pTransportUnit != NULL)
{
setTransportUnit(NULL);
}
setReconPlot(NULL);
setBlockading(false);
FAssertMsg(getAttackPlot() == NULL, "The current unit instance's attack plot is expected to be NULL");
FAssertMsg(getCombatUnit() == NULL, "The current unit instance's combat unit is expected to be NULL");
GET_TEAM(getTeam()).changeUnitClassCount((UnitClassTypes)m_pUnitInfo->getUnitClassType(), -1);
GET_PLAYER(getOwnerINLINE()).changeUnitClassCount((UnitClassTypes)m_pUnitInfo->getUnitClassType(), -1);
GET_PLAYER(getOwnerINLINE()).changeExtraUnitCost(-(m_pUnitInfo->getExtraCost()));
if (m_pUnitInfo->getNukeRange() != -1)
{
GET_PLAYER(getOwnerINLINE()).changeNumNukeUnits(-1);
}
if (m_pUnitInfo->isMilitarySupport())
{
GET_PLAYER(getOwnerINLINE()).changeNumMilitaryUnits(-1);
}
GET_PLAYER(getOwnerINLINE()).changeAssets(-(m_pUnitInfo->getAssetValue()));
GET_PLAYER(getOwnerINLINE()).changePower(-(m_pUnitInfo->getPowerValue()));
GET_PLAYER(getOwnerINLINE()).AI_changeNumAIUnits(AI_getUnitAIType(), -1);
eOwner = getOwnerINLINE();
eCapturingPlayer = getCapturingPlayer();
eCaptureUnitType = ((eCapturingPlayer != NO_PLAYER) ? getCaptureUnitType(GET_PLAYER(eCapturingPlayer).getCivilizationType()) : NO_UNIT);
setXY(INVALID_PLOT_COORD, INVALID_PLOT_COORD, true);
joinGroup(NULL, false, false);
CvEventReporter::getInstance().unitLost(this);
GET_PLAYER(getOwnerINLINE()).deleteUnit(getID());
if ((eCapturingPlayer != NO_PLAYER) && (eCaptureUnitType != NO_UNIT) && !(GET_PLAYER(eCapturingPlayer).isBarbarian()))
{
if (GET_PLAYER(eCapturingPlayer).isHuman() || GET_PLAYER(eCapturingPlayer).AI_captureUnit(eCaptureUnitType, pPlot) || 0 == GC.getDefineINT("AI_CAN_DISBAND_UNITS"))
{
CvUnit* pkCapturedUnit = GET_PLAYER(eCapturingPlayer).initUnit(eCaptureUnitType, pPlot->getX_INLINE(), pPlot->getY_INLINE());
if (pkCapturedUnit != NULL)
{
szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_CAPTURED_UNIT", GC.getUnitInfo(eCaptureUnitType).getTextKeyWide());
gDLL->getInterfaceIFace()->addMessage(eCapturingPlayer, true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_UNITCAPTURE", MESSAGE_TYPE_INFO, pkCapturedUnit->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());
// Add a captured mission
CvMissionDefinition kMission;
kMission.setMissionTime(GC.getMissionInfo(MISSION_CAPTURED).getTime() * gDLL->getSecsPerTurn());
kMission.setUnit(BATTLE_UNIT_ATTACKER, pkCapturedUnit);
kMission.setUnit(BATTLE_UNIT_DEFENDER, NULL);
kMission.setPlot(pPlot);
kMission.setMissionType(MISSION_CAPTURED);
gDLL->getEntityIFace()->AddMission(&kMission);
pkCapturedUnit->finishMoves();
if (!GET_PLAYER(eCapturingPlayer).isHuman())
{
CvPlot* pPlot = pkCapturedUnit->plot();
if (pPlot && !pPlot->isCity(false))
{
if (GET_PLAYER(eCapturingPlayer).AI_getPlotDanger(pPlot) && GC.getDefineINT("AI_CAN_DISBAND_UNITS"))
{
pkCapturedUnit->kill(false);
}
}
}
}
}
}
}
€^2: teilweise hatten wir COMMAND_DELETE, das ist vielleicht etwas sicherer, weil vorher noch überprüft wird, ob die Einheit grad in nem Kampf ist