Aller au contenu

Photo

Does Anybody Know If Any Special AI Variables Have Been Added To Any OC Creatures?


  • Veuillez vous connecter pour répondre
27 réponses à ce sujet

#1
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages
Hi All,

In my ongoing research into understanding the workings of creature AI, I have come to recognise that there is a lot of redundant code around. My question is aimed to try to narrow down which are the core AI scripts being used and to find a creature that uses them as an example of use.

As the key elements of creature AI appear to be set up as they spawn by setting flags according to variables set on the creature, then it stands to reason that somewhere, some creatures must have a variable of this nature attached to them. E.g. A creature set up to be stealthy would have the variable X2_L_SPAWN_USE_STEALTH with a value 1 attached to it. Then, within its OnSpawn, it would recognise that this creature is supposed to have the NW_FLAG_STEALTH variable condition set on it according to the following code:

if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_STEALTH) == TRUE)
    {SetSpawnInCondition(NW_FLAG_STEALTH);}

This then allows the creature to behave stealthy when and where appropriate - and seems to be checked in scripts like x0_i0_walkway.

However, in my quick search I was unable to find any creature that has these kinds of variable attached. I did not look too hard though and is why I am posting here, in case anybody can point me to a creatures (or creatures) that have examples of these types of variables attached and set on them.

Thanks in advance.

Lance.

Modifié par Lance Botelle, 24 mars 2011 - 06:21 .


#2
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
There is hardly anything using that stuff, does not affect it working, try it and see. Most is to solve one little problem and the devs moved on.

#3
MasterChanger

MasterChanger
  • Members
  • 686 messages
I've used X2_L_SPAWN_USE_STEALTH with some trigger-spawned creatures for a PW. It seems to work consistently in single-player testing, but I've also had reports of it resulting in wonky behavior, such as stealthy creatures walking slowly (in stealth mode) while being visible even to characters with hardly any detection.

I've also played around with the flags in x0_i0_behavior a bit and found them useful but in a limited way, and heavily dependent on whether you set them hostile or not. Using NW_FLAG_BEHAVIOR_HERBIVORE, for example, a creature will sometimes flee for a round or two. If it's attacked though, it will sometimes start back for a bit, move away, start back, and not be able to decide what it wants to do.

I know this doesn't answer your question about OC creatures, but hopefully it helps you in thinking about AI as you've been doing.

#4
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

MasterChanger wrote...

I've used X2_L_SPAWN_USE_STEALTH with some trigger-spawned creatures for a PW. It seems to work consistently in single-player testing, but I've also had reports of it resulting in wonky behavior, such as stealthy creatures walking slowly (in stealth mode) while being visible even to characters with hardly any detection.

I've also played around with the flags in x0_i0_behavior a bit and found them useful but in a limited way, and heavily dependent on whether you set them hostile or not. Using NW_FLAG_BEHAVIOR_HERBIVORE, for example, a creature will sometimes flee for a round or two. If it's attacked though, it will sometimes start back for a bit, move away, start back, and not be able to decide what it wants to do.

I know this doesn't answer your question about OC creatures, but hopefully it helps you in thinking about AI as you've been doing.


H MC,

Thanks for the post.

I do know that the NW_FLAG_BEHAVIOR_HERBIVORE uses the HenchDetermineSpecialBehavior function (if you are using the latest version of the default3 script) prior to the HenchDetermineCombatRound, which then does one or two checks prior to the normal HenchDetermineCombatRound actions. However, the weird thing is, I'm wondering if it will really do anything if called at the end of round combat (where it is found) as it only uses ClearAllActions without the TRUE parameter, which might prevent it from doing the run away functions that follows. (I thought you needed the TRUE parameter if the creature was in combat.) This may explain why it does not truly stop fighting and only keep running away sometimes.

It also raises the question (for me) as to why the script does not make use of the HenchTalentFlee or TalentFlee functions found elsewhere to achieve the running away as well? It seems like a lot of examples of similar code all trying to make a creature flee from combat. Why not just have one function that handles fleeing from combat with various checks within it if needed?

It does certainly keep me thinking ... I am thinking about writing my own "Talent" include library at the moment to make the selection of talents simpler and more straightforward.

Lance.

painofdungeoneternal wrote...

There is hardly anything using that stuff, does not affect it working, try it and see. Most is to solve one little problem and the devs moved on.


