K-Mod: Far Beyond the Sword

keldath: I don't have it. I think karadoc meant to put the source code on GitHub after some more testing, but never did. The GitHub version is still 1.44b.
 
I really hope some karadoc-like mind would take over the work on K-Mod and keep it alive, or better karadoc himself be back :(
 
Firstly, a big fan to the mod :)

Ok this should go to thread "1000 clues you play Civ IV too much" since it was a dream about Civ IV but writing it here:

I had a dream where people were discussing about Civ IV. In that dream there was a person who brought up a very valid point about a thing and then someone said something like: your opinions isn't valid, you filthy K-Mod player. I just thought this was really funny :D
 
Hey guys, I've just wasted several hours trying to fix a bug in K-Mod that's not in base BtS. Perhaps one of you might like to take a crack at it. Here's how to produce the symptom: Worldbuilder yourself a barbarian city, add a barbarian archer and a barbarian fighter, then attack the city with a gunship. Unless the archer wins, your gunship conquers the city, which it should never be able to do. (Tipp: Search for "isNoCapture()".)
 
Hey guys, I've just wasted several hours trying to fix a bug in K-Mod that's not in base BtS. Perhaps one of you might like to take a crack at it. Here's how to produce the symptom: Worldbuilder yourself a barbarian city, add a barbarian archer and a barbarian fighter, then attack the city with a gunship. Unless the archer wins, your gunship conquers the city, which it should never be able to do. (Tipp: Search for "isNoCapture()".)

What do you mean by fighter? I think this bug is triggered when captureable unit is in city, i.e. worker.
 
What do you mean by fighter? I think this bug is triggered when captureable unit is in city, i.e. worker.

By "fighter", I mean a fighter aircraft. You can also use a jet fighter, trireme or missile cruiser (all visible units that can't defend against land units, yet aren't captureable).

I'm positive that it has to do with the XML tag <bNoCapture>. For units with that tag, isNoCapture() returns true. As I understand it, that tag has two intended effects. First, it makes the unit kill instead of capture captureable units. Second, it makes the unit unable to move into and thus conquer, occupy or "capture" enemy cities.

My best guess at the moment is that karadoc's changes to CvSelectionGroup::groupMove introduced the bug, but I've been at it so long, I can't think straight anymore.
 
So the problem only happens when there is a uncapturable unit left in the city, and you attack with a unit which cannot capture units/cities?
(so it works if there is a capturable unit instead or no unit at all, and also works if you attack with a normal unit)
 
So the problem only happens when there is a uncapturable unit left in the city, and you attack with a unit which cannot capture units/cities?
(so it works if there is a capturable unit instead or no unit at all, and also works if you attack with a normal unit)

Okay, I've gone back and ran more tests. It turns out having workers and settlers in the city produces the same result. That changes nothing, however. It only confirms my point that whether the extra units in the city are captureable or not is irrelevant.

Just to be clear: The problem occurs when the defending enemy city holds two or more visible units, at most one of which can defend. The problem does not occur with empty cities; those cities, gunships cannot take.
 
My best guess at the moment is that karadoc's changes to CvSelectionGroup::groupMove introduced the bug, but I've been at it so long, I can't think straight anymore.
This seems to be the culprit:
https://github.com/karadoc/Civ4-K-Mod/commit/20ee7503a4502ea777f06fe217e0f78e8b66c83e
The code in v1.44 leaves it to canMoveInto to prevent noCapture units from entering enemy cities. However, canMoveInto (strangely) doesn't ensure this when bAttack is set:
Code:
if (isNoCapture()) {
    if (!bAttack)
      if (pPlot->isEnemyCity(*this))
        return false;
}
When the city is empty, canMoveInto still returns false, but this seems rather coincidental; karadoc's comment about the respective clause: "I'm not entirely sure I understand what they were trying to do here. But I'm pretty sure it's wrong. (...)"

