Jump to content

AddexperiencePartyGlobal


Recommended Posts

i have a global variable which is incrementing correctly. however, when i use this variable, it does not give my party the amount of experience that the global value is. in fact, it always gives me 1080408868 experience, even if my global variable is 2. when my global increments, i can verify it with the console. however, this function will still give me the exact same billion experience. it's not an arbitrary number i'm typing either, it's literally that exact amount. the experience is real as well, the engine gives me enough to level a party of 6 triple classes to max.

i did a search in nearinfinity and this function is never called in any bcs nor dlg file.

Link to comment
43 minutes ago, squiros said:

i have a global variable which is incrementing correctly. however, when i use this variable, it does not give my party the amount of experience that the global value is. in fact, it always gives me 1080408868 experience, even if my global variable is 2. when my global increments, i can verify it with the console. however, this function will still give me the exact same billion experience. it's not an arbitrary number i'm typing either, it's literally that exact amount. the experience is real as well, the engine gives me enough to level a party of 6 triple classes to max.

i did a search in nearinfinity and this function is never called in any bcs nor dlg file.

Try ar1300.bcs ... https://gibberlings3.github.io/iesdp/scripting/actions/bgeeactions.htm#164
Could it be that you did something horribly wrong .. might just be. To help with more, I bet that if you were to show us the script you made, it would help us to identify what went wrong ...

The short of it is, use it like this;
 

IF
  Global("CustomGlobalVariable","GLOBAL",0)
other conditions you want and customization 
THEN
  RESPONSE #100
  SetGlobal("CustomGlobalVariable","GLOBAL",1)
  AddexperienceParty(29750)				//custom amount of xp you want to give
END

The others use is a little more complicated, but essentially you might not want to use it. ..

Edited by Jarno Mikkola
Link to comment

OP asked specifically about AddexperiencePartyGlobal() which isn't actually used in any of the games.

@squiros It looks like you stumbled upon a bug in NearInfinity's script (de)compiler which encodes and decodes the parameters for this script action incorrectly in some of the game engine variants. It'll be fixed in the next release. In the meantime only use WeiDU to compile or decompile your script that contains this action.

Edit: The issue in NI has been fixed and can already be tested in the nightly release: https://github.com/Argent77/NearInfinity/releases/tag/nightly

Edited by argent77
Link to comment

@argent77 Looks like GivePartyGoldGlobal() also doesn't concatenate its strings.

I stepped through what the in-engine encoder does, and aside from GivePartyGoldGlobal(), it aligns with Near Infinity's hardcoded list:

Spoiler
//////////////
// Triggers //
//////////////

Decode type - 0xD: param2 + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'I'
        no param4

    TRIGGER.IDS Matches:
		0x400F Global(S:Name*,S:Area*,I:Value*)
		0x4034 GlobalGT(S:Name*,S:Area*,I:Value*)
		0x4035 GlobalLT(S:Name*,S:Area*,I:Value*)
		0x40F7 BitCheck(S:Name*,S:Area*,I:Bit*Bits) // BUG - The trigger expects both string1 and string2 to be used



Decode type - 0x21: param2 + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'I'
        param4 type annotation == 'I'
        no param5
        param1 == "name*" (case insensitive)
        param2 == "area*" (case insensitive)

    TRIGGER.IDS Matches:
    	None



/////////////
// Actions //
/////////////

Decode type - 0xD: param2 + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'I'
        no param4

    ACTION.IDS Matches:
        30 SetGlobal(S:Name*,S:Area*,I:Value*)
        109 IncrementGlobal(S:Name*,S:Area*,I:Value*)
        115 SetGlobalTimer(S:Name*,S:Area*,I:Time*GTimes)
        268 RealSetGlobalTimer(S:Name*,S:Area*,I:Time*GTimes)



Decode type - 0x1D: <first 6 characters of param2, padded with spaces if less than 6> + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'S'
        param4 type annotation == 'O'

    ACTION.IDS Matches:
        None



