Skip to content

[Draft] Bugfixes and routines#62

Draft
modawan wants to merge 29 commits intoseedhartha:masterfrom
modawan:wip
Draft

[Draft] Bugfixes and routines#62
modawan wants to merge 29 commits intoseedhartha:masterfrom
modawan:wip

Conversation

@modawan
Copy link
Copy Markdown

@modawan modawan commented Jul 27, 2025

Hi, thanks for amazing work! I wanted to quickly check how the engine works and got carried away.

Here is a bunch of bug fixes and implementation of routines that appear in combat scripts and cutsceens. With these patches, I don't see anything major missing for combat (routines-wise, the actual combat is still very much broken). Endar Spire works fine until the duel, and then enemies spawn as neutral and lock the progress.

This is just a heads-up, no need to review the branch as it is now. I'm going to change some commits later and split them into separate pull-request where it makes sense. I also need to figure out how to make unit tests at least for some of these patches.

Next I plan to check what we need to fix combat.

modawan added 29 commits July 27, 2025 13:53
The check is supposed to bypass currently active object (e.g. the
player), but it was always active, effectively disabling selection of
any object.
The clip "nm15aacomp04000_" (Dantooine starmap terminal) was NULL and
caused a crash.

While the patch avoids a crash and the terminal opens, there is some
"static" unpleasant noise. Perhaps the audio system goes mad, and
there should be another fix.
This caused mouse wheel events to never register in game GUI.
This sets a table of faction reputations (enemy, neutral, friendly).
With this change, on TAR_M02AD we can now transition from the dialog
to combat.
The function used to be called GetLastAttackObjectAction, but the name was
inconsistent with other KOTOR tools.

The function should return a type of the last attack action (AttackObject,
CastSpell, etc.)

For this routine (as well as for other GetLast* routines) the patch adds a
combat history that keeps all past attacks for each creature.
The function returns AttackResultType as int (HitSuccessful,
CriticalHit, etc.)
For GetCreatureTalentBest and other talent-related routines, it is
benefitial to store feats and spells in a sorted data structure with
random access.

This allows us to find a feat/spell by category (binary search), and
then iterate over elements to find the one matching criteria.

Same approach should work for GetCreatureTalentRandom, but with
std::lower_bound + std::upper_bound.

It should also be benefitial to replace std::unordered_map with
another array (sorted by type). With low number of elements (~100) it
should be better for performance, but this is off-topic for this
patch.

The patch also initializes spells and feats globals.
The patch adds GetAttemptedSpellTarget to get the last target of a
spell, as well as infrastructure to support other GetAttempted*
routines.

Every object now stores a history of its combat actions. For now, only
spell actions are added, but it should support attack, move, and other
actions as well.

There is an existing Character::getAttemptedAttackTarget() that is
used for GetAttemptedAttackTarget routine, but I think it doesn't
follow semantic of GetAttemptedAttackTarget. It only checks for the
current action, while the documentation suggests that it should search
for previous actions if the current one has a different type. For
example, when an attack is followed by a move,
GetAttemptedAttackTarget should return the attack even when it is no
longer "current".

There is some overlap between Combat::attackHistory() and
Creature::combatActionHistory():

  - Combat::attackHistory() contains only "attacks", but they are
    augumented with resultType (hit, miss) and damage.

  - Creature::combatActionHistory() contains all actions performed by
    creature during combat. This includes move, spells, and attacks
    as well.
This is more of a workaround until Combat can deal with spells. Until
then, we search through action history and find a spell that targeted
an enemy.
It seems there are no MoveToObject actions in combat scripts.
This should be equivalent to UseFeatAction.
…untested)

This seems to only be called on party characters, and they are unable
to use talents now. Therefore the patch is untested.
Variable `offset` was a reference to an element that is removed by the
subsequent `controls.pop()`, and later used to call
`control.render()`. The patch turns it into a copy by value instead to
avoid this.

The error was highlighted by Clang address sanitizer.
It is unclear what exactly an "encounter" means, but it seems that
OnSpawn scripts use GetIsEncounterCreature to give objects created by
CreateObject items (grenades, credits).
When forceNPC is -1, it becomes 1 after conversion to bool. This
breaks the logic by forcing NPC 1 to be a party member even when it is
not available.

The patch fixes a crash on Endar Spire after party selection screen.
std::static_pointer_cast does not perform a check - it casts an object
as if it was a Creature, so creatureActor is never null.
@modawan
Copy link
Copy Markdown
Author

modawan commented Dec 29, 2025

Development of reone continues in https://github.com/modawan/reone. Feel free to join the effort! There are a lot of open issues you can work on. Please join OpenKotOR Discord server to discuss the project.
Once we hear back from Seedhartha, we can figure out a long-term plan.

This PR is outdated. Most of these patches are finalized and integrated into the fork.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant