Jump to content

CRE modding questions


Miloch

Recommended Posts

You'll have to muck around with the scripts anyway :) Unless you use wildcards in the script, they're still going to have to be told to cast spells they've memorized.

 

Which is probably why Bioware, and so many modders, generally don't bother with the spell memorization: you can do it all in the script, or you can change the script and also play with the .cres.

 

If I'm recalling correctly, there's a limit in OCAML syntax to which WeiDU is already dangerously close, which makes the Bigg leery of adding more of these high level functions (especially ones that aren't desperately necessary and can be easily replicated with macros.)

 

I don't know why REMOVE_MEMORIZED_SPELL exists, really.

Link to comment
Another basic question, and something rather hard to determine via testing. When you add armour to a CRE via patching, does that also mod its AC automatically, or do you also have to set its effective AC? I guess the same goes for modding DEX...
As berelinde says, these bonuses are automatic. I think a PC's true AC will always be 10; probably the effective AC too, but I don't know if the game stores it as the current effective or just the base. For NPCs, you may just want to play around with it until you find something you like. They should get the AC bonuses, but you might want something a little tougher than what the engine will automatically give you.
I feel a bit uneasy about modding a dynamically-set attribute, so I'm sticking with modding Dex appropriately. In some special cases, I'm adding or improving actual armour (setting it as UNDROPPABLE if it would create unnecessary clutter or overpowered items). This is all applicable to non-joinable NPCs (enemies). Any argument for or against this approach vs. setting Effective AC?
If in Baldur's Gate, the spears proficiency was also used as the halberds proficiency (i.e., you stick points in spears to become proficient with halberds), then it would also apply to items with the halberds category... If it's Tutu or BG2, you should probably stick with new-style proficiencies. If you need to do a lot of NPCs and they test fine using old-style proficiencies, then I wouldn't bother converting them or really worrying about it (and you won't need LAUNCH_PATCH_MACRO to WRITE_BYTE 0x6e 0x3 :D ).
This is still grey area that I'm finding difficult to test, and I'd rather have a definitive answer than operating off guesswork. You would think Tutu uses the BG2-style proficiencies by default, but in fact all the CREs I looked at have the BG1-style proficiencies set (and no BG2-style ones that I can tell). Unless the Tutu engine does some sort of dynamic conversion behind the scenes? Or if it is indeed, as devSin implies, the case that BG1 settings *also* cover the BG2 proficiencies? If not, I will use Nythrun's patch for the Tutu/BGT section and regular BG1 settings otherwise. But I would prefer to avoid redundant or excessive code if possible (though I don't want to waste the code someone took the time to write either :rant:).

 

Finally, I'm not sure why I had this question written down, but I'm sure there's a reason buried somewhere in my to-do list. What happens if you try to copy files over in WeiDU to a directory that doesn't exist? Does the directory get created, is there an error message, or does the copy fail with no error?

 

Thanks in advance to all you masters of Wei-Fu. :)

Link to comment

In the .cre file, effective AC should be whatever the base AC was - the engine will take it from there. You can set base AC to a value lower than 10 if you want though.

 

If you're working with either BGT or tutu you'll probably want to be using the old-style proficiencies, actually. I just found out that creatures aren't being updated to use v.2 effs, so the code I'd posted is of no use to you. Won't matter unless you need dual-wielding or some other unavailable proficiency type.

 

WeiDU should fail with a directory does not exist error unless the folder in question is the one designated as BACKUP, if I remember correctly (though you can always use the MKDIR patch to ensure the folder you want exists).

Link to comment

Thanks for the answers. If no one's reported a glitch in proficiencies in BGT/Tutu yet I guess we'd have to assume it's working as expected. But how would you know for sure? I have seen people reporting Tutu and BGT are a lot easier than BG1 (hence the need for stacking a bunch of "harder" mods like SCS - practically a requirement for BGT apparently). Anyway, it makes it easier for me if I just have to worry about the BG1-style proficiencies. :rant:

You'll have to muck around with the scripts anyway :) Unless you use wildcards in the script, they're still going to have to be told to cast spells they've memorized.
But what if they haven't memorised them?

 

A lot of the Dudleyfixed CREs are amended as follows:

25.01.05 Fixed WUDEI.CRE

Wudei, AR0123 - should have Entangle removed from her arsenal of spells as it is exclusively for Druids.

1. Remove Entangle from Known and Memorized spells (add Miscast Magic and Command).

2. Sex and Gender should be Female.

