Mercenaires : le mercenaire connait son monde, et sait ou il se tient
Il tenait son role mais parlait dans le vide. Trois ajouts. Un socle sur Azeroth a l heure de la Legion : les Iles Brisees, Dalaran qui flotte, les armes prodigieuses, Sargeras, le retour d Illidan, les continents, les capitales des deux factions, la monnaie. Avec une contrainte qui compte autant que le reste : il n a JAMAIS entendu parler de ce qui vient apres - Kul Tiras, l Ombreterre, les Dragons. Un modele entraine sur tout le corpus de Warcraft racontait sinon des evenements qui n existent pas sur ce royaume. Le lieu reel ensuite : la zone et la sous-zone sont lues dans les tables du client (AreaName->Str[locale]) et injectees a chaque replique. Le mercenaire peut enfin rechigner sur le froid d une region qu il traverse vraiment. Enfin, la relance des refus passagers. Les paliers gratuits repondent regulierement 503 ou 429 ; renoncer au premier essai laissait le mercenaire muet pour une gene d une seconde. Trois tentatives espacees, dans le fil dedie - la boucle du monde n en sait rien. Un refus definitif, lui, n est jamais retente. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "Chat.h"
|
||||
#include "ChatPackets.h"
|
||||
#include "Config.h"
|
||||
#include "DB2Stores.h"
|
||||
#include "Group.h"
|
||||
#include "Log.h"
|
||||
#include "ObjectAccessor.h"
|
||||
@@ -30,7 +31,9 @@
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -468,7 +471,34 @@ std::string MercenaryChatMgr::BuildSystemPrompt(Player* owner, Player* bot) cons
|
||||
<< "!summon). Si ton employeur te demande d'agir en pleine conversation, reponds-lui en personnage "
|
||||
<< "et rappelle-lui de crier son ordre avec le point d'exclamation.";
|
||||
|
||||
prompt << "\nMONDE : nous sommes en Azeroth, au temps de la troisieme invasion de la Legion "
|
||||
<< "ardente. Les Iles Brisees ont resurgi de la mer ; Dalaran la cite mage flotte "
|
||||
<< "au-dessus d elles ; les champions se battent pour des armes prodigieuses. Sargeras "
|
||||
<< "menace le monde, Illidan Hurlorage est revenu d entre les morts. Les continents "
|
||||
<< "connus sont Kalimdor, les Royaumes de l Est, Norfendre, la Pandarie et Draenor. "
|
||||
<< "L Alliance tient Hurlevent, Forgefer, Darnassus, l Exodar et Gilneas ; la Horde "
|
||||
<< "tient Orgrimmar, les Pitons du Tonnerre, Fossoyeuse, Lune-d Argent et la "
|
||||
<< "Baie-du-Butin. On paie en pieces de cuivre, d argent et d or ; cent pieces d or "
|
||||
<< "sont une somme. Tu connais les gobelins marchands, les gryphons et les zeppelins, "
|
||||
<< "les tavernes, les donjons hantes et les demons de la Legion. "
|
||||
<< "Tu n'as JAMAIS entendu parler de ce qui vient apres : ni de la guerre entre l'Alliance "
|
||||
<< "et la Horde a Kul Tiras ou Zandalar, ni de l Ombreterre, ni des Dragons. Ces noms ne "
|
||||
<< "te disent rien, et tu le dis franchement si on t en parle.";
|
||||
|
||||
prompt << "\nSITUATION : ";
|
||||
LocaleConstant const locale = owner->GetSession() ? owner->GetSession()->GetSessionDbcLocale() : LOCALE_frFR;
|
||||
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(bot->GetAreaId()))
|
||||
{
|
||||
prompt << "vous vous tenez a " << area->AreaName->Str[locale];
|
||||
// La sous-zone porte souvent un nom de hameau ; la zone situe la region.
|
||||
if (bot->GetZoneId() != bot->GetAreaId())
|
||||
if (AreaTableEntry const* zone = sAreaTableStore.LookupEntry(bot->GetZoneId()))
|
||||
prompt << ", en " << zone->AreaName->Str[locale];
|
||||
prompt << ". ";
|
||||
}
|
||||
else if (MapEntry const* map = sMapStore.LookupEntry(bot->GetMapId()))
|
||||
prompt << "vous vous tenez en " << map->MapName->Str[locale] << ". ";
|
||||
|
||||
if (Group* group = owner->GetGroup())
|
||||
prompt << "vous chevauchez a " << uint32(group->GetMembersCount()) << " en compagnie. ";
|
||||
|
||||
@@ -656,7 +686,31 @@ std::string MercenaryChatMgr::BuildPayload(MercenaryChatRequest const& request)
|
||||
return json.str();
|
||||
}
|
||||
|
||||
// Un fournisseur sature (503), ou qui trouve le rythme trop soutenu (429),
|
||||
// se remet souvent en une seconde. On retente donc deux fois avant de rendre
|
||||
// les armes, en espacant les tentatives. Ces attentes se passent dans le fil
|
||||
// dedie aux appels : la boucle du monde n en sait rien.
|
||||
bool MercenaryChatMgr::Perform(MercenaryChatRequest const& request, std::string& answer, std::string& error)
|
||||
{
|
||||
uint32 const maxAttempts = 3;
|
||||
for (uint32 attempt = 0; attempt < maxAttempts; ++attempt)
|
||||
{
|
||||
long httpCode = 0;
|
||||
if (PerformOnce(request, answer, error, httpCode))
|
||||
return true;
|
||||
|
||||
// httpCode nul : la connexion elle-meme a echoue, cela aussi se retente.
|
||||
bool const transient = httpCode == 0 || httpCode == 429 || httpCode == 500
|
||||
|| httpCode == 502 || httpCode == 503 || httpCode == 504;
|
||||
if (!transient || attempt + 1 == maxAttempts)
|
||||
return false;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(700 * (attempt + 1)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MercenaryChatMgr::PerformOnce(MercenaryChatRequest const& request, std::string& answer, std::string& error, long& httpCode)
|
||||
{
|
||||
CURL* curl = curl_easy_init();
|
||||
if (!curl)
|
||||
@@ -706,7 +760,7 @@ bool MercenaryChatMgr::Perform(MercenaryChatRequest const& request, std::string&
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "SylvaniaCore-Mercenary/1.0");
|
||||
|
||||
CURLcode const result = curl_easy_perform(curl);
|
||||
long httpCode = 0;
|
||||
httpCode = 0;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
|
||||
|
||||
curl_slist_free_all(headers);
|
||||
@@ -735,6 +789,8 @@ bool MercenaryChatMgr::Perform(MercenaryChatRequest const& request, std::string&
|
||||
text << "Modele introuvable pour votre cle";
|
||||
else if (httpCode == 429)
|
||||
text << "Votre fournisseur refuse le rythme";
|
||||
else if (httpCode == 503 || httpCode == 502 || httpCode == 504)
|
||||
text << "Votre fournisseur est surcharge, reessayez dans un instant";
|
||||
else
|
||||
text << "Le fournisseur a repondu par une erreur";
|
||||
|
||||
|
||||
@@ -164,6 +164,9 @@ class TC_GAME_API MercenaryChatMgr
|
||||
static std::string BuildPayload(MercenaryChatRequest const& request);
|
||||
static std::string BuildUrl(MercenaryChatRequest const& request);
|
||||
static bool Perform(MercenaryChatRequest const& request, std::string& answer, std::string& error);
|
||||
// Un seul aller-retour. Renseigne le code HTTP pour que l appelant
|
||||
// sache si le refus vaut la peine d etre retente.
|
||||
static bool PerformOnce(MercenaryChatRequest const& request, std::string& answer, std::string& error, long& httpCode);
|
||||
static std::string ExtractAnswer(uint8 provider, std::string const& body, std::string& error);
|
||||
|
||||
// Identifiants par employeur.
|
||||
|
||||
Reference in New Issue
Block a user