OpenXcom Forum

Modding => OXCE Support => OpenXcom Extended => OXCE Support Y-scripts => Topic started by: Kozinsky on April 29, 2020, 04:40:55 pm

Title: [Example] Handcuffs script
Post by: Kozinsky on April 29, 2020, 04:40:55 pm
This script makes it possible to fully use the handcuffs - each prisoner becomes stunned forever and does not die from overstun. The idea of ​​handcuffs is taken from the X-Piratez mod: this is a medikit with one charge of the stimulator, which can only be used on stunned bodies. After use, the handcuffs disappear from the player’s inventory.
Code: [Select]
items:
  - type: STR_HANDCUFFS
    medikitTargetImmune: true
    medikitTargetMatrix: 21
    stimulant: 1
    stunRecovery: 0 #no matter what value is here - script overrides it
    isConsumable: true
    costUse:
      time: 75
      energy: 10
    tags:
      HANDCUFF_STRENGTH: 1

extended:
  tags:
    RuleItem:
      HANDCUFF_STRENGTH: int
    BattleItem:
      ITEM_HANDCUFF_STRENGTH: int
    BattleUnit:
      IS_HANDCUFFED: int
  scripts:
    createItem:
      - offset: 1
        code: |
          var ptr RuleItem itemRuleset;
          var int strength;
         
          item.getRuleItem itemRuleset;
          itemRuleset.getTag strength Tag.HANDCUFF_STRENGTH;
         
          if gt strength 0;
            item.setTag Tag.ITEM_HANDCUFF_STRENGTH strength;
            debug_log "item.setTag.ITEM_HANDCUFF_STRENGTH: " strength;
          end;
          return;         
    healUnit:
      - offset: 1
        code: |
          var int strength 0;
          var int NewStun;
         
          item.getTag strength Tag.ITEM_HANDCUFF_STRENGTH;
          debug_log "item.getTag.ITEM_HANDCUFF_STRENGTH: " strength;
          if gt strength 0;
            target.setTag Tag.IS_HANDCUFFED 1;
            debug_log "target.setTag.IS_HANDCUFFED: " 1;
           
            target.getStunMax NewStun;
            target.setStun NewStun;
            debug_log "target.setStun: " NewStun;
          end;
         
          return;
    newTurnUnit:
      - offset: 2
        code: |
          var int IsHandcuff;
          var int NewStun;
         
          unit.getTag IsHandcuff Tag.IS_HANDCUFFED;
          debug_log "unit.getTag.IS_HANDCUFFED: " IsHandcuff;
         
          if gt IsHandcuff 0;
            unit.getStunMax NewStun;
            unit.setStun NewStun;
            debug_log "unit.setStun: " NewStun;
          end;
          return;
Sorry for my bad English.
Title: Re: [Script] Handcuffs
Post by: Thermite on April 30, 2020, 12:45:08 am
This script makes it possible to fully use the handcuffs - each prisoner becomes stunned forever and does not die from overstun. The idea of ​​handcuffs is taken from the X-Piratez mod: this is a medikit with one charge of the stimulator, which can only be used on stunned bodies. After use, the handcuffs disappear from the player’s inventory.
Code: [Select]
items:
  - type: STR_HANDCUFFS
    medikitTargetImmune: true
    medikitTargetMatrix: 21
    stimulant: 1
    stunRecovery: 0 #no matter what value is here - script overrides it
    isConsumable: true
    costUse:
      time: 75
      energy: 10
    tags:
      HANDCUFF_STRENGTH: 1

extended:
  tags:
    RuleItem:
      HANDCUFF_STRENGTH: int
    BattleItem:
      ITEM_HANDCUFF_STRENGTH: int
    BattleUnit:
      IS_HANDCUFFED: int
  scripts:
    createItem:
      - offset: 1
        code: |
          var ptr RuleItem itemRuleset;
          var int strength;
         
          item.getRuleItem itemRuleset;
          itemRuleset.getTag strength Tag.HANDCUFF_STRENGTH;
         
          if gt strength 0;
            item.setTag Tag.ITEM_HANDCUFF_STRENGTH strength;
            debug_log "item.setTag.ITEM_HANDCUFF_STRENGTH: " strength;
          end;
          return;         
    healUnit:
      - offset: 1
        code: |
          var int strength 0;
          var int NewStun;
         
          item.getTag strength Tag.ITEM_HANDCUFF_STRENGTH;
          debug_log "item.getTag.ITEM_HANDCUFF_STRENGTH: " strength;
          if gt strength 0;
            target.setTag Tag.IS_HANDCUFFED 1;
            debug_log "target.setTag.IS_HANDCUFFED: " 1;
           
            target.getStunMax NewStun;
            target.setStun NewStun;
            debug_log "target.setStun: " NewStun;
          end;
         
          return;
    newTurnUnit:
      - offset: 2
        code: |
          var int IsHandcuff;
          var int NewStun;
         
          unit.getTag IsHandcuff Tag.IS_HANDCUFFED;
          debug_log "unit.getTag.IS_HANDCUFFED: " IsHandcuff;
         
          if gt IsHandcuff 0;
            unit.getStunMax NewStun;
            unit.setStun NewStun;
            debug_log "unit.setStun: " NewStun;
          end;
          return;
Sorry for my bad English.

OwO
Solarius, I think this would be a nice addition to XCF...
Title: Re: [Script] Handcuffs
Post by: vadracas on April 30, 2020, 12:57:04 am
OwO
Solarius, I think this would be a nice addition to XCF...

