Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/agents/Hush/1.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/agents/Hush/2.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/agents/Hush/3.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/agents/Hush/4.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/agents/Hush/icon.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions lib/const/agents.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum AgentType {
waylay,
veto,
miks,
hush,
}

enum AgentState {
Expand Down Expand Up @@ -1192,6 +1193,38 @@ class AgentData implements DraggableData {
agent.abilities[3] = miksHarmonize;
agent.abilities.add(miksUlt);

return agent;
})(),
AgentType.hush: (() {
final agent = AgentData(
type: AgentType.hush,
role: AgentRole.duelist,
name: "Hush",
abilityNames: const [
"Flow",
"Flashbulb",
"Displacement",
"Suspension",
],
);

// Radii from the Valorant 13.09 files: Displacement's pull area
// (RangeRadius 575) and the players Suspension lifts
// (PlayerHitRadius 700; its 900 dome only lifts dropped guns).
agent.abilities[2].abilityData = CircleAbility(
iconPath: agent.abilities[2].iconPath,
size: 5.75,
rangeOutlineColor: const Color(0xFFF47AC7),
hasCenterDot: true,
);

agent.abilities.last.abilityData = CircleAbility(
iconPath: agent.abilities.last.iconPath,
size: 7,
rangeOutlineColor: const Color(0xFFF47AC7),
hasCenterDot: true,
);

return agent;
})(),
};
Expand Down
1 change: 1 addition & 0 deletions lib/const/json_converters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const _agentTypeEnumMap = {
AgentType.waylay: 'waylay',
AgentType.veto: 'veto',
AgentType.miks: 'miks',
AgentType.hush: 'hush',
};

class AbilityInfoConverter
Expand Down
4 changes: 4 additions & 0 deletions lib/hive/hive_adapters.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion lib/hive/hive_adapters.g.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ types:
index: 12
AgentType:
typeId: 7
nextIndex: 29
nextIndex: 30
fields:
jett:
index: 0
Expand Down Expand Up @@ -189,6 +189,8 @@ types:
index: 27
miks:
index: 28
hush:
index: 29
Offset:
typeId: 8
nextIndex: 2
Expand Down
14 changes: 14 additions & 0 deletions lib/replay/replay_ability_catalog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -542,6 +544,18 @@ final Map<String, ReplayAbilityEntry> _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),
Expand Down
1 change: 1 addition & 0 deletions lib/replay/replay_agents.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const Map<String, AgentType> 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,
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,6 @@ flutter:
- assets/agents/Waylay/
- assets/agents/Veto/
- assets/agents/Miks/
- assets/agents/Hush/

uses-material-design: true
1 change: 1 addition & 0 deletions test/agent_ability_names_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ void main() {
'Harmonize',
'Bassquake',
],
AgentType.hush: ['Flow', 'Flashbulb', 'Displacement', 'Suspension'],
};

expect(AgentData.agents.keys.toSet(), expectedNames.keys.toSet());
Expand Down
15 changes: 11 additions & 4 deletions test/canvas_compatibility_fixture_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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(),
Expand All @@ -75,8 +81,9 @@ void main() {

final expectedAbilities = <String>{
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<String, dynamic>.from(ability['data'] as Map))
Expand Down
155 changes: 153 additions & 2 deletions test/desktop_4_6_3_adapters_test_support.dart
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -619,6 +621,155 @@ class Desktop463WeaponTypeAdapter extends TypeAdapter<WeaponType> {
typeId == other.typeId;
}

class Desktop463AgentTypeAdapter extends TypeAdapter<AgentType> {
@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<int, dynamic> fields, {
required int colorFieldIndex,
Expand Down
Loading
Loading