Skip to content

Commit

Permalink
Partially implement (7-61) Complete Kills rework
Browse files Browse the repository at this point in the history
  • Loading branch information
RecursiveVision committed Jul 5, 2024
1 parent 998d2e9 commit 3e7eef5
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 7 deletions.
3 changes: 3 additions & 0 deletions (1) Community Patch/Core Files/Core Values/CoreDefines.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
INSERT INTO Defines(Name, Value) SELECT 'MAJORS_CAN_MOVE_STARTING_SETTLER', 1;
INSERT INTO Defines(Name, Value) SELECT 'CS_CAN_MOVE_STARTING_SETTLER', 0;

-- If > -1, a player with no cities but who is still alive (Complete Kills) will be granted a free Settler after this many turns
INSERT INTO Defines(Name, Value) SELECT 'COMPLETE_KILLS_TURN_TIMER', -1;

-- Maximum number of Ideology Tenets of each Level that a Player can have (should correspond to the limitations put on human players by the Ideology Selection UI)
INSERT INTO Defines(Name, Value) SELECT 'MAX_NUM_TENETS_LEVEL_1', 7;
INSERT INTO Defines(Name, Value) SELECT 'MAX_NUM_TENETS_LEVEL_2', 4;
Expand Down
7 changes: 7 additions & 0 deletions (2) Vox Populi/Database Changes/DefineChanges.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
-- General Changes to the DLL's Global Values

-------------------------------------------------------------------------------------------------------------------
-- Game Options
-------------------------------------------------------------------------------------------------------------------

-- If > -1, a player with no cities but who is still alive (Complete Kills) will be granted a free Settler after this many turns
UPDATE Defines SET Value = 10 WHERE Name = 'COMPLETE_KILLS_TURN_TIMER';

-------------------------------------------------------------------------------------------------------------------
-- Defensive Pact
-------------------------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
UPDATE Language_en_US
SET Text = 'Barbarians and their Encampments do not appear on the map. Rebel (barbarian) uprisings from [ICON_HAPPINESS_4] Unhappiness do not occur.'
WHERE Tag = 'TXT_KEY_GAME_OPTION_NO_BARBARIANS_HELP';