Lol, you really need to check out the discord.
Title: Re: [Script] Handcuffs
Post by: Solarius Scorch on April 30, 2020, 08:07:58 pm
Yep, I am quite excited about this development. ;)
Title: Re: [Script] Handcuffs
Post by: Thermite on May 01, 2020, 06:51:21 am
Lol, you really need to check out the discord.

I am a forum kiddy, ok.
>_<
Title: Re: [Script] Handcuffs
Post by: Kozinsky on May 01, 2020, 06:20:07 pm
So, here is an improved version of the script:
Code: [Select]
items:
  - type: STR_HANDCUFFS
    battleType: 6
    invWidth: 1
    invHeight: 2
    medikitType: 2 #stimulant only
    medikitTargetSelf: false #not for user
    medikitTargetImmune: true #can use also on an bleed units
    medikitTargetMatrix: 21 #only for all stunned bodies
    medikitActionName: STR_HANDCUFFS_ACTION
    stimulant: 1
    stunRecovery: 0 #no matter what value is here - script overrides it
    isConsumable: true
    costUse:
      time: 75
      energy: 10
    twoHanded: true
    blockBothHands: true
    listOrder: 46290
    tags:
      HANDCUFF_STRENGTH: 40

armors:
  - type: CIVM_ARMOR
    tags:
      HANDCUFF_PROTECTION: 10
  - type: CIVF_ARMOR
    tags:
      HANDCUFF_PROTECTION: 5

extended:
  tags:
    RuleItem:
      HANDCUFF_STRENGTH: int #the handcuff strength in ruleset for items
    RuleArmor:
      HANDCUFF_PROTECTION: int #the handcuff protection in ruleset for units
    BattleItem:
      ITEM_HANDCUFF_STRENGTH: int #the handcuff strength for every copy of item in battlescape
    BattleUnit:
      UNIT_HANDCUFF_PROTECTION: int #the handcuff protection for every copy of unit in battlescape
      IS_HANDCUFFED: int #is this unit under handcuffs?
      VIRTUAL_STUN_LEVEL: int #real stunlevel for every copy of unit on battlescape
  scripts:
    createItem:
      - offset: 1
        code: |
          var ptr RuleItem ItemRuleset;
          var int HandcuffStrength 0;
         
          item.getRuleItem ItemRuleset;
          ItemRuleset.getTag HandcuffStrength Tag.HANDCUFF_STRENGTH;
         
          if gt HandcuffStrength 0;
            item.setTag Tag.ITEM_HANDCUFF_STRENGTH HandcuffStrength;
            debug_log "createItem: STR_HANDCUFF with tag ITEM_HANDCUFF_STRENGTH: " HandcuffStrength;
          end;
          return;         
    createUnit:
      - offset: 1
        code: |
          var ptr RuleArmor UnitRuleset;
          var int HandcuffProtection 0;
          var int UnitID 0;
         
          unit.getId UnitID;
          unit.getRuleArmor UnitRuleset;
          UnitRuleset.getTag HandcuffProtection Tag.HANDCUFF_PROTECTION;
         
          if gt HandcuffProtection 0;
            unit.setTag Tag.UNIT_HANDCUFF_PROTECTION HandcuffProtection;
            debug_log "createUnit: ID " UnitID " with tag UNIT_HANDCUFF_PROTECTION: " HandcuffProtection;
          end;
          return;
    healUnit:
      - offset: 1
        code: |
          var int HandcuffStrength 0;
          var int HandcuffProtection 0;
          var int CurrStun;
          var int NewStun;
          var int UnitID 0;
         
          target.getId UnitID;
         
          item.getTag HandcuffStrength Tag.ITEM_HANDCUFF_STRENGTH;
          target.getTag HandcuffProtection Tag.UNIT_HANDCUFF_PROTECTION;
          debug_log "healUnit: used item with ITEM_HANDCUFF_STRENGTH: " HandcuffStrength " on target " UnitID " with UNIT_HANDCUFF_PROTECTION: " HandcuffProtection;
          if and gt HandcuffStrength 0 gt HandcuffStrength HandcuffProtection;
            target.setTag Tag.IS_HANDCUFFED 1;
            debug_log "healUnit: if item with ITEM_HANDCUFF_STRENGTH (" HandcuffStrength ") > 0 and item with ITEM_HANDCUFF_STRENGTH (" HandcuffStrength ") > target " UnitID " with UNIT_HANDCUFF_PROTECTION (" HandcuffProtection ") then: set to target " UnitID " tag IS_HANDCUFFED: " 1;
           
            target.getStunMax NewStun;
            target.getStun CurrStun;
            target.setTag Tag.VIRTUAL_STUN_LEVEL CurrStun;
            target.setStun NewStun;
            debug_log "healUnit: set to target " UnitID " VIRTUAL_STUN_LEVEL: " CurrStun " and real stun level: " NewStun;
          end;
         
          return;
    newTurnUnit:
      - offset: 2
        code: |
          var int IsHandcuff;
          var int NewStun;
          var int CurrStrength 0;
          var int CurrStun 0;
          var int PrevStun 0;
          var int StrengthLevel 0;
          var int RandomValue 0;
          var int UnitID 0;
          unit.getId UnitID;
          debug_log "---------- Turn " turn ", unit " UnitID ":";
         
          unit.getTag IsHandcuff Tag.IS_HANDCUFFED;
                   
          if gt IsHandcuff 0; 
            unit.Stats.getStrength CurrStrength;
            debug_log "newTurnUnit: for unit " UnitID " get strength: " CurrStrength;
            battle_game.randomRange RandomValue 1 100;
            debug_log "newTurnUnit: generate RandomValue (1..100): " RandomValue;           
            if and ge CurrStrength 0 le CurrStrength 39;
              set StrengthLevel 1;
            else and ge CurrStrength 40 le CurrStrength 49;
              set StrengthLevel 5;
            else and ge CurrStrength 50 le CurrStrength 59;
              set StrengthLevel 10;
            else and ge CurrStrength 60 le CurrStrength 69;
              set StrengthLevel 20;
            else and ge CurrStrength 70 le CurrStrength 79;
              set StrengthLevel 30;
            else and ge CurrStrength 80 le CurrStrength 89;
              set StrengthLevel 40;
            else and ge CurrStrength 90 le CurrStrength 99;
              set StrengthLevel 50;
            else and ge CurrStrength 100 le CurrStrength 109;
              set StrengthLevel 60;
            else and ge CurrStrength 110 le CurrStrength 119;
              set StrengthLevel 70;
            else and ge CurrStrength 120 le CurrStrength 129;
              set StrengthLevel 80;
            else and ge CurrStrength 130 le CurrStrength 139;
              set StrengthLevel 90;
            else ge CurrStrength 140;
              set StrengthLevel 100;
            end;
            debug_log "newTurnUnit: unit " UnitID " got StrengthLevel: " StrengthLevel;
           
            unit.getTag PrevStun Tag.VIRTUAL_STUN_LEVEL;
            if le RandomValue StrengthLevel;
              if lt PrevStun 0;
                clear PrevStun;
              end;
              unit.setStun PrevStun;
              unit.setTag Tag.IS_HANDCUFFED 0;
              unit.setTag Tag.VIRTUAL_STUN_LEVEL 0;
              debug_log "newTurnUnit: if RandomValue (" RandomValue ") <= unit " UnitID " StrengthLevel (" StrengthLevel ") then set real stun: " PrevStun " and remove tag IS_HANDCUFFED";
            else gt RandomValue StrengthLevel;
              unit.getStun CurrStun;
              unit.getStunMax NewStun;
              sub CurrStun NewStun;
              add PrevStun CurrStun;
              unit.setTag Tag.VIRTUAL_STUN_LEVEL PrevStun;
              unit.setStun NewStun;
              debug_log "newTurnUnit: if RandomValue (" RandomValue ") > unit " UnitID " StrengthLevel (" StrengthLevel ") then set VIRTUAL_STUN_LEVEL: " PrevStun " and real stun: " NewStun;
            end;           
          end;
          return;

