Hooks
static bool BeforeCvUnitMission_PushMission(UnitHandle hUnit, MissionTypes eMission, int iData1, int iData2, int iFlags, bool bAppend, bool bManual, MissionAITypes eMissionAI, CvPlot* pMissionAIPlot, CvUnit* pMissionAIUnit);static void AfterCvUnitMission_PushMission(UnitHandle hUnit, MissionTypes eMission, int iData1, int iData2, int iFlags, bool bAppend, bool bManual, MissionAITypes eMissionAI, CvPlot* pMissionAIPlot, CvUnit* pMissionAIUnit);static void ReplaceCvUnitMission_PushMission(void (*original)(UnitHandle, MissionTypes, int, int, int, bool, bool, MissionAITypes, CvPlot*, CvUnit*), UnitHandle hUnit, MissionTypes eMission, int iData1, int iData2, int iFlags, bool bAppend, bool bManual, MissionAITypes eMissionAI, CvPlot* pMissionAIPlot, CvUnit* pMissionAIUnit);CivRegisterBefore<CivHooks::CvUnitMission_PushMission>(host, &BeforeCvUnitMission_PushMission);CivRegisterAfter<CivHooks::CvUnitMission_PushMission>(host, &AfterCvUnitMission_PushMission);CivRegisterReplace<CivHooks::CvUnitMission_PushMission>(host, &ReplaceCvUnitMission_PushMission);
Code
122/// Queue up a new mission123void CvUnitMission::PushMission(UnitHandle hUnit, MissionTypes eMission, int iData1, int iData2, int iFlags, bool bAppend, bool bManual, MissionAITypes eMissionAI, CvPlot* pMissionAIPlot, CvUnit* pMissionAIUnit)124{125 if(CvPreGame::isHuman(hUnit->getOwner()))126 {127 CvAssertMsg(CvUnit::dispatchingNetMessage(), "Multiplayer Error! CvUnit::PushMission invoked for a human player outside of a network message!");128 if(!CvUnit::dispatchingNetMessage())129 gDLL->netMessageDebugLog("*** PROTOCOL ERROR *** : PushMission invoked for a human controlled player outside of a network message!");130 }131132 MissionData mission;133134 CvAssert(hUnit->getOwner() != NO_PLAYER);135136 if(!bAppend)137 {138 hUnit->ClearMissionQueue();139 }140141 if(bManual)142 {143 hUnit->SetAutomateType(NO_AUTOMATE);144 }145146 // Update Builder Resource info147 if(eMission == CvTypes::getMISSION_BUILD())148 {149 const BuildTypes eBuild = (BuildTypes) iData1;150 if(eBuild != NO_BUILD)151 {152 CvBuildInfo* pkBuildInfo = GC.getBuildInfo(eBuild);153 if(pkBuildInfo)154 {155 if (GET_PLAYER(hUnit->getOwner()).IsPlotUnderImmediateThreat(*(hUnit->plot())))156 {157 if(hUnit->plot()->getNumDefenders(hUnit->getOwner()) <= 0)158 {159 hUnit->SetIgnoreDangerWakeup(true);160 }161 }162163 //if (hUnit->isHuman())164 {165 FeatureTypes eFeature = hUnit->plot()->getFeatureType();166 if(eFeature != NO_FEATURE && pkBuildInfo->isFeatureRemove(eFeature) && pkBuildInfo->getFeatureTime(eFeature) > 0)167 {168#if defined(MOD_BUGFIX_FEATURE_REMOVAL)169 if (MOD_BUGFIX_FEATURE_REMOVAL) {170 // Don't bother looking if this is the build that removes this feature171 if (!pkBuildInfo->isFeatureRemoveOnly(eFeature)) {172 173 // We need to find the build that will remove eFeature.174 CvBuildInfo* pRemoveBuild = NULL;175 176 // Assumes that the BuildFeatures table has an extra column RemoveOnly177 for(int iI = 0; iI < GC.getNumBuildInfos(); iI++) {178 CvBuildInfo* pRemoveBuildInfo = GC.getBuildInfo((BuildTypes) iI);179 if(pRemoveBuildInfo) {180 if(pRemoveBuildInfo->isFeatureRemoveOnly(eFeature)) {181 CvTeamTechs* pTechs = GET_TEAM(GET_PLAYER(hUnit->getOwner()).getTeam()).GetTeamTechs();182 TechTypes eObsoleteTech = (TechTypes) pRemoveBuildInfo->getFeatureObsoleteTech(eFeature);183184 if (eObsoleteTech == NO_TECH || !pTechs->HasTech(eObsoleteTech)) {185 TechTypes ePrereqTech = (TechTypes) pRemoveBuildInfo->getFeatureTech(eFeature);186 187 // We have a candidate build for removing this feature188 if (ePrereqTech == NO_TECH) {189 if (pRemoveBuild == NULL) {190 pRemoveBuild = pRemoveBuildInfo;191 }192 } else if (pTechs->HasTech(ePrereqTech)) {193 if (pRemoveBuild == NULL) {194 pRemoveBuild = pRemoveBuildInfo;195 } else if (GC.getTechInfo(ePrereqTech)->GetGridX() > GC.getTechInfo((TechTypes) pRemoveBuild->getFeatureTech(eFeature))->GetGridX()) {196 pRemoveBuild = pRemoveBuildInfo;197 }198 }199 }200 }201 }202 }203 204 if (pRemoveBuild != NULL) {205 MissionData removeMission;206 removeMission.eMissionType = eMission;207 removeMission.iData1 = pRemoveBuild->GetID();208 removeMission.iData2 = iData2;209 removeMission.iFlags = iFlags;210 removeMission.iPushTurn = GC.getGame().getGameTurn();211 212 hUnit->SetMissionAI(eMissionAI, pMissionAIPlot, pMissionAIUnit);213 InsertAtEndMissionQueue(hUnit, removeMission, !bAppend);214 bAppend = true;215 }216 }217 } else {218#endif219 CvFeatureInfo* feature = GC.getFeatureInfo(eFeature);220 MissionData removeMission;221 removeMission.eMissionType = eMission;222 if(iData1 != 15 && strcmp(feature->GetType(), "FEATURE_FOREST") == 0)223 {224 removeMission.iData1 = 15; // todo: future proof this225 removeMission.iData2 = iData2;226 removeMission.iFlags = iFlags;227 removeMission.iPushTurn = GC.getGame().getGameTurn();228 hUnit->SetMissionAI(eMissionAI, pMissionAIPlot, pMissionAIUnit);229 InsertAtEndMissionQueue(hUnit, removeMission, !bAppend);230 bAppend = true;231 }232 else if(iData1 != 14 && strcmp(feature->GetType(), "FEATURE_JUNGLE") == 0)233 {234 removeMission.iData1 = 14; // todo: future proof this235 removeMission.iData2 = iData2;236 removeMission.iFlags = iFlags;237 removeMission.iPushTurn = GC.getGame().getGameTurn();238 hUnit->SetMissionAI(eMissionAI, pMissionAIPlot, pMissionAIUnit);239 InsertAtEndMissionQueue(hUnit, removeMission, !bAppend);240 bAppend = true;241 }242 else if(iData1 != 16 && strcmp(feature->GetType(), "FEATURE_MARSH") == 0)243 {244 removeMission.iData1 = 16; // todo: future proof this245 removeMission.iData2 = iData2;246 removeMission.iFlags = iFlags;247 removeMission.iPushTurn = GC.getGame().getGameTurn();248 hUnit->SetMissionAI(eMissionAI, pMissionAIPlot, pMissionAIUnit);249 InsertAtEndMissionQueue(hUnit, removeMission, !bAppend);250 bAppend = true;251 }252 else if(iData1 != 17 && strcmp(feature->GetType(), "FEATURE_FALLOUT") == 0)253 {254 removeMission.iData1 = 17; // todo: future proof this255 removeMission.iData2 = iData2;256 removeMission.iFlags = iFlags;257 removeMission.iPushTurn = GC.getGame().getGameTurn();258 hUnit->SetMissionAI(eMissionAI, pMissionAIPlot, pMissionAIUnit);259 InsertAtEndMissionQueue(hUnit, removeMission, !bAppend);260 bAppend = true;261 }262#if defined(MOD_BUGFIX_FEATURE_REMOVAL)263 }264#endif265 }266 }267268269 ImprovementTypes eImprovement = NO_IMPROVEMENT;270 RouteTypes eRoute = NO_ROUTE;271272 if(pkBuildInfo->getImprovement() != NO_IMPROVEMENT)273 {274 eImprovement = (ImprovementTypes) pkBuildInfo->getImprovement();275 }276 else277 {278 eRoute = (RouteTypes) pkBuildInfo->getRoute();279 }280281 int iNumResource = 0;282283 // Update the amount of a Resource used up by popped Build284 for(int iResourceLoop = 0; iResourceLoop < GC.getNumResourceInfos(); iResourceLoop++)285 {286 iNumResource = 0;287288 if(eImprovement != NO_IMPROVEMENT)289 {290 CvImprovementEntry* pkImprovementInfo = GC.getImprovementInfo(eImprovement);291 CvAssert(pkImprovementInfo);292 if(pkImprovementInfo)293 {294 iNumResource += pkImprovementInfo->GetResourceQuantityRequirement(iResourceLoop);295 }296 }297 else if(eRoute != NO_ROUTE)298 {299 CvRouteInfo* pkRouteInfo = GC.getRouteInfo(eRoute);300 CvAssert(pkRouteInfo);301 if(pkRouteInfo)302 {303 iNumResource += pkRouteInfo->getResourceQuantityRequirement(iResourceLoop);304 }305 }306307 if(iNumResource > 0)308 {309 GET_PLAYER(hUnit->getOwner()).changeNumResourceUsed((ResourceTypes) iResourceLoop, iNumResource);310 }311 }312 }313 }314 }315316 mission.eMissionType = eMission;317 mission.iData1 = iData1;318 mission.iData2 = iData2;319 mission.iFlags = iFlags;320 mission.iPushTurn = GC.getGame().getGameTurn();321322 hUnit->SetMissionAI(eMissionAI, pMissionAIPlot, pMissionAIUnit);323324 InsertAtEndMissionQueue(hUnit, mission, !bAppend);325326 if(bManual)327 {328 if(hUnit->getOwner() == GC.getGame().getActivePlayer())329 {330 CvMissionInfo* pMissionInfo = GC.getMissionInfo(eMission);331332 if(hUnit->IsBusy() && pMissionInfo != NULL && pMissionInfo->isSound())333 {334 hUnit->PlayActionSound();335 }336337 GC.GetEngineUserInterface()->setHasMovedUnit(true);338 }339340 ////gDLL->getEventReporterIFace()->selectionGroupPushMission(this, eMission);341 hUnit.ignoreDestruction(true);342 hUnit->doDelayedDeath();343 }344}