Jump to content

Coding scripts in SSL: some lessons


Recommended Posts

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?

Edited by HerrSvensson
Link to comment

They're not equivalent.

 

Scenario: there are two PCs, one protected by Spell Trap and one not .What the script needs to do is find the nearest PC who is not protected by Spell Trap. The standard SSL-compiled code looks at the nearest PC to see if they're protected. If they aren't, cast at'em. If they are, look at the next PC.

 

Your code first just finds the nearest PC. If that PC isn't protected, cast at'em. If they are, give up.

Link to comment

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

Edited by HerrSvensson
Link to comment

For the two or three people who use SSL:

 

The version of SSL that will ship with v31 of SCS has two new features:

 

1) SSL now recognises a set of "Boolean variables", which can be defined when it's run using the -b tag: e.g.,

 

ssl.exe testscript.ssl -l ssl/library.slb -o stratagems_external/workspace/ssl_out -b WIZARD_MAGIC_MISSILE WIZARD_FLAME_ARROW 
sets Booleans WIZARD_MAGIC_MISSILE and WIZARD_FLAME_ARROW.

 

Booleans are referenced in SSL scripts via

 

SSLBoolean(firstBoolean|secondBoolean|etc)

 

which will blank the script unless at least one Boolean is set.

 

The point of this (over and above SSL's existing variables) is that Booleans are evaluated right before a given block is printed (whereas standard SSL variables are evaluated pretty much at the start). So in particular, SSL action arguments can be placed in an SSLBoolean command.

 

Example:

 

BEGIN_ACTION_DEFINITION
Name(Spell)
TRIGGER
SSLBoolean(scsargument1)
HaveSpell(scsargument1)
ACTION
RESPONSE #scsprob1
Spell(scstarget,scsargument1)
END

IF TRIGGER
Target(NearestEnemyOf(Myself))
THEN DO
Action(Spell,WIZARD_MAGIC_MISSILE)
Action(Spell,WIZARD_CHROMATIC_ORB)
compiles to

 

IF
      See(NearestEnemyOf(Myself))
      HaveSpell(WIZARD_MAGIC_MISSILE)
THEN
RESPONSE #100
Spell(NearestEnemyOf(Myself),WIZARD_MAGIC_MISSILE)
END
i.e the CHROMATIC_ORB block is skipped. Edited by DavidW
Link to comment

2) SSL library files now have two more options, alongside the existing TRIGGER and TARGET: TRIGGER_REPLACE and TARGET_REPLACE. These define triggers and targets (respectively) that destructively overwrite the existing trigger/target (the SSL default is to add to the existing one).

 

So:

 

TRIGGER=Imprisonment
!CheckSpellState(scstarget,STATE_ENRAGED)
TRIGGER=Imprisonment
!CheckSpellState(scstarget,IMMUNE_TO_EVERYTHING)
leaves the STATE_ENRAGED check in place, whereas

 

TRIGGER=Imprisonment
!CheckSpellState(scstarget,STATE_ENRAGED)
TRIGGER_REPLACE=Imprisonment
!CheckSpellState(scstarget,IMMUNE_TO_EVERYTHING)
removes the STATE_ENRAGED check.

 

Obviously this makes the order of libraries fairly crucial. (The point of the functionality is to make it easier to use custom library entries, e.g. for Spell Revisions compatibility.)

Link to comment

Fantastic.

 

On a sidenote, and unrelated to above - I couldn't get the custom library file to work in v30. I only tried it two times; but it didn't work. The lib file shipped with SCS always got processed instead of a custom one (I edited .ini file to set a custom lib).

Link to comment

Question: what does Combine() do? Here's an example from aTweaks/ssl/mage/chaos.ssl:

 

 

IF TRIGGER
  TargetBlock(PCsInOrder)
  TriggerBlock(Disabled|Enemy|MR50|Confusion|SIEnc)