Each type of handcuffs must have a HANDCUFF_STRENGTH parameter in the "tags" section. By default, it is zero, which means the item is not handcuffs.
For each type of armor, you can specify the HANDCUFF_PROTECTION parameter in the "tags" section. By default, it is equal to zero, which means that the creature can be handcuffed of any handcuffs strength.
When trying to put on handcuffs, the condition is checked: if HANDCUFF_STRENGTH is greater than HANDCUFF_PROTECTION, then the handcuffs will be put on, otherwise not.
The unit, that is handcuffed, is assigned the parameter IS_HANDCUFFED: 1.
Each turn, each unit, in which the IS_HANDCUFFED parameter is 1, is checked for the possibility to free, based on his strength:
if strength in 0..39 then unit has 1% chance to be free,
if 40..49 - 5%,
if 50..59 - 10%,
if 60..69 - 20%,
if 70..79 - 30%,
if 80..89 - 40%,
if 90..99 - 50%,
if 100..109 - 60%,
if 110..119 - 70%,
if 120..129 - 80%,
if 130..139 - 90%,
if 140..infinity - 100%.
Each turn checks how much the unit’s stunning level has changed and this change is recorded to the VIRTUAL_STUN_LEVEL variable in the unit's "tags" section.
If the unit was able to free, its stun level from the VIRTUAL_STUN_LEVEL variable is returned to his stunLevel" and the script finishes its work with this unit.

For understandable how script works, I provided almost every action with a message output to the "openxcom.log" file, because for the player there are no visible changes in the game.
Title: Re: [Script] Handcuffs
Post by: Thermite on May 01, 2020, 08:15:33 pm
So, here is an improved version of the script:
Code: [Select]
items:
  - type: STR_HANDCUFFS
    battleType: 6
    invWidth: 1
    invHeight: 2
    medikitType: 2 #stimulant only
    medikitTargetSelf: false #not for user
    medikitTargetImmune: true #can use also on an bleed units
    medikitTargetMatrix: 21 #only for all stunned bodies
    medikitActionName: STR_HANDCUFFS_ACTION
    stimulant: 1
    stunRecovery: 0 #no matter what value is here - script overrides it
    isConsumable: true
    costUse:
      time: 75
      energy: 10
    twoHanded: true
    blockBothHands: true
    listOrder: 46290
    tags:
      HANDCUFF_STRENGTH: 40

armors:
  - type: CIVM_ARMOR
    tags:
      HANDCUFF_PROTECTION: 10
  - type: CIVF_ARMOR
    tags:
      HANDCUFF_PROTECTION: 5

