CamDawg Posted November 15, 2006 Share Posted November 15, 2006 In Tyrianna's home, NPC s can not pass the stairs, resulting in her assassins never being able to succeed. While the cat no longer tries to summon guards, if the locked chest is opened it can summon guards hours/days/months after you've left. Typo in William Reirrac's dialogue from the GTU. Protector of the Second has no lore value, hence it always appears identified. In the Asylum maze, on of the imps near the crystal is on impassable ground and can not move (basically, it's stuck in a wall). // item requires lore COPY_EXISTING ~leat03.itm~ ~override~ // protector of the second WRITE_SHORT 0x42 60 BUT_ONLY_IF_IT_CHANGES //moves imp to passable ground COPY_EXISTING ~ar1513.are~ ~override~ READ_LONG 0x54 "actor_off" READ_SHORT 0x58 "actor_num" FOR (index = 0; index < actor_num; index = index + 1) BEGIN READ_ASCII ("%actor_off%" + 0x80 + ("%index%" * 0x110)) "cre_file" PATCH_IF ("%cre_file%" STRING_COMPARE_CASE "imp01" = 0) BEGIN READ_SHORT("%actor_off%" + 0x20 + ("%index%" * 0x110)) "x_coord" READ_SHORT("%actor_off%" + 0x22 + ("%index%" * 0x110)) "y_coord" PATCH_IF (("%x_coord%" = 1639) AND ("%y_coord%" = 1140)) BEGIN WRITE_SHORT("%actor_off%" + 0x20 + ("%index%" * 0x110)) 1724 WRITE_SHORT("%actor_off%" + 0x22 + ("%index%" * 0x110)) 1164 WRITE_SHORT("%actor_off%" + 0x24 + ("%index%" * 0x110)) 1724 WRITE_SHORT("%actor_off%" + 0x26 + ("%index%" * 0x110)) 1164 SET "index" = "%actor_num%" // kill loop END END END BUT_ONLY_IF_IT_CHANGES I'll have to think about the best way for ctalarm.bcs to not suck. Link to comment
Smoketest Posted November 15, 2006 Share Posted November 15, 2006 You stumbled on some old bugs... Play-throughs are great for finding the more obvious bugs, but admittedly they take more time. I modified my alarm scripts for containers to make them more realistic... here are some suggestions based on my working experiments of the past. Pseudo-code... - Am I open? - No, do nothing. - Yes, can I see a neutral actor? (the container's owner/guard) - No, do nothing. (nobody's around) - Yes, is that actor a humanoid? (non-humanoids usually don't care) - No, do nothing. (just an animal, undead or monster) - Yes, is the person who opened me invisible somehow? - No, sound the alarm. (busted!) - Yes, do nothing. (got away clean) I got tired of being 'seen' when nobody was around, or by the cat in that safehouse, so I decided to overhaul the scripts. You could modify/delete the actor type checking. I added it to show some versatility. In the case of the safehouse, the actor type checking allows you to loot the container if the cat is the only neutral actor present. Link to comment
Roana Posted November 15, 2006 Share Posted November 15, 2006 I'll have to think about the best way for ctalarm.bcs to not suck. Hello, if it is only this one trap in Paladin-stronghold, I would suggest a special script for this trap. If all traps are mentioned here, that have this script assigned, then I have only a more complicate scripting solution... . This script is used in my game on 69 traps (so said my NI). For only one trap, I would rename it and set an area-global, so that it would only call the enfoarm.cre once. example: rename it to ctpala.bcs (or something) and assign the followed to it. IF Opened([ANYONE]) !StateCheck(LastTrigger,STATE_INVISIBLE) !StateCheck(LastTrigger,STATE_IMPROVEDINVISIBILITY) Global("TrapDisarmed","ARXXXX",0) THEN RESPONSE #100 SetGlobal("TrapDisarmed","ARXXXX",1) CreateCreature("ENFORAM",[-1.-1],0) // No such index END IF True() THEN RESPONSE #100 NoAction() END If all traps are mentioned, I would have set them one Global and script all other into the arxxxx.bcs, because there are unfortunatly often more than one trap with this script in one area... But it would take much more work though... Regards Roana Link to comment
CamDawg Posted November 15, 2006 Author Share Posted November 15, 2006 Really, the only issue that needs to be addressed with the trap is the time element. I had burgled the house (the cat sounding the alarm is fixed already); when I went there a week later during the paladin stronghold quests (woo, go multi strongholds) Tyrianna's NORH guard sounded the alarm. Link to comment
devSin Posted November 15, 2006 Share Posted November 15, 2006 ENFORAM sticks around longer than it should. Just delete the Wait() before it destroys itself. Link to comment
Roana Posted November 16, 2006 Share Posted November 16, 2006 ENFORAM sticks around longer than it should. Just delete the Wait() before it destroys itself. Hello , I have made a little research in my old BG1-trap-fixes, and after reading additional once more this point in Sim's scripting guide, I have found an easy solution (silly me, not to look first in this guide ). change the last block in ENFORAM.BCS as followed: IF OR(2) !See([NOTGOOD.HUMANOID]) Global("warn","LOCALS",1) THEN RESPONSE #100 Wait(5) DestroySelf() END The original trigger !See([NOTGOOD]) includes the cat that is there in the AR0415, and so the ENFORAM.CRE will never disappear, as it sees "NOTGOOD" - the cat Regards Roana Link to comment
CamDawg Posted November 16, 2006 Author Share Posted November 16, 2006 Yeah, fixed. The Wait(5) should remain as it gives a slight window for folks to notice you. If someone came around a corner 3 seconds after you opened the locked chest, I think they could put two and two together. // containers can summon guards days after they're open COPY_EXISTING ~enforam.bcs~ ~override~ DECOMPILE_BCS_TO_BAF REPLACE_TEXTUALLY ~!See(\[NOTGOOD\])~ ~!See([NEUTRAL.HUMANOID])~ COMPILE_BAF_TO_BCS BUT_ONLY_IF_IT_CHANGES Link to comment
CamDawg Posted November 16, 2006 Author Share Posted November 16, 2006 Actually, no. This would still have the problem of enforam.cre sticking around if the PC was invisible or dead. Basically, if it's not summoning guards, we want enforam.cre to wait five seconds and disappear. Since the second block will only get evaluated if the first is false, then we can be exceptionally lazy and just make it a True() block: // containers can summon guards days after they're open COPY_EXISTING ~enforam.bcs~ ~override~ DECOMPILE_BCS_TO_BAF REPLACE_TEXTUALLY ~OR(2)[%tab% %lnl%%mnl%%wnl%]+!See([NOTGOOD])[%tab% %lnl%%mnl%%wnl%]+Global("warn","LOCALS",1)~ ~True()~ COMPILE_BAF_TO_BCS BUT_ONLY_IF_IT_CHANGES Or would this keep resetting the Wait()? Link to comment
devSin Posted November 16, 2006 Share Posted November 16, 2006 It shouldn't reset the Wait(). Actions from the same block shouldn't get added to the queue and don't interrupt it (however the engine decides it's at the same block in a script that it's currently executing). You can use ActionListEmpty() in place of True() if you want to be super sure. My concern is with the outstanding bug where BD reports they can be summoned if you leave and come back. The assumption is that if you leave the area while ENFORAM is waiting, it won't execute its DestroySelf(), and processing will start over if you return to the area (and this time, you'll probably be visible or the active actors might have changed). We might be able to get away with a LOCALS timer and have it DestroySelf() at the head of the script if the timer's expired, but the triggers to get everything working together with only 3 blocks might suck (but I don't have access to the original script at the moment). Maybe: IF OnCreation() THEN RESPONSE #100 SetGlobalTimer() Continue() END IF Stuff() GlobalTimerNotExpired() THEN RESPONSE #100 Caught() END IF GlobalTimerExpired() THEN RESPONSE #100 DestroySelf() END ? Link to comment
Roana Posted November 16, 2006 Share Posted November 16, 2006 Actually, no. This would still have the problem of enforam.cre sticking around if the PC was invisible or dead. Basically, if it's not summoning guards, we want enforam.cre to wait five seconds and disappear. Since the second block will only get evaluated if the first is false, then we can be exceptionally lazy and just make it a True() block: // containers can summon guards days after they're open COPY_EXISTING ~enforam.bcs~ ~override~ DECOMPILE_BCS_TO_BAF REPLACE_TEXTUALLY ~OR(2)[%tab% %lnl%%mnl%%wnl%]+!See([NOTGOOD])[%tab% %lnl%%mnl%%wnl%]+Global("warn","LOCALS",1)~ ~True()~ COMPILE_BAF_TO_BCS BUT_ONLY_IF_IT_CHANGES Or would this keep resetting the Wait()? Hello, well, maybe, I should claerify this more : Here are TWO scripts involved: the script on the trap itself (CTALARM.BCS): IF Opened([ANYONE]) !StateCheck(LastTrigger,STATE_INVISIBLE) !StateCheck(LastTrigger,STATE_IMPROVEDINVISIBILITY) THEN RESPONSE #100 CreateCreature("ENFORAM",[-1.-1],0) // No such index END IF True() THEN RESPONSE #100 NoAction() END This will ONLY spawn the ENFOARM.CRE, if the PC IS VISIVLE and the second script: the script on the spawned ENFOARM.CRE (ENFOARM.BCS): IF See([PC]) See([NEUTRAL.HUMANOID]) !Dead("LastSeenBy(Myself)") Global("warn","LOCALS",0) THEN RESPONSE #50 SetInterrupt(FALSE) SetGlobal("warn","LOCALS",1) DisplayStringHead(LastSeenBy(Myself),58585) // Diebe! DisplayStringHead(Myself,9896) // Jemand hat Euch bemerkt! Ihr hört, wie die Wache gerufen wird! ActionOverride(LastSeenBy(Myself),Enemy()) Wait(3) CreateCreatureObject("AMNCEN1",Myself,0,0,0) // Amnischer Zenturion CreateCreatureObject("AMNLEG1",Myself,0,0,0) // Amnischer Legionär CreateCreatureObject("AMNLEG1",Myself,0,0,0) // Amnischer Legionär CreateCreatureObject("AMNLEG1",Myself,0,0,0) // Amnischer Legionär CreateCreatureObject("AMNLEG1",Myself,0,0,0) // Amnischer Legionär CreateCreatureObject("COWENF1",Myself,0,0,0) // Verhüllter Vollstrecker CreateCreatureObject("COWENF1",Myself,0,0,0) // Verhüllter Vollstrecker SetInterrupt(TRUE) RESPONSE #30 SetInterrupt(FALSE) SetGlobal("warn","LOCALS",1) DisplayStringHead(LastSeenBy(Myself),58585) // Diebe! DisplayStringHead(Myself,9896) // Jemand hat Euch bemerkt! Ihr hört, wie die Wache gerufen wird! ActionOverride(LastSeenBy(Myself),Enemy()) Wait(3) CreateCreatureObject("AMNLEG1",Myself,0,0,0) // Amnischer Legionär CreateCreatureObject("AMNLEG1",Myself,0,0,0) // Amnischer Legionär SetInterrupt(TRUE) RESPONSE #30 SetInterrupt(FALSE) SetGlobal("warn","LOCALS",1) DisplayStringHead(LastSeenBy(Myself),58585) // Diebe! DisplayStringHead(Myself,9896) // Jemand hat Euch bemerkt! Ihr hört, wie die Wache gerufen wird! ActionOverride(LastSeenBy(Myself),Enemy()) Wait(3) CreateCreatureObject("AMNCEN1",Myself,0,0,0) // Amnischer Zenturion CreateCreatureObject("COWENF1",Myself,0,0,0) // Verhüllter Vollstrecker SetInterrupt(TRUE) RESPONSE #10 SetInterrupt(FALSE) SetGlobal("warn","LOCALS",1) DisplayStringHead(LastSeenBy(Myself),58585) // Diebe! DisplayStringHead(Myself,9896) // Jemand hat Euch bemerkt! Ihr hört, wie die Wache gerufen wird! ActionOverride(LastSeenBy(Myself),Enemy()) Wait(3) CreateCreatureObject("AMNCEN1",Myself,0,0,0) // Amnischer Zenturion CreateCreatureObject("AMNCEN1",Myself,0,0,0) // Amnischer Zenturion CreateCreatureObject("AMNCEN1",Myself,0,0,0) // Amnischer Zenturion CreateCreatureObject("AMNLEG1",Myself,0,0,0) // Amnischer Legionär CreateCreatureObject("AMNLEG1",Myself,0,0,0) // Amnischer Legionär CreateCreatureObject("AMNLEG1",Myself,0,0,0) // Amnischer Legionär CreateCreatureObject("COWENF1",Myself,0,0,0) // Verhüllter Vollstrecker CreateCreatureObject("COWENF1",Myself,0,0,0) // Verhüllter Vollstrecker CreateCreatureObject("COWENF1",Myself,0,0,0) // Verhüllter Vollstrecker SetInterrupt(TRUE) END IF OR(2) !See([NOTGOOD.HUMANOID]) Global("warn","LOCALS",1) THEN RESPONSE #100 Wait(5) DestroySelf() END This will either spawn the guards, if the creature sees NOTGOOD and THEN set the LOCALS to 1 OR DestroySelf, if it not sees NOTGOOD or has already spawned guards after 5 seconds. Well, while this creature only will be spawned, if the PC is visible, you don't need to exclude unvisible PC from the script of the (in this case not existing) ENFOARM.CRE. But if this creature IS ALREADY there, spawned by the CTALARM.BCS, then it will ONLY be destroyed, if it has done the job to spawn the guards, or if it not sees any NOTGOOD creature, as it is in the original. But a NOTGOOD creature is also a cat, so you have only to specify, that it should be a HUMANOID too, or NOTGOOD will ever return true, if a cat is running around I know, that this is more complicate, as it was in BG1, because in BG1 all this is bounded in one script, that is assigned on the trap. In BG1 the trap-script will on condition OPENED not only check the invisible STATE of the PC, but additional the See NOTGOOD in the same block. If this block returned true, this first and only script also calls the guards. There I have had only to fix the ACTXX.BCSs to check not only for NOTGOOD, but for NOTGOOD.HUMANOID, so that cats, running alone there in a room, don't call guards Hm... - well, I know, it IS more complicate in BG2 as in BG1, and additional once more complicate to explain this. I hope, this all sounds not too confusing to you Otherwise, please try to trust me this one time, fix this, as I have said above and test it - I promise, it will fix the cat-problem (I know, I'm only a woman, but even not a normal woman in logical-thinking, and scripting is my favorite pleasure in the BG-games - I know, I make also faults, but this time I'm really very sure, I'm right) Regards Roana (I have not written some words in capital letters to cry at you, only to try, to make something more clear) Link to comment
CamDawg Posted November 16, 2006 Author Share Posted November 16, 2006 We might be able to get away with a LOCALS timer and have it DestroySelf() at the head of the script if the timer's expired, but the triggers to get everything working together with only 3 blocks might suck (but I don't have access to the original script at the moment). I was thinking something a little different--instead of that final True() block containing the DestroySelf, have it set the timer instead. Then DestroySelf() when the timer ends, i.e. IF timer expired THEN destroySelf END IF thief gets caught (existing block, no change) THEN create guards END IF true THEN set timer END Add a variable to make sure the last block doesn't repeat, and we've got it. Since the second block already has a no-repeat variable the timer always gets set on either the first or second pass of the script and the guards never get summoned on an expired timer. Link to comment
devSin Posted November 16, 2006 Share Posted November 16, 2006 Except that you'll set the timer forever and ever and ever, it looks like it'll work the same. I just didn't want to suggest a method that both creates a new variable (set timer once) and then the timer itself. Data overload! But yeah, that's my current thought without looking at the script. (We should probably look at ALARM25 too.) Link to comment
CamDawg Posted November 16, 2006 Author Share Posted November 16, 2006 @Roana: See([NEUTRAL.HUMANOID]) ... !See([NOTGOOD.HUMANOID]) I presume you mean [NOTGOOD.HUMANOID] on the second one. Even so, while it works in this case, I prefer scripts to be self-contained. A modder may create a mod that uses enforam.cre without going through ctalarm.bcs. Given the choice between a fix that applies to one case or several, I'll take the latter. Link to comment
CamDawg Posted November 16, 2006 Author Share Posted November 16, 2006 Except that you'll set the timer forever and ever and ever, it looks like it'll work the same. Add a variable to make sure the last block doesn't repeat, and we've got it. I know you want a way that doesn't invoke a second variable, but I'm also trying to imagine the easiest patching path. Looking at our stuff though, I think it's probably about the same--some R_Ts and an EXTEND_TOP all told. Link to comment
Roana Posted November 16, 2006 Share Posted November 16, 2006 @Roana: See([NEUTRAL.HUMANOID]) ... !See([NOTGOOD.HUMANOID]) I presume you mean [NOTGOOD.HUMANOID] on the second one. Even so, while it works in this case, I prefer scripts to be self-contained. A modder may create a mod that uses enforam.cre without going through ctalarm.bcs. Given the choice between a fix that applies to one case or several, I'll take the latter. Hello , yes, I mean the second, cause the first is already in the original script Well, if you want to include non-visible PC here too, the append after block: IF OR(2) !See([NOTGOOD.HUMANOID]) Global("warn","LOCALS",1) THEN RESPONSE #100 Wait(5) DestroySelf() END this: IF OR(2) !See([PC]) Global("warn","LOCALS",1) THEN RESPONSE #100 Wait(5) DestroySelf() END The timer, you want is done by the Wait(5) action Regards Roana Edited: translation fault Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.