Skip to content

Infinity Engine Scripting Discussion

BelanosBelanos Member Posts: 968
edited January 2014 in General Modding
I PM'ed horredtheplague to get some answers to things I didn't quite understand while I've been working on my own AI scripts. He mentioned that he'd prefer to have a forum discussion about these sorts of things so other people could benefit. So I'm starting this thread and pasting his reply to a question I asked regarding the trigger condition called HasBounceEffects. This is what he mentioned about that query:


No, there aren't a lot of guides out there for IE scripting. But IEDSP has the best information, even if it's not 100% complete or accurate. From there is a good definition of what HasBounceEffects checks, even if it's a bit cryptic.

0x40B0 HasBounceEffects(O:Object*)
Returns true if any of the specified object is currently affected by any of the listed effects:

0xc5 Bounce Projectile
0xc6 Bounce Opcode
0xc7 Bounce Spell Level
0xc8
0xca Bounce Spell School
0xcb Bounce Secondary Type
0xcf Bounce Specified School
0xe3 Bounce School Decrement
0xe4 Bounce Secondary Type Decrement


Now, in order to see if a spell qualifies, you have to check its effects for one or more of the above. You can see it's a pretty broad range, and definitely not the most precise way to detect a certain spell's effects. Covers both spell turning and prot/missiles, e.g. It's most widely used as a blanket check for spell turning/trap/deflection (to see if your casting is wasted, or even worse).

That's why we invented the Detectable Stats (spells) system. If I was told right, the Neera add-on for BG2EE has it installed by default. But that is definitely the way to go, until Beamdog comes out with their planned ability to detect opcode values on anyone. As far as a description of DS, if it doesn't have one included I may have a crude copy I made from DSv1.0 (first public release) laying around on my hard drive at home.
Post edited by Belanos on
«1