extended:
  tags:
    RuleItem:
      HANDCUFF_STRENGTH: int #the handcuff strength in ruleset for items
    RuleArmor:
      HANDCUFF_PROTECTION: int #the handcuff protection in ruleset for units
    BattleItem:
      ITEM_HANDCUFF_STRENGTH: int #the handcuff strength for every copy of item in battlescape
    BattleUnit:
      UNIT_HANDCUFF_PROTECTION: int #the handcuff protection for every copy of unit in battlescape
      IS_HANDCUFFED: int #is this unit under handcuffs?
      VIRTUAL_STUN_LEVEL: int #real stunlevel for every copy of unit on battlescape
  scripts:
    createItem:
      - offset: 1
        code: |
          var ptr RuleItem ItemRuleset;
          var int HandcuffStrength 0;
         
          item.getRuleItem ItemRuleset;
          ItemRuleset.getTag HandcuffStrength Tag.HANDCUFF_STRENGTH;
         
          if gt HandcuffStrength 0;
            item.setTag Tag.ITEM_HANDCUFF_STRENGTH HandcuffStrength;
            debug_log "createItem: STR_HANDCUFF with tag ITEM_HANDCUFF_STRENGTH: " HandcuffStrength;
          end;
          return;         
    createUnit:
      - offset: 1
        code: |
          var ptr RuleArmor UnitRuleset;
          var int HandcuffProtection 0;
          var int UnitID 0;
         
          unit.getId UnitID;
          unit.getRuleArmor UnitRuleset;
          UnitRuleset.getTag HandcuffProtection Tag.HANDCUFF_PROTECTION;
         
          if gt HandcuffProtection 0;
            unit.setTag Tag.UNIT_HANDCUFF_PROTECTION HandcuffProtection;
            debug_log "createUnit: ID " UnitID " with tag UNIT_HANDCUFF_PROTECTION: " HandcuffProtection;
          end;
          return;
    healUnit:
      - offset: 1
        code: |
          var int HandcuffStrength 0;
          var int HandcuffProtection 0;
          var int CurrStun;
          var int NewStun;
          var int UnitID 0;
         
          target.getId UnitID;
         
          item.getTag HandcuffStrength Tag.ITEM_HANDCUFF_STRENGTH;
          target.getTag HandcuffProtection Tag.UNIT_HANDCUFF_PROTECTION;
          debug_log "healUnit: used item with ITEM_HANDCUFF_STRENGTH: " HandcuffStrength " on target " UnitID " with UNIT_HANDCUFF_PROTECTION: " HandcuffProtection;
          if and gt HandcuffStrength 0 gt HandcuffStrength HandcuffProtection;
            target.setTag Tag.IS_HANDCUFFED 1;
            debug_log "healUnit: if item with ITEM_HANDCUFF_STRENGTH (" HandcuffStrength ") > 0 and item with ITEM_HANDCUFF_STRENGTH (" HandcuffStrength ") > target " UnitID " with UNIT_HANDCUFF_PROTECTION (" HandcuffProtection ") then: set to target " UnitID " tag IS_HANDCUFFED: " 1;
           
            target.getStunMax NewStun;
            target.getStun CurrStun;
            target.setTag Tag.VIRTUAL_STUN_LEVEL CurrStun;
            target.setStun NewStun;
            debug_log "healUnit: set to target " UnitID " VIRTUAL_STUN_LEVEL: " CurrStun " and real stun level: " NewStun;
          end;
         
          return;
    newTurnUnit:
      - offset: 2
        code: |
          var int IsHandcuff;
          var int NewStun;
          var int CurrStrength 0;
          var int CurrStun 0;
          var int PrevStun 0;
          var int StrengthLevel 0;
          var int RandomValue 0;
          var int UnitID 0;
          unit.getId UnitID;
          debug_log "---------- Turn " turn ", unit " UnitID ":";
         
          unit.getTag IsHandcuff Tag.IS_HANDCUFFED;
                   
          if gt IsHandcuff 0; 
            unit.Stats.getStrength CurrStrength;
            debug_log "newTurnUnit: for unit " UnitID " get strength: " CurrStrength;
            battle_game.randomRange RandomValue 1 100;
            debug_log "newTurnUnit: generate RandomValue (1..100): " RandomValue;           
            if and ge CurrStrength 0 le CurrStrength 39;
              set StrengthLevel 1;
            else and ge CurrStrength 40 le CurrStrength 49;
              set StrengthLevel 5;
            else and ge CurrStrength 50 le CurrStrength 59;
              set StrengthLevel 10;
            else and ge CurrStrength 60 le CurrStrength 69;
              set StrengthLevel 20;
            else and ge CurrStrength 70 le CurrStrength 79;
              set StrengthLevel 30;
            else and ge CurrStrength 80 le CurrStrength 89;
              set StrengthLevel 40;
            else and ge CurrStrength 90 le CurrStrength 99;
              set StrengthLevel 50;
            else and ge CurrStrength 100 le CurrStrength 109;
              set StrengthLevel 60;
            else and ge CurrStrength 110 le CurrStrength 119;
              set StrengthLevel 70;
            else and ge CurrStrength 120 le CurrStrength 129;
              set StrengthLevel 80;
            else and ge CurrStrength 130 le CurrStrength 139;
              set StrengthLevel 90;
            else ge CurrStrength 140;
              set StrengthLevel 100;
            end;
            debug_log "newTurnUnit: unit " UnitID " got StrengthLevel: " StrengthLevel;
           
            unit.getTag PrevStun Tag.VIRTUAL_STUN_LEVEL;
            if le RandomValue StrengthLevel;
              if lt PrevStun 0;
                clear PrevStun;
              end;
              unit.setStun PrevStun;
              unit.setTag Tag.IS_HANDCUFFED 0;
              unit.setTag Tag.VIRTUAL_STUN_LEVEL 0;
              debug_log "newTurnUnit: if RandomValue (" RandomValue ") <= unit " UnitID " StrengthLevel (" StrengthLevel ") then set real stun: " PrevStun " and remove tag IS_HANDCUFFED";
            else gt RandomValue StrengthLevel;
              unit.getStun CurrStun;
              unit.getStunMax NewStun;
              sub CurrStun NewStun;
              add PrevStun CurrStun;
              unit.setTag Tag.VIRTUAL_STUN_LEVEL PrevStun;
              unit.setStun NewStun;
              debug_log "newTurnUnit: if RandomValue (" RandomValue ") > unit " UnitID " StrengthLevel (" StrengthLevel ") then set VIRTUAL_STUN_LEVEL: " PrevStun " and real stun: " NewStun;
            end;           
          end;
          return;

