Author Topic: [Solved] Scripting 'isFuseEnabled'  (Read 3330 times)

Offline The Martian

  • Commander
  • *****
  • Posts: 754
  • "It implores you to listen to its arguments..."
    • View Profile
[Solved] Scripting 'isFuseEnabled'
« on: February 23, 2022, 05:52:11 pm »
I see that BattleItem.isFuseEnabled in the 'newTurnItem' section of the verbose openxcom.log allows for checking if the fuse is already active on an item, which sounds pretty useful.


I'm not sure how to define the Args it requires, could someone please post an example of the phrasing?
Code: [Select]
Name: BattleItem.isFuseEnabled                Args: [ptr BattleItem] [var int]                        Desc: check if fuse is triggered (like throw or proxy unit)
I was thinking that newTurnItem cycled through all items during a new turn and ran any scripts off each item, so the code in new_TurnItem: is phrased with the current item in the sequence as the subject of what the script is reading/writing, but then what is the var int that isFuseEnabled needs? I was expecting it to return a value not take one so I'm most likely not understanding this correctly.

What I'm trying for is something like this, if the grenade's fuse is not active run the code: (I know this code is incorrect, but I'm hoping it will show what I mean to accomplish.)
Code: [Select]
  scripts:
    newTurnItem:
      - offset: 52
        code: |
          if Battle_Item.isFuseEnabled STR_EXAMPLE_GRENADE = false;
            <CODE>
          end;




Additional question:
Am I correct in that all BattleItem, BattleGame, etc found in the openxcom.log file are phrased as Battle_Item and Battle_Game with an underscore dividing them when used in a .rul file's code for scripting?
« Last Edit: February 12, 2023, 03:12:38 pm by Meridian »

Offline Filip H

  • Squaddie
  • *
  • Posts: 6
    • View Profile
Re: Scripting 'isFuseEnabled'
« Reply #1 on: February 23, 2022, 08:41:26 pm »
The var int that the isFuseEnabled requires is where its return value is written.
So to do what you're trying to accomplish you'd need to do something like this:
Code: [Select]
scripts:
   newTurnItem:       
       - offset: 1
         code: |
          var int x;
          item.isFuseEnabled x; #x gets the value 0 or 1 depending on if the fuse is lit
          if eq x 0;
            <CODE>
          end;
          return;

Regarding the additional question, no, the pointer names vary between script hooks. You can find the pointers available for each hook in the script data section of the API.
For example in the newTurnItem hook, the pointer for the BattleItem is just item
Code: [Select]
Name: battle_game                             ptre      BattleGame
Name: item                                    ptre      BattleItem
Name: null                                              null     
Name: rules                                   ptr       RuleMod 
Name: side                                              int     
Name: turn                                              int
The pointer for BattleGame seems to be consistently battle_game though.
« Last Edit: February 23, 2022, 09:00:02 pm by Filip H »

Offline Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3350
    • View Profile
Re: Scripting 'isFuseEnabled'
« Reply #2 on: February 23, 2022, 11:28:45 pm »
The var int that the isFuseEnabled requires is where its return value is written.
So to do what you're trying to accomplish you'd need to do something like this:
Code: [Select]
scripts:
   newTurnItem:       
       - offset: 1
         code: |
          var int x;
          item.isFuseEnabled x; #x gets the value 0 or 1 depending on if the fuse is lit
          if eq x 0;
            <CODE>
          end;
          return;

Regarding the additional question, no, the pointer names vary between script hooks. You can find the pointers available for each hook in the script data section of the API.
For example in the newTurnItem hook, the pointer for the BattleItem is just item
Code: [Select]
Name: battle_game                             ptre      BattleGame
Name: item                                    ptre      BattleItem
Name: null                                              null     
Name: rules                                   ptr       RuleMod 
Name: side                                              int     
Name: turn                                              int
The pointer for BattleGame seems to be consistently battle_game though.
I approve this message :>

@The Martian when you use my y-scripts you should more think as assembler than hi level langrage like C.

For naming, no, each script have its own naming (dump in logs too) as some times item is weapon and other times it could work as other thing.
But usually I try have consistent naming, for battle game it usually named  `battle_game`.

Offline Buscher

  • Colonel
  • ****
  • Posts: 168
    • View Profile
Re: Scripting 'isFuseEnabled'
« Reply #3 on: February 24, 2022, 09:41:28 pm »
TIS-100 and Shenzen I/O are nice games to get into the assembler mind set.

Offline The Martian

  • Commander
  • *****
  • Posts: 754
  • "It implores you to listen to its arguments..."
    • View Profile
Re: Scripting 'isFuseEnabled'
« Reply #4 on: February 25, 2022, 02:42:17 am »
Thank you for the explanation I think I'm getting a better grasp on it now, or rather I thought I was but now I'm getting an error message in the openxcom.log.
Code: [Select]
[24-02-2022_16-26-06] [ERROR] Error in parsing script 'newTurnItem' for 'Global Event Script': invalid variable definition after other operations: 'var int Fuse_State;'
What I've been trying to do is adapt Greenscarf's "Automatic Priming" script to include a few more options that can be quickly altered in a .rul file.

For convenience I've attached a small example mod to this post that reproduces the error:
TestGrenadeAutoPrime V0-1.zip

The lines that seems to be tripping the error are:
Code: [Select]
          var int Fuse_State;
          item.isFuseEnabled Fuse_State;

Line #1 which I thought should be fine creates a variable for storing an integer is created called Fuse_State.
Line #2 Fuse_State is assigned the value of item.isFuseEnabled.


The end goal for this script is:
. Allow automatic priming of grenades of varying fuse times as defined in .rul file.
. Toggle if the grenade can automatically prime while on the ground or only inside the carrying unit's inventory.
. Toggle if the grenade is only automatically primed on the first turn. (Useful if it can be disarmed.)


Here is the full script I'm working with:
Code: [Select]
extended:
  tags:
    RuleItem:
      AUTO_PRIMED_ENABLED: int
      AUTO_PRIMED_FUSE_TIME: int
      AUTO_PRIMED_GROUND_ARM: int
      AUTO_PRIMED_FIRST_TURN_ONLY: int
  scripts:
    newTurnItem:
      - offset: 52
        code: |
          var int Current_Turn;
          battle_game.getTurn Current_Turn;

          var int Fuse_State;
          item.isFuseEnabled Fuse_State;

          var ptr RuleInventory Items_Inventory;
          var int Inventory_Slot;

          item.getSlot Items_Inventory;
          Items_Inventory.getType Inventory_Slot;

          var int Auto_Prime;
          item.getTag Auto_Prime Tag.AUTO_PRIMED_ENABLED;

          var int Fuse_Time;
          item.getTag Fuse_Time Tag.AUTO_PRIMED_FUSE_TIME;

          var int Ground_Arm;
          item.getTag Ground_Arm Tag.AUTO_PRIMED_GROUND_ARM;

          var int First_Turn_Only;
          item.getTag First_Turn_Only Tag.AUTO_PRIMED_FIRST_TURN_ONLY;




          # If Grenade is not set for Auto Prime, Return.
          if neq Auto_Prime 1;
            return;
          end;

          # If Grenade is already armed, return
          if neq Fuse_State 0;
            return;
          end;

          # If Grenade is on ground and cannot be armed on ground, return
          if eq Ground_Arm 0;
            if eq Inventory_Slot INV_GROUND;
              return;
            end;
          end;

          # If Grenade can only be auto armed on first turn and it is after that, return
          if eq First_Turn_Only 1;
            if neq Current_Turn 1;
              return;
            end;
          end;

          # Set Grenade fuse to Fuse_Time
          item.setFuseTimer Fuse_Time;
          return;


It feels like I'm grasping at smoke, if 'var int Fuse_State;' is incorrect why isn't 'var int Current_Turn;' throwing an error as well?


TIS-100 and Shenzen I/O are nice games to get into the assembler mind set.

Both Shenzen I/O & TIS-100 are available for Linux!

I'll have to pick them up later, thank you for the recommendations.

Offline Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3350
    • View Profile
Re: Scripting 'isFuseEnabled'
« Reply #5 on: February 25, 2022, 11:38:42 am »
Thank you for the explanation I think I'm getting a better grasp on it now, or rather I thought I was but now I'm getting an error message in the openxcom.log.
Code: [Select]
[24-02-2022_16-26-06] [ERROR] Error in parsing script 'newTurnItem' for 'Global Event Script': invalid variable definition after other operations: 'var int Fuse_State;'
What I've been trying to do is adapt Greenscarf's "Automatic Priming" script to include a few more options that can be quickly altered in a .rul file.

For convenience I've attached a small example mod to this post that reproduces the error:
TestGrenadeAutoPrime V0-1.zip

The lines that seems to be tripping the error are:
Code: [Select]
          var int Fuse_State;
          item.isFuseEnabled Fuse_State;

Line #1 which I thought should be fine creates a variable for storing an integer is created called Fuse_State.
Line #2 Fuse_State is assigned the value of item.isFuseEnabled.


The end goal for this script is:
. Allow automatic priming of grenades of varying fuse times as defined in .rul file.
. Toggle if the grenade can automatically prime while on the ground or only inside the carrying unit's inventory.
. Toggle if the grenade is only automatically primed on the first turn. (Useful if it can be disarmed.)


Here is the full script I'm working with:
Code: [Select]
extended:
  tags:
    RuleItem:
      AUTO_PRIMED_ENABLED: int
      AUTO_PRIMED_FUSE_TIME: int
      AUTO_PRIMED_GROUND_ARM: int
      AUTO_PRIMED_FIRST_TURN_ONLY: int
  scripts:
    newTurnItem:
      - offset: 52
        code: |
          var int Current_Turn;
          battle_game.getTurn Current_Turn;

          var int Fuse_State;
          item.isFuseEnabled Fuse_State;

          var ptr RuleInventory Items_Inventory;
          var int Inventory_Slot;

          item.getSlot Items_Inventory;
          Items_Inventory.getType Inventory_Slot;

          var int Auto_Prime;
          item.getTag Auto_Prime Tag.AUTO_PRIMED_ENABLED;

          var int Fuse_Time;
          item.getTag Fuse_Time Tag.AUTO_PRIMED_FUSE_TIME;

          var int Ground_Arm;
          item.getTag Ground_Arm Tag.AUTO_PRIMED_GROUND_ARM;

          var int First_Turn_Only;
          item.getTag First_Turn_Only Tag.AUTO_PRIMED_FIRST_TURN_ONLY;




          # If Grenade is not set for Auto Prime, Return.
          if neq Auto_Prime 1;
            return;
          end;

          # If Grenade is already armed, return
          if neq Fuse_State 0;
            return;
          end;

          # If Grenade is on ground and cannot be armed on ground, return
          if eq Ground_Arm 0;
            if eq Inventory_Slot INV_GROUND;
              return;
            end;
          end;

          # If Grenade can only be auto armed on first turn and it is after that, return
          if eq First_Turn_Only 1;
            if neq Current_Turn 1;
              return;
            end;
          end;

          # Set Grenade fuse to Fuse_Time
          item.setFuseTimer Fuse_Time;
          return;


It feels like I'm grasping at smoke, if 'var int Fuse_State;' is incorrect why isn't 'var int Current_Turn;' throwing an error as well?


Both Shenzen I/O & TIS-100 are available for Linux!

I'll have to pick them up later, thank you for the recommendations.
what error? this is critical, each error mean something else and should be handled differently. y-script should say exactly what it do not like with this code.

Offline Filip H

  • Squaddie
  • *
  • Posts: 6
    • View Profile
Re: Scripting 'isFuseEnabled'
« Reply #6 on: February 25, 2022, 02:58:11 pm »
Code: [Select]
[25-02-2022_14-45-00] [ERROR] Error in parsing script 'newTurnItem' for 'Global Event Script': invalid variable definition after other operations: 'var int Fuse_State;'I believe this error is caused due to all variables being required to be declared before any operations (which is why var int Current_Turn; isn't throwing an error since it's before any operations).
I get no errors after editing the script to this:
Code: [Select]
extended:
  tags:
    RuleItem:
      AUTO_PRIMED_ENABLED: int
      AUTO_PRIMED_FUSE_TIME: int
      AUTO_PRIMED_GROUND_ARM: int
      AUTO_PRIMED_FIRST_TURN_ONLY: int
  scripts:
    newTurnItem:
      - offset: 52
        code: |
          var int Current_Turn;
          var int Fuse_State;
          var ptr RuleInventory Items_Inventory;
          var int Inventory_Slot;
          var int Auto_Prime;
          var int Fuse_Time;
          var int Ground_Arm;
          var int First_Turn_Only;
         
          battle_game.getTurn Current_Turn;

          item.isFuseEnabled Fuse_State;


          item.getSlot Items_Inventory;
          Items_Inventory.getType Inventory_Slot;

          item.getTag Auto_Prime Tag.AUTO_PRIMED_ENABLED;

          item.getTag Fuse_Time Tag.AUTO_PRIMED_FUSE_TIME;

          item.getTag Ground_Arm Tag.AUTO_PRIMED_GROUND_ARM;

          item.getTag First_Turn_Only Tag.AUTO_PRIMED_FIRST_TURN_ONLY;




          # If Grenade is not set for Auto Prime, Return.
          if neq Auto_Prime 1;
            return;
          end;

          # If Grenade is already armed, return
          if neq Fuse_State 0;
            return;
          end;

          # If Grenade is on ground and cannot ground arm, return
          if eq Ground_Arm 0;
            if eq Inventory_Slot INV_GROUND;
              return;
            end;
          end;

          # If Grenade can only be auto armed on first turn and it is after that, return
          if eq First_Turn_Only 1;
            if neq Current_Turn 1;
              return;
            end;
          end;

          # Set Grenade fuse to Fuse_Time
          item.setFuseTimer Fuse_Time;
          return;
« Last Edit: February 25, 2022, 03:00:25 pm by Filip H »

Offline Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3350
    • View Profile
Re: Scripting 'isFuseEnabled'
« Reply #7 on: February 25, 2022, 06:07:25 pm »
Code: [Select]
[25-02-2022_14-45-00] [ERROR] Error in parsing script 'newTurnItem' for 'Global Event Script': invalid variable definition after other operations: 'var int Fuse_State;'I believe this error is caused due to all variables being required to be declared before any operations (which is why var int Current_Turn; isn't throwing an error since it's before any operations).
I get no errors after editing the script to this:
Code: [Select]
extended:
  tags:
    RuleItem:
      AUTO_PRIMED_ENABLED: int
      AUTO_PRIMED_FUSE_TIME: int
      AUTO_PRIMED_GROUND_ARM: int
      AUTO_PRIMED_FIRST_TURN_ONLY: int
  scripts:
    newTurnItem:
      - offset: 52
        code: |
          var int Current_Turn;
          var int Fuse_State;
          var ptr RuleInventory Items_Inventory;
          var int Inventory_Slot;
          var int Auto_Prime;
          var int Fuse_Time;
          var int Ground_Arm;
          var int First_Turn_Only;
         
          battle_game.getTurn Current_Turn;

          item.isFuseEnabled Fuse_State;


          item.getSlot Items_Inventory;
          Items_Inventory.getType Inventory_Slot;

          item.getTag Auto_Prime Tag.AUTO_PRIMED_ENABLED;

          item.getTag Fuse_Time Tag.AUTO_PRIMED_FUSE_TIME;

          item.getTag Ground_Arm Tag.AUTO_PRIMED_GROUND_ARM;

          item.getTag First_Turn_Only Tag.AUTO_PRIMED_FIRST_TURN_ONLY;




          # If Grenade is not set for Auto Prime, Return.
          if neq Auto_Prime 1;
            return;
          end;

          # If Grenade is already armed, return
          if neq Fuse_State 0;
            return;
          end;

          # If Grenade is on ground and cannot ground arm, return
          if eq Ground_Arm 0;
            if eq Inventory_Slot INV_GROUND;
              return;
            end;
          end;

          # If Grenade can only be auto armed on first turn and it is after that, return
          if eq First_Turn_Only 1;
            if neq Current_Turn 1;
              return;
            end;
          end;

          # Set Grenade fuse to Fuse_Time
          item.setFuseTimer Fuse_Time;
          return;
This was homework for The Martian :p
but yes, you can't mix operations with variable declarations, all are required to be on beginning of block.
Reason was that older version had `goto` operation and it would allow to skip initialization of some variable.
But there is way araund it now, as `block; ... end;` can have its own variables.

Offline The Martian

  • Commander
  • *****
  • Posts: 754
  • "It implores you to listen to its arguments..."
    • View Profile
Re: Scripting 'isFuseEnabled'
« Reply #8 on: March 07, 2022, 12:52:58 pm »
That was driving me crazy.

Thank you both for the help, I really appreciate it.