Decode type - 0x1E: <first 6 characters of param2, padded with spaces if less than 6> + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'S'
        no param4

    ACTION.IDS Matches:
        246 CreateCreatureAtLocation(S:GLOBAL*,S:Area*,S:ResRef*)
        256 CreateItemGlobal(S:Global*,S:Area*,S:ResRef*)
        335 SetTokenGlobal(S:GLOBAL*,S:Area*,S:Token*)



Decode type - 0x21: param2 + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'I'
        param4 type annotation == 'I'
        no param5
        param1 == "name*" (case insensitive)
        param2 == "area*" (case insensitive)

    ACTION.IDS Matches:
        364 SetGlobalRandom(S:Name*,S:Area*,I:Count*,I:Size*)
        377 SetGlobalTimerRandom(S:Name*,S:Area*,I:Min*GTimes,I:Max*GTimes)



Decode type - 0x25: param2 + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'I'
        param4 type annotation == 'I'
        param5 type annotation == 'I'
        param1 == "name*" (case insensitive)
        param2 == "area*" (case insensitive)

    ACTION.IDS Matches:
        364 SetGlobalRandomPlus(S:Name*,S:Area*,I:Count*,I:Size*,I:Plus*)



Decode type - 0x26: param2 + param1 => string1

    Match Requirements:
        action id == 297
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        no param3

    ACTION.IDS Matches:
        297 MoveToSavedLocation(S:GLOBAL*,S:Area*)



Decode type - 0x29: param2 + param1 => string1, param4 + param3 => string2

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'S'
        param4 type annotation != 'O' (parsed as int)

    ACTION.IDS Matches:
        446 IncrementGlobalOnce(S:Name1*,S:Area1*,S:Name2*,S:Area2*,I:Val*)

 

Interestingly, BitCheck() is incorrectly matched by the engine for string merging – which causes it to always return false in dialog conditions.

Link to comment
18 hours ago, Bubb said:

@argent77 Looks like GivePartyGoldGlobal() also doesn't concatenate its strings.

I stepped through what the in-engine encoder does, and aside from GivePartyGoldGlobal(), it aligns with Near Infinity's hardcoded list:

  Reveal hidden contents
//////////////
// Triggers //
//////////////

Decode type - 0xD: param2 + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'I'
        no param4

    TRIGGER.IDS Matches:
		0x400F Global(S:Name*,S:Area*,I:Value*)
		0x4034 GlobalGT(S:Name*,S:Area*,I:Value*)
		0x4035 GlobalLT(S:Name*,S:Area*,I:Value*)
		0x40F7 BitCheck(S:Name*,S:Area*,I:Bit*Bits) // BUG - The trigger expects both string1 and string2 to be used



Decode type - 0x21: param2 + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'I'
        param4 type annotation == 'I'
        no param5
        param1 == "name*" (case insensitive)
        param2 == "area*" (case insensitive)

    TRIGGER.IDS Matches:
    	None



/////////////
// Actions //
/////////////

Decode type - 0xD: param2 + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'I'
        no param4

    ACTION.IDS Matches:
        30 SetGlobal(S:Name*,S:Area*,I:Value*)
        109 IncrementGlobal(S:Name*,S:Area*,I:Value*)
        115 SetGlobalTimer(S:Name*,S:Area*,I:Time*GTimes)
        268 RealSetGlobalTimer(S:Name*,S:Area*,I:Time*GTimes)



Decode type - 0x1D: <first 6 characters of param2, padded with spaces if less than 6> + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'S'
        param4 type annotation == 'O'

    ACTION.IDS Matches:
        None



Decode type - 0x1E: <first 6 characters of param2, padded with spaces if less than 6> + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'S'
        no param4

    ACTION.IDS Matches:
        246 CreateCreatureAtLocation(S:GLOBAL*,S:Area*,S:ResRef*)
        256 CreateItemGlobal(S:Global*,S:Area*,S:ResRef*)
        335 SetTokenGlobal(S:GLOBAL*,S:Area*,S:Token*)



