From 5233f4ed49f0674e8a4d96daf3ddd9b3e5a9471a Mon Sep 17 00:00:00 2001 From: Dara Adedeji Date: Wed, 28 Oct 2026 12:08:48 -0400 Subject: [PATCH] Add Hush VALORANT 13.09's new duelist (codename Paprika). She goes last in AgentType so every saved index stays put (Hive index 29). Abilities, in key order like the other agents: - Flow (C) and Flashbulb (Q) draw as their icons, like the other movement abilities (Tailwind) and flashes. - Displacement (E): a 5.75 m circle, the pull area's RangeRadius 575. - Suspension (X): a 7 m circle, its PlayerHitRadius 700. Its 900 dome only lifts dropped guns. Both radii come from the 13.09 game files, read the way Fade's Seize (658 -> 6.58 m) and Gekko's Mosh Pit (620 -> 6.2 m) are. Telekinesis is a passive with nothing to place, so Hush keeps four abilities. Icons are valorant-api.com's, at 128 px WebP like the rest. Her circles use her own accent color from the game, F47AC7. Desktop 4.6.3 reads an agent index it doesn't know as Jett. The rollback tests now use 4.6.3's own AgentType adapter and prove a page with Hush still opens there whole, with Hush and her four abilities as Jett's. The frozen v97 .ica fixture predates Hush, so its every-agent check leaves out agents added after it. Replays map her valorant-api UUID and her 13.09 actors; the actor names come from the asset index and are unverified against a replay. Co-Authored-By: Claude Opus 5.5 --- assets/agents/Hush/1.webp | Bin 0 -> 4894 bytes assets/agents/Hush/2.webp | Bin 0 -> 6708 bytes assets/agents/Hush/3.webp | Bin 0 -> 5660 bytes assets/agents/Hush/4.webp | Bin 0 -> 7244 bytes assets/agents/Hush/icon.webp | Bin 0 -> 5618 bytes lib/const/agents.dart | 33 ++++ lib/const/json_converters.dart | 1 + lib/hive/hive_adapters.g.dart | 4 + lib/hive/hive_adapters.g.yaml | 4 +- lib/replay/replay_ability_catalog.dart | 14 ++ lib/replay/replay_agents.dart | 1 + pubspec.yaml | 1 + test/agent_ability_names_test.dart | 1 + test/canvas_compatibility_fixture_test.dart | 15 +- test/desktop_4_6_3_adapters_test_support.dart | 155 +++++++++++++++++- test/hive_desktop_rollback_test.dart | 83 ++++++---- 16 files changed, 273 insertions(+), 39 deletions(-) create mode 100644 assets/agents/Hush/1.webp create mode 100644 assets/agents/Hush/2.webp create mode 100644 assets/agents/Hush/3.webp create mode 100644 assets/agents/Hush/4.webp create mode 100644 assets/agents/Hush/icon.webp diff --git a/assets/agents/Hush/1.webp b/assets/agents/Hush/1.webp new file mode 100644 index 0000000000000000000000000000000000000000..d03449047fe92a8ba9f8b5210902c34aa3b61a38 GIT binary patch literal 4894 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 Q?3Nw1AmjYd_)viW07$uH3IG5A literal 0 HcmV?d00001 diff --git a/assets/agents/Hush/2.webp b/assets/agents/Hush/2.webp new file mode 100644 index 0000000000000000000000000000000000000000..a50f2c0c0c32ecef3b4d196420dffb53aaf6f223 GIT binary patch literal 6708 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 CXbgG) literal 0 HcmV?d00001 diff --git a/assets/agents/Hush/4.webp b/assets/agents/Hush/4.webp new file mode 100644 index 0000000000000000000000000000000000000000..469c1730997d72be2973d63ae370bb5fe2147d24 GIT binary patch literal 7244 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 aQV`WH0TMz-nsA8yh`<5+|FkH800018{yt>@ literal 0 HcmV?d00001 diff --git a/assets/agents/Hush/icon.webp b/assets/agents/Hush/icon.webp new file mode 100644 index 0000000000000000000000000000000000000000..608ef5a9863dd4d2daa9f4d80ad4e52540ebef91 GIT binary patch literal 5618 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 { return AgentType.veto; case 28: return AgentType.miks; + case 29: + return AgentType.hush; default: return AgentType.jett; } @@ -471,6 +473,8 @@ class AgentTypeAdapter extends TypeAdapter { writer.writeByte(27); case AgentType.miks: writer.writeByte(28); + case AgentType.hush: + writer.writeByte(29); } } diff --git a/lib/hive/hive_adapters.g.yaml b/lib/hive/hive_adapters.g.yaml index 71b21b088..d1a5cdbf9 100644 --- a/lib/hive/hive_adapters.g.yaml +++ b/lib/hive/hive_adapters.g.yaml @@ -129,7 +129,7 @@ types: index: 12 AgentType: typeId: 7 - nextIndex: 29 + nextIndex: 30 fields: jett: index: 0 @@ -189,6 +189,8 @@ types: index: 27 miks: index: 28 + hush: + index: 29 Offset: typeId: 8 nextIndex: 2 diff --git a/lib/replay/replay_ability_catalog.dart b/lib/replay/replay_ability_catalog.dart index 97b4d0943..50e1b30b2 100644 --- a/lib/replay/replay_ability_catalog.dart +++ b/lib/replay/replay_ability_catalog.dart @@ -85,6 +85,8 @@ const _followUps = { 'GameObject_Nox_Wall', 'GameObject_Nox_BarbedWire', 'Patch_Nox_BarbedWire', + 'GameObject_Paprika_E_RedirectPullArea', + 'GameObject_Paprika_X_LevitateZone', }; /// The asset name of a class path, the part Riot names the blueprint by: @@ -542,6 +544,18 @@ final Map _catalog = { 'GameObject_Mage_E_WorldSmoke': _smoke(AgentType.harbor, 2), 'GameObject_Mage_X_TidalWave': _rectangle(AgentType.harbor, 3), + // Hush (Paprika), 13.09 asset index. Flow's actor is its anchor; the + // Displacement and Suspension areas open where their projectiles go off. + 'GameObject_Paprika_4_PullBlast': _marker(AgentType.hush, 0), + 'Projectile_Paprika_Q_RedirectFlash': _projectile(AgentType.hush, 1), + 'Projectile_Paprika_Q_RedirectFlash_Underhand': + _projectile(AgentType.hush, 1), + 'Projectile_Paprika_E_RedirectPull': _flight(AgentType.hush, 2), + 'Projectile_Paprika_E_RedirectPull_Underhand': _flight(AgentType.hush, 2), + 'GameObject_Paprika_E_RedirectPullArea': _area(AgentType.hush, 2), + 'Projectile_Paprika_X_FullBendPop': _flight(AgentType.hush, 3), + 'GameObject_Paprika_X_LevitateZone': _area(AgentType.hush, 3), + // Iso (Sequoia). 'GameObject_Sequoia_4_MovingCover': _rectangle(AgentType.iso, 0), 'GameObject_Sequoia_4_MovingCover_Slower': _rectangle(AgentType.iso, 0), diff --git a/lib/replay/replay_agents.dart b/lib/replay/replay_agents.dart index 5ce8ad016..8d5a3e4ed 100644 --- a/lib/replay/replay_agents.dart +++ b/lib/replay/replay_agents.dart @@ -14,6 +14,7 @@ const Map replayAgentsById = { 'dade69b4-4f5a-8528-247b-219e5a1facd6': AgentType.fade, 'e370fa57-4757-3604-3648-499e1f642d3f': AgentType.gekko, '95b78ed7-4637-86d9-7e41-71ba8c293152': AgentType.harbor, + 'ddd5a15c-4fbe-42fa-3789-11a55ca5ee04': AgentType.hush, '0e38b510-41a8-5780-5e8f-568b2a4f2d6c': AgentType.iso, 'add6443a-41bd-e414-f6ad-e58d267f4e95': AgentType.jett, '601dbbe7-43ce-be57-2a40-4abd24953621': AgentType.kayo, diff --git a/pubspec.yaml b/pubspec.yaml index b074b9eb2..40c2d7d56 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -155,5 +155,6 @@ flutter: - assets/agents/Waylay/ - assets/agents/Veto/ - assets/agents/Miks/ + - assets/agents/Hush/ uses-material-design: true diff --git a/test/agent_ability_names_test.dart b/test/agent_ability_names_test.dart index 633b8718d..29cc50169 100644 --- a/test/agent_ability_names_test.dart +++ b/test/agent_ability_names_test.dart @@ -102,6 +102,7 @@ void main() { 'Harmonize', 'Bassquake', ], + AgentType.hush: ['Flow', 'Flashbulb', 'Displacement', 'Suspension'], }; expect(AgentData.agents.keys.toSet(), expectedNames.keys.toSet()); diff --git a/test/canvas_compatibility_fixture_test.dart b/test/canvas_compatibility_fixture_test.dart index b97132df8..5f5ebef1a 100644 --- a/test/canvas_compatibility_fixture_test.dart +++ b/test/canvas_compatibility_fixture_test.dart @@ -12,6 +12,9 @@ import 'package:path/path.dart' as path; const _fixtureName = 'canvas-compatibility-v97.ica'; +/// Agents Icarus added after the fixture was frozen. +const _agentsSinceFixture = {AgentType.hush}; + void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -58,13 +61,16 @@ void main() { } }); - test('contains every current agent and ability', () { + test('contains every agent and ability Icarus had at v97', () { final agents = _entries(pages, 'agentData'); final actualAgentTypes = agents.map((agent) => agent['type'] as String).toSet(); expect( actualAgentTypes, - AgentType.values.map((type) => type.name).toSet(), + AgentType.values + .where((type) => !_agentsSinceFixture.contains(type)) + .map((type) => type.name) + .toSet(), ); expect( agents.map((agent) => agent['kind'] as String? ?? 'plain').toSet(), @@ -75,8 +81,9 @@ void main() { final expectedAbilities = { for (final type in AgentType.values) - for (final info in AgentData.agents[type]!.abilities) - '${type.name}:${info.index}', + if (!_agentsSinceFixture.contains(type)) + for (final info in AgentData.agents[type]!.abilities) + '${type.name}:${info.index}', }; final actualAbilities = _entries(pages, 'abilityData') .map((ability) => Map.from(ability['data'] as Map)) diff --git a/test/desktop_4_6_3_adapters_test_support.dart b/test/desktop_4_6_3_adapters_test_support.dart index 27bd1eb03..4ef4b2718 100644 --- a/test/desktop_4_6_3_adapters_test_support.dart +++ b/test/desktop_4_6_3_adapters_test_support.dart @@ -1,7 +1,9 @@ // Desktop 4.6.3's adapters for the typeIds this build writes by hand, copied // verbatim from the desktop-stable-v4.6.3+103 tag (only the class names -// changed), plus its WeaponTypeAdapter, which this build extended with the -// Warden. Every other adapter is unchanged since that release. Rollback +// changed), plus its WeaponTypeAdapter and AgentTypeAdapter, which this +// build extended with the Warden and Hush. Each of those two gains only the +// write case Dart's exhaustive switch demands for the new value, which +// throws. Every other adapter is unchanged since that release. Rollback // tests decode with these to prove 4.6.3 opens, and keeps, what this build // saves. Never edit them to match this build. @@ -619,6 +621,155 @@ class Desktop463WeaponTypeAdapter extends TypeAdapter { typeId == other.typeId; } +class Desktop463AgentTypeAdapter extends TypeAdapter { + @override + final typeId = 7; + + @override + AgentType read(BinaryReader reader) { + switch (reader.readByte()) { + case 0: + return AgentType.jett; + case 1: + return AgentType.raze; + case 2: + return AgentType.pheonix; + case 3: + return AgentType.astra; + case 4: + return AgentType.clove; + case 5: + return AgentType.breach; + case 6: + return AgentType.iso; + case 7: + return AgentType.viper; + case 8: + return AgentType.deadlock; + case 9: + return AgentType.yoru; + case 10: + return AgentType.sova; + case 11: + return AgentType.skye; + case 12: + return AgentType.kayo; + case 13: + return AgentType.killjoy; + case 14: + return AgentType.brimstone; + case 15: + return AgentType.cypher; + case 16: + return AgentType.chamber; + case 17: + return AgentType.fade; + case 18: + return AgentType.gekko; + case 19: + return AgentType.harbor; + case 20: + return AgentType.neon; + case 21: + return AgentType.omen; + case 22: + return AgentType.reyna; + case 23: + return AgentType.sage; + case 24: + return AgentType.vyse; + case 25: + return AgentType.tejo; + case 26: + return AgentType.waylay; + case 27: + return AgentType.veto; + case 28: + return AgentType.miks; + default: + return AgentType.jett; + } + } + + @override + void write(BinaryWriter writer, AgentType obj) { + switch (obj) { + case AgentType.jett: + writer.writeByte(0); + case AgentType.raze: + writer.writeByte(1); + case AgentType.pheonix: + writer.writeByte(2); + case AgentType.astra: + writer.writeByte(3); + case AgentType.clove: + writer.writeByte(4); + case AgentType.breach: + writer.writeByte(5); + case AgentType.iso: + writer.writeByte(6); + case AgentType.viper: + writer.writeByte(7); + case AgentType.deadlock: + writer.writeByte(8); + case AgentType.yoru: + writer.writeByte(9); + case AgentType.sova: + writer.writeByte(10); + case AgentType.skye: + writer.writeByte(11); + case AgentType.kayo: + writer.writeByte(12); + case AgentType.killjoy: + writer.writeByte(13); + case AgentType.brimstone: + writer.writeByte(14); + case AgentType.cypher: + writer.writeByte(15); + case AgentType.chamber: + writer.writeByte(16); + case AgentType.fade: + writer.writeByte(17); + case AgentType.gekko: + writer.writeByte(18); + case AgentType.harbor: + writer.writeByte(19); + case AgentType.neon: + writer.writeByte(20); + case AgentType.omen: + writer.writeByte(21); + case AgentType.reyna: + writer.writeByte(22); + case AgentType.sage: + writer.writeByte(23); + case AgentType.vyse: + writer.writeByte(24); + case AgentType.tejo: + writer.writeByte(25); + case AgentType.waylay: + writer.writeByte(26); + case AgentType.veto: + writer.writeByte(27); + case AgentType.miks: + writer.writeByte(28); + // Not in 4.6.3, which can never hold one; only Dart's exhaustive + // switch needs the case. + case AgentType.hush: + throw StateError('Desktop 4.6.3 has no Hush'); + } + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Desktop463AgentTypeAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} + int _readDrawingHiveColorValue( Map fields, { required int colorFieldIndex, diff --git a/test/hive_desktop_rollback_test.dart b/test/hive_desktop_rollback_test.dart index d954d0244..ec1d665a2 100644 --- a/test/hive_desktop_rollback_test.dart +++ b/test/hive_desktop_rollback_test.dart @@ -30,8 +30,9 @@ HiveImpl _currentRegistry() { } /// What desktop 4.6.3 registers: this build's adapters, which are unchanged -/// since that release, except the eight this build writes by hand and the -/// weapon list, which gained the Warden. +/// since that release, except the eight this build writes by hand, the +/// weapon list, which gained the Warden, and the agent list, which gained +/// Hush. HiveImpl _desktop463Registry() { final registry = _currentRegistry(); // hive_ce warns on every override, which is the point here. @@ -47,7 +48,8 @@ HiveImpl _desktop463Registry() { ..registerAdapter(Desktop463LineAdapter(), override: true) ..registerAdapter(Desktop463RectangleDrawingAdapter(), override: true) ..registerAdapter(Desktop463EllipseDrawingAdapter(), override: true) - ..registerAdapter(Desktop463WeaponTypeAdapter(), override: true); + ..registerAdapter(Desktop463WeaponTypeAdapter(), override: true) + ..registerAdapter(Desktop463AgentTypeAdapter(), override: true); } finally { Logger.level = previousLevel; } @@ -77,6 +79,39 @@ PlacedAbility _ability( ); } +/// A page holding each of [types] and every one of its abilities, with ids by +/// position so pages of different agents compare. +StrategyPage _rosterPage(List types) { + return StrategyPage( + id: 'page-roster', + name: 'Roster', + drawingData: const [], + agentData: [ + for (var a = 0; a < types.length; a++) + PlacedAgent( + id: 'agent-$a', + type: types[a], + position: const Offset(1, 1), + ), + ], + abilityData: [ + for (var a = 0; a < types.length; a++) + for (final (i, info) in AgentData.agents[types[a]]!.abilities.indexed) + PlacedAbility( + id: 'ability-$a-$i', + data: info, + position: const Offset(5, 5), + ), + ], + textData: const [], + imageData: const [], + utilityData: const [], + sortIndex: 0, + isAttack: true, + settings: StrategySettings(), + ); +} + StrategyPage _richPage() { const hidden = AbilityVisualState(showRangeFill: false); return StrategyPage( @@ -215,39 +250,23 @@ void main() { _expectSamePage(_across(desktop463, current, rolledBack), page); }); - test('every agent and ability survives a rollback', () { - final page = StrategyPage( - id: 'page-roster', - name: 'Roster', - drawingData: const [], - agentData: [ - for (final type in AgentType.values) - PlacedAgent( - id: 'agent-${type.name}', - type: type, - position: const Offset(1, 1), - ), - ], - abilityData: [ - for (final agent in AgentData.agents.values) - for (var i = 0; i < agent.abilities.length; i++) - PlacedAbility( - id: 'ability-${agent.type.name}-$i', - data: agent.abilities[i], - position: const Offset(5, 5), - ), - ], - textData: const [], - imageData: const [], - utilityData: const [], - sortIndex: 0, - isAttack: true, - settings: StrategySettings(), - ); + test('every agent 4.6.3 knows, and its abilities, survives a rollback', () { + final page = _rosterPage([ + for (final type in AgentType.values) + if (type != AgentType.hush) type, + ]); _expectSamePage(_across(current, desktop463, page), page); }); + test('desktop 4.6.3 opens a Hush this build saved as Jett', () { + // 4.6.3 reads an agent index it doesn't know as Jett, and an ability by + // its agent and index, so Hush's four abilities open as Jett's. + final opened = _across(current, desktop463, _rosterPage([AgentType.hush])); + + _expectSamePage(opened, _rosterPage([AgentType.jett])); + }); + test('folders keep their exact icon and color through a rollback', () { for (final iconId in [ FolderIconRegistry.defaultId,