Each type of handcuffs must have a HANDCUFF_STRENGTH parameter in the "tags" section. By default, it is zero, which means the item is not handcuffs.
For each type of armor, you can specify the HANDCUFF_PROTECTION parameter in the "tags" section. By default, it is equal to zero, which means that the creature can be handcuffed of any handcuffs strength.
When trying to put on handcuffs, the condition is checked: if HANDCUFF_STRENGTH is greater than HANDCUFF_PROTECTION, then the handcuffs will be put on, otherwise not.
The unit, that is handcuffed, is assigned the parameter IS_HANDCUFFED: 1.
Each turn, each unit, in which the IS_HANDCUFFED parameter is 1, is checked for the possibility to free, based on his strength:
if strength in 0..39 then unit has 1% chance to be free,
if 40..49 - 5%,
if 50..59 - 10%,
if 60..69 - 20%,
if 70..79 - 30%,
if 80..89 - 40%,
if 90..99 - 50%,
if 100..109 - 60%,
if 110..119 - 70%,
if 120..129 - 80%,
if 130..139 - 90%,
if 140..infinity - 100%.
Each turn checks how much the unit’s stunning level has changed and this change is recorded to the VIRTUAL_STUN_LEVEL variable in the unit's "tags" section.
If the unit was able to free, its stun level from the VIRTUAL_STUN_LEVEL variable is returned to his stunLevel" and the script finishes its work with this unit.

For understandable how script works, I provided almost every action with a message output to the "openxcom.log" file, because for the player there are no visible changes in the game.

What if the handcuff strength is far greater than their handcuff protection?
It wouldn't make sense for a strong civilian to be able to be able to free itself from the cuffs capable of restraining reapers or chryssalids.
Title: Re: [Script] Handcuffs
Post by: Solarius Scorch on May 01, 2020, 08:25:06 pm
As of today, this submod has been included with the X-Com Files mod, with very minor adjustments.

Thank you very much, Kozinsky!
Title: Re: [Script] Handcuffs
Post by: vadracas on May 01, 2020, 09:32:51 pm
What if the handcuff strength is far greater than their handcuff protection?
It wouldn't make sense for a strong civilian to be able to be able to free itself from the cuffs capable of restraining reapers or chryssalids.


I sincerely hope that handcuffs won't be able to restrain most monsters(excluding mongorns).
Title: Re: [Script] Handcuffs
Post by: Kozinsky on May 01, 2020, 10:06:04 pm
What if the handcuff strength is far greater than their handcuff protection?
It wouldn't make sense for a strong civilian to be able to be able to free itself from the cuffs capable of restraining reapers or chryssalids.
I sincerely hope that handcuffs won't be able to restrain most monsters(excluding mongorns).

If the strength of the handcuffs is greater than the creature's protection, the handcuffs will be put on the creature. If it's less, it won't. Unfortunately, in both cases handcuffs will disappear from the game forever - I don't know how to solve this problem due to limited knowledge or missing script functionality.

The parameters "handcuff strength" and "handcuff protection" have been introduced so that it is possible to introduce several types of handcuffs with different durability. Stronger handcuffs are for catching stronger creatures.
Title: Re: [Script] Handcuffs
Post by: vadracas on May 01, 2020, 11:19:24 pm
I like the idea of Alien Alloy and plasma handcuffs.
Title: Re: [Script] Handcuffs
Post by: Yankes on May 02, 2020, 12:26:24 am
If the strength of the handcuffs is greater than the creature's protection, the handcuffs will be put on the creature. If it's less, it won't. Unfortunately, in both cases handcuffs will disappear from the game forever - I don't know how to solve this problem due to limited knowledge or missing script functionality.

The parameters "handcuff strength" and "handcuff protection" have been introduced so that it is possible to introduce several types of handcuffs with different durability. Stronger handcuffs are for catching stronger creatures.
Because you spend last charge, if you block it, game would not remove your item.
Probably most correct way to do it is set `medikit_action_type` to zero if you are prevented doing any thing.
Title: Re: [Script] Handcuffs
Post by: Thermite on May 02, 2020, 11:35:39 pm
If the strength of the handcuffs is greater than the creature's protection, the handcuffs will be put on the creature. If it's less, it won't. Unfortunately, in both cases handcuffs will disappear from the game forever - I don't know how to solve this problem due to limited knowledge or missing script functionality.

The parameters "handcuff strength" and "handcuff protection" have been introduced so that it is possible to introduce several types of handcuffs with different durability. Stronger handcuffs are for catching stronger creatures.

