Skip to content

Commit 7d681de

Browse files
committed
✨ New auto honor plugin
1 parent 17fe661 commit 7d681de

File tree

2 files changed

+311
-0
lines changed

2 files changed

+311
-0
lines changed

plugins/Honor.js

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/// <reference path="../src/electron/typings/EndGame.d.ts" />
2+
3+
class Honor {
4+
constructor() {
5+
this.name = 'Auto Honor';
6+
this.description = 'Automatically honors';
7+
this.active = true;
8+
this.endpoint = '/lol-gameflow/v1/gameflow-phase';
9+
}
10+
11+
setup() {
12+
console.log('Honor.js loaded.');
13+
14+
const configuration = [
15+
{ id: 'honor.system', type: 'radio', value: 'Shotcalling', options: ['Cool', 'Shotcalling', 'GG', 'Skip'] },
16+
{ id: 'honor.player.type', type: 'radio', value: 'Best Player', options: ['Best Player', 'Random', 'Custom'] },
17+
{ id: 'honor.player.name', type: 'text', value: 'GR0236621563#EUW' }, // temp
18+
];
19+
20+
return configuration;
21+
}
22+
23+
async execute(getSetting, lcu, event) {
24+
if (event.data !== 'PreEndOfGame') return;
25+
26+
const response = await lcu.request({ method: 'GET', url: '/lol-honor-v2/v1/ballot' });
27+
const honorList = await response.json();
28+
29+
if (!honorList.eligiblePlayers.length) return;
30+
31+
const honorsTypes = {
32+
Cool: 'COOL',
33+
Shotcalling: 'SHOTCALLER',
34+
GG: 'HEART',
35+
Skip: 'OPT_OUT',
36+
};
37+
38+
const honorSystem = getSetting('honor.system');
39+
const honorType = getSetting('honor.player.type');
40+
41+
if (honorSystem.value === 'Skip') {
42+
const honor = {
43+
gameId: honorList.gameId,
44+
honorType: honorsTypes[honorSystem.value],
45+
puuid: '',
46+
summonerId: 0,
47+
};
48+
49+
const isHonored = await lcu.request({ method: 'POST', url: '/lol-honor-v2/v1/honor-player', body: honor });
50+
const data = await isHonored.json();
51+
console.log('Skiped.', JSON.parse(data));
52+
return;
53+
}
54+
55+
let player;
56+
switch (honorType.value) {
57+
case 'Random':
58+
player = this.random(honorList.eligiblePlayers);
59+
break;
60+
61+
case 'Custom':
62+
const customPlayer = getSetting('honor.player.name');
63+
const [customName, customTag] = customPlayer.value.split('#');
64+
const response = await lcu.request({ method: 'GET', url: `/lol-summoner/v1/summoners?name=${customName}%23${customTag}` });
65+
player = await response.json();
66+
break;
67+
68+
default:
69+
const gameResponse = await lcu.request({ method: 'GET', url: '/lol-end-of-game/v1/eog-stats-block' });
70+
const gameStats = await gameResponse.json();
71+
player = this.bestPlayer(gameStats.teams);
72+
break;
73+
}
74+
75+
const honor = {
76+
gameId: honorList.gameId,
77+
honorType: honorsTypes[honorSystem.value],
78+
puuid: player.puuid,
79+
summonerId: player.summonerId,
80+
};
81+
82+
const isHonored = await lcu.request({ method: 'POST', url: '/lol-honor-v2/v1/honor-player', body: honor });
83+
const data = await isHonored.json();
84+
console.log('Done.', JSON.parse(data));
85+
}
86+
87+
bestPlayer(teams) {
88+
let bestPlayer = null;
89+
let highestScore = -Infinity;
90+
91+
for (const team of teams) {
92+
if (!team.isPlayerTeam) continue;
93+
94+
for (const player of team.players) {
95+
if (player.isLocalPlayer) continue;
96+
97+
const score = this.score(player);
98+
console.log(`${player.summonerName} (${player.championName}) has a score: ${score}`);
99+
if (score <= highestScore) continue;
100+
101+
highestScore = score;
102+
bestPlayer = player;
103+
}
104+
}
105+
106+
return bestPlayer;
107+
}
108+
109+
random(array) {
110+
const randomIndex = Math.floor(Math.random() * array.length);
111+
return array[randomIndex];
112+
}
113+
114+
score(player) {
115+
const WEIGHT_KDA = 0.35;
116+
const WEIGHT_VISION = 0.15;
117+
const WEIGHT_DAMAGES_DEAL = 0.3;
118+
const WEIGHT_DAMAGES_TAKEN = 0.2;
119+
120+
const SCORE_KILLS_AND_ASSISTS = player.stats.ASSISTS + player.stats.CHAMPIONS_KILLED;
121+
const SCORE_KDA = player.stats.NUM_DEATHS ? SCORE_KILLS_AND_ASSISTS / player.stats.NUM_DEATHS : SCORE_KILLS_AND_ASSISTS;
122+
const SCORE_VISION = player.stats.VISION_WARDS_BOUGHT_IN_GAME;
123+
const SCORE_DAMAGES_DEAL = player.stats.TOTAL_DAMAGE_DEALT;
124+
const SCORE_DAMAGES_TAKEN = player.stats.TOTAL_DAMAGE_TAKEN;
125+
126+
const CONTRIBUTION_KDA = SCORE_KDA * WEIGHT_KDA;
127+
const CONTRIBUTION_VISION = SCORE_VISION * WEIGHT_VISION;
128+
const CONTRIBUTION_DAMAGES_DEAL = SCORE_DAMAGES_DEAL * WEIGHT_DAMAGES_DEAL;
129+
const CONTRIBUTION_DAMAGES_TAKEN = SCORE_DAMAGES_TAKEN * WEIGHT_DAMAGES_TAKEN;
130+
131+
const TOTAL = CONTRIBUTION_KDA + CONTRIBUTION_VISION + CONTRIBUTION_DAMAGES_DEAL + CONTRIBUTION_DAMAGES_TAKEN;
132+
return TOTAL;
133+
}
134+
}
135+
136+
module.exports = Honor;