#2 is an easy fix. I guess the first part of #1 is too, with the REMOVE_X_SPELL commands. The second part is a bit trickier. The race script for _WUDEI.CRE is _PRIEST4 which has the following block:

IF
See(Nearestenemyof(Myself))
Havespell(CLERIC_COMMAND)
!Statecheck(Nearestenemyof(Myself),STATE_SLEEPING)
!Statecheck(Nearestneemyof(Myself),STATE_HELPLESS)
THEN
RESPONSE #100
  Spell(Nearestenemyof(Myself),CLERIC_COMMAND)
END

I know jack about scripting, but I'm interpreting this to mean the CRE will cast Command if she "has" it (memorised I would assume, instead of just known) on an enemy who isn't incapacitated. What would the syntax be if the CRE does not have Command in her spellbook (and/or memorised)? (I guess the same would also apply to 'Miscast Magic' which isn't referenced at all in the current script.)

I don't know why REMOVE_MEMORIZED_SPELL exists, really.
I guess this is one use? The script by default has the CRE casting Entangle if known. So in theory, you could use either REMOVE_MEMORIZED_SPELL to take it out of the spellbook or remove the Entangle block from the script (or both perhaps), but this is a generic script that might be used by, say, regular druids who should actually be able to use it. So the REMOVE command is probably better.

 

For that matter, if I am modding a standard script to this extent, should I really be EXTENDing it, or copying a new version with my prefix over and patching it on to the CRE?

 

I checked to see how Dudley actually handled this. Turns out it's described as a completed fix, but the Fixpack does not actually contain the fix at all. :D Neither does Tutu.

Link to comment
But how would you know for sure?

Both devSin and I have tested it pretty throughly at this point :) They work fine in the BG2 engine - but feel free to check yourself!

 

Your scripting example is one of those rare cases when the script actually bothers to check if the spell is memorized, hee.

 

The only spell related scripting action that cares if you have a spell memorized is Spell() (well, SpellRes() does too).

 

If you give this to Minsc:

IF
 True()
THEN
 RESPONSE #100
SPELL(Myself,WIZARD_STONE_SKIN)
END

He'll stand around ninnily trying to cast something he can't. But change the Spell to SpellNoDec or ForceSpell or ReallyForceSpell and he'll happily chain cast his Stoneskins.

 

For that matter, if I am modding a standard script to this extent, should I really be EXTENDing it, or copying a new version with my prefix over and patching it on to the CRE?

 

If there's a HaveSpell() check in the .baf, you don't need to touch the scripts, as the action will be skipped once you remove the spell.

 

Otherwise, yeah, you may want to redo the script. I dunno how many of my peculiar coding habits you want on your doorstep though :rant: I'd probably copy of the .cre, check if it's a cleric class of some kind, check if it's got the default script assigned, then if both are true, start an inner action that runs a replace textually on the script and saves it under a new name to be punched into the relevant script slot. REPLACE_BCS_BLOCK is not very good.

