Skip to content

[(BG1) BUG] Stealing from shopkeepers (0824)

2

Comments

  • BalquoBalquo Member, Developer Posts: 2,746
    edited August 2012
    @KiethS @Nathan Ok, I've made a bunch of fixes. I've created new creature files from AMNISE2 named AMNISE3,AMNISE4 and AMNISE5. This is due to when the guards are bribed it is not guaranteed that they all leave. I have then went through all the script files that summon the AMNISE guards and added the appropriate creatures.

    I fixed a facing direction for one of them and added a script for SHOP01. I've tested it all so hopefully this will be the last revision.

    @SethDavis I also made some fixes to existing scripts that did not contain your new changes from this thread http://forum.baldursgate.com/discussion/1664/bg1-merchant-theft-bypass-exploit

    EDIT: I see the two threads are now merged. This is better probably and once the Weidu is applied is it pretty much all belonging to @SethDavis

    MALTZ.BC S, SHOPLU.BCS, SHOP05.BCS, SHOP01.BCS, INNKEEP.BCS

    I added your
    SetDialog("")
    Recoil()
    SmallWait(6)
    and remove Enemy() if that was there.

    The code:
    COPY_EXISTING ~WATCHN2.CRE~ ~override/WATCHN3.CRE~ 
    ~AMNISE2.CRE~ ~override/AMNISE3.CRE~
    ~AMNISE2.CRE~ ~override/AMNISE4.CRE~
    ~AMNISE2.CRE~ ~override/AMNISE5.CRE~
    COPY_EXISTING ~INNKEEP.BCS~ ~override~
    ~SHOPKN.BCS~ ~override~
    ~ACT12.BCS~ ~override~
    ~MERCH2.BCS~ ~override~
    ~MERCH4.BCS~ ~override~
    ~MERCH5.BCS~ ~override~
    ~MERCH6.BCS~ ~override~
    ~MERCHA.BCS~ ~override~
    ~MALTZ.BCS~ ~override~
    ~SHOPLU.BCS~ ~override~
    ~SHOP05.BCS~ ~override~
    DECOMPILE_AND_PATCH BEGIN
    REPLACE_TEXTUALLY ~CreateCreature("WATCHN2",\[554.516\],8)
    Enemy()~ ~CreateCreature("WATCHN3",[554.516],8)~
    REPLACE_TEXTUALLY ~CreateCreature("AMNISE2",\[223.407\],9)
    CreateCreature("AMNISE2",\[223.407\],9)
    CreateCreature("AMNISE2",\[223.407\],9)
    END~ ~CreateCreature("AMNISE3",[223.407],9)
    CreateCreature("AMNISE4",[223.407],9)
    CreateCreature("AMNISE5",[223.407],9)
    END~
    REPLACE_TEXTUALLY ~CreateCreature("WATCHN2",\[-1.-1\],0)
    CreateCreature("WATCHN2",\[-1.-1\],0)
    END~ ~CreateCreature("WATCHN2",[-1.-1],0)
    CreateCreature("WATCHN3",[-1.-1],0)
    END~
    REPLACE_TEXTUALLY ~CreateCreature("AMNISE2",\[275.590\],10)
    CreateCreature("AMNISE2",\[275.590\],10)
    CreateCreature("AMNISE2",\[275.590\],10)
    END~ ~CreateCreature("AMNISE3",[275.590],10)
    CreateCreature("AMNISE4",[275.590],10)
    CreateCreature("AMNISE5",[275.590],10)
    END~
    REPLACE_TEXTUALLY ~CreateCreature("AMNISE2",\[276.319\],0)
    CreateCreature("AMNISE2",\[276.319\],0)
    CreateCreature("AMNISE2",\[276.319\],0)
    END~ ~CreateCreature("AMNISE3",[276.319],0)
    CreateCreature("AMNISE4",[276.319],0)
    CreateCreature("AMNISE5",[276.319],0)
    END~
    REPLACE_TEXTUALLY ~CreateCreature("AMNISE2",\[262.326\],8)
    CreateCreature("AMNISE2",\[262.326\],8)
    CreateCreature("AMNISE2",\[262.326\],8)
    END~ ~CreateCreature("AMNISE3",[262.326],8)
    CreateCreature("AMNISE4",[262.326],8)
    CreateCreature("AMNISE5",[262.326],8)
    END~
    REPLACE_TEXTUALLY ~CreateCreature("AMNISE2",\[286.326\],0)
    CreateCreature("AMNISE2",\[286.326\],0)
    CreateCreature("AMNISE2",\[286.326\],0)
    END~ ~CreateCreature("AMNISE3",[286.326],0)
    CreateCreature("AMNISE4",[286.326],0)
    CreateCreature("AMNISE5",[286.326],0)
    END~
    REPLACE_TEXTUALLY ~Wait(3)
    CreateCreature("FLAMEN",\[425.362\],6)
    CreateCreature("FLAMEN2",\[400.370\],6)
    CreateCreature("FLAMEN2",\[435.340\],6)
    Enemy()
    END~ ~SetDialog("")
    Recoil()
    SmallWait(6)
    CreateCreature("FLAMEN",[425.362],6)
    CreateCreature("FLAMEN2",[400.370],6)
    CreateCreature("FLAMEN2",[435.340],6)
    END~
    REPLACE_TEXTUALLY ~Wait(3)
    CreateCreature("FLAMEN",\[553.407\],7)
    CreateCreature("FLAMEN2",\[553.455\],7)
    CreateCreature("FLAMEN2",\[595.432\],7)
    Enemy()~ ~SetDialog("")
    Recoil()
    SmallWait(6)
    CreateCreature("FLAMEN",[553.407],7)
    CreateCreature("FLAMEN2",[553.455],7)
    CreateCreature("FLAMEN2",[595.432],7)~
    REPLACE_TEXTUALLY ~CreateCreature("FLAMEN",\[694.372\],0)
    CreateCreature("FLAMEN2",\[694.372\],0)
    CreateCreature("FLAMEN2",\[694.372\],0)
    END~ ~CreateCreature("FLAMEN",[694.372],6)
    CreateCreature("FLAMEN2",[694.372],6)
    CreateCreature("FLAMEN2",[694.372],6)
    END~
    END
    BUT_ONLY
    <<<<<<<< amnise.d
    REPLACE_ACTION_TEXT amnise ~ActionOverride("AMNISE3",EscapeArea())~ ~ActionOverride("AMNISE3",EscapeArea()) ActionOverride("AMNISE4",EscapeArea()) ActionOverride("AMNISE5",EscapeArea())~
    >>>>>>>>
    COMPILE ~amnise.d~
    COPY_EXISTING ~AMNISE3.cre~ ~override~
    WRITE_EVALUATED_ASCII 0x280 ~AMNISE3~
    BUT_ONLY_IF_IT_CHANGES
    COPY_EXISTING ~AMNISE4.cre~ ~override~
    WRITE_EVALUATED_ASCII 0x280 ~AMNISE4~
    BUT_ONLY_IF_IT_CHANGES
    COPY_EXISTING ~AMNISE5.cre~ ~override~
    WRITE_EVALUATED_ASCII 0x280 ~AMNISE5~
    BUT_ONLY_IF_IT_CHANGES
    COPY_EXISTING ~WATCHN2.cre~ ~override~
    WRITE_EVALUATED_ASCII 0x280 ~WATCHN2~
    BUT_ONLY_IF_IT_CHANGES
    COPY_EXISTING ~WATCHN3.cre~ ~override~
    WRITE_EVALUATED_ASCII 0x280 ~WATCHN3~
    BUT_ONLY_IF_IT_CHANGES
    <<<<<<<< monken.d
    REPLACE_ACTION_TEXT monken ~Shout(2)~ ~Shout(2) ActionOverride("WATCHN2",EscapeArea()) ActionOverride("WATCHN3",EscapeArea())~
    >>>>>>>>
    COMPILE ~monken.d~

    <<<<<<<< shop01guardspawn.baf
    IF
    StealFailed([ANYONE])
    THEN
    RESPONSE #100
    SetDialog("")
    Recoil()
    SmallWait(6)
    CreateCreature("FLAMEN",[558.462],6) // Flaming Fist Enforcer
    CreateCreature("FLAMEN2",[558.462],6) // Flaming Fist Enforcer
    CreateCreature("FLAMEN2",[558.462],6) // Flaming Fist Enforcer
    END
    >>>>>>>>
    COPY_EXISTING ~shop01.cre~ ~override~
    WRITE_ASCII 0x250 ~shop01~
    EXTEND_BOTTOM ~shop01.bcs~ ~shop01guardspawn.baf~
    Tanthalas
  • BhryaenBhryaen Member Posts: 2,874
    Wow, @Balquo, what does that do?
  • BalquoBalquo Member, Developer Posts: 2,746
    @Bhryaen Very little, actually. It pretty much makes all the AMNISE creatures unique so they all leave if bribed.

    Example: Load up AR4803 and fail a steal and bribe the guard with 200 gold. See what happens. It fixes this among a few other things.
  • BhryaenBhryaen Member Posts: 2,874
    @Balquo
    Ah, so this is sort of an addition to the Getting the Nashkel Guards To Perform fixes? OK, so the whole stealing situation remains a bungle...
  • BalquoBalquo Member, Developer Posts: 2,746
    @Bhryaen Yes, this makes no attempt in fixing anything that may be wrong, simply because I've no idea what is going on with it. I simply included SethDavis' additions to steal scripts that he forgot to include. This is why Winthrop goes hostile in the current build. Simply forgot to remove Enemy().
    Bhryaen
  • TanthalasTanthalas Member Posts: 6,738
    @Bhryaen, @Balquo

    This one should be sent to Confirmed Not Fixed or Being Worked On then?
  • BhryaenBhryaen Member Posts: 2,874
    @Tanthalas
    Oh, you're right- hasn't even been noticed by a dev yet. Heh... Moving to "Found in BG1-B"
  • BalquoBalquo Member, Developer Posts: 2,746
    The devs have been working on this.
  • SethDavisSethDavis Member Posts: 1,812
    edited August 2012
    checking this one now

    Potentially fixed - @Balquo's fix has been applied and my SetDialog("")s have been replaced with @Avenger_teambg's DialogInterrupt(FALSE) which when combined create an awesome force of thief induced failure! Which is actually a success for the purposes of this thread ^^
    TanthalasBhryaenAvenger_teambg
  • TanthalasTanthalas Member Posts: 6,738
    Well, I'm not sure what the expected behaviour is but:

    - Getting caught stealing gets me kicked out of Winthrop's store.
    - If I click fast enough I can initiate dialogue again, but no shop option, just room renting. When I exit no guards show up.
    - If I wait a second or two the guards show up.

    So basically, while you can't steal you still can escape the guards being summoned.
  • BalquoBalquo Member, Developer Posts: 2,746
    First point is expected behaviour.
    The third point is correct.

    Second point is partly correct. If the shopkeeper has a room renting option then you should still be able to access that. The guards not showing up if you click it quick enough after getting caught stealing is wrong and should be fixed.
  • BhryaenBhryaen Member Posts: 2,874
    edited August 2012
    Damn, I already reported everything @Tanthalas just did, but in some other related thread...

    [EDIT]:
    Oh, earlier in this thread- so not completely addressed:
    http://forum.baldursgate.com/discussion/comment/31625/#Comment_31625
    http://forum.baldursgate.com/discussion/comment/31809/#Comment_31809
  • Avenger_teambgAvenger_teambg Member, Developer Posts: 5,862
    The fast clicking should be disabled by DialogInterrupt(FALSE). And innkeep.bcs contains that.
    Why isn't it fixed then... I'm confused.
  • TanthalasTanthalas Member Posts: 6,738
    I'm not sure. Maybe that script (?) simply doesn't kick in immediately?
  • BhryaenBhryaen Member Posts: 2,874
    @Avenger_teambg
    Does DialogInterrupt(FALSE) work if the dialog is over? That is, the problem is that after being ejected from the store, you can immediately pause and click to start another dialog. So there's no dialog to interrupt at that point, just to forestall. It seems like something needs to be set to prevent the merchant from speaking again until the party has left the area and returned (and then not have the store available any longer). A grumpy line would also be nice, but still.
  • BalquoBalquo Member, Developer Posts: 2,746
    edited August 2012
    Strange. Is it possible the script just doesn't kick in that fast? I know it works as if you wait a bit then you can not start dialogue.

    @Tanthalas Ah, I see you wrote that already above. Need to refresh more :P
  • TanthalasTanthalas Member Posts: 6,738
    @Balquo
    That's true, after a sec he doesn't talk to you.
  • Avenger_teambgAvenger_teambg Member, Developer Posts: 5,862
    I know that the engine can force 2 things (Enemy)/(EscapeArea) immediately when a dialog is force closed (like with stealing). This is the so called 'freeze flag' in dltcep. I don't know how NI calls it.
    It would be nice if it could execute DialogInterrupt as well.
  • WispWisp Member Posts: 1,102
    In NI the field is called Threat Response and the bits Turn Hostile, Escape Area and Ignore Attack.
  • Avenger_teambgAvenger_teambg Member, Developer Posts: 5,862
    Yeah, that's a much more appropriate name.
  • TanthalasTanthalas Member Posts: 6,738
    So, moving this one to Confirmed Not Fixed since it still needs to be worked on. Hopefully its possible to perfect this one.
  • SethDavisSethDavis Member Posts: 1,812
    @Wisp - Can you point me to that set of flags please? I cannot seem to find them.
  • WispWisp Member Posts: 1,102
    @SethDavis
    It is a dword at 0x30, but apparently only in "BG2" DLGs. The DLGs imported straight from BG1 lack the whole field. Recompiling them with e.g., WeiDU BG2-ifies the DLGs.
  • SethDavisSethDavis Member Posts: 1,812
    @Wisp - Ah, thank you. I'll try that then.
  • SethDavisSethDavis Member Posts: 1,812
    Ok, so I found the area of code that handles these flags, but getting caught stealing never results in that code running, likely because there is no dialog being run while in a store?

    I tried calling the equivalent of DialogInterrupt(FALSE) from the caught stealing code and it appears to have worked.

    After being caught by Winthrop I paused, queued up dialog, and unpaused. Before this resulted in the behaviour @Tanthalas mentioned but now he is not interrupted.
    After paying off the guards that showed up I tried to speak with Wintrop again and he still wouldn't talk, which fits in with a previously desired behaviour.
    Upon leaving the store and immediately coming back in Winthrop was willing to talk again and only offered to let me rent a room.

    I think this may (finally) be a fix to this thread, barring alien intervention... or multiplayer....
    BhryaenAvenger_teambg
  • Avenger_teambgAvenger_teambg Member, Developer Posts: 5,862
    Sounds promising, so the threat response flags are not handled by stealing in shop?
    I thought they would, because you enter the shop from a dialog.
    On the other hand, it is the last action of a dialog, so i can understand.
    Not much use of those flags, then. You cannot attack them while in dialog :(
    SethDavis
  • SethDavisSethDavis Member Posts: 1,812
    @Avenger_teambg - I only played multiplayer for a little while, but are there situations where some players don't have their actions locked when another player initiates dialog (different houses maybe)? Either that or it might be used for scripting fights if someone had something against cutscene mode.
  • Avenger_teambgAvenger_teambg Member, Developer Posts: 5,862
    I don' know i never played this MP. But i guess, yeah, in mp others might attack the target.
    Speaking of MP, is BGEE MP compatible? Who will test that O_o
  • BhryaenBhryaen Member Posts: 2,874
    lol! Confirmed Fixed! Works fabulously! Kudos to @SethDavis

    The merchant pretty much instantly calls for the guards- couldn't sneak in any re-click distraction- who comes pretty darn fast- happened to be passing by. He becomes unavailable for anything until you leave, and when you return you either have access only to the inn or only to the purchase area, though in the latter case you can't buy anything. At the Nashkel Carnival you get five guards on you!! Bad bad thief!

    Worked with Winthrop, Lucky, Maltz, and the three thievable Nashkel Carnival merchants...

    The dialog doesn't change- i.e., to anything like "Like I'm selling you anything now? You can look but that's it!" But the exploit is definitely quashed with an iron boot.
  • BhryaenBhryaen Member Posts: 2,874
    @Balquo, you should check this one out. :-)
Sign In or Register to comment.