From 5c014bd935da7a19aeed831450a02d6d7f068a46 Mon Sep 17 00:00:00 2001 From: LordMidas <55047920+LordMidas@users.noreply.github.com> Date: Mon, 12 May 2025 22:38:52 +0100 Subject: [PATCH] refactor: change many hooks to VeryLate for safer wrapping msu features --- msu/hooks/ai/tactical/agent.nut | 52 ++-- .../tactical/behaviors/ai_pickup_weapon.nut | 46 +-- .../tactical/behaviors/ai_switchto_melee.nut | 64 ++-- .../tactical/behaviors/ai_switchto_ranged.nut | 48 +-- .../ai/tactical/behaviors/ai_throw_bomb.nut | 46 +-- msu/hooks/entity/tactical/actor.nut | 71 +++-- msu/hooks/entity/tactical/entity.nut | 38 +-- msu/hooks/entity/tactical/player.nut | 50 ++-- msu/hooks/entity/world/combat_manager.nut | 27 +- msu/hooks/entity/world/settlement.nut | 24 +- msu/hooks/items/item_container.nut | 38 +-- msu/hooks/items/shields/shield.nut | 32 +- msu/hooks/items/weapons/weapon.nut | 68 +++-- msu/hooks/skills/skill.nut | 198 ++++++------ msu/hooks/states/main_menu_state.nut | 100 ++++--- msu/hooks/states/state.nut | 14 +- msu/hooks/states/tactical_state.nut | 74 ++--- msu/hooks/states/world/asset_manager.nut | 45 +-- msu/hooks/states/world_state.nut | 282 +++++++++--------- msu/hooks/ui/global/data_helper.nut | 22 +- .../screens/menu/modules/main_menu_module.nut | 17 +- .../ui/screens/tooltip/tooltip_events.nut | 106 +++---- .../town_travel_dialog_module.nut | 16 +- 23 files changed, 763 insertions(+), 715 deletions(-) diff --git a/msu/hooks/ai/tactical/agent.nut b/msu/hooks/ai/tactical/agent.nut index b4b6498fc..6b8d726f9 100644 --- a/msu/hooks/ai/tactical/agent.nut +++ b/msu/hooks/ai/tactical/agent.nut @@ -1,32 +1,6 @@ ::MSU.MH.hook("scripts/ai/tactical/agent", function(q) { q.m.MSU_BehaviorStacks <- {}; q.m.MSU_BehaviorToRemove <- null; - - q.addBehavior = @(__original) function( _behavior ) - { - if (_behavior.getID() in this.m.MSU_BehaviorStacks) - { - ++this.m.MSU_BehaviorStacks[_behavior.getID()]; - return; - } - - this.m.MSU_BehaviorStacks[_behavior.getID()] <- 1; - return __original(_behavior); - } - - q.removeBehavior = @(__original) function( _id ) - { - if (_id in this.m.MSU_BehaviorStacks) delete this.m.MSU_BehaviorStacks[_id]; - return __original(_id); - } - - // TODO: This function's name is temporary and is currently undocumented while we search for a better name - // Once we find a better name we will change it and add it to documentation - q.removeBehaviorByStack <- function( _id ) - { - if (!(_id in this.m.MSU_BehaviorStacks) || --this.m.MSU_BehaviorStacks[_id] == 0) - return this.removeBehavior(_id); - } }); ::MSU.QueueBucket.VeryLate.push(function() { @@ -41,5 +15,31 @@ } return ret; } + + q.addBehavior = @(__original) function( _behavior ) + { + if (_behavior.getID() in this.m.MSU_BehaviorStacks) + { + ++this.m.MSU_BehaviorStacks[_behavior.getID()]; + return; + } + + this.m.MSU_BehaviorStacks[_behavior.getID()] <- 1; + return __original(_behavior); + } + + q.removeBehavior = @(__original) function( _id ) + { + if (_id in this.m.MSU_BehaviorStacks) delete this.m.MSU_BehaviorStacks[_id]; + return __original(_id); + } + + // TODO: This function's name is temporary and is currently undocumented while we search for a better name + // Once we find a better name we will change it and add it to documentation + q.removeBehaviorByStack <- function( _id ) + { + if (!(_id in this.m.MSU_BehaviorStacks) || --this.m.MSU_BehaviorStacks[_id] == 0) + return this.removeBehavior(_id); + } }); }); diff --git a/msu/hooks/ai/tactical/behaviors/ai_pickup_weapon.nut b/msu/hooks/ai/tactical/behaviors/ai_pickup_weapon.nut index 725af87be..452309b8b 100644 --- a/msu/hooks/ai/tactical/behaviors/ai_pickup_weapon.nut +++ b/msu/hooks/ai/tactical/behaviors/ai_pickup_weapon.nut @@ -1,33 +1,35 @@ -::MSU.MH.hook("scripts/ai/tactical/behaviors/ai_pickup_weapon", function(q) { - q.onExecute = @(__original) function( _entity ) - { - local itemsBefore = array(::Const.ItemSlot.COUNT); - for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/ai/tactical/behaviors/ai_pickup_weapon", function(q) { + q.onExecute = @(__original) function( _entity ) { - itemsBefore[i] = clone _entity.getItems().m.Items[i]; - } + local itemsBefore = array(::Const.ItemSlot.COUNT); + for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) + { + itemsBefore[i] = clone _entity.getItems().m.Items[i]; + } - _entity.getItems().m.MSU_IsIgnoringItemAction = true; - local ret = __original(_entity); - _entity.getItems().m.MSU_IsIgnoringItemAction = false; + _entity.getItems().m.MSU_IsIgnoringItemAction = true; + local ret = __original(_entity); + _entity.getItems().m.MSU_IsIgnoringItemAction = false; - if (ret) - { - local items = []; - for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) + if (ret) { - foreach (j, item in _entity.getItems().m.Items[i]) + local items = []; + for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) { - if (item != itemsBefore[i][j] && items.find(item) == null) + foreach (j, item in _entity.getItems().m.Items[i]) { - if (item != null && item != -1) items.push(item); - if (itemsBefore[i][j] != null && itemsBefore[i][j] != -1) items.push(itemsBefore[i][j]); + if (item != itemsBefore[i][j] && items.find(item) == null) + { + if (item != null && item != -1) items.push(item); + if (itemsBefore[i][j] != null && itemsBefore[i][j] != -1) items.push(itemsBefore[i][j]); + } } } + _entity.getItems().payForAction(items); } - _entity.getItems().payForAction(items); - } - return ret; - } + return ret; + } + }); }); diff --git a/msu/hooks/ai/tactical/behaviors/ai_switchto_melee.nut b/msu/hooks/ai/tactical/behaviors/ai_switchto_melee.nut index 9383c90ac..76af744d7 100644 --- a/msu/hooks/ai/tactical/behaviors/ai_switchto_melee.nut +++ b/msu/hooks/ai/tactical/behaviors/ai_switchto_melee.nut @@ -1,44 +1,46 @@ -::MSU.MH.hook("scripts/ai/tactical/behaviors/ai_switchto_melee", function(q) { - q.onExecute = @(__original) function( _entity ) - { - local itemsBefore = array(::Const.ItemSlot.COUNT); - // We need to cache this as it is set to false in onExecute - local wasNegatingDisarm = this.m.IsNegatingDisarm; - for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/ai/tactical/behaviors/ai_switchto_melee", function(q) { + q.onExecute = @(__original) function( _entity ) { - itemsBefore[i] = clone _entity.getItems().m.Items[i]; - } - - _entity.getItems().m.MSU_IsIgnoringItemAction = true; - local ret = __original(_entity); - _entity.getItems().m.MSU_IsIgnoringItemAction = false; - - if (ret) - { - if (wasNegatingDisarm) + local itemsBefore = array(::Const.ItemSlot.COUNT); + // We need to cache this as it is set to false in onExecute + local wasNegatingDisarm = this.m.IsNegatingDisarm; + for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) { - // Once to use up quickhands, once to actually pay for the cost - _entity.getItems().payForAction([_entity.getMainhandItem()]); - _entity.getItems().payForAction([_entity.getMainhandItem()]); + itemsBefore[i] = clone _entity.getItems().m.Items[i]; } - else + + _entity.getItems().m.MSU_IsIgnoringItemAction = true; + local ret = __original(_entity); + _entity.getItems().m.MSU_IsIgnoringItemAction = false; + + if (ret) { - local items = []; - for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) + if (wasNegatingDisarm) + { + // Once to use up quickhands, once to actually pay for the cost + _entity.getItems().payForAction([_entity.getMainhandItem()]); + _entity.getItems().payForAction([_entity.getMainhandItem()]); + } + else { - foreach (j, item in _entity.getItems().m.Items[i]) + local items = []; + for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) { - if (item != itemsBefore[i][j] && items.find(item) == null) + foreach (j, item in _entity.getItems().m.Items[i]) { - if (item != null && item != -1) items.push(item); - if (itemsBefore[i][j] != null && itemsBefore[i][j] != -1) items.push(itemsBefore[i][j]); + if (item != itemsBefore[i][j] && items.find(item) == null) + { + if (item != null && item != -1) items.push(item); + if (itemsBefore[i][j] != null && itemsBefore[i][j] != -1) items.push(itemsBefore[i][j]); + } } } + _entity.getItems().payForAction(items); } - _entity.getItems().payForAction(items); } - } - return ret; - } + return ret; + } + }); }); diff --git a/msu/hooks/ai/tactical/behaviors/ai_switchto_ranged.nut b/msu/hooks/ai/tactical/behaviors/ai_switchto_ranged.nut index 15c356cb1..886613a73 100644 --- a/msu/hooks/ai/tactical/behaviors/ai_switchto_ranged.nut +++ b/msu/hooks/ai/tactical/behaviors/ai_switchto_ranged.nut @@ -1,34 +1,36 @@ -::MSU.MH.hook("scripts/ai/tactical/behaviors/ai_switchto_ranged", function(q) { - q.onExecute = @(__original) function( _entity ) - { - local itemsBefore = array(::Const.ItemSlot.COUNT); - for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/ai/tactical/behaviors/ai_switchto_ranged", function(q) { + q.onExecute = @(__original) function( _entity ) { - itemsBefore[i] = clone _entity.getItems().m.Items[i]; - } - - _entity.getItems().m.MSU_IsIgnoringItemAction = true; - local ret = __original(_entity); - _entity.getItems().m.MSU_IsIgnoringItemAction = false; + local itemsBefore = array(::Const.ItemSlot.COUNT); + for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) + { + itemsBefore[i] = clone _entity.getItems().m.Items[i]; + } - if (ret) - { + _entity.getItems().m.MSU_IsIgnoringItemAction = true; + local ret = __original(_entity); + _entity.getItems().m.MSU_IsIgnoringItemAction = false; - local items = []; - for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) + if (ret) { - foreach (j, item in _entity.getItems().m.Items[i]) + + local items = []; + for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) { - if (item != itemsBefore[i][j] && items.find(item) == null) + foreach (j, item in _entity.getItems().m.Items[i]) { - if (item != null && item != -1) items.push(item); - if (itemsBefore[i][j] != null && itemsBefore[i][j] != -1) items.push(itemsBefore[i][j]); + if (item != itemsBefore[i][j] && items.find(item) == null) + { + if (item != null && item != -1) items.push(item); + if (itemsBefore[i][j] != null && itemsBefore[i][j] != -1) items.push(itemsBefore[i][j]); + } } } + _entity.getItems().payForAction(items); } - _entity.getItems().payForAction(items); - } - return ret; - } + return ret; + } + }); }); diff --git a/msu/hooks/ai/tactical/behaviors/ai_throw_bomb.nut b/msu/hooks/ai/tactical/behaviors/ai_throw_bomb.nut index a0a6b4a35..b09199f4a 100644 --- a/msu/hooks/ai/tactical/behaviors/ai_throw_bomb.nut +++ b/msu/hooks/ai/tactical/behaviors/ai_throw_bomb.nut @@ -1,33 +1,35 @@ -::MSU.MH.hook("scripts/ai/tactical/behaviors/ai_throw_bomb", function(q) { - q.onExecute = @(__original) function( _entity ) - { - local itemsBefore = array(::Const.ItemSlot.COUNT); - for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/ai/tactical/behaviors/ai_throw_bomb", function(q) { + q.onExecute = @(__original) function( _entity ) { - itemsBefore[i] = clone _entity.getItems().m.Items[i]; - } + local itemsBefore = array(::Const.ItemSlot.COUNT); + for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) + { + itemsBefore[i] = clone _entity.getItems().m.Items[i]; + } - _entity.getItems().m.MSU_IsIgnoringItemAction = true; - local ret = __original(_entity); - _entity.getItems().m.MSU_IsIgnoringItemAction = false; + _entity.getItems().m.MSU_IsIgnoringItemAction = true; + local ret = __original(_entity); + _entity.getItems().m.MSU_IsIgnoringItemAction = false; - if (ret && this.m.Skill == null) - { - local items = []; - for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) + if (ret && this.m.Skill == null) { - foreach (j, item in _entity.getItems().m.Items[i]) + local items = []; + for (local i = 0; i < ::Const.ItemSlot.COUNT; i++) { - if (item != itemsBefore[i][j] && items.find(item) == null) + foreach (j, item in _entity.getItems().m.Items[i]) { - if (item != null && item != -1) items.push(item); - if (itemsBefore[i][j] != null && itemsBefore[i][j] != -1) items.push(itemsBefore[i][j]); + if (item != itemsBefore[i][j] && items.find(item) == null) + { + if (item != null && item != -1) items.push(item); + if (itemsBefore[i][j] != null && itemsBefore[i][j] != -1) items.push(itemsBefore[i][j]); + } } } + _entity.getItems().payForAction(items); } - _entity.getItems().payForAction(items); - } - return ret; - } + return ret; + } + }); }); diff --git a/msu/hooks/entity/tactical/actor.nut b/msu/hooks/entity/tactical/actor.nut index 52ad2f600..1e02b0d88 100644 --- a/msu/hooks/entity/tactical/actor.nut +++ b/msu/hooks/entity/tactical/actor.nut @@ -1,40 +1,13 @@ ::MSU.MH.hook("scripts/entity/tactical/actor", function(q) { - q.onMovementStart = @(__original) function ( _tile, _numTiles ) - { - __original(_tile, _numTiles); - this.m.IsMoving = true; - this.m.Skills.onMovementStarted(_tile, _numTiles); - this.m.IsMoving = false; - } - - // legacy support for MSU-added skill_container.onMovementFinished for vanilla up to 1.5.0.15 - if (::Hooks.getMod("vanilla").getVersion() <= ::Hooks.SQClass.ModVersion("1.5.0-15")) - { - q.onMovementFinish = @(__original) function ( _tile ) - { - __original(_tile); - this.m.IsMoving = true; - this.m.Skills.onMovementFinished(_tile); - this.m.IsMoving = false; - } - } - - q.onMovementStep = @(__original) function( _tile, _levelDifference ) - { - local ret = __original(_tile, _levelDifference); - - if (ret) - { - this.m.Skills.onMovementStep(_tile, _levelDifference); - } - - return ret; - } - // VANILLAFIX: http://battlebrothersgame.com/forums/topic/oncombatstarted-is-not-called-for-ai-characters/ // This fix is spread out over 4 files: tactical_entity_manager, actor, player, standard_bearer q.onCombatStart <- function() { + // player class already has its own onCombatStart defined in vanilla + // which does exactly what this function does + if (::isKindOf(this, "player")) + return; + this.m.Skills.onCombatStarted(); this.m.Items.onCombatStarted(); this.m.Skills.update(); @@ -127,6 +100,40 @@ }); ::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/entity/tactical/actor", function(q) { + q.onMovementStart = @(__original) function ( _tile, _numTiles ) + { + __original(_tile, _numTiles); + this.m.IsMoving = true; + this.m.Skills.onMovementStarted(_tile, _numTiles); + this.m.IsMoving = false; + } + + // legacy support for MSU-added skill_container.onMovementFinished for vanilla up to 1.5.0.15 + if (::Hooks.getMod("vanilla").getVersion() <= ::Hooks.SQClass.ModVersion("1.5.0-15")) + { + q.onMovementFinish = @(__original) function ( _tile ) + { + __original(_tile); + this.m.IsMoving = true; + this.m.Skills.onMovementFinished(_tile); + this.m.IsMoving = false; + } + } + + q.onMovementStep = @(__original) function( _tile, _levelDifference ) + { + local ret = __original(_tile, _levelDifference); + + if (ret) + { + this.m.Skills.onMovementStep(_tile, _levelDifference); + } + + return ret; + } + }); + ::MSU.MH.hookTree("scripts/entity/tactical/actor", function(q) { q.onDeath = @(__original) function( _killer, _skill, _tile, _fatalityType ) { diff --git a/msu/hooks/entity/tactical/entity.nut b/msu/hooks/entity/tactical/entity.nut index f323adb58..73d8696e6 100644 --- a/msu/hooks/entity/tactical/entity.nut +++ b/msu/hooks/entity/tactical/entity.nut @@ -1,13 +1,4 @@ ::MSU.MH.hook("scripts/entity/tactical/entity", function(q) { - q.create = @(__original) function() - { - __original(); - if (!::MSU.Serialization.isLoading()) - { - this.MSU_generateUID(); - } - } - q.getUID <- function() { if (::MSU.Serialization.isLoading()) @@ -24,17 +15,30 @@ this.getFlags().set("MSU_UID", ::MSU.Utils.__generateUID()); ::MSU.__addToUIDMap(this); } +}); - q.onDeserialize = @(__original) function( _in ) - { - __original(_in); - if (!this.getFlags().has("MSU_UID")) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/entity/tactical/entity", function(q) { + q.create = @(__original) function() { - this.MSU_generateUID(); + __original(); + if (!::MSU.Serialization.isLoading()) + { + this.MSU_generateUID(); + } } - else + + q.onDeserialize = @(__original) function( _in ) { - ::MSU.__addToUIDMap(this); + __original(_in); + if (!this.getFlags().has("MSU_UID")) + { + this.MSU_generateUID(); + } + else + { + ::MSU.__addToUIDMap(this); + } } - } + }); }); diff --git a/msu/hooks/entity/tactical/player.nut b/msu/hooks/entity/tactical/player.nut index bc35e38de..862ff8d50 100644 --- a/msu/hooks/entity/tactical/player.nut +++ b/msu/hooks/entity/tactical/player.nut @@ -20,33 +20,37 @@ { return 1.0; } +}); - q.setAttributeLevelUpValues = @(__original) function( _v ) - { - __original(_v); - this.m.LevelUpsSpent++; - } - - q.onHired = @(__original) function() - { - __original(); +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/entity/tactical/player", function(q) { + q.setAttributeLevelUpValues = @(__original) function( _v ) + { + __original(_v); + this.m.LevelUpsSpent++; + } - foreach (bro in ::World.getPlayerRoster().getAll()) + q.onHired = @(__original) function() { - bro.getSkills().onAnyBroHired(this); + __original(); + + foreach (bro in ::World.getPlayerRoster().getAll()) + { + bro.getSkills().onAnyBroHired(this); + } } - } - q.onSerialize = @(__original) function( _out ) - { - this.getFlags().set("LevelUpsSpent", this.m.LevelUpsSpent); - __original(_out); - this.getFlags().remove("LevelUpsSpent"); - } + q.onSerialize = @(__original) function( _out ) + { + this.getFlags().set("LevelUpsSpent", this.m.LevelUpsSpent); + __original(_out); + this.getFlags().remove("LevelUpsSpent"); + } - q.onDeserialize = @(__original) function( _in ) - { - __original(_in); - this.m.LevelUpsSpent = this.getFlags().has("LevelUpsSpent") ? this.getFlags().get("LevelUpsSpent") : 0; - } + q.onDeserialize = @(__original) function( _in ) + { + __original(_in); + this.m.LevelUpsSpent = this.getFlags().has("LevelUpsSpent") ? this.getFlags().get("LevelUpsSpent") : 0; + } + }); }); diff --git a/msu/hooks/entity/world/combat_manager.nut b/msu/hooks/entity/world/combat_manager.nut index bb52b42f4..2a5b87d26 100644 --- a/msu/hooks/entity/world/combat_manager.nut +++ b/msu/hooks/entity/world/combat_manager.nut @@ -1,15 +1,18 @@ -::MSU.MH.hook("scripts/entity/world/combat_manager", function(q) { - /* Compatibility for mods that add factions. At least two areas need to get changed, - combat_manager and getLocalCombatProperties of world_state. The problem is that the - Factions array is initialised with fixed size 32, which is not large enough once - custom factions (or more towns etc) are added. This hook is the cleanest way to - fix combat_manager, so you don't need to overwrite multiple functions instead. */ - q.joinCombat = @(__original) function( _combat, _party ) - { - if (_combat.Factions.len() <= 100) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/entity/world/combat_manager", function(q) { + /* Compatibility for mods that add factions. At least two areas need to get changed, + combat_manager and getLocalCombatProperties of world_state. The problem is that the + Factions array is initialised with fixed size 32, which is not large enough once + custom factions (or more towns etc) are added. This hook is the cleanest way to + fix combat_manager, so you don't need to overwrite multiple functions instead. */ + q.joinCombat = @(__original) function( _combat, _party ) { - _combat.Factions.resize(256, []); + if (_combat.Factions.len() <= 100) + { + _combat.Factions.resize(256, []); + } + return __original(_combat, _party); } - return __original(_combat, _party); - } + }); }); + diff --git a/msu/hooks/entity/world/settlement.nut b/msu/hooks/entity/world/settlement.nut index c5e3f943c..458fb660f 100644 --- a/msu/hooks/entity/world/settlement.nut +++ b/msu/hooks/entity/world/settlement.nut @@ -1,16 +1,18 @@ -::MSU.MH.hook("scripts/entity/world/settlement", function(q) { - q.onEnter = @(__original) function() - { - local ret = __original(); - - if (ret) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/entity/world/settlement", function(q) { + q.onEnter = @(__original) function() { - foreach (bro in ::World.getPlayerRoster().getAll()) + local ret = __original(); + + if (ret) { - bro.getSkills().onEnterSettlement(this); + foreach (bro in ::World.getPlayerRoster().getAll()) + { + bro.getSkills().onEnterSettlement(this); + } } - } - return ret; - } + return ret; + } + }); }); diff --git a/msu/hooks/items/item_container.nut b/msu/hooks/items/item_container.nut index def36386f..7e3c684f2 100644 --- a/msu/hooks/items/item_container.nut +++ b/msu/hooks/items/item_container.nut @@ -68,28 +68,32 @@ this.m.ActionCost = ::Const.Tactical.Settings.SwitchItemAPCost; return ret; } +}); - q.equip = @(__original) function( _item ) - { - local ret = __original(_item); - if (ret == true && !::MSU.isNull(this.m.Actor) && this.m.Actor.isAlive()) this.m.Actor.getSkills().onEquip(_item); - return ret; - } +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/items/item_container", function(q) { + q.equip = @(__original) function( _item ) + { + local ret = __original(_item); + if (ret == true && !::MSU.isNull(this.m.Actor) && this.m.Actor.isAlive()) this.m.Actor.getSkills().onEquip(_item); + return ret; + } - q.unequip = @(__original) function( _item ) - { - if (_item != null && _item != -1 && _item.getCurrentSlotType() != ::Const.ItemSlot.None && _item.getCurrentSlotType() != ::Const.ItemSlot.Bag && !::MSU.isNull(this.m.Actor) && this.m.Actor.isAlive()) + q.unequip = @(__original) function( _item ) { - foreach (item in this.m.Items[_item.getSlotType()]) + if (_item != null && _item != -1 && _item.getCurrentSlotType() != ::Const.ItemSlot.None && _item.getCurrentSlotType() != ::Const.ItemSlot.Bag && !::MSU.isNull(this.m.Actor) && this.m.Actor.isAlive()) { - if (item == _item) + foreach (item in this.m.Items[_item.getSlotType()]) { - this.m.Actor.getSkills().onUnequip(_item); - break; + if (item == _item) + { + this.m.Actor.getSkills().onUnequip(_item); + break; + } } } - } - return __original(_item); - } -}); + return __original(_item); + } + }); +}) diff --git a/msu/hooks/items/shields/shield.nut b/msu/hooks/items/shields/shield.nut index ecb4ecc78..b17e2f9ef 100644 --- a/msu/hooks/items/shields/shield.nut +++ b/msu/hooks/items/shields/shield.nut @@ -1,18 +1,20 @@ -::MSU.MH.hook("scripts/items/shields/shield", function(q) { - q.addSkill = @(__original) function( _skill ) - { - __original(_skill); - if (_skill.isType(::Const.SkillType.Active)) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/items/shields/shield", function(q) { + q.addSkill = @(__original) function( _skill ) { - // We reset the FatigueCost so any modifications to it from other skills is reverted - // the latter part is a copy of the vanilla code applying FatigueOnSkillUse - // which we then include in the skill's base fatigue cost - _skill.resetField("FatigueCost"); - local fatigueOnSkillUse = this.getContainer().getActor().getCurrentProperties().IsProficientWithHeavyWeapons && this.m.FatigueOnSkillUse > 0 ? 0 : this.m.FatigueOnSkillUse; - local fatCost = ::Math.max(0, _skill.getFatigueCostRaw() + fatigueOnSkillUse); - _skill.setFatigueCost(::Math.max(0, fatCost)); - _skill.setBaseValue("FatigueCost", fatCost); - this.getContainer().getActor().getSkills().update(); + __original(_skill); + if (_skill.isType(::Const.SkillType.Active)) + { + // We reset the FatigueCost so any modifications to it from other skills is reverted + // the latter part is a copy of the vanilla code applying FatigueOnSkillUse + // which we then include in the skill's base fatigue cost + _skill.resetField("FatigueCost"); + local fatigueOnSkillUse = this.getContainer().getActor().getCurrentProperties().IsProficientWithHeavyWeapons && this.m.FatigueOnSkillUse > 0 ? 0 : this.m.FatigueOnSkillUse; + local fatCost = ::Math.max(0, _skill.getFatigueCostRaw() + fatigueOnSkillUse); + _skill.setFatigueCost(::Math.max(0, fatCost)); + _skill.setBaseValue("FatigueCost", fatCost); + this.getContainer().getActor().getSkills().update(); + } } - } + }); }); diff --git a/msu/hooks/items/weapons/weapon.nut b/msu/hooks/items/weapons/weapon.nut index 692ef53b3..ab22c32a5 100644 --- a/msu/hooks/items/weapons/weapon.nut +++ b/msu/hooks/items/weapons/weapon.nut @@ -1,11 +1,3 @@ -::MSU.MH.hookTree("scripts/items/weapons/weapon", function(q) { - q.create = @(__original) function() - { - __original(); - this.initWeaponType(); - } -}); - ::MSU.MH.hook("scripts/items/weapons/weapon", function(q) { q.m.WeaponType <- ::Const.Items.WeaponType.None; q.m.MSU_WeaponTypeInit <- false; @@ -20,30 +12,6 @@ } } - q.addSkill = @(__original) function( _skill ) - { - local ret = __original(_skill); - if (::MSU.isIn("AdditionalAccuracy", _skill.m, true)) - { - _skill.resetField("AdditionalAccuracy"); - _skill.m.AdditionalAccuracy += this.m.AdditionalAccuracy; - _skill.setBaseValue("AdditionalAccuracy", _skill.m.AdditionalAccuracy); - } - if (_skill.isType(::Const.SkillType.Active)) - { - // We reset the FatigueCost so any modifications to it from other skills is reverted - // the latter part is a copy of the vanilla code applying FatigueOnSkillUse - // which we then include in the skill's base fatigue cost (so that orc weapon skills get the proper fatigue cost) - _skill.resetField("FatigueCost"); - local fatigueOnSkillUse = this.getContainer().getActor().getCurrentProperties().IsProficientWithHeavyWeapons && this.m.FatigueOnSkillUse > 0 ? 0 : this.m.FatigueOnSkillUse; - local fatCost = ::Math.max(0, _skill.getFatigueCostRaw() + fatigueOnSkillUse); - _skill.setFatigueCost(fatCost); - _skill.setBaseValue("FatigueCost", fatCost); - this.getContainer().getActor().getSkills().update(); - } - return ret; - } - q.buildWeaponTypeFromCategories <- function() { this.m.WeaponType = ::Const.Items.WeaponType.None; @@ -171,3 +139,39 @@ } } }); + +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hookTree("scripts/items/weapons/weapon", function(q) { + q.create = @(__original) function() + { + __original(); + this.initWeaponType(); + } + }); + + ::MSU.MH.hook("scripts/items/weapons/weapon", function(q) { + q.addSkill = @(__original) function( _skill ) + { + local ret = __original(_skill); + if (::MSU.isIn("AdditionalAccuracy", _skill.m, true)) + { + _skill.resetField("AdditionalAccuracy"); + _skill.m.AdditionalAccuracy += this.m.AdditionalAccuracy; + _skill.setBaseValue("AdditionalAccuracy", _skill.m.AdditionalAccuracy); + } + if (_skill.isType(::Const.SkillType.Active)) + { + // We reset the FatigueCost so any modifications to it from other skills is reverted + // the latter part is a copy of the vanilla code applying FatigueOnSkillUse + // which we then include in the skill's base fatigue cost (so that orc weapon skills get the proper fatigue cost) + _skill.resetField("FatigueCost"); + local fatigueOnSkillUse = this.getContainer().getActor().getCurrentProperties().IsProficientWithHeavyWeapons && this.m.FatigueOnSkillUse > 0 ? 0 : this.m.FatigueOnSkillUse; + local fatCost = ::Math.max(0, _skill.getFatigueCostRaw() + fatigueOnSkillUse); + _skill.setFatigueCost(fatCost); + _skill.setBaseValue("FatigueCost", fatCost); + this.getContainer().getActor().getSkills().update(); + } + return ret; + } + }); +}); diff --git a/msu/hooks/skills/skill.nut b/msu/hooks/skills/skill.nut index ada8a59a7..386795960 100644 --- a/msu/hooks/skills/skill.nut +++ b/msu/hooks/skills/skill.nut @@ -1,40 +1,3 @@ -::MSU.MH.hookTree("scripts/skills/skill", function(q) { - if (!q.contains("create")) - return; - - q.create = @(__original) function() - { - if (this.m.DamageType == null) - { - this.m.DamageType = ::MSU.Class.DamageType(); - this.m.DamageType.setSkill(this); - } - - __original(); - - this.m.DamageType.doInit(); - } -}); - -::MSU.QueueBucket.VeryLate.push(function() { - ::MSU.MH.hookTree("scripts/skills/skill", function(q) { - if (::Hooks.getMod("vanilla").getVersion() >= ::Hooks.SQClass.ModVersion("1.5.1-4")) - { - q.onUpdate = @(__original) function( _properties ) - { - __original(_properties); - this.__MSU_redirectSkillCostAdjustments(_properties.SkillCostAdjustments); - } - - q.onAfterUpdate = @(__original) function( _properties ) - { - __original(_properties); - this.__MSU_redirectSkillCostAdjustments(_properties.SkillCostAdjustments); - } - } - }); -}); - ::MSU.MH.hook("scripts/skills/skill", function(q) { q.m.AIBehaviorID <- null; q.m.DamageType <- null; @@ -220,36 +183,6 @@ return true; } - // TODO: Should probably switch to a hookTree on `onAdded` in VeryLateBucket - q.setContainer = @(__original) function( _c ) - { - if (_c == null) - { - if (this.m.AIBehaviorID != null && !::MSU.isNull(this.getContainer())) - { - local agent = this.getContainer().getActor().getAIAgent(); - local activeBehavior = agent.m.ActiveBehavior; - if (activeBehavior != null && activeBehavior.getID() == this.m.AIBehaviorID) agent.m.MSU_BehaviorToRemove = activeBehavior; - else agent.removeBehaviorByStack(this.m.AIBehaviorID); - } - - return __original(_c); - } - - this.saveBaseValues(); - __original(_c); - - if (this.m.AIBehaviorID != null && !::MSU.isNull(this.getContainer().getActor())) - { - local agent = this.getContainer().getActor().getAIAgent(); - if (!::MSU.isNull(agent) && agent.getID() != ::Const.AI.Agent.ID.Player) - { - agent.addBehavior(::new(::MSU.AI.getBehaviorScriptFromID(this.m.AIBehaviorID))); - agent.finalizeBehaviors(); - } - } - } - q.onMovementStarted <- function( _tile, _numTiles ) { } @@ -348,23 +281,6 @@ ::MSU.Skills.modifyPreview(this, null, _field, _newChange, _multiplicative); } - q.use = @(__original) function( _targetTile, _forFree = false ) - { - // Save the container as a local variable because some skills delete - // themselves during use (e.g. Reload Bolt) causing this.m.Container - // to point to null. - local container = this.m.Container; - local targetEntity = _targetTile.IsOccupiedByActor ? _targetTile.getEntity() : null; - - container.onBeforeAnySkillExecuted(this, _targetTile, targetEntity, _forFree); - - local ret = __original(_targetTile, _forFree); - - container.onAnySkillExecuted(this, _targetTile, targetEntity, _forFree); - - return ret; - } - q.getDamageType <- function() { return this.m.DamageType; @@ -413,23 +329,6 @@ return ret; } - q.getHitFactors = @(__original) function( _targetTile ) - { - local ret = __original(_targetTile); - if (::MSU.Mod.ModSettings.getSetting("ExpandedSkillTooltips").getValue() && ::MSU.isIn("AdditionalAccuracy", this.m, true) && this.m.AdditionalAccuracy != 0) - { - local payload = { - icon = this.m.AdditionalAccuracy > 0 ? "ui/tooltips/positive.png" : "ui/tooltips/negative.png", - text = this.getName() - }; - - if (this.m.AdditionalAccuracy > 0) ret.insert(0, payload); - else ret.push(payload); - } - this.getContainer().onGetHitFactors(this, _targetTile, ret); - return ret; - } - q.getRangedTooltip <- function( _tooltip = null ) { if (_tooltip == null) _tooltip = []; @@ -490,7 +389,104 @@ }); ::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hookTree("scripts/skills/skill", function(q) { + if (::Hooks.getMod("vanilla").getVersion() >= ::Hooks.SQClass.ModVersion("1.5.1-4")) + { + q.onUpdate = @(__original) function( _properties ) + { + __original(_properties); + this.__MSU_redirectSkillCostAdjustments(_properties.SkillCostAdjustments); + } + + q.onAfterUpdate = @(__original) function( _properties ) + { + __original(_properties); + this.__MSU_redirectSkillCostAdjustments(_properties.SkillCostAdjustments); + } + } + + if (q.contains("create")) + { + q.create = @(__original) function() + { + if (this.m.DamageType == null) + { + this.m.DamageType = ::MSU.Class.DamageType(); + this.m.DamageType.setSkill(this); + } + + __original(); + + this.m.DamageType.doInit(); + } + } + }); + ::MSU.MH.hook("scripts/skills/skill", function(q) { + // TODO: Should probably switch to a hookTree on `onAdded` in VeryLateBucket + q.setContainer = @(__original) function( _c ) + { + if (_c == null) + { + if (this.m.AIBehaviorID != null && !::MSU.isNull(this.getContainer())) + { + local agent = this.getContainer().getActor().getAIAgent(); + local activeBehavior = agent.m.ActiveBehavior; + if (activeBehavior != null && activeBehavior.getID() == this.m.AIBehaviorID) agent.m.MSU_BehaviorToRemove = activeBehavior; + else agent.removeBehaviorByStack(this.m.AIBehaviorID); + } + + return __original(_c); + } + + this.saveBaseValues(); + __original(_c); + + if (this.m.AIBehaviorID != null && !::MSU.isNull(this.getContainer().getActor())) + { + local agent = this.getContainer().getActor().getAIAgent(); + if (!::MSU.isNull(agent) && agent.getID() != ::Const.AI.Agent.ID.Player) + { + agent.addBehavior(::new(::MSU.AI.getBehaviorScriptFromID(this.m.AIBehaviorID))); + agent.finalizeBehaviors(); + } + } + } + + q.use = @(__original) function( _targetTile, _forFree = false ) + { + // Save the container as a local variable because some skills delete + // themselves during use (e.g. Reload Bolt) causing this.m.Container + // to point to null. + local container = this.m.Container; + local targetEntity = _targetTile.IsOccupiedByActor ? _targetTile.getEntity() : null; + + container.onBeforeAnySkillExecuted(this, _targetTile, targetEntity, _forFree); + + local ret = __original(_targetTile, _forFree); + + container.onAnySkillExecuted(this, _targetTile, targetEntity, _forFree); + + return ret; + } + + q.getHitFactors = @(__original) function( _targetTile ) + { + local ret = __original(_targetTile); + if (::MSU.Mod.ModSettings.getSetting("ExpandedSkillTooltips").getValue() && ::MSU.isIn("AdditionalAccuracy", this.m, true) && this.m.AdditionalAccuracy != 0) + { + local payload = { + icon = this.m.AdditionalAccuracy > 0 ? "ui/tooltips/positive.png" : "ui/tooltips/negative.png", + text = this.getName() + }; + + if (this.m.AdditionalAccuracy > 0) ret.insert(0, payload); + else ret.push(payload); + } + this.getContainer().onGetHitFactors(this, _targetTile, ret); + return ret; + } + foreach (func in ::MSU.Skills.PreviewApplicableFunctions) { q[func] = @(__original) function() diff --git a/msu/hooks/states/main_menu_state.nut b/msu/hooks/states/main_menu_state.nut index ee7053578..702945242 100644 --- a/msu/hooks/states/main_menu_state.nut +++ b/msu/hooks/states/main_menu_state.nut @@ -2,13 +2,6 @@ q.m.ModSettingsShown <- false; q.m.TempSettings <- null; - q.onInit = @(__original) function() - { - __original(); - local mainMenuModule = this.m.MainMenuScreen.getMainMenuModule(); - mainMenuModule.setOnModOptionsPressedListener(this.main_menu_module_onModOptionsPressed.bindenv(this)); - } - q.main_menu_module_onModOptionsPressed <- function() { ::MSU.SettingsScreen.setOnCancelPressedListener(this.msu_settings_screen_onCancelPressed.bindenv(this)); // Need to bind these every time because it's a new screen and not a module (which tbh was probs a mistake). @@ -25,31 +18,6 @@ }); } - q.campaign_menu_module_onStartPressed = @(__original) function( _settings ) - { - this.m.TempSettings = _settings; - if (this.m.ModSettingsShown || !::MSU.System.ModSettings.isVisibleWithFlags(::MSU.SettingsFlags.NewCampaign)) - { - __original(_settings); - } - else - { - this.m.ModSettingsShown = true; - ::MSU.SettingsScreen.setOnCancelPressedListener(this.msu_settings_screen_onCancelPressed.bindenv(this)); - ::MSU.SettingsScreen.setOnSavePressedListener(this.msu_settings_screen_onSavepressed.bindenv(this)); - this.m.MainMenuScreen.hideNewCampaignModule(); - ::MSU.SettingsScreen.show(::MSU.SettingsFlags.NewCampaign); - this.m.MenuStack.push(function () - { - ::MSU.SettingsScreen.hide(); - this.m.MainMenuScreen.showNewCampaignModule(); - }, function () - { - return !::MSU.SettingsScreen.isAnimating(); - }) - } - } - q.msu_settings_screen_onCancelPressed <- function() { this.m.ModSettingsShown = false; @@ -67,30 +35,66 @@ this.m.ModSettingsShown = false; } } +}); - q.onKeyInput = @(__original) function( _key ) - { - if (!::MSU.Key.isKnownKey(_key)) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/states/main_menu_state", function(q) { + q.onInit = @(__original) function() { - return __original(_key); + __original(); + local mainMenuModule = this.m.MainMenuScreen.getMainMenuModule(); + mainMenuModule.setOnModOptionsPressedListener(this.main_menu_module_onModOptionsPressed.bindenv(this)); } - if (::MSU.System.Keybinds.onKeyInput(_key, this, ::MSU.Key.State.MainMenu) || ::MSU.Mod.ModSettings.getSetting("SuppressBaseKeybinds").getValue()) + + q.campaign_menu_module_onStartPressed = @(__original) function( _settings ) { - return false; + this.m.TempSettings = _settings; + if (this.m.ModSettingsShown || !::MSU.System.ModSettings.isVisibleWithFlags(::MSU.SettingsFlags.NewCampaign)) + { + __original(_settings); + } + else + { + this.m.ModSettingsShown = true; + ::MSU.SettingsScreen.setOnCancelPressedListener(this.msu_settings_screen_onCancelPressed.bindenv(this)); + ::MSU.SettingsScreen.setOnSavePressedListener(this.msu_settings_screen_onSavepressed.bindenv(this)); + this.m.MainMenuScreen.hideNewCampaignModule(); + ::MSU.SettingsScreen.show(::MSU.SettingsFlags.NewCampaign); + this.m.MenuStack.push(function () + { + ::MSU.SettingsScreen.hide(); + this.m.MainMenuScreen.showNewCampaignModule(); + }, function () + { + return !::MSU.SettingsScreen.isAnimating(); + }) + } } - return __original(_key); - } - q.onMouseInput = @(__original) function( _mouse ) - { - if (!::MSU.Key.isKnownMouse(_mouse)) + q.onKeyInput = @(__original) function( _key ) { - return __original(_mouse); + if (!::MSU.Key.isKnownKey(_key)) + { + return __original(_key); + } + if (::MSU.System.Keybinds.onKeyInput(_key, this, ::MSU.Key.State.MainMenu) || ::MSU.Mod.ModSettings.getSetting("SuppressBaseKeybinds").getValue()) + { + return false; + } + return __original(_key); } - if (::MSU.System.Keybinds.onMouseInput(_mouse, this, ::MSU.Key.State.MainMenu)) + + q.onMouseInput = @(__original) function( _mouse ) { - return false; + if (!::MSU.Key.isKnownMouse(_mouse)) + { + return __original(_mouse); + } + if (::MSU.System.Keybinds.onMouseInput(_mouse, this, ::MSU.Key.State.MainMenu)) + { + return false; + } + return __original(_mouse); } - return __original(_mouse); - } + }); }); diff --git a/msu/hooks/states/state.nut b/msu/hooks/states/state.nut index a29993c28..f77fd8442 100644 --- a/msu/hooks/states/state.nut +++ b/msu/hooks/states/state.nut @@ -1,7 +1,9 @@ -::MSU.MH.hookTree("scripts/states/state", function(q) { - q.onInit = @(__original) function() - { - ::MSU.Utils.States[this.ClassName] <- ::WeakTableRef(this); - return __original(); - } +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hookTree("scripts/states/state", function(q) { + q.onInit = @(__original) function() + { + ::MSU.Utils.States[this.ClassName] <- ::WeakTableRef(this); + return __original(); + } + }); }); diff --git a/msu/hooks/states/tactical_state.nut b/msu/hooks/states/tactical_state.nut index 299ab8c2b..002583557 100644 --- a/msu/hooks/states/tactical_state.nut +++ b/msu/hooks/states/tactical_state.nut @@ -1,23 +1,4 @@ ::MSU.MH.hook("scripts/states/tactical_state", function(q) { - q.executeEntityTravel = @(__original) function( _activeEntity, _mouseEvent ) - { - _activeEntity.getSkills().m.IsPreviewing = false; - return __original(_activeEntity, _mouseEvent); - } - - q.executeEntitySkill = @(__original) function( _activeEntity, _targetTile ) - { - _activeEntity.getSkills().m.IsPreviewing = false; - return __original(_activeEntity, _targetTile); - } - - q.onInitUI = @(__original) function() - { - __original(); - local mainMenuModule = this.m.TacticalMenuScreen.getMainMenuModule(); - mainMenuModule.setOnModOptionsPressedListener(this.main_menu_module_onModOptionsPressed.bindenv(this)); - } - q.main_menu_module_onModOptionsPressed <- function() { ::MSU.SettingsScreen.setOnCancelPressedListener(this.msu_settings_screen_onCancelPressed.bindenv(this)); @@ -46,30 +27,53 @@ ::MSU.System.ModSettings.updateSettingsFromJS(_data); this.m.MenuStack.pop(); } +}); - q.onKeyInput = @(__original) function( _key ) - { - if (!::MSU.Key.isKnownKey(_key)) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/states/tactical_state", function(q) { + q.onInitUI = @(__original) function() { - return __original(_key); + __original(); + local mainMenuModule = this.m.TacticalMenuScreen.getMainMenuModule(); + mainMenuModule.setOnModOptionsPressedListener(this.main_menu_module_onModOptionsPressed.bindenv(this)); } - if (::MSU.System.Keybinds.onKeyInput(_key, this, ::MSU.Key.State.Tactical) || ::MSU.Mod.ModSettings.getSetting("SuppressBaseKeybinds").getValue()) + + q.executeEntityTravel = @(__original) function( _activeEntity, _mouseEvent ) { - return false; + _activeEntity.getSkills().m.IsPreviewing = false; + return __original(_activeEntity, _mouseEvent); } - return __original(_key); - } - q.onMouseInput = @(__original) function( _mouse ) - { - if (!::MSU.Key.isKnownMouse(_mouse)) + q.executeEntitySkill = @(__original) function( _activeEntity, _targetTile ) { - return __original(_mouse); + _activeEntity.getSkills().m.IsPreviewing = false; + return __original(_activeEntity, _targetTile); } - if (::MSU.System.Keybinds.onMouseInput(_mouse, this, ::MSU.Key.State.Tactical)) + + q.onKeyInput = @(__original) function( _key ) { - return false; + if (!::MSU.Key.isKnownKey(_key)) + { + return __original(_key); + } + if (::MSU.System.Keybinds.onKeyInput(_key, this, ::MSU.Key.State.Tactical) || ::MSU.Mod.ModSettings.getSetting("SuppressBaseKeybinds").getValue()) + { + return false; + } + return __original(_key); } - return __original(_mouse); - } + + q.onMouseInput = @(__original) function( _mouse ) + { + if (!::MSU.Key.isKnownMouse(_mouse)) + { + return __original(_mouse); + } + if (::MSU.System.Keybinds.onMouseInput(_mouse, this, ::MSU.Key.State.Tactical)) + { + return false; + } + return __original(_mouse); + } + }); }); diff --git a/msu/hooks/states/world/asset_manager.nut b/msu/hooks/states/world/asset_manager.nut index e7955a2a4..0c881033c 100644 --- a/msu/hooks/states/world/asset_manager.nut +++ b/msu/hooks/states/world/asset_manager.nut @@ -1,25 +1,5 @@ ::MSU.MH.hook("scripts/states/world/asset_manager", function(q) { q.m.LastDayMorningEventCalled <- 0; - q.update = @(__original) function( _worldState ) - { - if (::World.getTime().Hours == 1 && ::World.getTime().Hours != this.m.LastHourUpdated && ::World.getTime().Days > this.m.LastDayMorningEventCalled) - { - this.m.LastDayMorningEventCalled = ::World.getTime().Days; - local roster = ::World.getPlayerRoster().getAll(); - foreach (bro in roster) - { - bro.getSkills().onNewMorning(); - } - ::World.Assets.getOrigin().onNewMorning(); - } - - if (::World.getTime().Days > this.m.LastDayPaid && ::World.getTime().Hours > 8 && this.m.IsConsumingAssets) - { - ::World.Assets.getOrigin().onNewDay(); - } - - return __original(_worldState); - } q.getLastDayMorningEventCalled <- function() { @@ -31,3 +11,28 @@ this.m.LastDayMorningEventCalled = _day; } }); + +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/states/world/asset_manager", function(q) { + q.update = @(__original) function( _worldState ) + { + if (::World.getTime().Hours == 1 && ::World.getTime().Hours != this.m.LastHourUpdated && ::World.getTime().Days > this.m.LastDayMorningEventCalled) + { + this.m.LastDayMorningEventCalled = ::World.getTime().Days; + local roster = ::World.getPlayerRoster().getAll(); + foreach (bro in roster) + { + bro.getSkills().onNewMorning(); + } + ::World.Assets.getOrigin().onNewMorning(); + } + + if (::World.getTime().Days > this.m.LastDayPaid && ::World.getTime().Hours > 8 && this.m.IsConsumingAssets) + { + ::World.Assets.getOrigin().onNewDay(); + } + + return __original(_worldState); + } + }); +}); diff --git a/msu/hooks/states/world_state.nut b/msu/hooks/states/world_state.nut index 98a40d5c1..f247134d7 100644 --- a/msu/hooks/states/world_state.nut +++ b/msu/hooks/states/world_state.nut @@ -1,11 +1,4 @@ ::MSU.MH.hook("scripts/states/world_state", function(q) { - q.onInitUI = @(__original) function() - { - __original(); - local mainMenuModule = this.m.WorldMenuScreen.getMainMenuModule(); - mainMenuModule.setOnModOptionsPressedListener(this.main_menu_module_onModOptionsPressed.bindenv(this)); - } - q.main_menu_module_onModOptionsPressed <- function() { ::MSU.SettingsScreen.setOnCancelPressedListener(this.msu_settings_screen_onCancelPressed.bindenv(this)); @@ -186,178 +179,168 @@ return properties; } +}); - q.loadCampaign = @(__original) function( _campaignFileName ) - { - __original(_campaignFileName); - local time = ::World.getTime(); - ::logInfo(format("MSU -- Current campaign length: %i Days, %i Hours, %i Minutes. (TimeOfDay: %i, SecondsOfDay: %f)", time.Days, time.Hours, time.Minutes, time.TimeOfDay, time.SecondsOfDay)); - } +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/states/world_state", function(q) { + q.onInitUI = @(__original) function() + { + __original(); + local mainMenuModule = this.m.WorldMenuScreen.getMainMenuModule(); + mainMenuModule.setOnModOptionsPressedListener(this.main_menu_module_onModOptionsPressed.bindenv(this)); + } - q.onBeforeSerialize = @(__original) function( _out ) - { - __original(_out); - local meta = _out.getMetaData(); - local modIDsString = ""; - foreach (mod in ::MSU.System.Serialization.Mods) + q.onKeyInput = @(__original) function( _key ) { - meta.setString(mod.getID() + "Version", mod.getVersionString()); - ::MSU.Mod.Debug.printLog(format("MSU Serialization: Saving %s (%s), Version: %s", mod.getName(), mod.getID(), mod.getVersionString())); + if (!::MSU.Key.isKnownKey(_key)) + { + return __original(_key); + } + if (::MSU.System.Keybinds.onKeyInput(_key, this, ::MSU.Key.State.World) || ::MSU.Mod.ModSettings.getSetting("SuppressBaseKeybinds").getValue()) + { + return false; + } + return __original(_key); } - foreach (mod in ::Hooks.getMods()) modIDsString += mod.getID() + ","; - meta.setString("MSU.SavedModIDs", modIDsString.slice(0, -1)); - } - q.onBeforeDeserialize = @(__original) function( _in ) - { - __original(_in); + q.onMouseInput = @(__original) function( _mouse ) + { + if (!::MSU.Key.isKnownMouse(_mouse)) + { + return __original(_mouse); + } + if (::MSU.System.Keybinds.onMouseInput(_mouse, this, ::MSU.Key.State.World)) + { + return false; + } + return __original(_mouse); + } - if (::MSU.Mod.Serialization.isSavedVersionAtLeast("1.1.0", _in.getMetaData())) + q.onBeforeSerialize = @(__original) function( _out ) { - local modIDs = split(_in.getMetaData().getString("MSU.SavedModIDs"), ","); - local hooksMods = ::Hooks.getMods(); - foreach (mod in hooksMods) + ::MSU.System.Serialization.SerializationMetaData = _out.getMetaData(); + ::MSU.System.Serialization.IsDuringOnBeforeSerialize = true; + __original(_out); + ::MSU.System.Serialization.IsDuringOnBeforeSerialize = false; + local meta = _out.getMetaData(); + local modIDsString = ""; + foreach (mod in ::MSU.System.Serialization.Mods) + { + meta.setString(mod.getID() + "Version", mod.getVersionString()); + ::MSU.Mod.Debug.printLog(format("MSU Serialization: Saving %s (%s), Version: %s", mod.getName(), mod.getID(), mod.getVersionString())); + } + foreach (mod in ::Hooks.getMods()) modIDsString += mod.getID() + ","; + meta.setString("MSU.SavedModIDs", modIDsString.slice(0, -1)); + } + + q.onBeforeDeserialize = @(__original) function( _in ) + { + ::MSU.System.Serialization.DeserializationMetaData = _in.getMetaData(); + __original(_in); + + if (::MSU.Mod.Serialization.isSavedVersionAtLeast("1.1.0", _in.getMetaData())) { - local IDIdx = modIDs.find(mod.getID()); - if (IDIdx != null) + local modIDs = split(_in.getMetaData().getString("MSU.SavedModIDs"), ","); + local hooksMods = ::Hooks.getMods(); + foreach (mod in hooksMods) { - modIDs.remove(IDIdx); - if (::MSU.System.Registry.hasMod(mod.getID())) + local IDIdx = modIDs.find(mod.getID()); + if (IDIdx != null) { - local oldVersion = _in.getMetaData().getString(mod.getID() + "Version"); - if (oldVersion == "") - { - ::logInfo(format("MSU Serialization: First time this save has been loaded with an MSU version of %s (%s)", mod.getName(), mod.getID())); - } - else + modIDs.remove(IDIdx); + if (::MSU.System.Registry.hasMod(mod.getID())) { - local msuMod = ::MSU.System.Registry.getMod(mod.getID()); - switch (::MSU.SemVer.compare(msuMod, ::MSU.SemVer.getTable(oldVersion))) + local oldVersion = _in.getMetaData().getString(mod.getID() + "Version"); + if (oldVersion == "") { - case 1: - ::logInfo(format("MSU Serialization: Loading old save for %s (%s), %s -> %s", msuMod.getName(), msuMod.getID(), oldVersion, msuMod.getVersionString())); - break; - case 0: - ::MSU.Mod.Debug.printLog(format("MSU Serialization: Loading %s (%s), version %s", msuMod.getName(), msuMod.getID(), msuMod.getVersionString())); - break; - case -1: - ::logWarning(format("MSU Serialization: Loading save from newer version for %s (%s), %s -> %s", msuMod.getName(), msuMod.getID(), oldVersion, msuMod.getVersionString())); - break; + ::logInfo(format("MSU Serialization: First time this save has been loaded with an MSU version of %s (%s)", mod.getName(), mod.getID())); } - } - } // else hooks mod loaded that already existed in save + else + { + local msuMod = ::MSU.System.Registry.getMod(mod.getID()); + switch (::MSU.SemVer.compare(msuMod, ::MSU.SemVer.getTable(oldVersion))) + { + case 1: + ::logInfo(format("MSU Serialization: Loading old save for %s (%s), %s -> %s", msuMod.getName(), msuMod.getID(), oldVersion, msuMod.getVersionString())); + break; + case 0: + ::MSU.Mod.Debug.printLog(format("MSU Serialization: Loading %s (%s), version %s", msuMod.getName(), msuMod.getID(), msuMod.getVersionString())); + break; + case -1: + ::logWarning(format("MSU Serialization: Loading save from newer version for %s (%s), %s -> %s", msuMod.getName(), msuMod.getID(), oldVersion, msuMod.getVersionString())); + break; + } + } + } // else hooks mod loaded that already existed in save + } + else + { + ::logWarning(format("MSU Serialization: First time this save is being loaded with %s (%s)", mod.getName(), mod.getID())); + } } - else + + foreach (id in modIDs) { - ::logWarning(format("MSU Serialization: First time this save is being loaded with %s (%s)", mod.getName(), mod.getID())); + ::logWarning(format("MSU Serialization: This save was made while using %s but is being loaded without it.", id)); } } - - foreach (id in modIDs) + else // pre 1.1.0 legacy save support (should be removed in the future) { - ::logWarning(format("MSU Serialization: This save was made while using %s but is being loaded without it.", id)); - } - } - else // pre 1.1.0 legacy save support (should be removed in the future) - { - foreach (mod in ::MSU.System.Serialization.Mods) - { - local oldVersion = _in.getMetaData().getString(mod.getID() + "Version"); - if (oldVersion == "") - { - ::logInfo(format("MSU Serialization: First time loading this save with %s (%s)", mod.getName(), mod.getID())); - } - else + foreach (mod in ::MSU.System.Serialization.Mods) { - switch (::MSU.SemVer.compare(mod, ::MSU.SemVer.getTable(oldVersion))) + local oldVersion = _in.getMetaData().getString(mod.getID() + "Version"); + if (oldVersion == "") { - case 1: - ::logInfo(format("MSU Serialization: Loading old save for %s (%s), %s -> %s", mod.getName(), mod.getID(), oldVersion, mod.getVersionString())); - break; - case 0: - ::MSU.Mod.Debug.printLog(format("MSU Serialization: Loading %s (%s), version %s", mod.getName(), mod.getID(), mod.getVersionString())); - break; - case -1: - ::logWarning(format("MSU Serialization: Loading save from newer version for %s (%s), %s -> %s", mod.getName(), mod.getID(), oldVersion, mod.getVersionString())); - break; - default: - ::logError("Something has gone very wrong with MSU Serialization"); - ::MSU.Log.printStackTrace(); + ::logInfo(format("MSU Serialization: First time loading this save with %s (%s)", mod.getName(), mod.getID())); + } + else + { + switch (::MSU.SemVer.compare(mod, ::MSU.SemVer.getTable(oldVersion))) + { + case 1: + ::logInfo(format("MSU Serialization: Loading old save for %s (%s), %s -> %s", mod.getName(), mod.getID(), oldVersion, mod.getVersionString())); + break; + case 0: + ::MSU.Mod.Debug.printLog(format("MSU Serialization: Loading %s (%s), version %s", mod.getName(), mod.getID(), mod.getVersionString())); + break; + case -1: + ::logWarning(format("MSU Serialization: Loading save from newer version for %s (%s), %s -> %s", mod.getName(), mod.getID(), oldVersion, mod.getVersionString())); + break; + default: + ::logError("Something has gone very wrong with MSU Serialization"); + ::MSU.Log.printStackTrace(); + } } } } } - } - - q.onSerialize = @(__original) function( _out ) - { - ::MSU.System.ModSettings.flagSerialize(_out); - ::World.Flags.set("MSU.LastDayMorningEventCalled", ::World.Assets.getLastDayMorningEventCalled()); - ::World.Flags.set("MSU_LastUID", ::MSU.Utils.UID); - __original(_out); - ::MSU.System.Serialization.clearFlags(); - } - - q.onDeserialize = @(__original) function( _in ) - { - __original(_in); - if (::World.Flags.has("MSU.LastDayMorningEventCalled")) - { - ::World.Assets.setLastDayMorningEventCalled(::World.Flags.get("MSU.LastDayMorningEventCalled")); - } - else - { - ::World.Assets.setLastDayMorningEventCalled(::World.getTime().Days); - } - if (::World.Flags.has("MSU_LastUID")) - { - ::MSU.Utils.UID = ::World.Flags.get("MSU_LastUID"); - } - ::MSU.System.ModSettings.flagDeserialize(_in); - ::MSU.System.Serialization.clearFlags(); - } - - q.onKeyInput = @(__original) function( _key ) - { - if (!::MSU.Key.isKnownKey(_key)) - { - return __original(_key); - } - if (::MSU.System.Keybinds.onKeyInput(_key, this, ::MSU.Key.State.World) || ::MSU.Mod.ModSettings.getSetting("SuppressBaseKeybinds").getValue()) - { - return false; - } - return __original(_key); - } - - q.onMouseInput = @(__original) function( _mouse ) - { - if (!::MSU.Key.isKnownMouse(_mouse)) - { - return __original(_mouse); - } - if (::MSU.System.Keybinds.onMouseInput(_mouse, this, ::MSU.Key.State.World)) - { - return false; - } - return __original(_mouse); - } -}); -::MSU.QueueBucket.VeryLate.push(function() { - ::MSU.MH.hook("scripts/states/world_state", function(q) { - q.onBeforeSerialize = @(__original) function( _out ) + q.onSerialize = @(__original) function( _out ) { - ::MSU.System.Serialization.SerializationMetaData = _out.getMetaData(); - ::MSU.System.Serialization.IsDuringOnBeforeSerialize = true; + ::MSU.System.ModSettings.flagSerialize(_out); + ::World.Flags.set("MSU.LastDayMorningEventCalled", ::World.Assets.getLastDayMorningEventCalled()); + ::World.Flags.set("MSU_LastUID", ::MSU.Utils.UID); __original(_out); - ::MSU.System.Serialization.IsDuringOnBeforeSerialize = false; + ::MSU.System.Serialization.clearFlags(); } - q.onBeforeDeserialize = @(__original) function( _in ) + q.onDeserialize = @(__original) function( _in ) { - ::MSU.System.Serialization.DeserializationMetaData = _in.getMetaData(); __original(_in); + if (::World.Flags.has("MSU.LastDayMorningEventCalled")) + { + ::World.Assets.setLastDayMorningEventCalled(::World.Flags.get("MSU.LastDayMorningEventCalled")); + } + else + { + ::World.Assets.setLastDayMorningEventCalled(::World.getTime().Days); + } + if (::World.Flags.has("MSU_LastUID")) + { + ::MSU.Utils.UID = ::World.Flags.get("MSU_LastUID"); + } + ::MSU.System.ModSettings.flagDeserialize(_in); + ::MSU.System.Serialization.clearFlags(); } q.saveCampaign = @(__original) function( _campaignFileName, _campaignLabel = null ) @@ -377,6 +360,9 @@ __original(_campaignFileName); ::MSU.Serialization.IsLoading = false; ::MSU.System.Serialization.DeserializationMetaData = null; + + local time = ::World.getTime(); + ::logInfo(format("MSU -- Current campaign length: %i Days, %i Hours, %i Minutes. (TimeOfDay: %i, SecondsOfDay: %f)", time.Days, time.Hours, time.Minutes, time.TimeOfDay, time.SecondsOfDay)); } }); }); diff --git a/msu/hooks/ui/global/data_helper.nut b/msu/hooks/ui/global/data_helper.nut index 1218bc88c..bb22003e6 100644 --- a/msu/hooks/ui/global/data_helper.nut +++ b/msu/hooks/ui/global/data_helper.nut @@ -1,14 +1,16 @@ -::MSU.MH.hook("scripts/ui/global/data_helper", function(q) { - q.convertCampaignStoragesToUIData = @( __original ) function() - { - local queryStorages = ::PersistenceManager.queryStorages; - ::PersistenceManager.queryStorages = function() +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/ui/global/data_helper", function(q) { + q.convertCampaignStoragesToUIData = @( __original ) function() { - return queryStorages().filter(@(_, _v) !::MSU.String.startsWith(_v.getFileName(), ::MSU.System.PersistentData.FilePrefix)); + local queryStorages = ::PersistenceManager.queryStorages; + ::PersistenceManager.queryStorages = function() + { + return queryStorages().filter(@(_, _v) !::MSU.String.startsWith(_v.getFileName(), ::MSU.System.PersistentData.FilePrefix)); + } + local ret = __original(); + ::PersistenceManager.queryStorages = queryStorages; + return ret; } - local ret = __original(); - ::PersistenceManager.queryStorages = queryStorages; - return ret; - } + }); }); diff --git a/msu/hooks/ui/screens/menu/modules/main_menu_module.nut b/msu/hooks/ui/screens/menu/modules/main_menu_module.nut index de09920b7..590819afe 100644 --- a/msu/hooks/ui/screens/menu/modules/main_menu_module.nut +++ b/msu/hooks/ui/screens/menu/modules/main_menu_module.nut @@ -11,12 +11,6 @@ this.m.OnModOptionsPressedListener(); } - q.create = @(__original) function() - { - __original(); - ::MSU.Popup.quitGame = this.onQuitButtonPressed.bindenv(this); - } - q.connectBackend <- function() { ::MSU.Popup.connect(); @@ -26,3 +20,14 @@ } } }); + +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/ui/screens/menu/modules/main_menu_module", function(q) { + q.create = @(__original) function() + { + __original(); + ::MSU.Popup.quitGame = this.onQuitButtonPressed.bindenv(this); + } + }); +}); + diff --git a/msu/hooks/ui/screens/tooltip/tooltip_events.nut b/msu/hooks/ui/screens/tooltip/tooltip_events.nut index 6f99822ab..b8cc5db3c 100644 --- a/msu/hooks/ui/screens/tooltip/tooltip_events.nut +++ b/msu/hooks/ui/screens/tooltip/tooltip_events.nut @@ -1,68 +1,72 @@ ::MSU.MH.hook("scripts/ui/screens/tooltip/tooltip_events", function(q) { - q.tactical_queryTileTooltipData = @(__original) function() + q.onQueryMSUTooltipData <- function( _data ) { - local ret = __original(); - if (ret != null && ::Tactical.TurnSequenceBar.getActiveEntity() != null && ::Tactical.TurnSequenceBar.getActiveEntity().isPlayerControlled()) - { - ::Tactical.TurnSequenceBar.getActiveEntity().getSkills().onQueryTileTooltip(::Tactical.State.getLastTileHovered(), ret); - } - return ret; + return ::MSU.System.Tooltips.getTooltip(_data.modId, _data.elementId).getUIData(_data); } +}); - q.general_querySkillTooltipData = @(__original) function( _entityId, _skillId ) - { - local ret = __original(_entityId, _skillId); - - if (ret != null) +::MSU.QueueBucket.VeryLate.push(function() { + ::MSU.MH.hook("scripts/ui/screens/tooltip/tooltip_events", function(q) { + q.tactical_queryTileTooltipData = @(__original) function() { - local skill = ::Tactical.getEntityByID(_entityId).getSkills().getSkillByID(_skillId); - skill.getContainer().onQueryTooltip(skill, ret); + local ret = __original(); + if (ret != null && ::Tactical.TurnSequenceBar.getActiveEntity() != null && ::Tactical.TurnSequenceBar.getActiveEntity().isPlayerControlled()) + { + ::Tactical.TurnSequenceBar.getActiveEntity().getSkills().onQueryTileTooltip(::Tactical.State.getLastTileHovered(), ret); + } + return ret; } - return ret; - } - - q.general_queryStatusEffectTooltipData = @(__original) function( _entityId, _statusEffectId ) - { - local ret = __original(_entityId, _statusEffectId); - if (ret != null) + q.general_querySkillTooltipData = @(__original) function( _entityId, _skillId ) { - local statusEffect = ::Tactical.getEntityByID(_entityId).getSkills().getSkillByID(_statusEffectId); - statusEffect.getContainer().onQueryTooltip(statusEffect, ret); + local ret = __original(_entityId, _skillId); + + if (ret != null) + { + local skill = ::Tactical.getEntityByID(_entityId).getSkills().getSkillByID(_skillId); + skill.getContainer().onQueryTooltip(skill, ret); + } + + return ret; } - return ret; - } + q.general_queryStatusEffectTooltipData = @(__original) function( _entityId, _statusEffectId ) + { + local ret = __original(_entityId, _statusEffectId); + if (ret != null) + { + local statusEffect = ::Tactical.getEntityByID(_entityId).getSkills().getSkillByID(_statusEffectId); + statusEffect.getContainer().onQueryTooltip(statusEffect, ret); + } - q.onQueryMSUTooltipData <- function( _data ) - { - return ::MSU.System.Tooltips.getTooltip(_data.modId, _data.elementId).getUIData(_data); - } + return ret; + } - // deprecated, MSU settings (and future tooltips) should now use onQueryMSUTooltipData - q.general_queryUIElementTooltipData = @(__original) function( _entityId, _elementId, _elementOwner ) - { - local ret = __original(_entityId, _elementId, _elementOwner); - if (ret == null) + // deprecated, MSU settings (and future tooltips) should now use onQueryMSUTooltipData + q.general_queryUIElementTooltipData = @(__original) function( _entityId, _elementId, _elementOwner ) { - if (_elementId.find("msu-settings") == 0) + local ret = __original(_entityId, _elementId, _elementOwner); + if (ret == null) { - local threePartArray = split(_elementId, ".") - local setting = ::getModSetting(threePartArray[1], threePartArray[2]); - return [ - { - id = 1, - type = "title", - text = setting.getName() - }, - { - id = 2, - type = "description", - text = setting.getDescription() - } - ]; + if (_elementId.find("msu-settings") == 0) + { + local threePartArray = split(_elementId, ".") + local setting = ::getModSetting(threePartArray[1], threePartArray[2]); + return [ + { + id = 1, + type = "title", + text = setting.getName() + }, + { + id = 2, + type = "description", + text = setting.getDescription() + } + ]; + } } + return ret; } - return ret; - } + }); }); diff --git a/msu/hooks/ui/screens/world/modules/world_town_screen/town_travel_dialog_module.nut b/msu/hooks/ui/screens/world/modules/world_town_screen/town_travel_dialog_module.nut index 87a0a3908..2c10c9ef8 100644 --- a/msu/hooks/ui/screens/world/modules/world_town_screen/town_travel_dialog_module.nut +++ b/msu/hooks/ui/screens/world/modules/world_town_screen/town_travel_dialog_module.nut @@ -1,8 +1,10 @@ -// VANILLAFIX https://steamcommunity.com/app/365360/discussions/1/4334231842064065638/ -::MSU.MH.hook("scripts/ui/screens/world/modules/world_town_screen/town_travel_dialog_module", function(q) { - q.fastTravelTo = @(__original) function( _dest ) - { - ::World.State.getCurrentTown().onLeave(); - return __original(_dest); - } +::MSU.QueueBucket.VeryLate.push(function() { + // VANILLAFIX https://steamcommunity.com/app/365360/discussions/1/4334231842064065638/ + ::MSU.MH.hook("scripts/ui/screens/world/modules/world_town_screen/town_travel_dialog_module", function(q) { + q.fastTravelTo = @(__original) function( _dest ) + { + ::World.State.getCurrentTown().onLeave(); + return __original(_dest); + } + }); });