Tommmsunb

New to modding KOTOR/TSL, looking for function and object definitions

Recommended Posts

Hello all, just as a quick introduction to me as this is my first post. I'm a game design student with an unhealthy obsession with Star Wars, I have something silly like 10000 or 15000+ hours cumulatively between SWG/SWTOR and all the other star wars games over the last 20 years. I started modding and programming on Empire at war making very basic mods for personal use only about 10 years ago as a teen but thats where my actual video game programming experience ends outside of stuff I've done in class or as assignments. I'm looking to expand my career portfolio and have some fun by making some mods for KOTOR/TSL. 

I've been familiarizing myself with NWScript and how things are handled in the game files and I still have a lot to learn. I'm a total noob as far as artwork and module design goes but I'm fairly adept at object oriented programming/scripting which is a skill I'd like to further polish through this endeavour, I'd also like to learn the aforementioned skills and start making models/meshes and levels. On an aside, I'd appreciate any literature/documentation/whateveryouhave that I can use for learning for any of the above and whatever else you might think could help me on my journey. 

Now that thats out of the way, here is the main purpose of my posting: I haven't been able to find actual definitions for the abstracts (or at least what I think are abstracts, you don't know what you don't know etc etc) in the Nwscript.nss in any of the files I've inspected in KOTOR tool

###from nwscript.nss###

// 485: Create a Modify Attacks effect to add attacks.
// - nAttacks: maximum is 5, even with the effect stacked
// * Returns an effect of type EFFECT_TYPE_INVALIDEFFECT if nAttacks > 5.
effect EffectModifyAttacks(int nAttacks);

// 486: Get the last trap detected by oTarget.
// * Return value on error: OBJECT_INVALID
object GetLastTrapDetected(object oTarget=OBJECT_SELF);

// 487: Create a Damage Shield effect which does (nDamageAmount + nRandomAmount)
// damage to any melee attacker on a successful attack of damage type nDamageType.
// - nDamageAmount: an integer value
// - nRandomAmount: DAMAGE_BONUS_*
// - nDamageType: DAMAGE_TYPE_*
effect EffectDamageShield(int nDamageAmount, int nRandomAmount, int nDamageType);

As you can see, the abstracts are here in nwscript.nss. I chose this particular excerpt because I'd like to 1. potentially add effects of my own that I could use for future projects and 2. Modify constraints on existing effects, namely the modifyattacks effect. As my first foray into this I'd like to increase the maximum on nAttacks so that I can give the player more options for increasing their damage. 

So. Are the definitions I'm looking for found in the engine itself or something?

From what I can tell in my ongoing investigation of the opensource re implementation of the Aurora engine called Xoreos found here https://xoreos.org/doxygen/da/d48/namespaceEngines_1_1KotOR2.html this doesn't seem to be the case, but I also haven't been very thorough. I also understand that KOTOR/TSL are ran by the odyssey engine; not the Aurora engine though odyssey is apparently based off of Aurora. I honestly couldn't tell you what the differences between the two are and am hoping I could be informed on that front as well :) 

TL;DR Any information you have on how nwscript/c/c++ work or constraints on making mods for kotor/tsl and especially where I can find the definitions of the functions I'm looking for would be greatly appreciated.

Thanks in advance!

  • Like 2

Share this post


Link to post
Share on other sites

Unfortunately, I don't think anything you mentioned can be edited. Everything defined in nwscript.nss is all we have to work with as far as scripting for the game, and the source for that is hard-coded. You'd have to crack the EXE to do anything about it.

1 hour ago, Tommmsunb said:

From what I can tell in my ongoing investigation of the opensource re implementation of the Aurora engine called Xoreos found here https://xoreos.org/doxygen/da/d48/namespaceEngines_1_1KotOR2.html this doesn't seem to be the case, but I also haven't been very thorough. I also understand that KOTOR/TSL are ran by the odyssey engine; not the Aurora engine though odyssey is apparently based off of Aurora.

Yes, xoreos is an open source implementation of the entire Aurora family, including KOTOR. Everything from Neverwinter Nights to Dragon Age 2. The open source part is the key point there, as it would theoretically allow for the sort of thing you want to do when completed.

It's not exactly in a playable state yet, but it might be more up your alley. And I'm sure they'd welcome any assistance.

  • Like 1

Share this post


Link to post
Share on other sites
Guest Qui-Gon Glenn

The KotOR Tool Script Editor has a built in function base. I highly recommend playing with it.

As mentioned above, the limits of the nwscript are our limits - we cannot add to it unfortunately. 

Share this post


Link to post
Share on other sites
4 hours ago, JCarter426 said:

Unfortunately, I don't think anything you mentioned can be edited. Everything defined in nwscript.nss is all we have to work with as far as scripting for the game, and the source for that is hard-coded. You'd have to crack the EXE to do anything about it.

