Jump to content


  • Content Count

  • Joined

  • Last visited

About HerrSvensson

Profile Information

  • Gender
  1. Locks that are not trapped are a little more difficult, but here's what you can do: Create a Lock script (bsc format) similar to the gdarts example above. Let's call it lock1.bcs Edit the area files for the area where the lock exists, for example AR0602 to unlock "Chest 6". Then start the script lock1.bcs by adding ActionOverride("Chest 6",ChangeAIScript("LOCK1",AREA)) in AR0602.baf after OnCreation().
  2. I've made a script like that. It was a bit tedious, because you need to know exactly which traps are detected and trapped beforehand. What I did was to create global variables for each trap and each lock in the trap scripts and used the triggers Detected, Disarmed and Opened in that script. Then when I knew the global variables, I could check what their value was in a normal script. For example, in when you start a new game, there is a chest called "Picture 1" which is trapped with a script called GDARTS. So what you could do is edit gdarts.bcs with Near Infinity like this: ... ... IF OnCreation() THEN RESPONSE #100 SetGlobal("Picture 1 trap","AR0602",2) SetGlobal("Picture 1 lock","AR0602",1) END IF Detected([ANYONE]) AreaCheck("AR0602") Name("Picture 1",Myself) !Global("Picture 1 trap","AR0602",1) THEN RESPONSE #100 SetGlobal("Picture 1 trap","AR0602",1) END IF Disarmed([ANYONE]) AreaCheck("AR0602") Name("Picture 1",Myself) !Global("Picture 1 trap","AR0602",0) THEN RESPONSE #100 SetGlobal("Picture 1 trap","AR0602",0) END IF Unlocked([ANYONE]) AreaCheck("AR0602") Name("Picture 1",Myself) !Global("Picture 1 lock","AR0602",0) THEN RESPONSE #100 SetGlobal("Picture 1 lock","AR0602",0) END Then you could disarm (or unlock) the trap in a custom script. // Very close to "Picture 1", start searching IF Class(Myself,THIEF_ALL) Range("Picture 1",10) !ModalState(DETECTTRAPS) // !DETECTTRAPS in the last round? Global("Picture 1 trap","AR0602",2) // Is trapped but not detected THEN RESPONSE #100 DisplayString(Myself,52376) // "There is something here.. just let me - Hold! It moves!" ClearActions(Myself) FindTraps() END // "Picture 1" trap detected (detect skill: 50) IF Range("Picture 1",10) Global("Picture 1 trap","AR0602",1) // Is detected Class(Myself,THIEF_ALL) CheckStatGT(Myself,39,TRAPS) // Can disarm THEN RESPONSE #100 ClearActions(Myself) RemoveTraps("Picture 1") PickLock("Picture 1") Continue() END
  3. After some testing, to detect some items, you need to use HasItem instead of HasItemEquiped. Example: MELFMET (Melf's MInute meteors). I think it's safer to use HasItem against weapons that are created by magic than static items.
  4. That explains it, and makes it a bit more tedious to detect Crushing damage.
  5. Here are some item codes that I believe the following spells will protect against. Protection from Normal Weapons + all mantle spells: Only Protection from Normal Missiles: PFMW + all Mantle spells (Magical weapons): PFMW + all Mantle spells (Enchantment +1): PFMW + all Mantle spells (Enchantment +2): PFMW, Improved Mantle, Absolute Immunity(Enchantment +3): PFMW, Absolute Immunity(Enchantment +4): PFMW, Absolute Immunity(Enchantment +5): PFMW only (Enchantment > +5): Most weapons here are just shocking grasp, vampire touch etc.
  6. I think I solved the MISTVA01 mystery. Its flag was not "Magical", and therefore only WIZARD_PROTECTION_FROM_NORMAL_WEAPONS works. The following melee weapons have Enchantments > 0 but can actually be protected with Protection from Normal Weapons: LIONSPIR SNAKSPIR WOLFSPIR BEARSPIR BONEFD MISTCD MISTVA MISTPO ABISRED1 MISTVA2 MISTICE DEMABI01 MISTWA MISTHO PLYSALA STALKESU WIGHT SPECTR ETTIN DAX1H01 PLYFIST WOLFM PLYSPID PLYWYVRN PLYMSTAR SW1H47 I tested this with Wakizashi +1 (SW1H47) and then only Protection from Normal Weapons or mantle spells work. Protection from Magical Weapons does not work against these weapons it seems.
  7. My question is if there is a good way to react to being attacked and cast the appropriate buffs like protection from magical weapon in script? There are several limitations that I have discovered. AttackedBy does not work properly. AttackedBy([ANYONE],RANGED) does not work AttackedBy([ANYONE],MELEE) does not work AttackedBy([ANYONE],DEFAULT) works What I want to do is to cast WIZARD_MANTLE, WIZARD_IMPROVED_MANTLE, WIZARD_ABSOLUTE_IMMUNITY, WIZARD_PROTECTION_FROM_MAGIC_WEAPONS or WIZARD_PROTECTION_FROM_NORMAL_WEAPONS when it is appropriate. It could work most of the times to just use AttackedBy([ANYONE],DEFAULT) Range(LastAttackerOf(),10) when attacked by Melee for example (not guaranteed), but to know exactly what type of shield to cast, I need to know more about the attacker, so I use HasItemEquiped("MISTVA01",LastAttackerOf()) for example to check if the enemy is using the weapon with code MISTVA01 (vampiric mist use this). According to NearInfinity it is a +3 weapon, but when I try the code against a Vampiric Mist, it will detect the +3 weapon, but the mist attacks with a normal weapon apparently and level drain you, so the spell WIZARD_PROTECTION_FROM_MAGIC_WEAPONS does not work. What does work is WIZARD_PROTECTION_FROM_NORMAL_WEAPONS. Is there a better way to determine what spell to cast? I also tried HasItemEquipedReal, but it seems to do the same. The HitBy function works okay, except against for the CRUSHING constant which is always active for any type of damage for some reason. The problem with this function is that you need to get hit first, and even then you don't know exactly what the appropriate response is (protection vs magic or physical?).
  8. I didn't use CombatCounter. How does this information help?
  9. Here is an example of a script I just did to test if the AI would react to being attacked by different enemies: IF AttackedBy(NearestEnemyOf(),DEFAULT) THEN RESPONSE #100 DisplayStringHead(NearestEnemyOf(),40734) Continue() END IF AttackedBy(SecondNearestEnemyOf(),DEFAULT) NumCreatureGT([ENEMY], 1) THEN RESPONSE #100 DisplayStringHead(SecondNearestEnemyOf(),40735) Continue() END IF AttackedBy(ThirdNearestEnemyOf(),DEFAULT) NumCreatureGT([ENEMY], 2) THEN RESPONSE #100 DisplayStringHead(ThirdNearestEnemyOf(),40736) Continue() END What is weird about this script is that it works only after I set the script in combat. By that I mean, when I am outside of combat, and activate the script and then go to combat, nothing happens. But when I set the script when combat has started, it works like expected. Does anyone know how to make it work regardless of whether you're in combat or not?
  10. Thanks, you are right. I don't know a good reason for why you would want to code like I did then, but it's still possible to do in SSL, that's good: IF TRIGGER OR(2) See([PC]) See(SecondNearest([PC]) Target(LastSeenBy(Myself)) THEN DO Action(Spell, WIZARD_FIREBALL) END
  11. Seems very useful. Why are targets separated in different blocks? Wouldn't it be sufficient to simply add an OR(x)? Example: Library definitions: For example: TARGET=test [PC] SecondNearest([PC]) Action definition: BEGIN_ACTION_DEFINITION Name(Spell) TRIGGER HaveSpell(scsargument1) !CheckStatGT(scstarget,0,SANCTUARY) CheckStatLT(Myself,50,SPELLFAILUREMAGE) !CheckStat(scstarget,2,WIZARD_SPELL_TRAP) ACTION RESPONSE #scsprob1 SetGlobalTimer("castspell","LOCALS",6) Spell(scstarget,scsargument1) END ssl script: IF TRIGGER TargetBlock(test) THEN DO Action(Spell,WIZARD_FIREBALL) END Will compile into: IF HaveSpell(WIZARD_FIREBALL) !CheckStatGT([PC],0,SANCTUARY) CheckStatLT(Myself,50,SPELLFAILUREMAGE) !CheckStat([PC],2,WIZARD_SPELL_TRAP) See([PC]) THEN RESPONSE #100 SetGlobalTimer("castspell","LOCALS",6) Spell([PC],WIZARD_FIREBALL) END IF HaveSpell(WIZARD_FIREBALL) !CheckStatGT(SecondNearest([PC]),0,SANCTUARY) CheckStatLT(Myself,50,SPELLFAILUREMAGE) !CheckStat(SecondNearest([PC]),2,WIZARD_SPELL_TRAP) See(SecondNearest([PC])) THEN RESPONSE #100 SetGlobalTimer("castspell","LOCALS",6) Spell(SecondNearest([PC]),WIZARD_FIREBALL) END Is there a way to compile it into the following instead? IF HaveSpell(WIZARD_FIREBALL) OR(2) See([PC]) See(SecondNearest([PC])) !CheckStatGT(LastSeenBy(),0,SANCTUARY) CheckStatLT(Myself,50,SPELLFAILUREMAGE) !CheckStat(LastSeenBy(),2,WIZARD_SPELL_TRAP) THEN RESPONSE #100 SetGlobalTimer("castspell","LOCALS",6) Spell(LastSeenBy(),WIZARD_FIREBALL) END I think the script would then be quicker, or am I wrong about that? Does infinity engine read triggers from bottom and up instead of top to bottom like I assume it does?
  12. I've never experienced an action being interrupted when a timer expired. Could it be because you use StartTimer/TimerExpires instead of SetGlobalTimer/GlobalTimerNotExpired ?
  13. Here is an old script of mine I know works for checking if TRUE_SIGHT is active for my inquisitor. I had Detectable spells installed. // True sight in combat IF ActionListEmpty() !GlobalTimerNotExpired("BUSY_MAGIC", "LOCALS") OR(3) Detect([ENEMY.0.0.BARD_ALL]) Detect([ENEMY.0.0.MAGE_ALL]) Detect([ENEMY.0.0.THIEF_ALL]) CheckStat(Myself, 0, 167) // TRUE_SIGHT HaveSpell(4232) // INQUIS_TRUE_SIGHT THEN RESPONSE #100 Spell(Myself, 4232) SetGlobalTimer("BUSY_MAGIC", "LOCALS", 6) END
  14. SetGlobal interrupts actions, even hiding, detecting traps, singing etc. That's why it's always best to start with it in my opinion. It might just interrupt your next actions in queue. If all else fails, you could try to force the spell, and maybe add a delay/wait: IF Global("BackStab","LOCALS",1) See([EVILCUTOFF]) HasItemEquiped("Ring28",Myself) Global("UsedRing28","LOCALS",0) !StateCheck(Myself,STATE_INVISIBLE) CheckStatGT(Myself,1,BACKSTABDAMAGEMULTIPLIER) THEN RESPONSE #100 //UseItem("Ring28",Myself) SetGlobal("UsedRing28","LOCALS",1) ForceSpell(Myself,WIZARD_IMPROVED_INVISIBILITY) END
  15. I solved this problem. Apparently the functions Detected, Unlocked or Disarmed only works on the actual objects you interact with. Example 1: edit the trap file, GDARTS, which "Picture 1" is using. Whenever one of the triggers above is activated, simply add a global variable. A thief will can then check for this global variable. GDARTS.BAF: IF OnCreation() THEN RESPONSE #100 SetGlobal("EllRoomTrap5Trap","AR0602",2) SetGlobal("Picture1Trap","AR0602",2) SetGlobal("Picture1Lock","AR0602",1) END // ---- The old script ------ IF OR(2) Entered([ANYONE]) Opened([ANYONE]) THEN RESPONSE #100 DisplayString(LastTrigger,14381) // Trap Sprung ForceSpell(LastTrigger,TRAP_DARTS) END // --------------------------- IF Detected([ANYONE]) AreaCheck("AR0602") Name("Ell Room Trap 5",Myself) !Global("EllRoomTrap5Trap","AR0602",1) // Is not detected? THEN RESPONSE #100 SetGlobal("EllRoomTrap5Trap","AR0602",1) DisplayStringHead(Myself,16488) // "You have detected a trap." END IF Detected([ANYONE]) AreaCheck("AR0602") Name("Picture 1",Myself) !Global("Picture1Trap","AR0602",1) // Is not detected? THEN RESPONSE #100 SetGlobal("Picture1Trap","AR0602",1) DisplayStringHead(Myself,16488) // "You have detected a trap." END IF Disarmed([ANYONE]) AreaCheck("AR0602") Name("Ell Room Trap 5",Myself) GlobalGT("EllRoomTrap5Trap","AR0602",0) // Is trapped? THEN RESPONSE #100 SetGlobal("EllRoomTrap5Trap","AR0602",0) DisplayStringHead(Myself,16520) // "Trap Disarmed" END IF Disarmed([ANYONE]) AreaCheck("AR0602") Name("Picture 1",Myself) GlobalGT("Picture1Trap","AR0602",0) // Is trapped? THEN RESPONSE #100 SetGlobal("Picture1Trap","AR0602",0) DisplayStringHead(Myself,16520) // "Trap Disarmed" END IF Unlocked([ANYONE]) AreaCheck("AR0602") Name("Picture 1",Myself) Global("Picture1Lock","AR0602",1) // Is locked? THEN RESPONSE #100 DisplayStringHead(Myself,16517) // "Lock Pick Succeeded" SetGlobal("Picture1Lock","AR0602",0) END Example 2: Locked objects without traps were more tedious. I first created a new "lock script" and loaded an object with it using ChangeAIScript in an ARxxxx.baf file. AR0602.BAF IF OnCreation() Global("NewGame","AR0602",0) THEN RESPONSE #100 HideGUI() FadeToColor([1.0],0) SetGlobal("NewGame","AR0602",1) ActionOverride("Chest 6",ChangeAIScript("LOCKTEST",AREA)) // <-- Added this Continue() END IF Global("RielevDisable","AR0602",0) THEN RESPONSE #100 SetGlobal("RielevDisable","AR0602",1) TriggerActivation("Rielevdeadtrigger",FALSE) END IF Global(... LOCKTEST.BAF: IF OnCreation() THEN RESPONSE #100 SetGlobal("Chest6Lock","AR0602",1) END IF Unlocked([ANYONE]) AreaCheck("AR0602") Name("Chest 6",Myself) Global("Chest6Lock","AR0602",1) // Is locked? THEN RESPONSE #100 DisplayStringHead(Myself,16517) // "Lock Pick Succeeded" SetGlobal("Chest6Lock","AR0602",0) END The last solution in example 2 works, but it feels a bit too much like a hack. I don't think it works to load a "lock script" for an object in one area only so with this approach you'd have to load the script in all areas where the object exists. Of course, you still need to use different global variables for lock checking depending on which area you are in otherwise if a lock is unlocked in one area, the same object in another area might think its unlocked when its not. Here is a script I used for my thief: //*Thief toggle* // Toggle disarm activity ON: IF ActionListEmpty() Class(Myself,THIEF_ALL) Global("THIEF_SEARCH","LOCALS",0) // Toggle: Off Hotkey(D) THEN RESPONSE #100 DisplayString(Myself,17596) // "THIEF SCOUT:" DisplayStringHead(Myself,14669) // "AI On" SetGlobal("THIEF_SEARCH","LOCALS",1) END // Toggle disarm activity OFF: IF Class(Myself,THIEF_ALL) Global("THIEF_SEARCH","LOCALS",1) // Toggle: On Hotkey(D) THEN RESPONSE #100 DisplayString(Myself,17596) // "THIEF SCOUT:" DisplayStringHead(Myself,14671) // "AI Off" SetGlobal("THIEF_SEARCH","LOCALS",0) END // *Detect traps* // Find traps IF ActionListEmpty() !GlobalTimerNotExpired("LOOT_TIMER","LOCALS") Global("THIEF_SEARCH","LOCALS",1) // Toggle: On !ModalState(DETECTTRAPS) !GlobalTimerNotExpired("FIND_TRAP_TIMER","LOCALS") // Is Find traps off? THEN RESPONSE #100 SetGlobalTimer("FIND_TRAP_TIMER","LOCALS",5) FindTraps() END // Very close to "Ell Room Trap 5" IF Class(Myself,THIEF_ALL) Range("Ell Room Trap 5",10) !ModalState(DETECTTRAPS) !GlobalTimerNotExpired("FIND_TRAP_TIMER","LOCALS") // Is Find traps off? Global("EllRoomTrap5Trap","AR0602",2) // Is trapped but not detected? THEN RESPONSE #100 DisplayString(Myself,52376) // "There is something here.. just let me - Hold! It moves!" ClearActions(Myself) SetGlobalTimer("FIND_TRAP_TIMER","LOCALS",5) FindTraps() END // Thief toggle ON: "Ell Room Trap 5" trap detected (detect skill: 10) IF Range("Ell Room Trap 5",10) !GlobalTimerNotExpired("LOOT_TIMER","LOCALS") Global("THIEF_SEARCH","LOCALS",1) // Toggle: On Global("EllRoomTrap5Trap","AR0602",1) // Is detected? Class(Myself,THIEF_ALL) CheckStatGT(Myself,69,TRAPS) // Can disarm? THEN RESPONSE #100 ClearActions(Myself) SetInterrupt(FALSE) RemoveTraps("Ell Room Trap 5") SetInterrupt(TRUE) Continue() END // Very close to "Picture 1" IF Class(Myself,THIEF_ALL) Range("Picture 1",10) !ModalState(DETECTTRAPS) !GlobalTimerNotExpired("FIND_TRAP_TIMER","LOCALS") Global("Picture1Trap","AR0602",2) // Is trapped but not detected? THEN RESPONSE #100 DisplayString(Myself,52376) // "There is something here.. just let me - Hold! It moves!" ClearActions(Myself) SetGlobalTimer("FIND_TRAP_TIMER","LOCALS",5) FindTraps() END // Thief toggle ON: "Picture 1" trap detected (detect skill: 50) IF Range("Picture 1",10) !GlobalTimerNotExpired("LOOT_TIMER","LOCALS") Global("THIEF_SEARCH","LOCALS",1) // Toggle: On Global("Picture1Trap","AR0602",1) // Is detected? Class(Myself,THIEF_ALL) CheckStatGT(Myself,39,TRAPS) // Can disarm? THEN RESPONSE #100 ClearActions(Myself) SetInterrupt(FALSE) RemoveTraps("Picture 1") PickLock("Picture 1") SetInterrupt(TRUE) Continue() END // Thief toggle ON: "Chest 6" is locked (lock skill: 20) IF ActionListEmpty() !See([ENEMY]) Range("Chest 6",10) Global("Chest6Lock","AR0602",1) // Is locked? !GlobalTimerNotExpired("LOOT_TIMER","LOCALS") Global("THIEF_SEARCH","LOCALS",1) // Toggle: On Class(Myself,THIEF_ALL) CheckStatGT(Myself,19,LOCKPICKING) THEN RESPONSE #100 SetInterrupt(FALSE) PickLock("Chest 6") SetInterrupt(TRUE) Continue() END
  • Create New...