![]() |
First off, I would like to give kudos to SimDing0 for his "Complete Scripting Guide". The following codeblocks below were inspired by his "False Conditions" method. I was wondering whether veteran coders can go through my codeblocks and see whether it can be further streamlined.
One problem with only having one codeblock to handle priority targetting is that the conditions can vary so wildly, making it impossible to make one without flaws. The most glaring one being overlooking more suitable targets just because they are lower on the list. It was problematic though, to create a priority targetting system for each spell/attack without severely bloating the .BS file. I think I may have found a solution though. Under my system, only 3 codeblocks are needed to enable priority targetting from the NearestEnemy to the TenthNearestEnemy. The following example below demostrates the handling of two spells. Melf's Acid Arrow and Magic Missile. Note that the numbers come from IWD, so it may not match up with the more familiar BG2 ones. Note also that for brevity sake, I have removed some conditions and codeblocks for easier viewing and to place more emphasise on how the priority targetting works. This example is just about the bare minimum needed for the thing to work properly. I have tested it a bit so far, and there seems to be no problems yet. </font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">// [*Melf's Acid Arrow*] IF See([ENEMY]) HaveSpell(2211) !GlobalTimerNotExpired("MAArrow","L OCALS") OR(3) !See(NearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(SecondNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(ThirdNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(FourthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(FifthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(SixthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(SeventhNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(EighthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(NinthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(TenthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) THEN RESPONSE #100 SetGlobal("S2211","LOCALS",1) Continue() END IF !Global("S2211","LOCALS",1) THEN RESPONSE #100 SetGlobalTimer("MAArrow","LOCALS&qu ot;,18) Spell(LastSeenBy(Myself),2211) END IF Global("S2211","LOCALS",1) THEN RESPONSE #100 SetGlobal("S2211","LOCALS",0) Continue() END // [*Magic Missile*] IF See([ENEMY]) HaveSpell(2112) !GlobalTimerNotExpired("MAArrow","L OCALS") OR(3) !See(NearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTMAGIC) OR(3) !See(SecondNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTMAGIC) OR(3) !See(ThirdNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTMAGIC) OR(3) !See(FourthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTMAGIC) OR(3) !See(FifthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTMAGIC) OR(3) !See(SixthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTMAGIC) OR(3) !See(SeventhNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTMAGIC) OR(3) !See(EighthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTMAGIC) OR(3) !See(NinthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTMAGIC) OR(3) !See(TenthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTMAGIC) THEN RESPONSE #100 SetGlobal("S2211","LOCALS",1) Continue() END IF !Global("S2112","LOCALS",1) THEN RESPONSE #100 Spell(LastSeenBy(Myself),2112) END IF Global("S2112","LOCALS",1) THEN RESPONSE #100 SetGlobal("S2112","LOCALS",0) Continue() END // [*Twiddle Thumbs*] IF ActionListEmpty() THEN RESPONSE #100 DisplayString(Myself,3678) END</pre>[/QUOTE]Now I will go through each codeblock in detail. </font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">// [*Melf's Acid Arrow*] IF See([ENEMY]) HaveSpell(2211) !GlobalTimerNotExpired("MAArrow","L OCALS") OR(3) !See(NearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(SecondNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(ThirdNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(FourthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(FifthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(SixthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(SeventhNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(EighthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(NinthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) OR(3) !See(TenthNearestEnemyOf(Myself)) CheckStat(LastSeenBy(Myself),1,MINORGLOBE) CheckStatGT(LastSeenBy(Myself),40,RESISTACID) THEN RESPONSE #100 SetGlobal("S2211","LOCALS",1) Continue() END</pre>[/QUOTE]This is the heart of the priority targetting process. It will start to execute when an enemy is seen. First it checks that the character has the spell memorised. The Global Timer ensures that Melf's Acid Arrow is only casted every three rounds. The setting of the Global Timer is done by the next codeblock. The OR() statements are where the False Conditions come into play. When the character sees the NearestEnemy, LastSeenBy() is set and the first line in the OR() sequence is set as false. When all the lines in the OR() statement are false, the target is a Valid one and the codeblock will return false, making it move on to the next codeblock where the spell will be cast on the LastSeenBy() target which has already been recognised as being a Valid one. When one of the lines in the OR() statement is true, the target is considered Invalid and it will move on to the next OR() statement. This proceeds so on and so forth. If ALL the OR() statements are true, meaning none of the nearest ten targets are valid. The codeblock will return true and execute the RESPONSE #100 statements. In the RESPONSE #100 statements, the Global variable, "S2211", will be set to 1 and Continue() will cause the script to move on to the next codeblock, where it will be informed of the invalidity of the targets. </font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">IF !Global("S2211","LOCALS",1) THEN RESPONSE #100 SetGlobalTimer("MAArrow","LOCALS&qu ot;,18) Spell(LastSeenBy(Myself),2211) END</pre>[/QUOTE]If "S2211" is 1, the codeblock returns false and moves on to the next codeblock. If 0, the codeblock is executed, the Global Timer is set, and the spell is casted on the valid target. </font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">IF Global("S2211","LOCALS",1) THEN RESPONSE #100 SetGlobal("S2211","LOCALS",0) Continue() END</pre>[/QUOTE]This codeblock serves to reset the "S2211" variable when the initial round of targetting reveals no valid targets. If executed, it will move on to the next set of codeblocks since there were no valid targets for Melf's Acid Arrow. By the by, all the targetting conditions are in the priority targetting codeblock because it will prevent the flaw of accidentally looking over more suitable targets which are lower on the list. </font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">// [*Twiddle Thumbs*] IF ActionListEmpty() THEN RESPONSE #100 DisplayString(Myself,3678) END</pre>[/QUOTE]Unless you ensure that the last codeblock has no Continue() line, this will make sure that your .BS file will not hang. [ 01-21-2004, 05:56 AM: Message edited by: Dundee Slaytern ] |
All times are GMT -4. The time now is 10:26 AM. |
Powered by vBulletin® Version 3.8.3
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
©2024 Ironworks Gaming & ©2024 The Great Escape Studios TM - All Rights Reserved