Bazaar developer reference

CvUnitCombat::GenerateMeleeCombatInfo(CvUnit &, CvUnit *, CvPlot &, CvCombatInfo *)

Defined in
CvUnitCombat.cpp, line 101
Class
CvUnitCombat
Hook name
CivHooks::CvUnitCombat_GenerateMeleeCombatInfo
Lua events
GameEvents.UnitCanFollowupFrom

Hooks

static bool BeforeCvUnitCombat_GenerateMeleeCombatInfo(CvUnit& kAttacker, CvUnit* pkDefender, CvPlot& plot, CvCombatInfo* pkCombatInfo);static void AfterCvUnitCombat_GenerateMeleeCombatInfo(CvUnit& kAttacker, CvUnit* pkDefender, CvPlot& plot, CvCombatInfo* pkCombatInfo);static void ReplaceCvUnitCombat_GenerateMeleeCombatInfo(void (*original)(CvUnit&, CvUnit*, CvPlot&, CvCombatInfo*), CvUnit& kAttacker, CvUnit* pkDefender, CvPlot& plot, CvCombatInfo* pkCombatInfo);CivRegisterBefore<CivHooks::CvUnitCombat_GenerateMeleeCombatInfo>(host, &BeforeCvUnitCombat_GenerateMeleeCombatInfo);CivRegisterAfter<CivHooks::CvUnitCombat_GenerateMeleeCombatInfo>(host, &AfterCvUnitCombat_GenerateMeleeCombatInfo);CivRegisterReplace<CivHooks::CvUnitCombat_GenerateMeleeCombatInfo>(host, &ReplaceCvUnitCombat_GenerateMeleeCombatInfo);

Code