Unfortunately, that seems like a lot of wasted and uncoordinated programming then. :(

Lance.

Modifié par Lance Botelle, 24 mars 2011 - 07:50 .


#5
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
It works though, just not being used adequately, if all the code was coordinated i never would have had to do my CSL library. Quite a bit of modding NWN2 is just learning where things which already are implemented are located, either on the vault or in game. Even the code for formations is still in there from back in baldurs gate i imagine, and there is code written for a PSP i think by stormfront. That codebase is really really old, very complex, and still is better than it would be if they just started over.

#6
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages

Lance Botelle wrote...
It also raises the question (for me) as to why the script does not make use of the HenchTalentFlee or TalentFlee functions found elsewhere to achieve the running away as well? It seems like a lot of examples of similar code all trying to make a creature flee from combat. Why not just have one function that handles fleeing from combat with various checks within it if needed?


I am taking the SOD flee system, which akavit did, and regiggering it so it uses the master variable to implement a global skittish and fleeing. I am using the master variables ( set via spawn conditions ) to implement major and global behavior changes, and trying to organize the remaining 10 or so bits to best utilize this system.

If you ask "why" too much with the AI you are just going to give yourself a headache. We all know it should have been done different, but at this point we can only redo it completely, or figure out work arounds. That is like complaining that the marine corps is too violent. The AI is just too big to deal with, and most folks when needing to implement something will see it as much more efficient to add what they need on top instead of fixing the core issue and extending the current system to make it more versatile. Quite a bit of what i am doing is reviewing this carefully soas to refactor these tacked on changes so the resulting code is designed properly.

#7
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

painofdungeoneternal wrote...

I am taking the SOD flee system, which akavit did, and regiggering it so it uses the master variable to implement a global skittish and fleeing. I am using the master variables ( set via spawn conditions ) to implement major and global behavior changes, and trying to organize the remaining 10 or so bits to best utilize this system.

If you ask "why" too much with the AI you are just going to give yourself a headache. We all know it should have been done different, but at this point we can only redo it completely, or figure out work arounds. That is like complaining that the marine corps is too violent. The AI is just too big to deal with, and most folks when needing to implement something will see it as much more efficient to add what they need on top instead of fixing the core issue and extending the current system to make it more versatile. Quite a bit of what i am doing is reviewing this carefully soas to refactor these tacked on changes so the resulting code is designed properly.


Hi Pain,

I only ask "why" so as to try to understand what I can do to work with it. Posted Image I cannot help myself. I am not complaining, as opposed to being a little mystified as to why the coders did not remove some of the redundant stuff while writing the new. Posted Image

I certainly agree that it is (now apparent) to add what's needed on top of the core code, but even the "adding to" is not as straight forward to do until you understand what flag settings are still valid and which functions are still valid to add and use within the override script one writes.

I believe an entire manual could be written that explains which FLAGS can be set and used within an OnSpawn script, explaining what they actually do in detail as well. E.g. I now know that the NW_FLAG_FAST_BUFF_ENEMY works mostly from the monters HB script and applies a buff spell to itself if it spies an enemy PC within 40 meters. The list of spells it checks through is found within the hench_i0_ai, so I can get a feel of what the spell will likely be when the creature casts it. Part of the confusion and my continued questioning of what is happening, is when I find two versions of similar functions that do similar things ... e.g. x0_i0_talent contains the TalentAdvancedBuff function that is very similar to the one used in hench_i0_ai called HenchTalentAdvancedBuff. At first looking, one would determine that the latter is the latest one to use because of the scripts used in the latest NWN game. However, a global search of TalentAdvancedBuff shows that the older function is still used in quite a number of places, which suggests that it (and accompanying functions within the same include) may still be of valid use in some situations. (*)

The problem is, having just a list of flags that can be set is not helpful when trying to plan a creature's AI. We need information that explains what abilities, spells etc will be used at any given time, even if that is a list of possibilities as opposed to specifics.

(*) I am guessing that this is partly what you are trying to sort through ... and is something I was also trying to look at as well, so that I am using the most valid FLAGS and functions that relate to the most up to date (and valid) functions and scripts.

Surely, this speghetti  does not not need any more sauce/source. Posted Image

Lance.

EDIT: As another point and line of questioning ... HenchTalentAdvancedBuff only appears to buff a creature once. I am not 100% sure, but I have the impression that once this spell is cast, then that's it for the creature, the buff is set as done. That would imply the player could leave and come back later and the buff may have gone and the creature not have any other buff to do. It also means a creature will only set one buff and not continue to buff if given the time before going into combat. That's my first impressions, but would like to be told if thi si snot the case and if other variables are set to allow more buffing or later buffing in either case. If not, then this function would need updating to take this into account perhaps? Just one example of AI ignornace on my part.

Modifié par Lance Botelle, 24 mars 2011 - 09:24 .


#8
Kaldor Silverwand

Kaldor Silverwand
  • Members
  • 1 585 messages

Lance Botelle wrote...
As another point and line of questioning ... HenchTalentAdvancedBuff only appears to buff a creature once. I am not 100% sure, but I have the impression that once this spell is cast, then that's it for the creature, the buff is set as done. That would imply the player could leave and come back later and the buff may have gone and the creature not have any other buff to do.


Lance,

I think you've hit the nail on the head as to why the devs didn't use these features. Generally buffing is only going to be used with bosses and bosses are either placed or they have a triggered conversation. In both cases fast buffing makes sense just prior to battle beginning, not at the time they are spawned.  So instead the devs would write special scripts executed from the conversations or special on perceived scripts.

Most of the boss-type creatures I've seen in the OC and MotB have unique scripts rather than using the AI variables.The AI variables are easy to use but they are not that helpful if you are trying to tell a story and have interaction besides just fighting.

Regards

#9
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Lance i'd say you probably want to attack the problem this way. Take the variables which are known ( we have known about them a long time and they are on google, same ones largely were used in NWN1 ) and do some trial and error.

Trying to figure out which function is used when there are two that are the same is not going to help you. The question should be if i set this, does it actually work. The AI itself it incredibly involved, and reading it's code to figure out why such and such should happen is about as useful as a scientist reading the bible to develop new theories. By the time you look thru the code you could have fired up the game, done a test in game and seen if the variable being changed actually does work. Note i do this to almost every bit of code i do, as even things that look like they work tend to have issues preventing them from doing so.

Doing the thinking you are doing is what i am doing, however what i am doing is refactoring those two functions into one function, then doing alot of searches/testing to make sure it's fixed. Note i am giving this advice because after looking at it for 6 months i don't really have any clue what happens when any thread of this spagetti is pulled. I have just at this moment gotten henchspells so i can see it, i know it's important but up until now i had no way of knowing what values it was putting into the system. I can say its just too complex to be able to study it, by the time you get half of it figured out you will start forgetting where you came from. ( i have flowcharts i did which went hundreds of levels deep. ) I cannot understand the tangle, however i can pull threads and slowly piece by piece untangle it which is what i am dong.

However having said all that. To use the AI and twist it to your whims is alot easier to accomplish without looking behind the curtain. AI scripts there are plenty of examples of, and hardcoding what a creature does is more brute force than anything else. Those variables are also there and they work for the most part, which should save you time. I will try and look up what those variables are, and i already have known which functions are actually used ( i delete lots of functions which are just dead weight on the codebase ). Writing how to use those variables is a major task, one which i suggest you go on IRC and get knowledge from the masters.

I am also trying to comment out what is inside that editor so you can see what the 2da's are doing.

Quite a bit of the current AI is basically so much of a mess that everyone just sidesteps it and writes their own, even the devs. It will take alot of work to make it usable so it even comes close to making sense.

Modifié par painofdungeoneternal, 25 mars 2011 - 12:02 .


#10
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Ok to make this simple, the file called x2_inc_switches.nss holds the main constants. Open it up and document it. This guy's got the flags you set inside your module, on npc's which are the MOST important, and used by everything. If it's in here it's something you should use before other things.

Spawn conditions controls the master AI variable. This is defined in x0_i0_spawncond.nss and you use the ONE variable NW_GENERIC_MASTER and then set the value in toolset as an integer. ( ie if it's the 1st bit and the 4th bit, that is 1 + 8 = 9. Each bit up progresses like 1, 2, 4, 8, 16 and so forth. Good use for an online calculator.

Another good one to know is ginc_event_handlers.nss which has code to swap out via script the event handlers.

I am sure there are other ones, but just documenting what those do should be a good start. I could have sworn i did that already on the citadel but i can't find it at this point.

#11
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages
Hi Pain,
I'm back from the "land of nod". Posted Image

Anyway, yes, I did know about the x2_inc_switches and have already copied the switch names into my OnSpawn for easy recall. Although, I am consdiering using different variable holders for my own ease. There's no reason why not is there? After all, I don't think the holder is used specifcially anywhere else, and I find the OC ones too unwieldy. E.g. I would like to use if (GetLocalInt(OBJECT_SELF, "STEALTHY") == TRUE){SetSpawnInCondition(NW_FLAG_STEALTH);} rather than have to remember such things as const string CREATURE_VAR_USE_SPAWN_STEALTH = "X2_L_SPAWN_USE_STEALTH";





.... If it's in here it's something you should use before other things.

I agree. And having checked the comments and examined the code, I am beginning to have a better understanding of how they work. I have yet to track down the CREATURE_VAR_USE_SPAWN_AMBIENT and the CREATURE_VAR_USE_SPAWN_AMBIENT_IMMOBILE, which make creatures play "ambient animations", but do not really know what they mean by this. For instance, do spawned in creatures not move at all when they are first spawned in? This may be a really noob-like queston, but all my spawned in creatures do something at the moment (even if they just stand there and look around), so I do not know what extra animation these two conditions are meant to do. I know I could add them, test and see .... BUT ... that does not always answer my question as I may not wait long enough or not do the correct thing to make this happen. E.g. I added a cold aura effect to a creature, expecting to see an aura and be affected by cold when I approached it. In practice, nothing happened .... The reason being ... (a) I was used to and expecting an aura visual like NWN1 used to do, which is no longer the case in NWN2 and (B) the code did not apply damage if the creature did not see the PC as an enemy! Now I can understand this in some circumstances, but I had no idea that this was what was happening. Once I tracked down the code and examined some of the process myself, I could see how it was meant to work and therefore, not be surprised by apparent results of nothing.





Another good one to know is ginc_event_handlers.nss which has code to swap out via script the event handlers.

I was not aware of this one. Does it have anything to do with the SetCreatureScriptsToSet function, which I do use. If not, then maybe it is an area I do not understand. Anything that has things like "event_handler" seem a little trickier to use in my experience. Could you explain how this script is useful to know? Posted Image

However, I do have a couple of questions that are close to the end of my immediate enquiries (under the circumstances that it is easier to work around that "fix") and that is where do these two functions get defined (or what do they actually do?):

GetCreatureTalentBest and GetCreatureTalentRandom

With reference to the henchspells.2da, I can see it referenced inside hench_i0_spells ... so is it only used as a way to prioritise spells learned as opposed to spell ability? Is this the only place (script) where the 2da file is referenced?

Slowly getting there...

One last question, what do coders mean when they refer to a "prototype"? Does it mean the most basic function, which cannot be broken down further. i.e. The core functions rather than user created ones that use these "prototypes"? if so, are the above two functions protoypes?

Lance.

SOME PROGRESS:
==============

I looked closer at the NW_FLAG_FAST_BUFF_ENEMY flag and discovered that it applied more than one buff subject to a category and if the creature had the buff spell. However, it also treated the creature's special ability of the spell as having the spell, which was good to discover. (I thought it would only fire an actual spell as opposed to an ability.)

I was also able to reset the flag by using a AssignCommand(oCreature, SetSpawnInCondition(NW_FLAG_FAST_BUFF_ENEMY, TRUE)); when looping through creatures on a PC exiting the areas, which meant a creature would rebuff using the same spells as long as they had a number of them.

NB: Setting the number of spells to limitless appeared to stop the creature from using them at all! ??? Anybody else notice this?

I also set the NW_FLAG_FAST_BUFF_ENEMY to set TRUE by default for every creature ... no reason why not is there? After all, if the creature does not have the buffs, then it simply won't do anything with it. But surely its better for the creature to buff if possible?

I also found that using the TalentSpellAttack(oTarget); in an AI override script makes the creature cast any offensive spell I had given it ... and again, only up to the number it is given.

In this simple testing, my creatures are starting to look like they mean business.Posted Image

Modifié par Lance Botelle, 25 mars 2011 - 03:34 .


#12
kevL

kevL
  • Members
  • 4 056 messages

Lance Botelle wrote...

One last question, what do coders mean when they refer to a "prototype"? Does it mean the most basic function, which cannot be broken down further. i.e. The core functions rather than user created ones that use these "prototypes"? if so, are the above two functions protoypes?

A prototype gives the compiler just what it needs to start compiling a script. (how's that for ambiguous and 'guessy')

Say you have a void main() function, and write an external function for it (either in an include or right there in the same .nss file). The compiler wants the prototype of that external function (not sure if i'm using 'external' right here, etc.) first. Hence #include goes at the top of the page; so do extra functions, or if not the entire function, then its Prototype. Then you can put the function definition out of the way down at the bottom of the page ( after void main() ). example prototype:

// this function gets an object Bunny, sName defaults to "Daisy".
object GetBunny(string sName = "Daisy")

NB: Setting the number of spells to limitless appeared to stop the creature from using them at all! ??? Anybody else notice this?

It took me a while to find, rather stumble across this (again) .. i don't trust those 3 or 4 paramaters there. What are they? Readied, Spontaneous, Unlimited, & Metamagic. I set Metamagic to Extend, and others to Empower, but noticed that the assigned level of the spells did not increase correspondingly. Further, it sure seemed they became non-accessible by the AI, (although I could still call the spell manually). So unless someone figures out just how these work (on Properties->Spells tab of an NPC) .. bleh.

I looked closer at the NW_FLAG_FAST_BUFF_ENEMY flag and discovered that it applied more than one buff subject to a category and if the creature had the buff spell. However, it also treated the creature's special ability of the spell as having the spell, which was good to discover. (I thought it would only fire an actual spell as opposed to an ability.)

I was also able to reset the flag by using a AssignCommand(oCreature, SetSpawnInCondition(NW_FLAG_FAST_BUFF_ENEMY, TRUE)); when looping through creatures on a PC exiting the areas, which meant a creature would rebuff using the same spells as long as they had a number of them.

[snip to above]

I also set the NW_FLAG_FAST_BUFF_ENEMY to set TRUE by default for every creature ... no reason why not is there? After all, if the creature does not have the buffs, then it simply won't do anything with it. But surely its better for the creature to buff if possible?

sure, i mean Yeh!

I also found that using the TalentSpellAttack(oTarget); in an AI override script makes the creature cast any offensive spell I had given it ... and again, only up to the number it is given.

In this simple testing, my creatures are starting to look like they mean business.

excellent!

I'm trying to remember these things you've found, for further reference & use. I tend to jive with Pain's advice, which i interpret as "use the AI, but don't trust it" - so I tend to start with a defaultish, minimalistic setup, see what happens, then start scripting in extra action (including auto-buffing onAreaEnter or onPerception). eg, watch how Fighters handle their weapons: I put a composite Longbow into one of my Defenders' inventories, and he likes to equip it; but noticed that when he switches back to hand-to-hand he prefers using his sword two-handed style (w/out shield) .... changing that (to w/ shield) is beyond me, unless/until i find the function that does weapon switching.


ps. your more indepth questions above are way beyond me. Right now I'm trying to sort out why two of my ActionCastSpellAtObject() commands are going off instantly, when they're specifically set to not do that, and why my Priestess is seemingly casting two Bear's Endurances when i gave her only one (neither of them assigned as bCheat) ..

anyway, if & when you play around with the Animations, LB, remember that the onHeartbeat script might be getting in the way.

#13
MasterChanger

MasterChanger
  • Members
  • 686 messages

kevL wrote...

Lance Botelle wrote...

One last question, what do coders mean when they refer to a "prototype"? Does it mean the most basic function, which cannot be broken down further. i.e. The core functions rather than user created ones that use these "prototypes"? if so, are the above two functions protoypes?

A prototype gives the compiler just what it needs to start compiling a script. (how's that for ambiguous and 'guessy')

Say you have a void main() function, and write an external function for it (either in an include or right there in the same .nss file). The compiler wants the prototype of that external function (not sure if i'm using 'external' right here, etc.) first. Hence #include goes at the top of the page; so do extra functions, or if not the entire function, then its Prototype. Then you can put the function definition out of the way down at the bottom of the page ( after void main() ). example prototype:

// this function gets an object Bunny, sName defaults to "Daisy".
object GetBunny(string sName = "Daisy")


This is based on a traditional C-language distinction: a function must be "defined" but it can be "declared" first. When you see a function listed with a semicolon at the end and no brackets below it, that's declaring a prototype. When the full function is spelled out, that's a definition.

The reason to use prototypes is that order matters in C. If you define function A above function B, function A cannot call function B, because the compiler doesn't yet know what you mean by function B. You can just carefully define all your function in the proper order, or you can declare your prototypes at the top, and then define in any order you please. You could, for example, list all your prototypes, then your main() function, then define your functions, instead of putting main() at the bottom.

It's a bit of a stylistic thing (when I learned C programming in high school, the order we were taught was first declarations/prototypes, then main(), and last function definitions) but it can give you some flexibility.

Modifié par MasterChanger, 26 mars 2011 - 07:41 .


#14
kevL

kevL
  • Members
  • 4 056 messages
thanks MC

( i missed the semicolon, so )

object GetBunny(string sName = "Daisy");


#15
The Fred

The Fred
  • Members
  • 2 516 messages
It's also nice to keep all that code down at the bottom. The execution is going to jump around from function to function anyway, but you can at least have it start at the start (otherwise you have to scroll through loads of helper functions to find what the main() does). In an include file, there is no main() and no start, but you still want to see all of the available functions before reading the individual code.

#16
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
I would advise not using prototypes. About 15 or so major episodes with toolset crashing, which each took 2-3 weeks to diagnose and fix before i could script again, were caused by the official codebase having prototypes without a actual definition. There is no warning if in an include that is too deep, and in a lot of code it can be an issue when you move function from one include to another. I actually arrange functions in order to prevent the need for prototypes, and only use prototypes in chicken or the egg situations where there is no way to make the order work. I also have removed almost all includes which use developer includes just because i can't handle losing another 3 weeks to hunt down another dangling prototype, and basically think of them as plain evil.

Not saying everyone should do this, i just have way too much code to remember to delete the prototype everytime i zap a duplicate function, and less code always means less bugs to fix. Regardless MAKE SURE your prototypes and definitions always match, to the point of zapping all the prototypes and copying them again from your definitions.

If you want to have your code documented, i would suggest using javadoc and doxygen, putting the comments and description into your code, then if you need to learn the code you can just review the auto generated documentation

A good description of your code, your intentions and goals at the top of the file is good as well. Generally writing this, and outlining what you intend to do ahead of your code, basically doing the documentation prior to the code results in much better code when you can do it. Then as you write the code you tend to just follow the game plan.

Knightmare has a good tutorial on nwscript and scripting ( in his signature, in script resources thread with all the links, on vault and on google ). Probably need to go thru that as it addresses this question and quite a few other things a person new to the language should know from the get go.

#17
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages
Hi All,

Prototypes
=======

Now, while I have always done this (used prototypes), I never knew they were called that. I just thought it was "declaring the function" (not realising that is what is meant by prototype). I have already seen for myself how order of functions matters inside a script, because one function cannot fire another if called in the wrong order. (I write the prototype part immediatey above the function, so they are not all listed at the top, which, like Pain, I do not like and try to avoid.) E.g.

void FirstFunction(string sMessage); // So, this part is the prototype bit.
void FirstFunction(string sMessage)
{
CODE HERE
}

void SecondFunction(string sMessage); // So, this part is the prototype bit.
void SecondFunction(string sMessage)
{
CODE HERE
}

Etc.

OTHER
=====

KevL ..... It took me a while to find, rather stumble across this (again) .. i don't trust those 3 or 4 paramaters there. What are they? Readied, Spontaneous, Unlimited, & Metamagic. I set Metamagic to Extend, and others to Empower, but noticed that the assigned level of the spells did not increase correspondingly. Further, it sure seemed they became non-accessible by the AI, (although I could still call the spell manually). So unless someone figures out just how these work (on Properties->Spells tab of an NPC) .. bleh.

Agreed.



I am still interested if anybody can give me a better understanding of how GetCreatureTalentBest and GetCreatureTalentRandom work if possible?


Pain .... Knightmare has a good tutorial on nwscript and scripting ( in his signature, in script resources thread with all the links, on vault and on google ). Probably need to go thru that as it addresses this question and quite a few other things a person new to the language should know from the get go.

Sounds like this might be useful to get to learn some of the official terms and names ... for although I am a "reasonable" scripter, I tend to only pick up bits and pieces along the way. I will look out for it. Also, great CSL link. I wil take a closer look at some of those functions. I could have used some of these a while ago ... not too sure how easy it would be to go back and change stuff now.

Lance.

Modifié par Lance Botelle, 26 mars 2011 - 11:46 .


#18
kevL

kevL
  • Members
  • 4 056 messages

Lance Botelle wrote...

I am still interested if anybody can give me a better understanding of how GetCreatureTalentBest and GetCreatureTalentRandom work if possible?

This is odd (though not so much so, in light of what PoDE was just saying). I can't find the definitions for GetCreatureTalentBest or GetCreatureTalentRandom anywhere; only their prototypes/declarations, in nwscript.nss - yet they are referred to any number of times, and even have wrapper functions, GetCreatureTalentBestStd & GetCreatureTalentRandomStd, in x0_inc_generic


CSL is only a matter of time, afaiac.


nb. Also in nwscript.nss are 25 TALENT_CATEGORY_* constants - these might be helpful in finally figuring out how to make a creature drink a potion ... ;)

#19
MasterChanger

MasterChanger
  • Members
  • 686 messages
Nwscript.nss pretty much is the hard-coded stuff. You can find constants there and function prototypes, but you're not going to see function definitions for the stuff in there. We can wish that nothing was hard-coded (how great would it be to see/alter definitions of Effect*() functions???) but it's better to have the declarations and the comments about the functions than nothing at all.

Also, while I haven't used CSL to redo functions that I call all the time, there's some indispensable stuff in there when you don't know how to do something. For example, I'm clueless as to how to go between the hexadecimal masks that 2da's use for things like meta-magic and binaries. I started reading up on how to do a conversion for a project that I'm working on, then just for kicks decided to check the CSL. This handy CSLHexStringToInt function popped up, and it's better than what I could have written myself.

Modifié par MasterChanger, 27 mars 2011 - 02:56 .


#20
kevL

kevL
  • Members
  • 4 056 messages
ah :)

#21
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
The nwscript.nss defines the language itself, the prototypes are in a given order and the game uses this to store information in the ncs files. Anything in nwscript.nss is really defined in the engine itself and it kind of allows the correct ncs file to be compiled. Adjusting this file in anyway can make all scripts suddenly stop working since the engine is hard coded to match the order of things in this file. This file only contains variable definitions, and prototypes since how these functions work is not defined in a script we can edit.

How it works, well you need to refer to the documentation that comes with the game, or look at the resources for scripting for further community developed information. It has docs in that CSL link i provided ( look under file and i have two named nwscript_i for includes and nwscript_c for constants, and in the links to the lexicons for nwn1 and nwn2, also found in that thread, all things worth book marking. Also some information is on nwnwiki and nwn2wiki.

Note that as you learn things about functions, if you send me a message about how those functions work, or corrections to the documentation i will update that documentation. I am hoping to eventually either correct the in game documentation, or have set up a website with linked documentation with this information.

#22
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

MasterChanger wrote...

... Nwscript.nss pretty much is the hard-coded stuff. You can find constants there and function prototypes, but you're not going to see function definitions for the stuff in there.


I had a nasty feeling it would be down to this. So, it's not easy to determine what these functions actually do when called.

... This handy CSLHexStringToInt function popped up ...


Interesting.

PotED wrote ....

... How it works, well you need to refer to the documentation that comes with the game, or look at the resources for scripting for further community developed information. It has docs in that CSL link i provided ( look under file and i have two named nwscript_i for includes and nwscript_c for constants, and in the links to the lexicons for nwn1 and nwn2, also found in that thread, all things worth book marking. Also some information is on nwnwiki and nwn2wiki.


I will check these out. Many thanks.

PotED wrote ....

Note that as you learn things about functions, if you send me a message about how those functions work, or corrections to the documentation i will update that documentation. I am hoping to eventually either correct the in game documentation, or have set up a website with linked documentation with this information.


If I ever find anything, I will let you know. Although, I don't think I am confident enough to say anything for sure, but more likely present something as a "possibly".

Lance.

#23
The Fred

The Fred
  • Members
  • 2 516 messages
Incidentally, I don't think there's much point in declaring prototypes right before the function, because IIRC, you can just forgoe the prototype. You might want this if you need to arange the functions in a certain order, as pain was saying, for example putting prototype1, then function2, then function1, but personally I think this would make the code far more like spaghetti (and I think Pain was suggesting forgoing prototypes at all, NOT doing this, for the record).

Personally I find sticking all the prototypes at the top to be the best thing - if you find you are forgetting to remove them when you remove a function, fine, don't do it (I know that I often forget to change both the protoype and function when, say, editing the argument list, but you get an obvious error right away if you do that), but I find them more helpful than harmful.

#24
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages

The Fred wrote...

Incidentally, I don't think there's much point in declaring prototypes right before the function, because IIRC, you can just forgoe the prototype. You might want this if you need to arange the functions in a certain order, as pain was saying, for example putting prototype1, then function2, then function1, but personally I think this would make the code far more like spaghetti (and I think Pain was suggesting forgoing prototypes at all, NOT doing this, for the record).


The function implementation itself declares itself. This is just extra work.

Personally I find sticking all the prototypes at the top to be the best thing - if you find you are forgetting to remove them when you remove a function, fine, don't do it (I know that I often forget to change both the protoype and function when, say, editing the argument list, but you get an obvious error right away if you do that), but I find them more helpful than harmful.


I think to accomplish what you are doing - ie better documentation basically, you should learn to put javadoc comments in. Then you can read the documentation, and it will list errors you can look thru as well, has todos, show a map of all your functions and how they are used, and also forces you to spend some time thinking about making your code readable by others.

Don't always throw an error, especially if they are a few includes deep, i basically find errors like non matching, or even worse prototypes with no implementation all the time. Note some of the files listed are includes which are used almost globally. Some are just different parameters too.

These includes have errors in them of one sort or another, often prototype issues, there are others but i am imperfect in keeping track of everything, and frankly its so hard to detect these issues that i have taken to just redoing everything i need from the official codebase library line by line to ensure its not going to create a scavenger hunt. Pretty sure a few of these cause all the henchman to stand around and look stupid in the AI at random, for some reason the toolset compiles and runs even though the PRC compiler says its borked. 
nx2_s0_hlfrblst.nss
nw_s1_dragwbuffet.nss
ginc_companion.nss
x2_inc_switches.nss
nw_s0_icharm.nss
x2_inc_treasure.nss
nw_s0_1carrion.nss
x2_inc_banter.nss
nw_ch_ac3.nss
x2_inc_cutscene.nss

Less lines of code =  less errors, more lines of code = more errors, that is something which is not a fact, but it seems to always happen regardless just like all computers seem to end up with bugs. If you start hitting sudden crashes on compile or other wonkiness i generally go hunting for prototypes that don't match or don't have an implementation -- 90% of the time this is the root cause. And i seem to find it is an issue created by even the best coders in the community whose code is very very clean, i think it's just too easy to forget that prototype since it's not right next to the function. As such one of the first things i do when i use others code is zap all prototypes, then if there is a compile error add ones back in from the implementation.

Modifié par painofdungeoneternal, 30 mars 2011 - 07:00 .


#25
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

The Fred wrote...

Incidentally, I don't think there's much point in declaring prototypes right before the function, because IIRC, you can just forgoe the prototype. You might want this if you need to arange the functions in a certain order, as pain was saying, for example putting prototype1, then function2, then function1, but personally I think this would make the code far more like spaghetti (and I think Pain was suggesting forgoing prototypes at all, NOT doing this, for the record).

Personally I find sticking all the prototypes at the top to be the best thing - if you find you are forgetting to remove them when you remove a function, fine, don't do it (I know that I often forget to change both the protoype and function when, say, editing the argument list, but you get an obvious error right away if you do that), but I find them more helpful than harmful.



Hi The Fred,

Understood .... The only reason I have continued to place prototypes just before the function is that it can make them easier to find in a serch. :) When I see a double line Void() ... followed by the same void() ... I know that's it. It's a small and not very good reason, and probably one that (now I know it serves little other purpose) will probably stop doing. Posted Image Although, do they aid the compiler in any way to help find errors?

Lance.



Pain ... Less lines of code =  less errors, more lines of code = more errors, that is something which is not a fact, but it seems to always happen regardless just like all computers seem to end up with bugs.

Hi Pain,

I think it is because of the large number of include files tat go layers deep and cross reference each other that causes most headaches and errors. Personally, I have tried to keep the number of includes down to a minimum and only have about 3-4 at the moment. There is one very generic functions include that handles almost all my functions, and the rest are includes specific to certain procedures like handling text in my Readable Books or from others like Edward Beck's Calendar system (which I altered).

Just one question ... Can includes be of any size? I only mention this because I find my generic functions include is becoming very large and can sometimes get very slow to respond when I edit it.

Lance.

Modifié par Lance Botelle, 30 mars 2011 - 11:19 .