Decode type - 0x21: param2 + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'I'
        param4 type annotation == 'I'
        no param5
        param1 == "name*" (case insensitive)
        param2 == "area*" (case insensitive)

    ACTION.IDS Matches:
        364 SetGlobalRandom(S:Name*,S:Area*,I:Count*,I:Size*)
        377 SetGlobalTimerRandom(S:Name*,S:Area*,I:Min*GTimes,I:Max*GTimes)



Decode type - 0x25: param2 + param1 => string1

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'I'
        param4 type annotation == 'I'
        param5 type annotation == 'I'
        param1 == "name*" (case insensitive)
        param2 == "area*" (case insensitive)

    ACTION.IDS Matches:
        364 SetGlobalRandomPlus(S:Name*,S:Area*,I:Count*,I:Size*,I:Plus*)



Decode type - 0x26: param2 + param1 => string1

    Match Requirements:
        action id == 297
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        no param3

    ACTION.IDS Matches:
        297 MoveToSavedLocation(S:GLOBAL*,S:Area*)



Decode type - 0x29: param2 + param1 => string1, param4 + param3 => string2

    Match Requirements:
        has param1
        param1 type annotation != 'P'
        param1 type annotation != 'O'
        param1 type annotation != 'I' (parsed as string)
        param2 type annotation == 'S'
        param3 type annotation == 'S'
        param4 type annotation != 'O' (parsed as int)

    ACTION.IDS Matches:
        446 IncrementGlobalOnce(S:Name1*,S:Area1*,S:Name2*,S:Area2*,I:Val*)

 

Interestingly, BitCheck() is incorrectly matched by the engine for string merging – which causes it to always return false in dialog conditions.

Thank you. It looks like the game engine can actually handle both parameter encoding variants correctly. However, NI has to use the same encoding as WeiDU is using to prevent the bug mentioned in my previous comment. (And WeiDU made some arbitrary choices regarding parameter encoding for some engine variants.) See comments below.

Edited by argent77
Link to comment
8 hours ago, argent77 said:

It looks like the game engine can actually handle both parameter encoding variants correctly.

I think I'm missing something; in what cases does the engine handle both? From what I've seen actions / triggers generally only accept one version of the encoding, and if they encounter the other version the "no matching global" behavior will be used, which itself seems to be undefined for some of these.

Link to comment
32 minutes ago, Bubb said:

From what I've seen actions / triggers generally only accept one version of the encoding, and if they encounter the other version the "no matching global" behavior will be used, which itself seems to be undefined for some of these.

I think you're right. My test script had some flaws which lead to misleading results. The outcome of these actions is indeed random when an unsupported parameter encoding is used. But in that case WeiDU compiles both script actions incorrectly for oIWD and (possibly) oPST.

Link to comment

thanks argent77

everything is fixed, much obliged.

i wanted to test up to 6 member parties at different levels, up to max. however, i wanted to test all of them at various intervals against various enemies. how much xp does it take to make an archer + sorc viable against 4 beholders, for example. i wrote a script to incrementally add XP that will eventually get everyone to max xp, regardless of party size and multiclass. of course i could have 100 lines of if addglobals and partyhasXP statements, but all i really need is a few checkpoints like hla's, 7th level spells, etc.

 

    HotKey(X)
THEN
    RESPONSE #100
        AddexperiencePartyGlobal("HELPFULLER","GLOBAL")
        AddGlobals("HELPFULLER","HELPFULLER")
        SetTokenGlobal("HELPFULLER","GLOBAL","AREA_NAME")
        DisplayStringHead(Myself,103241)  // <AREA_NAME>

i realize reusing a global is horribly bad form. these tutorial variables are basically my 'test' variables so i don't introduce a lot of junk variables that may be confusing later on. rest assured were i to release a real mod, it would conform to all best practices.

 

 

Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

×
×
  • Create New...