The easiest fix would be to restore the isNoCapture check from v1.43:
Code:
void CvSelectionGroup::groupMove(CvPlot* pPlot, bool bCombat, CvUnit* pCombatUnit, bool bEndMove)
{ // ...
  while (pUnitNode != NULL)
  { // ...
    if (pLoopUnit->canMove() && (bCombat ? pLoopUnit->canMoveOrAttackInto(pPlot) : pLoopUnit->canMoveInto(pPlot))
      [COLOR="Blue"]&& (!pLoopUnit->isNoCapture() || !pPlot->isEnemyCity(*pLoopUnit))[/COLOR]
    )
    {
      pLoopUnit->move(pPlot, true);
    } // ...
This worked on the few small examples I've tested it on, and shouldn't break anything else. It doesn't perfectly work when attacking with a group where a Gunship is the best attacker. E.g. with 1 Mechanized Infantry and 1 Gunship. (For some reason the game/AI then prefers to attack with the Gunship.) The Gunship kills the (single) defender, and only the Mech. Infantry moves into the city. If the Mech. Infantry would advance first, isEnemyCity would immediately become false, and the Gunship could also advance. Always moving noCapture units last seems to fix this problem, but the two attackers somehow still end up in separate groups (though both in the city tile). Upd.: Or rather - they're in the same group, but only the capturing unit is selected. Maybe better to keep it simple; still here's the code I've tried:
Spoiler :
Code:
for(int stage = 0; stage < 2; stage++) {
  pUnitNode = headUnitNode();
  while (pUnitNode != NULL) {
    pLoopUnit = ::getUnit(pUnitNode->m_data);
    pUnitNode = nextUnitNode(pUnitNode);
    if((bool)stage != pLoopUnit->isNoCapture())
      continue;
    // ...
  }
}
 
The easiest fix would be to restore the isNoCapture check from v1.43:
Code:
void CvSelectionGroup::groupMove(CvPlot* pPlot, bool bCombat, CvUnit* pCombatUnit, bool bEndMove)
{ // ...
  while (pUnitNode != NULL)
  { // ...
    if (pLoopUnit->canMove() && (bCombat ? pLoopUnit->canMoveOrAttackInto(pPlot) : pLoopUnit->canMoveInto(pPlot))
      [COLOR="Blue"]&& (!pLoopUnit->isNoCapture() || !pPlot->isEnemyCity(*pLoopUnit))[/COLOR]
    )
    {
      pLoopUnit->move(pPlot, true);
    } // ...
Strangely, this crashed my game. The following worked however.
Code:
void CvSelectionGroup::groupMove(CvPlot* pPlot, bool bCombat, CvUnit* pCombatUnit, bool bEndMove)
{ // ...
  while (pUnitNode != NULL)
  { // ...
    if (pLoopUnit->canMove() && (bCombat [COLOR="Blue"]&& (!pLoopUnit->isNoCapture() || !pPlot->isEnemyCity(*pLoopUnit))[/COLOR] ? pLoopUnit->canMoveOrAttackInto(pPlot) : pLoopUnit->canMoveInto(pPlot)))
    {
      pLoopUnit->move(pPlot, true);
    } // ...
If the Mech. Infantry would advance first, isEnemyCity would immediately become false, and the Gunship could also advance. Always moving noCapture units last seems to fix this problem, but the two attackers somehow still end up in separate groups (though both in the city tile). Upd.: Or rather - they're in the same group, but only the capturing unit is selected.
The reason for that would appear to lie in CvUnit::updateCombat:
Code:
bool bAdvance = false;

if (isSuicide())
{
  kill(true);

  pDefender->kill(false);
  pDefender = NULL;
}
else
{
  bAdvance = canAdvance(pPlot, ((pDefender->canDefend()) ? 1 : 0));

  if (bAdvance)
  {
    if (!isNoCapture())
    {
      pDefender->setCapturingPlayer(getOwnerINLINE());
    }
  }


  pDefender->kill(false);
  pDefender = NULL;

  if (!bAdvance)
  {
    [COLOR="Blue"]changeMoves(std::max(GC.getMOVE_DENOMINATOR(), pPlot->movementCost(this, plot())));
    checkRemoveSelectionAfterAttack();[/color]
  }
}
 
Strangely, this crashed my game. The following worked however. [...]
I thought this would come down to the same thing (because canMoveInto returns false when isNoCapture and isEnemyCity) - apparently not.
The reason for that would appear to lie in CvUnit::updateCombat:[...]
Ah, yes, looks like it. Good to know, but not so easy to fix. Oh well.
 
I thought this would come down to the same thing (because canMoveInto returns false when isNoCapture and isEnemyCity) - apparently not.

I thought so too.

Ah, yes, looks like it. Good to know, but not so easy to fix. Oh well.

Yes, too bad this feature appears to be a lot harder to implement than karadoc seems to have thought. But the bug is gone, so I'm satisfied. :)
 
I've been looking for to activate the sentry plus healed button, sentry land units, sentry sea units etc that normally come with BUG, but I've haven't found them. Aren't these included in K-Mod?
 
I've been looking for to activate the sentry plus healed button, sentry land units, sentry sea units etc that normally come with BUG, but I've haven't found them. Aren't these included in K-Mod?

Those are not in BUG, they are in BULL since they require DLL-changes. So if you want them I guess you'll have to copy the code from BULL.
 
It seems that there's an OOS bug which happens when someone on Windows 7 plays with someone on Windows 8/10. It starts happening approx after 200th turn on normal speed. I'll try to check what's happening.
 
Hey everyone, I've been getting into DLL-modding and am working on my idea of how Civ4 should have been released in the first place (which AFAIK is basically the same as what karadoc set out to do when starting K-Mod). I'm using K-Mod v1.44 as a base. It's nowhere near complete, but with karadoc having been silent for so long, I thought I'd make a stripped down version as close as possible to K-Mod v1.44 that could also be enjoyed by K-Mod lovers who don't share my taste for more radical changes. I'll add it to this post as an attachment. It's basically K-Mod v1.44 + Platyping's Platypedia + Afforess' Advanced Automations + most of Pep's New Sentry Actions + some other changes you probably won't even notice. It hasn't been tested extensively because, as I said, it's merely a stripped down version of what I'm actually working on, but bug reports (and other forms of feedback) are welcome nonetheless.
 

Attachments

  • Mod-Z_v0.01.7z
    3 MB · Views: 50
Top Bottom