1. SPS Accounts:
    Do you find yourself coming back time after time? Do you appreciate the ongoing hard work to keep this community focused and successful in its mission? Please consider supporting us by upgrading to an SPS Account. Besides the warm and fuzzy feeling that comes from supporting a good cause, you'll also get a significant number of ever-expanding perks and benefits on the site and the forums. Click here to find out more.
    Dismiss Notice
Dismiss Notice
You are currently viewing Boards o' Magick as a guest, but you can register an account here. Registration is fast, easy and free. Once registered you will have access to search the forums, create and respond to threads, PM other members, upload screenshots and access many other features unavailable to guests.

BoM cultivates a friendly and welcoming atmosphere. We have been aiming for quality over quantity with our forums from their inception, and believe that this distinction is truly tangible and valued by our members. We'd love to have you join us today!

(If you have any problems with the registration process or your account login, please contact us. If you've forgotten your username or password, click here.)

AI Script for Mage and Mage Thief

Discussion in 'Icewind Dale (Classic)' started by Tsumari, Jul 1, 2001.

  1. Tsumari Gems: 1/31
    Latest gem: Turquoise


    Joined:
    Jul 1, 2001
    Messages:
    7
    Likes Received:
    0
    I've spent a lot of time over the past few days working on my scripts to solve some issues I have with the built-in scripts.

    Namely, if you have a mage scripted with the game he/she will either blow her direct damage spells off the bat or not use them at all. My brother plays with his mage on a thief script to keep her from wasting magic.

    With that in mind, I've created a mage script that 1 - knows how to use direct damage spells, but only in "tough" situations, 2 - checks to charm nearby human enemies, 3 - checks for near-death trolls and kills them with fire magic, 4 - uses Hold Person, but only in "tough" situations, 5 - if under attack and health is low, check the type of attack and cast one of a variety of defensive spells to counter. Finally, if nothing especially interesting is going on, use a ranged weapon to shoot at mobs.

    "Tough" situations - a party member is at 50-60 percent health and enemies are nearby. The mage will typically cast an offensive spell against the enemy closest to the injured party member.

    Defensive spells - If the mage is injured (below 60 health) he/she will check to cast blur. If under attack by missile weapons she will try protection from normal missiles. Finally, the mage will cast minor globe of invulnerability.

    Layout of the script:

    1: Save myself - the first thing the script checks for is danger to the caster, and tries to respond. It will even try to teleport to the main character's position if you have the proper spell.

    2: Check to kill trolls - looks for weak trolls and hits them with fire magic.

    3: Save my allies - casts offensive and status magic against enemies who are wounding party members.

    4: General combat - use ranged or melee weapons as appropriate. This is the most-used part of the script.

    The entire script is based on reaction rather than action. I found that my characters were going overboard, so I wanted to put limits on when and why they would cast magic, while expanding the realm of magic they could automatically cast.

    Important - the Mage/Thief version is identical to the pure mage version, except for it includes a hiding routine at the beginning of the script. You must remove this routine for the pure mage script. Since all but 5 lines are the same I'm only posting it as one document.

    You will need the script compiler available from the sorcerers.net download page.

    Finally, there are some minor issues with the script - for example, it can cast blur twice when it really isn't needed. It is a minor issue (which I dont know how to fix). This is a non-cheating script, and should go fine with any adventuring party.

    Note: The web board does not support tab, so my script will appear deformed. I have no idea if it will work when copied and pasted directly from this message. To work around that problem, click the edit icon on my message and copy it directly from the text box, which supports the tabs.

    SCRIPT:

    IF
    Delay(15)
    THEN
    RESPONSE #100
    Hide()
    END

    IF
    AttackedBy([ENEMY],DEFAULT)
    HPPercentLT(Myself,30)
    HaveSpell(WIZARD_HASTE)
    THEN
    RESPONSE #100
    Spell(Myself,WIZARD_HASTE)
    END

    IF
    AttackedBy([ENEMY],DEFAULT)
    HPPercentLT(Myself,30)
    HaveSpell(WIZARD_DIMENSION_DOOR)
    THEN
    RESPONSE #100
    Spell(Player1,WIZARD_DIMENSION_DOOR)
    END

    IF
    AttackedBy([ENEMY],DEFAULT)
    HPPercentLT(Myself,60)
    HaveSpell(WIZARD_BLUR)
    THEN
    RESPONSE #100
    Spell(Myself,WIZARD_BLUR)
    END

    IF
    AttackedBy([ENEMY],DEFAULT)
    HPPercentLT(Myself,40)
    HaveSpell(WIZARD_MINOR_GLOBE_OF_INVULNERABILITY)
    !HaveSpell(WIZARD_BLUR)
    THEN
    RESPONSE #100
    Spell(Myself,WIZARD_MINOR_GLOBE_OF_INVULNERABILITY)
    END

    IF
    HPPercentLT(Myself,60)
    AttackedBy([ENEMY],DEFAULT)
    Range(NearestEnemyOf(Myself),4)
    HaveSpell(WIZARD_VAMPIRIC_TOUCH)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(Myself),WIZARD_VAMPIRIC_TOUCH)
    END

    IF
    HPPercentLT(Myself,60)
    AttackedBy([ENEMY],DEFAULT)
    Range(NearestEnemyOf(Myself),4)
    HaveSpell(WIZARD_LICH_TOUCH)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(Myself),WIZARD_LICH_TOUCH)
    END

    IF
    HPPercentLT(Myself,60)
    AttackedBy([ENEMY],DEFAULT)
    Range(NearestEnemyOf(Myself),4)
    HaveSpell(WIZARD_LARLOCHS_MINOR_DRAIN)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(Myself),WIZARD_LARLOCHS_MINOR_DRAIN)
    END


    IF
    General(NearestEnemyOf(Myself),Humanoid)
    Havespell(WIZARD_CHARM_PERSON)
    HPGT(NearestEnemyOf(Myself),40)

    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(Myself),WIZARD_CHARM_PERSON)
    END

    IF
    Race(NearestEnemyOf(Myself),TROLL)
    HPLT(NearestEnemyOf(Myself),5)
    HaveSpell(WIZARD_BURNING_HANDS)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(Myself),WIZARD_BURNING_HANDS)
    END

    IF
    Race(NearestEnemyOf(Myself),TROLL)
    HPLT(NearestEnemyOf(Myself),10)
    HaveSpell(WIZARD_AGANNAZAR_SCORCHER)
    THEN
    RESPONSE #100
    MoveToObject(NearestEnemyOf(Myself))
    Spell(NearestEnemyOf(Myself),WIZARD_AGANNAZAR_SCORCHER)
    END

    IF
    Race(NearestEnemyOf(Myself),TROLL)
    HPLT(NearestEnemyOf(Myself),1)
    HaveSpell(WIZARD_FLAME_ARROW)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(Myself),WIZARD_FLAME_ARROW)
    END

    IF
    AttackedBy([ENEMY],RANGED)
    HPPercentLT(Myself,60)
    HaveSpell(WIZARD_PROTECTION_FROM_NORMAL_MISSILES)
    THEN
    RESPONSE #100
    Spell(Myself,WIZARD_PROTECTION_FROM_NORMAL_MISSILES)
    END

    IF
    HPPercentLT(MostDamagedOf(GroupOf(Myself)),60)
    General(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),Humanoid)
    HaveSpell(WIZARD_CHARM_PERSON)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),WIZARD_CHARM_PERSON)
    END

    IF
    HPPercentLT(MostDamagedOf(GroupOf(Myself)),60)
    !Race(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),NO_RACE)
    Exists(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))))
    HaveSpell(WIZARD_COLOR_SPRAY)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),WIZARD_COLOR_SPRAY)
    END

    IF
    HPPercentLT(MostDamagedOf(GroupOf(Myself)),60)
    !Race(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),NO_RACE)
    Exists(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))))
    HaveSpell(WIZARD_MAGIC_MISSILE)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),WIZARD_MAGIC_MISSILE)
    END

    IF
    HPPercentLT(MostDamagedOf(GroupOf(Myself)),60)
    Exists(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))))
    HaveSpell(WIZARD_BURNING_HANDS)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),WIZARD_BURNING_HANDS)
    END

    IF
    HPPercentLT(MostDamagedOf(GroupOf(Myself)),60)
    !Race(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),NO_RACE)
    Exists(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))))
    HaveSpell(WIZARD_COLOR_SPRAY)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),WIZARD_COLOR_SPRAY)
    END

    IF
    HPPercentLT(MostDamagedOf(GroupOf(Myself)),60)
    !Race(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),NO_RACE)
    Exists(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))))
    HaveSpell(WIZARD_CHROMATIC_ORB)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),WIZARD_CHROMATIC_ORB)
    END

    IF
    HPPercentLT(MostDamagedOf(GroupOf(Myself)),60)
    !Race(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),NO_RACE)
    Exists(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))))
    HaveSpell(WIZARD_SLEEP)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),WIZARD_SLEEP)
    END

    IF
    HPPercentLT(MostDamagedOf(GroupOf(Myself)),60)
    !Race(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),NO_RACE)
    Exists(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))))
    !Class(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),MAGE)
    HaveSpell(WIZARD_BLINDNESS)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),WIZARD_BLINDNESS)
    END

    IF
    HPPercentLT(MostDamagedOf(GroupOf(Myself)),60)
    !Race(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),NO_RACE)
    Exists(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))))
    HaveSpell(WIZARD_FLAME_ARROW)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),WIZARD_FLAME_ARROW)
    END

    IF
    HPPercentLT(MostDamagedOf(GroupOf(Myself)),60)
    !Race(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),NO_RACE)
    Exists(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))))
    HaveSpell(WIZARD_ICELANCE)
    THEN
    RESPONSE #100
    Spell(NearestEnemyOf(MostDamagedOf(GroupOf(Myself))),WIZARD_ICELANCE)
    END

    IF
    HPPercentLT(Myself,75)
    See(NearestEnemyOf(Myself))
    THEN
    RESPONSE #100
    Help()
    Continue()
    END

    IF
    See(NearestEnemyOf(Myself))
    !Range(NearestEnemyOf(Myself),4)
    THEN
    RESPONSE #100
    EquipRanged()
    AttackReevaluate(NearestEnemyOf(Myself),30)
    END

    IF
    See(NearestEnemyOf(Myself))
    Range(NearestEnemyOf(Myself),4)
    THEN
    RESPONSE #100
    EquipMostDamagingMelee()
    AttackReevaluate(NearestEnemyOf(Myself),30)
    END

    ---end of script

    Edit: I'm learning about the Statecheck command and its format. With it, I'll be able to make sure that the character does not waste spells such as blur. I also think I'll be able to check Inparty status to use LastAttackerOf instead of NearestEnemyOf to get more specific in retaliation. I'm working on it =)

    Tsumari
    (How's this for my second post?)

    [This message has been edited by Tsumari (edited July 01, 2001).]
     
  2. Taluntain

    Taluntain Resident Alpha and Omega Staff Member ★ SPS Account Holder Resourceful Adored Veteran Pillars of Eternity SP Immortalizer (for helping immortalize Sorcerer's Place in the game!) New Server Contributor [2012] (for helping Sorcerer's Place lease a new, more powerful server!) Torment: Tides of Numenera SP Immortalizer (for helping immortalize Sorcerer's Place in the game!) BoM XenForo Migration Contributor [2015] (for helping support the migration to new forum software!)

    Joined:
    Jun 11, 2000
    Messages:
    23,630
    Media:
    494
    Likes Received:
    558
    Gender:
    Male
    [​IMG] Then how about sending it to me in it's original form so I can put it on the site for download, eh? That goes for all the scripts and similar you come up with.
     
  3. Tsumari Gems: 1/31
    Latest gem: Turquoise


    Joined:
    Jul 1, 2001
    Messages:
    7
    Likes Received:
    0
    Give me a week or so before I start putting stuff on download pages. I'm still experimenting with a lot of commands - sometimes they work, sometimes they don't. I'm hoping that some more experienced scripters will see my mistakes and help me out. I've only been doing this for three days =)

    In any event, I've tried to use StateCheck to look for poisoned allies and heal them, but the trigger never seems to return true on the following code:

    IF
    StateCheck(Player1,STATE_POISONED)
    HaveSpell(CLERIC_NEUTRALIZE_POISON)
    THEN
    RESPONSE #100
    Spell(Player1,CLERIC_NEUTRALIZE_POISON)
    END

    Similar for Players 2-6.

    Here is more alternative anti-poison code that doesn't work:

    IF
    StateCheck([ALLY],STATE_POISONED)
    HaveSpell(CLERIC_NEUTRALIZE_POISON)
    THEN
    RESPONSE #100
    Spell([ALLY],CLERIC_NEUTRALIZE_POISON)
    END

    However, I used StateCheck on STATE_BLUR on my mage/thief script, and it triggers the correct response - the mage casts Blur if the effect is not already up and all other conditions are met.

    Here is code that works:

    IF
    AttackedBy([ENEMY],DEFAULT)
    HPPercentLT(Myself,60)
    !StateCheck(Myself,STATE_BLUR)
    HaveSpell(WIZARD_BLUR)
    THEN
    RESPONSE #100
    Spell(Myself,WIZARD_BLUR)
    END

    So does anyone know if StateCheck only works on the player's own stats? If so, that eliminates some potentially useful scripts I could have made (auto-silence enemy mages if they aren't silenced, auto-slow enemy warriors if they aren't already).

    I'm a little confused. I guess the only other possible problem is that I am incorrectly using the object types to identify who to check thus Myself works but Player1 does not, but the documentation I have says that Player1 returns an object type just like Myself does.

    The script I have already is pretty good, but what I want to develop is a script where I can walk my party into just about any reasonable situation, turn the script on, and let them handle it. It wont be able to beat Yxunomei on its own, but it'll be fun to get my people plowing through a few rooms of a dungeon on their own =)

    Update: I've been checking into the differences between those two situations. The poison I've been checking against for the cleric spell is a small poison from a rogue dagger, so I'm hoping that the problem is that the game just doesn't recognize that poison as something that needs to be cured.

    Tsumari

    [This message has been edited by Tsumari (edited July 01, 2001).]
     
  4. Mathetais Gems: 28/31
    Latest gem: Star Sapphire


    Joined:
    Apr 5, 2001
    Messages:
    2,767
    Likes Received:
    0
    [​IMG] Wow - you can make up your own scripts?

    Tal - PLEASE put a link on SP somewhere re: how to do this? I'm more interested in BG2:TOB, but I'll be playing IWD when I'm finished with that one.

    Personally, I would love a Thief script that had him/her find traps when walking and take a ranged or offensive stance when attacking.

    (I hate the thief scripts, and I hate having to select "Find Traps" after every action!)
     
  5. Tsumari Gems: 1/31
    Latest gem: Turquoise


    Joined:
    Jul 1, 2001
    Messages:
    7
    Likes Received:
    0
    Well, the games use the same script, so you could literally take my script and port it straight to TOB, it just wouldn't take account for the spells in TOB. I've been working on my scripts since I posted here, and I should have them on SP's download page soon. I just need to playtest and learn.

    I'll look into search for traps code for you. I've got some non-gaming stuff to finish in the next week, so we'll see how fast I can investigate it.

    Tsumari
     
  6. Mathetais Gems: 28/31
    Latest gem: Star Sapphire


    Joined:
    Apr 5, 2001
    Messages:
    2,767
    Likes Received:
    0
    "I've got some non-gaming stuff to finish in the next week"

    What exactly is "non-gaming stuff"????

    Have you accessed that hidden area of IWD & BG that occurs when you hit the "EXIT GAME" button.

    You have far more courage than I do!

    When you finish your adventures out there, come back where it is safe and hook me up with a script!

    (Thanks for your work on this. You'll save me tons of time)
     
  7. Tsumari Gems: 1/31
    Latest gem: Turquoise


    Joined:
    Jul 1, 2001
    Messages:
    7
    Likes Received:
    0
    I've worked on the scripts a little more and submitted them to go on the download page. Once they're up give me a yell and tell me what you think.

    Tsumari
     
Sorcerer's Place is a project run entirely by fans and for fans. Maintaining Sorcerer's Place and a stable environment for all our hosted sites requires a substantial amount of our time and funds on a regular basis, so please consider supporting us to keep the site up & running smoothly. Thank you!

Sorcerers.net is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to products on amazon.com, amazon.ca and amazon.co.uk. Amazon and the Amazon logo are trademarks of Amazon.com, Inc. or its affiliates.