101void CvUnitCombat::GenerateMeleeCombatInfo(CvUnit& kAttacker, CvUnit* pkDefender, CvPlot& plot, CvCombatInfo* pkCombatInfo)102{103	BATTLE_STARTED(BATTLE_TYPE_MELEE, plot);104#if defined(MOD_UNITS_MAX_HP)105	int iAttackerMaxHP = kAttacker.GetMaxHitPoints();106#else107	int iMaxHP = GC.getMAX_HIT_POINTS();108#endif109110	pkCombatInfo->setUnit(BATTLE_UNIT_ATTACKER, &kAttacker);111	pkCombatInfo->setUnit(BATTLE_UNIT_DEFENDER, pkDefender);112	pkCombatInfo->setPlot(&plot);113114	// Attacking a City115	if(plot.isCity())116	{117		// Unit vs. City (non-ranged so the city will retaliate118		CvCity* pkCity = plot.getPlotCity();119		BATTLE_JOINED(pkCity, BATTLE_UNIT_DEFENDER, true);120		int iMaxCityHP = pkCity->GetMaxHitPoints();121122		int iAttackerStrength = kAttacker.GetMaxAttackStrength(kAttacker.plot(), &plot, NULL);123		int iDefenderStrength = pkCity->getStrengthValue();124125		int iAttackerDamageInflicted = kAttacker.getCombatDamage(iAttackerStrength, iDefenderStrength, kAttacker.getDamage(), /*bIncludeRand*/ true, /*bAttackerIsCity*/ false, /*bDefenderIsCity*/ true);126		int iDefenderDamageInflicted = kAttacker.getCombatDamage(iDefenderStrength, iAttackerStrength, pkCity->getDamage(), /*bIncludeRand*/ true, /*bAttackerIsCity*/ true, /*bDefenderIsCity*/ false);127128		int iAttackerTotalDamageInflicted = iAttackerDamageInflicted + pkCity->getDamage();129		int iDefenderTotalDamageInflicted = iDefenderDamageInflicted + kAttacker.getDamage();130131		// Will both the attacker die, and the city fall? If so, the unit wins132#if defined(MOD_UNITS_MAX_HP)133		if (iAttackerTotalDamageInflicted >= iMaxCityHP && iDefenderTotalDamageInflicted >= iAttackerMaxHP)134		{135			iDefenderDamageInflicted = iAttackerMaxHP - kAttacker.getDamage() - 1;136			iDefenderTotalDamageInflicted = iAttackerMaxHP - 1;137		}138#else139		if (iAttackerTotalDamageInflicted >= iMaxCityHP && iDefenderTotalDamageInflicted >= iMaxHP)140		{141			iDefenderDamageInflicted = iMaxHP - kAttacker.getDamage() - 1;142			iDefenderTotalDamageInflicted = iMaxHP - 1;143		}144#endif145146		pkCombatInfo->setFinalDamage(BATTLE_UNIT_ATTACKER, iDefenderTotalDamageInflicted);147		pkCombatInfo->setDamageInflicted(BATTLE_UNIT_ATTACKER, iAttackerDamageInflicted);148		pkCombatInfo->setFinalDamage(BATTLE_UNIT_DEFENDER, iAttackerTotalDamageInflicted);149		pkCombatInfo->setDamageInflicted(BATTLE_UNIT_DEFENDER, iDefenderDamageInflicted);150151		int iExperience = /*5*/ GC.getEXPERIENCE_ATTACKING_CITY_MELEE();152		pkCombatInfo->setExperience(BATTLE_UNIT_ATTACKER, iExperience);153		pkCombatInfo->setMaxExperienceAllowed(BATTLE_UNIT_ATTACKER, MAX_INT);154		pkCombatInfo->setInBorders(BATTLE_UNIT_ATTACKER, plot.getOwner() == pkCity->getOwner());155#if defined(MOD_TRAITS_GG_FROM_BARBARIANS) || defined(MOD_PROMOTIONS_GG_FROM_BARBARIANS)156		pkCombatInfo->setUpdateGlobal(BATTLE_UNIT_ATTACKER, kAttacker.isGGFromBarbarians() || !kAttacker.isBarbarian());157#else158		pkCombatInfo->setUpdateGlobal(BATTLE_UNIT_ATTACKER, !kAttacker.isBarbarian());159#endif160161		pkCombatInfo->setExperience(BATTLE_UNIT_DEFENDER, 0);162		pkCombatInfo->setMaxExperienceAllowed(BATTLE_UNIT_DEFENDER, kAttacker.maxXPValue());163		pkCombatInfo->setInBorders(BATTLE_UNIT_DEFENDER, plot.getOwner() == kAttacker.getOwner());164#if defined(MOD_TRAITS_GG_FROM_BARBARIANS) || defined(MOD_PROMOTIONS_GG_FROM_BARBARIANS)165		pkCombatInfo->setUpdateGlobal(BATTLE_UNIT_DEFENDER, !pkCity->isBarbarian()); // Kind of irrelevant, as cities don't get XP!166#else167		pkCombatInfo->setUpdateGlobal(BATTLE_UNIT_DEFENDER, !pkCity->isBarbarian());168#endif169170		pkCombatInfo->setAttackIsRanged(false);171		pkCombatInfo->setDefenderRetaliates(true);172	}173	// Attacking a Unit174	else175	{176		// Unit vs. Unit177		CvAssert(pkDefender != NULL);178179#if defined(MOD_UNITS_MAX_HP)180		int iDefenderMaxHP = pkDefender->GetMaxHitPoints();181#endif182183		int iDefenderStrength = pkDefender->GetMaxDefenseStrength(&plot, &kAttacker);184		int iAttackerStrength = 0;185		if(kAttacker.GetMaxRangedCombatStrength(NULL, /*pCity*/ NULL, true, true) > 0 && kAttacker.getDomainType() == DOMAIN_AIR)186		{187			iAttackerStrength = kAttacker.GetMaxRangedCombatStrength(NULL, /*pCity*/ NULL, true, true);188			if(pkDefender->getDomainType() != DOMAIN_AIR)189			{190				iDefenderStrength /= 2;191			}192		}193		else194		{195			iAttackerStrength = kAttacker.GetMaxAttackStrength(kAttacker.plot(), &plot, pkDefender);196		}197198		if (kAttacker.IsCanHeavyCharge() && !pkDefender->CanFallBackFromMelee(kAttacker))199		{200			iAttackerStrength = (iAttackerStrength * 150) / 100;201		}202203		int iAttackerDamageInflicted = kAttacker.getCombatDamage(iAttackerStrength, iDefenderStrength, kAttacker.getDamage(), /*bIncludeRand*/ true, /*bAttackerIsCity*/ false, /*bDefenderIsCity*/ false);204		int iDefenderDamageInflicted = pkDefender->getCombatDamage(iDefenderStrength, iAttackerStrength, pkDefender->getDamage(), /*bIncludeRand*/ true, /*bAttackerIsCity*/ false, /*bDefenderIsCity*/ false);205206		if(kAttacker.getDomainType() == DOMAIN_AIR && pkDefender->getDomainType() != DOMAIN_AIR)207		{208			iAttackerDamageInflicted /= 2;209			iDefenderDamageInflicted /= 3;210		}211212		int iAttackerTotalDamageInflicted = iAttackerDamageInflicted + pkDefender->getDamage();213		int iDefenderTotalDamageInflicted = iDefenderDamageInflicted + kAttacker.getDamage();214215		// Will both units be killed by this? :o If so, take drastic corrective measures216#if defined(MOD_UNITS_MAX_HP)217		if (iAttackerTotalDamageInflicted >= iDefenderMaxHP && iDefenderTotalDamageInflicted >= iAttackerMaxHP)218#else219		if (iAttackerTotalDamageInflicted >= iMaxHP && iDefenderTotalDamageInflicted >= iMaxHP)220#endif221		{222			// He who hath the least amount of damage survives with 1 HP left223			if(iAttackerTotalDamageInflicted > iDefenderTotalDamageInflicted)224			{225#if defined(MOD_UNITS_MAX_HP)226				iDefenderDamageInflicted = iAttackerMaxHP - kAttacker.getDamage() - 1;227				iDefenderTotalDamageInflicted = iAttackerMaxHP - 1;228				iAttackerTotalDamageInflicted = iDefenderMaxHP;229#else230				iDefenderDamageInflicted = iMaxHP - kAttacker.getDamage() - 1;231				iDefenderTotalDamageInflicted = iMaxHP - 1;232				iAttackerTotalDamageInflicted = iMaxHP;233#endif234			}235			else236			{237#if defined(MOD_UNITS_MAX_HP)238				iAttackerDamageInflicted = iDefenderMaxHP - pkDefender->getDamage() - 1;239				iAttackerTotalDamageInflicted = iDefenderMaxHP - 1;240				iDefenderTotalDamageInflicted = iAttackerMaxHP;241#else242				iAttackerDamageInflicted = iMaxHP - pkDefender->getDamage() - 1;243				iAttackerTotalDamageInflicted = iMaxHP - 1;244				iDefenderTotalDamageInflicted = iMaxHP;245#endif246			}247		}248249		pkCombatInfo->setFinalDamage(BATTLE_UNIT_ATTACKER, iDefenderTotalDamageInflicted);250		pkCombatInfo->setDamageInflicted(BATTLE_UNIT_ATTACKER, iAttackerDamageInflicted);251		pkCombatInfo->setFinalDamage(BATTLE_UNIT_DEFENDER, iAttackerTotalDamageInflicted);252		pkCombatInfo->setDamageInflicted(BATTLE_UNIT_DEFENDER, iDefenderDamageInflicted);253254		// Fear Damage255		pkCombatInfo->setFearDamageInflicted(BATTLE_UNIT_ATTACKER, kAttacker.getCombatDamage(iAttackerStrength, iDefenderStrength, kAttacker.getDamage(), true, false, true));256		//	pkCombatInfo->setFearDamageInflicted( BATTLE_UNIT_DEFENDER, getCombatDamage(iDefenderStrength, iAttackerStrength, pDefender->getDamage(), true, false, true) );257258#if defined(MOD_UNITS_MAX_HP)259		int iAttackerEffectiveStrength = iAttackerStrength * (iAttackerMaxHP - range(kAttacker.getDamage(), 0, iAttackerMaxHP - 1)) / iAttackerMaxHP;260#else261		int iAttackerEffectiveStrength = iAttackerStrength * (iMaxHP - range(kAttacker.getDamage(), 0, iMaxHP - 1)) / iMaxHP;262#endif263		iAttackerEffectiveStrength = iAttackerEffectiveStrength > 0 ? iAttackerEffectiveStrength : 1;264#if defined(MOD_UNITS_MAX_HP)265		int iDefenderEffectiveStrength = iDefenderStrength * (iDefenderMaxHP - range(pkDefender->getDamage(), 0, iDefenderMaxHP - 1)) / iDefenderMaxHP;266#else267		int iDefenderEffectiveStrength = iDefenderStrength * (iMaxHP - range(pkDefender->getDamage(), 0, iMaxHP - 1)) / iMaxHP;268#endif269		iDefenderEffectiveStrength = iDefenderEffectiveStrength > 0 ? iDefenderEffectiveStrength : 1;270271		//int iExperience = kAttacker.defenseXPValue();272		//iExperience = ((iExperience * iAttackerEffectiveStrength) / iDefenderEffectiveStrength); // is this right? looks like more for less [Jon: Yes, it's XP for the defender]273		//iExperience = range(iExperience, GC.getMIN_EXPERIENCE_PER_COMBAT(), GC.getMAX_EXPERIENCE_PER_COMBAT());274		int iExperience = /*4*/ GC.getEXPERIENCE_DEFENDING_UNIT_MELEE();275		pkCombatInfo->setExperience(BATTLE_UNIT_DEFENDER, iExperience);276		pkCombatInfo->setMaxExperienceAllowed(BATTLE_UNIT_DEFENDER, kAttacker.maxXPValue());277		pkCombatInfo->setInBorders(BATTLE_UNIT_DEFENDER, plot.getOwner() == pkDefender->getOwner());278#if defined(MOD_TRAITS_GG_FROM_BARBARIANS) || defined(MOD_PROMOTIONS_GG_FROM_BARBARIANS)279		pkCombatInfo->setUpdateGlobal(BATTLE_UNIT_DEFENDER, pkDefender->isGGFromBarbarians() || !kAttacker.isBarbarian());280#else281		pkCombatInfo->setUpdateGlobal(BATTLE_UNIT_DEFENDER, !kAttacker.isBarbarian());282#endif283284		//iExperience = ((iExperience * iDefenderEffectiveStrength) / iAttackerEffectiveStrength);285		//iExperience = range(iExperience, GC.getMIN_EXPERIENCE_PER_COMBAT(), GC.getMAX_EXPERIENCE_PER_COMBAT());286		iExperience = /*6*/ GC.getEXPERIENCE_ATTACKING_UNIT_MELEE();287		pkCombatInfo->setExperience(BATTLE_UNIT_ATTACKER, iExperience);288		pkCombatInfo->setMaxExperienceAllowed(BATTLE_UNIT_ATTACKER, pkDefender->maxXPValue());289		pkCombatInfo->setInBorders(BATTLE_UNIT_ATTACKER, plot.getOwner() == kAttacker.getOwner());290#if defined(MOD_TRAITS_GG_FROM_BARBARIANS) || defined(MOD_PROMOTIONS_GG_FROM_BARBARIANS)291		pkCombatInfo->setUpdateGlobal(BATTLE_UNIT_ATTACKER, kAttacker.isGGFromBarbarians() || !pkDefender->isBarbarian());292#else293		pkCombatInfo->setUpdateGlobal(BATTLE_UNIT_ATTACKER, !pkDefender->isBarbarian());294#endif295296		pkCombatInfo->setAttackIsRanged(false);297298		bool bAdvance = true;299		if(plot.getNumDefenders(pkDefender->getOwner()) > 1)300		{301			bAdvance = false;302		}303#if defined(MOD_UNITS_MAX_HP)304		else if (iAttackerTotalDamageInflicted >= iDefenderMaxHP && kAttacker.IsCaptureDefeatedEnemy() && kAttacker.AreUnitsOfSameType(*pkDefender))305#else306		else if (iAttackerTotalDamageInflicted >= iMaxHP && kAttacker.IsCaptureDefeatedEnemy() && kAttacker.AreUnitsOfSameType(*pkDefender))307#endif308		{309			int iCaptureRoll = GC.getGame().getJonRandNum(100, "Capture Enemy Roll");310311			if (iCaptureRoll < kAttacker.GetCaptureChance(pkDefender))312			{313				bAdvance = false;314				pkCombatInfo->setDefenderCaptured(true);315			}316		}317		else if (kAttacker.IsCanHeavyCharge() && !pkDefender->isDelayedDeath() && (iAttackerDamageInflicted > iDefenderDamageInflicted) )318		{319			bAdvance = true;320		}321322#if defined(MOD_GLOBAL_NO_FOLLOWUP_FROM_CITIES)323		// If the attacker is in a city, don't advance324		if (MOD_GLOBAL_NO_FOLLOWUP_FROM_CITIES && kAttacker.plot()->isCity()) {325			CUSTOMLOG("Attacker %s is in a city/fort/citadel at (%i, %i) - they will not follow up", kAttacker.getName().GetCString(), kAttacker.getX(), kAttacker.getY());326			bAdvance = false;327		}328#endif329330#if defined(MOD_GLOBAL_NO_FOLLOWUP) || defined(MOD_EVENTS_UNIT_ACTIONS)331		ImprovementTypes eImprovement = kAttacker.plot()->getImprovementType();332		333		if (eImprovement != NO_IMPROVEMENT) {334#if defined(MOD_GLOBAL_NO_FOLLOWUP)335			if (MOD_GLOBAL_NO_FOLLOWUP && GC.getImprovementInfo(eImprovement)->IsNoFollowup()) {336				// The attacker is in a designated improvement (fort, citadel, etc), so don't advance337				CUSTOMLOG("Attacker %s is in a designated improvement (%i) at (%i, %i) - they will not follow up", kAttacker.getName().GetCString(), eImprovement, kAttacker.getX(), kAttacker.getY());338				bAdvance = false;339			}340#endif341342#if defined(MOD_EVENTS_UNIT_ACTIONS)343			if (MOD_EVENTS_UNIT_ACTIONS && bAdvance) {344				if (GAMEEVENTINVOKE_TESTALL(GAMEEVENT_UnitCanFollowupFrom, kAttacker.getOwner(), kAttacker.GetID(), eImprovement, kAttacker.getX(), kAttacker.getY(), pkDefender->getX(), pkDefender->getY()) == GAMEEVENTRETURN_FALSE) {345					bAdvance = false;346				}347			}348#endif349		}350#endif351352		pkCombatInfo->setAttackerAdvances(bAdvance);353		pkCombatInfo->setDefenderRetaliates(true);354	}355356	GC.GetEngineUserInterface()->setDirty(UnitInfo_DIRTY_BIT, true);357}

Calls

Called by