Jump to content


  • Content Count

  • Joined

  • Last visited

About Gimble

  1. I didn't know that: it would have been a help a month or two ago (before I wrote my own script-helping tools based largely on the C++ preprocessor). It wasn't the tedium that bothers me ( it's been "macroed" to be just a _IsImmune1() call ), but the performance hit at run time. User script check blocks are already long, and the extra string lookups and inventory checks for three items don't make things faster. I've moved them to be last in evaluation (since they rarely fail), but it's that programmer tendency to always want to optimize things that is just kicking in. I appreciate the help you've provided and all the work you've done. (Side question: is there a way to detect Vocalize? It dawned on me some things like Silence 15' Radius could be safely cast without range checks if Vocalize was already on the caster).
  2. Ah, well it was worth asking. One thought: would it make sense to change the behavior of the MINORGLOBE stat? All the script snippets I've seen to date have just checked for non-zero (a binary flag), which would still work if it were switched to mean immunity to spell level N and below.
  3. The range check can be removed from WIZARD_SLEEP. After doing some things with WIZARD_COLOR_SPRAY lately, though, I found that its range is very considerable. As a result, it's not really possible to range check for WIZARD_COLOR_SPRAY that party members aren't too close... so it probably shouldn't be moved there.
  4. I'm not sure it belongs in this forum, but I've loaded a piece of SCS just for doing user scripting. A big annoyance for user scripting is the "immunity to spell level" checks, as they require tests like the following: !CheckStatGT(LastSeenBy(Myself),0,MINORGLOBE) !HasItemEquiped("RAKRING",LastSeenBy(Myself)) // Immune to 8th and below !HasItemEquiped("LICH",LastSeenBy(Myself)) //Immune to 5th and below !HasItemEquiped("MAGEAMUL",LastSeenBy(Myself)) // Immune to 3rd and below Instead, if there was a IMMUNE_TO_SPELL_LEVEL_AND_BELOW stat (and items and spells modified), it could be simplified to something much simpler, like: CheckStatLT(LastSeenBy(Myself),3, IMMUNE_TO_SPELL_LEVEL_AND_BELOW ) ... or at least, that's what I think could be done.
  5. That could be done, when coupled with a local variable to denote the timer was started. It's a slight performance penalty because of string checks, but probably doable. I haven't had any problems with the StartTimer(s) just because they're very transient and are just used to interrupt continuous actions in progress: something that is (automatically) interrupted during program loads and frequently during saves. If I encounter any problems, I'll use that as a fallback position. Thanks for the thought.
  6. After typing "continuous action timer"several times, I've decided to abbreviate it to CAT for this post at least. I believe so. I'm compiling my user scripts to .bcs ( I have a slot-loading system, with the user script loading position & class specific scripts in the RACE and GENERAL slots ), and so far in testing I have been... very happy with the results. The follow and move to combat code works like a charm, once I converted to MoveToObject() with a range check from FollowObjectFormation(). I had already worked out a solution for stealth / search combinations that does pretty well, and the BardSong ability actually works as stolen from the eSeries (with a Delay(2) IIRC). Attack() as mentioned above works like a charm. Since I also set a second CAT on spellcasting, it also makes "cast and attack" work: the Attack() action will also be broken whenever the spell CAT expires. Overall, I'm very happy with how the user scripts work with this model. The biggest problem is right after the end of combat: for a round or so, you still get expiring CATs. This makes looting a little annoying, because looting is also apparently a continuous action timer and can be broken by an expiring timer. You kill the last dude, click on the loot, and usually manage to walk to the corpse and open the container to loot. Then, the CAT expires from the last Attack(), and the container closes again... and you're standing on top of the loot. So, you have to either right-click into inventory, or move away and come back to the container to get the stuff. Yes, just a few second delay before you start looting avoids the whole mess, but I was surprised at how ingrained that natural "combat is over, let's start looting!" behavior is in my personality at least.
  7. Stupid question from a newbie: could you separate out this new functionality into a meta-tool that would translate your new user-readable stuff into raw Weidu-code, and then distribute that generated Weidu code as a way to reduce installation overhead? I more or less did that in my user-scripting land: I have a "C" style preprocessor that parses a BAF file ( with extra #includes, #defines, etc.) and generates a .BAF file as output, that I then hand off to Weidu for compiling. It's not a perfect solution but it does 90% of what I want, and doesn't pollute the Weidu language namespace with a different model. Even more cool would be something that would take an existing Weidu script and reverse-engineer it back into user-readable stuff. I don't do anything but AI scripting, but I can say if I were ever willing to take on modding, the stuff you have proposed is far more accessible than the raw data. I may be a good coder (I hope so, I get paid to do it), but I really don't relish grokking other people's Weidu ugliness to learn how to do basic modding. Yes, I'm lazy. It's part of not having a lot of free time to work with.
  8. Code first. Moderators, please move if in wrong forum. IF TimerExpired(11) // Continuous action timer THEN // Continuous actions, like Attack() or FollowObjectFormation() // has been running for a while. We want to break the continuous // action without aborting anything else that might be going on // instead (e.g. a user-selected and cast spell, for example). // Experimentation seems to indicate that starting a timer is // sufficient to break the continuous action without disrupting // useful activities. RESPONSE #100 StartTimer(12,6) // Timer 12 unused, just started to break the continuous action END IF ActionListEmpty() Range(Player2,0) !See(NearestEnemyOf(Myself)) !See([EVILCUTOFF]) THEN RESPONSE #100 StartTimer(11,2) // Start the continuous action timer FollowObjectFormation(Player1,3,2) END IF ActionListEmpty() OR(2) See(NearestEnemyOf(Myself)) See([EVILCUTOFF]) THEN RESPONSE #100 StartTimer(11,6) // Start the continuous action timer Attack(LastSeenBy(Myself)) END A lot of the AI Scripting code easily findable is geared towards monster AI (don't have to deal with user input). For user scripts, you have to do your best to avoid stopping an action the user requested. However, the two common methods used for attacking ( AttackOneRound() and AttackeReevaluate() ) are both known to have issues from posts gathered here and elsewhere. It's frustrating to watch a user script sit there, attack foes, but not actually get an attack role for some percentage of the time. The above code is something I figured out yesterday as an acceptable solution. Continuous actions (like Attack() ) are broken by almost any script action, including setting timers or globals. However, most "valuable" actions like casting spells are not broken by some actions. As a result, a local timer becomes an easy way to interrupt a continuous action without interrupting an overridden action. Early testing seems very promising: with my AI script (larger than the sample): the team follows the leader, attacks when in range, and I can override with spells or movement from the keyboard without issue. Hope this helps!
  9. I like the idea in general, although you would need to provide some basic equipment at the beginning of the catacombs, to not greatly handicap non-spellcasting parties. One way to give the player access to the items would be to add dialog to the guard outside Candlekeep. Unknown to CHARNAME (until now), he also runs a smuggling operation in and out of Candlekeep, and willing to smuggle items (including claimed equipment) out of Candlekeep to the PC for an appropriate bribe. The dialog could get wordy, though, unless there's a way to add the items via script to a custom Store the guard has access to (in which case it might be fairly easy to implement).
  10. From my limited understanding of bears, when angry they actually can be (for short periods of time) a fair amount faster than an equivalent human, although their normal pace is rather slow. If someone is bored enough, I would hope it would not be difficult to create an innate Rage like ability for bears, that they could trigger (via script) in combat, increasing their speed to wolf-like speed (I think wolves are a little faster than people) for a short period of time ( perhaps 10 rounds ). I would think the bear would fire the ability when AttackedBy([ANYONE],DEFAULT). But I've not done anything but AI Script modding so I don't know how practical this might be.
  11. Playing with the eSeries on BGT, I found that WIZARD_SLEEP does not fire. The offending script code is as follows: OR(2) Range(Player1,0) //Either I'm Player1 CheckStatGT(Player1,5,LEVEL) // or they're high enough to be immune to this OR(2) Range(Player2,0) //Either I'm Player2 CheckStatGT(Player2,5,LEVEL) // or they're high enough to be immune to this OR(2) Range(Player3,0) //Either I'm Player3 CheckStatGT(Player3,5,LEVEL) // or they're high enough to be immune to this OR(2) Range(Player4,0) //Either I'm Player4 CheckStatGT(Player4,5,LEVEL) // or they're high enough to be immune to this OR(2) Range(Player5,0) //Either I'm Player5 CheckStatGT(Player5,5,LEVEL) // or they're high enough to be immune to this OR(2) Range(Player6,0) //Either I'm Player6 CheckStatGT(Player6,5,LEVEL) // or they're high enough to be immune to this I suggest moving the above code block from the WIZARD_SLEEP block to the WIZARD_COLOR_SPRAY block. WIZARD_SLEEP affects enemies only, so the check is not necessary. WIZARD_COLOR_SPRAY, however, can affect party members, so the check would be helpful to be added (to avoid blasting fellow party members). I'm aware this is pretty much a non-issue in Amn and ToB, but for BG1 Sleep is a great spell and this simple change should make it more usable.
  12. Another note about TakePartyItemNum: If done within the party, the following seems to happen (assume 'source' and 'destination' are both in the party, and may or may not be the same person): With TakePartyItemNum("foo",1): Source has a stack of 'N' items replaced by 'N-1' items. Destination is given a stack of 'N-1' items. Note that this is patently wrong: Taking one goodberry from a stack of 10 results in two stacks of nine, even if the party only has one member. Talk about magical!
  13. Slot clarifications to SLOTS.IDS, based on testing. I isolated the main inventory slots by row and column (and verified the quick slots locations), using user script. A note about XEquipItem: if on an equip request the destination is filled, it merely swaps the location of the two items. This can be benign or disasterous, depending on if the swapped source is an invalid location for the item. 15 SLOT_QUICK_1 16 SLOT_QUICK_2 17 SLOT_QUICK_3 18 SLOT_MISC_R1_C1 19 SLOT_MISC_R2_C1 20 SLOT_MISC_R1_C2 21 SLOT_MISC_R2_C2 22 SLOT_MISC_R1_C3 23 SLOT_MISC_R2_C3 24 SLOT_MISC_R1_C4 25 SLOT_MISC_R2_C4 26 SLOT_MISC_R1_C5 27 SLOT_MISC_R2_C5 28 SLOT_MISC_R1_C6 29 SLOT_MISC_R2_C6 30 SLOT_MISC_R1_C7 31 SLOT_MISC_R2_C7 32 SLOT_MISC_R1_C8 33 SLOT_MISC_R2_C8 34 SLOT_MISC_R3_C1 35 SLOT_MISC_R3_C2 36 SLOT_MISC_R3_C3 37 SLOT_MISC_R3_C4 38 SLOT_MISC_R3_C5 39 SLOT_MISC_R3_C6 40 SLOT_MISC_R3_C7 41 SLOT_MISC_R3_C8
  14. I believe it's noted elsewhere, but the AI scripting for PCs does not run constantly. Particularly when you interactively move a character ( click on them, click on destination to walk to ), their script does not run during the move itself, or for a few seconds afterwards. This means that PC-based scripts in IWD2 have a significant disadvantage, as they don't "fire" right at the start of combat -- though the enemy monster AI does. As a result, you can have a swarm in your face before the first PC AI script action occurs.
  15. Thanks, Yovaneth. I hadn't gotten around to Hide-n-Search yet, and I'll put it on my really low-priority list of things to look at (I now expect failure). More notes: 215 FollowObjectFormation(O:Object*,I:Formation*,I:Position*) isn't in ACTION.IDS, but works fine. Useless for PC scripting as best I could tell, though, because there's no good way I could find to 'break' back into script when something valuable happens (e.g. monsters ). MoveToObject works fine for that, though. You can use it with an additional IF check that breaks the movement. However, don't expect fine-grained control here: between AI cycles your guy can move several circle-widths ( 5-10' in game terms? ). MoveToObject is unacceptable without a code check for breaking the move. Otherwise, the followers are constantly 'shoving' the leader forward as they push into them. I imagine this is really, really bad if you're close to traps or enemies, for example. Annoying, and important to remember, is that PC script slots one and two (and presumably zero) are not stored in the save file. If you save your game, with scripts in every slot, and then examine the save game, slots 3-5 will still be populated with the right script names, but slots 1 and 2 will be empty ("None" in Beyond Infinity terms).
  • Create New...