Skip to content

Picky creatures

chimericchimeric Member Posts: 1,163
edited September 2016 in Feature Requests
This could go to troubleshooting, I think. Anyway, if you script a creature - like a creature you are about to make an invisible servant out of, for all sorts of menial tasks - if you script a servant, I say, to look around for Nearest, SecondNearest and so forth so it can, for example, cast a spell on them, he will totally ignore and snub Specifics values and Spell State values that you may have wanted to distinguish the target with. This goes for both custom and basic entries in those IDS files. For example, if you tell him to look for

Specifics(Nearest,NORMAL)

and so on for everyone up to TenthNearest, the servant will just turn his nose and not notice any of them. He will react to Race, Class, Alignment and Gender that you can set through opcode 72, Set IDS State, but not Specifics. This makes Specifics a lot less useful for doing what it's supposed to do, marking things. I'm less certain about Spell States, but I wasn't able to get the servant to notice those either. I don't know if switching someone's class through 72 is an actual game change or only a formal change, the same for gender-swapping and so on. I haven't tried. If this opcode only changes the IDS value, it can be used as a marker, but turning someone's class to ANKHEG is an awfully theatrical way to get noticed.

Comments

  • ArdanisArdanis Member Posts: 1,736
    Last time I checked, specifics detection was working fine:
    See(Nearest([0.0.0.0.SPECIFICS]))

    This makes Specifics a lot less useful for doing what it's supposed to do, marking things.

    It's not really meant to be used outside of AI and InMyGroup() trigger.
    You certainly can use it for other purpose, but that may cause AI to malfunction sometimes, especially in SoD.

    Regarding spell states (or any other way to mark the target, really, like local variable), it's more likely to be an error in your script somewhere.
    IF
      See(NearestEnemyOf())
      CheckSpellState(NearestEnemyOf(),CUSTOM_VALUE)
    THEN
      RESPONSE #100
    END
  • chimericchimeric Member Posts: 1,163
    edited September 2016
    Look, this bit of script doesn't work. I turn someone into a wild dog through an IDS change... It works, that I know. Just as a marker. Well, the invisible creature spawned right next to it can't find it with this script:

    IF True() THEN RESPONSE #100 Wait(2) Continue() END IF Class(Nearest,DOG_WILD) RandomNumLT(20,10) THEN RESPONSE #100 Wait(2) ReallyForceSpellRES("SPWI105",Nearest) // Color Spray DestroySelf() END IF Class(Nearest,DOG_WILD) RandomNumGT(20,9) THEN RESPONSE #100 DestroySelf() END
  • chimericchimeric Member Posts: 1,163
    Ardanis said:

    Last time I checked, specifics detection was working fine:
    See(Nearest([0.0.0.0.SPECIFICS]))

    By the way, I don't understand this bit of code. See() only takes an Object there, right? How do you put the Specifics in there, and what are all the zeros?

  • ArdanisArdanis Member Posts: 1,736
    edited September 2016
    Dynamic objects go like this [EA.GENERAL.RACE.CLASS.SPECIFIC.GENDER.ALIGN], where you put real values in respectable fields, or 0 for "ANY". You don't need to specify further values (to the right) if you don't want to, but you do have to put in previous ones (to the left), even if they're all zeros.
    IF
    	Detect(Nearest([0.0.0.DOG_WILD])) // Detect() bypasses invis, unlike See()
    	RandomNumLT(20,10)
    THEN
    	RESPONSE #100
    		Wait(2)
    		ReallyForceSpellRES("SPWI105",LastSeenBy()) // Color Spray
    		DestroySelf()
    END
    Post edited by Ardanis on
  • chimericchimeric Member Posts: 1,163
    Thanks for the explanation. I don't have a problem with See(), it's not that. For some reason creatures just don't react normally to code like this, with one RandomNum range in the first response and another in the second. But I think I know a way to factor in Charisma without creatures...
  • chimericchimeric Member Posts: 1,163
    edited September 2016
    @Ardanis , I'll bother you again with this if I may. This is the script I have now for the creature:

    IF True() THEN RESPONSE #100 ReallyForceSpellRES("VISION_#",Myself) // Not important Wait(2) Continue() END IF Detect(Nearest) THEN RESPONSE #100 ReallyForceSpellRES("SPWI003",LastSeenBy()) // Magic Missile END

    It casts MM on itself. Plus, it's weird but I keep putting

    Detect(Nearest([0.0.0.0.0.0.NONE]))

    there in Near Infinity, save, and when I come back in the window, it has been converted to just

    Detect(Nearest)
  • ArdanisArdanis Member Posts: 1,736
    It casts MM on itself.

    Oh, I almost forgot about this :facepalm:
    There's a problem (or was it a feature, lol?) with Nearest() in that it includes myself in the range of available objects. So, if you use Nearest() without additional specifications, it will return the script owner themselves, not an actor that is nearest in the common human sense. SecondNearest() and so forth work fine.

    Regarding NI auto converting the script, in ALIGN.IDS the value of 0 is labeled as NONE, which results in [0.0.0.0.0.0.0] object and is basically the same as just Nearest(), so I think NI is simply trying to not display data it deems irrelevant.

    So, you gonna need a non-zero value to match in at least one of these ids EA.GENERAL.RACE.CLASS.SPECIFIC.GENDER.ALIGN (I actually misspelled two of them as SPECIFICS and ALIGNMENT in my earlier post). Not that I recommend setting object fields to custom IDS values anyway...

    Assuming we're still talking about charm, and you still set it to GOODBUTBLUE, then you should be able to match it with Nearest([GOODBUTBLUE]). If you expect other GOODBUTBLUEs to be present in the area, then additionally set a custom spell state (opcode 328) on the target and iterate through Nearest([GOODBUTBLUE])-TenthNearest([GOODBUTBLUE]) to check if any of them have the spell state set. Note that it may sometimes fail in SoD, due to large numbers of allied soldiers all flagged as GOODBUTBLUE.
  • chimericchimeric Member Posts: 1,163
    edited September 2016
    They don't react to allegiance, unfortunately. I have creatures in GOODBUTBLUE strutting in front of them and nothing happens. That's why I started putting in other markers, and alignment NONE seemed perfect. Although it was my second choice after class: DOG_WILD. :* No creatures that I know use NONE, but you can change someone's alignment to it - it becomes a blank on the character sheet. If NONE exists in the engine, it must be used somewhere. But I know now I can't use it as a condition for Apply Effects List. Unaligned is not an option... I guess a custom spell state it will have to be.
  • chimericchimeric Member Posts: 1,163
    edited September 2016
    By the way... thanks for all the advice, and is it possible to somehow detect the "author" of an AI change or a spell state? Who the spell was cast by? There was that SpellCastOnMe trigger, but it only works within one round, yes?

    And another thing: that ANYONE object. Just what is it useful for? Only for reactions to seeing or detecting someone so the creature fires off a spell or such? I mean, you can't put that object in regular triggers, right? ForceSpellOn(ANYONE... and so on. It would be nice. It would work as EVERYONE, if I could just issue a command or cast a spell on a whole bunch of creatures at once. I wouldn't have to go through SecondNearest and so on. But then, I already can with an Everyone-targeted effect, which I can further filter through a specific or something... That only works for effects, though. Not for script actions or ActionOverride in particular.

    If the creature doing the search for nearests takes itself to be the first Nearest, then there is no point to using that object at all, is there? I can just start with SecondNearest.
  • ArdanisArdanis Member Posts: 1,736
    edited October 2016
    is it possible to somehow detect the "author" of an AI change or a spell state? Who the spell was cast by? There was that SpellCastOnMe trigger, but it only works within one round, yes?

    No direct way, I'm afraid... LastSummonerOf(Myself) can be used to reliably detect one's summoner, but there can only be one such a thing, so if you want the caster and their target, you're still out of luck.

    And another thing: that ANYONE object. Just what is it useful for?

    For when you don't care about some particular ids value.
    See([ENEMY.0.HUMAN.FIGHTER.0.MALE.NEUTRAL_GOOD]) will match hostile neutral good human male fighters. But if you only want enemy fighters in general, then you need a wildcard for other parameters, which is what ANY/ANYONE/0 is, making the trigger look like See([ENEMY.0.0.FIGHTER]).

    I mean, you can't put that object in regular triggers, right? ForceSpellOn(ANYONE... and so on

    Not sure if I understood correctly... [0.0.0.FIGHTER], Player1, "custom_script_name", NearestEnemyOf(LastSummonerOf(Myself)) are all valid object types, so as long as the action/trigger allow an object as an argument, you can use any. The catch, of course, is that the existing types are not always enough, i.e. you can't include a variable check or a spell state this way, it'd have to be checked in a separate scripting line.

    I mean, you can't put that object in regular triggers, right? ForceSpellOn(ANYONE... and so on. It would be nice. It would work as EVERYONE, if I could just issue a command or cast a spell on a whole bunch of creatures at once. But then, I already can with an Everyone-targeted effect, which I can further filter through a specific or something... That only works for effects, though. Not for script actions or ActionOverride in particular.

    What you mean by everyone doesn't exist unfortunately, a scripting object in Infinity Engine is always a singular entity. So it's either iterating through SecondNearest() etc. or using an AoE projectile.

    If the creature doing the search for nearests takes itself to be the first Nearest, then there is no point to using that object at all, is there? I can just start with SecondNearest.

    Problem is that you'll miss an actual nearest this way, which may or may not be the one you really need. If you search for a particular ids value (e.g. [0.0.0.FIGHTER]), then you can set the script owner's class to e.g. MAGE. Since myself will not return true, it will search for the next nearest fighter, and do it correctly this time.
    It won't work as nice if you want anyone but myself, though, since there can be no negatives (IIRC only ea.ids has a NOTEVIL entry, that sounds remotely close). Even though you can check manually later whether someone's class is fighter or not, it's not possible to automatically See() any non-fighters.
    Another easy way is when you don't care about neutrals, then you can rely on NearestEnemyOf(), NearestEnemyOfType() and NearestAllyOf(), which automatically omit myself from a list of valid targets.
  • chimericchimeric Member Posts: 1,163
    I just saw this. I'll read it later.
Sign In or Register to comment.