No, that isn't what I meant! :o
I meant that, if you have a restraining item with, let's say, 5 handcuff strength and use it to restrain a creature that has 2 handcuff protection, it would not make sense for that creature to break free from it, even if it had 50 strength, because the handcuffs are far too potent in handcuff strength for the creature.
Title: Re: [Script] Handcuffs
Post by: Kozinsky on May 03, 2020, 09:32:19 am
No, that isn't what I meant! :o
I meant that, if you have a restraining item with, let's say, 5 handcuff strength and use it to restrain a creature that has 2 handcuff protection, it would not make sense for that creature to break free from it, even if it had 50 strength, because the handcuffs are far too potent in handcuff strength for the creature.
My idea is that parameters "handcuff strength" and "handcuff protection" are only for the purpose of understanding whether a creature can be handcuffed, and if so, what kind of handcuffs he can use. The ability to be released from handcuffs depends on the strength of the creature. Although I am thinking of adding "handcuff strength" to this formula as well, the chance of escaping is calculated from the strength of the prisoner and the strength of the handcuffs. The stronger the handcuffs, the less chance of escape. A weak creature in strong handcuffs can have a 0% chance of escape.
That's what I'll do after I understand and can apply what the Yankes suggested))
Title: Re: [Script] Handcuffs
Post by: vadracas on May 04, 2020, 02:54:17 am
Quick question, where do you find this relationship in the save? Basically, what I'm asking is, will the handcuffs work if you handcuff something, save the game, and load it? I can't find it on the unit id in the save.
Title: Re: [Script] Handcuffs
Post by: Kozinsky on May 04, 2020, 08:51:14 am
Quick question, where do you find this relationship in the save? Basically, what I'm asking is, will the handcuffs work if you handcuff something, save the game, and load it? I can't find it on the unit id in the save.

For a unit, two lines "IS_HANDCUFFED" and "VIRTUAL_STUN_LEVEL" will appear in the "tags" section. If this did not happen, then the handcuffs could not be put on.
Are there any records in the file "openxcom.log"?
Title: Re: [Script] Handcuffs
Post by: vadracas on May 04, 2020, 12:12:05 pm
I received no data in the log, and it did consume my handcuffs, which gave me the impression that what I had used the cuffs on must have been cuffed. However, I was suspicious when I saw nothing in the log, and more so when there wasn't a handcuffed tag on the unit In question(a zombie boomer since I had limited electrical and couldn't afford to let him stand again).
Title: Re: [Script] Handcuffs
Post by: Kozinsky on May 04, 2020, 12:28:15 pm
I received no data in the log, and it did consume my handcuffs, which gave me the impression that what I had used the cuffs on must have been cuffed. However, I was suspicious when I saw nothing in the log, and more so when there wasn't a handcuffed tag on the unit In question(a zombie boomer since I had limited electrical and couldn't afford to let him stand again).

This is very strange. It looks like your version of OXCE doesn't support scripts - in this case the handcuffs behave like a normal stimulant. Maybe you made a syntax mistake when using my script in your mod? And when you run OXCE, script was ignored, while loading, with the corresponding message in "openxcom.log".
Title: Re: [Script] Handcuffs
Post by: vadracas on May 04, 2020, 02:43:13 pm
This is very strange. It looks like your version of OXCE doesn't support scripts - in this case the handcuffs behave like a normal stimulant. Maybe you made a syntax mistake when using my script in your mod? And when you run OXCE, script was ignored, while loading, with the corresponding message in "openxcom.log".


Well, I am using OXCE 6.4.6(compiled on my mac) and the mod with the handcuffs is Solarius's xcomfiles downloaded the latest release from github. When I checked his script, it doesn't have entries to the log, so no surprise there, but I do see that it is supposed to give the unit a tag.
Title: Re: [Script] Handcuffs
Post by: Kozinsky on May 04, 2020, 03:23:41 pm

Well, I am using OXCE 6.4.6(compiled on my mac) and the mod with the handcuffs is Solarius's xcomfiles downloaded the latest release from github. When I checked his script, it doesn't have entries to the log, so no surprise there, but I do see that it is supposed to give the unit a tag.
Tested the latest version of XCF from GitHub - everything works well for civilians. Maybe you have some kind of specific creature you're handcuffing?
Title: Re: [Script] Handcuffs
Post by: vadracas on May 04, 2020, 03:35:38 pm
Zombie Boomer
Title: Re: [Script] Handcuffs
Post by: Solarius Scorch on May 05, 2020, 10:40:04 am
Yeah, I removed the log outputs on Kozinsky's advice. I understand its purpose was beta-testing.

Zombie Boomers are probably way too strong to care much about puny handcuffs...
Title: Re: [Script] Handcuffs
Post by: vadracas on May 05, 2020, 12:44:33 pm
Yeah, I removed the log outputs on Kozinsky's advice. I understand its purpose was beta-testing.

Zombie Boomers are probably way too strong to care much about puny handcuffs...


That's perfectly reasonable, however, I was under the impression the handcuffs wouldn't be consumed if it failed based on this thread?
Title: Re: [Script] Handcuffs
Post by: Solarius Scorch on May 05, 2020, 12:57:52 pm

That's perfectly reasonable, however, I was under the impression the handcuffs wouldn't be consumed if it failed based on this thread?

Both this mod and XCF very clearly state that the handcuffs will be consumed even when unsuccessful.
Title: Re: [Script] Handcuffs
Post by: vadracas on May 05, 2020, 03:11:05 pm
Because you spend last charge, if you block it, game would not remove your item.
Probably most correct way to do it is set `medikit_action_type` to zero if you are prevented doing any thing.

