Author Topic: Scripting basics  (Read 1654 times)

Offline Kzer-Za

  • Colonel
  • ****
  • Posts: 140
    • View Profile
Re: Scripting basics
« Reply #15 on: August 18, 2019, 08:52:01 pm »
A pity. Well, I suppose, getting killed during the alien turn is not gonna be a common occurrence.

Can I ask another question? Is there any place where I can look up a list of possibilities of your languange? Inbuilt variables (like to_health), commands (or what is it called), like unit.setHealth, and so on, so I could not bug you on every little thing.

Offline Yankes

  • Moderator
  • Commander
  • ***
  • Posts: 2142
    • View Profile
Re: Scripting basics
« Reply #16 on: August 19, 2019, 01:44:23 am »
Verbose logging dump all script meta data in log.

Offline Kzer-Za

  • Colonel
  • ****
  • Posts: 140
    • View Profile
Re: Scripting basics
« Reply #17 on: August 19, 2019, 02:36:47 pm »
Thanks!

I've been looking through the possibilities and found two operations for BattleUnit: getFatalwounds and getFatalwoundsTotal. What is the difference between them? When I try to assign the first of them to a variable I get an error, and with the second, I don't:

Code: [Select]
    damageUnit:
      - offset: 10
        code: |
          var int wounds;
          var int woundsTotal;
          unit.getFatalwounds wounds;
          unit.getFatalwoundsTotal woundsTotal;

This is the error:

Code: [Select]
[19-08-2019_14-18-41] [ERROR] Can't match overload for operator 'BattleUnit.getFatalwounds' for:
[19-08-2019_14-18-41] [ERROR]   [ptre BattleUnit] [var int]
[19-08-2019_14-18-41] [ERROR] Excepted:
[19-08-2019_14-18-41] [ERROR]   [ptr BattleUnit] [var int] [int]
[19-08-2019_14-18-41] [ERROR] Error in parsing script 'damageUnit' for 'Global Event Script': invalid operation in line: 'unit.getFatalwounds wounds;'

As far as I understand, BattleUnit.getFatalwounds is expecting two arguments? What is the second one?

Also, when is selectMoveSoundUnit hook is triggered? When a unit is moved?

Thanks for your patience!

Offline Yankes

  • Moderator
  • Commander
  • ***
  • Posts: 2142
    • View Profile
Re: Scripting basics
« Reply #18 on: August 19, 2019, 08:25:29 pm »
Do you remember medkit screen? Each part have its own wounds. This function do this exactly, you can access each part wounds (you have predefined const variables that have body parts numbers).
`getFatalwoundsTotal` is simple sum of all parts, useful if you want only total value.


`selectMoveSoundUnit`: For each unit step this hook is triggered, it do more times than needed, IIRC original game play sound only on 0step, 1step, 3step and 7step.
Depending on move type/unit it could change.
And remember if you try play too many sound at once most of them will clip.

This function have lot of parameters for exposing add information used when deterring original unit sound. You can ignore most of them and play some arbitrary sound. or if you are fancy, you could create new step sound that can be affected by tile.

Offline Kzer-Za

  • Colonel
  • ****
  • Posts: 140
    • View Profile
Re: Scripting basics
« Reply #19 on: August 19, 2019, 09:45:36 pm »
Regarding `selectMoveSoundUnit`, actually I thought of using it to stop powersuits from spending energy when flying. Trigger it with this hook, then check if "BattleUnit.isFlying", then manipulate energy with getEnergy and setEnergy. You know, since the soldiers are not actually relying on their own body for flying, the work is done by the suit :)

Offline Yankes

  • Moderator
  • Commander
  • ***
  • Posts: 2142
    • View Profile
Re: Scripting basics
« Reply #20 on: August 19, 2019, 11:59:55 pm »
Usually scripts that calculate something can't change any thing else.
Overall I limit what scripts can do because I can reason what can be changed and can easy refactor code without worrying about breaking scrips.
And vice versa. I try make that scripts can't break game, usually game can handle all that scripts throw can at it.

Bottom line is `selectMoveSoundUnit` only can calculate sound and nothing else (`ptr` vs `ptre`).

Offline Kzer-Za

  • Colonel
  • ****
  • Posts: 140
    • View Profile
Re: Scripting basics
« Reply #21 on: August 20, 2019, 05:17:56 pm »
Okay, thanks for the explanation.

Offline Kzer-Za

  • Colonel
  • ****
  • Posts: 140
    • View Profile
Re: Scripting basics
« Reply #22 on: August 20, 2019, 06:04:08 pm »
Oh, I forgot to ask one more thing: I don't see a way to randomize anything inside a script. Am I missing something, or is this possibility absent for now?