Yes, xoreos is an open source implementation of the entire Aurora family, including KOTOR. Everything from Neverwinter Nights to Dragon Age 2. The open source part is the key point there, as it would theoretically allow for the sort of thing you want to do when completed.

It's not exactly in a playable state yet, but it might be more up your alley. And I'm sure they'd welcome any assistance.

I am in no way skilled enough to really offer any meaningful assistance to that project yet but I'll keep studying and maybe in time I will be. Who knows what the future may hold.

I'm disappointed but not surprised. Thanks for the reply!

I'll do some research on cracking exes but thats something Ive never even thought about doing, though I doubt anything I'd be able to produce after the learning process would be in any way distributable to others. Might be fun for me to play around with on my own playthroughs though :P


@Qui-Gon Glenn I'll play around with it and see if there's anything funky I can do.



EDIT:After a solid few hours of shenanigans I have good news and bad news.

The good news is I was able to isolate the address for nAttacks in the memory using cheat engine which implies that I can maybe find a way to locate related data using  odbg for cracking if I get smarter. I never thought I'd try to learn assembly/machine code before but here I am.

The bad news is that simply forcing the value to anything other than what it should be using cheat engine causes a crash as soon as you try to use any attack action. 

Which leads me to another question. Is there anywhere I can find debug/crash info?

No matter what, I'm enjoying this process so if I don't end up with anything to show for my work then I'll still be happy and won't give up.

Edited by Tommmsunb
  • Like 1

Share this post


Link to post
Share on other sites
20 hours ago, Tommmsunb said:

or at least what I think are abstracts

In C/C++-parlance, these are called "function declarations". They declare the name and parameters of a function, so that the function can be called. (Additionally, you have a comment explaining the function, which is not strictly necessary to call the function but helps the programmer.)

20 hours ago, Tommmsunb said:

So. Are the definitions I'm looking for found in the engine itself or something?

Yes. The whole functionality for these functions is inside the engine, inside the EXE. It can't be changed readily at all.

20 hours ago, Tommmsunb said:

From what I can tell in my ongoing investigation of the opensource re implementation of the Aurora engine called Xoreos found here https://xoreos.org/doxygen/da/d48/namespaceEngines_1_1KotOR2.html this doesn't seem to be the case

Wrong. The code and documentation of xoreos show explictly that the functionality is within the engine.

17 hours ago, Tommmsunb said:

The bad news is that simply forcing the value to anything other than what it should be using cheat engine causes a crash as soon as you try to use any attack action.

That's pretty much expected, yeah.

These engine functions usually check the parameters to be within their valid ranges. The rest of the code expects them to be still within the valid ranges, too. If you suddenly violate this expectancy, a crash is the most likely thing to happen. What you are doing is most probably invoking what's called "Undefined Behaviour", and the program might actually do everything it wants to in such a case. Common joking examples include eating your grandmother or letting demons fly out of your nose.

On a more serious note, the game might also not crash immediately, and just leave your game in a broken state (even carrying on in future save states), so that you might, for example, always get a crash in a later section of the game, or just not progress through the game at all. Because you're changing the game's memory to values the original programmers never thought about.

Essentially, what you'd need to do is to check every single location in the game that uses the value you changed, and verify that it still does the originally intended actions. And if you want it to do something additional or different, you need to make sure that it still makes logical sense in combination with the rest of the code. In addition to adding the new functionality, that is, which in itself is a tall order.

Frankly, I for one would disadvise you from going down that road, but it's your life.

  • Like 1
  • Light Side Points 1

Share this post


Link to post
Share on other sites
22 minutes ago, DrMcCoy said:

In C/C++-parlance, these are called "function declarations". They declare the name and parameters of a function, so that the function can be called. (Additionally, you have a comment explaining the function, which is not strictly necessary to call the function but helps the programmer.)

Yes. The whole functionality for these functions is inside the engine, inside the EXE. It can't be changed readily at all.

Wrong. The code and documentation of xoreos show explictly that the functionality is within the engine.

That's pretty much expected, yeah.

These engine functions usually check the parameters to be within their valid ranges. The rest of the code expects them to be still within the valid ranges, too. If you suddenly violate this expectancy, a crash is the most likely thing to happen. What you are doing is most probably invoking what's called "Undefined Behaviour", and the program might actually do everything it wants to in such a case. Common joking examples include eating your grandmother or letting demons fly out of your nose.

On a more serious note, the game might also not crash immediately, and just leave your game in a broken state (even carrying on in future save states), so that you might, for example, always get a crash in a later section of the game, or just not progress through the game at all. Because you're changing the game's memory to values the original programmers never thought about.

Essentially, what you'd need to do is to check every single location in the game that uses the value you changed, and verify that it still does the originally intended actions. And if you want it to do something additional or different, you need to make sure that it still makes logical sense in combination with the rest of the code. In addition to adding the new functionality, that is, which in itself is a tall order.

Frankly, I for one would disadvise you from going down that road, but it's your life.

Thanks a lot for the reply,

