Bazaar developer reference

CvUnit::kill(bool, PlayerTypes)

Defined in
CvUnit.cpp, line 1520
Class
CvUnit
Hook name
CivHooks::CvUnit_kill
Changed in
0.5.0
Lua events
GameEvents.UnitPrekill, GameEvents.UnitCaptured, GameEvents.CanSaveUnit

Runs whenever a unit leaves play: when it dies, and also when it is upgraded, used up (a settler founding a city, a great person spent) or disbanded. Nothing in its parameters says which. For deaths in combat only, hook CvPlayer::DoUnitKilledCombat, which runs for the player whose unit did the killing.

Hooks

static bool BeforeCvUnit_kill(CvUnit* self, bool bDelay, PlayerTypes ePlayer);static void AfterCvUnit_kill(CvUnit* self, bool bDelay, PlayerTypes ePlayer);static void ReplaceCvUnit_kill(void (*original)(CvUnit*, bool, PlayerTypes), CvUnit* self, bool bDelay, PlayerTypes ePlayer);CivRegisterBefore<CivHooks::CvUnit_kill>(host, &BeforeCvUnit_kill);CivRegisterAfter<CivHooks::CvUnit_kill>(host, &AfterCvUnit_kill);CivRegisterReplace<CivHooks::CvUnit_kill>(host, &ReplaceCvUnit_kill);

Code