What does this mean then?
Title: Re: [Script] Handcuffs
Post by: Yankes on May 05, 2020, 06:57:15 pm
Item is removed because all charges are set to zero,
and they are set because default medkit logic was run after script,
and it was run because script allowed it.

To fix it you need set in script property I show to block default medkit behavior.

This is clear?

Title: Re: [Script] Handcuffs
Post by: vadracas on May 05, 2020, 07:14:37 pm
Yes, thank you.
Title: Re: [Script] Handcuffs
Post by: Kozinsky on May 05, 2020, 09:17:28 pm
Because you spend last charge, if you block it, game would not remove your item.
Probably most correct way to do it is set `medikit_action_type` to zero if you are prevented doing any thing.
Could you give me an example?

What I need:
I check some condition through "if ... else ... end".
If the condition is "true", the medikit should disappear and the soldier should spend TU and energy to use the medikit (according to the "costUse" block of the item).
If the condition is "false", nothing should happen, the soldier should not waste TU and energy on using the medikit.

What I've done:
If the condition is "true" the medikit is used according to the rules of the game - it disappears, and the soldier spends TU and energy.
If the condition is "false", I restore the charge to the medikit and return the spent TU and energy to the soldier:
Code: [Select]
    healUnit:
      - offset: 1
        code: |
          var int CurrEnergy 0;
          var int CurrTU 0;
...
          if ...
...
          else ...
            actor.getEnergy CurrEnergy;
            actor.getTimeUnits CurrTU;
            add CurrEnergy 10;
            add CurrTU 40;           
            item.setStimulantQuantity 1;
            actor.setEnergy CurrEnergy;
            actor.setTimeUnits CurrTU;
          end;
Title: Re: [Script] Handcuffs
Post by: Yankes on May 05, 2020, 10:46:53 pm
Instead of
Code: [Select]
item.setStimulantQuantity 1;
you should use

Code: [Select]
set medikit_action_type 0;

This will prevent code that is run after script that change number of `setStimulantQuantity`.
Title: Re: [Script] Handcuffs
Post by: Kozinsky on May 06, 2020, 09:23:46 am
Code: [Select]
set medikit_action_type 0;

It doesn't work. The medikit disappears, and the soldier loses TU and energy.

Code: [Select]
items:
  - type: STR_HANDCUFFS
    medikitType: 2
    medikitTargetSelf: false
    medikitTargetImmune: true
    medikitTargetMatrix: 21
    medikitActionName: STR_HANDCUFFS_ACTION
    stimulant: 1
    stunRecovery: 0
    isConsumable: true
    costUse:
      time: 40
      energy: 10

extended:
  scripts:
    healUnit:
      - offset: 1
        code: |
          var int CurrEnergy 0;
          var int CurrTU 0;
...
          if ...
...
          else ...
            #actor.getEnergy CurrEnergy;
            #actor.getTimeUnits CurrTU;
            #add CurrEnergy 10;
            #add CurrTU 40;           
            #item.setStimulantQuantity 1;
            #actor.setEnergy CurrEnergy;
            #actor.setTimeUnits CurrTU;
            set medikit_action_type 0;
          end;
Title: Re: [Script] Handcuffs
Post by: Yankes on May 06, 2020, 07:52:11 pm
ups, I forget one thing, spending resources is unconditional BEFORE script is run.
I incorrectly assume that default behavior still have change of charges but it was removed from it.

Code: [Select]
set medikit_action_type 0;
Is only responsible for:
a) Applying default healing or stim or pankilers
b) Updating item usage statistics (like revivedSoldier or appliedStimulant counts)

Spend of charges and costs are done before script unconditionally.

Sorry for confusion.
Title: Re: [Script] Handcuffs
Post by: Kozinsky on May 06, 2020, 08:33:32 pm
Spend of charges and costs are done before script unconditionally.

I came to the same conclusion.
But it's strange that the script can affect an item that has run out of charges - in my case, it means that the item disappears from the game. I thought that first the algorithm of using the item is processed, then it disappears from the game after spending all its charge and only then the script starts.
Anyway, my task solution works pretty well.
Title: Re: [Script] Handcuffs
Post by: krautbernd on May 28, 2020, 12:37:27 pm
Sometimes - not always - unconscious units become overstunned upon applying handcuffs. Checking the save file, health on these units declines every turn. From what I can tell (by manually reducing health in the save), the unit eventually dies from overstun. There is no way to prevent this in-game, as the stun level can't be reduced and handcuffs can not be removed. This makes applying handcuffs a potential liability.

Is this intended? Mod is XCF btw, but according to Solarius the script should be indentical.
Title: Re: [Script] Handcuffs
Post by: Kozinsky on May 28, 2020, 06:57:28 pm
Sometimes - not always - unconscious units become overstunned upon applying handcuffs. Checking the save file, health on these units declines every turn. From what I can tell (by manually reducing health in the save), the unit eventually dies from overstun. There is no way to prevent this in-game, as the stun level can't be reduced and handcuffs can not be removed. This makes applying handcuffs a potential liability.