-- Complete Kills
UPDATE Language_en_US
SET Text = 'In order to be eliminated from the game, a player must have all of his Cities AND Units destroyed. A player who remains alive for 10 turns with no Cities or Settlers will receive a free Settler.'
WHERE Tag = 'TXT_KEY_GAME_OPTION_COMPLETE_KILLS_HELP';
2 changes: 2 additions & 0 deletions CvGameCoreDLL_Expansion2/CvGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1800,6 +1800,7 @@ CvGlobals::CvGlobals() :
GD_INT_INIT(COMBAT_AI_DEFENSE_SCORE_BIAS, 200),
GD_INT_INIT(MAJORS_CAN_MOVE_STARTING_SETTLER, 1),
GD_INT_INIT(CS_CAN_MOVE_STARTING_SETTLER, 0),
GD_INT_INIT(COMPLETE_KILLS_TURN_TIMER, -1),
GD_INT_INIT(MAX_NUM_TENETS_LEVEL_1, 7),
GD_INT_INIT(MAX_NUM_TENETS_LEVEL_2, 4),
GD_INT_INIT(MAX_NUM_TENETS_LEVEL_3, 3),
Expand Down Expand Up @@ -6629,6 +6630,7 @@ void CvGlobals::cacheGlobals()
GD_INT_CACHE(COMBAT_AI_DEFENSE_SCORE_BIAS);
GD_INT_CACHE(MAJORS_CAN_MOVE_STARTING_SETTLER);
GD_INT_CACHE(CS_CAN_MOVE_STARTING_SETTLER);
GD_INT_CACHE(COMPLETE_KILLS_TURN_TIMER);
GD_INT_CACHE(MAX_NUM_TENETS_LEVEL_1);
GD_INT_CACHE(MAX_NUM_TENETS_LEVEL_2);
GD_INT_CACHE(MAX_NUM_TENETS_LEVEL_3);
Expand Down
1 change: 1 addition & 0 deletions CvGameCoreDLL_Expansion2/CvGlobals.h
Original file line number Diff line number Diff line change
Expand Up @@ -2391,6 +2391,7 @@ class CvGlobals
GD_INT_MEMBER(COMBAT_AI_DEFENSE_SCORE_BIAS); // VP
GD_INT_MEMBER(MAJORS_CAN_MOVE_STARTING_SETTLER); // VP
GD_INT_MEMBER(CS_CAN_MOVE_STARTING_SETTLER); // VP
GD_INT_MEMBER(COMPLETE_KILLS_TURN_TIMER); // VP
GD_INT_MEMBER(MAX_NUM_TENETS_LEVEL_1); // VP
GD_INT_MEMBER(MAX_NUM_TENETS_LEVEL_2); // VP
GD_INT_MEMBER(MAX_NUM_TENETS_LEVEL_3); // VP
Expand Down
113 changes: 108 additions & 5 deletions CvGameCoreDLL_Expansion2/CvPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ CvPlayer::CvPlayer() :
, m_bExtendedGame()
, m_bFoundedFirstCity()
, m_iNumCitiesFounded()
, m_iCompleteKillsTimerTurn()
, m_bStrike()
, m_bCramped()
, m_bLostCapital()
Expand Down Expand Up @@ -1709,6 +1710,7 @@ void CvPlayer::uninit()
m_bExtendedGame = false;
m_bFoundedFirstCity = false;
m_iNumCitiesFounded = 0;
m_iCompleteKillsTimerTurn = -1;
m_bStrike = false;
m_bCramped = false;
m_bLostCapital = false;
Expand Down Expand Up @@ -2652,7 +2654,7 @@ void CvPlayer::initFreeUnits()


