Skip to content

Commit

Permalink
feat(flow): add effect-guessing heuristic for unknown weapons
Browse files Browse the repository at this point in the history
If we do not have a defined effect for a weapon, allow the module to
pick one which should be appropriate. This helps to bridge the gap for
homebrew items in the absence of a customization option.

As this may not always be desirable, gate the heuristic behind a config
option (enabled by default).

All credit to @dodgepong for the idea and algorithm.
  • Loading branch information
cirrahn committed Jul 8, 2024
1 parent a89c99e commit 5efa72f
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 4 deletions.
10 changes: 7 additions & 3 deletions lang/en.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"lancer-weapon-fx.Sound Volume": "Sound Volume",
"lancer-weapon-fx.Sound Volume Hint": "Set a base volume level for all sound effects. Note that for each user, this value is combined with the user's \"Global: Interface\" volume setting (see the \"Playlists\" sidebar tab) to produce their final volume level.",
"lancer-weapon-fx.Debug: Play Miss Animations by Default": "Debug: Play Miss Animations by Default"
"lancer-weapon-fx": {
"Sound Volume": "Sound Volume",
"Sound Volume Hint": "Set a base volume level for all sound effects. Note that for each user, this value is combined with the user's \"Global: Interface\" volume setting (see the \"Playlists\" sidebar tab) to produce their final volume level.",
"Use Weapon Heuristic": "Use Weapon Heuristic",
"Use Weapon Heuristic Hint": "Use a heuristic to determine a suitable effect to play when using an unknown (homebrew/custom) weapon.",
"Debug: Play Miss Animations by Default": "Debug: Play Miss Animations by Default"
}
}
14 changes: 14 additions & 0 deletions scripts/effectResolver/weaponEffects.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,20 @@ const weaponEffects = {
"npc_Tempest_NaniteMonsoonDispensers": "Nexus",
"npc_Tempest_TyphoonNaniteCannon": "Nexus",
"npc_PDCTurret": "Leviathan",
//HEURISTICS
"lwfx_heuristic_melee": "DefaultMelee",
"lwfx_heuristic_cqb_energy": "PPC",
"lwfx_heuristic_cqb_shotgun": "Shotgun",
"lwfx_heuristic_cqb_other": "Pistol",
"lwfx_heuristic_cannon_energy": "Tachyon Lance",
"lwfx_heuristic_cannon_mg": "HMG",
"lwfx_heuristic_cannon_other": "Mortar",
"lwfx_heuristic_launcher": "Missile",
"lwfx_heuristic_nexus": "Nexus",
"lwfx_heuristic_rifle_energy": "Thermal Rifle",
"lwfx_heuristic_rifle_mg": "HMG",
"lwfx_heuristic_rifle_ar": "Assault Rifle",
"lwfx_heuristic_rifle_other": "AMR",
};

export { weaponEffects };
68 changes: 68 additions & 0 deletions scripts/flow/WeaponAttackFlow/heuristic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { MODULE_ID } from "../../consts.js";
import { SETTING_IS_WEAPON_HEURISTIC_ACTIVE } from "../../settings.js";

const getPrimaryDamageType = ({ activeProfile }) => {
return activeProfile.all_damage?.[0]?.type;
};

const getPrimaryRange = ({ activeProfile }) => {
return activeProfile.all_range?.[0]?.type;
};

const isShotgun = ({ name, activeProfile }) => {
if (getPrimaryRange({ activeProfile }) === "Cone") return true;
return /\bshotgun\b/i.test(name);
};

const isMachineGun = ({ name }) => {
return /\b(?:assault|lmg|hmg|machine gun|minigun)\b/i.test(name);
};

export const fallbackActionIdentifier = flow => {
if (!game.settings.get(MODULE_ID, SETTING_IS_WEAPON_HEURISTIC_ACTIVE)) return null;

const activeProfile = flow.state.item?.system?.active_profile;
if (!activeProfile) return null;

const {
name,
system: { size },
} = flow.state.item;

switch (flow.state.item.system.active_profile.type) {
case "Melee": {
return "lwfx_heuristic_melee";
}

case "CQB": {
if (getPrimaryDamageType({ activeProfile }) === "Energy") return "lwfx_heuristic_cqb_energy";
if (isShotgun({ name, activeProfile })) return "lwfx_heuristic_cqb_shotgun";
return "lwfx_heuristic_cqb_other";
}

case "Rifle": {
if (getPrimaryDamageType({ activeProfile }) === "Energy") return "lwfx_heuristic_rifle_energy";
if (isMachineGun({ name })) {
if (["Heavy", "Superheavy"].includes(size)) return "lwfx_heuristic_rifle_mg";
return "lwfx_heuristic_rifle_ar";
}
return "lwfx_heuristic_rifle_other";
}

case "Launcher": {
return "lwfx_heuristic_launcher";
}

case "Cannon": {
if (getPrimaryDamageType({ activeProfile }) === "Energy") return "lwfx_heuristic_cannon_energy";
if (isMachineGun({ name })) return "lwfx_heuristic_cannon_mg";
return "lwfx_heuristic_cannon_other";
}

case "Nexus": {
return "lwfx_heuristic_nexus";
}
}

return null;
};
6 changes: 5 additions & 1 deletion scripts/flow/flowListener.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FlowInfo, getTokenByIdOrActorId, processFlowInfo } from "./common.js";
import { pGetMacroUuid } from "../effectResolver/effectResolver.js";
import { fallbackActionIdentifier as fallbackActionIdentifier_WeaponAttackFlow } from "./WeaponAttackFlow/heuristic.js";

/**
* @param state
Expand Down Expand Up @@ -108,7 +109,10 @@ const _onReady = () => {
if (!foundry.utils.isNewerVersion(game.version, "11")) return;

// Weapon attacks
_bindFlowHook({ flowName: "WeaponAttackFlow" });
_bindFlowHook({
flowName: "WeaponAttackFlow",
fallbackActionIdentifier: fallbackActionIdentifier_WeaponAttackFlow,
});
// Basic attacks
_bindFlowHook({ flowName: "BasicAttackFlow", fallbackActionIdentifier: fallbackActionIdentifier_BasicAttackFlow });

Expand Down
10 changes: 10 additions & 0 deletions scripts/settings.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { MODULE_ID } from "./consts.js";

export const SETTING_VOLUME = "volume";
export const SETTING_IS_WEAPON_HEURISTIC_ACTIVE = "isWeaponHeuristicActive";

export const SETTING_DEBUG_IS_DEFAULT_MISS = "debug-is-default-miss";

Expand All @@ -17,6 +18,15 @@ export const bindHooks = () => {
default: 1.0,
});

game.settings.register(MODULE_ID, SETTING_IS_WEAPON_HEURISTIC_ACTIVE, {
name: "lancer-weapon-fx.Use Weapon Heuristic",
hint: "lancer-weapon-fx.Use Weapon Heuristic Hint",
scope: "world",
config: true,
type: Boolean,
default: true,
});

game.settings.register(MODULE_ID, SETTING_DEBUG_IS_DEFAULT_MISS, {
name: "lancer-weapon-fx.Debug: Play Miss Animations by Default",
scope: "client",
Expand Down

0 comments on commit 5efa72f

Please sign in to comment.