Hooks
static bool BeforeCvUnit_build(CvUnit* self, BuildTypes eBuild, bool& result);static void AfterCvUnit_build(CvUnit* self, BuildTypes eBuild, bool& result);static bool ReplaceCvUnit_build(bool (*original)(CvUnit*, BuildTypes), CvUnit* self, BuildTypes eBuild);CivRegisterBefore<CivHooks::CvUnit_build>(host, &BeforeCvUnit_build);CivRegisterAfter<CivHooks::CvUnit_build>(host, &AfterCvUnit_build);CivRegisterReplace<CivHooks::CvUnit_build>(host, &ReplaceCvUnit_build);
Code
10387// Returns true if build finished...10388bool CvUnit::build(BuildTypes eBuild)10389{10390 VALIDATE_OBJECT10391 bool bFinished;1039210393 CvAssertMsg(eBuild < GC.getNumBuildInfos(), "Invalid Build");10394 CvPlayer& kPlayer = GET_PLAYER(getOwner());1039510396 CvBuildInfo* pkBuildInfo = NULL;10397 if(eBuild != NO_BUILD)10398 {10399 pkBuildInfo = GC.getBuildInfo(eBuild);10400 }10401 CvPlot* pPlot = plot();1040210403 // Don't test Gold10404 if(!canBuild(pPlot, eBuild, false, false))10405 {10406 return false;10407 }1040810409 if(GC.getLogging() && GC.getAILogging())10410 {10411 if(pPlot->getBuildProgress(eBuild) == 0)10412 {10413 LogWorkerEvent(eBuild, true);10414 }10415 }1041610417 int iStartedYet = pPlot->getBuildProgress(eBuild);10418#if defined(MOD_BUGFIX_MINOR)10419 int iWorkRateFactor = 1;10420#endif1042110422 // if we are starting something new wipe out the old thing immediately10423 if(iStartedYet == 0)10424 {10425 ImprovementTypes eImprovement = NO_IMPROVEMENT;1042610427 if(pkBuildInfo)10428 {10429 eImprovement = (ImprovementTypes) pkBuildInfo->getImprovement();10430 }1043110432 if(eImprovement != NO_IMPROVEMENT)10433 {10434 if(pPlot->getImprovementType() != NO_IMPROVEMENT)10435 {10436 CvImprovementEntry *pkImprovementEntry = GC.getImprovementInfo(eImprovement);10437 if (!pkImprovementEntry || !pkImprovementEntry->IsRequiresImprovement())10438 {10439 pPlot->setImprovementType(NO_IMPROVEMENT);10440 }10441 }10442 }1044310444#if defined(MOD_BUGFIX_MINOR)10445 /*10446 * This appears to be a bug, in that we drop out of the if into an exact duplicate of the call below.10447 * However, this is so long established that if we fix it, we'll get howls of complaints from 999 out of 1000 players10448 * that build times have increased under some circumstances, or, more likely, "it's broken".10449 *10450 * The double call is only a problem if the build takes one turn, ie instantaneous.10451 * There are no standard builds where this is the case.10452 *10453 * The double call is also only an issue if you a) care about the BuildFinished event being duplicated or b)10454 * have set a maintenance cost on the improvement and are building it outside your territory, in which case you get charged twice10455 * but will only receive one refund if the improvement is destroyed or the territory captured.10456 *10457 * The simple solution is "don't do this!"10458 *10459 * The coding solution is to avoid the call and just double the workrate (to allow for the double call),10460 * dirty but a win-win solution!10461 */10462 iWorkRateFactor = 2;10463#else10464 // wipe out all build progress also10465 bFinished = pPlot->changeBuildProgress(eBuild, workRate(false), getOwner());10466#endif10467 }1046810469#if defined(MOD_BUGFIX_MINOR)10470 bFinished = pPlot->changeBuildProgress(eBuild, workRate(false) * iWorkRateFactor, getOwner());10471#else10472 bFinished = pPlot->changeBuildProgress(eBuild, workRate(false), getOwner());10473#endif1047410475#if defined(MOD_EVENTS_PLOT)10476 if (MOD_EVENTS_PLOT) {10477 GAMEEVENTINVOKE_HOOK(GAMEEVENT_PlayerBuilding, getOwner(), GetID(), getX(), getY(), eBuild, (iStartedYet == 0));10478 }10479#endif1048010481 finishMoves(); // needs to be at bottom because movesLeft() can affect workRate()...1048210483 if(bFinished)10484 {10485 // Update Resource info10486 if(pkBuildInfo)10487 {10488 ImprovementTypes eImprovement = NO_IMPROVEMENT;10489 RouteTypes eRoute = NO_ROUTE;1049010491 if(pkBuildInfo->getImprovement() != NO_IMPROVEMENT)10492 {10493 eImprovement = (ImprovementTypes) pkBuildInfo->getImprovement();1049410495 CvImprovementEntry* pkImprovementInfo = GC.getImprovementInfo(eImprovement);10496 if(pkImprovementInfo)10497 {10498 if (pkImprovementInfo->GetCultureBombRadius() > 0)10499 {10500 PerformCultureBomb(pkImprovementInfo->GetCultureBombRadius());10501 }10502 }10503 }10504#if defined(GLOBAL_ALPINE_PASSES)10505 // Can be both an improvement and a route10506 if(pkBuildInfo->getRoute() != NO_ROUTE)10507#else10508 else if(pkBuildInfo->getRoute() != NO_ROUTE)10509#endif10510 {10511 eRoute = (RouteTypes) pkBuildInfo->getRoute();10512 }1051310514 int iNumResource = 0;1051510516 // Update the amount of a Resource used up by popped Build10517 for(int iResourceLoop = 0; iResourceLoop < GC.getNumResourceInfos(); iResourceLoop++)10518 {10519 if(eImprovement != NO_IMPROVEMENT)10520 {10521 CvImprovementEntry* pkImprovementInfo = GC.getImprovementInfo(eImprovement);10522 if(pkImprovementInfo)10523 {10524 iNumResource = pkImprovementInfo->GetResourceQuantityRequirement(iResourceLoop);10525 }10526 }10527#if defined(GLOBAL_ALPINE_PASSES)10528 // Can be both an improvement and a route10529 if(eRoute != NO_ROUTE)10530#else10531 else if(eRoute != NO_ROUTE)10532#endif10533 {10534 CvRouteInfo* pkRouteInfo = GC.getRouteInfo(eRoute);10535 if(pkRouteInfo)10536 {10537#if defined(GLOBAL_ALPINE_PASSES)10538 iNumResource += pkRouteInfo->getResourceQuantityRequirement(iResourceLoop);10539#else10540 iNumResource = pkRouteInfo->getResourceQuantityRequirement(iResourceLoop);10541#endif10542 }10543 }1054410545 if(iNumResource > 0)10546 {10547 kPlayer.changeNumResourceUsed((ResourceTypes) iResourceLoop, -iNumResource);10548 }10549 }1055010551 if(pkBuildInfo->isKill())10552 {10553 if (pPlot->isActiveVisible(false))10554 {10555 auto_ptr<ICvUnit1> pDllUnit(new CvDllUnit(this));10556 gDLL->GameplayUnitActivate(pDllUnit.get());10557 }1055810559 if(IsGreatPerson())10560 {10561#if defined(MOD_EVENTS_GREAT_PEOPLE)10562 kPlayer.DoGreatPersonExpended(getUnitType(), this);10563#else10564 kPlayer.DoGreatPersonExpended(getUnitType());10565#endif10566 }1056710568 kill(true);10569 }1057010571 // Add to player's Improvement count, which will increase cost of future Improvements10572 if(pkBuildInfo->getImprovement() != NO_IMPROVEMENT || pkBuildInfo->getRoute() != NO_ROUTE) // Prevents chopping Forest or Jungle from counting10573 {10574 kPlayer.changeTotalImprovementsBuilt(1);10575 }1057610577 if(GC.getLogging() && GC.getAILogging())10578 {10579 LogWorkerEvent(eBuild, false);10580 }10581 }1058210583#if defined(MOD_EVENTS_PLOT)10584 if (MOD_EVENTS_PLOT) {10585 GAMEEVENTINVOKE_HOOK(GAMEEVENT_PlayerBuilt, getOwner(), GetID(), getX(), getY(), eBuild);10586 }10587#endif10588 }10589 else // we are not done doing this10590 {10591 if(pkBuildInfo)10592 {10593 ImprovementTypes eImprovement = NO_IMPROVEMENT;10594 RouteTypes eRoute = NO_ROUTE;1059510596 if(pkBuildInfo->getImprovement() != NO_IMPROVEMENT)10597 {10598 eImprovement = (ImprovementTypes) pkBuildInfo->getImprovement();10599 }10600 else if(pkBuildInfo->getRoute() != NO_ROUTE)10601 {10602 eRoute = (RouteTypes) pkBuildInfo->getRoute();10603 }1060410605 if(iStartedYet == 0)10606 {10607 if(pPlot->isVisible(GC.getGame().getActiveTeam(), true))10608 {10609 if(eImprovement != NO_IMPROVEMENT)10610 {10611 pPlot->setLayoutDirty(true);1061210613 }10614 else if(eRoute != NO_ROUTE)10615 {10616 pPlot->setLayoutDirty(true);10617 }10618 }10619 }10620 }10621 }1062210623 return bFinished;10624}