// --------------------------------------------------------------------------------
void CvPlayer::addFreeUnitAI(UnitAITypes eUnitAI, bool bGameStart, int iCount)
void CvPlayer::addFreeUnitAI(UnitAITypes eUnitAI, bool bGameStart, int iCount, bool bCompleteKills)
{
UnitTypes eBestUnit = NO_UNIT;
int iBestUnitValue = 0;
Expand All @@ -2670,7 +2672,7 @@ void CvPlayer::addFreeUnitAI(UnitAITypes eUnitAI, bool bGameStart, int iCount)

// Starting Settler is the only unit that doesn't require a canTrainUnit check
bool bIsSettler = (pkUnitInfo->GetUnitClassType() == GC.getInfoTypeForString("UNITCLASS_SETTLER"));
if ((bGameStart && bIsSettler) || canTrainUnit(eLoopUnit))
if (((bGameStart || bCompleteKills) && bIsSettler) || canTrainUnit(eLoopUnit))
{
int iValue = 0;

Expand All @@ -2682,7 +2684,7 @@ void CvPlayer::addFreeUnitAI(UnitAITypes eUnitAI, bool bGameStart, int iCount)
// Not default, but still possible?
else if (pkUnitInfo->GetUnitAIType(eUnitAI))
{
if (!bGameStart)
if (!bGameStart && !bCompleteKills)
iValue += pkUnitInfo->GetProductionCost();
else if (eUnitAI != UNITAI_SETTLE && eUnitAI != UNITAI_WORKER && eUnitAI != UNITAI_WORKER_SEA) // Never spawn in secondary Settlers or Workers at game start
iValue += pkUnitInfo->GetProductionCost();
Expand All @@ -2700,14 +2702,14 @@ void CvPlayer::addFreeUnitAI(UnitAITypes eUnitAI, bool bGameStart, int iCount)
{
for (int iI = 0; iI < iCount; iI++)
{
addFreeUnit(eBestUnit, bGameStart, eUnitAI);
addFreeUnit(eBestUnit, bGameStart, eUnitAI, bCompleteKills);
}
}
}

// --------------------------------------------------------------------------------
/// Returns plot where new unit was created
CvPlot* CvPlayer::addFreeUnit(UnitTypes eUnit, bool bGameStart, UnitAITypes eUnitAI)
CvPlot* CvPlayer::addFreeUnit(UnitTypes eUnit, bool bGameStart, UnitAITypes eUnitAI, bool bCompleteKills)
{
CvUnitEntry* pkUnitInfo = GC.getUnitInfo(eUnit);
if (!pkUnitInfo)
Expand Down Expand Up @@ -2758,6 +2760,72 @@ CvPlot* CvPlayer::addFreeUnit(UnitTypes eUnit, bool bGameStart, UnitAITypes eUni
pStartingPlot = getStartingPlot();
}

// If this is a Complete Kills spawn, pick a plot occupied by one of the AI's existing land units
if (bCompleteKills)
{
int iBestPlotValue = 0;
int iLoop = 0;
pStartingPlot = NULL;
// Try to spawn on top of an existing land combat unit
for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
{
if (!pLoopUnit->IsCanDefend())
continue;

CvPlot* pUnitPlot = pLoopUnit->plot();
if (!pUnitPlot || pUnitPlot->isWater())
continue;

int iValue = pLoopUnit->GetMaxDefenseStrength(pUnitPlot, NULL, NULL, false, true);
if (iValue > iBestPlotValue)
{
iBestPlotValue = iValue;
pStartingPlot = pUnitPlot;
}
}
// Try to spawn on top of an existing land non-combat unit
if (!pStartingPlot)
{
for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
{
if (pLoopUnit->isDelayedDeath() || !pLoopUnit->IsCivilianUnit())
continue;

CvPlot* pUnitPlot = pLoopUnit->plot();
if (!pUnitPlot || pUnitPlot->isWater())
continue;

int iValue = max(1, pLoopUnit->getUnitInfo().GetProductionCost());
if (iValue > iBestPlotValue)
{
iBestPlotValue = iValue;
pStartingPlot = pUnitPlot;
}
}
}
// Just pick the first plot that a city can be founded on
if (!pStartingPlot)
{
CvMap& theMap = GC.getMap();
int iNumWorldPlots = theMap.numPlots();
for (int iI = 0; iI < iNumWorldPlots; iI++)
{
CvPlot* pLoopPlot = theMap.plotByIndexUnchecked(iI);
if (pLoopPlot->isWater() || pLoopPlot->isOwned() || pLoopPlot->IsAdjacentOwnedByTeamOtherThan(getTeam()) || !pLoopPlot->isValidMovePlot(GetID()))
continue;

if (pLoopPlot->getNumUnits() > 0 || pLoopPlot->IsEnemyUnitAdjacent(getTeam()))
continue;

if (!canFoundCity(pLoopPlot->getX(), pLoopPlot->getY()))
continue;

pStartingPlot = pLoopPlot;
break;
}
}
}

if (!pStartingPlot)
return NULL;

Expand Down Expand Up @@ -34723,6 +34791,40 @@ void CvPlayer::verifyAlive(PlayerTypes eKiller /* = NO_PLAYER */)
setAlive(true);
}
}

if (/*-1 in CP, 10 in VP*/ GD_INT_GET(COMPLETE_KILLS_TURN_TIMER) > -1)
checkCompleteKillsTimer();
}

