Multi Account
Dans ce tutoriel je vais vous montrer comment refaire le plugin MultiAccount (pas totalement complet), en vous guidant pas-à-pas.
Avant toute chose, veuillez lire la partie "Introduction" et "Créer un plugin", afin d'être plus à l'aise et savoir comment setup votre projet Visual Studio.
Création du projet et import des dépendances
Créer un nouveau projet Visual Studio portant le nom "
Dtwo.Plugins.MultiAccount
"Importer les dll "
Dtwo.API.Hybride
,Dtwo.API.Retro
,Dtwo.API.Dofus2
,Dtwo.API.Inputs
,Dtwo.Plugins
"
Création de la classe MultiAccount_Plugin
using Dtwo.API;
public class MultiAccount_Plugin : Plugin
{
public static MultiAccount_Plugin Instance { get; private set; }
public MultiAccount_Plugin(PluginInfos infos, Assembly assembly) : base(infos, assembly)
{
Instance = this;
MultiAccountManager.Init();
}
}
Création de la classe MultiAccountManager et MultiAccountController
using Dtwo.API;
public static class MultiAccountManager
{
private Dictionary<DofusWindow, MultiAccountController> m_accounts = new()
public IReadonlyDictionary<DofusWindow, MultiAccountController> Accounts => m_accounts;
public void Init()
{
// On s'abonne aux events OnDofusWindowStarted / Stopped
DofusWindow.OnDofusWindowStarted += OnDofusWindowStarted;
DofusWindow.OnDofusWindowStoped += OnDofusWindowStoped;
}
// Une fenêtre commence a être sniffé
private static void OnDofusWindowStarted(DofusWindow dofusWindow)
{
m_accounts.Add(dofusWindow, new MultiAccountController(dofusWindow))
}
// Une fenêtre n'est plus sniffé
private static void OnDofusWindowStoped(DofusWindow dofusWindow)
{
m_accounts.Remove(dofusWindow);
}
}
using Dtwo.API;
public class MultiAccountController
{
public readonly DofusWindow DofusWindow;
public MultiAccountController(DofusWindow dofusWindow)
{
DofusWindow = dofusWindow;
}
}
Raccourcis pour appliquer un clique sur toutes les fenêtres
Créer une classe MultiClickManager
using Dtwo.API;
using Dtwo.API.Inputs;
using Dtwo.API.Inputs.Extensions;
public static class MultiClickManager
{
private static bool m_isStarted;
private static bool m_onMultiClick;
public static void Start()
{
if (m_isStarted)
{
return;
}
// On s'abonne aux event de KeyUp
InputKeyListener.Instance.KeyUp += OnKeyUp;
// On écoute les cliques du milieu
InputKeyListener.Instance.AddKey(0x04); // Middle click
m_isStarted = true;
}
public static void Stop()
{
m_isStarted = false;
}
private static void OnKeyUp(int key)
{
if (m_onMultiClick)
{
// On est déjà en train d'appliquer des clics dans les autres fenêtres
return;
}
if (key == Ox04) // Middle Click
{
OnMultiClick()
}
}
public static void Stop()
{
m_isStarted = false;
// On se désabonne de KeyUp, et on arrête d'écouter le clique du milieu
InputKeyListener.Instance.KeyUp -= OnKeyUp;
InputKeyListener.Instance.RemoveKey(0x04);
}
private static void OnMultiClick()
{
// On démarre un nouveau thread, pour ne pas bloquer l'application
Task.Factory.StartNew(async () =>
{
m_onMultiClick = true;
PInvoke.POINT pos = new PInvoke.POINT();
// On récupère la position de la souris sur l'écran en px
PInvoke.GetCursorPos(out pos);
// On récupère la position relative à la fenêtre sur la-quelle le clique a été fait
// En l'occurence la fenêtre en premier plan.
PInvoke.ScreenToClient(PInvoke.GetForegroundWindow(), ref pos);
for (int i = 0; i < MultiAccountManager.Accounts.Count; i++)
{
var account = MultiAccountManager.Accounts.ElementAt(i).Value;
// Initialization d'un click gauche aux coordonées indiquées
ClickInfo clickInfo = new ClickInfo(pos.X, pos.Y, false);
// On applique le clique sur cette fenêtre dofus
// La position du clique sera relative à la nouvelle fenêtre
// La taille de la fenêtre doit être la même que la fenêtre qui a reçu le clique original
// On attend que le clique se finisse (Click down + Click Up)
await account.DofusWindow.SendClick(clickInfo);
// On attend un peu de temps avant de passer à la fenêtre suivante
Thread.Sleep(API.Random.Range(250,500));
if (m_isStarted == false)
{
// Si on a stop, on s'arrête là
m_onMultiClick = false;
return;
}
}
m_onMultiClick = false;
});
}
}
Dans la classe MultiAccountManager
public void Init()
{
// ...
MultiClickManager.Start()
}
A l'étape où vous en êtes, si vous compilez et ajouter le plugin, vous devriez être capable d'appliquer des cliques sur toutes les fenêtres à l'aide du clique du milieu
Raccourcis pour passer à la fenêtre Suivante / Précédente
TODO
Update de l'initiative
Dans la classe MultiAccount_Plugin :
using Dtwo.API;
using Dtwo.API.Hybride
public class MultiAccount_Plugin : Plugin
{
// ...
// Un joueur rejoint le groupe
[DofusEvent]
public void OnPartyJoinMessage(DofusWindow dofusWindow, PartyJoinMessage message)
{
MultiAccountManager.OnPartyJoin(dofusWindow, message);
}
// Le groupe a été updaté (changement d'initiative, etc ...)
[DofusEvent]
public void OnPartyUpdateMessage(DofusWindow dofusWindow, PartyUpdateMessage message)
{
MultiAccountManager.OnPartyUpdate(dofusWindow, message);
}
}
Dans la classe MultiAccountManager
// Un personnage a été ajouté au groupe
// L'évent est call pour toutes les fenêtres
public static void OnPartyJoin(DofusWindow dofusWindow, PartyJoinMessage message)
{
foreach (var member in message.Members)
{
foreach (var account in m_accounts)
{
// On cherche a update seulement la fenêtre qui a reçu le message
// Afin de ne pas répéter l'opération pour toutes les autres fenêtres
if (account.DofusWindow.Character.Name != member.name)
continue;
// On update l'initiative
account.UpdateInitiative((int)member.initiative);
break;
}
}
// On change l'ordre de la liste
ReOrder();
}
// Le groupe a été update (initiative qui change, etc ...)
public static void OnPartyUpdate(DofusWindow dofusWindow, PartyUpdateMessage message)
{
if (m_accounts.ContainsKey(dofusWindow) == false)
return;
var owner = m_accounts[dofusWindow];
if (wnerController.IsLeader == false)
{
// OnPartyUpdate va être appellé pour chaque fenêtre,
// On ne veut itérer qu'une seule fois
// Donc on se base sur le leader
return;
}
// Find the account with the same name
foreach (var account in m_accounts)
{
// On cherche le joueur qui a été update
if (account.Value.DofusWindow.Character.Name != message.MemberInformations.name)
continue;
// On update l'initiative
account.Value.UpdateInitiative((int)message.MemberInformations.initiative);
// On change l'ordre de la liste
ReOrder();
break;
}
}
public static void ReOrder()
{
// On applique l'ordre d'initiative
m_accounts = m_accounts .OrderByDescending(x => x.Value.Initiative).ToDictionary(p => p.Key, p2 => p2.Value);
}
Dans la classe MultiAccountController
// ...
public int Initiative { get; private set; }
public void UpdateInitiative(int val)
{
Initiative = val;
}
Compiler et Test le plugin
A savoir que dans ce tutoriel nous avons vu le strict minimum, a presque aucun moment nous avons fait de gestion d'erreur.
Vous n'avez plus cas compiler le plugin, et suivre les opérations dans "Créer un Plugin
".
Last updated