Comments

  • BelanosBelanos Member Posts: 968
    Hmm, it seem quote tags don't work on this site for some reason. Anyway horred, thanks for taking the time to reply. It didn't really clarify anything for me, but the fact that you mention to check a spell's effects might shine some light on the subject. As for Detectable Spells, I don't think it was included with Neera as she came pre-installed in my games and there's a huge difference in what I see in things like Stats.ids after installing the DS version that comes with your AI routines. It looks to me like Beamdog didn't do a lot of work in that area. For instance, MAGE_ALL and LONG_BOW still share the same ids value. That kind of indicates to me that they didn't get around to making any fixes in that area.

    Another thing I've been wondering about, I see that both you and Cierrek(sp?) in his eSeries scripts uses an interrupt timer for pretty much everything that's in the scripts. What exactly is the value of that? In the eSeries scripts at least the very last action listed has a character attacking for one round, so wouldn't that make having a timer redundant? Nothing will get done until that action is completed after all. The spell timer I can see since not all spells require a full round to cast, but the interrupt timer I don't quite get.

    Also, does the STATE_HELPLESS condition also include things like being Held or being caught in a Web, both of which have Stat checks for them. Wouldn't having both conditions listed be kind of redundant?
  • BelanosBelanos Member Posts: 968
    edited January 2014
    Never mind I discovered that I can move my threads by myself. Cool feature.
  • horredtheplaguehorredtheplague Member, Developer Posts: 186
    RE: MAGE_ALL vs LONG_BOW

    The reason this was not changed, is because doing so would have broken a lot of BG2 mods. Beamdog does their best in this department, believe it or not. It has plenty of former modders on staff, and they haven't forgotten their roots (yet).


    STATE_HELPLESS: I wonder the same. Everything that could render somebody "helpless" is essentially covered. Maybe somebody else knows. I only use it in a blanket command, just out of paranoia that I'll miss something important :)

    Do you understand how STATE.IDS works--the concept of a bitwise? If not, I'll try to explain this one. Bottom line, you can make several state checks, like an OR statement, from a single line of code. That's how those old community-standard custom entries were made (STATE_HARMLESS, STATE_OUT_OF_ACTION, etc).
    Only thing I've noticed is that weidu's compiler chokes on the >9 values (A-F). At least, when entered as raw hex code. Sometimes I have to write these as 2 lines of code instead of 1.


    INTERUPT timer: If you check the most recent versions of BP Series, you'll see it's no longer a timer but a 0-1 toggle (more on that in a bit). The last action in a BPSeries script is not AttackOneRound(), but Attack(). The latter goes on until the opponent is dead or it's broken by another action. Now, note that all the spells work on a basis of ActionListEmpty(). This is done to prevent your action queue from getting overstacked, clogged, and causing lag and incorrect execution. Now, what happens if you have a constant action going, and what can break it requires the action list to be empty? Nothing, it keeps playing til its bitter end. This was why mages e.g. got locked into dart combat instead of spellcasting.

    I saw this same potential with using a timer, so I switched to a toggle. Why w/ the timer? It was set for 1 second, so the script could interrupt right away if needed. Sounds great. But what happens if your "cast n' attack" timer is still counting to 5, when that 1 second timer expires? No spells can get cast, nothing gets interrupted--that's what. And our mage goes on to the dart league finals. But by using a toggle, it's not bound by time limits and the attack can be broken during any parsing round (parses 1/second). Tested, works much much better.
  • BelanosBelanos Member Posts: 968
    edited January 2014
    Regarding the MAGE_ALL, LONG_BOW thing, I see your point but I doubt that very many people used the LONG_BOW class in a script. I always switch it to the next available value to clear the MAGE_ALL value.

    One other thing I've noticed is that I see some very weird Race entries in both your scripts and those of the eSeries. In yours it comes out as Morningstar, and in the eSeries as Wyvern. I thought maybe it was the same sort of thing as the MAGE_ALL, LONG_BOW conflict but I don't see anything in the ids file that would cause that, and I can't figure out what that race is supposed to be. In the eSeries it's always found in conditions that have something to do with magic, usually along with the MAGE_ALL etc. conditions.

    As for the STATE_HELPLESS condition, I've taken to using the STATE_OUT_OF_ACTION one. Reading about it on the IESDP site, it seems to cover just about everything I'd want for targeting parameters, at least if STATE_HELPLESS works the way I think it does. Just in case though, I've added the stat checks for HELD etc. I'm just wondering if that's overkill.

    I'll keep your idea for the interrupt toggle in mind. I still don't fully understand the value of that though, at least if I'm using the AttackOneRound command. I can see that a simple Attack command would be more flexible though, since an enemy might be dead before the round is over.
  • BelanosBelanos Member Posts: 968
    edited January 2014
    Do you think this makes any sense?

    IF
    OR(2)
    ActionListEmpty()
    Global("INTERUPT","LOCALS",0)
    !InParty(LastSeenBy(Myself))
    THEN
    RESPONSE #100
    SetGlobal("INTERUPT","LOCALS",1)
    Attack(LastSeenBy(Myself))
    END

    IF
    StateCheck(LastSeenBy(Myself)),STATE_REALLY_DEAD)
    THEN
    RESPONSE #100
    SetGlobal("INTERUPT","LOCALS",0)
    END

    Looking at your current script, I get the sense that it would be possible for a character to stop an attack before he/she was finished and switch to something else. I think with this method, he/she would continue attacking an enemy until it was finished off before doing something else. Keep in mind that I'm using Interupt in the opposite way that you are in your script, my 0 is like your 1. You got me thinking about using a toggle as well, after noticing that one of my party members had a slight pause after killing his enemy. I'm guessing that the round hadn't finished yet, so he just stood there doing nothing for a couple of seconds. It kind of sucks that I can't retain any of the formatting, this would be easier to read if I could.
  • horredtheplaguehorredtheplague Member, Developer Posts: 186
    edited January 2014
    RACE ENTRIES,etc: Cirrerek & I probably took different measures to fix the same problem. In default BG2, and at least for months in BGEE, Wyvern, Cows, Dogs and a few other creatures had their CLASS entry set to 1-MAGE. Now, imagine writing a script that wants to check if there are enemy mages around. You use MAGE_ALL (or LONG_BOW) right? Well, when the script thinks Bessie the Cow is an archmage, because the IDS entries told it so--what's going to happen? Bessie gets a pretty light show of spell buffs like turning/trap/deflection etc, and runs a severe risk of getting Breach'ed.

    Cirrerek's measure for some reason involved changing morningstar to wyvern. No idea why. The proper entry of "WYVERN" was already in the RACE and CLASS file. BPSeries instead changes the creatures to have the proper identifiers.

    Also, I use unique identifiers in a very weird way in order to make sure my "cloud detector" is clearly identified. That's what the MORNINGSTAR.FAIRY_NYMPH.SHOU_FLAYER check is for. Those are identifers set on the BPINVISO creature, which is placed at a cloud spell's epicenter to give players (and enemies, if you use BP) something solid to RunAwayFrom(). And, later in the scripts (both mods) you'll find checks in the targeting blocks to make sure these cloud creatures are not targetted for combat.

    Finally, if you look in my BAF files rather than the compiled scripts, you'll see I use raw numbers for IDS in many cases. While this goes against conventional wisdom and negates some of the handiness of IDS entries, it also insures my scripts can compile regardless of what the current entries say. The DS package does stuff behind the scenes that will make this approach work fine. I do this because both BP and BP Series are an integral part of the BWP install (BP is actually the grandfather of BWP, if you know its history). Some mods set these values differently than the DS package. Two that come to mind are Ding0's quest mod and Kelsey NPC. And that's just one of many IDS files, and 2 of 100's of mods. You mentioned ESeries and BPSeries having different values, same line...

    P.S:
    CheckStat(Myself,0,HELD)
    CheckStat(Myself,0,ENTANGLE)
    CheckStat(Myself,0,WEB)
    CheckStat(Myself,0,GREASE)
    NotStateCheck(Myself,STATE_OUT_OF_ACTION)

    All check for similar yet uniquely different things. Use what's needed, that's not overkill. Sometimes you don't always need all of STATE_OUT_OF_ACTION however. Remember you can make your own customs w/ or w/o IDS entries (raw hex values will do, just don't use A-F in weidu compiler unless we can convince @Wisp to fix this).

    Side Note: In some mods, STATE_OUT_OF_ACTION = STATE_DISABLED. So much for "old community standards". See why I favor those raw number entries for custom values? ;)


    ATTACK, etc:
    AttackOneRound() was not used for the very reason you described. It can add blank spots if the enemy is killed prematurely. It was reported years back that it could actually make a script pause, but I've never witnessed this just the former.

    AttackReevaluate() can also add pauses, especially when used for a time shorter than it takes the script runner to launch an attack. Someone that launches 1 attack/round takes 90 beats between attacks, somebody with 3/2 attacks takes 60, 2 attacks = 45, etc. As this is an arbitrary value unless you tailor a script for just one entity--the potential for a script-stutter is always there.


    In your script, I'd add a Global("INTERUPT","LOCALS",1) check to the top of your second block. Otherwise, because of a currently existing bug in BG2EE, your dead foe will always ring true for See(NearestEnemyOf(Myself)). This in turn would cause that block to be an endless loop while that dead person remained your nearest enemy, unless you add this value = 1 check. Besides, if the value isn't already at 1, why does it need to be set to zero? In BPSeries, I throw a HPLT(LastSeenBy(Myself),1) into my conditions, to help remedy this problem, rather than a StateCheck. All of the various forms of death also set the victim's hit pt value to zero or lower. ;)

    If you merely want to attack a foe until they're dead, without pause, you don't need all this glitter. A simple Attack("what's-his-face") should handle that for you. It was because we didn't find this desirable (Cirrerek and I) that we set up the interrupting system. We wanted the benefits of both approaches available. You'll find that the targeting blocks will often keep finding, and thus beating on, the same foe round-by-round. If they switch, there's usually some good (defined/controlled) reason. But this system allows us to do something special once/round (cast spell, use item, etc), while still using the remaining seconds (to attack w/ a weapon).

    This system works for enemies equally as well. e.g, One of the things BP does is give enemy mages a staff and a stack of darts, plus proficiencies to use them w/o penalty. That was done both so they could benefit from the cast/attack system, and because the majority of vanilla mages had no weapons/proficiencies at all. We know most mages are the arrogant sort when it comes to physical combat, but this was taking it to an extreme.
  • BelanosBelanos Member Posts: 968
    edited January 2014

    RACE ENTRIES,etc: Cirrerek & I probably took different measures to fix the same problem. In default BG2, and at least for months in BGEE, Wyvern, Cows, Dogs and a few other creatures had their CLASS entry set to 1-MAGE. Now, imagine writing a script that wants to check if there are enemy mages around. You use MAGE_ALL (or LONG_BOW) right? Well, when the script thinks Bessie the Cow is an archmage, because the IDS entries told it so--what's going to happen? Bessie gets a pretty light show of spell buffs like turning/trap/deflection etc, and runs a severe risk of getting Breach'ed.[/quote]

    That explains it, thanks. So you're saying that's no longer needed now in the EE games?

    [quote]Also, I use unique identifiers in a very weird way in order to make sure my "cloud detector" is clearly identified. That's what the MORNINGSTAR.FAIRY_NYMPH.SHOU_FLAYER check is for. Those are identifers set on the BPINVISO creature, which is placed at a cloud spell's epicenter to give players (and enemies, if you use BP) something solid to RunAwayFrom(). And, later in the scripts (both mods) you'll find checks in the targeting blocks to make sure these cloud creatures are not targetted for combat.[/quote]

    I see, thanks for the explanation. I'm guessing that the entries I saw with Morningstar would involve spells like Cloud Kill then.

    [quote] Remember you can make your own customs w/ or w/o IDS entries (raw hex values will do, just don't use A-F in weidu compiler unless we can convince @Wisp to fix this).[/quote]

    I was thinking of doing this actually but I wasn't sure I had it right. Do I match up the integer of the state I'd like to use and add that value to the shortcut? I'm presuming that the OUT_ACTION_ACTION that's included in the DS in your mod matches the explanation in the IESDP index?

    [quote]
    In BPSeries, I throw a HPLT(LastSeenBy(Myself),1) into my conditions, to help remedy this problem, rather than a StateCheck.[/quote]

    I was wondering why that was used. Cirrerek used something similar, though his value was 5, not 0. I went and removed all those entries thinking they weren't really needed, but I guess they are. Though wouldn't a StateCheck Really Dead entry work as well? As for the AttackOne round and interupt toggle things, I guess I'll be changing those in my scripts. Of should I say Cirrerek's revised scripts.

    Man, this is really annoying not having quote tags working on this site.


  • horredtheplaguehorredtheplague Member, Developer Posts: 186
    edited January 2014
    I just checked--it seems the Wyvern fix is not needed in BGEE nor BG2EE any longer. :) Note that I didn't check every CRE file, and it doesn't hurt to run this anyways in BPSeries. If nothing needs changing, nothing is done...

    My STATE_DISEASED_FIX patch (STAT #134) however still is needed, in all 3 games. STATE_DISEASED in State.ids is, and has always been, broken.

    The BPINVISO/ MORNINGSTAR bit is used for cloudkill, web, entangle, etc--any lingering AoE spell. A central point to run away from, or focus some other action on. Not foolproof, but better than just standing there. :)

    All the State.ids customs in BP are either unique, or correspond to what you see in IEDSP
    Belanos said:


    Try "blockquote" instead of "quote", and use < > instead of [ ]


    For the name hash type blockquote class="Quote" rel="[username]"

  • WispWisp Member Posts: 1,102

    (raw hex values will do, just don't use A-F in weidu compiler unless we can convince @Wisp to fix this).

    @horredtheplague
    I'm pretty sure you can use numbers in base 10.
  • horredtheplaguehorredtheplague Member, Developer Posts: 186
    Wisp said:

    (raw hex values will do, just don't use A-F in weidu compiler unless we can convince @Wisp to fix this).

    @horredtheplague
    I'm pretty sure you can use numbers in base 10.
    True, this will work too. (Keep your calculators handy...) Using full hex input was just a convenience factor, as it already works for hex digits using [0-9]. I suppose its only real value is when dealing with a bitwise like State.ids, and there's not many bitwise operators in BG that use hex input. Most use binary.
  • BelanosBelanos Member Posts: 968
    edited January 2014
    I just noticed a discrepancy in your Melf's Meteor block. You first have SetGlobal("Interupt",Locals,0), then just two lines down from that you set it again to 1. Maybe I'm missing something, but that looks like a mistake to me.

    So one thing I've been thinking about recently. Looking around I discovered that Beamdog has added a script command that allows someone to add an item into a store. Coupled with a random number trigger, that has some interesting possibilities. I've been adding my own bags to the game, mainly through various stores, and it would be rather cool to have them appear randomly, rather than having me know where they all are ahead of time. But so far my IE scripting experience has been strictly dealing with AI routines. Any suggestion on how I could do something like that? I'm not sure how to make a general script trigger when a game starts up.
  • horredtheplaguehorredtheplague Member, Developer Posts: 186
    The melf's attack (and others like it) is not a mistake. There is a couple seconds of casting time going on, where you don't want any interruptions. This is folllowed by (w/in the same action block) an Attack(). Thus, it's set back to 1 at the end of the block, to allow for new castings.

    For sometthing like your 'bag mission', you can approach it several ways. One could be adding blocks to Baldur.bcs, the 'always running' script. Another could be blocks to AR0602.bcs, the starter script. Or, AR0700.bcs, the first script ran when you leave the dungeon (and are thus able to shop).Another way still is to paint a trigger on the floor where the player "has to" walk. Run the script from that trigger, as if it were a trap. It doesn't "have to" be done right at the start, being my point. I recommend either AR0700 or the floor trigger, simply because AR0602 and Baldur scripts are pretty clogged up already (much worse when several/certain mods are added).
  • BelanosBelanos Member Posts: 968
    OK, thanks. Yeah the trigger idea seems like a good one. I'll have to keep it in mind.
  • BelanosBelanos Member Posts: 968
    So I've been revising my scripts based on your tips, using Attack instead of AttackOneRound and replacing the interrupt timer with a toggle, and my characters are definitely a lot more responsive now. They're switching weapons as well as selecting new targets much quicker, with no pauses. Thanks.

    So I'd like to offer you a tip in exchange. I've noticed that you sometimes use AttackedBy([ANYONE],Default), or !AttackedBy([ANYONE],Default), as a condition. That doesn't necessarily make any sense. In a battle I had with a pack of Gibberlings, I noticed while reading the dialogue box text that one of them was attacking Dynaheir. But it was a long way off and had to travel to her in order to actually do any damage. But my party destroyed all of the Gibberlings before they even got close to her, so she was never in any real danger. After that I changed my conditions to:

    OR(2)
    !AttackedBy([ANYONE],Ranged)
    !Range(LastAttackerOf(Myself),4)

    OR(2)
    AttackedBy([ANYONE],Ranged)
    Range(LastAttackerOf(Myself),4)

    Depending on what type of spell it was, offensive or defensive. It's just a little more specific IMO. I've noticed that you sometimes use HitBy([ANYTHING],Missile). That's even better.
  • horredtheplaguehorredtheplague Member, Developer Posts: 186

    Unfortunately both attempts are in vain (yours and mine).


    HitBy([ANYTHING],MISSILE) will actually not help. The attack style (ASTYLES) MISSILE or MELEE identifiers don't actually work. Unfortunately. So, the MISSILE check defaults to DEFAULT (0). Unless BG2EE fixed it, and I missed it. Same story with DAMAGES.ids unfortunately, unless recently fixed. Only CRUSHING (default = 0) works, not HitBy(xxx,COLD) HitBy(xxx,SLASHING) etc.

    So, even in my scripts, this was wishful thinking. The inconsistency wasn't from lack of realizing there were IDS entries made for the task, it was from knowing the futility of it. At one point I was hopeful it had been fixed, but it wasn't. That was some time ago (a year/so ago). If you want to know for sure if it works now, you can set up a test environment by giving a couple creatures a script that displays string heads when a certain attack style or damage is done: "I was hit by Missiles", "I was hit by Cold", and so on. If you find it is working, let me know. I'd gladly refine some scripts if I had this capability.

    Also, the other flaw here is in the object choice. [ANYONE] or [0]. The use of raw IDS entries looks for the very nearest creature that qualifies for this condition. [EVILCUTOFF.0.0.CLERIC_ALL] finds the nearest enemy clerical type w/in sight range. You can use (Second,Third,etc)NearestEnemyOfType([w.x.y.z]) format in conjunction with these, and it will work. So, if you really want to get a target in the far range--look at the BPMONK "near/far" system.

    You'd actually need a series of blocks more like this, to detect a far-off archer and target them:


    HitBy(NearestEnemyOf(Myself),DEFAULT)
    !Range(NearestEnemyOf(Myself),4)
    See(NearestEnemyOf(Myself))


    HitBy(SecondNearestEnemyOf(Myself),DEFAULT)
    !Range(SecondNearestEnemyOf(Myself),4)
    See(SecondNearestEnemyOf(Myself))

    [You can change EnemyOf(Myself) to EnemyOfType([x.x.x.x.x]) if you prefer]

    Even HitBy and AttackedBy can let you down in a firefight--I try to only use them in targeting blocks when I am looking for a general statement. The object entries are more reliable (LastAttackerOf, LastHitter).


    Finally, in your example blocks, I don't think you want the two negative statements in an OR() statement. I think those should be AND instead:

    !AttackedBy([ANYONE],Ranged)
    !Range(LastAttackerOf(Myself),4)

    But that depends on what exactly you're using them for. If as two sides of the same coin, my statement stands.
  • BelanosBelanos Member Posts: 968
    edited January 2014
    I see. Well I don't think I want to bother with that test you suggest, I have enough to do as it is. As for your final statement, my reasoning was that even though the Gibberlings were attacking Dynaheir in melee mode, they were approaching her at a ranged distance. So it wouldn't make sense to have a blanket condition for that situation, but rather use something more specific. Anyway, I guess my idea is moot since those things aren't working anyway. I had actually removed those sorts of conditions before that, because I felt AttackedBy([ANYONE],Default]) was too restrictive. Maybe I should just go back to not having them at all.

    So I've been working on my idea of the random bags, and I've hit a few roadblocks. First of all, I discovered how to create a container script that creates the item when it's opened, with a random number to determine it's probability. I was also thinking of adding one to various enemies in the game, so that I would have to earn some of those bags in battle. But I'm not sure if I can get it work. If I create an override script that attaches to the character can I get it to point to my party as a condition somehow? The only thing I've been able to think of using is !PartyHasItem, along with the RandonNum condition. So it would be something like:

    If

    !PartyHasItem("Bag"01)
    RandomNumberLT(100,51)

    THEN

    RESPONSE #100

    CreateItem("Bag01")

    Now that works with containers because I can use the "Opened By" trigger, but I'm not sure how I can accomplish it in a combat situation, so that a Bag appears in an enemy's inventory. Any suggestions? I was thinking of a kind of OnDeath script using the State_Really_Dead check, but I'm not sure if that would work.

  • BelanosBelanos Member Posts: 968
    Nice idea, too bad it doesn't work. I've spent hours randomizing the bags I'm adding to the game, but the new AddStoreItem action doesn't do anything. I tried adding it to the Friendly Arm Inn area script, and attaching it to Bentley as a Default script with a See([PC]) trigger but nothing is being added to his inventory. On a bright note though, I've figured out how to get some bags appearing through combat encounters. And I'm guessing the container script should work as well, though I haven't gotten far enough into a new game to be sure. So hopefully I'll be able to have at least half of my bags be random.
  • horredtheplaguehorredtheplague Member, Developer Posts: 186
    Nice stuff, @Belanos. Just be advised that duplicate bags in BG hold the exact same items between them. This is because a STO file handles contents. It's the same case when you assign duplicate stores to merchants. This is why mods adding bags to BG always add new bags, not in-game bags.
  • BelanosBelanos Member Posts: 968
    I'm aware of that, thanks. Each one has to be unique. It's taken me awhile, with a few false starts along the way and no lack of frustration, but I'm finally getting a handle on it. It's been quite the learning process, I've picked up a lot of information about how the game works. There were a few questions I was thinking of asking you, but I can't seem to remember what they were right now. Maybe after I've had my morning coffee. Now if only I could get that AddStoreItem to work. I've discovered that it only functions in BG2EE, they have added the capability to BGEE yet.
  • BelanosBelanos Member Posts: 968
    I remember one question now. When using the CreateItem action, there's 3 flags at the end used for "Usage". What do those do exactly? Usage is a very broad term and it's not described anywhere that I can see. I've seen some default script that have a value in the first one when dealing with things like arrows, so I guess that deals with quantity. Though the engine will always create at least one item even if the value is 0. But the other two I have no clue of, and I haven't come across any sort of explanation yet.
  • BelanosBelanos Member Posts: 968
    edited January 2014
    Ah yes, I remembered another one. I don't know what I'd do without coffee. How does the game go about creating items? Is everything pregenerated at the beginning of a new game or does nothing happen until your party is actually in an area? I've been thinking of adding in a check so that the bags I'm adding don't get created until I'm actually in an area. But if the game already works that way, then I don't have to bother. With the combat drops, I'm using See([PC]), but there's nothing I can use along those lines for containers. It turns out that Opened function only works with doors, not containers.
  • BelanosBelanos Member Posts: 968
    One more thing. I've avoided adding my container scripts to any area that doesn't have it's own WED file. Some areas share WEDs with others, and I'm not sure if making any changes may cause any problems. Is it something I should be concerned about or can I disregard the shared WED file? Whatever they are. I know they serve some graphic function, but I'm not sure exactly what that is.
  • CamDawgCamDawg Member, Developer Posts: 3,438
    Belanos said:

    I remember one question now. When using the CreateItem action, there's 3 flags at the end used for "Usage". What do those do exactly? Usage is a very broaond term and it's not described anywhere that I can see. I've seen some default script that have a value in the first one when dealing with things like arrows, so I guess that deals with quantity. Though the engine will always create at least one item even if the value is 0. But the other two I have no clue of, and I haven't come across any sort of explanation yet.

    The usage parameters generally refer to charges, which is why they're almost always zeroes or ones. They correspond to the ability headers on the item (usage 1 to header 1 e.g.).
    Belanos said:

    Nice idea, too bad it doesn't work. I've spent hours randomizing the bags I'm adding to the game, but the new AddStoreItem action doesn't do anything. I tried adding it to the Friendly Arm Inn area script, and attaching it to Bentley as a Default script with a See([PC]) trigger but nothing is being added to his inventory. On a bright note though, I've figured out how to get some bags appearing through combat encounters. And I'm guessing the container script should work as well, though I haven't gotten far enough into a new game to be sure. So hopefully I'll be able to have at least half of my bags be random.

    If I may ask a question--have you seen Bentley's inventory before you tested the action? Stores are saved in saved games so it's possible it's only working on new stores (I honestly can't remember).

    It's also possible the engine doesn't quite support it yet even though it's listed as an action. We added that action for... future projects.
    Belanos said:

    One more thing. I've avoided adding my container scripts to any area that doesn't have it's own WED file. Some areas share WEDs with others, and I'm not sure if making any changes may cause any problems. Is it something I should be concerned about or can I disregard the shared WED file? Whatever they are. I know they serve some graphic function, but I'm not sure exactly what that is.

    Sharing WEDs is not a problem. Containers are stored in the ARE file itself, so the containers won't cross over between identical tilesets. The only possible conflict would be if the areas shared an area script, which isn't the case anywhere in the game.
  • CamDawgCamDawg Member, Developer Posts: 3,438
    CamDawg said:

    Belanos said:

    I remember one question now. When using the CreateItem action, there's 3 flags at the end used for "Usage". What do those do exactly? Usage is a very broaond term and it's not described anywhere that I can see. I've seen some default script that have a value in the first one when dealing with things like arrows, so I guess that deals with quantity. Though the engine will always create at least one item even if the value is 0. But the other two I have no clue of, and I haven't come across any sort of explanation yet.

    The usage parameters generally refer to charges, which is why they're almost always zeroes or ones. They correspond to the ability headers on the item (usage 1 to header 1 e.g.).
    Duh, except I forgot about the even more common use of those--for stackable items, usage 1 is the number in the stack. E.g. CreateItem("arow01",20,0,0) creates a stack of 20 arrows. CreateItem("wand05",10,7,0) would create a wand of fire with 10 fireball charges and 7 scorcher charges.
  • BelanosBelanos Member Posts: 968
    CamDawg said:


    If I may ask a question--have you seen Bentley's inventory before you tested the action? Stores are saved in saved games so it's possible it's only working on new stores (I honestly can't remember).



    Yes, I'm aware of that. I made sure to keep using the auto save just outside the inn before going to Bentley to see if things were working or not.
    CamDawg said:

    It's also possible the engine doesn't quite support it yet even though it's listed as an action. We added that action for... future projects.

    I believe this is the case. I noticed that the action was listed in the BG2EE IDS file but not in the one for BGEE. I tried adding it myself but doing so had no effect. I've left a post in the feature request forum to have this action put into the game, as it can be quite a useful one.
    CamDawg said:


    Sharing WEDs is not a problem. Containers are stored in the ARE file itself, so the containers won't cross over between identical tilesets. The only possible conflict would be if the areas shared an area script, which isn't the case anywhere in the game.

    OK, thanks. I started out working with DLTCEP and it kept giving me what appeared to be dire warnings so I avoided doing anything with those areas. I guess I'll have to get back and do them.
    CamDawg said:


    Duh, except I forgot about the even more common use of those--for stackable items, usage 1 is the number in the stack. E.g. CreateItem("arow01",20,0,0) creates a stack of 20 arrows. CreateItem("wand05",10,7,0) would create a wand of fire with 10 fireball charges and 7 scorcher charges.

    Interesting. So that's the first two, what about the third?

    Thanks for replying. I was hoping when I started this thread that it would evolve into a broad discussion of IE scripting, instead of just a discussion between me and horredtheplague. There's not a lot of information out there about some things, and what there is tends to be vague at best. It would be nice to have a resource where people can go to have their questions answered and to share ideas. It would be nice to eventually get this thread stickied, and well used.

  • BelanosBelanos Member Posts: 968
    edited January 2014
    While you're here CamDawg, I'm still hoping for an answer on how the engine handles creating items. Is everything predefined at the start of a game, or does it create them on the fly as the player enters an area? In my case, I'd like to know if any of these items I'm adding actually exists before a container is opened, or whether the game creates them just at the moment the container is opened.
  • CamDawgCamDawg Member, Developer Posts: 3,438
    Belanos said:

    CamDawg said:


    Duh, except I forgot about the even more common use of those--for stackable items, usage 1 is the number in the stack. E.g. CreateItem("arow01",20,0,0) creates a stack of 20 arrows. CreateItem("wand05",10,7,0) would create a wand of fire with 10 fireball charges and 7 scorcher charges.

    Interesting. So that's the first two, what about the third?
    If there's no third header on an item, the third usage number doesn't matter. CreateItem("wand05",10,7,0) and CreateItem("wand05",10,7,100) would produce the same wand with the same number of charges--there's no third header on the item, so the third usage number is ignored.
    Belanos said:

    Thanks for replying. I was hoping when I started this thread that it would evolve into a broad discussion of IE scripting, instead of just a discussion between me and horredtheplague. There's not a lot of information out there about some things, and what there is tends to be vague at best. It would be nice to have a resource where people can go to have their questions answered and to share ideas. It would be nice to eventually get this thread stickied, and well used.

    Well, the thing is with scripting... a good 98% scripting that folks use is fairly basic and simple and doesn't really require a lot of thought. On top of that there usually lots of examples in the game or mods. Stuff like spawning creatures, setting variables, handing out XP, etc. are all fairly straightforward and something like SimDing0's old scripting tutorial will be all most folks need.

    The problem lies in that 2% that generally encompasses high-end AI scripting. I don't think people really appreciate how hard it is to do good, high-level AI--there's a reason why most 'tougher X' mods tend to beef up enemy stats in lieu of more intelligent behavior. The engine's not really built for it, so good AI scripts include a pile of tricks that become really hard to follow for someone who hasn't run into the same issues themselves. Folks live Cuv, horred, and aVENGER have been plugging at it for years now. Hell, DavidW wrote his own tool in Python to get it to work sensibly for SCS.
  • BelanosBelanos Member Posts: 968
    Yes, I read SimDingo's tutorial. And while helpful, it quite often only went so far to help me figure something out that I was attempting to do. I have in fact been working mainly with AI scripts so I understand what you mean about how difficult it can be. Still there's a lot of stuff you can do with IE scripting that's not very well explained. There's all sorts of Actions, Triggers, States etc. that I can only guess at what they do. Plus with IE scripting, there's multiple ways to accomplish the same goals. There's a lot of redundancy in the functions, with one or more of them doing the same basic thing as the others. It's not always easy or straight forward to decide which would be the best approach to take.

    You're also looking at it from the perspective of an experienced modder. With the release of the EE games, there will no doubt be a whole new generation of people who are approaching modding the games for the very first time. It would no doubt be helpful to them to have some place to go with their questions. I've spent time at The Gibberlings Three and at Pocketplane recently, and they're practically "ghost towns" these days. There's a lot more traffic here now than at both of those sites combined, so they're losing their relevance as far as IE modding is concerned. They're great places to go for getting mods, but they're no longer all that useful as far as learning how to do it is concerned. You could ask a question there and not have it answered for months, if at all.
  • horredtheplaguehorredtheplague Member, Developer Posts: 186
    I agree, the more the merrier. Let's inspire an EE scripting renaissance. :)



    I may as well mention this one here, since the only other place I mentioned my discoveries was in the BP Series changelog and this seems like the righ place.

    This is a hidden function that exists in BG2 even, unearthed by AvengerTeamBG:

    ACTION.IDS
    34 UseItemExt(S:Item,O:Object,I:Slot*SLOTS,I:Abil)

    This action allows you to use items that have > 1 ability, that also aren't weapons. I mentioned this in a (now-buried) thread around day 1 of BG2EE release, but since then I've learned a couple of things about it.

    1) It has to go above the existing 34 UseItemSlot entry, or it doesn't work. This makes UseItemSlot not work, but there were only a mere handful of vanilla scripts using it (barely, not even at its potential --same items same slot every time). I wrote a weidu patch to change them over (in latest BP Series) as well as ACTION.ids.

    It's worth the effort, as this is a much handier function than UseItemSlot by a longshot. It combines UseItem, UseItemSlot, and UseWeaponAbility into one sweet command.

    2) This has to be the first action line after RESPONSE #100, or it doesn't work.

    3) Confirmed: this does work for multiple item abilities of the same item, if you follow the blueprint above. I:Abil entry--start with 0 for ability 0, 1 for 1, etc. Just like with UseWeaponAbility

    4) Using the proper SLOTS.ids entry (SLOT_HELMET for a helm, etc) seemed helpful to me in my testing, but the default 0 SLOT_AMULET is also supposed to work according to AvengerTeamBG.

    My next big push on BPSeries, when I find the time, will be adding code to handle item usage for all the vanilla items in all 3 games. There's already plenty of working examples in the scripts to see it in action (made it to "H" in BG2EE, thus far) so check it out if you like.
  • lansounetlansounet Member Posts: 1,182
    edited January 2014
    About AddStoreItem() I'm pretty sure this was added for BP2 so only implemented in BG2EE. No idea how it works but my guess would be that it requires that you opened that store at least once.
    Belanos said:

    While you're here CamDawg, I'm still hoping for an answer on how the engine handles creating items. Is everything predefined at the start of a game, or does it create them on the fly as the player enters an area? In my case, I'd like to know if any of these items I'm adding actually exists before a container is opened, or whether the game creates them just at the moment the container is opened.


    Containers and their items are stored in ARE files so predefined. However there is some randomness with the RNDTRE01-05 items that create a random item based on 2DA tables, when that is decided I don't know, I guess 1st time the area is loaded.

Sign In or Register to comment.