THEN DO
    Combine()
    Action(Spell,WIZARD_CHAOS|100|50)
END

 

My initial guess is that it generates a series of False() targeting blocks with all the "scstarget"s followed up by a LastSeenBy(Myself) block but I could be wrong.

Link to comment

My initial guess is that it generates a series of False() targeting blocks with all the "scstarget"s followed up by a LastSeenBy(Myself) block but I could be wrong.

That is correct. Uncombined actions generate BAF like

IF
  Trigger()
THEN
  RESPONSE #such
    Action()
  RESPONSE #andsuch // Provided there is such a probability
    Continue()
END
A combined action considers all targets and Action()s on the highest-priority target available (or skips the whole thing, on the Continue() branch).
Link to comment

Thanks for your reply, Wisp. I've been looking into pregenerating .baf blocks but you do not seem to have ssl.exe in aTweaks; I am speculating that the scripts distributed in aTweaks are already "ready-made" complete .baf files and the .ssl blocks are there for reference. SCS pregenerates so much with different scripts that it's difficult to boil it down to a simple example of a .tph launching an .ssl compiler with the most basic features and libraries.

 

I've been trying to generate one .baf file from the single block of .ssl code above by running ssl.exe via a .bat but keep getting the error

Input file is testssl.ssl
Error near line 7: Spell is not a recognised action type at <directory>\ssl.exe line 634.

Can someone with experience in ssl look at this? Simply run the .bat after downloading the folder:

https://drive.google.com/open?id=0ByYA3DEzP-QMUWZnVFU3ZlI3WUU

Link to comment

Thanks for your reply, Wisp. I've been looking into pregenerating .baf blocks but you do not seem to have ssl.exe in aTweaks; I am speculating that the scripts distributed in aTweaks are already "ready-made" complete .baf files and the .ssl blocks are there for reference. SCS pregenerates so much with different scripts that it's difficult to boil it down to a simple example of a .tph launching an .ssl compiler with the most basic features and libraries.

Packaging perl scripts in stand-alone executables is a total hassle. I run SSL locally and ship the resulting scripts. It's less adaptive, but much easier.

 

I've been trying to generate one .baf file from the single block of .ssl code above by running ssl.exe via a .bat but keep getting the error

Input file is testssl.ssl
Error near line 7: Spell is not a recognised action type at <directory>\ssl.exe line 634.
Can someone with experience in ssl look at this? Simply run the .bat after downloading the folder:

https://drive.google.com/open?id=0ByYA3DEzP-QMUWZnVFU3ZlI3WUU

 

You can't put your action definitions in your library file. The library file only takes TARGETs and TRIGGERs. Put them in an SSL file called actions.ssl or something and INCLUDE that where needed (this also allows you to group your definitions logically, say one definition file for scripts in bucket A and another for the same in bucket B).
Link to comment

Thanks for the help, Wisp. That was the issue. I was now able to generate the desired .baf file.

 

Now I've got yet even more questions to ask you:

1. Why did you choose not to run ssl.exe? Is it a hassle to account for the different operating systems?

2. You have written a python script make_baf.pl which I couldn't find in any of the SCS folders. What does it do? Is it something specific for aTweaks rather than ssl?

Edited by Galactygon
Link to comment

1. Why did you choose not to run ssl.exe? Is it a hassle to account for the different operating systems?

I did not want the scripts I wrote to particularly stand out from the ones already written, so running the SSL->BAF process at install-time was largely unnecessary.

2. You have written a python script make_baf.pl which I couldn't find in any of the SCS folders. What does it do? Is it something specific for aTweaks rather than ssl?

Yes, it's specific to aTweaks. It's my build script. It runs SSL with input file A, options B to generate BAF C, for all the SSL-sourced BAFs aTweaks needs.
Link to comment

Also, SCS scripts are adaptive (they install differently according to which magic items are in the game, whether some other mods are installed, which options the player selects at install time, etc) - that requires me to compile at install time.

Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...