Offline Yankes

  • Moderator
  • Commander
  • ***
  • Posts: 2142
    • View Profile
Re: Scripting basics
« Reply #23 on: August 20, 2019, 08:51:03 pm »
As game use static random state you can use it only in script that can change game state, its available in `BattleGame` object. Name of function is `randomChance` and `randomRange`.

Offline Kzer-Za

  • Colonel
  • ****
  • Posts: 140
    • View Profile
Re: Scripting basics
« Reply #24 on: August 20, 2019, 10:09:42 pm »
Could you please give an example of how it's used? I tried this:

Code: [Select]
    scripts:
      createItem: |
        var int chance1;
        var int chance2;
        BattleGame.randomChance chance1;
        debug_log 1 chance1;
        BattleGame.randomRange chance2 0 3;
        debug_log 2 chance2;
        return;

I thought that BattleGame.randomChance assigns a random number (0-99 or something like that) to a variable, and BattleGame.randomRange assigns to a variable a number in range (between 0 and 3 in the case above). But these return errors.

Offline Yankes

  • Moderator
  • Commander
  • ***
  • Posts: 2142
    • View Profile
Re: Scripting basics
« Reply #25 on: August 20, 2019, 10:17:48 pm »
I probably do not say this accurate, `BattleGame` is type of object. Name of variable (in case of `createItem`) is `battle_game`.

Your script should look like:

Code: [Select]
battle_game.randomChance chance1;

btw one tidbit, this line is equal to:

Code: [Select]
BattleGame.randomChance battle_game chance1;

this is short hand that allow you to skip repeating name of type because we already know it from `battle_game`.
Error message should show you what exactly `BattleGame.randomChance` need as agreements.

Offline Kzer-Za

  • Colonel
  • ****
  • Posts: 140
    • View Profile
Re: Scripting basics
« Reply #26 on: August 20, 2019, 11:20:13 pm »
Aha, thanks!

Offline Kzer-Za

  • Colonel
  • ****
  • Posts: 140
    • View Profile
Re: Scripting basics
« Reply #27 on: August 22, 2019, 05:18:21 pm »
Could you please describe the hook psiDefenceBonusStats? It seems to me that if I try to change the "bonus" it returns, it takes effect only after the success of the attack is calculated. For example, for this experiment I tried this:

Code: [Select]
    psiDefenceBonusStats:
      - offset: 10
        code: |
          set bonus 1;
          debug_log 1 bonus;
          return bonus;

I psi-attack a unit two times by a soldier with a rather low psi-attack rating. In the log for both attacks I see "1 1" written. But the first attack always fails, even if it is Panic. The second always succeeds, even if it is Mind Control. So it seems that the bonus affects only the subsequent attacks, but not the current one. Am I right?

Also if I just output the bonus like this:

Code: [Select]
    psiDefenceBonusStats:
      - offset: 10
        code: |
          debug_log 1 bonus;
          return bonus;

it is equal to the "pure" Defense Strength of the attacked unit, without the Difficulty modifier (I mean the formula: Defense Strength (DS) = Psi Strength + (Psi Skill / 5 ) + Difficulty (from here https://www.ufopaedia.org/index.php/Psionics)). Does it mean the Difficulty is hard-coded and can't be affected?

Also, am I right that I cannot from this script access the attack strength of the incoming attack and change it? Or take into account some additional characteristics of the attacker?

Offline Yankes

  • Moderator
  • Commander
  • ***
  • Posts: 2142
    • View Profile
Re: Scripting basics
« Reply #28 on: August 22, 2019, 10:54:54 pm »
First of all script with ending `BonusStats` are stats bonuses, This is used to calculate some stats of item or armor.
Armor have property named `psiDefence` that is used in psi attack calculations:
https://github.com/MeridianOXC/OpenXcom/blob/oxce-plus/src/Battlescape/TileEngine.cpp#L3823

You compare psi attacker value (e.g. item `accuracyMindControl` + `accuracyMultiplier`)  to pis defense strength (armor `30` + `psiDefence`) and some other factors.
If this is greater than 0 then attack success.

One drawback of this script types that they only have access to "owning" unit and nothing else. Because this is expansion of old implementation of bonus stats mechanic. And it do not have access to anything other than unit, and this script group inherited this limitation.

Proper psi attack scripts (calculation + custom effects) are planed in some future.

Offline Kzer-Za

  • Colonel
  • ****
  • Posts: 140
    • View Profile
Re: Scripting basics
« Reply #29 on: August 23, 2019, 11:15:51 pm »
I will be waiting eagerly :) In the meantime, I suppose, there is no way to add some damage to psi attacks?