I'm guessing that a function declaration can't have multiple children like an abstract class/method could in java, or is that wrong?  Am I better off just looking for existing explanations of these concepts on stack overflow? (in other words are my questions annoying?) 

I haven't been able to find the functionality for effects so far in xoreos, could you link me to where you found that please?

I've heard that eating your grandmother example before somewhere, I love programming humour haha. 


I appreciate you advising me against going down this road, however assembly/machine code has been referred to in hushed tones thusfar in my schooling and while I can see why, I'd also like to understand it all  better (it kinda feels like a forbidden fruit if you feel me). I don't really expect to get anything usable out of learning about it but I like having knowledge for the sake of knowledge on things like this. I'll lower my hopes/expectations of what I can achieve mod-wise and separate the time in my schedule so that they're different endeavours. 

I'm starting to get a better idea of what I can realistically hope to achieve and can enter the next phase of planning for the mods I hope to create. Thank you very much everybody. 

Share this post


Link to post
Share on other sites
4 minutes ago, Tommmsunb said:

I'm guessing that a function declaration can't have multiple children like an abstract class/method could in java, or is that wrong?

That...depends. In C, you can't. In C++, you can overload a function, as long as the signatures, i.e. the number of parameters and their types, are different (internally, C++ "mangles" the identifiers, using a scheme that encodes the parameter types into the name).

In NWScript, you can't either. The compiler wouldn't know what to do.

When you write a script in NWScript, you use the compiler (for example, a modifed nwnnsscomp for Kotor, based on a open source reimplementation by the "OpenKnights Consortium" of the original NWN compiler, based on the work of Torlack who RE'd the stuff back in the day) to turn the C-like NWScript source (nss) into NWScript bytecode (ncs).

Internally, the bytecode doesn't know much about the engine functions anymore. The compiler looks into the nwscript.nss file to look for the name of the function, and then counts at the index of the function within the file. I.e. if it's the first function in nwscript.nss, the second, the third, etc. That number it puts into the bytecode file ncs.

So in the bytecode, you only have pushes onto the stack, for the parameters, that the compiler arranged there (and space for the return value), and then "call engine function 523".

The game, when running the script bytecode, takes that number, then knows what to do, and which parameters it takes.

I.e. with NWScript, you can't change the number of parameters, and the types, because that knowledge is hardcoded into the game. (Well, it's not impossible, just quite hard.)

What you could, theoretically, do is add a new function to the bottom, then manipulate the look-up function in the game to recognize it. You'd still have to add the functionality itself, though. It's still hard, just slightly less so.

(This could also be used to emulate overloading, by extending the compiler to map the overloaded functions onto later indices. Might not be worth the hassle, though.)

15 minutes ago, Tommmsunb said:

I haven't been able to find the functionality for effects so far in xoreos, could you link me to where you found that please?

We, err, don't have that implemented yet. :P

16 minutes ago, Tommmsunb said:

(it kinda feels like a forbidden fruit if you feel me)

It's not really that it's forbidden. It's just that you're setting yourself up for a lot of hard work and pain. And potentially failure, of course.

I know, coming from me, who's RE'ing games for fun, and who has too many projects and stuff to do for 10 lifetimes, that's a bit ironic. :P

Still, I still think the "best" way to resolve hardcoded things in KotOR is going over xoreos: getting xoreos in a playable and "done" state, so that improvements can be build upon xoreos. Not that this isn't a massive amount of work either, far from it, just that this opens up so many more possibilities.

If you're adding a single thing to KotOR using the manual binary-hackery method, it's way harder to be sure you didn't miss anything, you can't verify easily when you continue to work on it that you're not breaking it, it's harder to integrate with other people's work, etc.

You could instead do something similar, figure out how things for in the game and reimplement that in xoreos, bringing xoreos further along. It will not give you the gratification of having changed something in the original game as quickly, and still need to wait for other people to do similar things for other areas, but once it's all done, that's a far more stable base.

At least that's how I see it. YMMV and all that jazz. And to be fair, I started xoreos low-key in 2010, and while there has been progress, it's still far from done, nearly a decade later. It is what it is.

  • Like 1

Share this post


Link to post
Share on other sites

haha I didn't realize I was talking to the guy who started xoreos. I'm a fan of your work!

I'd be down to sign up and help out with Xoreos however I could as @JCarter426 suggested. Though as I said earlier in this thread I doubt I'd be all that useful as I'm greener than grass. That being said, I'll never turn down an opportunity to get career knowledge/experience even if I don't know if it would pay off down the line. You simply never know if something will pay off in life as unexpected circumstances are a natural part of the world and living.

As for the section about adding functions to nwscript.nss thats exactly what I was hoping I could do. Though I haven't actually found the lookup function so far in my inspections of kotortool, I'm assuming that's hardcoded? 


As for the hard work and pain, I'm the kinda guy that enjoys the journey regardless of if it pays off in the end. I have an abundance of time and energy as it stands right now and I'd like to use it.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.