diff --git a/src/server/game/Mercenary/MercenaryMgr.cpp b/src/server/game/Mercenary/MercenaryMgr.cpp index 63c616a..5075e4f 100644 --- a/src/server/game/Mercenary/MercenaryMgr.cpp +++ b/src/server/game/Mercenary/MercenaryMgr.cpp @@ -460,8 +460,9 @@ MercenaryResult MercenaryMgr::Summon(Player* owner, uint8 role, Creature* portal } m_contracts.push_back(contract); - TC_LOG_INFO("server.worldserver", freeOfCharge ? "Mercenaires: %s recoit gratuitement un %3 (compte bot %4), cout %2 po non preleve." : "Mercenaires: %s a paye %u po pour un %s (compte bot %u).", - owner->GetName().c_str(), GetCostGold(), GetRoleName(role), accountId); + TC_LOG_INFO("server.worldserver", "Mercenaires: %s engage un %s (compte bot %u) -- %s.", + owner->GetName().c_str(), GetRoleName(role), accountId, + freeOfCharge ? "recrutement offert" : "100 po preleves"); return MERC_OK; } @@ -657,7 +658,34 @@ void MercenaryMgr::Update(uint32 diff) // le mercenaire a son ancienne place aux yeux de tout le monde. if (it->summonPending) { - if (BotGroupAI* groupAI = dynamic_cast(bot->GetAI())) + // Est-il arrive ? Le point de rendez-vous est le portail quand + // il y en a un, l employeur sinon. + bool arrive = false; + if (it->hasPortal) + arrive = bot->GetMapId() == it->portalMap + && bot->GetExactDist2d(it->portalPos.GetPositionX(), + it->portalPos.GetPositionY()) < MERCENARY_ARRIVAL_RANGE; + else + arrive = bot->GetMapId() == owner->GetMapId() + && bot->GetExactDist2d(owner) < MERCENARY_ARRIVAL_RANGE; + + if (arrive) + it->summonPending = false; + else if (it->summonCheckTimer > 0) + --it->summonCheckTimer; + else if (it->summonAttempts >= MERCENARY_SUMMON_RETRIES) + { + // On cesse d insister : mieux vaut un mercenaire annonce + // perdu qu un mercenaire qu on croit present. + it->summonPending = false; + ChatHandler(owner->GetSession()).PSendSysMessage( + "|cffff4444[Portail]|r %s n'a pas pu vous rejoindre.", bot->GetName().c_str()); + TC_LOG_ERROR("server.worldserver", + "Mercenaires: %s n'a pas rejoint %s apres %u rappels (carte %u).", + bot->GetName().c_str(), owner->GetName().c_str(), + uint32(it->summonAttempts), bot->GetMapId()); + } + else if (BotGroupAI* groupAI = dynamic_cast(bot->GetAI())) { // Repli : sans portail connu, ou si l armement immediat a // echoue, le mercenaire rejoint simplement son employeur. @@ -665,7 +693,9 @@ void MercenaryMgr::Update(uint32 diff) groupAI->TeleportToPoint(it->portalMap, BuildPortalExit(it->portalPos, bot)); else groupAI->ProcessBotCommand(owner, "!summon"); - it->summonPending = false; + + ++it->summonAttempts; + it->summonCheckTimer = MERCENARY_SUMMON_RECHECK; } } @@ -748,7 +778,11 @@ void MercenaryMgr::Update(uint32 diff) if (BotGroupAI* groupAI = dynamic_cast(bot->GetAI())) { groupAI->TeleportToPoint(it->portalMap, BuildPortalExit(it->portalPos, bot)); - it->summonPending = false; + // L ordre est parti, mais rien ne dit encore qu il aboutira : + // on le compte comme une premiere tentative et la verification + // d arrivee prend le relais au tick suivant. + it->summonAttempts = 1; + it->summonCheckTimer = MERCENARY_SUMMON_RECHECK; } } diff --git a/src/server/game/Mercenary/MercenaryMgr.h b/src/server/game/Mercenary/MercenaryMgr.h index e33b3a2..e942517 100644 --- a/src/server/game/Mercenary/MercenaryMgr.h +++ b/src/server/game/Mercenary/MercenaryMgr.h @@ -40,6 +40,18 @@ class Player; #define MERCENARY_GROUP_SIZE 5 #define MERCENARY_HARD_CAP (MERCENARY_GROUP_SIZE - 1) #define MERCENARY_SUMMON_TIMEOUT 60 // secondes avant abandon + remboursement + +// SIGNALE EN JEU : « Semid n est meme pas vers moi, elle est a l autre bout de +// la map ». L ordre de rappel partait une seule fois et le contrat le tenait +// aussitot pour honore. Quand il se perdait -- IA pas encore prete, teleport +// deja en cours, changement de carte -- le mercenaire restait a sa derniere +// position enregistree pour toute la duree du contrat. +// +// On verifie desormais l arrivee, et on renouvelle l ordre tant qu elle ne +// vient pas. +#define MERCENARY_ARRIVAL_RANGE 80.0f // distance au-dela de laquelle il n est pas arrive +#define MERCENARY_SUMMON_RETRIES 4 // ordres de rappel au maximum +#define MERCENARY_SUMMON_RECHECK 3 // secondes entre deux verifications #define MERCENARY_COPPER_PER_GOLD 10000 enum MercenaryStage @@ -66,7 +78,8 @@ enum MercenaryResult struct MercenaryContract { MercenaryContract() : accountId(0), role(0), stage(MERC_STAGE_SUMMONING), waitSeconds(0), - pendingRelease(false), summonPending(false), hasPortal(false), portalMap(0) { } + pendingRelease(false), summonPending(false), summonAttempts(0), + summonCheckTimer(0), hasPortal(false), portalMap(0) { } uint32 accountId; // compte bot reserve ObjectGuid ownerGuid; // joueur qui a paye @@ -84,6 +97,12 @@ struct MercenaryContract // groupe aura reconnu son maitre. bool summonPending; + // Ordres de rappel deja emis, et delai avant de reverifier l arrivee. Un + // teleport de bot se joue en trois echanges : reverifier au tick suivant + // conclurait a un echec alors qu il est simplement en cours de route. + uint8 summonAttempts; + uint32 summonCheckTimer; + // Le portail d ou part l invocation : le mercenaire doit en sortir, pas // se materialiser aux pieds de son employeur reste en retrait. bool hasPortal;