OpenXcom Forum
OpenXcom Forks => OXCE Support => OpenXcom Extended (OXCE) => OXCE Support Y-scripts => Topic started by: memmaker on January 07, 2020, 07:52:42 pm
-
So, I've been working on some ModScripts for OXCE+ and wanted to share what I have so far.
I am actually aiming for some documentation of the various scripting possibilities but did not yet find the time to write something meaningful. So examples will have to do for know.
I will start of with two of my debug scripts which I used for some damage scaling and understanding how XCOM applies damage. (See attached file debug.rul)
I am using two hooks which are part of the hit and damage calculations: hitUnit and damageUnit.
Both are called in quick succession after each other, every time a unit will potentially receive damage.
The first hook (hitUnit) receives power, part and side and is expected to also return these values. So we have the opportunity to change the power of an attack, the body part which was hit or the side of the armor where the hit connected.
The second hook (damageUnit) has variables for all the damage that is applied after a succesful hit (like to_health, to_armor, to_stun, etc.). Here you can change the amount of damage that is applied to the respective type.
One potential use of this would be a weapon which enables for body part targeting. I have included such an example as bodypart_targeting.rul.
We define three new Tags: AUTO_IS_KNEESHOT, AUTO_IS_ARMSHOT & AUTO_IS_HEADSHOT. When applied to a gun, the scripts will check for that tag on the weapon and apply fatal wounds to the bodypart which has been targeted.
(My meal is getting cold, so I will add more information later..;)
-
So, I guess this is the right place to continue posting about my various modscripting examples that fit nowhere else. Let's start off with a XCOM2 style mimic beacon:
items:
- type: STR_MIMIC_BEACON
size: 0.1
costBuy: 10000 # cannot buy
costSell: 8000
weight: 3
bigSprite: 55
floorSprite: 72
power: 0
damageType: 0
damageAlter:
FixRadius: 0
battleType: 4
accuracyThrow: 100
costPrime:
time: 45
costUnprime:
time: 5
costThrow:
time: 5
primeActionName: STR_MIMIC_PRIME_ACTION
primeActionMessage: STR_MIMIC_PRIME_MESSAGE
unprimeActionName: STR_MIMIC_UNPRIME_ACTION
unprimeActionMessage: STR_MIMIC_UNPRIME_MESSAGE
recover: true
spawnUnit: STR_SOLDIER_MIMIC # Default empty meaning don't spawn a unit, when a valid unit (defined in the units: ruleset) is defined here it will be spawned by this item.
spawnUnitFaction: 2 # Default -1 meaning the spawned unit will be the same faction as the unit using/firing the item, this defines which faction gets the new unit:
# -1: Same faction as item user
# 0: Player faction
# 1: Enemy faction
# 2: Civilian faction
units:
- type: STR_SOLDIER_MIMIC
race: STR_SOLDIER_MIMIC
stats:
tu: 0
stamina: 0
health: 45
bravery: 110
reactions: 0
firing: 0
throwing: 0
strength: 0
psiStrength: 100
psiSkill: 0
melee: 0
armor: MIMIC_ARMOR
standHeight: 16
kneelHeight: 16
value: 0
deathSound: 23
moveSound: 14
energyRecovery: 50
aggression: 0
capturable: false
moraleLossWhenKilled: 0
extended:
tags:
BattleUnit:
MIMIC_COUNTER: int
RuleArmor:
IS_MIMIC: int
armors:
- type: MIMIC_ARMOR
tags:
IS_MIMIC: 1
units: [STR_SOLDIER_MIMIC]
corpseBattle:
- STR_CORPSE
allowsMoving: false
createsMeleeThreat: false
spriteSheet: XCOM_0.PCK
spriteInv: MAN_0
spriteFaceGroup: 6
spriteFaceColor: [96, 96, 96, 96, 160, 160, 163, 163] #M0 F0 M1 F1 M2 F2 M3 F3
spriteHairGroup: 9
spriteHairColor: [144, 144, 164, 164, 245, 245, 166, 166] #M0 F0 M1 F1 M2 F2 M3 F3
storeItem: STR_NONE
frontArmor: 12
sideArmor: 12
rearArmor: 12
underArmor: 12
damageModifier:
- 1.0
- 1.0
- 1.0
- 1.0
- 1.0
- 1.0
- 1.0
- 1.0
- 1.0
- 1.0
loftempsSet: [ 3 ]
scripts:
createUnit: |
var ptr RuleArmor armor_rule;
var int is_mimic;
debug_log "Mimic Beacon Code running";
unit.getRuleArmor armor_rule;
armor_rule.getTag is_mimic Tag.IS_MIMIC;
if gt is_mimic 0; # we have a mimic
debug_log "Mimic Beacon Spawned";
unit.setTag Tag.MIMIC_COUNTER 2;
end;
return;
recolorUnitSprite: |
var int color;
var int temp;
get_color color new_pixel;
set temp anim_frame;
wavegen_tri temp 16 16 15;
mul temp -1;
add temp 8;
add_shade new_pixel temp;
return new_pixel;
newTurnUnit: |
var ptr RuleArmor armor_rule;
var int counter;
var int is_mimic;
debug_log "Mimic Beacon Code On New Turn";
if eq side 1; # on the alien turns
unit.getRuleArmor armor_rule;
armor_rule.getTag is_mimic Tag.IS_MIMIC;
if gt is_mimic 0; # we have a mimic
unit.getTag counter Tag.MIMIC_COUNTER;
sub counter 1;
debug_log "Mimic Counter: " counter;
if gt counter 0;
unit.setTag Tag.MIMIC_COUNTER counter;
end;
if eq counter 0; # mimic beacon timer is over
unit.setHealth 0; # kill the mimic
debug_log "Mimic removed";
end;
end;
end;
return;
extraStrings:
- type: en-US
strings:
STR_MIMIC_BEACON: Mimic Beacon
STR_MIMIC_ARMOR: Mimic Armor
STR_SOLDIER_MIMIC: Deployed Mimic Beacon
STR_MIMIC_PRIME_ACTION: Activate Beacon
STR_MIMIC_PRIME_MESSAGE: Mimic Beacon activated
STR_MIMIC_UNPRIME_ACTION: Deactivate Beacon
STR_MIMIC_UNPRIME_MESSAGE: Mimic Beacon deactivated
-
Here I will post some scripts I use to fine-tune the game experience to my liking
1. Alien Exposer
This one negates the vision advantage of the aliens and makes XCOM units see as good as them.
2. Accuracy Nerfer (Adjuster ;)
Allows global changes to the accuracy of all alien units. I use this if I think the aliens are aiming a bit too good ;D Of course it can be used to make the Game even harder by just globally increasing the accuracy of your foes.
3. Power Nerfer
Same as the above. Allows global attack power adjustment of the enemies. Could also be used to make them hit harder..
4. Critical hits. Code for simple critical hits. Might still be a bit finicky. I use this because I play with with a very low damageRange.
extended:
tags:
BattleUnit:
CRITICAL_STATE: int
RuleItem:
CRIT_CHANCE: int
CRIT_DAMAGE: int
scripts:
visibilityUnit:
- offset: -1 # alien exposer
code: |
var ptr RuleArmor armor_rule;
var ptr RuleSoldier soldier_rule;
observer_unit.getRuleSoldier soldier_rule;
if neq soldier_rule null; # we have an xcom unit as observer
if le distance distance_max;
set current_visibility 100; # expose enemy unit if in max viewing dist (like the aliens..)
end;
end;
return current_visibility visibility_mode;
createUnit:
- offset: -1 # accuracy nerfer
code: |
var ptr RuleSoldier soldier_rule;
var int id;
var int firing;
var int adjustment;
set adjustment 90; # 90% accuracy
unit.getId id;
unit.getRuleSoldier soldier_rule;
if eq soldier_rule null; # we have an alien unit
debug_log "Adjusting accuracy of unit" id;
unit.Stats.getFiring firing;
debug_log " - from" firing;
muldiv firing adjustment 100;
unit.Stats.setFiring firing;
debug_log " - to" firing;
end;
return;
hitUnit:
- offset: -1 # power nerfer
code: |
var ptr RuleSoldier soldier_rule;
var int id;
var int firing;
var int adjustment;
set adjustment 70; # 70% power
unit.getId id;
unit.getRuleSoldier soldier_rule;
if neq soldier_rule null; # we have an xcom unit
debug_log "Adjusting power of hit against xcom unit" id;
debug_log " - from" power;
muldiv power adjustment 100;
debug_log " - to" power;
end;
return power part side;
damageUnit:
- offset: -1 # critical hits (balancing for lower damageRange)
code: |
var ptr RuleItem item_rule;
var int weapon_chance;
var int unit_chance;
var int chance;
var int crit_factor; # 100 = 100% additional damage of original power
var int crit_damage;
weapon_item.getRuleItem item_rule;
unit.getTag unit_chance Tag.CRITICAL_STATE;
item_rule.getTag weapon_chance Tag.CRIT_CHANCE;
item_rule.getTag crit_factor Tag.CRIT_DAMAGE;
add unit_chance weapon_chance;
if eq unit_chance 0;
set unit_chance 5; # base chance of 5% for everybody
end;
if eq crit_factor 0;
set crit_factor 20; # 20% additional damage as baseline for everybody on crit
end;
battle_game.randomChance unit_chance; # will set unit_chance to 1 on success
if gt unit_chance 0;
set crit_damage orig_power;
muldiv crit_damage crit_factor 100;
add to_health crit_damage;
debug_log "CRITICAL HIT:" crit_damage;
end;
return;
-
I will put this here, since I do not know where to put this otherwise ;)
# weapon proficicency system - by memmaker
#
# how to use: flag weapons with WEAPON_TYPE tags
# eg. You decide all shotguns are weapon type 3
# Then you would have something like this:
# items:
# - type: STR_SHOTGUN
# tags:
# WEAPON_TYPE: 4 # shotguns
# - type: STR_ALLOY_SHOTGUN
# tags:
# WEAPON_TYPE: 4 # shotguns
#
# You can decide which WEAPON_TYPE entry to use by using this table:
#
# Type 1 -> WEAPON_TYPE: 1
# Type 2 -> WEAPON_TYPE: 2
# Type 3 -> WEAPON_TYPE: 4
# Type 4 -> WEAPON_TYPE: 8
# Type 5 -> WEAPON_TYPE: 16
# Type 6 -> WEAPON_TYPE: 32
# Type 7 -> WEAPON_TYPE: 64
# Type 8 -> WEAPON_TYPE: 128
#
# NOTE1: The current script only allows for a maximum of 8 different weapon types. Could be expanded.
#
# All hits with weapons which are tagged with WEAPON_TYPE will be tracked.
# After the hit_limit is reached (search for "set hit_limit" if you want change it),
# the soldier is awarded the proficiency with this weapon type.
#
# A soldier's accuracy with a proficient weapon is increased (defined at "set accuracy_bonus").
# IMPORTANT: If a soldier has weapons in both hands the bonus of the right hand weapon is applied.
# The technical reason for this is, that we do not know for which item an accuracy bonus is being calculated.
# Also, having a proficient weapon equipped also boosts PSI accuracy, since the bonus is not bound
# to a specific action.
extraStrings:
- type: en-US
strings:
STR_PROFICIENT_MESSAGE_TYPE1: "Soldier became proficient with TYPE1"
STR_PROFICIENT_MESSAGE_TYPE2: "Soldier became proficient with TYPE2"
STR_PROFICIENT_MESSAGE_TYPE3: "Soldier became proficient with TYPE3"
STR_PROFICIENT_MESSAGE_TYPE4: "Soldier became proficient with TYPE4"
STR_PROFICIENT_MESSAGE_TYPE5: "Soldier became proficient with TYPE5"
STR_PROFICIENT_MESSAGE_TYPE6: "Soldier became proficient with TYPE6"
STR_PROFICIENT_MESSAGE_TYPE7: "Soldier became proficient with TYPE7"
STR_PROFICIENT_MESSAGE_TYPE8: "Soldier became proficient with TYPE8"
extended:
tags:
GeoscapeSoldier:
WEAPON_PROFICIENCY_FLAGS: int # 8 bits of flags, one for each weapon type
EXP_WITH_TYPE1: int # tracks the hits a soldier made with these weapon types
EXP_WITH_TYPE2: int
EXP_WITH_TYPE3: int
EXP_WITH_TYPE4: int
EXP_WITH_TYPE5: int
EXP_WITH_TYPE6: int
EXP_WITH_TYPE7: int
EXP_WITH_TYPE8: int
BattleUnit:
HITS_WITH_TYPE1: int # tracks the hits a unit makes with the specific weapon type during a mission
HITS_WITH_TYPE2: int
HITS_WITH_TYPE3: int
HITS_WITH_TYPE4: int
HITS_WITH_TYPE5: int
HITS_WITH_TYPE6: int
HITS_WITH_TYPE7: int
HITS_WITH_TYPE8: int
RuleItem:
WEAPON_TYPE: int # one of, 0 = none, 1 = type 1, 2 = type 2, 4 = type 3, 8 = type 4, 16, 32, 64, 128
scripts:
hitUnit:
- offset: 66 # get weapon type, track hit for that weapon type on unit
code: |
var ptr RuleItem item_rule;
var int weapon_type;
var int temp;
var int hit_limit;
var int exp;
var int wp_flags;
var ptre GeoscapeSoldier soldier;
var ptr RuleSoldier soldier_rule; # replace with getFaction code, when available
unit.getRuleSoldier soldier_rule;
set hit_limit 30; # award weapon proficiency after this number of hits..
if neq soldier_rule null; # is xcom unit
unit.getGeoscapeSoldier soldier;
damaging_item.getRuleItem item_rule;
item_rule.getTag weapon_type Tag.WEAPON_TYPE;
if eq weapon_type 1;
soldier.getTag exp Tag.EXP_WITH_TYPE1;
unit.getTag temp Tag.HITS_WITH_TYPE1;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE1 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE1";
end;
else eq weapon_type 2;
soldier.getTag exp Tag.EXP_WITH_TYPE2;
unit.getTag temp Tag.HITS_WITH_TYPE2;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE2 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE2";
end;
else eq weapon_type 4;
soldier.getTag exp Tag.EXP_WITH_TYPE3;
unit.getTag temp Tag.HITS_WITH_TYPE3;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE3 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE3";
end;
else eq weapon_type 8;
soldier.getTag exp Tag.EXP_WITH_TYPE4;
unit.getTag temp Tag.HITS_WITH_TYPE4;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE4 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE4";
end;
else eq weapon_type 16;
soldier.getTag exp Tag.EXP_WITH_TYPE5;
unit.getTag temp Tag.HITS_WITH_TYPE5;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE5 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE5";
end;
else eq weapon_type 32;
soldier.getTag exp Tag.EXP_WITH_TYPE6;
unit.getTag temp Tag.HITS_WITH_TYPE6;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE6 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE6";
end;
else eq weapon_type 64;
soldier.getTag exp Tag.EXP_WITH_TYPE7;
unit.getTag temp Tag.HITS_WITH_TYPE7;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE7 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE7";
end;
else eq weapon_type 128;
soldier.getTag exp Tag.EXP_WITH_TYPE8;
unit.getTag temp Tag.HITS_WITH_TYPE8;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE8 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE8";
end;
end;
end;
return power part side;
accuracyMultiplierBonusStats:
- offset: 66 # check if unit is proficient with current weapon type, boost accuracy
code: |
var ptr RuleItem item_rule;
var ptr BattleItem weapon;
var int weapon_type;
var int temp;
var int wp_flags;
var ptr GeoscapeSoldier soldier;
var int accuracy_bonus;
var ptr RuleSoldier soldier_rule; # replace with getFaction code, when available
set accuracy_bonus 10; # adjusts the bonus accuracy for handling proficient weapons
unit.getRuleSoldier soldier_rule;
if neq soldier_rule null; # is xcom unit
unit.getGeoscapeSoldier soldier;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
unit.getRightHandWeapon weapon;
if eq weapon null;
unit.getLeftHandWeapon weapon;
end;
if neq weapon null;
weapon.getRuleItem item_rule;
item_rule.getTag weapon_type Tag.WEAPON_TYPE;
bit_and wp_flags weapon_type;
if neq wp_flags 0;
# soldier is proficient in this weapon type
add bonus accuracy_bonus;
debug_log "Weapon proficiency bonus added: " unit weapon;
end;
end;
end;
return bonus;
meleeMultiplierBonusStats:
- offset: 66 # check if unit is proficient with current weapon type, boost accuracy
code: |
var ptr RuleItem item_rule;
var ptr BattleItem weapon;
var int weapon_type;
var int temp;
var int wp_flags;
var ptr GeoscapeSoldier soldier;
var int accuracy_bonus;
var ptr RuleSoldier soldier_rule; # replace with getFaction code, when available
set accuracy_bonus 10; # adjusts the bonus accuracy for handling proficient weapons
unit.getRuleSoldier soldier_rule;
if neq soldier_rule null; # is xcom unit
unit.getGeoscapeSoldier soldier;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
unit.getRightHandWeapon weapon;
if eq weapon null;
unit.getLeftHandWeapon weapon;
end;
if neq weapon null;
weapon.getRuleItem item_rule;
item_rule.getTag weapon_type Tag.WEAPON_TYPE;
bit_and wp_flags weapon_type;
if neq wp_flags 0;
# soldier is proficient in this weapon type
add bonus accuracy_bonus;
debug_log "Weapon proficiency bonus added: " unit weapon;
end;
end;
end;
return bonus;
throwMultiplierBonusStats:
- offset: 66 # check if unit is proficient with current weapon type, boost accuracy
code: |
var ptr RuleItem item_rule;
var ptr BattleItem weapon;
var int weapon_type;
var int temp;
var int wp_flags;
var ptr GeoscapeSoldier soldier;
var int accuracy_bonus;
var ptr RuleSoldier soldier_rule; # replace with getFaction code, when available
set accuracy_bonus 10; # adjusts the bonus accuracy for handling proficient weapons
unit.getRuleSoldier soldier_rule;
if neq soldier_rule null; # is xcom unit
unit.getGeoscapeSoldier soldier;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
unit.getRightHandWeapon weapon;
if eq weapon null;
unit.getLeftHandWeapon weapon;
end;
if neq weapon null;
weapon.getRuleItem item_rule;
item_rule.getTag weapon_type Tag.WEAPON_TYPE;
bit_and wp_flags weapon_type;
if neq wp_flags 0;
# soldier is proficient in this weapon type
add bonus accuracy_bonus;
debug_log "Weapon proficiency bonus added: " unit weapon;
end;
end;
end;
return bonus;
returnFromMissionUnit:
- offset: 66 # transfer hits from battlescape unit to geoscape soldier, award weapon proficiency when limit is hit
code: |
var int hits;
var int exp;
unit.getTag hits Tag.HITS_WITH_TYPE1;
soldier.getTag exp Tag.EXP_WITH_TYPE1;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE1 exp;
unit.getTag hits Tag.HITS_WITH_TYPE2;
soldier.getTag exp Tag.EXP_WITH_TYPE2;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE2 exp;
unit.getTag hits Tag.HITS_WITH_TYPE3;
soldier.getTag exp Tag.EXP_WITH_TYPE3;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE3 exp;
unit.getTag hits Tag.HITS_WITH_TYPE4;
soldier.getTag exp Tag.EXP_WITH_TYPE4;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE4 exp;
unit.getTag hits Tag.HITS_WITH_TYPE5;
soldier.getTag exp Tag.EXP_WITH_TYPE5;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE5 exp;
unit.getTag hits Tag.HITS_WITH_TYPE6;
soldier.getTag exp Tag.EXP_WITH_TYPE6;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE6 exp;
unit.getTag hits Tag.HITS_WITH_TYPE7;
soldier.getTag exp Tag.EXP_WITH_TYPE7;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE7 exp;
unit.getTag hits Tag.HITS_WITH_TYPE8;
soldier.getTag exp Tag.EXP_WITH_TYPE8;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE8 exp;
return;
-
I will put this here, since I do not know where to put this otherwise ;)
This is blowing my mind, thanks for posting this.
-
Here I will post some scripts I use to fine-tune the game experience to my liking
1. Alien Exposer
This one negates the vision advantage of the aliens and makes XCOM units see as good as them.
2. Accuracy Nerfer (Adjuster ;)
Allows global changes to the accuracy of all alien units. I use this if I think the aliens are aiming a bit too good ;D Of course it can be used to make the Game even harder by just globally increasing the accuracy of your foes.
3. Power Nerfer
Same as the above. Allows global attack power adjustment of the enemies. Could also be used to make them hit harder..
4. Critical hits. Code for simple critical hits. Might still be a bit finicky. I use this because I play with with a very low damageRange.
extended:
tags:
BattleUnit:
CRITICAL_STATE: int
RuleItem:
CRIT_CHANCE: int
CRIT_DAMAGE: int
scripts:
visibilityUnit:
- offset: -1 # alien exposer
code: |
var ptr RuleArmor armor_rule;
var ptr RuleSoldier soldier_rule;
observer_unit.getRuleSoldier soldier_rule;
if neq soldier_rule null; # we have an xcom unit as observer
if le distance distance_max;
set current_visibility 100; # expose enemy unit if in max viewing dist (like the aliens..)
end;
end;
return current_visibility visibility_mode;
createUnit:
- offset: -1 # accuracy nerfer
code: |
var ptr RuleSoldier soldier_rule;
var int id;
var int firing;
var int adjustment;
set adjustment 90; # 90% accuracy
unit.getId id;
unit.getRuleSoldier soldier_rule;
if eq soldier_rule null; # we have an alien unit
debug_log "Adjusting accuracy of unit" id;
unit.Stats.getFiring firing;
debug_log " - from" firing;
muldiv firing adjustment 100;
unit.Stats.setFiring firing;
debug_log " - to" firing;
end;
return;
hitUnit:
- offset: -1 # power nerfer
code: |
var ptr RuleSoldier soldier_rule;
var int id;
var int firing;
var int adjustment;
set adjustment 70; # 70% power
unit.getId id;
unit.getRuleSoldier soldier_rule;
if neq soldier_rule null; # we have an xcom unit
debug_log "Adjusting power of hit against xcom unit" id;
debug_log " - from" power;
muldiv power adjustment 100;
debug_log " - to" power;
end;
return power part side;
damageUnit:
- offset: -1 # critical hits (balancing for lower damageRange)
code: |
var ptr RuleItem item_rule;
var int weapon_chance;
var int unit_chance;
var int chance;
var int crit_factor; # 100 = 100% additional damage of original power
var int crit_damage;
weapon_item.getRuleItem item_rule;
unit.getTag unit_chance Tag.CRITICAL_STATE;
item_rule.getTag weapon_chance Tag.CRIT_CHANCE;
item_rule.getTag crit_factor Tag.CRIT_DAMAGE;
add unit_chance weapon_chance;
if eq unit_chance 0;
set unit_chance 5; # base chance of 5% for everybody
end;
if eq crit_factor 0;
set crit_factor 20; # 20% additional damage as baseline for everybody on crit
end;
battle_game.randomChance unit_chance; # will set unit_chance to 1 on success
if gt unit_chance 0;
set crit_damage orig_power;
muldiv crit_damage crit_factor 100;
add to_health crit_damage;
debug_log "CRITICAL HIT:" crit_damage;
end;
return;
Curiously, is there a way to make critical hits negate a portion of armor instead?
-
It should be possible, it would need some code to "revert" part done in engine, but most needed variables are avaialbe in scripts.
[ps]
One big drawback I find, `ArmorEffectiveness` is not exposed to scripts, this mean you need guess what values was.
Probably easiest way would be ignore complete current behavior of engine and write your own damage mechanism :D
I will look in this week if I can add details of damage type to scripts.
-
It should be possible, it would need some code to "revert" part done in engine, but most needed variables are avaialbe in scripts.
[ps]
One big drawback I find, `ArmorEffectiveness` is not exposed to scripts, this mean you need guess what values was.
Probably easiest way would be ignore complete current behavior of engine and write your own damage mechanism :D
I will look in this week if I can add details of damage type to scripts.
While it's not exposed, can you still set the armor or armor effectiveness to 0?
Thanks for peeking into it. I really need to look into the code deeper and see about if I can create more hooks. An inventory iterator would be nice like getInventoryArray()
-
While it's not exposed, can you still set the armor or armor effectiveness to 0?
Thanks for peeking into it. I really need to look into the code deeper and see about if I can create more hooks. An inventory iterator would be nice like getInventoryArray()
Yes, this is one option, and then in script (`hitUnit`) manually subtract armor value using your own logic. Probaby better is alter effectiveness as is not avaiable to scripts right now (unit armor is).
Loops are on my TODO, this is bit tricky because I need made some refactors to make them easy to use and safe (I would prefer that scripts can't hang whole game).
-
I've always wondered how noticeably y-scripts can affect game performance? After all, some are called quite often (each frame). Are there any recommendations about this, restrictions? Say, if my y-script will consist of 5 thousand lines of calculation code? Or 10? Could there be a difference between hooks?
-
y-scripts was designed to DRAW graphic (or at least alter pixels it in arbitrarily way).
Last time I check budget was around 100M script operations per second or something this magnitude.
More important question is what you script do exactly, because some functions could do lot of things (like getting rules by name or finding item in inventory).
-
For now, I was only using tag loads, things like getting an attacker unit or damaging item. Now sure how expensive those operations are.
-
Most of them are relative cheap. And for overall performance, check how often given hook is call, if you do not fill up debug output limit then you should not worry about performance even if you have complex script.
-
Yes, this is one option, and then in script (`hitUnit`) manually subtract armor value using your own logic. Probaby better is alter effectiveness as is not avaiable to scripts right now (unit armor is).
Loops are on my TODO, this is bit tricky because I need made some refactors to make them easy to use and safe (I would prefer that scripts can't hang whole game).
Set Armor effectiveness to 0 or .25 or whatever fits. Got ya.
-
Here I will post some scripts I use to fine-tune the game experience to my liking
4. Critical hits. Code for simple critical hits. Might still be a bit finicky. I use this because I play with with a very low damageRange.
I've been playing around with the critical hit code, combining it to the "turn red for one frame" code and a message to show critical hits.
extraStrings:
- type: en-US
strings:
STR_CRITICAL_HIT_MESSAGE: "Critical hit!"
extended:
tags:
BattleUnit:
CRITICAL_STATE: int
LAST_HIT_FRAME: int
RuleItem:
CRIT_CHANCE: int
CRIT_DAMAGE: int
scripts:
# Future Script for luck
#
# Script for Criticals
damageUnit:
- offset: -1 # critical hits (balancing for lower damageRange)
code: |
var ptr RuleItem item_rule;
var int weapon_chance;
var int unit_chance;
var int chance;
var int crit_factor; # 100 = 100% additional damage of original power
var int crit_damage;
var int temp;
weapon_item.getRuleItem item_rule;
unit.getTag unit_chance Tag.CRITICAL_STATE;
item_rule.getTag weapon_chance Tag.CRIT_CHANCE;
item_rule.getTag crit_factor Tag.CRIT_DAMAGE;
add unit_chance weapon_chance;
if eq unit_chance 0;
set unit_chance 5; # base chance of 5% for everybody
end;
if eq crit_factor 0;
set crit_factor 100; # 100% additional damage as baseline for everybody on crit
end;
battle_game.randomChance unit_chance; # will set unit_chance to 1 on success
if gt unit_chance 0;
set crit_damage orig_power;
muldiv crit_damage crit_factor 100;
add to_health crit_damage;
# Flash RED when crit hit
# NEED TO BUILD IN A CHECK TO SEE IF ITS WEAPON DAMAGE FFS
battle_game.flashMessage "STR_CRITICAL_HIT_MESSAGE";
battle_game.getAnimFrame temp;
unit.setTag Tag.LAST_HIT_FRAME temp;
debug_log "CRITICAL HIT:" crit_damage;
end;
return;
recolorUnitSprite:
- offset: 10
code: |
var int temp;
unit.getTag temp Tag.LAST_HIT_FRAME;
if neq temp 0;
sub temp anim_frame;
if gt temp -3; #only 3 frames after hit have changed color
set_color new_pixel 2; #red color
end;
end;
return new_pixel;
I need to figure out
1) How to connect it to shoot script, since I'd love to have it as 5% for snap shots, 1% for auto shots and 10% for aimed shots.
a) Also I need it to stop declaring critical hits for smoke
2) How to change the code so that it leaves off a damage roll and just gives the base damage number (100%) and then reduces armor effectiveness to 0.25
But I haven't been playing with it all that much yet. Too busy streaming.
Thanks for posting this up.
-
`battle_action` is value you seek for point 1)
Second point is on TODO list. Probably in this month I will have some things finished.
-
`battle_action` is value you seek for point 1)
Second point is on TODO list. Probably in this month I will have some things finished.
Thank you, Yankes, but no need to hurry.
The scripting is pretty intuitive as long as the scope is limited. Still figuring out how to go from mode to mode, but the examples provided help.
I've just been playing with different things. Got it to stop happening for smoke pretty easily and have it re-rolling damage rolls if the damage is under orig_power so that it will give base damage to 150% on a crit.
-
I now added support to query damage type of rule item, two new operations `getDamageType` and `getMeleeDamageType`, each one return object that can be check for exact bonuses or random logic its use.
-
Yes, this is one option, and then in script (`hitUnit`) manually subtract armor value using your own logic. Probaby better is alter effectiveness as is not avaiable to scripts right now (unit armor is).
Loops are on my TODO, this is bit tricky because I need made some refactors to make them easy to use and safe (I would prefer that scripts can't hang whole game).
@Yankes,
How should I approach changing the damage type? I know, I could read the damage type of a clip by checking the damaging_type variable. However, I do not see a way to alter the damaging_type.
-
Some random example of new custom vapor:
- update: STR_BLASTER_BOMB
power: 10
blastRadius: 2
vaporColorSurface: 6
vaporDensitySurface: 10
vaporProbabilitySurface: 100
scripts:
vaporParticleAmmo: |
var int temp;
set subvoxel_velocity subvoxel_trajectory_forward;
muldiv subvoxel_velocity -3 2;
random.randomRangeSymmetric temp 100;
subvoxel_velocity.addX temp;
random.randomRangeSymmetric temp 100;
subvoxel_velocity.addY temp;
random.randomRangeSymmetric temp 100;
subvoxel_velocity.addZ temp;
begin;
var int last 6000;
sub last subvoxel_trajectory_distance_max;
add last subvoxel_trajectory_distance;
if gt last 0;
set temp 100;
muldiv temp last 6000;
random.randomChance temp;
if gt temp 0;
muldiv subvoxel_velocity last 6000;
end;
else lt subvoxel_trajectory_distance 6000;
muldiv subvoxel_velocity subvoxel_trajectory_distance 6000;
end;
end;
subvoxel_velocity.addZ 200;
return;
- update: STR_LASER_RIFLE
vaporColorSurface: 5
vaporDensitySurface: 1
vaporProbabilitySurface: 100
scripts:
vaporParticleAmmo: |
# noting
return;
- update: STR_RIFLE_CLIP
vaporColorSurface: 2
vaporDensitySurface: 17
vaporProbabilitySurface: 100
scripts:
vaporParticleAmmo: |
var int off;
var int temp;
if lt particle_number 3;
var Position up subvoxel_trajectory_up;
var Position right subvoxel_trajectory_right;
var int sin;
var int cos;
set sin subvoxel_trajectory_distance;
set cos subvoxel_trajectory_distance;
wavegen_sin sin 10000 8;
wavegen_cos cos 10000 8;
mul up sin;
mul right cos;
set subvoxel_offset up;
add subvoxel_offset right;
set subvoxel_velocity 0 0 0;
set subvoxel_acceleration 0 0 0;
set subvoxel_drift 10;
set subvoxel_velocity subvoxel_trajectory_forward;
mul subvoxel_velocity -1;
else lt particle_number 5;
add vapor_color -2;
set subvoxel_drift 50;
set subvoxel_velocity subvoxel_trajectory_forward;
else lt particle_number 12;
# set off subvoxel_trajectory_distance;
# wavegen_sin off 1200 5;
set vapor_color -1;
# add vapor_color +1;
# set subvoxel_velocity 0 0 150;
# set subvoxel_acceleration 0 0 off;
else;
var int sin;
var int last 6400;
sub last subvoxel_trajectory_distance_max;
add last subvoxel_trajectory_distance;
if gt last 0;
#hit point
add vapor_color -2;
set subvoxel_offset subvoxel_trajectory_forward;
muldiv subvoxel_offset last 256;
random.randomRangeSymmetric temp 500;
subvoxel_velocity.setX temp;
random.randomRangeSymmetric temp 500;
subvoxel_velocity.setY temp;
random.randomRangeSymmetric temp 500;
subvoxel_velocity.setZ temp;
set subvoxel_acceleration subvoxel_velocity;
muldiv subvoxel_acceleration -1 50;
else lt subvoxel_trajectory_distance 6000;
add vapor_color +1;
#start trajectory
set subvoxel_velocity subvoxel_trajectory_forward;
mul subvoxel_velocity -4;
random.randomRangeSymmetric temp 100;
subvoxel_velocity.addX temp;
random.randomRangeSymmetric temp 100;
subvoxel_velocity.addY temp;
random.randomRangeSymmetric temp 100;
subvoxel_velocity.addZ temp;
set subvoxel_acceleration 0 0 -10;
else;
# set sin subvoxel_trajectory_distance;
# wavegen_sin sin 1000 -12;
# add vapor_color -1;
# set subvoxel_acceleration 0 0 sin;
# set subvoxel_drift 1000;
# set vapor_color -1;
end;
end;
return;
In next week I prepare more concrete examples of some popular weapons trails.
-
I will put this here, since I do not know where to put this otherwise ;)
# weapon proficicency system - by memmaker
#
# how to use: flag weapons with WEAPON_TYPE tags
# eg. You decide all shotguns are weapon type 3
# Then you would have something like this:
# items:
# - type: STR_SHOTGUN
# tags:
# WEAPON_TYPE: 4 # shotguns
# - type: STR_ALLOY_SHOTGUN
# tags:
# WEAPON_TYPE: 4 # shotguns
#
# You can decide which WEAPON_TYPE entry to use by using this table:
#
# Type 1 -> WEAPON_TYPE: 1
# Type 2 -> WEAPON_TYPE: 2
# Type 3 -> WEAPON_TYPE: 4
# Type 4 -> WEAPON_TYPE: 8
# Type 5 -> WEAPON_TYPE: 16
# Type 6 -> WEAPON_TYPE: 32
# Type 7 -> WEAPON_TYPE: 64
# Type 8 -> WEAPON_TYPE: 128
#
# NOTE1: The current script only allows for a maximum of 8 different weapon types. Could be expanded.
#
# All hits with weapons which are tagged with WEAPON_TYPE will be tracked.
# After the hit_limit is reached (search for "set hit_limit" if you want change it),
# the soldier is awarded the proficiency with this weapon type.
#
# A soldier's accuracy with a proficient weapon is increased (defined at "set accuracy_bonus").
# IMPORTANT: If a soldier has weapons in both hands the bonus of the right hand weapon is applied.
# The technical reason for this is, that we do not know for which item an accuracy bonus is being calculated.
# Also, having a proficient weapon equipped also boosts PSI accuracy, since the bonus is not bound
# to a specific action.
extraStrings:
- type: en-US
strings:
STR_PROFICIENT_MESSAGE_TYPE1: "Soldier became proficient with TYPE1"
STR_PROFICIENT_MESSAGE_TYPE2: "Soldier became proficient with TYPE2"
STR_PROFICIENT_MESSAGE_TYPE3: "Soldier became proficient with TYPE3"
STR_PROFICIENT_MESSAGE_TYPE4: "Soldier became proficient with TYPE4"
STR_PROFICIENT_MESSAGE_TYPE5: "Soldier became proficient with TYPE5"
STR_PROFICIENT_MESSAGE_TYPE6: "Soldier became proficient with TYPE6"
STR_PROFICIENT_MESSAGE_TYPE7: "Soldier became proficient with TYPE7"
STR_PROFICIENT_MESSAGE_TYPE8: "Soldier became proficient with TYPE8"
extended:
tags:
GeoscapeSoldier:
WEAPON_PROFICIENCY_FLAGS: int # 8 bits of flags, one for each weapon type
EXP_WITH_TYPE1: int # tracks the hits a soldier made with these weapon types
EXP_WITH_TYPE2: int
EXP_WITH_TYPE3: int
EXP_WITH_TYPE4: int
EXP_WITH_TYPE5: int
EXP_WITH_TYPE6: int
EXP_WITH_TYPE7: int
EXP_WITH_TYPE8: int
BattleUnit:
HITS_WITH_TYPE1: int # tracks the hits a unit makes with the specific weapon type during a mission
HITS_WITH_TYPE2: int
HITS_WITH_TYPE3: int
HITS_WITH_TYPE4: int
HITS_WITH_TYPE5: int
HITS_WITH_TYPE6: int
HITS_WITH_TYPE7: int
HITS_WITH_TYPE8: int
RuleItem:
WEAPON_TYPE: int # one of, 0 = none, 1 = type 1, 2 = type 2, 4 = type 3, 8 = type 4, 16, 32, 64, 128
scripts:
hitUnit:
- offset: 66 # get weapon type, track hit for that weapon type on unit
code: |
var ptr RuleItem item_rule;
var int weapon_type;
var int temp;
var int hit_limit;
var int exp;
var int wp_flags;
var ptre GeoscapeSoldier soldier;
var ptr RuleSoldier soldier_rule; # replace with getFaction code, when available
unit.getRuleSoldier soldier_rule;
set hit_limit 30; # award weapon proficiency after this number of hits..
if neq soldier_rule null; # is xcom unit
unit.getGeoscapeSoldier soldier;
damaging_item.getRuleItem item_rule;
item_rule.getTag weapon_type Tag.WEAPON_TYPE;
if eq weapon_type 1;
soldier.getTag exp Tag.EXP_WITH_TYPE1;
unit.getTag temp Tag.HITS_WITH_TYPE1;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE1 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE1";
end;
else eq weapon_type 2;
soldier.getTag exp Tag.EXP_WITH_TYPE2;
unit.getTag temp Tag.HITS_WITH_TYPE2;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE2 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE2";
end;
else eq weapon_type 4;
soldier.getTag exp Tag.EXP_WITH_TYPE3;
unit.getTag temp Tag.HITS_WITH_TYPE3;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE3 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE3";
end;
else eq weapon_type 8;
soldier.getTag exp Tag.EXP_WITH_TYPE4;
unit.getTag temp Tag.HITS_WITH_TYPE4;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE4 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE4";
end;
else eq weapon_type 16;
soldier.getTag exp Tag.EXP_WITH_TYPE5;
unit.getTag temp Tag.HITS_WITH_TYPE5;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE5 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE5";
end;
else eq weapon_type 32;
soldier.getTag exp Tag.EXP_WITH_TYPE6;
unit.getTag temp Tag.HITS_WITH_TYPE6;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE6 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE6";
end;
else eq weapon_type 64;
soldier.getTag exp Tag.EXP_WITH_TYPE7;
unit.getTag temp Tag.HITS_WITH_TYPE7;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE7 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE7";
end;
else eq weapon_type 128;
soldier.getTag exp Tag.EXP_WITH_TYPE8;
unit.getTag temp Tag.HITS_WITH_TYPE8;
add temp 1;
unit.setTag Tag.HITS_WITH_TYPE8 temp;
add exp temp;
if ge exp hit_limit;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
bit_or wp_flags weapon_type;
soldier.setTag Tag.WEAPON_PROFICIENCY_FLAGS wp_flags;
battle_game.flashMessage "STR_PROFICIENT_MESSAGE_TYPE8";
end;
end;
end;
return power part side;
accuracyMultiplierBonusStats:
- offset: 66 # check if unit is proficient with current weapon type, boost accuracy
code: |
var ptr RuleItem item_rule;
var ptr BattleItem weapon;
var int weapon_type;
var int temp;
var int wp_flags;
var ptr GeoscapeSoldier soldier;
var int accuracy_bonus;
var ptr RuleSoldier soldier_rule; # replace with getFaction code, when available
set accuracy_bonus 10; # adjusts the bonus accuracy for handling proficient weapons
unit.getRuleSoldier soldier_rule;
if neq soldier_rule null; # is xcom unit
unit.getGeoscapeSoldier soldier;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
unit.getRightHandWeapon weapon;
if eq weapon null;
unit.getLeftHandWeapon weapon;
end;
if neq weapon null;
weapon.getRuleItem item_rule;
item_rule.getTag weapon_type Tag.WEAPON_TYPE;
bit_and wp_flags weapon_type;
if neq wp_flags 0;
# soldier is proficient in this weapon type
add bonus accuracy_bonus;
debug_log "Weapon proficiency bonus added: " unit weapon;
end;
end;
end;
return bonus;
meleeMultiplierBonusStats:
- offset: 66 # check if unit is proficient with current weapon type, boost accuracy
code: |
var ptr RuleItem item_rule;
var ptr BattleItem weapon;
var int weapon_type;
var int temp;
var int wp_flags;
var ptr GeoscapeSoldier soldier;
var int accuracy_bonus;
var ptr RuleSoldier soldier_rule; # replace with getFaction code, when available
set accuracy_bonus 10; # adjusts the bonus accuracy for handling proficient weapons
unit.getRuleSoldier soldier_rule;
if neq soldier_rule null; # is xcom unit
unit.getGeoscapeSoldier soldier;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
unit.getRightHandWeapon weapon;
if eq weapon null;
unit.getLeftHandWeapon weapon;
end;
if neq weapon null;
weapon.getRuleItem item_rule;
item_rule.getTag weapon_type Tag.WEAPON_TYPE;
bit_and wp_flags weapon_type;
if neq wp_flags 0;
# soldier is proficient in this weapon type
add bonus accuracy_bonus;
debug_log "Weapon proficiency bonus added: " unit weapon;
end;
end;
end;
return bonus;
throwMultiplierBonusStats:
- offset: 66 # check if unit is proficient with current weapon type, boost accuracy
code: |
var ptr RuleItem item_rule;
var ptr BattleItem weapon;
var int weapon_type;
var int temp;
var int wp_flags;
var ptr GeoscapeSoldier soldier;
var int accuracy_bonus;
var ptr RuleSoldier soldier_rule; # replace with getFaction code, when available
set accuracy_bonus 10; # adjusts the bonus accuracy for handling proficient weapons
unit.getRuleSoldier soldier_rule;
if neq soldier_rule null; # is xcom unit
unit.getGeoscapeSoldier soldier;
soldier.getTag wp_flags Tag.WEAPON_PROFICIENCY_FLAGS;
unit.getRightHandWeapon weapon;
if eq weapon null;
unit.getLeftHandWeapon weapon;
end;
if neq weapon null;
weapon.getRuleItem item_rule;
item_rule.getTag weapon_type Tag.WEAPON_TYPE;
bit_and wp_flags weapon_type;
if neq wp_flags 0;
# soldier is proficient in this weapon type
add bonus accuracy_bonus;
debug_log "Weapon proficiency bonus added: " unit weapon;
end;
end;
end;
return bonus;
returnFromMissionUnit:
- offset: 66 # transfer hits from battlescape unit to geoscape soldier, award weapon proficiency when limit is hit
code: |
var int hits;
var int exp;
unit.getTag hits Tag.HITS_WITH_TYPE1;
soldier.getTag exp Tag.EXP_WITH_TYPE1;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE1 exp;
unit.getTag hits Tag.HITS_WITH_TYPE2;
soldier.getTag exp Tag.EXP_WITH_TYPE2;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE2 exp;
unit.getTag hits Tag.HITS_WITH_TYPE3;
soldier.getTag exp Tag.EXP_WITH_TYPE3;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE3 exp;
unit.getTag hits Tag.HITS_WITH_TYPE4;
soldier.getTag exp Tag.EXP_WITH_TYPE4;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE4 exp;
unit.getTag hits Tag.HITS_WITH_TYPE5;
soldier.getTag exp Tag.EXP_WITH_TYPE5;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE5 exp;
unit.getTag hits Tag.HITS_WITH_TYPE6;
soldier.getTag exp Tag.EXP_WITH_TYPE6;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE6 exp;
unit.getTag hits Tag.HITS_WITH_TYPE7;
soldier.getTag exp Tag.EXP_WITH_TYPE7;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE7 exp;
unit.getTag hits Tag.HITS_WITH_TYPE8;
soldier.getTag exp Tag.EXP_WITH_TYPE8;
add exp hits;
soldier.setTag Tag.EXP_WITH_TYPE8 exp;
return;
Any chance to make this directly work based upon soldierDiaryentries? (totalKillsWithAWeapon)
-
Right now `soldierDiaryentries` are not exposed to scripts. When I have some time I could check how easy would add some getters there.
-
Right now `soldierDiaryentries` are not exposed to scripts. When I have some time I could check how easy would add some getters there.
Would be nice to have some tiny bonuses applied, via commendation, when becoming profient with a weapon, tracked via soldier diaries. It would also mean it is applicable for older savegames and gets retroactive granted.
I am wondering if it would be possible to also give reductions to enemies attempting to shoot a soldier, who shoot at before and awarded a Medal with totalShotAt10Times.
Ok without exposure this is something to be dreaming about in the future.
Thanks for your work and considering this.
-
Would be nice to have some tiny bonuses applied, via commendation, when becoming profient with a weapon, tracked via soldier diaries. It would also mean it is applicable for older savegames and gets retroactive granted.
Commendations can be linked to soldier bonuses: https://openxcom.org/forum/index.php/topic,7405.msg116840.html#msg116840
Even without scripting.
Mods like XcomFiles already do that, have a look if such bonuses are enough for you.
-
Funny to forget features you add yourself :D
-
Commendations can be linked to soldier bonuses: https://openxcom.org/forum/index.php/topic,7405.msg116840.html#msg116840
Even without scripting.
Mods like XcomFiles already do that, have a look if such bonuses are enough for you.
Thanks for pointing this out. I thought it would two different things. Now i can start working on things.
-
visibilityUnit:
- new: BASIC_VISIBILITY_CALC
offset: 0.01
code: |
var int newVisibility;
var int heatVision;
observer_unit.getHeatVision heatVision;
limit heatVision 0 100;
set newVisibility distance_max; # max visibility distance based on current light level of target tile and camouflages
sub newVisibility distance; # distance to target
begin;
var int temp;
var int proportion 100;
sub proportion heatVision;
set temp smoke_density_near_observer; # special adjustment to reduce effect of smoke on close observer in dark places
div temp -2;
add temp smoke_density;
mul proportion distance_target_max; # adjustment to scale effectives bases to max possbile visiblity range
muldiv temp proportion 6000;
add newVisibility temp;
end;
begin;
var int temp;
var int proportion 0;
add proportion heatVision;
set temp fire_density_near_observer; # special adjustment to reduce effect of fire on close observer in dark places
div temp -2;
add temp fire_density;
mul proportion distance_target_max; # adjustment to scale effectives bases to max possbile visiblity range
muldiv temp proportion 6000;
add newVisibility temp;
end;
set current_visibility newVisibility;
return current_visibility visibility_mode;
This is approximation of current (OXCE 8.0) basic visibility calucaltion, good starting point if you want override itr