1516//	Kill a unit.1517//	Parameters:1518//		bDelay			- If true, the unit will be partially cleaned up, but its final removal will happen at the end of the frame.1519//		ePlayer			- Optional player ID who is doing the killing.1520void CvUnit::kill(bool bDelay, PlayerTypes ePlayer /*= NO_PLAYER*/)1521{1522	VALIDATE_OBJECT1523	CvUnit* pTransportUnit;1524	CvUnit* pLoopUnit;1525	CvPlot* pPlot;1526	CvString strBuffer;15271528	ICvEngineScriptSystem1* pkScriptSystem = gDLL->GetScriptSystem();1529	if(pkScriptSystem)1530	{1531		CvLuaArgsHandle args;1532		args->Push(getOwner());1533		args->Push(GetID());  // unit being killed15341535		bool bResult = false;1536		if(LuaSupport::CallTestAll(pkScriptSystem, "CanSaveUnit", args.get(), bResult))1537		{1538			// Check the result.1539			if(bResult)1540			{1541				return;   // Unit was saved1542			}1543		}1544	}15451546	auto_ptr<ICvUnit1> pDllThisUnit = GC.WrapUnitPointer(this);15471548	if(IsSelected() && !bDelay)1549	{1550		DLLUI->VisuallyDeselectUnit(pDllThisUnit.get());1551	}15521553	GET_PLAYER(getOwner()).removeFromArmy(m_iArmyId, GetID());15541555	pPlot = plot();1556	CvAssertMsg(pPlot != NULL, "Plot is not assigned a valid value");15571558	if(pPlot)1559	{1560		IDInfo* pkOldUnits = NULL;1561		uint uiOldUnitCount = pPlot->getNumUnits();1562		const IDInfo* pUnitNode = pPlot->headUnitNode();15631564		if(pUnitNode)1565		{1566			pkOldUnits = (IDInfo*)_malloca(pPlot->getNumUnits() * sizeof(IDInfo));	// Allocate an array on the stack, it shouldn't be too large1567			IDInfo* pkEntry = pkOldUnits;1568			while(pUnitNode != NULL)1569			{1570				*pkEntry++ = *pUnitNode;1571				pUnitNode = pPlot->nextUnitNode(pUnitNode);1572			}1573		}15741575		for(uint i = 0; i < uiOldUnitCount; i++)1576		{1577			pLoopUnit = ::getUnit(pkOldUnits[i]);15781579			if(pLoopUnit != NULL)1580			{1581				if(pLoopUnit->getTransportUnit() == this)	// Is this the transport for the search unit?1582				{1583					if(pLoopUnit->isSuicide() && pLoopUnit->isInCombat())1584					{1585						// Let suicide units (missiles & other single use items) kill themselves.1586						pLoopUnit->setTransportUnit(NULL);1587					}1588					else1589					{1590						if(pPlot->isValidDomainForLocation(*pLoopUnit))1591						{1592							pLoopUnit->setCapturingPlayer(getCapturingPlayer());	// KWG: Creating a new captured cargo, but how does its transport (this) then get attached to the new cargo?1593						}15941595						pLoopUnit->kill(false, ePlayer);1596					}1597				}1598			}1599		}16001601		if(pkOldUnits)1602			_freea(pkOldUnits);1603	}1604	// If a player killed this Unit...1605	if(ePlayer != NO_PLAYER)1606	{1607		if(!isBarbarian() && !GET_PLAYER(ePlayer).isBarbarian())1608		{1609			// Notify Diplo AI that damage has been done1610			// Best unit that can be built now is given value of 1001611			int iValue = getUnitInfo().GetPower();16121613			int iTypicalPower = GET_PLAYER(ePlayer).GetMilitaryAI()->GetPowerOfStrongestBuildableUnit(DOMAIN_LAND);16141615			if(iTypicalPower > 0)1616			{1617				iValue = iValue* /*100*/ GC.getDEFAULT_WAR_VALUE_FOR_UNIT() / iTypicalPower;1618			}1619			else1620			{1621				iValue = /*100*/ GC.getDEFAULT_WAR_VALUE_FOR_UNIT();1622			}16231624			// My viewpoint1625			GET_PLAYER(getOwner()).GetDiplomacyAI()->ChangeWarValueLost(ePlayer, iValue);1626			// Bad guy's viewpoint1627			GET_PLAYER(ePlayer).GetDiplomacyAI()->ChangeOtherPlayerWarValueLost(getOwner(), ePlayer, iValue);1628		}16291630		if(NO_UNIT != getLeaderUnitType())1631		{1632			for(int iI = 0; iI < MAX_PLAYERS; iI++)1633			{1634				if(GET_PLAYER((PlayerTypes)iI).isAlive())1635				{1636					strBuffer = GetLocalizedText("TXT_KEY_MISC_GENERAL_KILLED", getNameKey());1637					DLLUI->AddUnitMessage(0, GetIDInfo(), ((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), strBuffer, GC.getEraInfo(GC.getGame().getCurrentEra())->getAudioUnitDefeatScript(), MESSAGE_TYPE_MAJOR_EVENT);1638				}1639			}1640		}1641	}1642	1643#if defined(MOD_EVENTS_UNIT_PREKILL)1644	if (MOD_EVENTS_UNIT_PREKILL) {1645		GAMEEVENTINVOKE_HOOK(GAMEEVENT_UnitPrekill, getOwner(), GetID(), getUnitType(), getX(), getY(), bDelay, ePlayer);1646	} else {1647#endif1648	if (pkScriptSystem) 1649	{1650		CvLuaArgsHandle args;1651		args->Push(((int)getOwner()));1652		args->Push(GetID());1653		args->Push(getUnitType());1654		args->Push(getX());1655		args->Push(getY());1656		args->Push(bDelay);1657		args->Push(ePlayer);16581659		bool bResult;1660		LuaSupport::CallHook(pkScriptSystem, "UnitPrekill", args.get(), bResult);1661	}1662#if defined(MOD_EVENTS_UNIT_PREKILL)1663	}1664#endif16651666	if(bDelay)1667	{1668		startDelayedDeath();1669		return;1670	}16711672#if defined(MOD_GLOBAL_NO_LOST_GREATWORKS)1673	if(MOD_GLOBAL_NO_LOST_GREATWORKS && !bDelay)1674	{1675		if (HasUnusedGreatWork())1676		{1677			CUSTOMLOG("Killing a Great Writer, Artist or Musician who didn't create their Great Work (%s)", getGreatName().c_str());1678			GC.getGame().removeGreatPersonBornName(getGreatName());1679		}1680	}1681#endif16821683	///////////////////////////////////////////////////////////////////////////////////////////////1684	// EVERYTHING AFTER THIS LINE OCCURS UPON THE ACTUAL DELETION OF THE UNIT AND NOT WITH A DELAYED DEATH1685	///////////////////////////////////////////////////////////////////////////////////////////////16861687	if(IsSelected())1688	{1689		DLLUI->setDirty(UnitInfo_DIRTY_BIT, true);1690		if(DLLUI->GetLengthSelectionList() == 1)1691		{1692			if(!(DLLUI->isFocused()) && !(DLLUI->isCitySelection()) && !(DLLUI->isDiploOrPopupWaiting()))1693			{1694				GC.getGame().updateSelectionList();1695			}16961697			if(IsSelected())1698			{1699				DLLUI->setCycleSelectionCounter(1);1700			}1701			else1702			{1703				DLLUI->setDirty(SelectionCamera_DIRTY_BIT, true);1704			}1705		}1706	}17071708	DLLUI->RemoveFromSelectionList(pDllThisUnit.get());1709	GET_PLAYER(getOwner()).GetUnitCycler().RemoveUnit(GetID());17101711	// Killing a unit while in combat is not something we really expect to happen.1712	// It is *mostly* safe for it to happen, but combat systems must be able to gracefully handle the disapperance of a unit.1713	CvAssertMsg_Debug(!isInCombat(), "isCombat did not return false as expected");17141715	clearCombat();	// Disconnect from any combat17161717	pTransportUnit = getTransportUnit();17181719	if(pTransportUnit != NULL)1720	{1721		setTransportUnit(NULL);1722	}17231724	setReconPlot(NULL);17251726	CvAssertMsg(getAttackPlot() == NULL, "The current unit instance's attack plot is expected to be NULL");1727	CvAssertMsg(getCombatUnit() == NULL, "The current unit instance's combat unit is expected to be NULL");17281729	GET_TEAM(getTeam()).changeUnitClassCount((UnitClassTypes)getUnitInfo().GetUnitClassType(), -1);1730	GET_PLAYER(getOwner()).changeUnitClassCount((UnitClassTypes)getUnitInfo().GetUnitClassType(), -1);17311732	// Builder Limit1733	if(getUnitInfo().GetWorkRate() > 0 && getUnitInfo().GetDomainType() == DOMAIN_LAND)1734	{1735		GET_PLAYER(getOwner()).ChangeNumBuilders(-1);1736	}17371738	// Some Units count against Happiness1739	if(getUnitInfo().GetUnhappiness() != 0)1740	{1741		GET_PLAYER(getOwner()).ChangeUnhappinessFromUnits(-getUnitInfo().GetUnhappiness());1742	}17431744	GET_PLAYER(getOwner()).changeExtraUnitCost(-(getUnitInfo().GetExtraMaintenanceCost()));17451746	if(getUnitInfo().GetNukeDamageLevel() != -1)1747	{1748		GET_PLAYER(getOwner()).changeNumNukeUnits(-1);1749	}17501751	if(getUnitInfo().IsMilitarySupport())1752	{1753		GET_PLAYER(getOwner()).changeNumMilitaryUnits(-1);1754	}17551756	// A unit dying reduces the Great General meter1757#if defined(MOD_UNITS_XP_TIMES_100)1758	if (getExperienceTimes100() > 0 && ePlayer != NO_PLAYER)1759#else1760	if (getExperience() > 0 && ePlayer != NO_PLAYER)1761#endif1762	{1763#if defined(MOD_UNITS_XP_TIMES_100)1764		int iGreatGeneralMeterLossTimes100 = getExperienceTimes100() * /*50*/ GC.getUNIT_DEATH_XP_GREAT_GENERAL_LOSS();1765		iGreatGeneralMeterLossTimes100 /= 100;1766#else1767		int iGreatGeneralMeterLoss = getExperience() * /*50*/ GC.getUNIT_DEATH_XP_GREAT_GENERAL_LOSS();1768		iGreatGeneralMeterLoss /= 100;1769#endif17701771		if(getDomainType() == DOMAIN_SEA)1772		{1773#if defined(MOD_UNITS_XP_TIMES_100)1774			GET_PLAYER(getOwner()).changeNavalCombatExperienceTimes100(-iGreatGeneralMeterLossTimes100);1775#else1776			GET_PLAYER(getOwner()).changeNavalCombatExperience(-iGreatGeneralMeterLoss);1777#endif1778		}1779		else1780		{1781#if defined(MOD_UNITS_XP_TIMES_100)1782			GET_PLAYER(getOwner()).changeCombatExperienceTimes100(-iGreatGeneralMeterLossTimes100);1783#else1784			GET_PLAYER(getOwner()).changeCombatExperience(-iGreatGeneralMeterLoss);1785#endif1786		}1787	}17881789	CvUnitCaptureDefinition kCaptureDef;1790	getCaptureDefinition(&kCaptureDef);1791	1792#if defined(MOD_EVENTS_UNIT_CAPTURE)1793	if (MOD_EVENTS_UNIT_CAPTURE && (kCaptureDef.eCapturingPlayer != NO_PLAYER && kCaptureDef.eCaptureUnitType != NO_UNIT)) {1794		GAMEEVENTINVOKE_HOOK(GAMEEVENT_UnitCaptured, kCaptureDef.eCapturingPlayer, kCaptureDef.eCaptureUnitType, getOwner(), GetID(), false, 1);1795	}1796#endif17971798	setXY(INVALID_PLOT_COORD, INVALID_PLOT_COORD, true);1799	if(pPlot)1800		pPlot->removeUnit(this, false);18011802	// Remove Resource Quantity from Used1803	for(int iResourceLoop = 0; iResourceLoop < GC.getNumResourceInfos(); iResourceLoop++)1804	{1805		if(getUnitInfo().GetResourceQuantityRequirement(iResourceLoop) > 0)1806		{1807			GET_PLAYER(getOwner()).changeNumResourceUsed((ResourceTypes) iResourceLoop, -getUnitInfo().GetResourceQuantityRequirement(iResourceLoop));1808		}1809	}18101811#if defined(CIV_HOST_API)1812	CivHostCaptureFrom(getOwner(), GetID());1813#endif1814	//////////////////////////////////////////////////////////////////////////1815	// WARNING: This next statement will delete 'this'1816	// ANYTHING BELOW HERE MUST NOT REFERENCE THE UNIT!1817	GET_PLAYER(getOwner()).deleteUnit(GetID());18181819	// Update Unit Production Maintenance1820	GET_PLAYER(kCaptureDef.eOldPlayer).UpdateUnitProductionMaintenanceMod();18211822	// Create the captured unit that will replace this unit (if the capture definition is valid)1823	CvUnit::createCaptureUnit(kCaptureDef);1824#if defined(CIV_HOST_API)1825	CivHostCaptureDone();1826#endif18271828	if(GC.getGame().getActivePlayer() == kCaptureDef.eOldPlayer)1829	{1830		CvMap& theMap = GC.getMap();1831		theMap.updateDeferredFog();1832	}18331834	//////////////////////////////////////////////////////////////////////////1835	// Do not add anything below here in this method1836}

Calls

Called by

70 functions in 14 files