src/electron/typings/EndGame.d.ts

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
export interface EndGame {
2+
basePoints: number;
3+
battleBoostIpEarned: number;
4+
boostIpEarned: number;
5+
boostXpEarned: number;
6+
causedEarlySurrender: boolean;
7+
currentLevel: number;
8+
difficulty: string;
9+
earlySurrenderAccomplice: boolean;
10+
experienceEarned: number;
11+
experienceTotal: number;
12+
firstWinBonus: number;
13+
gameEndedInEarlySurrender: boolean;
14+
gameId: number;
15+
gameLength: number;
16+
gameMode: string;
17+
gameMutators: string[];
18+
gameType: string;
19+
globalBoostXpEarned: number;
20+
invalid: boolean;
21+
ipEarned: number;
22+
ipTotal: number;
23+
leveledUp: boolean;
24+
localPlayer: Player;
25+
loyaltyBoostXpEarned: number;
26+
missionsXpEarned: number;
27+
multiUserChatId: string;
28+
multiUserChatPassword: string;
29+
myTeamStatus: string;
30+
newSpells: any[];
31+
nextLevelXp: number;
32+
preLevelUpExperienceTotal: number;
33+
preLevelUpNextLevelXp: number;
34+
previousLevel: number;
35+
previousXpTotal: number;
36+
queueType: string;
37+
ranked: boolean;
38+
reportGameId: number;
39+
rpEarned: number;
40+
teamBoost: Boost;
41+
teamEarlySurrendered: boolean;
42+
teams: Team[];
43+
timeUntilNextFirstWinBonus: number;
44+
xbgpBoostXpEarned: number;
45+
}
46+
47+
interface Team {
48+
fullId: string;
49+
isBottomTeam: boolean;
50+
isPlayerTeam: boolean;
51+
isWinningTeam: boolean;
52+
memberStatusString: string;
53+
name: string;
54+
players: Player[];
55+
stats: Stats;
56+
tag: string;
57+
teamId: number;
58+
}
59+
60+
export interface Player {
61+
botPlayer: boolean;
62+
championId: number;
63+
championName: string;
64+
championSquarePortraitPath: string;
65+
detectedTeamPosition: string;
66+
gameId: number;
67+
isLocalPlayer: boolean;
68+
items: number[];
69+
leaver: boolean;
70+
leaves: number;
71+
level: number;
72+
losses: number;
73+
profileIconId: number;
74+
puuid: string;
75+
selectedPosition: string;
76+
skinEmblemPaths: any[];
77+
skinSplashPath: string;
78+
skinTilePath: string;
79+
spell1Id: number;
80+
spell2Id: number;
81+
stats: Stats;
82+
summonerId: number;
83+
summonerName: string;
84+
teamId: number;
85+
wins: number;
86+
}
87+
88+
export interface Boost {
89+
availableSkins: any[];
90+
ipReward: number;
91+
ipRewardForPurchaser: number;
92+
price: number;
93+
skinUnlockMode: string;
94+
summonerName: string;
95+
unlocked: boolean;
96+
}
97+
98+
export interface Stats {
99+
ASSISTS: number;
100+
BARRACKS_KILLED: number;
101+
CHAMPIONS_KILLED: number;
102+
GAME_ENDED_IN_EARLY_SURRENDER: number;
103+
GAME_ENDED_IN_SURRENDER: number;
104+
GOLD_EARNED: number;
105+
LARGEST_CRITICAL_STRIKE: number;
106+
LARGEST_KILLING_SPREE: number;
107+
LARGEST_MULTI_KILL: number;
108+
LEVEL: number;
109+
MAGIC_DAMAGE_DEALT_PLAYER: number;
110+
MAGIC_DAMAGE_DEALT_TO_CHAMPIONS: number;
111+
MAGIC_DAMAGE_TAKEN: number;
112+
MINIONS_KILLED: number;
113+
NEUTRAL_MINIONS_KILLED: number;
114+
NUM_DEATHS: number;
115+
PERK0: number;
116+
PERK0_VAR1: number;
117+
PERK0_VAR2: number;
118+
PERK0_VAR3: number;
119+
PERK1: number;
120+
PERK1_VAR1: number;
121+
PERK1_VAR2: number;
122+
PERK1_VAR3: number;
123+
PERK2: number;
124+
PERK2_VAR1: number;
125+
PERK2_VAR2: number;
126+
PERK2_VAR3: number;
127+
PERK3: number;
128+
PERK3_VAR1: number;
129+
PERK3_VAR2: number;
130+
PERK3_VAR3: number;
131+
PERK4: number;
132+
PERK4_VAR1: number;
133+
PERK4_VAR2: number;
134+
PERK4_VAR3: number;
135+
PERK5: number;
136+
PERK5_VAR1: number;
137+
PERK5_VAR2: number;
138+
PERK5_VAR3: number;
139+
PERK_PRIMARY_STYLE: number;
140+
PERK_SUB_STYLE: number;
141+
PHYSICAL_DAMAGE_DEALT_PLAYER: number;
142+
PHYSICAL_DAMAGE_DEALT_TO_CHAMPIONS: number;
143+
PHYSICAL_DAMAGE_TAKEN: number;
144+
PLAYER_AUGMENT_1: number;
145+
PLAYER_AUGMENT_2: number;
146+
PLAYER_AUGMENT_3: number;
147+
PLAYER_AUGMENT_4: number;
148+
PLAYER_SUBTEAM: number;
149+
PLAYER_SUBTEAM_PLACEMENT: number;
150+
SIGHT_WARDS_BOUGHT_IN_GAME: number;
151+
SPELL1_CAST: number;
152+
SPELL2_CAST: number;
153+
TEAM_EARLY_SURRENDERED: number;
154+
TEAM_OBJECTIVE: number;
155+
TIME_CCING_OTHERS: number;
156+
TOTAL_DAMAGE_DEALT: number;
157+
TOTAL_DAMAGE_DEALT_TO_BUILDINGS: number;
158+
TOTAL_DAMAGE_DEALT_TO_CHAMPIONS: number;
159+
TOTAL_DAMAGE_DEALT_TO_OBJECTIVES: number;
160+
TOTAL_DAMAGE_DEALT_TO_TURRETS: number;
161+
TOTAL_DAMAGE_SELF_MITIGATED: number;
162+
TOTAL_DAMAGE_SHIELDED_ON_TEAMMATES: number;
163+
TOTAL_DAMAGE_TAKEN: number;
164+
TOTAL_HEAL: number;
165+
TOTAL_HEAL_ON_TEAMMATES: number;
166+
TOTAL_TIME_CROWD_CONTROL_DEALT: number;
167+
TOTAL_TIME_SPENT_DEAD: number;
168+
TRUE_DAMAGE_DEALT_PLAYER: number;
169+
TRUE_DAMAGE_DEALT_TO_CHAMPIONS: number;
170+
TRUE_DAMAGE_TAKEN: number;
171+
TURRETS_KILLED: number;
172+
VISION_WARDS_BOUGHT_IN_GAME: number;
173+
WAS_AFK: number;
174+
WIN: 1;
175+
}

0 commit comments

Comments
 (0)