In examining this case, I concluded that the maximum safety stun level of the wounded creatures (before they begin to suffer damage from overstun) is lower than maxStunLevel. I therefore reduce maxStunLevel by the percentage reduction of the creature's health.
For example, there is a healthy creature with 100 HP and maxStunLevel 200, i.e. when it receives 201 stun level, it will receive damage from overstun.
We will deal 40 damage to this creature and its current health will be 60 HP. In this state the creature will take damage from overstun at (very approximately) 120 stun level.
I have implemented this algorithm in the current version of XCF at GitHub. But I need to run many different tests to make sure that this solution will always work fine.
Title: Re: [Script] Handcuffs
Post by: krautbernd on May 28, 2020, 07:53:07 pm
Thanks for the update on this, will wait for next XCF version.
Title: Re: [Script] Handcuffs
Post by: Dioxine on September 18, 2020, 07:11:15 pm
1) Is there a standalone version of this script? There's downloads, but not sure how up to date are they. (I'm interested in the version as described in the first posts, with % chances of targets breaking out dependant on their Strength.)
2) Would it be possible to add a text message when the target is getting handcuffed, and when handcuffing failed due to it being immune to that level of handcuffs?
3) Would it be possible to add some indicator that target broke out of handcuffs, ideally by playing a sound?
Title: Re: [Script] Handcuffs
Post by: ohartenstein23 on September 18, 2020, 09:04:47 pm
Scripts can't play sounds, but text warnings are possible. Probably could do an indicator like colored flashing of the the corpse while handcuffed.
Title: Re: [y-script] Handcuffs
Post by: spawi on May 18, 2021, 10:04:30 am
Folks, I was grokking the handcuffs scripts and I think I found up to three possible problems, or I don't get the intent behind the logic. Can you help me understand?

I am talking about these handcuffs scripts:
https://github.com/SolariusScorch/XComFiles/blob/4f8e083df57eeca3a3a1b2dcd455a8ddc30b0cfa/Ruleset/scripts_XCOMFILES.rul#L2150-L2167

               
              else gt RandomValue StrengthLevel;
                unit.getStun CurrStun;
                unit.getStunMax NewStun;
                unit.Stats.getHealth UnitStatHealth;
                unit.getHealth UnitHealth;
               
                muldiv NewStun UnitHealth UnitStatHealth;
                # debug_log "newTurnUnit: unit.Stats.getHealth = " UnitStatHealth ", unit.getHealth = " UnitHealth ", NewStun = " NewStun;
               
                sub CurrStun NewStun;
                add PrevStun CurrStun;
                if lt PrevStun 0;
                  set PrevStun 0;
                end;
                unit.setTag Tag.VIRTUAL_STUN_LEVEL PrevStun;
                unit.setStun NewStun;
                # debug_log "newTurnUnit: if RandomValue (" RandomValue ") > StrengthLevel (" StrengthLevel ") then unit.setTag.VIRTUAL_STUN_LEVEL: " PrevStun ",   unit.setStun: " NewStun;
              end;


The first possible issue I see is that the NewStun, aka "stun-with-handcuffs" aka "stun as understood by the game", is not capped at 200, the same way it is done here:
https://github.com/SolariusScorch/XComFiles/blob/4f8e083df57eeca3a3a1b2dcd455a8ddc30b0cfa/Ruleset/scripts_XCOMFILES.rul#L1860-L1863

This might cause problems for units that have more than 50 base health, because maxStun is base health * 4, as can be seen here:
https://github.com/MeridianOXC/OpenXcom/blob/19449159c806c9e3e57e6907e3580812ff9bacf9/src/Savegame/BattleUnit.cpp#L5224

Thus, for example, if a unit with 100 base health loses 20 hit points, this script will compute its new stun to be (100*4) * (100-20) / 100 = 400 * 0.8 = 360. Ouch.

The second potential problem I see is that the "stun-without-handcuffs" aka "virtual stun" gets set to 4 * (baseHealth - health). Meaning: the more badly wounded the unit, the larger the virtual stun.
This virtual stun is used to compute if the unit will even try to escape the handcuffs. If it is > 0 it won't. This can be seen here:
https://github.com/SolariusScorch/XComFiles/blob/4f8e083df57eeca3a3a1b2dcd455a8ddc30b0cfa/Ruleset/scripts_XCOMFILES.rul#L2134-L2139

For the third problem: this virtual stun sometimes will end up dropping by 1 or 2 by turn, or not at all. Not sure why, but I think these are some rounding errors, as sometimes maxStun is 4*baseHealth-1 or -2.
Thus, some units will never try to escape the handcuffs while some of them will when the stun gets to 0. This is dependent on rounding error.

I deduced the formula for virtual stun from this code fragment:

                sub CurrStun NewStun;
                add PrevStun CurrStun;
                if lt PrevStun 0;
                  set PrevStun 0;


Here CurrStun is initially set to the "stun-including-handcuffs" which is at first MIN(maxStun, 200) which is MIN(baseHealth * 4, 200)
NewStun is maxStun * health / baseHealth

So CurrStun becomes, ignoring he MIN function:
CurrStun = CurrStun - NewStun
which is
maxStun - (maxStun * health/baseHealth)
which is
baseHealth * 4 - (baseHealth * 4 * health/baseHealth)
which is
baseHealth * 4 - (health * 4)
which is
4 * (baseHealth - health)

This now ends up being added to PrevStun which is the "stun-without-handcuffs" a.k.a. virtual stun.

Note that the numbers stabilize in repeated computations in following turns.
Next turn CurrStun will have the value of previous turns' NewStun

Applying to the formula above we get:

CurrStun = CurrStun - NewStun
=>
CurrStun = NewStun - NewStun
=>
CurrStun = 0

As I mentioned, sometimes there are rounding errors and instead CurrStun is -1 or even -2, decreasing the virtual stun by 1 or 2 each turn. But not the "stun-with-handcuffs" aka "stun as understood by the game".