Link to comment
If there's a HaveSpell() check in the .baf, you don't need to touch the scripts, as the action will be skipped once you remove the spell.
Right. But I want to add spells too (that's kind of the difficult part here):
1. Remove Entangle from Known and Memorized spells (add Miscast Magic and Command).
And ideally, I want her to be able to cast the added spells only once (or maybe twice) to emulate what would be the case if she had them memorised. So the forced chain-casting of Command wouldn't really be appropriate. :rant:

 

Is there a reference for these scripting commands somewhere? I was putting off learning these for now (having enough trouble with WeiDU syntax) but I guess it'll be necessary. :) Cheers.

 

Edit: Nevermind the struck question... It's in the IESDP; I knew that, just braindead. :D

Link to comment

This is the way it's usually done:

IF
 GLOBALLT("MyPrefixMiscastMagic","LOCALS",2)
THEN
 RESPONSE #100
SpellNoDec(NearestEnemyOf(Myself),CLERIC_MISCAST_MAGIC)
IncrementGlobal("MyPrefixMiscastMagic","LOCALS",1)
END

 

Obviously, you'll want something less dumb for the targetting (e.g. ([GOODCUTOFF.0.0.LONG_BOW]) ) but that's a start.

 

Aside from the Iesdp I'm not sure where to point you, though SimDing0 did a scripting guide awhile back that you may find useful.

Link to comment
Obviously, you'll want something less dumb for the targetting (e.g. ([GOODCUTOFF.0.0.LONG_BOW]) ) but that's a start.
I'm a bit confused there. Where would that go, and what would be realistic values for a cleric spell (not LONG_BOW I'm assuming)? Also, where do I declare "MyPrefixMiscastMagic" or whatever as a variable (or do I need to declare it if I'm just assigning values to it in a script)? I guess I should repeat I'm a complete neophyte at scripting (of this nature anyway, though it doesn't look like rocket science either). :rant:
Aside from the Iesdp I'm not sure where to point you, though SimDing0 did a scripting guide awhile back that you may find useful.
After some searching, it looks like that would be this. I'll probably read it at length, though it may be as intelligible to me as Old Assyrian or even WeiDU (not implying a defect in the guide but in my own understanding). Cheers.
Link to comment

Scripting variables don't have to be declared, if they've never been set to any value the engine defaults to zero.

 

The snippet I mentioned is IDS targetting - it checks EnemyAlly ids and only targets partymembers, party allies, and summons, ignores the next two fields, and only casts on mages (LONG_BOW and the MAGE_ALL class mask share the same integer value, 200 if I remember correctly, so the script looks stupider than it is).

 

This is done to ensure that hostile creatures only target the party with their spells, and to ensure that they only cast miscast magic on someone who can actually cast some magic (it does no good to cast it on Kagain!). You'd probably want to include priests also in a real script, it's just a terrible example :rant:

 

Sim's guide is pretty good despite being old and covers a lot of useful stuff - play around with it :)

Link to comment
LONG_BOW and the MAGE_ALL class mask share the same integer value, 200 if I remember correctly...
In BG2, LONG_BOW and MAGE_ALL are both assigned in CLASS.IDS at 202. In Tutu, there are 2 identical values for MAGE_ALL at 202. Is this a bug? Does it matter which you refer to (in the case of BG2 anyhow)?

 

So I'm working through the scripting guide... about halfway through I found some good examples of what I want to do. I adapted them and your examples along with the existing script to the following:

IF
 OR(5)
See(NearestEnemyOfType([GOODCUTOFF.0.0.BARD_ALL]))
See(NearestEnemyOfType([GOODCUTOFF.0.0.DRUID_ALL]))
See(NearestEnemyOfType([GOODCUTOFF.0.0.CLERIC_ALL]))
See(NearestEnemyOfType([GOODCUTOFF.0.0.MAGE_ALL]))
See(NearestEnemyOfType([GOODCUTOFF.0.0.SORCERER]))
 False()
 GLOBALLT("T-MiscastMagic","LOCALS",1)
 !Statecheck(LastSeenBy(Myself),STATE_SLEEPING)
 !Statecheck(LastSeenBy(Myself),STATE_HELPLESS)
THEN
 RESPONSE #100
SpellNoDec(LastSeenBy(Myself),CLERIC_MISCAST_MAGIC)
IncrementGlobal("T-MiscastMagic","LOCALS",1)
END

IF
 See(NearestEnemyOf(Myself))
 GLOBALLT("T-Command","LOCALS",1)
 !Statecheck(NearestEnemyOf(Myself),STATE_SLEEPING)
 !Statecheck(NearestEnemyOf(Myself),STATE_HELPLESS)
THEN
 RESPONSE #100
SpellNoDec(NearestEnemyOf(Myself),CLERIC_COMMAND)
IncrementGlobal("T-Command","LOCALS",1)
END

The result I want is for the CRE to cast Miscast Magic once on the closest spellcaster enemy (if there is one who isn't sleeping or helpless - last listed being highest priority) and then cast Command once on the closest enemy (if you're closest *and* a mage, you're hosed :rant:). Will this work?

 

Also, this CRE has the following scripts:

Override: _SHOUT

Class: NONE

Race: _PRIEST4

General: NONE

Default: _TASIGHT

 

So could I make a new script out of the above and assign it to her class script, instead of modding her race script which is used by other CREs? It will take precedence over the race script (which has other spells like Animal Summoning and Glyph of Warding), correct?

Link to comment
Is this a bug? Does it matter which you refer to (in the case of BG2 anyhow)?

.ids files are translation lexicons for the engine - it looks up MAGE_ALL (which doesn't mean anything) in class.ids until it finds MAGE_ALL, then looks up the numeric value (which can be directly compared to a byte in the .cre, and does mean something) So this isn't harmful. It would be a problem in Tutu iff there are scripts which look for LONG_BOW when they want to use the mage classmask. There definately are such scripts in BG2, but I don't know about Tutu (text search in NI will let you know in short order if you're curious :) )

 

Will this work?

Almost :rant:

 

The False() in your first block ensures that that block will never execute - the engine will parse it, and attempt to run it, (checking the nearest enemy's type in the process and setting NearestEnemyOfType) - and then not do anything. You can make this work by either pulling the targetting bit out into a separate block , replacing it in the Miscast Magic Block with another targeting check and keeping the False() in there in a seperate block that only sets targeting and does nothing else, or you can remove the False() entirely, either will work.

 

So could I make a new script out of the above and assign it to her class script, instead of modding her race script which is used by other CREs? It will take precedence over the race script (which has other spells like Animal Summoning and Glyph of Warding), correct?

 

The class script will take precedence, but the race script will still be running, and will still impel the creature to take some actions. All of the scripts on the creature will run fifteen times a second. It's always possible to replace scripts only if they're default or empty values by using PATCH_IF in the .tp2, so that might be the route you wish to go.

Link to comment
It would be a problem in Tutu iff there are scripts which look for LONG_BOW when they want to use the mage classmask. There definately are such scripts in BG2, but I don't know about Tutu (text search in NI will let you know in short order if you're curious :D )
Apparently when they renamed the IDS entry, they renamed all the BCS values too (so it's MAGE_ALL instead of LONG_BOW). Makes the scripts look less stupid I guess (they all appear to be referring to mages, not long bows :rant:).
The False() in your first block ensures that that block will never execute - the engine will parse it, and attempt to run it, (checking the nearest enemy's type in the process and setting NearestEnemyOfType)
It sets LastSeenBy, correct? The scripting guide says this:
The False() trigger's primary use is in targetting, to ensure that LastSeenBy is stored correctly, but the script does not execute blocks unnecessarily or restart.
So I was interpreting this to mean it doesn't execute anything between IF and THEN (nothing is executable anyway) but I guess it means everything between IF and END. So how about this:
IF
 OR(5)
See(NearestEnemyOfType([GOODCUTOFF.0.0.BARD_ALL]))
See(NearestEnemyOfType([GOODCUTOFF.0.0.DRUID_ALL]))
See(NearestEnemyOfType([GOODCUTOFF.0.0.CLERIC_ALL]))
See(NearestEnemyOfType([GOODCUTOFF.0.0.MAGE_ALL]))
See(NearestEnemyOfType([GOODCUTOFF.0.0.SORCERER]))
 False()
THEN
 RESPONSE #100
END

IF
 GLOBALLT("T-MiscastMagic","LOCALS",1)
 !StateCheck(LastSeenBy(Myself),STATE_SLEEPING)
 !StateCheck(LastSeenBy(Myself),STATE_HELPLESS)
THEN
 RESPONSE #100
SpellNoDec(LastSeenBy(Myself),CLERIC_MISCAST_MAGIC)
IncrementGlobal("T-MiscastMagic","LOCALS",1)
END

Should I put the GLOBALLT check also in the first block, or doesn't it matter much (will it slow things down with/without it)?

The class script will take precedence, but the race script will still be running, and will still impel the creature to take some actions. All of the scripts on the creature will run fifteen times a second. It's always possible to replace scripts only if they're default or empty values by using PATCH_IF in the .tp2, so that might be the route you wish to go.
I think that's what I want - both scripts functional but this one taking precedence (once the variables reach 1, this script does nothing, right?). This particular CRE has no race script anyhow, but I guess I could check for one (if another mod assigns one). I was just going to copy the CRE and WRITE_ASCII the race script name BUT_ONLY :).
Link to comment
So I was interpreting this to mean it doesn't execute anything between IF and THEN (nothing is executable anyway) but I guess it means everything between IF and END.

Nothing between the IF and the THEN is ever executable :rant: Those are triggers, and the IF ... THEN portion exists to provide constraints on which actions are taken. Only actions have effects. The triggers need to be true in order for the actions (which go after RESPONSE) to be executed, and False() is never true, so it's parsed but nothing will happen.

 

Should I put the GLOBALLT check also in the first block, or doesn't it matter much (will it slow things down with/without it)?

 

Doesn't matter, looks fine :)

Link to comment
If you're working with either BGT or tutu you'll probably want to be using the old-style proficiencies, actually. I just found out that creatures aren't being updated to use v.2 effs, so the code I'd posted is of no use to you. Won't matter unless you need dual-wielding or some other unavailable proficiency type.
Any idea whether the scimitar/wakizashi/ninja-to proficiency in Tutu would be covered by the BG1 large sword or the small sword proficiency?

 

Edit: Well it seems that scimitars at least are considered 'large swords' in BG1. Might it be safe to assume that wakizashis and ninja-to are also (even if they are really small swords), since they are handled under the same proficiency by default in BG2?

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...