void CvPlayer::checkCompleteKillsTimer()
{
if (!isBarbarian() && isAlive() && getNumCities() == 0 && getNumUnits() > 0 && GC.getGame().isOption(GAMEOPTION_COMPLETE_KILLS) && !HasActiveSettler())
{
int iTurn = GC.getGame().getGameTurn();
if (GetCompleteKillsTimerTurn() == -1)
SetCompleteKillsTimerTurn(iTurn);

int iTurnDifference = iTurn - GetCompleteKillsTimerTurn();
if (iTurnDifference >= GD_INT_GET(COMPLETE_KILLS_TURN_TIMER))
{
// Spawn a Settler somewhere!
addFreeUnitAI(UNITAI_SETTLE, false, 1, true);
if (HasActiveSettler())
SetCompleteKillsTimerTurn(-1);
}
}
else if (GetCompleteKillsTimerTurn() != -1)
SetCompleteKillsTimerTurn(-1);
}

int CvPlayer::GetCompleteKillsTimerTurn() const
{
return m_iCompleteKillsTimerTurn;
}

void CvPlayer::SetCompleteKillsTimerTurn(int iTurn)
{
m_iCompleteKillsTimerTurn = iTurn;
}

// --------------------------------------------------------------------------------
Expand Down Expand Up @@ -45946,6 +46048,7 @@ void CvPlayer::Serialize(Player& player, Visitor& visitor)
visitor(player.m_bExtendedGame);
visitor(player.m_bFoundedFirstCity);
visitor(player.m_iNumCitiesFounded);
visitor(player.m_iCompleteKillsTimerTurn);
visitor(player.m_bStrike);
visitor(player.m_bCramped);
visitor(player.m_bLostCapital);
Expand Down
9 changes: 7 additions & 2 deletions CvGameCoreDLL_Expansion2/CvPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ class CvPlayer

void initFreeState(CvGameInitialItemsOverrides& kOverrides);
void initFreeUnits();
void addFreeUnitAI(UnitAITypes eUnitAI, bool bGameStart, int iCount);
CvPlot* addFreeUnit(UnitTypes eUnit, bool bGameStart, UnitAITypes eUnitAI = NO_UNITAI);
void addFreeUnitAI(UnitAITypes eUnitAI, bool bGameStart, int iCount, bool bCompleteKills = false);
CvPlot* addFreeUnit(UnitTypes eUnit, bool bGameStart, UnitAITypes eUnitAI = NO_UNITAI, bool bCompleteKills = false);

CvCity* initCity(int iX, int iY, bool bBumpUnits = true, bool bInitialFounding = true, ReligionTypes eInitialReligion = NO_RELIGION, const char* szName = NULL, CvUnitEntry* pkSettlerUnitEntry = NULL);

Expand Down Expand Up @@ -1631,6 +1631,9 @@ class CvPlayer
void setEverAlive(bool bNewValue);
void setAlive(bool bNewValue, bool bNotify = true);
void verifyAlive(PlayerTypes eKiller = NO_PLAYER);
void checkCompleteKillsTimer();
int GetCompleteKillsTimerTurn() const;
void SetCompleteKillsTimerTurn(int iTurn);
bool isAlive() const
{
return m_bAlive;
Expand Down Expand Up @@ -3456,6 +3459,7 @@ class CvPlayer
bool m_bExtendedGame;
bool m_bFoundedFirstCity;
int m_iNumCitiesFounded;
int m_iCompleteKillsTimerTurn;
bool m_bStrike;
bool m_bCramped;
bool m_bLostCapital;
Expand Down Expand Up @@ -4267,6 +4271,7 @@ SYNC_ARCHIVE_VAR(bool, m_bPbemNewTurn)
SYNC_ARCHIVE_VAR(bool, m_bExtendedGame)
SYNC_ARCHIVE_VAR(bool, m_bFoundedFirstCity)
SYNC_ARCHIVE_VAR(int, m_iNumCitiesFounded)
SYNC_ARCHIVE_VAR(int, m_iCompleteKillsTimerTurn)
SYNC_ARCHIVE_VAR(bool, m_bStrike)
SYNC_ARCHIVE_VAR(bool, m_bCramped)
SYNC_ARCHIVE_VAR(bool, m_bLostCapital)
Expand Down

0 comments on commit 3e7eef5

Please sign in to comment.