From 272588ce696862dac622cc5b01c08497e63d1e99 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:12:22 +0100 Subject: [PATCH 01/32] Loot strategy improvement --- conf/playerbots.conf.dist | 42 +- src/PlayerbotAIConfig.cpp | 7 + src/PlayerbotAIConfig.h | 7 + src/strategy/actions/LootRollAction.cpp | 546 +++++++++++++++++++++--- src/strategy/actions/LootRollAction.h | 30 +- 5 files changed, 578 insertions(+), 54 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 47501b29ac..af41ec0de7 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -288,9 +288,47 @@ AiPlayerbot.SayWhenCollectingItems = 1 AiPlayerbot.FreeMethodLoot = 0 # Bots' loot roll level (0 = pass, 1 = greed, 2 = need) -# Default: 1 (greed) +# Default: 1 (greed), recommanded 2 with new loot AI AiPlayerbot.LootRollLevel = 1 +# NEED only if the item matches the bot's MAIN spec (stats & armor/weapon type). +# Off-spec upgrades are automatically downgraded to GREED. +# Recommended default: 1 (enabled) +AiPlayerbot.Roll.SmartNeedBySpec = 1 + +# Bind-on-Equip etiquette: GREED by default to keep it tradeable. +# Set to 1 to allow NEED on BoE if it's a clear upgrade. +# Default: 0 (disabled) +AiPlayerbot.Roll.AllowBoENeedIfUpgrade = 0 + +# Bind-on-Use etiquette: GREED by default to keep it tradeable. +# Set to 1 to allow NEED on BoU if it's a clear upgrade. +# Default: 0 (disabled) +AiPlayerbot.Roll.AllowBoUNeedIfUpgrade = 0 + +# Cross-armor rule (cloth/leather/mail on a plate user, etc.): +# Allow NEED only if newScore >= CrossArmorExtraMargin * bestEquippedScore. +# Recommended default: 1.20 (conservative). Use 9.99 to effectively forbid cross-armor NEED. +AiPlayerbot.Roll.CrossArmorExtraMargin = 1.20 + +# If Need-Before-Greed is active and the item is only useful for disenchanting, +# bots will press the "Disenchant" button instead of GREED. +# Recommended default: 1 (enabled) +AiPlayerbot.Roll.UseDEButton = 1 + +# Minimum item level delta to treat a SET TOKEN as a real upgrade (0 means >=). +# Prevents NEED on same-tier duplicates. +# Example: Paladin Prot with chest ilvl 232: +# - “Trophy of the Crusade” (ilvl 245) => NEED allowed. +# - Token ilvl 232 with TokenILevelMargin=0.1 => GREED (no same-tier NEED). +# Recommended default: 0.1 +AiPlayerbot.Roll.TokenILevelMargin = 0.1 + +# Announce each bot's roll choice to its master via private whisper. +# Useful for debugging; can be noisy in large groups. +# Recommended default: 0 (disabled) +AiPlayerbot.Roll.AnnounceToMaster = 0 + # # # @@ -2055,4 +2093,4 @@ AiPlayerbot.SummonAtInnkeepersEnabled = 1 # 30% more damage, 40% damage reduction (tank bots), increased all resistances, reduced threat for non tank bots, increased threat for tank bots. # Buffs will be applied on PP, Sindragosa and Lich King -AiPlayerbot.EnableICCBuffs = 1 +AiPlayerbot.EnableICCBuffs = 1 \ No newline at end of file diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 7a6fa429d3..f9cb8cac02 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -575,6 +575,13 @@ bool PlayerbotAIConfig::Initialize() autoPickReward = sConfigMgr->GetOption("AiPlayerbot.AutoPickReward", "yes"); autoEquipUpgradeLoot = sConfigMgr->GetOption("AiPlayerbot.AutoEquipUpgradeLoot", true); equipUpgradeThreshold = sConfigMgr->GetOption("AiPlayerbot.EquipUpgradeThreshold", 1.1f); + allowBoENeedIfUpgrade = sConfigMgr->GetOption("AiPlayerbot.Roll.AllowBoENeedIfUpgrade", false); + allowBoUNeedIfUpgrade = sConfigMgr->GetOption("AiPlayerbot.Roll.AllowBoUNeedIfUpgrade", false); + crossArmorExtraMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.CrossArmorExtraMargin", 1.15f); + useDEButton = sConfigMgr->GetOption("AiPlayerbot.Roll.UseDEButton", true); + tokenILevelMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.TokenILevelMargin", 0.0f); + announceLootRollsToMaster = sConfigMgr->GetOption("AiPlayerbot.Roll.AnnounceToMaster", true); + smartNeedBySpec = sConfigMgr->GetOption("AiPlayerbot.Roll.SmartNeedBySpec", true); twoRoundsGearInit = sConfigMgr->GetOption("AiPlayerbot.TwoRoundsGearInit", false); syncQuestWithPlayer = sConfigMgr->GetOption("AiPlayerbot.SyncQuestWithPlayer", true); syncQuestForPlayer = sConfigMgr->GetOption("AiPlayerbot.SyncQuestForPlayer", false); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 36faa98bf7..f9b72fc498 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -326,6 +326,13 @@ class PlayerbotAIConfig std::string autoPickReward; bool autoEquipUpgradeLoot; float equipUpgradeThreshold; + bool allowBoENeedIfUpgrade; // Loot roll fine-tuning + bool allowBoUNeedIfUpgrade; // Allow NEED on BoU if upgrade + float crossArmorExtraMargin; + bool useDEButton; // Allow "Disenchant" on NBG if available + float tokenILevelMargin; // ilvl threshold to consider the token an upgrade + bool announceLootRollsToMaster; // ANotify the bot’s master of the roll choice + bool smartNeedBySpec; // Intelligent NEED (based on stats/spec) bool twoRoundsGearInit; bool syncQuestWithPlayer; bool syncQuestForPlayer; diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index a73e5c75cd..18cedf64c4 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -12,6 +12,284 @@ #include "ObjectMgr.h" #include "PlayerbotAIConfig.h" #include "Playerbots.h" +#include "Player.h" +#include "StatsWeightCalculator.h" +#include +#include +#include +#include +#include "SharedDefines.h" +#include "AiFactory.h" +#include +#include + +// Local helper: not a class member +static bool HasAnyStat(ItemTemplate const* proto, + std::initializer_list mods) +{ + if (!proto) return false; + for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) + { + if (!proto->ItemStat[i].ItemStatValue) continue; + ItemModType t = ItemModType(proto->ItemStat[i].ItemStatType); + for (auto m : mods) + if (t == m) return true; + } + return false; +} + +static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) +{ + if (!bot || !proto) return false; + + // Jewelry/cloaks: focus mainly on the stat profile (stat set) + const bool isJewelry = + proto->InventoryType == INVTYPE_TRINKET || + proto->InventoryType == INVTYPE_FINGER || + proto->InventoryType == INVTYPE_NECK || + proto->InventoryType == INVTYPE_CLOAK; + + const std::string spec = AiFactory::GetPlayerSpecName(bot); + const uint8 cls = bot->getClass(); + + auto specIs = [&](char const* s){ return spec == s; }; + auto specIn = [&](std::initializer_list names){ + for (auto n : names) if (spec == n) return true; + return false; + }; + + // Flags class/spec + const bool isPureCasterClass = (cls == CLASS_MAGE || cls == CLASS_WARLOCK || cls == CLASS_PRIEST); + const bool isHolyPal = (cls == CLASS_PALADIN && spec == "holy"); + const bool isProtPal = (cls == CLASS_PALADIN && (specIs("prot") || specIs("protection"))); + const bool isRetPal = (cls == CLASS_PALADIN && (specIs("retrib") || specIs("ret") || specIs("retribution"))); + + const bool isDK = (cls == CLASS_DEATH_KNIGHT); + const bool isDKBlood = (isDK && specIs("blood")); + const bool isDKFrost = (isDK && specIs("frost")); + const bool isDKUH = (isDK && (specIs("unholy") || specIs("uh"))); + const bool isDKTank = (isDKBlood || isDKFrost) && !isDKUH; // DK tank heuristic (Blood/Frost) + + const bool isWarrior = (cls == CLASS_WARRIOR); + const bool isWarProt = (isWarrior && (specIs("prot") || specIs("protection"))); + + const bool isHunter = (cls == CLASS_HUNTER); // // BM/MM/SV -> physical DPS + const bool isRogue = (cls == CLASS_ROGUE); // Assassination/Combat/Subtlety -> physical DPS + + const bool isShaman = (cls == CLASS_SHAMAN); + const bool isEleSham = (isShaman && specIs("elemental")); + const bool isRestoSh = (isShaman && (specIs("resto") || specIs("restoration"))); + const bool isEnhSham = (isShaman && (specIs("enhance") || specIs("enhancement"))); + + const bool isDruid = (cls == CLASS_DRUID); + const bool isBalance = (isDruid && specIs("balance")); + const bool isRestoDr = (isDruid && (specIs("resto") || specIs("restoration"))); + const bool isFeralTk = (isDruid && (specIs("feraltank") || specIs("bear"))); + const bool isFeralDps= (isDruid && (specIs("feraldps") || specIs("cat") || specIs("kitty"))); + + const bool isCasterSpec = isPureCasterClass || isHolyPal || isEleSham || isRestoSh || isBalance || isRestoDr; + const bool isTankLikeSpec = isProtPal || isWarProt || isFeralTk || isDKTank; + const bool isPhysicalSpec = !isCasterSpec; // Everything that is not a caster -> physical profiles (DK/War/Rogue/Hunter/Ret/Enh/Feral/Prot…) + + // Loot Stats + const bool hasINT = HasAnyStat(proto, { ITEM_MOD_INTELLECT }); + const bool hasSPI = HasAnyStat(proto, { ITEM_MOD_SPIRIT }); + const bool hasMP5 = HasAnyStat(proto, { ITEM_MOD_MANA_REGENERATION }); + const bool hasSP = HasAnyStat(proto, { ITEM_MOD_SPELL_POWER }); + const bool hasSTR = HasAnyStat(proto, { ITEM_MOD_STRENGTH }); + const bool hasAGI = HasAnyStat(proto, { ITEM_MOD_AGILITY }); + const bool hasSTA = HasAnyStat(proto, { ITEM_MOD_STAMINA }); + const bool hasAP = HasAnyStat(proto, { ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER }); + const bool hasARP = HasAnyStat(proto, { ITEM_MOD_ARMOR_PENETRATION_RATING }); + const bool hasEXP = HasAnyStat(proto, { ITEM_MOD_EXPERTISE_RATING }); + const bool hasHIT = HasAnyStat(proto, { ITEM_MOD_HIT_RATING }); + const bool hasHASTE = HasAnyStat(proto, { ITEM_MOD_HASTE_RATING }); + const bool hasCRIT = HasAnyStat(proto, { ITEM_MOD_CRIT_RATING }); + const bool hasDef = HasAnyStat(proto, { ITEM_MOD_DEFENSE_SKILL_RATING }); + const bool hasAvoid = HasAnyStat(proto, { ITEM_MOD_DODGE_RATING, ITEM_MOD_PARRY_RATING, ITEM_MOD_BLOCK_RATING }); + + /// Quick profiles + const bool looksCaster = hasSP || hasSPI || hasMP5 || (hasINT && !hasSTR && !hasAGI && !hasAP); + const bool looksPhysical = hasSTR || hasAGI || hasAP || hasARP || hasEXP; + const bool hasDpsRatings = hasHIT || hasHASTE || hasCRIT; // Common to all DPS (physical & casters) + + // Generic rules by role/family + if (isPhysicalSpec) + { + // (1) All physicals/tanks: never Spell Power/Spirit/MP5 (even if plate/mail) + if (looksCaster) + return false; + // (2) Weapon/shield with Spell Power: always off-spec for DK/War/Rogue/Hunter/Ret/Enh/Feral/Prot + if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) + && hasSP) + return false; + // (3) Jewelry/cloaks with caster stats (SP/SPI/MP5/pure INT) -> off-spec + if (isJewelry && looksCaster) + return false; + } + else // Caster/Healer + { + // (1) Casters/healers should not NEED pure melee items (STR/AP/ARP/EXP) without INT/SP + if (looksPhysical && !hasSP && !hasINT) + return false; + // (2) Melee jewelry (AP/ARP/EXP/STR/AGI) without INT/SP -> off-spec + if (isJewelry && looksPhysical && !hasSP && !hasINT) + return false; + // Paladin Holy (plate INT+SP/MP5), Shaman Elemental/Restoration (mail INT+SP/MP5), + // Druid Balance/Restoration (leather/cloth caster) → OK + } + + // Class/spec specific adjustments (readable) + // DK Unholy (DPS): allows STR/HIT/HASTE/CRIT/ARP; rejects all caster items + if (isDKUH) + { + if (looksCaster) return false; + } + // DK Blood/Frost tanks: DEF/AVOID/STA/STR are useful; reject caster items + if (isDKTank) + { + if (looksCaster) return false; + // Pure caster DPS rings/trinkets already filtered above. + } + // Hunter (BM/MM/SV): agi/hit/haste/AP/crit/arp → OK; avoid STR-only or caster items + if (isHunter) + { + if (looksCaster) return false; + // Avoid rings with "pure STR" without AGI/AP/DPS ratings + if (isJewelry && hasSTR && !hasAGI && !hasAP && !hasDpsRatings) + return false; + } + // Rogue (all specs): same strict physical filter (no caster items) + if (isRogue) + { + if (looksCaster) return false; + } + // Warrior Arms/Fury : no caster items + if (isWarrior && !isWarProt) + { + if (looksCaster) return false; + } + // Warrior Protection: DEF/AVOID/STA/STR are useful; no caster items + if (isWarProt) + { + if (looksCaster) return false; + } + // Shaman Enhancement: no Spell Power weapons/shields, no pure INT/SP items + if (isEnhSham) + { + if (looksCaster) return false; + if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) + && hasSP) + return false; + } + // Druid Feral (tank/DPS): AGI/STA/AVOID/ARP/EXP → OK; no caster items + if (isFeralTk || isFeralDps) + { + if (looksCaster) return false; + } + + // Let the cross-armor rules (CrossArmorExtraMargin) decide for major off-armor upgrades. + return true; +} + + +// Local mini-helper: maps an InventoryType (INVTYPE_*) to an EquipmentSlot (EQUIPMENT_SLOT_*) +// Only covers the slots relevant for T7-T10 tokens (head/shoulders/chest/hands/legs). +static uint8 EquipmentSlotByInvTypeSafe(uint8 invType) +{ + switch (invType) + { + case INVTYPE_HEAD: return EQUIPMENT_SLOT_HEAD; + case INVTYPE_SHOULDERS: return EQUIPMENT_SLOT_SHOULDERS; + case INVTYPE_CHEST: + case INVTYPE_ROBE: return EQUIPMENT_SLOT_CHEST; + case INVTYPE_HANDS: return EQUIPMENT_SLOT_HANDS; + case INVTYPE_LEGS: return EQUIPMENT_SLOT_LEGS; + default: return EQUIPMENT_SLOT_END; // inconnu/nonnull + } +} + +// All equippable items -> corresponding slots +static void GetEquipSlotsForInvType(uint8 invType, std::vector& out) +{ + out.clear(); + switch (invType) + { + case INVTYPE_HEAD: out = {EQUIPMENT_SLOT_HEAD}; break; + case INVTYPE_NECK: out = {EQUIPMENT_SLOT_NECK}; break; + case INVTYPE_SHOULDERS: out = {EQUIPMENT_SLOT_SHOULDERS}; break; + case INVTYPE_BODY: /* shirt, ignore */ break; + case INVTYPE_CHEST: + case INVTYPE_ROBE: out = {EQUIPMENT_SLOT_CHEST}; break; + case INVTYPE_WAIST: out = {EQUIPMENT_SLOT_WAIST}; break; + case INVTYPE_LEGS: out = {EQUIPMENT_SLOT_LEGS}; break; + case INVTYPE_FEET: out = {EQUIPMENT_SLOT_FEET}; break; + case INVTYPE_WRISTS: out = {EQUIPMENT_SLOT_WRISTS}; break; + case INVTYPE_HANDS: out = {EQUIPMENT_SLOT_HANDS}; break; + case INVTYPE_FINGER: out = {EQUIPMENT_SLOT_FINGER1, EQUIPMENT_SLOT_FINGER2}; break; + case INVTYPE_TRINKET: out = {EQUIPMENT_SLOT_TRINKET1, EQUIPMENT_SLOT_TRINKET2}; break; + case INVTYPE_CLOAK: out = {EQUIPMENT_SLOT_BACK}; break; + case INVTYPE_WEAPON: out = {EQUIPMENT_SLOT_MAINHAND, EQUIPMENT_SLOT_OFFHAND}; break; + case INVTYPE_2HWEAPON: out = {EQUIPMENT_SLOT_MAINHAND}; break; + case INVTYPE_SHIELD: out = {EQUIPMENT_SLOT_OFFHAND}; break; + case INVTYPE_WEAPONMAINHAND: out = {EQUIPMENT_SLOT_MAINHAND}; break; + case INVTYPE_WEAPONOFFHAND: out = {EQUIPMENT_SLOT_OFFHAND}; break; + case INVTYPE_HOLDABLE: out = {EQUIPMENT_SLOT_OFFHAND}; break; // tome/orb + case INVTYPE_RANGED: + case INVTYPE_THROWN: + case INVTYPE_RANGEDRIGHT: out = {EQUIPMENT_SLOT_RANGED}; break; + case INVTYPE_RELIC: out = {EQUIPMENT_SLOT_RANGED}; break; // totem/idol/sigil/libram + case INVTYPE_TABARD: + case INVTYPE_BAG: + case INVTYPE_AMMO: + case INVTYPE_QUIVER: + default: break; // not relevant for gear + } +} + +// Internal prototypes +static bool CanBotUseToken(ItemTemplate const* proto, Player* bot); +static bool RollUniqueCheck(ItemTemplate const* proto, Player* bot); + +// Internal helpers +// Deduces the target slot from the token's name. +// Returns an expected InventoryType (HEAD/SHOULDERS/CHEST/HANDS/LEGS) or -1 if unknown. +static int8 TokenSlotFromName(ItemTemplate const* proto) +{ + if (!proto) return -1; + std::string n = std::string(proto->Name1); + std::transform(n.begin(), n.end(), n.begin(), + [](unsigned char c){ + return static_cast(std::tolower(c)); + }); + if (n.find("helm") != std::string::npos || n.find("head") != std::string::npos) + return INVTYPE_HEAD; + if (n.find("shoulder") != std::string::npos || n.find("mantle") != std::string::npos || n.find("spauld") != std::string::npos) + return INVTYPE_SHOULDERS; + if (n.find("chest") != std::string::npos || n.find("tunic") != std::string::npos || n.find("robe") != std::string::npos || n.find("breastplate") != std::string::npos || n.find("chestguard") != std::string::npos) + return INVTYPE_CHEST; + if (n.find("glove") != std::string::npos || n.find("handguard") != std::string::npos || n.find("gauntlet") != std::string::npos) + return INVTYPE_HANDS; + if (n.find("leg") != std::string::npos || n.find("pant") != std::string::npos || n.find("trouser") != std::string::npos) + return INVTYPE_LEGS; + return -1; +} + +// Upgrade heuristic for a token: if the slot is known, +// consider it a "likely upgrade" if ilvl(token) >= ilvl(best equipped item in that slot) + margin. +static bool IsTokenLikelyUpgrade(ItemTemplate const* token, uint8 invTypeSlot, Player* bot) +{ + if (!token || !bot) return false; + uint8 eq = EquipmentSlotByInvTypeSafe(invTypeSlot); + if (eq >= EQUIPMENT_SLOT_END) + return true; // unknown slot -> do not block Need + Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, eq); + if (!oldItem) return true; // empty slot -> guaranteed upgrade + ItemTemplate const* oldProto = oldItem->GetTemplate(); + if (!oldProto) return true; + float margin = sPlayerbotAIConfig->tokenILevelMargin; // configurable + return (float)token->ItemLevel >= (float)oldProto->ItemLevel + margin; +} bool LootRollAction::Execute(Event event) { @@ -27,7 +305,6 @@ bool LootRollAction::Execute(Event event) continue; } ObjectGuid guid = roll->itemGUID; - uint32 slot = roll->itemSlot; uint32 itemId = roll->itemid; int32 randomProperty = 0; if (roll->itemRandomPropId) @@ -35,12 +312,13 @@ bool LootRollAction::Execute(Event event) else if (roll->itemRandomSuffix) randomProperty = -((int)roll->itemRandomSuffix); - RollVote vote = PASS; ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (!proto) continue; - + + RollVote vote = PASS; std::string itemUsageParam; + if (randomProperty != 0) { itemUsageParam = std::to_string(itemId) + "," + std::to_string(randomProperty); } else { @@ -48,39 +326,47 @@ bool LootRollAction::Execute(Event event) } ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam); - // Armor Tokens are classed as MISC JUNK (Class 15, Subclass 0), luckily no other items I found have class bits and epic quality. + // Armor Tokens are classed as MISC JUNK (Class 15, Subclass 0), but no other items have class bits and epic quality. + // - CanBotUseToken(proto, bot) => NEED + // - else => GREED if (proto->Class == ITEM_CLASS_MISC && proto->SubClass == ITEM_SUBCLASS_JUNK && proto->Quality == ITEM_QUALITY_EPIC) { if (CanBotUseToken(proto, bot)) { - vote = NEED; // Eligible for "Need" + // vote = NEED; // Eligible for Need + // Token mainspec: NEED only if the corresponding slot piece would be a real upgrade + int8 tokenSlot = TokenSlotFromName(proto); + if (tokenSlot >= 0) + { + if (IsTokenLikelyUpgrade(proto, (uint8)tokenSlot, bot)) + vote = NEED; + else + vote = GREED; + } + else + { + // Unknown slot (e.g. T10 sanctification tokens) + vote = GREED; + } } else { - vote = GREED; // Not eligible, so "Greed" + vote = GREED; // Not eligible, so Greed } } else { - switch (proto->Class) - { - case ITEM_CLASS_WEAPON: - case ITEM_CLASS_ARMOR: - if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP) - { - vote = NEED; - } - else if (usage != ITEM_USAGE_NONE) - { - vote = GREED; - } - break; - default: - if (StoreLootAction::IsLootAllowed(itemId, botAI)) - vote = CalculateRollVote(proto); // Ensure correct Need/Greed behavior - break; - } + // Let CalculateRollVote decide (includes SmartNeedBySpec, BoE/BoU, unique, cross-armor) + vote = CalculateRollVote(proto, randomProperty); } + + // Disenchant button (Need-Before-Greed): if useful for DE, prefer DE over Greed + if (vote == GREED && usage == ITEM_USAGE_DISENCHANT && sPlayerbotAIConfig->useDEButton) + { + if (group && group->GetLootMethod() == NEED_BEFORE_GREED) + vote = DISENCHANT; + } + if (sPlayerbotAIConfig->lootRollLevel == 0) { vote = PASS; @@ -103,16 +389,12 @@ bool LootRollAction::Execute(Event event) vote = PASS; } } - switch (group->GetLootMethod()) - { - case MASTER_LOOT: - case FREE_FOR_ALL: - group->CountRollVote(bot->GetGUID(), guid, PASS); - break; - default: - group->CountRollVote(bot->GetGUID(), guid, vote); - break; - } + // Announce + send the roll vote (if ML/FFA => PASS) + RollVote sent = vote; + if (group->GetLootMethod() == MASTER_LOOT || group->GetLootMethod() == FREE_FOR_ALL) + sent = PASS; + AnnounceRollChoice(sent, itemId); + group->CountRollVote(bot->GetGUID(), guid, sent); // One item at a time return true; } @@ -121,35 +403,168 @@ bool LootRollAction::Execute(Event event) } -RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto) +RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 randomProperty) { + // Player mimic: upgrade => NEED; useful => GREED; otherwise => PASS std::ostringstream out; - out << proto->ItemId; + if (randomProperty != 0) + out << proto->ItemId << "," << randomProperty; + else + out << proto->ItemId; ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", out.str()); - RollVote needVote = PASS; + RollVote vote = PASS; switch (usage) { case ITEM_USAGE_EQUIP: case ITEM_USAGE_REPLACE: - case ITEM_USAGE_GUILD_TASK: + vote = NEED; + // Downgrade to GREED if the item does not match the main spec + if (sPlayerbotAIConfig->smartNeedBySpec && !IsPrimaryForSpec(bot, proto)) + vote = GREED; + break; case ITEM_USAGE_BAD_EQUIP: - needVote = NEED; - break; + case ITEM_USAGE_GUILD_TASK: case ITEM_USAGE_SKILL: case ITEM_USAGE_USE: case ITEM_USAGE_DISENCHANT: case ITEM_USAGE_AH: case ITEM_USAGE_VENDOR: - needVote = GREED; + case ITEM_USAGE_KEEP: + case ITEM_USAGE_AMMO: + vote = GREED; break; default: + vote = PASS; break; } + // VETO “physical -> caster” (safety net): + // even if ItemUsage returned EQUIP/REPLACE, a physical character should never NEED a caster-profile item. + if (vote == NEED && sPlayerbotAIConfig->smartNeedBySpec) + { + const std::string spec = AiFactory::GetPlayerSpecName(bot); + const uint8 cls = bot->getClass(); + auto specIs = [&](char const* s){ return spec == s; }; + const bool isPhysicalSpec = + !(cls == CLASS_MAGE || cls == CLASS_WARLOCK || cls == CLASS_PRIEST) && + !(cls == CLASS_PALADIN && spec == "holy") && + !(cls == CLASS_SHAMAN && (specIs("elemental") || specIs("resto") || specIs("restoration"))) && + !(cls == CLASS_DRUID && (specIs("balance") || specIs("resto") || specIs("restoration"))); + + const bool hasINT = HasAnyStat(proto, { ITEM_MOD_INTELLECT }); + const bool hasSPI = HasAnyStat(proto, { ITEM_MOD_SPIRIT }); + const bool hasMP5 = HasAnyStat(proto, { ITEM_MOD_MANA_REGENERATION }); + const bool hasSP = HasAnyStat(proto, { ITEM_MOD_SPELL_POWER }); + const bool hasMelee = HasAnyStat(proto, { ITEM_MOD_STRENGTH, ITEM_MOD_AGILITY, + ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER }); + const bool looksCaster = hasSP || hasSPI || hasMP5 || (hasINT && !hasMelee); + + if (isPhysicalSpec && looksCaster) + vote = GREED; // force GREED for rogue/hunter/warrior/DK/retribution/enhancement/feral/protection, etc. + } + + // Generic BoP rule: if the item is BoP, equippable, matches the spec + // AND at least one relevant slot is empty -> allow NEED + constexpr uint32 BIND_WHEN_PICKED_UP = 1; + if (vote != NEED && proto->Bonding == BIND_WHEN_PICKED_UP) + { + std::vector slots; GetEquipSlotsForInvType(proto->InventoryType, slots); + if (!slots.empty()) + { + const bool specOk = !sPlayerbotAIConfig->smartNeedBySpec || IsPrimaryForSpec(bot, proto); + if (specOk) + { + for (uint8 s : slots) + { + if (!bot->GetItemByPos(INVENTORY_SLOT_BAG_0, s)) + { + vote = NEED; // fills an empty slot -> NEED + break; + } + } + } + } + } + + // BoE/BoU rule: by default, avoid NEED on Bind-on-Equip / Bind-on-Use (raid etiquette) + constexpr uint32 BIND_WHEN_EQUIPPED = 2; // BoE + constexpr uint32 BIND_WHEN_USE = 3; // BoU + if (vote == NEED && proto->Bonding == BIND_WHEN_EQUIPPED && !sPlayerbotAIConfig->allowBoENeedIfUpgrade) + { + vote = GREED; + } + if (vote == NEED && proto->Bonding == BIND_WHEN_USE && !sPlayerbotAIConfig->allowBoUNeedIfUpgrade) + { + vote = GREED; + } - return StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? needVote : PASS; + // Unique-equip: never NEED a duplicate (already equipped/owned) + if (vote == NEED && RollUniqueCheck(proto, bot)) + { + vote = PASS; + } + + // Cross-armor: if BAD_EQUIP (e.g. cloth for paladin), allow NEED only if it's a massive upgrade + if (vote == GREED && usage == ITEM_USAGE_BAD_EQUIP && proto->Class == ITEM_CLASS_ARMOR) + { + StatsWeightCalculator calc(bot); + float newScore = calc.CalculateItem(proto->ItemId); + float bestOld = 0.0f; + // Find the best currently equipped item of the same InventoryType + for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) + { + Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + if (!oldItem) continue; + ItemTemplate const* oldProto = oldItem->GetTemplate(); + if (!oldProto) continue; + if (oldProto->Class != ITEM_CLASS_ARMOR) continue; + if (oldProto->InventoryType != proto->InventoryType) continue; + float oldScore = calc.CalculateItem(oldProto->ItemId, oldItem->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID)); + if (oldScore > bestOld) bestOld = oldScore; + } + if (bestOld > 0.0f && newScore >= bestOld * sPlayerbotAIConfig->crossArmorExtraMargin) + vote = NEED; + } + + // Final filter: loot strategy + return StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? vote : PASS; +} + +// Helpers d'annonce +const char* LootRollAction::RollVoteToText(RollVote v) const +{ + switch (v) + { + case NEED: return "NEED"; + case GREED: return "GREED"; + case PASS: return "PASS"; + case DISENCHANT: return "DISENCHANT"; + default: return "PASS"; + } +} + +void LootRollAction::AnnounceRollChoice(RollVote vote, uint32 itemId) +{ + if (!sPlayerbotAIConfig->announceLootRollsToMaster) + return; + + Player* master = botAI->GetMaster(); + if (!master) + return; + + std::ostringstream ss; + if (ItemTemplate const* ip = sObjectMgr->GetItemTemplate(itemId)) + ss << "[Loot] " << bot->GetName() << " choisit " << RollVoteToText(vote) + << " sur [" << ip->Name1 << "]"; + else + ss << "[Loot] " << bot->GetName() << " choisit " << RollVoteToText(vote) + << " sur item " << itemId; + + // Message to Master + botAI->TellMaster(ss.str()); } + bool MasterLootRollAction::isUseful() { return !botAI->HasActivePlayerMaster(); } bool MasterLootRollAction::Execute(Event event) @@ -168,7 +583,7 @@ bool MasterLootRollAction::Execute(Event event) p.rpos(0); // reset packet pointer p >> creatureGuid; // creature guid what we're looting - p >> mapId; /// 3.3.3 mapid + p >> mapId; // 3.3.3 mapid p >> itemSlot; // the itemEntryId for the item that shall be rolled for p >> itemId; // the itemEntryId for the item that shall be rolled for p >> randomSuffix; // randomSuffix @@ -184,13 +599,47 @@ bool MasterLootRollAction::Execute(Event event) if (!group) return false; - RollVote vote = CalculateRollVote(proto); - group->CountRollVote(bot->GetGUID(), creatureGuid, CalculateRollVote(proto)); + // 1) Token heuristic: ONLY NEED if the target slot is a likely upgrade + RollVote vote = PASS; + if (proto->Class == ITEM_CLASS_MISC && proto->SubClass == ITEM_SUBCLASS_JUNK && proto->Quality == ITEM_QUALITY_EPIC) + { + if (CanBotUseToken(proto, bot)) + { + int8 tokenSlot = TokenSlotFromName(proto); // Internal helper + if (tokenSlot >= 0) + vote = IsTokenLikelyUpgrade(proto, (uint8)tokenSlot, bot) ? NEED : GREED; + else + vote = GREED; // Unknow slot + } + else + { + vote = GREED; + } + } + else + { + vote = CalculateRollVote(proto, randomPropertyId ? (int32)randomPropertyId : (randomSuffix ? -(int32)randomSuffix : 0)); + } + + // 2) Disenchant button in Need-Before-Greed if the usage is "DISENCHANT" + if (vote == GREED && sPlayerbotAIConfig->useDEButton && group->GetLootMethod() == NEED_BEFORE_GREED) + { + std::ostringstream out; out << itemId; + ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", out.str()); + if (usage == ITEM_USAGE_DISENCHANT) + vote = DISENCHANT; + } + + RollVote sent = vote; + if (group->GetLootMethod() == MASTER_LOOT || group->GetLootMethod() == FREE_FOR_ALL) + sent = PASS; + AnnounceRollChoice(sent, itemId); + group->CountRollVote(bot->GetGUID(), creatureGuid, sent); return true; } -bool CanBotUseToken(ItemTemplate const* proto, Player* bot) +static bool CanBotUseToken(ItemTemplate const* proto, Player* bot) { // Get the bitmask for the bot's class uint32 botClassMask = (1 << (bot->getClass() - 1)); @@ -204,7 +653,7 @@ bool CanBotUseToken(ItemTemplate const* proto, Player* bot) return false; // Bot's class cannot use this token } -bool RollUniqueCheck(ItemTemplate const* proto, Player* bot) +static bool RollUniqueCheck(ItemTemplate const* proto, Player* bot) { // Count the total number of the item (equipped + in bags) uint32 totalItemCount = bot->GetItemCount(proto->ItemId, true); @@ -251,7 +700,8 @@ bool RollAction::Execute(Event event) { case ITEM_CLASS_WEAPON: case ITEM_CLASS_ARMOR: - if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP) + //if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP) + if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE) { bot->DoRandomRoll(0,100); } diff --git a/src/strategy/actions/LootRollAction.h b/src/strategy/actions/LootRollAction.h index 2582274c79..6516f3c61d 100644 --- a/src/strategy/actions/LootRollAction.h +++ b/src/strategy/actions/LootRollAction.h @@ -7,6 +7,7 @@ #define _PLAYERBOT_LOOTROLLACTION_H #include "QueryItemUsageAction.h" +#include "ItemTemplate.h" class PlayerbotAI; @@ -22,12 +23,33 @@ class LootRollAction : public QueryItemUsageAction bool Execute(Event event) override; protected: - RollVote CalculateRollVote(ItemTemplate const* proto); + /** + * Default roll rule (outside Master Loot & outside tokens): + * - NEED if direct upgrade (ItemUsage = EQUIP/REPLACE) + * - GREED if useful but not an upgrade (BAD_EQUIP, USE, SKILL, DISENCHANT, AH, VENDOR, KEEP, AMMO) + * - PASS otherwise + * + * Safeguards: + * - SmartNeedBySpec: downgrade NEED->GREED if the item does not match the bot's main spec + * - BoP: if at least one relevant slot is empty, allow NEED (if spec is valid) + * - BoE/BoU: NEED blocked unless explicitly allowed by config (AllowBoENeedIfUpgrade / AllowBoUNeedIfUpgrade) + * - Cross-armor: BAD_EQUIP can become NEED only if newScore >= bestScore * CrossArmorExtraMargin + * + * Specific cases: + * - Tokens: NEED only if the targeted slot is a likely upgrade (ilvl heuristic), + * otherwise GREED (tokens with unknown slot remain GREED by default) + * - Disenchant (NBG): if ItemUsage = DISENCHANT and config enabled, vote DISENCHANT + * (the core enforces if the DE button is actually available) + */ + + // randomProperty: 0 (none) ; >0 = itemRandomPropId ; <0 = -itemRandomSuffix + RollVote CalculateRollVote(ItemTemplate const* proto, int32 randomProperty = 0); + + // Announce the roll choice to the bot's master (if enabled in config) + void AnnounceRollChoice(RollVote vote, uint32 itemId); + const char* RollVoteToText(RollVote v) const; }; -bool CanBotUseToken(ItemTemplate const* proto, Player* bot); -bool RollUniqueCheck(ItemTemplate const* proto, Player* bot); - class MasterLootRollAction : public LootRollAction { public: From ef4fe3c00fa971eff9834b8b0dd196bd49911b38 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Wed, 3 Sep 2025 15:36:15 +0100 Subject: [PATCH 02/32] Changes asked on review --- conf/playerbots.conf.dist | 18 +++++------ src/strategy/actions/LootRollAction.cpp | 42 +++++++++++++++++++------ 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index af41ec0de7..7bd73edc1c 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -293,27 +293,27 @@ AiPlayerbot.LootRollLevel = 1 # NEED only if the item matches the bot's MAIN spec (stats & armor/weapon type). # Off-spec upgrades are automatically downgraded to GREED. -# Recommended default: 1 (enabled) +# Default: 1 (enabled) AiPlayerbot.Roll.SmartNeedBySpec = 1 # Bind-on-Equip etiquette: GREED by default to keep it tradeable. # Set to 1 to allow NEED on BoE if it's a clear upgrade. -# Default: 0 (disabled) -AiPlayerbot.Roll.AllowBoENeedIfUpgrade = 0 +# Default: 1 (enabled) +AiPlayerbot.Roll.AllowBoENeedIfUpgrade = 1 # Bind-on-Use etiquette: GREED by default to keep it tradeable. # Set to 1 to allow NEED on BoU if it's a clear upgrade. -# Default: 0 (disabled) -AiPlayerbot.Roll.AllowBoUNeedIfUpgrade = 0 +# Default: (enabled) +AiPlayerbot.Roll.AllowBoUNeedIfUpgrade = 1 # Cross-armor rule (cloth/leather/mail on a plate user, etc.): # Allow NEED only if newScore >= CrossArmorExtraMargin * bestEquippedScore. -# Recommended default: 1.20 (conservative). Use 9.99 to effectively forbid cross-armor NEED. +# Default: 1.20 (conservative). Use 9.99 to effectively forbid cross-armor NEED. AiPlayerbot.Roll.CrossArmorExtraMargin = 1.20 # If Need-Before-Greed is active and the item is only useful for disenchanting, # bots will press the "Disenchant" button instead of GREED. -# Recommended default: 1 (enabled) +# Default: 1 (enabled) AiPlayerbot.Roll.UseDEButton = 1 # Minimum item level delta to treat a SET TOKEN as a real upgrade (0 means >=). @@ -321,12 +321,12 @@ AiPlayerbot.Roll.UseDEButton = 1 # Example: Paladin Prot with chest ilvl 232: # - “Trophy of the Crusade” (ilvl 245) => NEED allowed. # - Token ilvl 232 with TokenILevelMargin=0.1 => GREED (no same-tier NEED). -# Recommended default: 0.1 +# Default: 0.1 AiPlayerbot.Roll.TokenILevelMargin = 0.1 # Announce each bot's roll choice to its master via private whisper. # Useful for debugging; can be noisy in large groups. -# Recommended default: 0 (disabled) +# Default: 0 (disabled) AiPlayerbot.Roll.AnnounceToMaster = 0 # diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 18cedf64c4..86d22d207b 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -23,6 +23,15 @@ #include #include +// Encode "random enchant" parameter for CalculateRollVote / ItemUsage +// >0 => randomPropertyId, <0 => randomSuffixId, 0 => none +static inline int32 EncodeRandomEnchantParam(uint32 randomPropertyId, uint32 randomSuffix) +{ + if (randomPropertyId) return static_cast(randomPropertyId); + if (randomSuffix) return -static_cast(randomSuffix); + return 0; +} + // Local helper: not a class member static bool HasAnyStat(ItemTemplate const* proto, std::initializer_list mods) @@ -188,6 +197,17 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (looksCaster) return false; } + // Global VETO global: a physical character should never NEED a caster-profile item. + if (sPlayerbotAIConfig->smartNeedBySpec) + { + const bool isPhysicalSpec = !(isPureCasterClass || isHolyPal || isEleSham || isRestoSh || isBalance || isRestoDr); + const bool hasMelee = hasSTR || hasAGI || hasAP || hasARP || hasEXP; + const bool looksCaster2 = hasSP || hasSPI || hasMP5 || (hasINT && !hasMelee); + + if (isPhysicalSpec && looksCaster2) + return false; + } + // Let the cross-armor rules (CrossArmorExtraMargin) decide for major off-armor upgrades. return true; } @@ -306,12 +326,13 @@ bool LootRollAction::Execute(Event event) } ObjectGuid guid = roll->itemGUID; uint32 itemId = roll->itemid; - int32 randomProperty = 0; + /*int32 randomProperty = 0; if (roll->itemRandomPropId) randomProperty = roll->itemRandomPropId; else if (roll->itemRandomSuffix) - randomProperty = -((int)roll->itemRandomSuffix); - + randomProperty = -((int)roll->itemRandomSuffix);*/ + int32 randomProperty = EncodeRandomEnchantParam(roll->itemRandomPropId, roll->itemRandomSuffix); + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (!proto) continue; @@ -438,7 +459,7 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand vote = PASS; break; } - // VETO “physical -> caster” (safety net): + /*// VETO “physical -> caster” (safety net): // even if ItemUsage returned EQUIP/REPLACE, a physical character should never NEED a caster-profile item. if (vote == NEED && sPlayerbotAIConfig->smartNeedBySpec) { @@ -461,7 +482,7 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand if (isPhysicalSpec && looksCaster) vote = GREED; // force GREED for rogue/hunter/warrior/DK/retribution/enhancement/feral/protection, etc. - } + }*/ // Generic BoP rule: if the item is BoP, equippable, matches the spec // AND at least one relevant slot is empty -> allow NEED @@ -554,11 +575,11 @@ void LootRollAction::AnnounceRollChoice(RollVote vote, uint32 itemId) std::ostringstream ss; if (ItemTemplate const* ip = sObjectMgr->GetItemTemplate(itemId)) - ss << "[Loot] " << bot->GetName() << " choisit " << RollVoteToText(vote) - << " sur [" << ip->Name1 << "]"; + ss << "[Loot] " << bot->GetName() << " choose " << RollVoteToText(vote) + << " on [" << ip->Name1 << "]"; else - ss << "[Loot] " << bot->GetName() << " choisit " << RollVoteToText(vote) - << " sur item " << itemId; + ss << "[Loot] " << bot->GetName() << " choose " << RollVoteToText(vote) + << " on item " << itemId; // Message to Master botAI->TellMaster(ss.str()); @@ -618,7 +639,8 @@ bool MasterLootRollAction::Execute(Event event) } else { - vote = CalculateRollVote(proto, randomPropertyId ? (int32)randomPropertyId : (randomSuffix ? -(int32)randomSuffix : 0)); + //vote = CalculateRollVote(proto, randomPropertyId ? (int32)randomPropertyId : (randomSuffix ? -(int32)randomSuffix : 0)); + vote = CalculateRollVote(proto, EncodeRandomEnchantParam(randomPropertyId, randomSuffix)); } // 2) Disenchant button in Need-Before-Greed if the usage is "DISENCHANT" From aa17c07cac7bd65f0455e0853b3c4481932f19b3 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Thu, 4 Sep 2025 18:50:46 +0100 Subject: [PATCH 03/32] Final version --- conf/playerbots.conf.dist | 4 +- src/strategy/actions/LootRollAction.cpp | 410 ++++++++++++++++++------ 2 files changed, 313 insertions(+), 101 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 7bd73edc1c..bfa16dc131 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -288,8 +288,8 @@ AiPlayerbot.SayWhenCollectingItems = 1 AiPlayerbot.FreeMethodLoot = 0 # Bots' loot roll level (0 = pass, 1 = greed, 2 = need) -# Default: 1 (greed), recommanded 2 with new loot AI -AiPlayerbot.LootRollLevel = 1 +# Default: 2 (need), recommanded 2 with new loot AI +AiPlayerbot.LootRollLevel = 2 # NEED only if the item matches the bot's MAIN spec (stats & armor/weapon type). # Off-spec upgrades are automatically downgraded to GREED. diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 86d22d207b..3b67e142d5 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -23,13 +23,108 @@ #include #include -// Encode "random enchant" parameter for CalculateRollVote / ItemUsage -// >0 => randomPropertyId, <0 => randomSuffixId, 0 => none -static inline int32 EncodeRandomEnchantParam(uint32 randomPropertyId, uint32 randomSuffix) +// Groups the "class + archetype" info in the same place +struct SpecTraits { - if (randomPropertyId) return static_cast(randomPropertyId); - if (randomSuffix) return -static_cast(randomSuffix); - return 0; + uint8 cls = 0; + std::string spec; + bool isCaster = false; // everything that affects SP/INT/SPI/MP5 + bool isHealer = false; + bool isTank = false; + bool isPhysical = false; // profiles STR/AGI/AP/ARP/EXP… + // Useful flags for fine rules + bool isDKTank = false; + bool isWarProt = false; + bool isEnhSham = false; + bool isFeralTk = false; + bool isFeralDps = false; + bool isHunter = false; + bool isRogue = false; + bool isWarrior = false; + bool isRetPal = false; +}; + +static SpecTraits GetSpecTraits(Player* bot) +{ + SpecTraits t; + if (!bot) return t; + t.cls = bot->getClass(); + t.spec = AiFactory::GetPlayerSpecName(bot); + + auto specIs = [&](char const* s){ return t.spec == s; }; + + // "Pure caster" classes + const bool pureCasterClass = (t.cls == CLASS_MAGE || t.cls == CLASS_WARLOCK || t.cls == CLASS_PRIEST); + + // Paladin + const bool holyPal = (t.cls == CLASS_PALADIN && specIs("holy")); + const bool protPal = (t.cls == CLASS_PALADIN && (specIs("prot") || specIs("protection"))); + t.isRetPal = (t.cls == CLASS_PALADIN && !holyPal && !protPal); + // DK + const bool dk = (t.cls == CLASS_DEATH_KNIGHT); + const bool dkBlood = dk && specIs("blood"); + const bool dkFrost = dk && specIs("frost"); + const bool dkUH = dk && (specIs("unholy") || specIs("uh")); + t.isDKTank = (dkBlood || dkFrost) && !dkUH; // tanks “blood/frost” + // Warrior + t.isWarrior = (t.cls == CLASS_WARRIOR); + t.isWarProt = t.isWarrior && (specIs("prot") || specIs("protection")); + // Hunter & Rogue + t.isHunter = (t.cls == CLASS_HUNTER); + t.isRogue = (t.cls == CLASS_ROGUE); + // Shaman + const bool eleSham = (t.cls == CLASS_SHAMAN && specIs("elemental")); + const bool restoSh = (t.cls == CLASS_SHAMAN && (specIs("resto") || specIs("restoration"))); + t.isEnhSham = (t.cls == CLASS_SHAMAN && (specIs("enhance") || specIs("enhancement"))); + // Druid + const bool balance = (t.cls == CLASS_DRUID && specIs("balance")); + const bool restoDr = (t.cls == CLASS_DRUID && (specIs("resto") || specIs("restoration"))); + t.isFeralTk = (t.cls == CLASS_DRUID && (specIs("feraltank") || specIs("bear"))); + t.isFeralDps = (t.cls == CLASS_DRUID && (specIs("feraldps") || specIs("cat") || specIs("kitty"))); + + // Roles + t.isHealer = holyPal || restoSh || restoDr || (t.cls == CLASS_PRIEST && !specIs("shadow")); + t.isTank = protPal || t.isWarProt || t.isFeralTk || t.isDKTank; + t.isCaster = pureCasterClass || holyPal || eleSham || balance || restoDr || restoSh + || (t.cls == CLASS_PRIEST && specIs("shadow")); // Shadow = caster DPS + t.isPhysical = !t.isCaster; + return t; +} + +// Local helper: identifies classic lockboxes the Rogue can pick. +// Heuristic: items with a LockID and “misc/junk” class often are lockboxes. +// Also fall back to a name check (“lockbox”, “coffre”) to cover edge DBs. +static bool IsLockbox(ItemTemplate const* proto) +{ + if (!proto) return false; + if (proto->LockID) + { + // Most lockboxes are misc/junk and openable. + if (proto->Class == ITEM_CLASS_MISC) + return true; + } + // Fallback on localized name check + static const std::vector lockboxKeywords = { + "lockbox", // English + "coffre", // French + "schließkassette", // German + "caja fuerte", // Spanish + "сундук", // Russian + "잠긴", // Korean + "锁箱", // Simplified Chinese + "鎖箱" // Traditional Chinese + }; + + std::string n = proto->Name1; + std::transform(n.begin(), n.end(), n.begin(), + [](unsigned char c){ return (c >= 'A' && c <= 'Z') ? char(c + 32) : char(c); }); + for (auto const& kw : lockboxKeywords) + { + const bool ascii = std::all_of(kw.begin(), kw.end(), [](unsigned char c){ return c < 0x80; }); + if ((ascii && n.find(kw) != std::string::npos) || (!ascii && std::string(proto->Name1).find(kw) != std::string::npos)) + return true; + } + return false; } // Local helper: not a class member @@ -47,6 +142,117 @@ static bool HasAnyStat(ItemTemplate const* proto, return false; } +// Encode "random enchant" parameter for CalculateRollVote / ItemUsage +// >0 => randomPropertyId, <0 => randomSuffixId, 0 => none +static inline int32 EncodeRandomEnchantParam(uint32 randomPropertyId, uint32 randomSuffix) +{ + if (randomPropertyId) return static_cast(randomPropertyId); + if (randomSuffix) return -static_cast(randomSuffix); + return 0; +} + +// Weapon/shield/relic whitelist per class. +// Returns false when the item is a WEAPON / SHIELD / RELIC the class should NOT use. +static bool IsWeaponOrShieldOrRelicAllowedForClass(SpecTraits const& T, ItemTemplate const* proto) +{ + if (!proto) return true; // non-weapon items handled elsewhere + + // Shields (Armor + Shield): Paladin / Warrior / Shaman + if ((proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD) || + proto->InventoryType == INVTYPE_SHIELD) + return T.cls == CLASS_PALADIN || T.cls == CLASS_WARRIOR || T.cls == CLASS_SHAMAN; + + // Relics (Idol/Totem/Sigil/Libram) + if (proto->InventoryType == INVTYPE_RELIC) + { + // DK (Sigil), Druid (Idol), Paladin (Libram), Shaman (Totem) + return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_DRUID || + T.cls == CLASS_PALADIN || T.cls == CLASS_SHAMAN; + } + + // Not a weapon: nothing to filter here + if (proto->Class != ITEM_CLASS_WEAPON) + return true; + + switch (proto->SubClass) + { + // Axes + case ITEM_SUBCLASS_WEAPON_AXE: + case ITEM_SUBCLASS_WEAPON_AXE2: + // 1H axes allowed for Rogue; 2H axes not (but same SubClass enum, handled by InventoryType later if needed) + return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_HUNTER || + T.cls == CLASS_PALADIN || T.cls == CLASS_SHAMAN || + T.cls == CLASS_WARRIOR || T.cls == CLASS_ROGUE; // Rogue: 1H axes + + // Swords + case ITEM_SUBCLASS_WEAPON_SWORD: // 1H swords + return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_HUNTER || + T.cls == CLASS_MAGE || T.cls == CLASS_PALADIN || + T.cls == CLASS_ROGUE || T.cls == CLASS_WARRIOR || + T.cls == CLASS_WARLOCK; // Warlocks can use 1H swords + case ITEM_SUBCLASS_WEAPON_SWORD2: // 2H swords + return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_HUNTER || + T.cls == CLASS_PALADIN || T.cls == CLASS_WARRIOR; + + // Maces + case ITEM_SUBCLASS_WEAPON_MACE: // 1H maces + return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_DRUID || + T.cls == CLASS_PALADIN || T.cls == CLASS_PRIEST || + T.cls == CLASS_SHAMAN || T.cls == CLASS_WARRIOR || + T.cls == CLASS_ROGUE; // Rogue: 1H maces in WotLK + case ITEM_SUBCLASS_WEAPON_MACE2: // 2H maces + return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_DRUID || + T.cls == CLASS_PALADIN || T.cls == CLASS_WARRIOR; // Shaman: no 2H maces + + // Polearms + case ITEM_SUBCLASS_WEAPON_POLEARM: + return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_DRUID || + T.cls == CLASS_HUNTER || T.cls == CLASS_PALADIN || + T.cls == CLASS_WARRIOR; // Shaman: cannot use polearms + + // Staves + case ITEM_SUBCLASS_WEAPON_STAFF: + return T.cls == CLASS_DRUID || T.cls == CLASS_HUNTER || + T.cls == CLASS_MAGE || T.cls == CLASS_PRIEST || + T.cls == CLASS_SHAMAN || T.cls == CLASS_WARLOCK; + + // Daggers + case ITEM_SUBCLASS_WEAPON_DAGGER: + return T.cls == CLASS_DRUID || T.cls == CLASS_HUNTER || + T.cls == CLASS_MAGE || T.cls == CLASS_PRIEST || + T.cls == CLASS_ROGUE || T.cls == CLASS_WARLOCK || + T.cls == CLASS_WARRIOR; // Warriors can use daggers + + // Fist weapons + case ITEM_SUBCLASS_WEAPON_FIST: + return T.cls == CLASS_DRUID || T.cls == CLASS_HUNTER || + T.cls == CLASS_ROGUE || T.cls == CLASS_SHAMAN || + T.cls == CLASS_WARRIOR; + + // Ranged (bows / guns / crossbows) — Hunters primary; also usable by Warriors/Rogues + case ITEM_SUBCLASS_WEAPON_BOW: + case ITEM_SUBCLASS_WEAPON_GUN: + case ITEM_SUBCLASS_WEAPON_CROSSBOW: + return T.cls == CLASS_HUNTER || T.cls == CLASS_WARRIOR || T.cls == CLASS_ROGUE; + + // Wands — only Mage/Priest/Warlock + case ITEM_SUBCLASS_WEAPON_WAND: + return T.cls == CLASS_MAGE || T.cls == CLASS_PRIEST || T.cls == CLASS_WARLOCK; + + // Thrown — Warriors/Rogues (Hunters rarely need them; bows/guns/xbows preferred) + case ITEM_SUBCLASS_WEAPON_THROWN: + return T.cls == CLASS_WARRIOR || T.cls == CLASS_ROGUE; + + // Exotic / fishing / misc — disallow + case ITEM_SUBCLASS_WEAPON_EXOTIC: + case ITEM_SUBCLASS_WEAPON_EXOTIC2: + case ITEM_SUBCLASS_WEAPON_MISC: + case ITEM_SUBCLASS_WEAPON_FISHING_POLE: + default: + return false; + } +} + static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) { if (!bot || !proto) return false; @@ -58,47 +264,18 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) proto->InventoryType == INVTYPE_NECK || proto->InventoryType == INVTYPE_CLOAK; - const std::string spec = AiFactory::GetPlayerSpecName(bot); - const uint8 cls = bot->getClass(); + const SpecTraits T = GetSpecTraits(bot); - auto specIs = [&](char const* s){ return spec == s; }; - auto specIn = [&](std::initializer_list names){ - for (auto n : names) if (spec == n) return true; + + // Hard filter first: do not NEED weapons/shields/relics the class shouldn't use. + // If this returns false, the caller will downgrade to GREED (off-spec/unsupported). + if (!IsWeaponOrShieldOrRelicAllowedForClass(T, proto)) return false; - }; // Flags class/spec - const bool isPureCasterClass = (cls == CLASS_MAGE || cls == CLASS_WARLOCK || cls == CLASS_PRIEST); - const bool isHolyPal = (cls == CLASS_PALADIN && spec == "holy"); - const bool isProtPal = (cls == CLASS_PALADIN && (specIs("prot") || specIs("protection"))); - const bool isRetPal = (cls == CLASS_PALADIN && (specIs("retrib") || specIs("ret") || specIs("retribution"))); - - const bool isDK = (cls == CLASS_DEATH_KNIGHT); - const bool isDKBlood = (isDK && specIs("blood")); - const bool isDKFrost = (isDK && specIs("frost")); - const bool isDKUH = (isDK && (specIs("unholy") || specIs("uh"))); - const bool isDKTank = (isDKBlood || isDKFrost) && !isDKUH; // DK tank heuristic (Blood/Frost) - - const bool isWarrior = (cls == CLASS_WARRIOR); - const bool isWarProt = (isWarrior && (specIs("prot") || specIs("protection"))); - - const bool isHunter = (cls == CLASS_HUNTER); // // BM/MM/SV -> physical DPS - const bool isRogue = (cls == CLASS_ROGUE); // Assassination/Combat/Subtlety -> physical DPS - - const bool isShaman = (cls == CLASS_SHAMAN); - const bool isEleSham = (isShaman && specIs("elemental")); - const bool isRestoSh = (isShaman && (specIs("resto") || specIs("restoration"))); - const bool isEnhSham = (isShaman && (specIs("enhance") || specIs("enhancement"))); - - const bool isDruid = (cls == CLASS_DRUID); - const bool isBalance = (isDruid && specIs("balance")); - const bool isRestoDr = (isDruid && (specIs("resto") || specIs("restoration"))); - const bool isFeralTk = (isDruid && (specIs("feraltank") || specIs("bear"))); - const bool isFeralDps= (isDruid && (specIs("feraldps") || specIs("cat") || specIs("kitty"))); - - const bool isCasterSpec = isPureCasterClass || isHolyPal || isEleSham || isRestoSh || isBalance || isRestoDr; - const bool isTankLikeSpec = isProtPal || isWarProt || isFeralTk || isDKTank; - const bool isPhysicalSpec = !isCasterSpec; // Everything that is not a caster -> physical profiles (DK/War/Rogue/Hunter/Ret/Enh/Feral/Prot…) + const bool isCasterSpec = T.isCaster; + const bool isTankLikeSpec = T.isTank; + const bool isPhysicalSpec = T.isPhysical; // Loot Stats const bool hasINT = HasAnyStat(proto, { ITEM_MOD_INTELLECT }); @@ -117,11 +294,20 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) const bool hasDef = HasAnyStat(proto, { ITEM_MOD_DEFENSE_SKILL_RATING }); const bool hasAvoid = HasAnyStat(proto, { ITEM_MOD_DODGE_RATING, ITEM_MOD_PARRY_RATING, ITEM_MOD_BLOCK_RATING }); - /// Quick profiles + // Quick profiles const bool looksCaster = hasSP || hasSPI || hasMP5 || (hasINT && !hasSTR && !hasAGI && !hasAP); const bool looksPhysical = hasSTR || hasAGI || hasAP || hasARP || hasEXP; const bool hasDpsRatings = hasHIT || hasHASTE || hasCRIT; // Common to all DPS (physical & casters) + // Tank-only profile: Defense / Avoidance (dodge/parry/block rating) / Block value + // Do NOT tag all shields as "tank": there are caster shields (INT/SP/MP5) + const bool hasBlockValue = HasAnyStat(proto, { ITEM_MOD_BLOCK_VALUE }); + const bool looksTank = hasDef || hasAvoid || hasBlockValue; + + // Non-tanks (DPS, casters/heals) never NEED purely tank items + if (!isTankLikeSpec && looksTank) + return false; + // Generic rules by role/family if (isPhysicalSpec) { @@ -148,20 +334,38 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // Druid Balance/Restoration (leather/cloth caster) → OK } + // Extra weapon sanity for Hunters/Ferals (avoid wrong stat-sticks): + // - Hunters: for melee weapons, require AGI (prevent Haste/AP-only daggers without AGI). + // - Feral (tank/DPS): for melee weapons, require AGI or STR. + if (proto->Class == ITEM_CLASS_WEAPON) + { + const bool meleeWeapon = + proto->InventoryType == INVTYPE_WEAPON || + proto->InventoryType == INVTYPE_WEAPONMAINHAND || + proto->InventoryType == INVTYPE_WEAPONOFFHAND || + proto->InventoryType == INVTYPE_2HWEAPON; + + if (meleeWeapon && T.isHunter && !hasAGI) + return false; + + if (meleeWeapon && (T.isFeralTk || T.isFeralDps) && !hasAGI && !hasSTR) + return false; + } + // Class/spec specific adjustments (readable) // DK Unholy (DPS): allows STR/HIT/HASTE/CRIT/ARP; rejects all caster items - if (isDKUH) + if (/* DK Unholy */ (T.cls == CLASS_DEATH_KNIGHT && (T.spec == "unholy" || T.spec == "uh"))) { if (looksCaster) return false; } // DK Blood/Frost tanks: DEF/AVOID/STA/STR are useful; reject caster items - if (isDKTank) + if (T.isDKTank) { if (looksCaster) return false; // Pure caster DPS rings/trinkets already filtered above. } // Hunter (BM/MM/SV): agi/hit/haste/AP/crit/arp → OK; avoid STR-only or caster items - if (isHunter) + if (T.isHunter) { if (looksCaster) return false; // Avoid rings with "pure STR" without AGI/AP/DPS ratings @@ -169,45 +373,62 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) return false; } // Rogue (all specs): same strict physical filter (no caster items) - if (isRogue) + if (T.isRogue) { if (looksCaster) return false; } // Warrior Arms/Fury : no caster items - if (isWarrior && !isWarProt) + if (T.isWarrior && !T.isWarProt) { if (looksCaster) return false; } // Warrior Protection: DEF/AVOID/STA/STR are useful; no caster items - if (isWarProt) + if (T.isWarProt) { if (looksCaster) return false; } // Shaman Enhancement: no Spell Power weapons/shields, no pure INT/SP items - if (isEnhSham) + if (T.isEnhSham) { if (looksCaster) return false; if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && hasSP) return false; } - // Druid Feral (tank/DPS): AGI/STA/AVOID/ARP/EXP → OK; no caster items - if (isFeralTk || isFeralDps) + // Druid Feral (tank/DPS): AGI/STA/AVOID/ARP/EXP -> OK; no caster items + if (T.isFeralTk || T.isFeralDps) { if (looksCaster) return false; } - // Global VETO global: a physical character should never NEED a caster-profile item. - if (sPlayerbotAIConfig->smartNeedBySpec) + // Paladin Retribution: physical DPS (no caster items; forbid SP weapons/shields; enforce 2H only) + if (T.isRetPal) { - const bool isPhysicalSpec = !(isPureCasterClass || isHolyPal || isEleSham || isRestoSh || isBalance || isRestoDr); - const bool hasMelee = hasSTR || hasAGI || hasAP || hasARP || hasEXP; - const bool looksCaster2 = hasSP || hasSPI || hasMP5 || (hasINT && !hasMelee); - - if (isPhysicalSpec && looksCaster2) + if (looksCaster) return false; + + // No Spell Power weapons or shields for Ret + if ((proto->Class == ITEM_CLASS_WEAPON || + (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && hasSP) return false; + + // Enforce 2H only (no 1H/off-hand/shields/holdables) + switch (proto->InventoryType) + { + case INVTYPE_WEAPON: // generic 1H + case INVTYPE_WEAPONMAINHAND: // explicit main-hand 1H + case INVTYPE_WEAPONOFFHAND: // off-hand weapon + case INVTYPE_SHIELD: // shields + case INVTYPE_HOLDABLE: // tomes/orbs + return false; // never NEED for Ret + default: + break; // INVTYPE_2HWEAPON is allowed; others handled elsewhere + } } + // Global VETO: a "physical" spec never considers a caster profile as primary + if (sPlayerbotAIConfig->smartNeedBySpec && T.isPhysical && looksCaster) + return false; + // Let the cross-armor rules (CrossArmorExtraMargin) decide for major off-armor upgrades. return true; } @@ -225,7 +446,7 @@ static uint8 EquipmentSlotByInvTypeSafe(uint8 invType) case INVTYPE_ROBE: return EQUIPMENT_SLOT_CHEST; case INVTYPE_HANDS: return EQUIPMENT_SLOT_HANDS; case INVTYPE_LEGS: return EQUIPMENT_SLOT_LEGS; - default: return EQUIPMENT_SLOT_END; // inconnu/nonnull + default: return EQUIPMENT_SLOT_END; // unknown/not applicable } } @@ -320,19 +541,17 @@ bool LootRollAction::Execute(Event event) std::vector rolls = group->GetRolls(); for (Roll*& roll : rolls) { - if (roll->playerVote.find(bot->GetGUID())->second != NOT_EMITED_YET) + // Avoid server crash, key may not exit for the bot on login + auto it = roll->playerVote.find(bot->GetGUID()); + if (it != roll->playerVote.end() && it->second != NOT_EMITED_YET) { continue; } + ObjectGuid guid = roll->itemGUID; uint32 itemId = roll->itemid; - /*int32 randomProperty = 0; - if (roll->itemRandomPropId) - randomProperty = roll->itemRandomPropId; - else if (roll->itemRandomSuffix) - randomProperty = -((int)roll->itemRandomSuffix);*/ int32 randomProperty = EncodeRandomEnchantParam(roll->itemRandomPropId, roll->itemRandomSuffix); - + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (!proto) continue; @@ -459,30 +678,13 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand vote = PASS; break; } - /*// VETO “physical -> caster” (safety net): - // even if ItemUsage returned EQUIP/REPLACE, a physical character should never NEED a caster-profile item. - if (vote == NEED && sPlayerbotAIConfig->smartNeedBySpec) - { - const std::string spec = AiFactory::GetPlayerSpecName(bot); - const uint8 cls = bot->getClass(); - auto specIs = [&](char const* s){ return spec == s; }; - const bool isPhysicalSpec = - !(cls == CLASS_MAGE || cls == CLASS_WARLOCK || cls == CLASS_PRIEST) && - !(cls == CLASS_PALADIN && spec == "holy") && - !(cls == CLASS_SHAMAN && (specIs("elemental") || specIs("resto") || specIs("restoration"))) && - !(cls == CLASS_DRUID && (specIs("balance") || specIs("resto") || specIs("restoration"))); - - const bool hasINT = HasAnyStat(proto, { ITEM_MOD_INTELLECT }); - const bool hasSPI = HasAnyStat(proto, { ITEM_MOD_SPIRIT }); - const bool hasMP5 = HasAnyStat(proto, { ITEM_MOD_MANA_REGENERATION }); - const bool hasSP = HasAnyStat(proto, { ITEM_MOD_SPELL_POWER }); - const bool hasMelee = HasAnyStat(proto, { ITEM_MOD_STRENGTH, ITEM_MOD_AGILITY, - ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER }); - const bool looksCaster = hasSP || hasSPI || hasMP5 || (hasINT && !hasMelee); - - if (isPhysicalSpec && looksCaster) - vote = GREED; // force GREED for rogue/hunter/warrior/DK/retribution/enhancement/feral/protection, etc. - }*/ + + // Lockboxes: if the item is a lockbox and the bot is a Rogue with Lockpicking, prefer NEED. + // (Handled before BoE/BoU etiquette; BoE/BoU checks below ignore lockboxes.) + const SpecTraits T = GetSpecTraits(bot); + const bool isLockbox = IsLockbox(proto); + if (isLockbox && T.isRogue && bot->HasSkill(SKILL_LOCKPICKING)) + vote = NEED; // Generic BoP rule: if the item is BoP, equippable, matches the spec // AND at least one relevant slot is empty -> allow NEED @@ -510,15 +712,24 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand // BoE/BoU rule: by default, avoid NEED on Bind-on-Equip / Bind-on-Use (raid etiquette) constexpr uint32 BIND_WHEN_EQUIPPED = 2; // BoE constexpr uint32 BIND_WHEN_USE = 3; // BoU - if (vote == NEED && proto->Bonding == BIND_WHEN_EQUIPPED && !sPlayerbotAIConfig->allowBoENeedIfUpgrade) + if (vote == NEED && !isLockbox && proto->Bonding == BIND_WHEN_EQUIPPED && !sPlayerbotAIConfig->allowBoENeedIfUpgrade) { vote = GREED; } - if (vote == NEED && proto->Bonding == BIND_WHEN_USE && !sPlayerbotAIConfig->allowBoUNeedIfUpgrade) + if (vote == NEED && !isLockbox && proto->Bonding == BIND_WHEN_USE && !sPlayerbotAIConfig->allowBoUNeedIfUpgrade) { vote = GREED; } + // Duplicate soft rule (non-unique): if the bot already owns at least one copy in bags, downgrade NEED to GREED. + // This complements "unique-equip" and avoids ninja-need on duplicates that are not unique. + if (vote == NEED) + { + // includeBank=true to catch banked duplicates as well; adjust if undesired. + if (bot->GetItemCount(proto->ItemId, true) > 0) + vote = GREED; + } + // Unique-equip: never NEED a duplicate (already equipped/owned) if (vote == NEED && RollUniqueCheck(proto, bot)) { @@ -547,8 +758,11 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand vote = NEED; } - // Final filter: loot strategy - return StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? vote : PASS; + // return StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? vote : PASS; + // Final filter: loot strategy (protect a potential nil AI earlier on login + if (PlayerbotAI* ai = GET_PLAYERBOT_AI(bot)) + return StoreLootAction::IsLootAllowed(proto->ItemId, ai) ? vote : PASS; + return PASS; } // Helpers d'annonce @@ -639,8 +853,7 @@ bool MasterLootRollAction::Execute(Event event) } else { - //vote = CalculateRollVote(proto, randomPropertyId ? (int32)randomPropertyId : (randomSuffix ? -(int32)randomSuffix : 0)); - vote = CalculateRollVote(proto, EncodeRandomEnchantParam(randomPropertyId, randomSuffix)); + vote = CalculateRollVote(proto, EncodeRandomEnchantParam(randomPropertyId, randomSuffix)); } // 2) Disenchant button in Need-Before-Greed if the usage is "DISENCHANT" @@ -722,7 +935,6 @@ bool RollAction::Execute(Event event) { case ITEM_CLASS_WEAPON: case ITEM_CLASS_ARMOR: - //if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP) if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE) { bot->DoRandomRoll(0,100); From 02eca5b2a8323b9f0109911692a98c8a9ebcf707 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:42:08 +0200 Subject: [PATCH 04/32] Review correction --- src/strategy/actions/LootRollAction.cpp | 130 ++++++++++++------------ src/strategy/actions/LootRollAction.h | 2 +- 2 files changed, 64 insertions(+), 68 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 3b67e142d5..46aa395991 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -153,21 +153,21 @@ static inline int32 EncodeRandomEnchantParam(uint32 randomPropertyId, uint32 ran // Weapon/shield/relic whitelist per class. // Returns false when the item is a WEAPON / SHIELD / RELIC the class should NOT use. -static bool IsWeaponOrShieldOrRelicAllowedForClass(SpecTraits const& T, ItemTemplate const* proto) +static bool IsWeaponOrShieldOrRelicAllowedForClass(SpecTraits const& traits, ItemTemplate const* proto) { if (!proto) return true; // non-weapon items handled elsewhere // Shields (Armor + Shield): Paladin / Warrior / Shaman if ((proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD) || proto->InventoryType == INVTYPE_SHIELD) - return T.cls == CLASS_PALADIN || T.cls == CLASS_WARRIOR || T.cls == CLASS_SHAMAN; + return traits.cls == CLASS_PALADIN || traits.cls == CLASS_WARRIOR || traits.cls == CLASS_SHAMAN; // Relics (Idol/Totem/Sigil/Libram) if (proto->InventoryType == INVTYPE_RELIC) { // DK (Sigil), Druid (Idol), Paladin (Libram), Shaman (Totem) - return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_DRUID || - T.cls == CLASS_PALADIN || T.cls == CLASS_SHAMAN; + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || + traits.cls == CLASS_PALADIN || traits.cls == CLASS_SHAMAN; } // Not a weapon: nothing to filter here @@ -180,68 +180,68 @@ static bool IsWeaponOrShieldOrRelicAllowedForClass(SpecTraits const& T, ItemTemp case ITEM_SUBCLASS_WEAPON_AXE: case ITEM_SUBCLASS_WEAPON_AXE2: // 1H axes allowed for Rogue; 2H axes not (but same SubClass enum, handled by InventoryType later if needed) - return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_HUNTER || - T.cls == CLASS_PALADIN || T.cls == CLASS_SHAMAN || - T.cls == CLASS_WARRIOR || T.cls == CLASS_ROGUE; // Rogue: 1H axes + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_HUNTER || + traits.cls == CLASS_PALADIN || traits.cls == CLASS_SHAMAN || + traits.cls == CLASS_WARRIOR || traits.cls == CLASS_ROGUE; // Rogue: 1H axes // Swords case ITEM_SUBCLASS_WEAPON_SWORD: // 1H swords - return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_HUNTER || - T.cls == CLASS_MAGE || T.cls == CLASS_PALADIN || - T.cls == CLASS_ROGUE || T.cls == CLASS_WARRIOR || - T.cls == CLASS_WARLOCK; // Warlocks can use 1H swords + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_HUNTER || + traits.cls == CLASS_MAGE || traits.cls == CLASS_PALADIN || + traits.cls == CLASS_ROGUE || traits.cls == CLASS_WARRIOR || + traits.cls == CLASS_WARLOCK; // Warlocks can use 1H swords case ITEM_SUBCLASS_WEAPON_SWORD2: // 2H swords - return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_HUNTER || - T.cls == CLASS_PALADIN || T.cls == CLASS_WARRIOR; + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_HUNTER || + traits.cls == CLASS_PALADIN || traits.cls == CLASS_WARRIOR; // Maces case ITEM_SUBCLASS_WEAPON_MACE: // 1H maces - return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_DRUID || - T.cls == CLASS_PALADIN || T.cls == CLASS_PRIEST || - T.cls == CLASS_SHAMAN || T.cls == CLASS_WARRIOR || - T.cls == CLASS_ROGUE; // Rogue: 1H maces in WotLK + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || + traits.cls == CLASS_PALADIN || traits.cls == CLASS_PRIEST || + traits.cls == CLASS_SHAMAN || traits.cls == CLASS_WARRIOR || + traits.cls == CLASS_ROGUE; // Rogue: 1H maces in WotLK case ITEM_SUBCLASS_WEAPON_MACE2: // 2H maces - return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_DRUID || - T.cls == CLASS_PALADIN || T.cls == CLASS_WARRIOR; // Shaman: no 2H maces + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || + traits.cls == CLASS_PALADIN || traits.cls == CLASS_WARRIOR; // Shaman: no 2H maces // Polearms case ITEM_SUBCLASS_WEAPON_POLEARM: - return T.cls == CLASS_DEATH_KNIGHT || T.cls == CLASS_DRUID || - T.cls == CLASS_HUNTER || T.cls == CLASS_PALADIN || - T.cls == CLASS_WARRIOR; // Shaman: cannot use polearms + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || + traits.cls == CLASS_HUNTER || traits.cls == CLASS_PALADIN || + traits.cls == CLASS_WARRIOR; // Shaman: cannot use polearms // Staves case ITEM_SUBCLASS_WEAPON_STAFF: - return T.cls == CLASS_DRUID || T.cls == CLASS_HUNTER || - T.cls == CLASS_MAGE || T.cls == CLASS_PRIEST || - T.cls == CLASS_SHAMAN || T.cls == CLASS_WARLOCK; + return traits.cls == CLASS_DRUID || traits.cls == CLASS_HUNTER || + traits.cls == CLASS_MAGE || traits.cls == CLASS_PRIEST || + traits.cls == CLASS_SHAMAN || traits.cls == CLASS_WARLOCK; // Daggers case ITEM_SUBCLASS_WEAPON_DAGGER: - return T.cls == CLASS_DRUID || T.cls == CLASS_HUNTER || - T.cls == CLASS_MAGE || T.cls == CLASS_PRIEST || - T.cls == CLASS_ROGUE || T.cls == CLASS_WARLOCK || - T.cls == CLASS_WARRIOR; // Warriors can use daggers + return traits.cls == CLASS_DRUID || traits.cls == CLASS_HUNTER || + traits.cls == CLASS_MAGE || traits.cls == CLASS_PRIEST || + traits.cls == CLASS_ROGUE || traits.cls == CLASS_WARLOCK || + traits.cls == CLASS_WARRIOR; // Warriors can use daggers // Fist weapons case ITEM_SUBCLASS_WEAPON_FIST: - return T.cls == CLASS_DRUID || T.cls == CLASS_HUNTER || - T.cls == CLASS_ROGUE || T.cls == CLASS_SHAMAN || - T.cls == CLASS_WARRIOR; + return traits.cls == CLASS_DRUID || traits.cls == CLASS_HUNTER || + traits.cls == CLASS_ROGUE || traits.cls == CLASS_SHAMAN || + traits.cls == CLASS_WARRIOR; // Ranged (bows / guns / crossbows) — Hunters primary; also usable by Warriors/Rogues case ITEM_SUBCLASS_WEAPON_BOW: case ITEM_SUBCLASS_WEAPON_GUN: case ITEM_SUBCLASS_WEAPON_CROSSBOW: - return T.cls == CLASS_HUNTER || T.cls == CLASS_WARRIOR || T.cls == CLASS_ROGUE; + return traits.cls == CLASS_HUNTER || traits.cls == CLASS_WARRIOR || traits.cls == CLASS_ROGUE; // Wands — only Mage/Priest/Warlock case ITEM_SUBCLASS_WEAPON_WAND: - return T.cls == CLASS_MAGE || T.cls == CLASS_PRIEST || T.cls == CLASS_WARLOCK; + return traits.cls == CLASS_MAGE || traits.cls == CLASS_PRIEST || traits.cls == CLASS_WARLOCK; // Thrown — Warriors/Rogues (Hunters rarely need them; bows/guns/xbows preferred) case ITEM_SUBCLASS_WEAPON_THROWN: - return T.cls == CLASS_WARRIOR || T.cls == CLASS_ROGUE; + return traits.cls == CLASS_WARRIOR || traits.cls == CLASS_ROGUE; // Exotic / fishing / misc — disallow case ITEM_SUBCLASS_WEAPON_EXOTIC: @@ -264,18 +264,17 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) proto->InventoryType == INVTYPE_NECK || proto->InventoryType == INVTYPE_CLOAK; - const SpecTraits T = GetSpecTraits(bot); - + const SpecTraits traits = GetSpecTraits(bot); // Hard filter first: do not NEED weapons/shields/relics the class shouldn't use. // If this returns false, the caller will downgrade to GREED (off-spec/unsupported). - if (!IsWeaponOrShieldOrRelicAllowedForClass(T, proto)) + if (!IsWeaponOrShieldOrRelicAllowedForClass(traits, proto)) return false; // Flags class/spec - const bool isCasterSpec = T.isCaster; - const bool isTankLikeSpec = T.isTank; - const bool isPhysicalSpec = T.isPhysical; + const bool isCasterSpec = traits.isCaster; + const bool isTankLikeSpec = traits.isTank; + const bool isPhysicalSpec = traits.isPhysical; // Loot Stats const bool hasINT = HasAnyStat(proto, { ITEM_MOD_INTELLECT }); @@ -345,27 +344,27 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) proto->InventoryType == INVTYPE_WEAPONOFFHAND || proto->InventoryType == INVTYPE_2HWEAPON; - if (meleeWeapon && T.isHunter && !hasAGI) + if (meleeWeapon && traits.isHunter && !hasAGI) return false; - if (meleeWeapon && (T.isFeralTk || T.isFeralDps) && !hasAGI && !hasSTR) + if (meleeWeapon && (traits.isFeralTk || traits.isFeralDps) && !hasAGI && !hasSTR) return false; } // Class/spec specific adjustments (readable) // DK Unholy (DPS): allows STR/HIT/HASTE/CRIT/ARP; rejects all caster items - if (/* DK Unholy */ (T.cls == CLASS_DEATH_KNIGHT && (T.spec == "unholy" || T.spec == "uh"))) + if (traits.cls == CLASS_DEATH_KNIGHT && (traits.spec == "unholy" || traits.spec == "uh")) { if (looksCaster) return false; } // DK Blood/Frost tanks: DEF/AVOID/STA/STR are useful; reject caster items - if (T.isDKTank) + if (traits.isDKTank) { if (looksCaster) return false; // Pure caster DPS rings/trinkets already filtered above. } // Hunter (BM/MM/SV): agi/hit/haste/AP/crit/arp → OK; avoid STR-only or caster items - if (T.isHunter) + if (traits.isHunter) { if (looksCaster) return false; // Avoid rings with "pure STR" without AGI/AP/DPS ratings @@ -373,36 +372,36 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) return false; } // Rogue (all specs): same strict physical filter (no caster items) - if (T.isRogue) + if (traits.isRogue) { if (looksCaster) return false; } // Warrior Arms/Fury : no caster items - if (T.isWarrior && !T.isWarProt) + if (traits.isWarrior && !traits.isWarProt) { if (looksCaster) return false; } // Warrior Protection: DEF/AVOID/STA/STR are useful; no caster items - if (T.isWarProt) + if (traits.isWarProt) { if (looksCaster) return false; } // Shaman Enhancement: no Spell Power weapons/shields, no pure INT/SP items - if (T.isEnhSham) + if (traits.isEnhSham) { if (looksCaster) return false; if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && hasSP) return false; } - // Druid Feral (tank/DPS): AGI/STA/AVOID/ARP/EXP -> OK; no caster items - if (T.isFeralTk || T.isFeralDps) + // Druid Feral (tank/DPS): AGI/STA/AVOID/ARP/EXP → OK; no caster items + if (traits.isFeralTk || traits.isFeralDps) { if (looksCaster) return false; } // Paladin Retribution: physical DPS (no caster items; forbid SP weapons/shields; enforce 2H only) - if (T.isRetPal) + if (traits.isRetPal) { if (looksCaster) return false; @@ -681,9 +680,9 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand // Lockboxes: if the item is a lockbox and the bot is a Rogue with Lockpicking, prefer NEED. // (Handled before BoE/BoU etiquette; BoE/BoU checks below ignore lockboxes.) - const SpecTraits T = GetSpecTraits(bot); + const SpecTraits traits = GetSpecTraits(bot); const bool isLockbox = IsLockbox(proto); - if (isLockbox && T.isRogue && bot->HasSkill(SKILL_LOCKPICKING)) + if (isLockbox && traits.isRogue && bot->HasSkill(SKILL_LOCKPICKING)) vote = NEED; // Generic BoP rule: if the item is BoP, equippable, matches the spec @@ -758,23 +757,20 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand vote = NEED; } - // return StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? vote : PASS; - // Final filter: loot strategy (protect a potential nil AI earlier on login - if (PlayerbotAI* ai = GET_PLAYERBOT_AI(bot)) - return StoreLootAction::IsLootAllowed(proto->ItemId, ai) ? vote : PASS; - return PASS; + // Final filter: loot strategy — Action has a valid AI in this context + return StoreLootAction::IsLootAllowed(proto->ItemId, this->ai) ? vote : PASS; } // Helpers d'annonce -const char* LootRollAction::RollVoteToText(RollVote v) const +const char* LootRollAction::RollVoteToText(RollVote vote) const { - switch (v) + switch (vote) { - case NEED: return "NEED"; - case GREED: return "GREED"; - case PASS: return "PASS"; - case DISENCHANT: return "DISENCHANT"; - default: return "PASS"; + case NEED: return "NEED"; + case GREED: return "GREED"; + case PASS: return "PASS"; + case DISENCHANT: return "DISENCHANT"; + default: return "UNKNOWN"; } } diff --git a/src/strategy/actions/LootRollAction.h b/src/strategy/actions/LootRollAction.h index 6516f3c61d..4d815d2693 100644 --- a/src/strategy/actions/LootRollAction.h +++ b/src/strategy/actions/LootRollAction.h @@ -47,7 +47,7 @@ class LootRollAction : public QueryItemUsageAction // Announce the roll choice to the bot's master (if enabled in config) void AnnounceRollChoice(RollVote vote, uint32 itemId); - const char* RollVoteToText(RollVote v) const; + const char* RollVoteToText(RollVote vote) const; }; class MasterLootRollAction : public LootRollAction From a007988c74095507c68f79da4c1ce074ffcc6f28 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Tue, 16 Sep 2025 22:13:15 +0200 Subject: [PATCH 05/32] Update LootRollAction.cpp --- src/strategy/actions/LootRollAction.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 46aa395991..cd0640c479 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -425,7 +425,7 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) } // Global VETO: a "physical" spec never considers a caster profile as primary - if (sPlayerbotAIConfig->smartNeedBySpec && T.isPhysical && looksCaster) + if (sPlayerbotAIConfig->smartNeedBySpec && traits.isPhysical && looksCaster) return false; // Let the cross-armor rules (CrossArmorExtraMargin) decide for major off-armor upgrades. @@ -757,8 +757,8 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand vote = NEED; } - // Final filter: loot strategy — Action has a valid AI in this context - return StoreLootAction::IsLootAllowed(proto->ItemId, this->ai) ? vote : PASS; + // Final filter: loot strategy — AI is valid here; use the standard accessor + return StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? vote : PASS; } // Helpers d'annonce From 1af193bd342a24aa3c3dd230ad80c954572c7cea Mon Sep 17 00:00:00 2001 From: Alex Dcnh <140754794+Wishmaster117@users.noreply.github.com> Date: Tue, 16 Sep 2025 23:42:02 +0200 Subject: [PATCH 06/32] Update playerbots.conf.dist --- conf/playerbots.conf.dist | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index d9431a5744..103141353e 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -287,8 +287,14 @@ AiPlayerbot.SayWhenCollectingItems = 1 # Default: 0 (disabled) AiPlayerbot.FreeMethodLoot = 0 -# Bots' loot roll level (0 = pass, 1 = greed, 2 = need) -# Default: 2 (need), recommanded 2 with new loot AI +# Bots' loot roll level: +# 0 = always pass +# 1 = always greed (legacy default, bots never roll "need") +# 2 = allow need (recommended with new loot AI) +# +# With the new loot AI, bots can correctly decide when an item is really useful. +# Setting this to 2 lets them use "need" appropriately. Value 1 only does greed, +# which was the old safe default but bypasses the new decision-making. AiPlayerbot.LootRollLevel = 2 # NEED only if the item matches the bot's MAIN spec (stats & armor/weapon type). @@ -2107,4 +2113,4 @@ AiPlayerbot.SummonAtInnkeepersEnabled = 1 # 30% more damage, 40% damage reduction (tank bots), increased all resistances, reduced threat for non tank bots, increased threat for tank bots. # Buffs will be applied on PP, Sindragosa and Lich King -AiPlayerbot.EnableICCBuffs = 1 \ No newline at end of file +AiPlayerbot.EnableICCBuffs = 1 From 6ddf1a99956fa1f7526382c705a94e1a532fa5b8 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Thu, 18 Sep 2025 17:06:55 +0200 Subject: [PATCH 07/32] Update for review requests --- conf/playerbots.conf.dist | 2 +- src/PlayerbotAIConfig.cpp | 10 ++++---- src/strategy/actions/LootRollAction.cpp | 33 ++++++++----------------- 3 files changed, 16 insertions(+), 29 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 0e353cc78b..a178197c7e 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -309,7 +309,7 @@ AiPlayerbot.Roll.AllowBoENeedIfUpgrade = 1 # Bind-on-Use etiquette: GREED by default to keep it tradeable. # Set to 1 to allow NEED on BoU if it's a clear upgrade. -# Default: (enabled) +# Default: 1 (enabled) AiPlayerbot.Roll.AllowBoUNeedIfUpgrade = 1 # Cross-armor rule (cloth/leather/mail on a plate user, etc.): diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index a04b1bf1eb..f07c3e7c74 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -586,12 +586,12 @@ bool PlayerbotAIConfig::Initialize() autoPickReward = sConfigMgr->GetOption("AiPlayerbot.AutoPickReward", "yes"); autoEquipUpgradeLoot = sConfigMgr->GetOption("AiPlayerbot.AutoEquipUpgradeLoot", true); equipUpgradeThreshold = sConfigMgr->GetOption("AiPlayerbot.EquipUpgradeThreshold", 1.1f); - allowBoENeedIfUpgrade = sConfigMgr->GetOption("AiPlayerbot.Roll.AllowBoENeedIfUpgrade", false); - allowBoUNeedIfUpgrade = sConfigMgr->GetOption("AiPlayerbot.Roll.AllowBoUNeedIfUpgrade", false); - crossArmorExtraMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.CrossArmorExtraMargin", 1.15f); + allowBoENeedIfUpgrade = sConfigMgr->GetOption("AiPlayerbot.Roll.AllowBoENeedIfUpgrade", true); + allowBoUNeedIfUpgrade = sConfigMgr->GetOption("AiPlayerbot.Roll.AllowBoUNeedIfUpgrade", true); + crossArmorExtraMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.CrossArmorExtraMargin", 1.20f); useDEButton = sConfigMgr->GetOption("AiPlayerbot.Roll.UseDEButton", true); - tokenILevelMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.TokenILevelMargin", 0.0f); - announceLootRollsToMaster = sConfigMgr->GetOption("AiPlayerbot.Roll.AnnounceToMaster", true); + tokenILevelMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.TokenILevelMargin", 0.10f); + announceLootRollsToMaster = sConfigMgr->GetOption("AiPlayerbot.Roll.AnnounceToMaster", false); smartNeedBySpec = sConfigMgr->GetOption("AiPlayerbot.Roll.SmartNeedBySpec", true); twoRoundsGearInit = sConfigMgr->GetOption("AiPlayerbot.TwoRoundsGearInit", false); syncQuestWithPlayer = sConfigMgr->GetOption("AiPlayerbot.SyncQuestWithPlayer", true); diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index cd0640c479..8552ab3aa9 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -92,39 +92,22 @@ static SpecTraits GetSpecTraits(Player* bot) } // Local helper: identifies classic lockboxes the Rogue can pick. -// Heuristic: items with a LockID and “misc/junk” class often are lockboxes. -// Also fall back to a name check (“lockbox”, “coffre”) to cover edge DBs. +// Keep English-only fallback for name checks. static bool IsLockbox(ItemTemplate const* proto) { if (!proto) return false; + // Primary, data-driven detection if (proto->LockID) { - // Most lockboxes are misc/junk and openable. + // Most lockboxes are misc/junk and openable in WotLK if (proto->Class == ITEM_CLASS_MISC) return true; } - // Fallback on localized name check - static const std::vector lockboxKeywords = { - "lockbox", // English - "coffre", // French - "schließkassette", // German - "caja fuerte", // Spanish - "сундук", // Russian - "잠긴", // Korean - "锁箱", // Simplified Chinese - "鎖箱" // Traditional Chinese - }; - + // English-only fallback on name (align with TokenSlotFromName behavior) std::string n = proto->Name1; std::transform(n.begin(), n.end(), n.begin(), - [](unsigned char c){ return (c >= 'A' && c <= 'Z') ? char(c + 32) : char(c); }); - for (auto const& kw : lockboxKeywords) - { - const bool ascii = std::all_of(kw.begin(), kw.end(), [](unsigned char c){ return c < 0x80; }); - if ((ascii && n.find(kw) != std::string::npos) || (!ascii && std::string(proto->Name1).find(kw) != std::string::npos)) - return true; - } - return false; + [](unsigned char c){ return static_cast(std::tolower(c)); }); + return n.find("lockbox") != std::string::npos; } // Local helper: not a class member @@ -785,11 +768,15 @@ void LootRollAction::AnnounceRollChoice(RollVote vote, uint32 itemId) std::ostringstream ss; if (ItemTemplate const* ip = sObjectMgr->GetItemTemplate(itemId)) + { ss << "[Loot] " << bot->GetName() << " choose " << RollVoteToText(vote) << " on [" << ip->Name1 << "]"; + } else + { ss << "[Loot] " << bot->GetName() << " choose " << RollVoteToText(vote) << " on item " << itemId; + } // Message to Master botAI->TellMaster(ss.str()); From bd07dd408b862d4b992ee83009edb7beca4ee77c Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Thu, 18 Sep 2025 21:46:18 +0200 Subject: [PATCH 08/32] Create 2025_09_18_00_ai_playerbot_french_texts.sql --- ...025_09_18_00_ai_playerbot_french_texts.sql | 855 ++++++++++++++++++ 1 file changed, 855 insertions(+) create mode 100644 data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql diff --git a/data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql b/data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql new file mode 100644 index 0000000000..490c6fec97 --- /dev/null +++ b/data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql @@ -0,0 +1,855 @@ +UPDATE ai_playerbot_texts SET text_loc2 = ''; + +UPDATE `ai_playerbot_texts` SET `id`=1, `text_loc2`='au milieu de nulle part' WHERE `id`=1; +UPDATE `ai_playerbot_texts` SET `id`=2, `text_loc2`='un endroit non divulgué' WHERE `id`=2; +UPDATE `ai_playerbot_texts` SET `id`=3, `text_loc2`='quelque part' WHERE `id`=3; +UPDATE `ai_playerbot_texts` SET `id`=4, `text_loc2`='un truc' WHERE `id`=4; +UPDATE `ai_playerbot_texts` SET `id`=5, `text_loc2`='je me demande quel goût a %item_link' WHERE `id`=5; +UPDATE `ai_playerbot_texts` SET `id`=6, `text_loc2`='noooon, j’ai eu %item_link' WHERE `id`=6; +UPDATE `ai_playerbot_texts` SET `id`=7, `text_loc2`='oh non, encore cette camelote %item_link' WHERE `id`=7; +UPDATE `ai_playerbot_texts` SET `id`=8, `text_loc2`='on dirait que je ramasse des ordures %item_link' WHERE `id`=8; +UPDATE `ai_playerbot_texts` SET `id`=9, `text_loc2`='bon, c’est mieux que rien je suppose %item_link' WHERE `id`=9; +UPDATE `ai_playerbot_texts` SET `id`=10, `text_loc2`='je ne sais pas quoi faire de %item_link' WHERE `id`=10; +UPDATE `ai_playerbot_texts` SET `id`=11, `text_loc2`='je me demande quel goût a %item_link' WHERE `id`=11; +UPDATE `ai_playerbot_texts` SET `id`=12, `text_loc2`='je pourrais ramasser du %item_link toute la journée' WHERE `id`=12; +UPDATE `ai_playerbot_texts` SET `id`=13, `text_loc2`='un jour de plus, un %item_link de plus' WHERE `id`=13; +UPDATE `ai_playerbot_texts` SET `id`=14, `text_loc2`='j’ai ramassé un peu de %item_link' WHERE `id`=14; +UPDATE `ai_playerbot_texts` SET `id`=15, `text_loc2`='un peu de %item_link, c’est toujours ça' WHERE `id`=15; +UPDATE `ai_playerbot_texts` SET `id`=16, `text_loc2`='pas mal, je viens de choper %item_link' WHERE `id`=16; +UPDATE `ai_playerbot_texts` SET `id`=17, `text_loc2`='je viens de ramasser %item_link à %zone_name' WHERE `id`=17; +UPDATE `ai_playerbot_texts` SET `id`=18, `text_loc2`='je pourrais bien l’utiliser ça %item_link' WHERE `id`=18; +UPDATE `ai_playerbot_texts` SET `id`=19, `text_loc2`='l’argent, l’argent, et encore %item_link' WHERE `id`=19; +UPDATE `ai_playerbot_texts` SET `id`=20, `text_loc2`='j’ai eu %item_link' WHERE `id`=20; +UPDATE `ai_playerbot_texts` SET `id`=21, `text_loc2`='%item_link est BiS pour les chasseurs' WHERE `id`=21; +UPDATE `ai_playerbot_texts` SET `id`=22, `text_loc2`='%item_link est BiS pour les %my_class' WHERE `id`=22; +UPDATE `ai_playerbot_texts` SET `id`=23, `text_loc2`='la chance est avec moi aujourd’hui %item_link' WHERE `id`=23; +UPDATE `ai_playerbot_texts` SET `id`=24, `text_loc2`='trop bon %item_link, fraîchement looté' WHERE `id`=24; +UPDATE `ai_playerbot_texts` SET `id`=25, `text_loc2`='wow, je viens de choper %item_link' WHERE `id`=25; +UPDATE `ai_playerbot_texts` SET `id`=26, `text_loc2`='%item_link est BiS pour les chasseurs' WHERE `id`=26; +UPDATE `ai_playerbot_texts` SET `id`=27, `text_loc2`='%item_link est BiS pour les %my_class' WHERE `id`=27; +UPDATE `ai_playerbot_texts` SET `id`=28, `text_loc2`='la chance est avec moi aujourd’hui %item_link' WHERE `id`=28; +UPDATE `ai_playerbot_texts` SET `id`=29, `text_loc2`='trop bon %item_link, fraîchement looté' WHERE `id`=29; +UPDATE `ai_playerbot_texts` SET `id`=30, `text_loc2`='OMG, regardez ce que je viens de looter %item_link !!!' WHERE `id`=30; +UPDATE `ai_playerbot_texts` SET `id`=31, `text_loc2`='Noooon ! C’est pas possible, j’ai eu %item_link, c’est de la folie' WHERE `id`=31; +UPDATE `ai_playerbot_texts` SET `id`=32, `text_loc2`='Noooon ! C’est pas possible, j’ai eu %item_link, c’est de la folie' WHERE `id`=32; +UPDATE `ai_playerbot_texts` SET `id`=33, `text_loc2`='je viens juste de prendre la quête %quest_link' WHERE `id`=33; +UPDATE `ai_playerbot_texts` SET `id`=34, `text_loc2`='je viens d’accepter %quest_link' WHERE `id`=34; +UPDATE `ai_playerbot_texts` SET `id`=35, `text_loc2`='%quest_link je vais essayer de la finir' WHERE `id`=35; +UPDATE `ai_playerbot_texts` SET `id`=36, `text_loc2`='j’ai pris %quest_link à %zone_name' WHERE `id`=36; +UPDATE `ai_playerbot_texts` SET `id`=37, `text_loc2`='Enfin fini l’objectif %quest_obj_name pour %quest_link' WHERE `id`=37; +UPDATE `ai_playerbot_texts` SET `id`=38, `text_loc2`='j’ai enfin %quest_obj_available/%quest_obj_required de %quest_obj_name pour %quest_link' WHERE `id`=38; +UPDATE `ai_playerbot_texts` SET `id`=39, `text_loc2`='%quest_obj_full_formatted pour %quest_link, enfin !' WHERE `id`=39; +UPDATE `ai_playerbot_texts` SET `id`=40, `text_loc2`='Oof, j’ai %quest_obj_available/%quest_obj_required %quest_obj_name pour %quest_link' WHERE `id`=40; +UPDATE `ai_playerbot_texts` SET `id`=41, `text_loc2`='il me manque encore %quest_obj_missing de %quest_obj_name pour %quest_link' WHERE `id`=41; +UPDATE `ai_playerbot_texts` SET `id`=42, `text_loc2`='%quest_obj_full_formatted, je bosse toujours sur %quest_link' WHERE `id`=42; +UPDATE `ai_playerbot_texts` SET `id`=43, `text_loc2`='Enfin fini avec %item_link pour %quest_link' WHERE `id`=43; +UPDATE `ai_playerbot_texts` SET `id`=44, `text_loc2`='j’ai enfin %quest_obj_available/%quest_obj_required de %item_link pour %quest_link' WHERE `id`=44; +UPDATE `ai_playerbot_texts` SET `id`=45, `text_loc2`='%quest_obj_full_formatted pour %quest_link, enfin !' WHERE `id`=45; +UPDATE `ai_playerbot_texts` SET `id`=46, `text_loc2`='Oof, j’ai %quest_obj_available/%quest_obj_required %item_link pour %quest_link' WHERE `id`=46; +UPDATE `ai_playerbot_texts` SET `id`=47, `text_loc2`='il me manque encore %quest_obj_missing de %item_link pour %quest_link' WHERE `id`=47; +UPDATE `ai_playerbot_texts` SET `id`=48, `text_loc2`='%quest_obj_full_formatted, je suis encore sur %quest_link' WHERE `id`=48; +UPDATE `ai_playerbot_texts` SET `id`=49, `text_loc2`='Échec : je n’ai pas fini %quest_link à temps...' WHERE `id`=49; +UPDATE `ai_playerbot_texts` SET `id`=50, `text_loc2`='Plus de temps pour %quest_link :(' WHERE `id`=50; +UPDATE `ai_playerbot_texts` SET `id`=51, `text_loc2`='J’ai terminé tous les objectifs de %quest_link' WHERE `id`=51; +UPDATE `ai_playerbot_texts` SET `id`=52, `text_loc2`='Objectifs terminés pour %quest_link' WHERE `id`=52; +UPDATE `ai_playerbot_texts` SET `id`=53, `text_loc2`='Je vais rendre %quest_link bientôt, tout est fait' WHERE `id`=53; +UPDATE `ai_playerbot_texts` SET `id`=54, `text_loc2`='Ouiii, j’ai enfin rendu %quest_link' WHERE `id`=54; +UPDATE `ai_playerbot_texts` SET `id`=55, `text_loc2`='%quest_link rendu' WHERE `id`=55; +UPDATE `ai_playerbot_texts` SET `id`=56, `text_loc2`='Mission %quest_link terminée, rendu !' WHERE `id`=56; +UPDATE `ai_playerbot_texts` SET `id`=57, `text_loc2`='%quest_link rendu' WHERE `id`=57; +UPDATE `ai_playerbot_texts` SET `id`=58, `text_loc2`='%quest_link rendu à %zone_name' WHERE `id`=58; +UPDATE `ai_playerbot_texts` SET `id`=59, `text_loc2`='encore un %victim_name à terre' WHERE `id`=59; +UPDATE `ai_playerbot_texts` SET `id`=60, `text_loc2`='je continue à tuer %victim_name, banalité' WHERE `id`=60; +UPDATE `ai_playerbot_texts` SET `id`=61, `text_loc2`='un autre %victim_name mord la poussière' WHERE `id`=61; +UPDATE `ai_playerbot_texts` SET `id`=62, `text_loc2`='un %victim_name en moins à %zone_name' WHERE `id`=62; +UPDATE `ai_playerbot_texts` SET `id`=63, `text_loc2`='J’ai descendu ce sale élite %victim_name !' WHERE `id`=63; +UPDATE `ai_playerbot_texts` SET `id`=64, `text_loc2`='élite %victim_name éliminé à %zone_name' WHERE `id`=64; +UPDATE `ai_playerbot_texts` SET `id`=65, `text_loc2`='Ouf, j’ai réussi à abattre %victim_name !' WHERE `id`=65; +UPDATE `ai_playerbot_texts` SET `id`=66, `text_loc2`='C’était épique ! %victim_name est tombé, j’ai une histoire à raconter' WHERE `id`=66; +UPDATE `ai_playerbot_texts` SET `id`=67, `text_loc2`='Yoo, je viens de tuer %victim_name !' WHERE `id`=67; +UPDATE `ai_playerbot_texts` SET `id`=68, `text_loc2`='rare %victim_name éliminé à %zone_name' WHERE `id`=68; +UPDATE `ai_playerbot_texts` SET `id`=69, `text_loc2`='Mais qu’est-ce que j’ai tué là ? %victim_name' WHERE `id`=69; +UPDATE `ai_playerbot_texts` SET `id`=70, `text_loc2`='J’ai tué cette bestiole %victim_name' WHERE `id`=70; +UPDATE `ai_playerbot_texts` SET `id`=71, `text_loc2`='Oh ouiii, j’ai tué %victim_name' WHERE `id`=71; +UPDATE `ai_playerbot_texts` SET `id`=72, `text_loc2`='%victim_name éliminé à %zone_name' WHERE `id`=72; +UPDATE `ai_playerbot_texts` SET `id`=73, `text_loc2`='Ding !' WHERE `id`=73; +UPDATE `ai_playerbot_texts` SET `id`=74, `text_loc2`='Ouiii, je suis niveau %my_level !' WHERE `id`=74; +UPDATE `ai_playerbot_texts` SET `id`=75, `text_loc2`='Je viens de passer un niveau' WHERE `id`=75; +UPDATE `ai_playerbot_texts` SET `id`=76, `text_loc2`='Je suis niveau %my_level !!!' WHERE `id`=76; +UPDATE `ai_playerbot_texts` SET `id`=77, `text_loc2`='Je deviens plus fort, déjà %my_level !!!' WHERE `id`=77; +UPDATE `ai_playerbot_texts` SET `id`=78, `text_loc2`='Je viens d’atteindre le niveau %my_level !!!' WHERE `id`=78; +UPDATE `ai_playerbot_texts` SET `id`=79, `text_loc2`='OMG, enfin niveau %my_level !!!' WHERE `id`=79; +UPDATE `ai_playerbot_texts` SET `id`=80, `text_loc2`='%my_level !!! prêt pour le contenu endgame' WHERE `id`=80; +UPDATE `ai_playerbot_texts` SET `id`=81, `text_loc2`='tout frais, nouveau %my_level %my_class !!!' WHERE `id`=81; +UPDATE `ai_playerbot_texts` SET `id`=82, `text_loc2`='encore un niveau %my_level %my_race %my_class !' WHERE `id`=82; +UPDATE `ai_playerbot_texts` SET `id`=83, `text_loc2`='Bien joué %other_name. Tu l’as mérité.' WHERE `id`=83; +UPDATE `ai_playerbot_texts` SET `id`=84, `text_loc2`='C’était affreux %other_name. J’ai détesté faire ça mais...' WHERE `id`=84; +UPDATE `ai_playerbot_texts` SET `id`=85, `text_loc2`='Quelqu’un veut faire %instance_name ?' WHERE `id`=85; +UPDATE `ai_playerbot_texts` SET `id`=86, `text_loc2`='Des groupes pour %instance_name ?' WHERE `id`=86; +UPDATE `ai_playerbot_texts` SET `id`=87, `text_loc2`='Besoin d’aide pour %instance_name ?' WHERE `id`=87; +UPDATE `ai_playerbot_texts` SET `id`=88, `text_loc2`='LFD : %instance_name.' WHERE `id`=88; +UPDATE `ai_playerbot_texts` SET `id`=89, `text_loc2`='Quelqu’un a besoin d’un %my_role pour %instance_name ?' WHERE `id`=89; +UPDATE `ai_playerbot_texts` SET `id`=90, `text_loc2`='Il manque un %my_role pour %instance_name ?' WHERE `id`=90; +UPDATE `ai_playerbot_texts` SET `id`=91, `text_loc2`='Je peux être %my_role pour %instance_name.' WHERE `id`=91; +UPDATE `ai_playerbot_texts` SET `id`=92, `text_loc2`='Besoin d’un coup de main à %instance_name ?' WHERE `id`=92; +UPDATE `ai_playerbot_texts` SET `id`=93, `text_loc2`='Besoin d’un %my_role pour %instance_name ?' WHERE `id`=93; +UPDATE `ai_playerbot_texts` SET `id`=94, `text_loc2`='Quelqu’un a besoin de loot à %instance_name ?' WHERE `id`=94; +UPDATE `ai_playerbot_texts` SET `id`=95, `text_loc2`='Un petit farm à %instance_name ?' WHERE `id`=95; +UPDATE `ai_playerbot_texts` SET `id`=96, `text_loc2`='WTR %instance_name' WHERE `id`=96; +UPDATE `ai_playerbot_texts` SET `id`=97, `text_loc2`='Besoin d’aide pour %instance_name.' WHERE `id`=97; +UPDATE `ai_playerbot_texts` SET `id`=98, `text_loc2`='Envie de faire %instance_name.' WHERE `id`=98; +UPDATE `ai_playerbot_texts` SET `id`=99, `text_loc2`='%my_role cherche un groupe pour %instance_name.' WHERE `id`=99; +UPDATE `ai_playerbot_texts` SET `id`=100, `text_loc2`='Et %instance_name, on y va ?' WHERE `id`=100; +UPDATE `ai_playerbot_texts` SET `id`=101, `text_loc2`='Qui veut farmer %instance_name ?' WHERE `id`=101; +UPDATE `ai_playerbot_texts` SET `id`=102, `text_loc2`='On entre dans %instance_name ?' WHERE `id`=102; +UPDATE `ai_playerbot_texts` SET `id`=103, `text_loc2`='Je cherche groupe pour %instance_name.' WHERE `id`=103; +UPDATE `ai_playerbot_texts` SET `id`=104, `text_loc2`='Des quêtes à %instance_name ?' WHERE `id`=104; +UPDATE `ai_playerbot_texts` SET `id`=105, `text_loc2`='Envie de faire des quêtes à %instance_name.' WHERE `id`=105; +UPDATE `ai_playerbot_texts` SET `id`=106, `text_loc2`='Quelqu’un avec des quêtes à %instance_name ?' WHERE `id`=106; +UPDATE `ai_playerbot_texts` SET `id`=107, `text_loc2`='Je peux aider pour les quêtes à %instance_name.' WHERE `id`=107; +UPDATE `ai_playerbot_texts` SET `id`=108, `text_loc2`='%my_role : une place dispo pour %instance_name ?' WHERE `id`=108; +UPDATE `ai_playerbot_texts` SET `id`=109, `text_loc2`='Est-ce que quelqu’un fait encore %instance_name de nos jours ?' WHERE `id`=109; +UPDATE `ai_playerbot_texts` SET `id`=110, `text_loc2`='%instance_name : quelqu’un cherche un %my_role ?' WHERE `id`=110; +UPDATE `ai_playerbot_texts` SET `id`=111, `text_loc2`='Ça sert encore à quelque chose d’être %my_role à %instance_name ?' WHERE `id`=111; +UPDATE `ai_playerbot_texts` SET `id`=112, `text_loc2`='Ça vaut vraiment le coup d’aller à %instance_name ?' WHERE `id`=112; +UPDATE `ai_playerbot_texts` SET `id`=113, `text_loc2`='Quelqu’un a besoin de plus de joueurs pour %instance_name ?' WHERE `id`=113; +UPDATE `ai_playerbot_texts` SET `id`=114, `text_loc2`='Les boss de %instance_name lootent du bon matos. On y va ?' WHERE `id`=114; +UPDATE `ai_playerbot_texts` SET `id`=115, `text_loc2`='Alors, %instance_name ?' WHERE `id`=115; +UPDATE `ai_playerbot_texts` SET `id`=116, `text_loc2`='Quelqu’un a besoin d’un %my_role ?' WHERE `id`=116; +UPDATE `ai_playerbot_texts` SET `id`=117, `text_loc2`='Quelqu’un a besoin d’un %my_role ?' WHERE `id`=117; +UPDATE `ai_playerbot_texts` SET `id`=118, `text_loc2`='Qui veut aller à %instance_name ?' WHERE `id`=118; +UPDATE `ai_playerbot_texts` SET `id`=119, `text_loc2`='Quelqu’un peut me TP à %instance_name ?' WHERE `id`=119; +UPDATE `ai_playerbot_texts` SET `id`=120, `text_loc2`='Retrouve-moi à %instance_name' WHERE `id`=120; +UPDATE `ai_playerbot_texts` SET `id`=121, `text_loc2`='Envie d’un petit run rapide à %instance_name ?' WHERE `id`=121; +UPDATE `ai_playerbot_texts` SET `id`=122, `text_loc2`='On se fait un run complet à %instance_name ?' WHERE `id`=122; +UPDATE `ai_playerbot_texts` SET `id`=123, `text_loc2`='T’as été combien de fois à %instance_name ? Sérieusement.' WHERE `id`=123; +UPDATE `ai_playerbot_texts` SET `id`=124, `text_loc2`='Encore un run à %instance_name ? T’es maso ou quoi ?' WHERE `id`=124; +UPDATE `ai_playerbot_texts` SET `id`=125, `text_loc2`='Wipe à %instance_name ? Prends-moi, je suis un porte-bonheur !' WHERE `id`=125; +UPDATE `ai_playerbot_texts` SET `id`=126, `text_loc2`='Emmène-moi à %instance_name s’il te plaît. J’ai les snacks !' WHERE `id`=126; +UPDATE `ai_playerbot_texts` SET `id`=127, `text_loc2`='Un petit %instance_name vite fait bien fait ?' WHERE `id`=127; +UPDATE `ai_playerbot_texts` SET `id`=128, `text_loc2`='Un gros %instance_name jusqu’à la fin ?' WHERE `id`=128; +UPDATE `ai_playerbot_texts` SET `id`=129, `text_loc2`='Qui peut prendre un %my_role à %instance_name ? (j’apporte les blagues)' WHERE `id`=129; +UPDATE `ai_playerbot_texts` SET `id`=130, `text_loc2`='LFG %instance_name, je suis %my_role, mais surtout... je suis prêt !' WHERE `id`=130; +UPDATE `ai_playerbot_texts` SET `id`=131, `text_loc2`='%my_role cherche groupe pour %instance_name ! J’suis pas chiant, promis.' WHERE `id`=131; +UPDATE `ai_playerbot_texts` SET `id`=132, `text_loc2`='Besoin d’aide pour %quest_link ? Je promets de ne pas tout ninja.' WHERE `id`=132; +UPDATE `ai_playerbot_texts` SET `id`=133, `text_loc2`='Quelqu’un veut partager %quest_link ? On est pauvres ensemble !' WHERE `id`=133; +UPDATE `ai_playerbot_texts` SET `id`=134, `text_loc2`='Quelqu’un fait %quest_link ? Je me joins à la souffrance !' WHERE `id`=134; +UPDATE `ai_playerbot_texts` SET `id`=135, `text_loc2`='On fait %quest_link ? J’ai des cookies.' WHERE `id`=135; +UPDATE `ai_playerbot_texts` SET `id`=136, `text_loc2`='Quelqu’un pour farmer du %category ? Les mobs m’aiment trop.' WHERE `id`=136; +UPDATE `ai_playerbot_texts` SET `id`=137, `text_loc2`='Cherche aide pour farmer %category. J’en ai marre de mourir seul.' WHERE `id`=137; +UPDATE `ai_playerbot_texts` SET `id`=138, `text_loc2`='Ces %category coûtent un bras ! Et l’autre bras pour les frais de port !' WHERE `id`=138; +UPDATE `ai_playerbot_texts` SET `id`=139, `text_loc2`='J’ai envie de %category. Envie irrépressible.' WHERE `id`=139; +UPDATE `ai_playerbot_texts` SET `id`=140, `text_loc2`='Besoin d’aide pour %category. Ma patience s’épuise.' WHERE `id`=140; +UPDATE `ai_playerbot_texts` SET `id`=141, `text_loc2`='WTB %category. Même moches. Même usagés.' WHERE `id`=141; +UPDATE `ai_playerbot_texts` SET `id`=142, `text_loc2`='Quelqu’un est intéressé par %category ? Ne soyez pas timides.' WHERE `id`=142; +UPDATE `ai_playerbot_texts` SET `id`=143, `text_loc2`='WTS %category. Prix spécial, sans garantie ni remboursement.' WHERE `id`=143; +UPDATE `ai_playerbot_texts` SET `id`=144, `text_loc2`='Je vends %category moins cher que l’HV... et sans file d’attente !' WHERE `id`=144; +UPDATE `ai_playerbot_texts` SET `id`=145, `text_loc2`='Qui veut farmer du %category ? Avec ou sans café ?' WHERE `id`=145; +UPDATE `ai_playerbot_texts` SET `id`=146, `text_loc2`='On farme du %category ? J’ai annulé mon IRL exprès.' WHERE `id`=146; +UPDATE `ai_playerbot_texts` SET `id`=147, `text_loc2`='Je cherche un groupe, après ça on fait du %category ?' WHERE `id`=147; +UPDATE `ai_playerbot_texts` SET `id`=148, `text_loc2`='Tous les %category sont les bienvenus. Même les rouillés.' WHERE `id`=148; +UPDATE `ai_playerbot_texts` SET `id`=149, `text_loc2`='J’achète tout ce qui ressemble à du %category. Même les faux.' WHERE `id`=149; +UPDATE `ai_playerbot_texts` SET `id`=150, `text_loc2`='Wow, y’a des gens qui farment encore du %category ? Respect.' WHERE `id`=150; +UPDATE `ai_playerbot_texts` SET `id`=151, `text_loc2`='Les %category partent comme des petits pains à l’HV !' WHERE `id`=151; +UPDATE `ai_playerbot_texts` SET `id`=152, `text_loc2`='L’HV brûle à cause des %category !' WHERE `id`=152; +UPDATE `ai_playerbot_texts` SET `id`=153, `text_loc2`='Y’a des %category sur le marché. Profitez avant le nerf.' WHERE `id`=153; +UPDATE `ai_playerbot_texts` SET `id`=154, `text_loc2`='On échange des %category ? J’ai des trucs louches en stock.' WHERE `id`=154; +UPDATE `ai_playerbot_texts` SET `id`=155, `text_loc2`='Il me faut plus de %category. Beaucoup plus. Genre montagne.' WHERE `id`=155; +UPDATE `ai_playerbot_texts` SET `id`=156, `text_loc2`='Quelqu’un a un peu de %category à donner à une bonne cause (moi) ?' WHERE `id`=156; +UPDATE `ai_playerbot_texts` SET `id`=157, `text_loc2`='Qui veut du %category ? C’est cadeau (non, pas vraiment).' WHERE `id`=157; +UPDATE `ai_playerbot_texts` SET `id`=158, `text_loc2`='Un peu de %category s’il vous plaît ? J’ai pas mangé depuis deux loots.' WHERE `id`=158; +UPDATE `ai_playerbot_texts` SET `id`=159, `text_loc2`='J’aurais dû monter une compétence pour les %category… la flemme.' WHERE `id`=159; +UPDATE `ai_playerbot_texts` SET `id`=160, `text_loc2`='Je meurs d’envie d’avoir des %category. Littéralement.' WHERE `id`=160; +UPDATE `ai_playerbot_texts` SET `id`=161, `text_loc2`='Les gens se battent pour les %category. J’arrive avec ma pelle.' WHERE `id`=161; +UPDATE `ai_playerbot_texts` SET `id`=162, `text_loc2`='%category, c’est une affaire en or ! Si j’en avais...' WHERE `id`=162; +UPDATE `ai_playerbot_texts` SET `id`=163, `text_loc2`='Tout le monde devient fou pour les %category ! C’est contagieux ?' WHERE `id`=163; +UPDATE `ai_playerbot_texts` SET `id`=164, `text_loc2`='C’est où le meilleur spot pour farmer des %category ? Je prends notes.' WHERE `id`=164; +UPDATE `ai_playerbot_texts` SET `id`=165, `text_loc2`='Je suis prêt pour le farm de %category. Café et slip d\'aventure.' WHERE `id`=165; +UPDATE `ai_playerbot_texts` SET `id`=166, `text_loc2`='Ça se vend bien les %category ? Histoire que je rêve un peu.' WHERE `id`=166; +UPDATE `ai_playerbot_texts` SET `id`=167, `text_loc2`='Je vais garder tous mes %category. Pour moi. Parce que je suis radin.' WHERE `id`=167; +UPDATE `ai_playerbot_texts` SET `id`=168, `text_loc2`='Besoin d’un groupe ? On pourrait farm des %category ensemble. Et mourir ensemble.' WHERE `id`=168; +UPDATE `ai_playerbot_texts` SET `id`=169, `text_loc2`='Je pense encore aux %category. C’est grave docteur ?' WHERE `id`=169; +UPDATE `ai_playerbot_texts` SET `id`=170, `text_loc2`='J’ai entendu parler des %category... mais mon porte-monnaie ne veut pas.' WHERE `id`=170; +UPDATE `ai_playerbot_texts` SET `id`=171, `text_loc2`='LFG pour %category, sérieux cette fois ! (ou pas)' WHERE `id`=171; +UPDATE `ai_playerbot_texts` SET `id`=172, `text_loc2`='Vendre %category rend riche ? Ou juste aigri ?' WHERE `id`=172; +UPDATE `ai_playerbot_texts` SET `id`=173, `text_loc2`='Ok. Demain je farm les %category. Enfin... peut-être.' WHERE `id`=173; +UPDATE `ai_playerbot_texts` SET `id`=174, `text_loc2`='Tout le monde parle des %category. Même ma grand-mère.' WHERE `id`=174; +UPDATE `ai_playerbot_texts` SET `id`=175, `text_loc2`='J’ai vu au moins dix gars farmer du %category. Et moi, je regarde.' WHERE `id`=175; +UPDATE `ai_playerbot_texts` SET `id`=176, `text_loc2`='J’ai tout vendu mes %category hier. Maintenant je mange du pain sec.' WHERE `id`=176; +UPDATE `ai_playerbot_texts` SET `id`=177, `text_loc2`='Envie de rejoindre une guilde qui farme du %category. Ou une secte.' WHERE `id`=177; +UPDATE `ai_playerbot_texts` SET `id`=178, `text_loc2`='Quelqu’un farm la réputation %faction ? J’ai de la place pour souffrir.' WHERE `id`=178; +UPDATE `ai_playerbot_texts` SET `id`=179, `text_loc2`='Quelqu’un peut m’aider pour %faction ? Même moralement.' WHERE `id`=179; +UPDATE `ai_playerbot_texts` SET `id`=180, `text_loc2`='On fait des quêtes pour %faction ? Avec style.' WHERE `id`=180; +UPDATE `ai_playerbot_texts` SET `id`=181, `text_loc2`='%faction, c’est la crème de la crème. Paraît-il.' WHERE `id`=181; +UPDATE `ai_playerbot_texts` SET `id`=182, `text_loc2`='Il me manque juste un tout petit peu pour être %rep_level avec %faction.' WHERE `id`=182; +UPDATE `ai_playerbot_texts` SET `id`=183, `text_loc2`='Quelqu’un est %rep_level avec %faction ? Montrez vos secrets !' WHERE `id`=183; +UPDATE `ai_playerbot_texts` SET `id`=184, `text_loc2`='Qui veut devenir %rep_level avec %faction ? Et pleurer ensuite.' WHERE `id`=184; +UPDATE `ai_playerbot_texts` SET `id`=185, `text_loc2`='Je serai jamais %rep_level avec %faction. J’ai accepté mon destin.' WHERE `id`=185; +UPDATE `ai_playerbot_texts` SET `id`=186, `text_loc2`='Quelqu’un a oublié de monter la réputation %faction ? Vous n’êtes pas seuls.' WHERE `id`=186; +UPDATE `ai_playerbot_texts` SET `id`=187, `text_loc2`='Je peux aider à farmer la réputation %faction. Et me plaindre en même temps.' WHERE `id`=187; +UPDATE `ai_playerbot_texts` SET `id`=188, `text_loc2`='Plus on a de réputation, mieux c’est. Surtout avec %faction.' WHERE `id`=188; +UPDATE `ai_playerbot_texts` SET `id`=189, `text_loc2`='%faction : il me faut encore %rndK pour être %rep_level. Tuez-moi.' WHERE `id`=189; +UPDATE `ai_playerbot_texts` SET `id`=190, `text_loc2`='Qui peut partager des quêtes %faction ? Ou un mouchoir.' WHERE `id`=190; +UPDATE `ai_playerbot_texts` SET `id`=191, `text_loc2`='Des donjons pour la réputation %faction ? J’apporte les wipes.' WHERE `id`=191; +UPDATE `ai_playerbot_texts` SET `id`=192, `text_loc2`='On farm la réput %faction ? Jusqu’au burnout.' WHERE `id`=192; +UPDATE `ai_playerbot_texts` SET `id`=193, `text_loc2`='Allons-y pour %faction ! Et que les loots soient bons !' WHERE `id`=193; +UPDATE `ai_playerbot_texts` SET `id`=194, `text_loc2`='Je farm la réputation %faction. Ou du moins j’essaie.' WHERE `id`=194; +UPDATE `ai_playerbot_texts` SET `id`=195, `text_loc2`='On farme pour %faction ? Avec larmes et sueur.' WHERE `id`=195; +UPDATE `ai_playerbot_texts` SET `id`=196, `text_loc2`='Besoin d’aide pour %faction. Et peut-être un psy.' WHERE `id`=196; +UPDATE `ai_playerbot_texts` SET `id`=197, `text_loc2`='%faction vend quelque chose d’utile ? À part des illusions ?' WHERE `id`=197; +UPDATE `ai_playerbot_texts` SET `id`=198, `text_loc2`='Il existe des vendeurs %faction ? Ou c’est une légende ?' WHERE `id`=198; +UPDATE `ai_playerbot_texts` SET `id`=199, `text_loc2`='Qui farme %faction ? Et pourquoi ?' WHERE `id`=199; +UPDATE `ai_playerbot_texts` SET `id`=200, `text_loc2`='Quelle est la meilleure façon de farmer %faction ? En dormant ?' WHERE `id`=200; +UPDATE `ai_playerbot_texts` SET `id`=201, `text_loc2`='Je déteste farmer la réputation %faction. Voilà, c’est dit.' WHERE `id`=201; +UPDATE `ai_playerbot_texts` SET `id`=202, `text_loc2`='J’en ai marre de %faction. Vraiment.' WHERE `id`=202; +UPDATE `ai_playerbot_texts` SET `id`=203, `text_loc2`='On va pour %faction ? Ou on fuit ?' WHERE `id`=203; +UPDATE `ai_playerbot_texts` SET `id`=204, `text_loc2`='Tout le monde est %rep_level avec %faction. Et moi, je galère encore.' WHERE `id`=204; +UPDATE `ai_playerbot_texts` SET `id`=205, `text_loc2`='LFG pour farm de réputation %faction ? Avec bonne humeur (ou pas).' WHERE `id`=205; +UPDATE `ai_playerbot_texts` SET `id`=206, `text_loc2`='Quelqu’un a un bon spot pour la réputation %faction ? J’ai une pelle.' WHERE `id`=206; +UPDATE `ai_playerbot_texts` SET `id`=207, `text_loc2`='Améliorer ma réput %faction, ça sert ? Ou je perds mon temps ?' WHERE `id`=207; +UPDATE `ai_playerbot_texts` SET `id`=208, `text_loc2`='Qui aurait cru que la réputation %faction finirait par servir ?' WHERE `id`=208; +UPDATE `ai_playerbot_texts` SET `id`=209, `text_loc2`='Je veux être exalté avec toutes les factions. En commençant par %faction.' WHERE `id`=209; +UPDATE `ai_playerbot_texts` SET `id`=210, `text_loc2`='Est-ce que ça vaut le coup de monter %faction ? Ou juste une perte de vie ?' WHERE `id`=210; +UPDATE `ai_playerbot_texts` SET `id`=211, `text_loc2`='Qu’est-ce qui marche le mieux pour %faction ? Les quêtes ou tuer des mobs ?' WHERE `id`=211; +UPDATE `ai_playerbot_texts` SET `id`=212, `text_loc2`='Je farm %faction pour toi, si tu me paies. Et je rigole pas.' WHERE `id`=212; +UPDATE `ai_playerbot_texts` SET `id`=213, `text_loc2`='Farmer la réputation %faction ? Ça prendra 3 vies au moins.' WHERE `id`=213; +UPDATE `ai_playerbot_texts` SET `id`=214, `text_loc2`='Je tue pour %faction tous les jours, mais je suis toujours pas %rep_level.' WHERE `id`=214; +UPDATE `ai_playerbot_texts` SET `id`=215, `text_loc2`='À %my_level, les dépôts à l’HV vont baisser, non ?' WHERE `id`=215; +UPDATE `ai_playerbot_texts` SET `id`=216, `text_loc2`='Combien de réputations exaltées tu as ? Allez, montre !' WHERE `id`=216; +UPDATE `ai_playerbot_texts` SET `id`=217, `text_loc2`='Qui veut être %my_level avec %faction ? Moi j’ai peur.' WHERE `id`=217; +UPDATE `ai_playerbot_texts` SET `id`=218, `text_loc2`='Ma guilde a farmé la réputation %faction hier. Sans moi. Tristesse.' WHERE `id`=218; +UPDATE `ai_playerbot_texts` SET `id`=219, `text_loc2`='Personne ne veut m’aider, tout ça parce que je suis %rep_level avec %faction.' WHERE `id`=219; +UPDATE `ai_playerbot_texts` SET `id`=220, `text_loc2`='Évitez %faction. Pour votre santé mentale.' WHERE `id`=220; +UPDATE `ai_playerbot_texts` SET `id`=221, `text_loc2`='On fait une soirée à %zone_name ? Bring the drums !' WHERE `id`=221; +UPDATE `ai_playerbot_texts` SET `id`=222, `text_loc2`='Quelqu’un cherche un %my_role ? Je suis dispo et pas trop nul.' WHERE `id`=222; +UPDATE `ai_playerbot_texts` SET `id`=223, `text_loc2`='%my_role cherche une guilde. Sérieux, je suis cool.' WHERE `id`=223; +UPDATE `ai_playerbot_texts` SET `id`=224, `text_loc2`='Je cherche de l’or. Et pas juste dans les rêves.' WHERE `id`=224; +UPDATE `ai_playerbot_texts` SET `id`=225, `text_loc2`='%my_role cherche une bonne guilde, pas une secte (sauf si vous avez des cookies)' WHERE `id`=225; +UPDATE `ai_playerbot_texts` SET `id`=226, `text_loc2`='J’ai besoin d’un ami. Ou d’un pet qui me juge pas.' WHERE `id`=226; +UPDATE `ai_playerbot_texts` SET `id`=227, `text_loc2`='Quelqu’un d’autre se sent seul ? On se fait un groupe de dépression ?' WHERE `id`=227; +UPDATE `ai_playerbot_texts` SET `id`=228, `text_loc2`='Je m’ennuie... Sauvez-moi ou tuez-moi, mais faites quelque chose.' WHERE `id`=228; +UPDATE `ai_playerbot_texts` SET `id`=229, `text_loc2`='Qui en veut ? J’ai des buffs et de la mauvaise foi !' WHERE `id`=229; +UPDATE `ai_playerbot_texts` SET `id`=230, `text_loc2`='Allez viens te battre !' WHERE `id`=230; +UPDATE `ai_playerbot_texts` SET `id`=231, `text_loc2`='Un petit duel à %zone_name, histoire de s’humilier ?' WHERE `id`=231; +UPDATE `ai_playerbot_texts` SET `id`=232, `text_loc2`='Quelqu’un fait quelque chose ici ? Parce que moi je campe le vide.' WHERE `id`=232; +UPDATE `ai_playerbot_texts` SET `id`=233, `text_loc2`='%zone_name : y’a une âme qui vive ici ?' WHERE `id`=233; +UPDATE `ai_playerbot_texts` SET `id`=234, `text_loc2`='%zone_name : tout le monde est en furtif ou quoi ?' WHERE `id`=234; +UPDATE `ai_playerbot_texts` SET `id`=235, `text_loc2`='On dirait que je suis seul à %zone_name. Même les PNJ me fuient.' WHERE `id`=235; +UPDATE `ai_playerbot_texts` SET `id`=236, `text_loc2`='Rejoins-moi à %zone_name ! Apporte la bière.' WHERE `id`=236; +UPDATE `ai_playerbot_texts` SET `id`=237, `text_loc2`='Allez, on fait des quêtes à %zone_name ! Le fun est presque garanti.' WHERE `id`=237; +UPDATE `ai_playerbot_texts` SET `id`=238, `text_loc2`='%zone_name c’est LE coin sympa. Et les mobs sont sympas aussi… parfois.' WHERE `id`=238; +UPDATE `ai_playerbot_texts` SET `id`=239, `text_loc2`='J’veux aller à %zone_name. Quelqu’un me suit ou je pars solo again ?' WHERE `id`=239; +UPDATE `ai_playerbot_texts` SET `id`=240, `text_loc2`='Qui veut aller à %zone_name ? Et mourir dans la joie ?' WHERE `id`=240; +UPDATE `ai_playerbot_texts` SET `id`=241, `text_loc2`='J’aime pas %zone_name. On bouge ? Vite.' WHERE `id`=241; +UPDATE `ai_playerbot_texts` SET `id`=242, `text_loc2`='Y’a de bonnes quêtes à %zone_name ou juste des traquenards ?' WHERE `id`=242; +UPDATE `ai_playerbot_texts` SET `id`=243, `text_loc2`='On va où après %zone_name ? L’enfer ?' WHERE `id`=243; +UPDATE `ai_playerbot_texts` SET `id`=244, `text_loc2`='Qui traîne à %zone_name ? Qu’on fasse un barbecue.' WHERE `id`=244; +UPDATE `ai_playerbot_texts` SET `id`=245, `text_loc2`='LFG pour %zone_name. J’apporte la bonne humeur (et le wipe).' WHERE `id`=245; +UPDATE `ai_playerbot_texts` SET `id`=246, `text_loc2`='%zone_name est l’endroit le plus naze du monde.' WHERE `id`=246; +UPDATE `ai_playerbot_texts` SET `id`=247, `text_loc2`='Attrape-moi à %zone_name si tu peux !' WHERE `id`=247; +UPDATE `ai_playerbot_texts` SET `id`=248, `text_loc2`='Direction %zone_name ! Pour le loot ! Ou les fails.' WHERE `id`=248; +UPDATE `ai_playerbot_texts` SET `id`=249, `text_loc2`='Envie de quêtes à %zone_name' WHERE `id`=249; +UPDATE `ai_playerbot_texts` SET `id`=250, `text_loc2`='Quelqu’un a des quêtes à %zone_name ? À partager, pas à fuir.' WHERE `id`=250; +UPDATE `ai_playerbot_texts` SET `id`=251, `text_loc2`='Venez à %zone_name ! C’est désert, mais charmant.' WHERE `id`=251; +UPDATE `ai_playerbot_texts` SET `id`=252, `text_loc2`='On dirait que la Horde a déserté %zone_name...' WHERE `id`=252; +UPDATE `ai_playerbot_texts` SET `id`=253, `text_loc2`='On dirait que l’Alliance a déserté %zone_name...' WHERE `id`=253; +UPDATE `ai_playerbot_texts` SET `id`=254, `text_loc2`='J’en peux plus de %zone_name. Quelqu’un me sort de là ?' WHERE `id`=254; +UPDATE `ai_playerbot_texts` SET `id`=255, `text_loc2`='Bonne chance !' WHERE `id`=255; +UPDATE `ai_playerbot_texts` SET `id`=256, `text_loc2`='Je veux rentrer chez moi… puis pleurer au bord du vide' WHERE `id`=256; +UPDATE `ai_playerbot_texts` SET `id`=257, `text_loc2`='Quelqu’un sait ce qu’il faut pour jouer double arme ? Une crise existentielle ?' WHERE `id`=257; +UPDATE `ai_playerbot_texts` SET `id`=258, `text_loc2`='Salut tout le monde !' WHERE `id`=258; +UPDATE `ai_playerbot_texts` SET `id`=259, `text_loc2`='%zone_name est cosy… ou alors je perds la tête' WHERE `id`=259; +UPDATE `ai_playerbot_texts` SET `id`=260, `text_loc2`='Je me sens bien… bizarrement suspect.' WHERE `id`=260; +UPDATE `ai_playerbot_texts` SET `id`=261, `text_loc2`='Je n’ignore pas les gens. Je les trolle jusqu’à ce qu’ils m’ignorent.' WHERE `id`=261; +UPDATE `ai_playerbot_texts` SET `id`=262, `text_loc2`='Que pensez-vous de mon build ? Soyez gentils %my_role' WHERE `id`=262; +UPDATE `ai_playerbot_texts` SET `id`=263, `text_loc2`='Heureux de voir que le chat ne m’a pas oublié (ou presque)' WHERE `id`=263; +UPDATE `ai_playerbot_texts` SET `id`=264, `text_loc2`='Comme toutes les armes, c’est BiS pour chasseur (hein ? hein ?)' WHERE `id`=264; +UPDATE `ai_playerbot_texts` SET `id`=265, `text_loc2`='Le but du jeu pour moi ? Solo tout ce qui bouge. Même les mouches.' WHERE `id`=265; +UPDATE `ai_playerbot_texts` SET `id`=266, `text_loc2`='J’ai JAMAIS arnaqué personne. Juré. Enfin… presque.' WHERE `id`=266; +UPDATE `ai_playerbot_texts` SET `id`=267, `text_loc2`='Ah, World of Warcraft. Là où je viens chercher des conseils de vie.' WHERE `id`=267; +UPDATE `ai_playerbot_texts` SET `id`=268, `text_loc2`='Y’A QUELQU’UN ?!' WHERE `id`=268; +UPDATE `ai_playerbot_texts` SET `id`=269, `text_loc2`='Il est temps de me frayer un chemin dans %zone_name à coups de sorts.' WHERE `id`=269; +UPDATE `ai_playerbot_texts` SET `id`=270, `text_loc2`='%zone_name' WHERE `id`=270; +UPDATE `ai_playerbot_texts` SET `id`=271, `text_loc2`='… faut que j’aille aux toilettes. Urgence IRL.' WHERE `id`=271; +UPDATE `ai_playerbot_texts` SET `id`=272, `text_loc2`='Si tu loot pas tes mobs skinables, ton zizi perd 1mm. C’est la règle.' WHERE `id`=272; +UPDATE `ai_playerbot_texts` SET `id`=273, `text_loc2`='NOOOOOOOOOOOOO' WHERE `id`=273; +UPDATE `ai_playerbot_texts` SET `id`=274, `text_loc2`='J’AIME LA PATATE' WHERE `id`=274; +UPDATE `ai_playerbot_texts` SET `id`=275, `text_loc2`='La discussion est animée.' WHERE `id`=275; +UPDATE `ai_playerbot_texts` SET `id`=276, `text_loc2`='salut, comment ça va les gens ?' WHERE `id`=276; +UPDATE `ai_playerbot_texts` SET `id`=277, `text_loc2`='Je viens de me déco / reco. Choc temporel.' WHERE `id`=277; +UPDATE `ai_playerbot_texts` SET `id`=278, `text_loc2`='Faites moins de bruit, j’suis perdu dans %zone_name…' WHERE `id`=278; +UPDATE `ai_playerbot_texts` SET `id`=279, `text_loc2`='Quelqu’un veut boire un verre à %zone_name ? hic' WHERE `id`=279; +UPDATE `ai_playerbot_texts` SET `id`=280, `text_loc2`='hahahahaheeeee dirin diring inggggg hahahahaheeeeeeeeeeeeee' WHERE `id`=280; +UPDATE `ai_playerbot_texts` SET `id`=281, `text_loc2`='Avant, les appâts étaient crédibles. Maintenant c’est TikTok.' WHERE `id`=281; +UPDATE `ai_playerbot_texts` SET `id`=282, `text_loc2`='Peut-être que t’as juste perdu ton innocence.' WHERE `id`=282; +UPDATE `ai_playerbot_texts` SET `id`=283, `text_loc2`='Y’a une guilde qui veut carry un %my_role fragile ?' WHERE `id`=283; +UPDATE `ai_playerbot_texts` SET `id`=284, `text_loc2`='Plus on monte en niveau, plus l’or coule à flots… sauf pour moi.' WHERE `id`=284; +UPDATE `ai_playerbot_texts` SET `id`=285, `text_loc2`='Bonjour ! (oui, juste ça)' WHERE `id`=285; +UPDATE `ai_playerbot_texts` SET `id`=286, `text_loc2`='Pourquoi j’ai mal au cul ?' WHERE `id`=286; +UPDATE `ai_playerbot_texts` SET `id`=287, `text_loc2`='Je pense que l’esprit est BiS pour monter de niveau.' WHERE `id`=287; +UPDATE `ai_playerbot_texts` SET `id`=288, `text_loc2`='Encore plus si t’es troll. Véridique.' WHERE `id`=288; +UPDATE `ai_playerbot_texts` SET `id`=289, `text_loc2`='QUELQU’UN PEUT M’INVITER ?' WHERE `id`=289; +UPDATE `ai_playerbot_texts` SET `id`=290, `text_loc2`='J’ai besoin de beaucouuuup de boissons. Et d’un foie neuf.' WHERE `id`=290; +UPDATE `ai_playerbot_texts` SET `id`=291, `text_loc2`='M*rde de gnomes…' WHERE `id`=291; +UPDATE `ai_playerbot_texts` SET `id`=292, `text_loc2`='Personne n’aime les gnomes. Même pas eux.' WHERE `id`=292; +UPDATE `ai_playerbot_texts` SET `id`=293, `text_loc2`='Les gnomes ne servent qu’à une chose… les blagues.' WHERE `id`=293; +UPDATE `ai_playerbot_texts` SET `id`=294, `text_loc2`='Bah…' WHERE `id`=294; +UPDATE `ai_playerbot_texts` SET `id`=295, `text_loc2`='… des champignons.' WHERE `id`=295; +UPDATE `ai_playerbot_texts` SET `id`=296, `text_loc2`='Les pensées automatiques, c’est flippant. Surtout les miennes.' WHERE `id`=296; +UPDATE `ai_playerbot_texts` SET `id`=297, `text_loc2`='L’esprit est plus malléable qu’on aimerait le croire.' WHERE `id`=297; +UPDATE `ai_playerbot_texts` SET `id`=298, `text_loc2`='Y’a des guildes pour leveling ? Ou faut pleurer en solo ?' WHERE `id`=298; +UPDATE `ai_playerbot_texts` SET `id`=299, `text_loc2`='brb' WHERE `id`=299; +UPDATE `ai_playerbot_texts` SET `id`=300, `text_loc2`='Pourquoi la neige est blanche mais la glace est transparente ? Mystère.' WHERE `id`=300; +UPDATE `ai_playerbot_texts` SET `id`=301, `text_loc2`='Pourquoi la crème fouettée est fluffy, mais pas la normale ?' WHERE `id`=301; +UPDATE `ai_playerbot_texts` SET `id`=302, `text_loc2`='Pourquoi les pieds sentent alors qu’ils n’ont pas de nez ?' WHERE `id`=302; +UPDATE `ai_playerbot_texts` SET `id`=303, `text_loc2`='On dirait que la boîte à noobs vient de s’ouvrir.' WHERE `id`=303; +UPDATE `ai_playerbot_texts` SET `id`=304, `text_loc2`='Arrêtez de troller les nouveaux avec vos réponses à la con.' WHERE `id`=304; +UPDATE `ai_playerbot_texts` SET `id`=305, `text_loc2`='Y’a du PvP sur ce serveur ? Ou que des pleureurs ?' WHERE `id`=305; +UPDATE `ai_playerbot_texts` SET `id`=306, `text_loc2`='évidemment...' WHERE `id`=306; +UPDATE `ai_playerbot_texts` SET `id`=307, `text_loc2`='ouf… :)' WHERE `id`=307; +UPDATE `ai_playerbot_texts` SET `id`=308, `text_loc2`='Vous saviez que… ? Bah moi non plus.' WHERE `id`=308; +UPDATE `ai_playerbot_texts` SET `id`=309, `text_loc2`='Je ne tente pas d’imaginer ce que ressentent les autres créatures. Trop de boulot.' WHERE `id`=309; +UPDATE `ai_playerbot_texts` SET `id`=310, `text_loc2`='Oups, mauvais canal.' WHERE `id`=310; +UPDATE `ai_playerbot_texts` SET `id`=311, `text_loc2`='Bruh, vous êtes déchaînés aujourd’hui.' WHERE `id`=311; +UPDATE `ai_playerbot_texts` SET `id`=312, `text_loc2`='Juste pour que tout le monde sache : mon message est passé ici' WHERE `id`=312; +UPDATE `ai_playerbot_texts` SET `id`=313, `text_loc2`='grrr énervéééééé' WHERE `id`=313; +UPDATE `ai_playerbot_texts` SET `id`=314, `text_loc2`='Le farm, c’est la vie. Ou la prison. On sait pas trop.' WHERE `id`=314; +UPDATE `ai_playerbot_texts` SET `id`=315, `text_loc2`='WoW me garde vif. Ou insomniaque.' WHERE `id`=315; +UPDATE `ai_playerbot_texts` SET `id`=316, `text_loc2`='Hé, question : où on prend le rôle pour plus d’XP ? Je suis à %zone_name.' WHERE `id`=316; +UPDATE `ai_playerbot_texts` SET `id`=317, `text_loc2`='Vous aimez les saucisses ? Celles qui se lootent hein !' WHERE `id`=317; +UPDATE `ai_playerbot_texts` SET `id`=318, `text_loc2`='Invitez-moi. Je suis utile. Enfin... je crois.' WHERE `id`=318; +UPDATE `ai_playerbot_texts` SET `id`=319, `text_loc2`='À votre avis, quelle classe est la meilleure en PvP ?' WHERE `id`=319; +UPDATE `ai_playerbot_texts` SET `id`=320, `text_loc2`='Où est ce foutu maître de cuisine à %zone_name ?!' WHERE `id`=320; +UPDATE `ai_playerbot_texts` SET `id`=321, `text_loc2`='Vous savez ce qu’il se passe à %zone_name ? Spoiler : pas grand-chose.' WHERE `id`=321; +UPDATE `ai_playerbot_texts` SET `id`=322, `text_loc2`='J’ai besoin de crafter un truc. Ou d’un miracle.' WHERE `id`=322; +UPDATE `ai_playerbot_texts` SET `id`=323, `text_loc2`='C’est quoi “ligma” ?' WHERE `id`=323; +UPDATE `ai_playerbot_texts` SET `id`=324, `text_loc2`='Et “sugma” ?' WHERE `id`=324; +UPDATE `ai_playerbot_texts` SET `id`=325, `text_loc2`='ligma balls' WHERE `id`=325; +UPDATE `ai_playerbot_texts` SET `id`=326, `text_loc2`='sugma balls' WHERE `id`=326; +UPDATE `ai_playerbot_texts` SET `id`=327, `text_loc2`='JE MANGE DES FESSES' WHERE `id`=327; +UPDATE `ai_playerbot_texts` SET `id`=328, `text_loc2`='J’ai envie de me fourrer %random_inventory_item_link là où le soleil ne brille pas' WHERE `id`=328; +UPDATE `ai_playerbot_texts` SET `id`=329, `text_loc2`='J’ai envie de te fourrer %random_inventory_item_link là où tu penses' WHERE `id`=329; +UPDATE `ai_playerbot_texts` SET `id`=330, `text_loc2`='Darnasses (oui oui, avec deux "s", on juge pas)' WHERE `id`=330; +UPDATE `ai_playerbot_texts` SET `id`=331, `text_loc2`='On dirait que t’as chopé le syndrôme de sugma' WHERE `id`=331; +UPDATE `ai_playerbot_texts` SET `id`=332, `text_loc2`='deez nutz dans ta bouche (attention, ça pique)' WHERE `id`=332; +UPDATE `ai_playerbot_texts` SET `id`=333, `text_loc2`='Sympa ton os, frérot' WHERE `id`=333; +UPDATE `ai_playerbot_texts` SET `id`=334, `text_loc2`='ERP ? Euh… Emmental, Roquefort, Parmesan ?' WHERE `id`=334; +UPDATE `ai_playerbot_texts` SET `id`=335, `text_loc2`='J’ai tout essayé, mais au final c’est l’ERP qui a marché... triste monde' WHERE `id`=335; +UPDATE `ai_playerbot_texts` SET `id`=336, `text_loc2`='J’ai envie de batifoler à %zone_name. Qui vient ?' WHERE `id`=336; +UPDATE `ai_playerbot_texts` SET `id`=337, `text_loc2`='Recherche gnome femelle avec gorille pour ERP sauvage à %zone_name' WHERE `id`=337; +UPDATE `ai_playerbot_texts` SET `id`=338, `text_loc2`='Je peux comprendre un idiot, mais un gros pervers ? Là j’suis perdu' WHERE `id`=338; +UPDATE `ai_playerbot_texts` SET `id`=339, `text_loc2`='Aucun GYAT en vue à %zone_name… scandale national' WHERE `id`=339; +UPDATE `ai_playerbot_texts` SET `id`=340, `text_loc2`='Je tue tous les animaux de %zone_name. Désolé WWF !' WHERE `id`=340; +UPDATE `ai_playerbot_texts` SET `id`=341, `text_loc2`='Heureusement que j’ai trois jambes!' WHERE `id`=341; +UPDATE `ai_playerbot_texts` SET `id`=342, `text_loc2`='Sois pas vénère, je goon comme un sigma' WHERE `id`=342; +UPDATE `ai_playerbot_texts` SET `id`=343, `text_loc2`='Essaye doigt, mais trou (philosophie du vide)' WHERE `id`=343; +UPDATE `ai_playerbot_texts` SET `id`=344, `text_loc2`='%prefix %random_taken_quest_or_item_link' WHERE `id`=344; +UPDATE `ai_playerbot_texts` SET `id`=345, `text_loc2`='%prefix %random_inventory_item_link' WHERE `id`=345; +UPDATE `ai_playerbot_texts` SET `id`=346, `text_loc2`='%thunderfury_link' WHERE `id`=346; +UPDATE `ai_playerbot_texts` SET `id`=347, `text_loc2`='%thunderfury_link%thunderfury_link' WHERE `id`=347; +UPDATE `ai_playerbot_texts` SET `id`=348, `text_loc2`='%thunderfury_link%thunderfury_link%thunderfury_link' WHERE `id`=348; +UPDATE `ai_playerbot_texts` SET `id`=349, `text_loc2`='Je crois que je viens d’entendre %thunderfury_link' WHERE `id`=349; +UPDATE `ai_playerbot_texts` SET `id`=350, `text_loc2`='J’ai entendu %thunderfury_link, non ?' WHERE `id`=350; +UPDATE `ai_playerbot_texts` SET `id`=351, `text_loc2`='J’ai clairement entendu %thunderfury_link' WHERE `id`=351; +UPDATE `ai_playerbot_texts` SET `id`=352, `text_loc2`='J’suis pas sûr, mais j’crois avoir entendu %thunderfury_link' WHERE `id`=352; +UPDATE `ai_playerbot_texts` SET `id`=353, `text_loc2`='T’as dit %thunderfury_link là ?' WHERE `id`=353; +UPDATE `ai_playerbot_texts` SET `id`=354, `text_loc2`='Quelqu’un a dit %thunderfury_link ?' WHERE `id`=354; +UPDATE `ai_playerbot_texts` SET `id`=355, `text_loc2`='Quelqu’un a VRAIMENT dit %thunderfury_link ?' WHERE `id`=355; +UPDATE `ai_playerbot_texts` SET `id`=356, `text_loc2`='Quelqu’un a parlé de %thunderfury_link' WHERE `id`=356; +UPDATE `ai_playerbot_texts` SET `id`=357, `text_loc2`='%thunderfury_link sort du placard, les gars' WHERE `id`=357; +UPDATE `ai_playerbot_texts` SET `id`=358, `text_loc2`='J’aurais juré que c’était un %thunderfury_link… ou peut-être un %thunderfury_link' WHERE `id`=358; +UPDATE `ai_playerbot_texts` SET `id`=359, `text_loc2`='Pourquoi utiliser %thunderfury_link alors que %thunderfury_link est bien plus OP ?' WHERE `id`=359; +UPDATE `ai_playerbot_texts` SET `id`=360, `text_loc2`='WTS %item_formatted_link pour %cost_gold ! Occasion en or !' WHERE `id`=360; +UPDATE `ai_playerbot_texts` SET `id`=361, `text_loc2`='Qui veut %item_formatted_link pour %cost_gold ?' WHERE `id`=361; +UPDATE `ai_playerbot_texts` SET `id`=362, `text_loc2`='Quelqu’un veut %item_formatted_link ? Seulement %cost_gold' WHERE `id`=362; +UPDATE `ai_playerbot_texts` SET `id`=363, `text_loc2`='Juste %cost_gold pour %item_formatted_link, vous hésitez encore ?' WHERE `id`=363; +UPDATE `ai_playerbot_texts` SET `id`=364, `text_loc2`='Je vends %item_formatted_link pour %cost_gold' WHERE `id`=364; +UPDATE `ai_playerbot_texts` SET `id`=365, `text_loc2`='%item_formatted_link est à toi pour seulement %cost_gold !' WHERE `id`=365; +UPDATE `ai_playerbot_texts` SET `id`=366, `text_loc2`='Prix ridicule : %cost_gold pour %item_formatted_link ! C’est cadeau !' WHERE `id`=366; +UPDATE `ai_playerbot_texts` SET `id`=367, `text_loc2`='Je cherche à vendre %item_formatted_link pour %cost_gold' WHERE `id`=367; +UPDATE `ai_playerbot_texts` SET `id`=368, `text_loc2`='Qui a besoin de %item_formatted_link ? Seulement %cost_gold' WHERE `id`=368; +UPDATE `ai_playerbot_texts` SET `id`=369, `text_loc2`='Quelqu’un veut %item_formatted_link pour %cost_gold ?' WHERE `id`=369; +UPDATE `ai_playerbot_texts` SET `id`=370, `text_loc2`='%cost_gold pour %item_formatted_link. Moins cher qu’à l’HV !' WHERE `id`=370; +UPDATE `ai_playerbot_texts` SET `id`=371, `text_loc2`='%item_formatted_link est cher, mais je te le fais à %cost_gold' WHERE `id`=371; +UPDATE `ai_playerbot_texts` SET `id`=372, `text_loc2`='Tu trouveras jamais %item_formatted_link moins cher que %cost_gold' WHERE `id`=372; +UPDATE `ai_playerbot_texts` SET `id`=373, `text_loc2`='J’ai besoin de plus que %item_formatted_link, là !' WHERE `id`=373; +UPDATE `ai_playerbot_texts` SET `id`=374, `text_loc2`='J’ai %item_formatted_link et j’en veux encore' WHERE `id`=374; +UPDATE `ai_playerbot_texts` SET `id`=375, `text_loc2`='J’ai %item_formatted_link. Qui l’achète pour %cost_gold ?' WHERE `id`=375; +UPDATE `ai_playerbot_texts` SET `id`=376, `text_loc2`='WTB %item_formatted_link pour %cost_gold, quelqu’un ?' WHERE `id`=376; +UPDATE `ai_playerbot_texts` SET `id`=377, `text_loc2`='Et %item_formatted_link ? Pour %cost_gold, ça vous tente ?' WHERE `id`=377; +UPDATE `ai_playerbot_texts` SET `id`=378, `text_loc2`='Qui m’a traité de radin ? %item_formatted_link pour %cost_gold c’est honnête !' WHERE `id`=378; +UPDATE `ai_playerbot_texts` SET `id`=379, `text_loc2`='Je vends %item_formatted_link. Juste %cost_gold' WHERE `id`=379; +UPDATE `ai_playerbot_texts` SET `id`=380, `text_loc2`='LFG pour du farm, et au passage %item_formatted_link à vendre %cost_gold' WHERE `id`=380; +UPDATE `ai_playerbot_texts` SET `id`=381, `text_loc2`='Presque tout vendu aujourd’hui. Me reste %item_formatted_link pour %cost_gold' WHERE `id`=381; +UPDATE `ai_playerbot_texts` SET `id`=382, `text_loc2`='À quoi sert le canal commerce ? Vendre %item_formatted_link pour %cost_gold, évidemment' WHERE `id`=382; +UPDATE `ai_playerbot_texts` SET `id`=383, `text_loc2`='Quelqu’un peut battre %cost_gold pour %item_formatted_link ? J’attends…' WHERE `id`=383; +UPDATE `ai_playerbot_texts` SET `id`=384, `text_loc2`='Envie d’arrêter le spam commerce ? Achetez %item_formatted_link à %cost_gold !' WHERE `id`=384; +UPDATE `ai_playerbot_texts` SET `id`=385, `text_loc2`='Tout le monde spam, moi aussi : %cost_gold pour %item_formatted_link !' WHERE `id`=385; +UPDATE `ai_playerbot_texts` SET `id`=386, `text_loc2`='%item_formatted_link est utile ? Je sais pas, mais je le vends %cost_gold' WHERE `id`=386; +UPDATE `ai_playerbot_texts` SET `id`=387, `text_loc2`='J’ai %item_formatted_link prêt à vendre %cost_gold' WHERE `id`=387; +UPDATE `ai_playerbot_texts` SET `id`=388, `text_loc2`='Hier j’ai rien foutu, mais j’ai loot %item_formatted_link. À vendre %cost_gold' WHERE `id`=388; +UPDATE `ai_playerbot_texts` SET `id`=389, `text_loc2`='J’ai farmé hier, j’ai eu %item_formatted_link. WTB ? %cost_gold' WHERE `id`=389; +UPDATE `ai_playerbot_texts` SET `id`=390, `text_loc2`='J’ai acheté %item_formatted_link hier. Quelqu’un le veut ? %cost_gold' WHERE `id`=390; +UPDATE `ai_playerbot_texts` SET `id`=391, `text_loc2`='Quelqu’un cherchait %item_formatted_link ? C’est %cost_gold toujours' WHERE `id`=391; +UPDATE `ai_playerbot_texts` SET `id`=392, `text_loc2`='J’ai encore %item_formatted_link. Achetez-le %cost_gold' WHERE `id`=392; +UPDATE `ai_playerbot_texts` SET `id`=393, `text_loc2`='Avant j’en avais plein %item_formatted_link, maintenant je dois vendre à %cost_gold' WHERE `id`=393; +UPDATE `ai_playerbot_texts` SET `id`=394, `text_loc2`='J’aimerais en avoir plus que %item_formatted_link. Mais achetez celui-là %cost_gold' WHERE `id`=394; +UPDATE `ai_playerbot_texts` SET `id`=395, `text_loc2`='Ton or te sert à quoi ? À acheter %item_formatted_link pour %cost_gold' WHERE `id`=395; +UPDATE `ai_playerbot_texts` SET `id`=396, `text_loc2`='Ayez pitié, donnez-moi de l’or... ou achetez %item_formatted_link %cost_gold' WHERE `id`=396; +UPDATE `ai_playerbot_texts` SET `id`=397, `text_loc2`='Est-ce que %cost_gold est un bon prix pour %item_formatted_link ?' WHERE `id`=397; +UPDATE `ai_playerbot_texts` SET `id`=398, `text_loc2`='J’ai acheté %item_formatted_links hier, mais j’en veux plus. À vendre %cost_gold' WHERE `id`=398; +UPDATE `ai_playerbot_texts` SET `id`=399, `text_loc2`='Je vais le mettre à l’HV, mais tu peux l’avoir moins cher : %cost_gold' WHERE `id`=399; +UPDATE `ai_playerbot_texts` SET `id`=400, `text_loc2`='Pourquoi j’ai acheté %item_formatted_link bordel ? Quelqu’un le veut ? %cost_gold' WHERE `id`=400; +UPDATE `ai_playerbot_texts` SET `id`=401, `text_loc2`='J’ai %quest_links' WHERE `id`=401; +UPDATE `ai_playerbot_texts` SET `id`=402, `text_loc2`='Moi aussi j’ai %quest_links' WHERE `id`=402; +UPDATE `ai_playerbot_texts` SET `id`=403, `text_loc2`='Moi aussi j’ai %quest_links, je suis à %zone_name' WHERE `id`=403; +UPDATE `ai_playerbot_texts` SET `id`=404, `text_loc2`='%other_name, moi aussi j’ai %quest_links' WHERE `id`=404; +UPDATE `ai_playerbot_texts` SET `id`=405, `text_loc2`='%other_name, moi aussi j’ai %quest_links, et je suis à %zone_name' WHERE `id`=405; +UPDATE `ai_playerbot_texts` SET `id`=406, `text_loc2`='Je suis dispo pour %quest_links, je suis à %zone_name' WHERE `id`=406; +UPDATE `ai_playerbot_texts` SET `id`=407, `text_loc2`='Je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=407; +UPDATE `ai_playerbot_texts` SET `id`=408, `text_loc2`='%other_name, je suis dispo pour %quest_links à %zone_name' WHERE `id`=408; +UPDATE `ai_playerbot_texts` SET `id`=409, `text_loc2`='%other_name, je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=409; +UPDATE `ai_playerbot_texts` SET `id`=410, `text_loc2`='Hey, je suis partant pour %quest_links' WHERE `id`=410; +UPDATE `ai_playerbot_texts` SET `id`=411, `text_loc2`='Hey, je pourrais faire %quest_links avec toi' WHERE `id`=411; +UPDATE `ai_playerbot_texts` SET `id`=412, `text_loc2`='Hey, moi aussi j’ai %quest_links' WHERE `id`=412; +UPDATE `ai_playerbot_texts` SET `id`=413, `text_loc2`='Hey %other_name, partant pour %quest_links' WHERE `id`=413; +UPDATE `ai_playerbot_texts` SET `id`=414, `text_loc2`='Hey %other_name, je peux faire %quest_links avec toi' WHERE `id`=414; +UPDATE `ai_playerbot_texts` SET `id`=415, `text_loc2`='Hey %other_name, moi aussi j’ai %quest_links' WHERE `id`=415; +UPDATE `ai_playerbot_texts` SET `id`=416, `text_loc2`='On se groupe pour %quest_links ?' WHERE `id`=416; +UPDATE `ai_playerbot_texts` SET `id`=417, `text_loc2`='Je suis partant pour %quest_links, je suis à %zone_name' WHERE `id`=417; +UPDATE `ai_playerbot_texts` SET `id`=418, `text_loc2`='Je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=418; +UPDATE `ai_playerbot_texts` SET `id`=419, `text_loc2`='%other_name, je peux te vendre %formatted_item_links' WHERE `id`=419; +UPDATE `ai_playerbot_texts` SET `id`=420, `text_loc2`='Je peux peut-être vendre %formatted_item_links' WHERE `id`=420; +UPDATE `ai_playerbot_texts` SET `id`=421, `text_loc2`='Je pense pouvoir vendre %formatted_item_links' WHERE `id`=421; +UPDATE `ai_playerbot_texts` SET `id`=422, `text_loc2`='%other_name, je peux peut-être te vendre %formatted_item_links' WHERE `id`=422; +UPDATE `ai_playerbot_texts` SET `id`=423, `text_loc2`='%other_name, tu penses que je peux vendre %formatted_item_links ?' WHERE `id`=423; +UPDATE `ai_playerbot_texts` SET `id`=424, `text_loc2`='Je peux te vendre %formatted_item_links' WHERE `id`=424; +UPDATE `ai_playerbot_texts` SET `id`=425, `text_loc2`='Hey, j’ai %formatted_item_links à vendre' WHERE `id`=425; +UPDATE `ai_playerbot_texts` SET `id`=426, `text_loc2`='Hey, je pourrais peut-être vendre %formatted_item_links' WHERE `id`=426; +UPDATE `ai_playerbot_texts` SET `id`=427, `text_loc2`='Quête acceptée' WHERE `id`=427; +UPDATE `ai_playerbot_texts` SET `id`=428, `text_loc2`='Quête abandonnée' WHERE `id`=428; +UPDATE `ai_playerbot_texts` SET `id`=429, `text_loc2`='Je ne peux pas prendre cette quête' WHERE `id`=429; +UPDATE `ai_playerbot_texts` SET `id`=430, `text_loc2`='Je ne peux pas parler au donneur de quête' WHERE `id`=430; +UPDATE `ai_playerbot_texts` SET `id`=431, `text_loc2`='J’ai déjà terminé %quest' WHERE `id`=431; +UPDATE `ai_playerbot_texts` SET `id`=432, `text_loc2`='J’ai déjà la quête %quest' WHERE `id`=432; +UPDATE `ai_playerbot_texts` SET `id`=433, `text_loc2`='Je ne peux pas prendre %quest' WHERE `id`=433; +UPDATE `ai_playerbot_texts` SET `id`=434, `text_loc2`='Je ne peux pas prendre %quest, mon journal de quêtes est plein' WHERE `id`=434; +UPDATE `ai_playerbot_texts` SET `id`=435, `text_loc2`='Je ne peux pas prendre %quest, mes sacs sont pleins' WHERE `id`=435; +UPDATE `ai_playerbot_texts` SET `id`=436, `text_loc2`='J’ai accepté la quête %quest' WHERE `id`=436; +UPDATE `ai_playerbot_texts` SET `id`=437, `text_loc2`='Je n’ai pas encore terminé la quête %quest' WHERE `id`=437; +UPDATE `ai_playerbot_texts` SET `id`=438, `text_loc2`='La quête %quest est dispo' WHERE `id`=438; +UPDATE `ai_playerbot_texts` SET `id`=439, `text_loc2`='J’ai échoué à la quête %quest' WHERE `id`=439; +UPDATE `ai_playerbot_texts` SET `id`=440, `text_loc2`='Je ne peux pas rendre la quête %quest' WHERE `id`=440; +UPDATE `ai_playerbot_texts` SET `id`=441, `text_loc2`='J’ai terminé la quête %quest' WHERE `id`=441; +UPDATE `ai_playerbot_texts` SET `id`=442, `text_loc2`='J’ai terminé la quête %quest et reçu %item' WHERE `id`=442; +UPDATE `ai_playerbot_texts` SET `id`=443, `text_loc2`='Quelle récompense devrais-je choisir pour la quête %quest ? %rewards' WHERE `id`=443; +UPDATE `ai_playerbot_texts` SET `id`=444, `text_loc2`='OK, je vais prendre %item comme récompense' WHERE `id`=444; +UPDATE `ai_playerbot_texts` SET `id`=445, `text_loc2`='Bonjour' WHERE `id`=445; +UPDATE `ai_playerbot_texts` SET `id`=446, `text_loc2`='Bonjour !' WHERE `id`=446; +UPDATE `ai_playerbot_texts` SET `id`=447, `text_loc2`='Salut' WHERE `id`=447; +UPDATE `ai_playerbot_texts` SET `id`=448, `text_loc2`='Salut !' WHERE `id`=448; +UPDATE `ai_playerbot_texts` SET `id`=449, `text_loc2`='Salut à toi !' WHERE `id`=449; +UPDATE `ai_playerbot_texts` SET `id`=450, `text_loc2`='Bonjour, je vous suis !' WHERE `id`=450; +UPDATE `ai_playerbot_texts` SET `id`=451, `text_loc2`='Bonjour, montrez-moi le chemin !' WHERE `id`=451; +UPDATE `ai_playerbot_texts` SET `id`=452, `text_loc2`='Salut, montre-moi le chemin !' WHERE `id`=452; +UPDATE `ai_playerbot_texts` SET `id`=453, `text_loc2`='Hey %player, tu veux rejoindre mon groupe ?' WHERE `id`=453; +UPDATE `ai_playerbot_texts` SET `id`=454, `text_loc2`='Hey %player, tu veux rejoindre mon groupe ?' WHERE `id`=454; +UPDATE `ai_playerbot_texts` SET `id`=455, `text_loc2`='Déconnexion annulée !' WHERE `id`=455; +UPDATE `ai_playerbot_texts` SET `id`=456, `text_loc2`='Je me déconnecte !' WHERE `id`=456; +UPDATE `ai_playerbot_texts` SET `id`=457, `text_loc2`='Au revoir !' WHERE `id`=457; +UPDATE `ai_playerbot_texts` SET `id`=458, `text_loc2`='Bye bye !' WHERE `id`=458; +UPDATE `ai_playerbot_texts` SET `id`=459, `text_loc2`='À plus tard !' WHERE `id`=459; +UPDATE `ai_playerbot_texts` SET `id`=460, `text_loc2`='c’était quoi ce truc %s ?' WHERE `id`=460; +UPDATE `ai_playerbot_texts` SET `id`=461, `text_loc2`='pas sûr d’avoir compris %s ?' WHERE `id`=461; +UPDATE `ai_playerbot_texts` SET `id`=462, `text_loc2`='euh… j’ai aucune idée de ce que tu racontes' WHERE `id`=462; +UPDATE `ai_playerbot_texts` SET `id`=463, `text_loc2`='tu parles à moi, %s ?' WHERE `id`=463; +UPDATE `ai_playerbot_texts` SET `id`=464, `text_loc2`='whaaaa ?' WHERE `id`=464; +UPDATE `ai_playerbot_texts` SET `id`=465, `text_loc2`='hein ?' WHERE `id`=465; +UPDATE `ai_playerbot_texts` SET `id`=466, `text_loc2`='quoi ?' WHERE `id`=466; +UPDATE `ai_playerbot_texts` SET `id`=467, `text_loc2`='tu parles ou tu râles ?' WHERE `id`=467; +UPDATE `ai_playerbot_texts` SET `id`=468, `text_loc2`='comme tu veux, mec' WHERE `id`=468; +UPDATE `ai_playerbot_texts` SET `id`=469, `text_loc2`='tu m’as perdu là' WHERE `id`=469; +UPDATE `ai_playerbot_texts` SET `id`=470, `text_loc2`='Bla bla bla…' WHERE `id`=470; +UPDATE `ai_playerbot_texts` SET `id`=471, `text_loc2`='T’as dit quoi, %s ?' WHERE `id`=471; +UPDATE `ai_playerbot_texts` SET `id`=472, `text_loc2`='Concentre-toi sur le jeu, %s !' WHERE `id`=472; +UPDATE `ai_playerbot_texts` SET `id`=473, `text_loc2`='Parler avec toi %s, c’est génial ! J’ai toujours rêvé de te rencontrer' WHERE `id`=473; +UPDATE `ai_playerbot_texts` SET `id`=474, `text_loc2`='Ces messages me font flipper ! J’ai l’impression de tous vous connaître !' WHERE `id`=474; +UPDATE `ai_playerbot_texts` SET `id`=475, `text_loc2`='Ouais bien sûr ! HAHA ! C’est ça, allez !' WHERE `id`=475; +UPDATE `ai_playerbot_texts` SET `id`=476, `text_loc2`='Je te crois !!! (ou pas)' WHERE `id`=476; +UPDATE `ai_playerbot_texts` SET `id`=477, `text_loc2`='OK, uhuh LOL' WHERE `id`=477; +UPDATE `ai_playerbot_texts` SET `id`=478, `text_loc2`='Pourquoi tout le monde dit toujours les mêmes trucs ???' WHERE `id`=478; +UPDATE `ai_playerbot_texts` SET `id`=479, `text_loc2`='Hey %s… euh, laisse tomber !' WHERE `id`=479; +UPDATE `ai_playerbot_texts` SET `id`=480, `text_loc2`='Tu parles de quoi %s ? Sérieux ?' WHERE `id`=480; +UPDATE `ai_playerbot_texts` SET `id`=481, `text_loc2`='Qui a dit ça ? Je me sens visé là' WHERE `id`=481; +UPDATE `ai_playerbot_texts` SET `id`=482, `text_loc2`='wtf vous racontez tous là ?' WHERE `id`=482; +UPDATE `ai_playerbot_texts` SET `id`=483, `text_loc2`='fr fr no cap on a stack' WHERE `id`=483; +UPDATE `ai_playerbot_texts` SET `id`=484, `text_loc2`='t’auras que dalle' WHERE `id`=484; +UPDATE `ai_playerbot_texts` SET `id`=485, `text_loc2`='swag' WHERE `id`=485; +UPDATE `ai_playerbot_texts` SET `id`=486, `text_loc2`='merci !' WHERE `id`=486; +UPDATE `ai_playerbot_texts` SET `id`=487, `text_loc2`='non' WHERE `id`=487; +UPDATE `ai_playerbot_texts` SET `id`=488, `text_loc2`='Yep' WHERE `id`=488; +UPDATE `ai_playerbot_texts` SET `id`=489, `text_loc2`='Paix à son ame.' WHERE `id`=489; +UPDATE `ai_playerbot_texts` SET `id`=490, `text_loc2`='%s sans déconner xD' WHERE `id`=490; +UPDATE `ai_playerbot_texts` SET `id`=491, `text_loc2`='pourquoi ça ?' WHERE `id`=491; +UPDATE `ai_playerbot_texts` SET `id`=492, `text_loc2`='mdr' WHERE `id`=492; +UPDATE `ai_playerbot_texts` SET `id`=493, `text_loc2`='Je pensais fermer ma gueule, j’ai encore rien compris au chat' WHERE `id`=493; +UPDATE `ai_playerbot_texts` SET `id`=494, `text_loc2`='Je peux devenir vraiment jaloux... comme un elfe sans loot' WHERE `id`=494; +UPDATE `ai_playerbot_texts` SET `id`=495, `text_loc2`='%s tu captes pas le sarcasme qui dégouline de mon message là ?' WHERE `id`=495; +UPDATE `ai_playerbot_texts` SET `id`=496, `text_loc2`='Il a dit "no homo", donc c’est bon apparemment' WHERE `id`=496; +UPDATE `ai_playerbot_texts` SET `id`=497, `text_loc2`='Instant nain™' WHERE `id`=497; +UPDATE `ai_playerbot_texts` SET `id`=498, `text_loc2`='Oui %s' WHERE `id`=498; +UPDATE `ai_playerbot_texts` SET `id`=499, `text_loc2`='Intéressant… ou pas' WHERE `id`=499; +UPDATE `ai_playerbot_texts` SET `id`=500, `text_loc2`='lol' WHERE `id`=500; +UPDATE `ai_playerbot_texts` SET `id`=501, `text_loc2`='%s va te faire voir mec :D' WHERE `id`=501; +UPDATE `ai_playerbot_texts` SET `id`=502, `text_loc2`=':^)' WHERE `id`=502; +UPDATE `ai_playerbot_texts` SET `id`=503, `text_loc2`='merci' WHERE `id`=503; +UPDATE `ai_playerbot_texts` SET `id`=504, `text_loc2`='%s bien dit !' WHERE `id`=504; +UPDATE `ai_playerbot_texts` SET `id`=505, `text_loc2`='ouiiiii' WHERE `id`=505; +UPDATE `ai_playerbot_texts` SET `id`=506, `text_loc2`='ouais' WHERE `id`=506; +UPDATE `ai_playerbot_texts` SET `id`=507, `text_loc2`='ooooooh (ça sent le loot !)' WHERE `id`=507; +UPDATE `ai_playerbot_texts` SET `id`=508, `text_loc2`='hmm… je réfléchis. Ou pas.' WHERE `id`=508; +UPDATE `ai_playerbot_texts` SET `id`=509, `text_loc2`='ouais c’est ça' WHERE `id`=509; +UPDATE `ai_playerbot_texts` SET `id`=510, `text_loc2`='t’as failli me faire vomir, wtf' WHERE `id`=510; +UPDATE `ai_playerbot_texts` SET `id`=511, `text_loc2`='chaud !' WHERE `id`=511; +UPDATE `ai_playerbot_texts` SET `id`=512, `text_loc2`='les rageux pleurent' WHERE `id`=512; +UPDATE `ai_playerbot_texts` SET `id`=513, `text_loc2`='T’as mangé quoi %s ? Des cailloux ?' WHERE `id`=513; +UPDATE `ai_playerbot_texts` SET `id`=514, `text_loc2`='wtf' WHERE `id`=514; +UPDATE `ai_playerbot_texts` SET `id`=515, `text_loc2`='Je vais essayer de comprendre ce que t’as dit… courage à moi' WHERE `id`=515; +UPDATE `ai_playerbot_texts` SET `id`=516, `text_loc2`='confus' WHERE `id`=516; +UPDATE `ai_playerbot_texts` SET `id`=517, `text_loc2`='putain ouais' WHERE `id`=517; +UPDATE `ai_playerbot_texts` SET `id`=518, `text_loc2`='0/10 ne lirait pas ça une deuxième fois' WHERE `id`=518; +UPDATE `ai_playerbot_texts` SET `id`=519, `text_loc2`='10/10 je relis direct' WHERE `id`=519; +UPDATE `ai_playerbot_texts` SET `id`=520, `text_loc2`='6/10 ouais, pourquoi pas' WHERE `id`=520; +UPDATE `ai_playerbot_texts` SET `id`=521, `text_loc2`='7/10 ça passe' WHERE `id`=521; +UPDATE `ai_playerbot_texts` SET `id`=522, `text_loc2`='basé' WHERE `id`=522; +UPDATE `ai_playerbot_texts` SET `id`=523, `text_loc2`='ah ouais peut-être' WHERE `id`=523; +UPDATE `ai_playerbot_texts` SET `id`=524, `text_loc2`='ouais, et alors ?' WHERE `id`=524; +UPDATE `ai_playerbot_texts` SET `id`=525, `text_loc2`='hey %s je t’ai pas oublié' WHERE `id`=525; +UPDATE `ai_playerbot_texts` SET `id`=526, `text_loc2`='tu m’énerves %s' WHERE `id`=526; +UPDATE `ai_playerbot_texts` SET `id`=527, `text_loc2`='je vais t’avoir cette fois %s' WHERE `id`=527; +UPDATE `ai_playerbot_texts` SET `id`=528, `text_loc2`='garde un œil derrière toi %s' WHERE `id`=528; +UPDATE `ai_playerbot_texts` SET `id`=529, `text_loc2`='J’ai pas trop aimé la manche d’avant' WHERE `id`=529; +UPDATE `ai_playerbot_texts` SET `id`=530, `text_loc2`='J’ai été nul à cause de %s la manche dernière' WHERE `id`=530; +UPDATE `ai_playerbot_texts` SET `id`=531, `text_loc2`='Prépare-toi à mourir %s' WHERE `id`=531; +UPDATE `ai_playerbot_texts` SET `id`=532, `text_loc2`='J’ai pas trop kiffé que tu me tues %s' WHERE `id`=532; +UPDATE `ai_playerbot_texts` SET `id`=533, `text_loc2`='%s, je te hais' WHERE `id`=533; +UPDATE `ai_playerbot_texts` SET `id`=534, `text_loc2`='grrrrr je vais t’avoir cette fois %s' WHERE `id`=534; +UPDATE `ai_playerbot_texts` SET `id`=535, `text_loc2`='eh bien va te faire voir' WHERE `id`=535; +UPDATE `ai_playerbot_texts` SET `id`=536, `text_loc2`='%s je vais vomir dans ta sale bouche' WHERE `id`=536; +UPDATE `ai_playerbot_texts` SET `id`=537, `text_loc2`='me juge pas bordel' WHERE `id`=537; +UPDATE `ai_playerbot_texts` SET `id`=538, `text_loc2`='Ta mère est tellement grosse qu’elle passe même pas le Portail des Ténèbres' WHERE `id`=538; +UPDATE `ai_playerbot_texts` SET `id`=539, `text_loc2`='wtf' WHERE `id`=539; +UPDATE `ai_playerbot_texts` SET `id`=540, `text_loc2`='wtf ??' WHERE `id`=540; +UPDATE `ai_playerbot_texts` SET `id`=541, `text_loc2`='vie misérable' WHERE `id`=541; +UPDATE `ai_playerbot_texts` SET `id`=542, `text_loc2`='qu’est-ce qui se passe là ?' WHERE `id`=542; +UPDATE `ai_playerbot_texts` SET `id`=543, `text_loc2`='nul à chier' WHERE `id`=543; +UPDATE `ai_playerbot_texts` SET `id`=544, `text_loc2`='REVANCHE !!! Je vais l’éclater' WHERE `id`=544; +UPDATE `ai_playerbot_texts` SET `id`=545, `text_loc2`='pathétique, je me suis fait tuer par %s' WHERE `id`=545; +UPDATE `ai_playerbot_texts` SET `id`=546, `text_loc2`='ok j’en ai fini' WHERE `id`=546; +UPDATE `ai_playerbot_texts` SET `id`=547, `text_loc2`='hé hé, j’ai explosé %s ?' WHERE `id`=547; +UPDATE `ai_playerbot_texts` SET `id`=548, `text_loc2`='C’était trop facile, exploser %s' WHERE `id`=548; +UPDATE `ai_playerbot_texts` SET `id`=549, `text_loc2`='T’es grillé, clochard' WHERE `id`=549; +UPDATE `ai_playerbot_texts` SET `id`=550, `text_loc2`='ha ha' WHERE `id`=550; +UPDATE `ai_playerbot_texts` SET `id`=551, `text_loc2`='Loser' WHERE `id`=551; +UPDATE `ai_playerbot_texts` SET `id`=552, `text_loc2`='J’ai tué %s et vous êtes tous les prochains, les gars' WHERE `id`=552; +UPDATE `ai_playerbot_texts` SET `id`=553, `text_loc2`='Oh ouais, je l’ai éclaté' WHERE `id`=553; +UPDATE `ai_playerbot_texts` SET `id`=554, `text_loc2`='Je suis une machine à tuer' WHERE `id`=554; +UPDATE `ai_playerbot_texts` SET `id`=555, `text_loc2`='%s, ça me rappelle un morceau de Slayer… tout ce sang, c’est beau' WHERE `id`=555; +UPDATE `ai_playerbot_texts` SET `id`=556, `text_loc2`='Désolé %s. On peut refaire la scène ? Avec plus de drama ?' WHERE `id`=556; +UPDATE `ai_playerbot_texts` SET `id`=557, `text_loc2`='Alors %s… ça fait quoi de nourrir les vers ???' WHERE `id`=557; +UPDATE `ai_playerbot_texts` SET `id`=558, `text_loc2`='T’étais censé être mort %s ! C’est dans le script bon sang !' WHERE `id`=558; +UPDATE `ai_playerbot_texts` SET `id`=559, `text_loc2`='Désolé %s. Franchement, c’était aussi beau qu’un Warhol !' WHERE `id`=559; +UPDATE `ai_playerbot_texts` SET `id`=560, `text_loc2`='%s, je prendrai les balles en caoutchouc la prochaine fois, promis !' WHERE `id`=560; +UPDATE `ai_playerbot_texts` SET `id`=561, `text_loc2`='Qu’est-ce qu’il y a %s ?? T’as perdu la tête ? Hahaha, faut rester cool !' WHERE `id`=561; +UPDATE `ai_playerbot_texts` SET `id`=562, `text_loc2`='Fallait que je le fasse %s… Le Réalisateur me l’a dit !' WHERE `id`=562; +UPDATE `ai_playerbot_texts` SET `id`=563, `text_loc2`='Hey %s… MUAHAHAHAHAHAHAHAHAHAHA' WHERE `id`=563; +UPDATE `ai_playerbot_texts` SET `id`=564, `text_loc2`='%s, celle-là, je l’ai savourée !! Allez, on recommence Sam !' WHERE `id`=564; +UPDATE `ai_playerbot_texts` SET `id`=565, `text_loc2`='Hey %s ! Tu peux commencer à m’appeler Scarface… espèce de M…erde !' WHERE `id`=565; +UPDATE `ai_playerbot_texts` SET `id`=566, `text_loc2`='Tu me parles à moi %s ?? Tu me parles à MOI ?!' WHERE `id`=566; +UPDATE `ai_playerbot_texts` SET `id`=567, `text_loc2`='%s, fais-le bien cette fois, évite MES balles' WHERE `id`=567; +UPDATE `ai_playerbot_texts` SET `id`=568, `text_loc2`='%s, pourquoi tu traînes par terre ? Allez bouge, clown !' WHERE `id`=568; +UPDATE `ai_playerbot_texts` SET `id`=569, `text_loc2`='J’ai rigolé comme jamais' WHERE `id`=569; +UPDATE `ai_playerbot_texts` SET `id`=570, `text_loc2`='Salut %s' WHERE `id`=570; +UPDATE `ai_playerbot_texts` SET `id`=571, `text_loc2`='Oh, salut %s' WHERE `id`=571; +UPDATE `ai_playerbot_texts` SET `id`=572, `text_loc2`='Wazzup %s !!!' WHERE `id`=572; +UPDATE `ai_playerbot_texts` SET `id`=573, `text_loc2`='Salut' WHERE `id`=573; +UPDATE `ai_playerbot_texts` SET `id`=574, `text_loc2`='Wazzup' WHERE `id`=574; +UPDATE `ai_playerbot_texts` SET `id`=575, `text_loc2`='Bonjour %s' WHERE `id`=575; +UPDATE `ai_playerbot_texts` SET `id`=576, `text_loc2`='Salut %s, je te connais ?' WHERE `id`=576; +UPDATE `ai_playerbot_texts` SET `id`=577, `text_loc2`='Hey %s' WHERE `id`=577; +UPDATE `ai_playerbot_texts` SET `id`=578, `text_loc2`='Hai %s' WHERE `id`=578; +UPDATE `ai_playerbot_texts` SET `id`=579, `text_loc2`='c’est quoi ce délire' WHERE `id`=579; +UPDATE `ai_playerbot_texts` SET `id`=580, `text_loc2`='wtf' WHERE `id`=580; +UPDATE `ai_playerbot_texts` SET `id`=581, `text_loc2`='c’est du foutage de gueule' WHERE `id`=581; +UPDATE `ai_playerbot_texts` SET `id`=582, `text_loc2`='admin' WHERE `id`=582; +UPDATE `ai_playerbot_texts` SET `id`=583, `text_loc2`='Hey %s, arrête d’abuser de ton admin là' WHERE `id`=583; +UPDATE `ai_playerbot_texts` SET `id`=584, `text_loc2`='Lâche-moi admin !' WHERE `id`=584; +UPDATE `ai_playerbot_texts` SET `id`=585, `text_loc2`='T’es nul admin' WHERE `id`=585; +UPDATE `ai_playerbot_texts` SET `id`=586, `text_loc2`='C’est mon nom ça, tu veux quoi %s ?' WHERE `id`=586; +UPDATE `ai_playerbot_texts` SET `id`=587, `text_loc2`='Oui ???' WHERE `id`=587; +UPDATE `ai_playerbot_texts` SET `id`=588, `text_loc2`='Euh… quoi ?' WHERE `id`=588; +UPDATE `ai_playerbot_texts` SET `id`=589, `text_loc2`='Tu me parles à moi %s ?' WHERE `id`=589; +UPDATE `ai_playerbot_texts` SET `id`=590, `text_loc2`='J’ai des chiots sous mon armure ! (ne demande pas)' WHERE `id`=590; +UPDATE `ai_playerbot_texts` SET `id`=591, `text_loc2`='Mords-moi, !' WHERE `id`=591; +UPDATE `ai_playerbot_texts` SET `id`=592, `text_loc2`='Hey ! Devine ce que ta mère a dit hier soir !' WHERE `id`=592; +UPDATE `ai_playerbot_texts` SET `id`=593, `text_loc2`=', t’es tellement moche que tu pourrais même pas scorer dans un bordel de singes avec un sac de bananes !' WHERE `id`=593; +UPDATE `ai_playerbot_texts` SET `id`=594, `text_loc2`='Tais-toi , tu seras jamais l’homme que ta mère est !!' WHERE `id`=594; +UPDATE `ai_playerbot_texts` SET `id`=595, `text_loc2`='Ta mère était un hamster et ton père sentait la surette !' WHERE `id`=595; +UPDATE `ai_playerbot_texts` SET `id`=596, `text_loc2`='Je ne veux plus te parler, espèce de vide-écuelle à bestiaux débiles !!!' WHERE `id`=596; +UPDATE `ai_playerbot_texts` SET `id`=597, `text_loc2`='Je pète dans ta direction générale !!!' WHERE `id`=597; +UPDATE `ai_playerbot_texts` SET `id`=598, `text_loc2`='Va faire bouillir ton postérieur, fils d’un imbécile cosmique !!!' WHERE `id`=598; +UPDATE `ai_playerbot_texts` SET `id`=599, `text_loc2`='Tu comptes faire quoi , saigner sur moi ? ALLEZ, VIENS !' WHERE `id`=599; +UPDATE `ai_playerbot_texts` SET `id`=600, `text_loc2`='M-O-O-N ! Ça veut dire aggro !' WHERE `id`=600; +UPDATE `ai_playerbot_texts` SET `id`=601, `text_loc2`='T’es aussi utile qu’un unijambiste dans un concours de coups de pied au cul' WHERE `id`=601; +UPDATE `ai_playerbot_texts` SET `id`=602, `text_loc2`='Hey ! Arrête de draguer, c’est pas ton genre. C’est pas gonflable.' WHERE `id`=602; +UPDATE `ai_playerbot_texts` SET `id`=603, `text_loc2`=', t’es tellement hors catégorie que tu joues carrément à un autre sport' WHERE `id`=603; +UPDATE `ai_playerbot_texts` SET `id`=604, `text_loc2`='Tu as fait une grosse erreur aujourd’hui … t’es sorti du lit.' WHERE `id`=604; +UPDATE `ai_playerbot_texts` SET `id`=605, `text_loc2`='Je veux essayer de me transformer en cheval. Je prends l’avant, et toi… tu restes toi.' WHERE `id`=605; +UPDATE `ai_playerbot_texts` SET `id`=606, `text_loc2`='Je peux emprunter ton visage ? Mon cul part en vacances.' WHERE `id`=606; +UPDATE `ai_playerbot_texts` SET `id`=607, `text_loc2`='J’aimerais t’offrir un cadeau de départ… d’abord, fais ta part.' WHERE `id`=607; +UPDATE `ai_playerbot_texts` SET `id`=608, `text_loc2`='Avant que t’arrives, on avait faim. Maintenant on en a juste marre.' WHERE `id`=608; +UPDATE `ai_playerbot_texts` SET `id`=609, `text_loc2`='Je t’aime bien. Les gens disent que j’ai mauvais goût, mais je t’aime bien.' WHERE `id`=609; +UPDATE `ai_playerbot_texts` SET `id`=610, `text_loc2`='Je pense que t’as un complexe d’infériorité… mais t’inquiète, il est mérité.' WHERE `id`=610; +UPDATE `ai_playerbot_texts` SET `id`=611, `text_loc2`='Arrière, créature pourrie ! Ou je secoue tes os hors de ta tunique !' WHERE `id`=611; +UPDATE `ai_playerbot_texts` SET `id`=612, `text_loc2`='Je crois pas que je perds mon temps avec toi… et pourtant !' WHERE `id`=612; +UPDATE `ai_playerbot_texts` SET `id`=613, `text_loc2`='J’adore quand on m’insulte : j’ai plus besoin d’être poli.' WHERE `id`=613; +UPDATE `ai_playerbot_texts` SET `id`=614, `text_loc2`='Espèce de veston de cuir, boutons en cristal, tête nouée, braillard à gerbe, jarretière de puce, langue mielleuse, bourse espagnole !' WHERE `id`=614; +UPDATE `ai_playerbot_texts` SET `id`=615, `text_loc2`='Espèce de pleurnichard, chasseur de chauve-souris, ivrogne de malte !' WHERE `id`=615; +UPDATE `ai_playerbot_texts` SET `id`=616, `text_loc2`='T’es vraiment une idole pour les adorateurs de l’idiotie !' WHERE `id`=616; +UPDATE `ai_playerbot_texts` SET `id`=617, `text_loc2`='Misérable piaf mal dégrossi !' WHERE `id`=617; +UPDATE `ai_playerbot_texts` SET `id`=618, `text_loc2`='Fils de mandragore ! T’es plus utile en plumeau qu’en laquais !' WHERE `id`=618; +UPDATE `ai_playerbot_texts` SET `id`=619, `text_loc2`='Toi ! Gueux ! Cloporte ! Tarlouze ! Je vais chatouiller ta catastrophe !' WHERE `id`=619; +UPDATE `ai_playerbot_texts` SET `id`=620, `text_loc2`='Oh ! Infâme fille de lin mal élevé !' WHERE `id`=620; +UPDATE `ai_playerbot_texts` SET `id`=621, `text_loc2`='On fuit par ta cheminée, !' WHERE `id`=621; +UPDATE `ai_playerbot_texts` SET `id`=622, `text_loc2`='Oh toi, misérable fleur de cancre gorgée de marais !' WHERE `id`=622; +UPDATE `ai_playerbot_texts` SET `id`=623, `text_loc2`='Si j’étais comme toi, je me jetterais à la poubelle.' WHERE `id`=623; +UPDATE `ai_playerbot_texts` SET `id`=624, `text_loc2`='Apprends-moi … à ne plus penser du tout.' WHERE `id`=624; +UPDATE `ai_playerbot_texts` SET `id`=625, `text_loc2`='T’es maudit comme un œuf mal rôti… tout cramé d’un côté.' WHERE `id`=625; +UPDATE `ai_playerbot_texts` SET `id`=626, `text_loc2`='Espèce de gringalet, de peau de hareng, de langue de bœuf séchée, de… souffle… taureau démembré, morceau de corde ! Queue d’épée, boîte à rien, tige de tailleur !' WHERE `id`=626; +UPDATE `ai_playerbot_texts` SET `id`=627, `text_loc2`='Fi ! Qu’on te jette dans la bouche pourrie de la Mort !' WHERE `id`=627; +UPDATE `ai_playerbot_texts` SET `id`=628, `text_loc2`=', t’es poissonnier, avoue !' WHERE `id`=628; +UPDATE `ai_playerbot_texts` SET `id`=629, `text_loc2`='Je vivrai assez pour te défoncer le crâne !' WHERE `id`=629; +UPDATE `ai_playerbot_texts` SET `id`=630, `text_loc2`='T’es aussi profond qu’une flaque ! , t’es bonne pour les vers, pas pour la viande !' WHERE `id`=630; +UPDATE `ai_playerbot_texts` SET `id`=631, `text_loc2`='Vermine ! Ô , espèce de noisette infernale puante !' WHERE `id`=631; +UPDATE `ai_playerbot_texts` SET `id`=632, `text_loc2`=' ! Ton baiser est aussi réconfortant qu’un glaçon pour un serpent affamé !' WHERE `id`=632; +UPDATE `ai_playerbot_texts` SET `id`=633, `text_loc2`='Je te méprise, compagnon galeux. Quoi, pauvre arnaqueur sans chemise ! Dégage, raclure moisie !' WHERE `id`=633; +UPDATE `ai_playerbot_texts` SET `id`=634, `text_loc2`='Hors de ma vue ! Tu infectes mes yeux !' WHERE `id`=634; +UPDATE `ai_playerbot_texts` SET `id`=635, `text_loc2`='HEURE DE JEU !!!!' WHERE `id`=635; +UPDATE `ai_playerbot_texts` SET `id`=636, `text_loc2`='Personne ne passera !' WHERE `id`=636; +UPDATE `ai_playerbot_texts` SET `id`=637, `text_loc2`='On est attaqués ! Hissez les voiles ! Repoussez les intrus !' WHERE `id`=637; +UPDATE `ai_playerbot_texts` SET `id`=638, `text_loc2`='Personne ne défie la Confrérie !' WHERE `id`=638; +UPDATE `ai_playerbot_texts` SET `id`=639, `text_loc2`='Imbéciles… tuez celui en robe !' WHERE `id`=639; +UPDATE `ai_playerbot_texts` SET `id`=640, `text_loc2`='Je vais offrir ton âme à Hakkar lui-même !' WHERE `id`=640; +UPDATE `ai_playerbot_texts` SET `id`=641, `text_loc2`='L’orgueil annonce la fin de ton monde ! Venez, mortels ! Affrontez la colère de la %randomfaction !' WHERE `id`=641; +UPDATE `ai_playerbot_texts` SET `id`=642, `text_loc2`='Tous mes plans menaient à CE moment !' WHERE `id`=642; +UPDATE `ai_playerbot_texts` SET `id`=643, `text_loc2`='Ahh ! Encore des agneaux pour l’abattoir !' WHERE `id`=643; +UPDATE `ai_playerbot_texts` SET `id`=644, `text_loc2`='Encore une journée, encore une glorieuse bataille !' WHERE `id`=644; +UPDATE `ai_playerbot_texts` SET `id`=645, `text_loc2`='Alors, affaires… ou plaisir ?' WHERE `id`=645; +UPDATE `ai_playerbot_texts` SET `id`=646, `text_loc2`='Vous n’êtes pas préparés !' WHERE `id`=646; +UPDATE `ai_playerbot_texts` SET `id`=647, `text_loc2`='La conquête finale de la %randomfaction a commencé ! Cette fois, aucun ne survivra !' WHERE `id`=647; +UPDATE `ai_playerbot_texts` SET `id`=648, `text_loc2`='Ta mort sera douloureuse.' WHERE `id`=648; +UPDATE `ai_playerbot_texts` SET `id`=649, `text_loc2`='Implore pitié ! Tes vies inutiles vont être sacrifiées.' WHERE `id`=649; +UPDATE `ai_playerbot_texts` SET `id`=650, `text_loc2`='Abandonne tout espoir ! La %randomfaction est revenue pour finir ce qui a commencé… et cette fois, pas d’échappatoire !' WHERE `id`=650; +UPDATE `ai_playerbot_texts` SET `id`=651, `text_loc2`='Alerte ! Tu es marqué pour l’EXTERMINATION !' WHERE `id`=651; +UPDATE `ai_playerbot_texts` SET `id`=652, `text_loc2`='Le %subzone est réservé aux invités seulement…' WHERE `id`=652; +UPDATE `ai_playerbot_texts` SET `id`=653, `text_loc2`='Ha ha ha ! Tu es totalement dépassé !' WHERE `id`=653; +UPDATE `ai_playerbot_texts` SET `id`=654, `text_loc2`='Je vais écraser tes illusions de grandeur !' WHERE `id`=654; +UPDATE `ai_playerbot_texts` SET `id`=655, `text_loc2`='Pardonne-moi, mais tu vas perdre cette partie.' WHERE `id`=655; +UPDATE `ai_playerbot_texts` SET `id`=656, `text_loc2`='Résister ne fait qu’empirer les choses.' WHERE `id`=656; +UPDATE `ai_playerbot_texts` SET `id`=657, `text_loc2`='Vermine ! Sangsues ! Prends mon sang et étouffe-toi avec !' WHERE `id`=657; +UPDATE `ai_playerbot_texts` SET `id`=658, `text_loc2`='Pas encore… PAS ENCORE !' WHERE `id`=658; +UPDATE `ai_playerbot_texts` SET `id`=659, `text_loc2`='Mon sang sera ta perte !' WHERE `id`=659; +UPDATE `ai_playerbot_texts` SET `id`=660, `text_loc2`='Parfait. Maintenant bats-toi contre moi !' WHERE `id`=660; +UPDATE `ai_playerbot_texts` SET `id`=661, `text_loc2`='Allez les gardes ! C’est l’heure de tuer !' WHERE `id`=661; +UPDATE `ai_playerbot_texts` SET `id`=662, `text_loc2`='N’attends pas la mort, viens à moi. Je rendrai ton sacrifice rapide.' WHERE `id`=662; +UPDATE `ai_playerbot_texts` SET `id`=663, `text_loc2`='Tu seras mort très bientôt !' WHERE `id`=663; +UPDATE `ai_playerbot_texts` SET `id`=664, `text_loc2`='Mouahaha !' WHERE `id`=664; +UPDATE `ai_playerbot_texts` SET `id`=665, `text_loc2`='C’est moi le prédateur ! Toi, la proie...' WHERE `id`=665; +UPDATE `ai_playerbot_texts` SET `id`=666, `text_loc2`='Tu vas repartir en morceaux !' WHERE `id`=666; +UPDATE `ai_playerbot_texts` SET `id`=667, `text_loc2`='La mort approche... As-tu la conscience tranquille ?' WHERE `id`=667; +UPDATE `ai_playerbot_texts` SET `id`=668, `text_loc2`='Ton comportement ne sera pas toléré.' WHERE `id`=668; +UPDATE `ai_playerbot_texts` SET `id`=669, `text_loc2`='La Ménagerie est réservée aux invités.' WHERE `id`=669; +UPDATE `ai_playerbot_texts` SET `id`=670, `text_loc2`='Hmm, des visiteurs non annoncés… Il faut se préparer…' WHERE `id`=670; +UPDATE `ai_playerbot_texts` SET `id`=671, `text_loc2`='Entités hostiles détectées. Évaluation de menace en cours. Cible principale verrouillée. Réévaluation dans trente secondes.' WHERE `id`=671; +UPDATE `ai_playerbot_texts` SET `id`=672, `text_loc2`='Des nouveaux jouets ? Pour moi ? Promis, je les casse pas… cette fois !' WHERE `id`=672; +UPDATE `ai_playerbot_texts` SET `id`=673, `text_loc2`='Je suis prêt à jouer !' WHERE `id`=673; +UPDATE `ai_playerbot_texts` SET `id`=674, `text_loc2`='Chut… tout sera fini bientôt.' WHERE `id`=674; +UPDATE `ai_playerbot_texts` SET `id`=675, `text_loc2`='Aaaaaughibbrgubugbugrguburgle !' WHERE `id`=675; +UPDATE `ai_playerbot_texts` SET `id`=676, `text_loc2`='RwlRwlRwlRwl !' WHERE `id`=676; +UPDATE `ai_playerbot_texts` SET `id`=677, `text_loc2`='Toi aussi, tu serviras !' WHERE `id`=677; +UPDATE `ai_playerbot_texts` SET `id`=678, `text_loc2`='Dis-moi... dis-moi tout ! Tes vilains petits secrets ! Je vais les arracher de ta chair !' WHERE `id`=678; +UPDATE `ai_playerbot_texts` SET `id`=679, `text_loc2`='Préparez-vous, les cloches ont sonné ! Protégez vos faibles, vos jeunes et vos vieux ! Chacun paiera le prix final ! Implorerez-vous pitié ? Le Jugement est arrivé !' WHERE `id`=679; +UPDATE `ai_playerbot_texts` SET `id`=680, `text_loc2`='Mais où suis-je, par les boutons en laiton de Bonzo ?' WHERE `id`=680; +UPDATE `ai_playerbot_texts` SET `id`=681, `text_loc2`='Je n’en peux plus ! Roi Gobelin ! Roi Gobelin ! Où que tu sois ! Emporte ce loin de moi !' WHERE `id`=681; +UPDATE `ai_playerbot_texts` SET `id`=682, `text_loc2`='Tu as treize heures pour résoudre le labyrinthe... sinon ton petit frère deviendra l’un des nôtres... pour toujours.' WHERE `id`=682; +UPDATE `ai_playerbot_texts` SET `id`=683, `text_loc2`='Alors, le c’est du gâteau, hein ? Voyons comment tu gères ce petit bout-là…' WHERE `id`=683; +UPDATE `ai_playerbot_texts` SET `id`=684, `text_loc2`='Recule, j’vais t’affronter. Déterminé, prêt à affronter n’importe qui. J’sais que t’as tort, t’as rien à faire ici !' WHERE `id`=684; +UPDATE `ai_playerbot_texts` SET `id`=685, `text_loc2`='Montre-moi c’que t’as dans le ventre !' WHERE `id`=685; +UPDATE `ai_playerbot_texts` SET `id`=686, `text_loc2`='Jusqu’à la mort !' WHERE `id`=686; +UPDATE `ai_playerbot_texts` SET `id`=687, `text_loc2`='Double lame, pour un rasage net à chaque fois !' WHERE `id`=687; +UPDATE `ai_playerbot_texts` SET `id`=688, `text_loc2`='Allez, viens !' WHERE `id`=688; +UPDATE `ai_playerbot_texts` SET `id`=689, `text_loc2`='Tu vas tomber !' WHERE `id`=689; +UPDATE `ai_playerbot_texts` SET `id`=690, `text_loc2`='Piou piou, coup de couteau !' WHERE `id`=690; +UPDATE `ai_playerbot_texts` SET `id`=691, `text_loc2`='Finissons-en vite, le temps c’est du mana.' WHERE `id`=691; +UPDATE `ai_playerbot_texts` SET `id`=692, `text_loc2`='Je ne crois pas que tu réalises dans quelle merde tu es.' WHERE `id`=692; +UPDATE `ai_playerbot_texts` SET `id`=693, `text_loc2`='Je vais faire honneur à ma famille et à mon royaume !' WHERE `id`=693; +UPDATE `ai_playerbot_texts` SET `id`=694, `text_loc2`='Lumière, donne-moi la force !' WHERE `id`=694; +UPDATE `ai_playerbot_texts` SET `id`=695, `text_loc2`='Mon église, c’est le champ de bataille – l’heure de la messe a sonné !' WHERE `id`=695; +UPDATE `ai_playerbot_texts` SET `id`=696, `text_loc2`='Je te tiens en mépris total…' WHERE `id`=696; +UPDATE `ai_playerbot_texts` SET `id`=697, `text_loc2`='Affronte le marteau de la justice !' WHERE `id`=697; +UPDATE `ai_playerbot_texts` SET `id`=698, `text_loc2`='Prouve ta valeur dans l’épreuve des armes, sous la Lumière !' WHERE `id`=698; +UPDATE `ai_playerbot_texts` SET `id`=699, `text_loc2`='Tous doivent tomber devant la puissance de ma cause – tu es le prochain !' WHERE `id`=699; +UPDATE `ai_playerbot_texts` SET `id`=700, `text_loc2`='Prépare-toi à mourir !' WHERE `id`=700; +UPDATE `ai_playerbot_texts` SET `id`=701, `text_loc2`='La bête en moi est bien pire que celle à mes côtés…' WHERE `id`=701; +UPDATE `ai_playerbot_texts` SET `id`=702, `text_loc2`='Admire la puissance de feu d’un chasseur totalement équipé !' WHERE `id`=702; +UPDATE `ai_playerbot_texts` SET `id`=703, `text_loc2`='Soigne-moi ! Vite !' WHERE `id`=703; +UPDATE `ai_playerbot_texts` SET `id`=704, `text_loc2`='Je suis presque mort ! Soignez-moi !' WHERE `id`=704; +UPDATE `ai_playerbot_texts` SET `id`=705, `text_loc2`='À l’aide ! Soignez-moi !' WHERE `id`=705; +UPDATE `ai_playerbot_texts` SET `id`=706, `text_loc2`='Quelqu’un ! Un soin vite !' WHERE `id`=706; +UPDATE `ai_playerbot_texts` SET `id`=707, `text_loc2`='Heal ! Heal ! Heal !' WHERE `id`=707; +UPDATE `ai_playerbot_texts` SET `id`=708, `text_loc2`='Je meurs ! Soin ! Aaaaarhg !' WHERE `id`=708; +UPDATE `ai_playerbot_texts` SET `id`=709, `text_loc2`='Soignez-moi !' WHERE `id`=709; +UPDATE `ai_playerbot_texts` SET `id`=710, `text_loc2`='Je vais mourir. Je vais mourir. Je vais mourir. Soignez-moi !' WHERE `id`=710; +UPDATE `ai_playerbot_texts` SET `id`=711, `text_loc2`='Healers, vous êtes où ? Je crève !' WHERE `id`=711; +UPDATE `ai_playerbot_texts` SET `id`=712, `text_loc2`='Ouille, la douleur ! Soignez vite !' WHERE `id`=712; +UPDATE `ai_playerbot_texts` SET `id`=713, `text_loc2`='Besoin de soin' WHERE `id`=713; +UPDATE `ai_playerbot_texts` SET `id`=714, `text_loc2`='Vie basse !' WHERE `id`=714; +UPDATE `ai_playerbot_texts` SET `id`=715, `text_loc2`='Lâche un heal. S’il te plaît.' WHERE `id`=715; +UPDATE `ai_playerbot_texts` SET `id`=716, `text_loc2`='Quelqu’un peut me balancer un soin ?' WHERE `id`=716; +UPDATE `ai_playerbot_texts` SET `id`=717, `text_loc2`='Hey ! Mieux vaut me soigner maintenant que me rez plus tard !' WHERE `id`=717; +UPDATE `ai_playerbot_texts` SET `id`=718, `text_loc2`='Désolé… mais encore un heal, please.' WHERE `id`=718; +UPDATE `ai_playerbot_texts` SET `id`=719, `text_loc2`='Saletés de mobs… heal moi vite !' WHERE `id`=719; +UPDATE `ai_playerbot_texts` SET `id`=720, `text_loc2`='Encore un coup et je suis mort. Un petit heal ?' WHERE `id`=720; +UPDATE `ai_playerbot_texts` SET `id`=721, `text_loc2`='Y’a des soigneurs dans cette galère ?' WHERE `id`=721; +UPDATE `ai_playerbot_texts` SET `id`=722, `text_loc2`='Pourquoi c’est toujours ma tête qu’ils frappent ? J’ai besoin d’un soin !' WHERE `id`=722; +UPDATE `ai_playerbot_texts` SET `id`=723, `text_loc2`='Quelqu’un pour me soigner un chouïa ?' WHERE `id`=723; +UPDATE `ai_playerbot_texts` SET `id`=724, `text_loc2`='OOM' WHERE `id`=724; +UPDATE `ai_playerbot_texts` SET `id`=725, `text_loc2`='Plus de mana !' WHERE `id`=725; +UPDATE `ai_playerbot_texts` SET `id`=726, `text_loc2`='J’ai cramé tout mon mana pour ça, sérieux...' WHERE `id`=726; +UPDATE `ai_playerbot_texts` SET `id`=727, `text_loc2`='Faudrait attendre que je boive ou que je régène, là…' WHERE `id`=727; +UPDATE `ai_playerbot_texts` SET `id`=728, `text_loc2`='Mana faible… très faible…' WHERE `id`=728; +UPDATE `ai_playerbot_texts` SET `id`=729, `text_loc2`='Encore à sec ? Pas de mana, encore.' WHERE `id`=729; +UPDATE `ai_playerbot_texts` SET `id`=730, `text_loc2`='Mana bas. Je veux une boisson !' WHERE `id`=730; +UPDATE `ai_playerbot_texts` SET `id`=731, `text_loc2`='On a une machine à boissons ? J’ai encore plus rien !' WHERE `id`=731; +UPDATE `ai_playerbot_texts` SET `id`=732, `text_loc2`='Mon mana ? Parti dans les limbes.' WHERE `id`=732; +UPDATE `ai_playerbot_texts` SET `id`=733, `text_loc2`='J’achèterai des boissons la prochaine fois. Là j’ai que dalle.' WHERE `id`=733; +UPDATE `ai_playerbot_texts` SET `id`=734, `text_loc2`='Où est passé mon mana ?' WHERE `id`=734; +UPDATE `ai_playerbot_texts` SET `id`=735, `text_loc2`='Il me reste quelques !' WHERE `id`=735; +UPDATE `ai_playerbot_texts` SET `id`=736, `text_loc2`='Besoin de plus de !' WHERE `id`=736; +UPDATE `ai_playerbot_texts` SET `id`=737, `text_loc2`='Plus que 100 !' WHERE `id`=737; +UPDATE `ai_playerbot_texts` SET `id`=738, `text_loc2`='C’est fini ! Plus un seul !' WHERE `id`=738; +UPDATE `ai_playerbot_texts` SET `id`=739, `text_loc2`='Et tu as mon arc… oups, plus de !' WHERE `id`=739; +UPDATE `ai_playerbot_texts` SET `id`=740, `text_loc2`='J’ai besoin de munitions !' WHERE `id`=740; +UPDATE `ai_playerbot_texts` SET `id`=741, `text_loc2`='Oh mon dieu !' WHERE `id`=741; +UPDATE `ai_playerbot_texts` SET `id`=742, `text_loc2`='J’ai peur… là… vraiment.' WHERE `id`=742; +UPDATE `ai_playerbot_texts` SET `id`=743, `text_loc2`='On est foutus !' WHERE `id`=743; +UPDATE `ai_playerbot_texts` SET `id`=744, `text_loc2`='C’est fini. F.I.N.I.' WHERE `id`=744; +UPDATE `ai_playerbot_texts` SET `id`=745, `text_loc2`='Ça se termine maintenant.' WHERE `id`=745; +UPDATE `ai_playerbot_texts` SET `id`=746, `text_loc2`='Quelqu’un peut balancer un blizzard ou un truc ?!' WHERE `id`=746; +UPDATE `ai_playerbot_texts` SET `id`=747, `text_loc2`='Mince. Le tank a aggro TOUT le monde…' WHERE `id`=747; +UPDATE `ai_playerbot_texts` SET `id`=748, `text_loc2`='On va mourir. On va mourir. On VA MOURIR !' WHERE `id`=748; +UPDATE `ai_playerbot_texts` SET `id`=749, `text_loc2`='Wow ! Tant de jouets à casser !' WHERE `id`=749; +UPDATE `ai_playerbot_texts` SET `id`=750, `text_loc2`='Je vais tous les buter ! TOUS !' WHERE `id`=750; +UPDATE `ai_playerbot_texts` SET `id`=751, `text_loc2`='Si le tank meurt, c’est foutu pour nous tous…' WHERE `id`=751; +UPDATE `ai_playerbot_texts` SET `id`=752, `text_loc2`='Aaaaaargh !' WHERE `id`=752; +UPDATE `ai_playerbot_texts` SET `id`=753, `text_loc2`='LEEEEERROOOYYYYYYYYYYYY JENNKINNNSSSSSS !!!!!!!!' WHERE `id`=753; +UPDATE `ai_playerbot_texts` SET `id`=754, `text_loc2`='Bon. Qu’est-ce qu’on a en AOE là ?' WHERE `id`=754; +UPDATE `ai_playerbot_texts` SET `id`=755, `text_loc2`='Ça devient intéressant…' WHERE `id`=755; +UPDATE `ai_playerbot_texts` SET `id`=756, `text_loc2`='Cool. Regroupez-les bien pour une jolie boule de feu !' WHERE `id`=756; +UPDATE `ai_playerbot_texts` SET `id`=757, `text_loc2`='TUEZ ! TUEZ ! TUEZ !' WHERE `id`=757; +UPDATE `ai_playerbot_texts` SET `id`=758, `text_loc2`='Je crois que j’ai mouillé mon pantalon…' WHERE `id`=758; +UPDATE `ai_playerbot_texts` SET `id`=759, `text_loc2`='C’est notre fin. C’était sympa.' WHERE `id`=759; +UPDATE `ai_playerbot_texts` SET `id`=760, `text_loc2`='J’espère que les healers sont prêts… LEEEEROYYYY !' WHERE `id`=760; +UPDATE `ai_playerbot_texts` SET `id`=761, `text_loc2`='Pourvu qu’ils ne me ciblent pas moi…' WHERE `id`=761; +UPDATE `ai_playerbot_texts` SET `id`=762, `text_loc2`='Oh non. Je peux pas regarder ce massacre…' WHERE `id`=762; +UPDATE `ai_playerbot_texts` SET `id`=763, `text_loc2`='J’espère qu’il y aura de la thune.' WHERE `id`=763; +UPDATE `ai_playerbot_texts` SET `id`=764, `text_loc2`='Loot ! LOOT !' WHERE `id`=764; +UPDATE `ai_playerbot_texts` SET `id`=765, `text_loc2`='Mon précieux…' WHERE `id`=765; +UPDATE `ai_playerbot_texts` SET `id`=766, `text_loc2`='J’espère qu’un bel objet épique m’attend là-dedans…' WHERE `id`=766; +UPDATE `ai_playerbot_texts` SET `id`=767, `text_loc2`='J’ai des poches profondes et des sacs encore vides.' WHERE `id`=767; +UPDATE `ai_playerbot_texts` SET `id`=768, `text_loc2`='Tout est à moi !' WHERE `id`=768; +UPDATE `ai_playerbot_texts` SET `id`=769, `text_loc2`='Pas de gris moisi aujourd’hui, pitié…' WHERE `id`=769; +UPDATE `ai_playerbot_texts` SET `id`=770, `text_loc2`='CE loot est À MOI !' WHERE `id`=770; +UPDATE `ai_playerbot_texts` SET `id`=771, `text_loc2`='Looter c’est sale… mais j’ai besoin de thunes.' WHERE `id`=771; +UPDATE `ai_playerbot_texts` SET `id`=772, `text_loc2`='De l’or !' WHERE `id`=772; +UPDATE `ai_playerbot_texts` SET `id`=773, `text_loc2`='Ok. Voyons ce qu’ils ont laissé…' WHERE `id`=773; +UPDATE `ai_playerbot_texts` SET `id`=774, `text_loc2`='T’inquiète, je vais tout looter. Tout.' WHERE `id`=774; +UPDATE `ai_playerbot_texts` SET `id`=775, `text_loc2`='Je suis un ninja du loot.' WHERE `id`=775; +UPDATE `ai_playerbot_texts` SET `id`=776, `text_loc2`='Je dois lancer les dés ?' WHERE `id`=776; +UPDATE `ai_playerbot_texts` SET `id`=777, `text_loc2`='Quelqu’un peut m’expliquer où ils ont rangé tout ça ?' WHERE `id`=777; +UPDATE `ai_playerbot_texts` SET `id`=778, `text_loc2`='Non, je loot pas cette merde grise.' WHERE `id`=778; +UPDATE `ai_playerbot_texts` SET `id`=779, `text_loc2`='C’est moi d’abord ! C’est moi ! MOI !' WHERE `id`=779; +UPDATE `ai_playerbot_texts` SET `id`=780, `text_loc2`='Donne-moi ton fric !' WHERE `id`=780; +UPDATE `ai_playerbot_texts` SET `id`=781, `text_loc2`='Mes poches sont vides, il faut les remplir.' WHERE `id`=781; +UPDATE `ai_playerbot_texts` SET `id`=782, `text_loc2`='J’ai un nouveau sac, il est fait pour ça.' WHERE `id`=782; +UPDATE `ai_playerbot_texts` SET `id`=783, `text_loc2`='J’espère que je vais pas aggro en lootant…' WHERE `id`=783; +UPDATE `ai_playerbot_texts` SET `id`=784, `text_loc2`='Ne regardez pas… je loot discret…' WHERE `id`=784; +UPDATE `ai_playerbot_texts` SET `id`=785, `text_loc2`='Ha ! Vous n’aurez rien de tout ça !' WHERE `id`=785; +UPDATE `ai_playerbot_texts` SET `id`=786, `text_loc2`='Le loot, c’est stylé.' WHERE `id`=786; +UPDATE `ai_playerbot_texts` SET `id`=787, `text_loc2`='J’adore les nouveaux équipements.' WHERE `id`=787; +UPDATE `ai_playerbot_texts` SET `id`=788, `text_loc2`='Je me casse si y’a encore rien de valeur…' WHERE `id`=788; +UPDATE `ai_playerbot_texts` SET `id`=789, `text_loc2`='J’espère que ce sera une jolie bague !' WHERE `id`=789; +UPDATE `ai_playerbot_texts` SET `id`=790, `text_loc2`='Je vais t’arracher le loot des mains !' WHERE `id`=790; +UPDATE `ai_playerbot_texts` SET `id`=791, `text_loc2`='Personne ne touche à rien. C’est MOI qui loot.' WHERE `id`=791; +UPDATE `ai_playerbot_texts` SET `id`=792, `text_loc2`='Loot sucré :D' WHERE `id`=792; +UPDATE `ai_playerbot_texts` SET `id`=793, `text_loc2`='Dieu du lancer, donne-moi un épique aujourd’hui…' WHERE `id`=793; +UPDATE `ai_playerbot_texts` SET `id`=794, `text_loc2`='Allez, de nouveaux jouets s’il vous plaît !' WHERE `id`=794; +UPDATE `ai_playerbot_texts` SET `id`=795, `text_loc2`='J’espère qu’ils ont des trucs savoureux…' WHERE `id`=795; +UPDATE `ai_playerbot_texts` SET `id`=796, `text_loc2`='L’or est à moi. Je laisse tout le reste… promis…' WHERE `id`=796; +UPDATE `ai_playerbot_texts` SET `id`=797, `text_loc2`='Non, je peux pas résister.' WHERE `id`=797; +UPDATE `ai_playerbot_texts` SET `id`=798, `text_loc2`='J’en veux ENCORE !' WHERE `id`=798; +UPDATE `ai_playerbot_texts` SET `id`=799, `text_loc2`='Je suis presque là, attendez-moi !' WHERE `id`=799; +UPDATE `ai_playerbot_texts` SET `id`=800, `text_loc2`='Je suis pas loin, attendez-moi !' WHERE `id`=800; +UPDATE `ai_playerbot_texts` SET `id`=801, `text_loc2`='J’arrive vers ta position' WHERE `id`=801; +UPDATE `ai_playerbot_texts` SET `id`=802, `text_loc2`='J’arrive vers toi' WHERE `id`=802; +UPDATE `ai_playerbot_texts` SET `id`=803, `text_loc2`='Je me dirige vers ta position' WHERE `id`=803; +UPDATE `ai_playerbot_texts` SET `id`=804, `text_loc2`='J’essaie de te rejoindre' WHERE `id`=804; +UPDATE `ai_playerbot_texts` SET `id`=805, `text_loc2`='Équipement de %item' WHERE `id`=805; +UPDATE `ai_playerbot_texts` SET `id`=806, `text_loc2`='%item retiré' WHERE `id`=806; +UPDATE `ai_playerbot_texts` SET `id`=807, `text_loc2`='J’ai appris les sorts : %spells' WHERE `id`=807; +UPDATE `ai_playerbot_texts` SET `id`=808, `text_loc2`='%item est en recharge' WHERE `id`=808; +UPDATE `ai_playerbot_texts` SET `id`=809, `text_loc2`='Je n’ai pas %item dans mon inventaire' WHERE `id`=809; +UPDATE `ai_playerbot_texts` SET `id`=810, `text_loc2`='L’objet avec l’ID %item n’existe pas' WHERE `id`=810; +UPDATE `ai_playerbot_texts` SET `id`=811, `text_loc2`='Insertion de %gem dans %item' WHERE `id`=811; +UPDATE `ai_playerbot_texts` SET `id`=812, `text_loc2`='Je ne peux pas utiliser %item' WHERE `id`=812; +UPDATE `ai_playerbot_texts` SET `id`=813, `text_loc2`='Suivi' WHERE `id`=813; +UPDATE `ai_playerbot_texts` SET `id`=814, `text_loc2`='Je reste ici' WHERE `id`=814; +UPDATE `ai_playerbot_texts` SET `id`=815, `text_loc2`='Je fuis' WHERE `id`=815; +UPDATE `ai_playerbot_texts` SET `id`=816, `text_loc2`='Je fuis pas avec toi, t’es trop loin !' WHERE `id`=816; +UPDATE `ai_playerbot_texts` SET `id`=817, `text_loc2`='Farm en cours' WHERE `id`=817; +UPDATE `ai_playerbot_texts` SET `id`=818, `text_loc2`='Attaque en cours' WHERE `id`=818; +UPDATE `ai_playerbot_texts` SET `id`=819, `text_loc2`='C’est trop loin' WHERE `id`=819; +UPDATE `ai_playerbot_texts` SET `id`=820, `text_loc2`='C’est sous l’eau' WHERE `id`=820; +UPDATE `ai_playerbot_texts` SET `id`=821, `text_loc2`='Je ne peux pas y aller' WHERE `id`=821; +UPDATE `ai_playerbot_texts` SET `id`=822, `text_loc2`='Je ne suis pas dans ta guilde !' WHERE `id`=822; +UPDATE `ai_playerbot_texts` SET `id`=823, `text_loc2`='Impossible de trouver une banque de guilde à proximité' WHERE `id`=823; +UPDATE `ai_playerbot_texts` SET `id`=824, `text_loc2`='Je ne peux pas déposer' WHERE `id`=824; +UPDATE `ai_playerbot_texts` SET `id`=825, `text_loc2`='Je n’ai pas les droits pour déposer dans le premier onglet de la banque de guilde' WHERE `id`=825; +UPDATE `ai_playerbot_texts` SET `id`=826, `text_loc2`='déposé dans la banque de guilde' WHERE `id`=826; +UPDATE `ai_playerbot_texts` SET `id`=827, `text_loc2`='Déplacement libre' WHERE `id`=827; +UPDATE `ai_playerbot_texts` SET `id`=828, `text_loc2`='En garde' WHERE `id`=828; +UPDATE `ai_playerbot_texts` SET `id`=829, `text_loc2`='Utilisation de %target' WHERE `id`=829; +UPDATE `ai_playerbot_texts` SET `id`=830, `text_loc2`='sur %unit' WHERE `id`=830; +UPDATE `ai_playerbot_texts` SET `id`=831, `text_loc2`='(%amount disponible)' WHERE `id`=831; +UPDATE `ai_playerbot_texts` SET `id`=832, `text_loc2`='(le dernier)' WHERE `id`=832; +UPDATE `ai_playerbot_texts` SET `id`=833, `text_loc2`='La châsse ne correspond pas' WHERE `id`=833; +UPDATE `ai_playerbot_texts` SET `id`=834, `text_loc2`='sur objet d’échange' WHERE `id`=834; +UPDATE `ai_playerbot_texts` SET `id`=835, `text_loc2`='sur moi-même' WHERE `id`=835; +UPDATE `ai_playerbot_texts` SET `id`=836, `text_loc2`='sur %item' WHERE `id`=836; +UPDATE `ai_playerbot_texts` SET `id`=837, `text_loc2`='sur %gameobject' WHERE `id`=837; +UPDATE `ai_playerbot_texts` SET `id`=838, `text_loc2`='Loot de %item' WHERE `id`=838; +UPDATE `ai_playerbot_texts` SET `id`=839, `text_loc2`='Invocation de %target' WHERE `id`=839; +UPDATE `ai_playerbot_texts` SET `id`=840, `text_loc2`='Je n’ai pas assez de membres du groupe à proximité pour invoquer' WHERE `id`=840; +UPDATE `ai_playerbot_texts` SET `id`=841, `text_loc2`='Impossible de trouver la cible d’invocation' WHERE `id`=841; +UPDATE `ai_playerbot_texts` SET `id`=842, `text_loc2`='Je ne peux pas invoquer en combat' WHERE `id`=842; +UPDATE `ai_playerbot_texts` SET `id`=843, `text_loc2`='Je ne connais pas le sort %spell' WHERE `id`=843; +UPDATE `ai_playerbot_texts` SET `id`=844, `text_loc2`='Lancement du sort %spell' WHERE `id`=844; +UPDATE `ai_playerbot_texts` SET `id`=845, `text_loc2`='Fabrication de %spell' WHERE `id`=845; +UPDATE `ai_playerbot_texts` SET `id`=846, `text_loc2`='Impossible de lancer %spell' WHERE `id`=846; +UPDATE `ai_playerbot_texts` SET `id`=847, `text_loc2`='Échec du lancement de %spell' WHERE `id`=847; +UPDATE `ai_playerbot_texts` SET `id`=848, `text_loc2`='|cffffff00(x%amount restant)|r' WHERE `id`=848; +UPDATE `ai_playerbot_texts` SET `id`=849, `text_loc2`='dummy' WHERE `id`=849; +UPDATE `ai_playerbot_texts` SET `id`=934, `text_loc2`='Par la Lumière... J\'ai oublié mes Symboles du roi. On se contentera de %base_spell !' WHERE `id`=934; +UPDATE `ai_playerbot_texts` SET `id`=935, `text_loc2`='La nature est généreuse, pas mes sacs... plus d\'herbes pour %group_spell. Prenez %base_spell pour l\'instant !' WHERE `id`=935; +UPDATE `ai_playerbot_texts` SET `id`=936, `text_loc2`='Plus de poudre des arcanes... %group_spell attendra. Je lance %base_spell !' WHERE `id`=936; +UPDATE `ai_playerbot_texts` SET `id`=937, `text_loc2`='Oups, je n\'ai plus de composants pour %group_spell. On fera avec %base_spell !' WHERE `id`=937; From 16bb0f10d93681b129b184cff5d38c05ab6c2b4e Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:16:02 +0200 Subject: [PATCH 09/32] Update 2025_09_18_00_ai_playerbot_french_texts.sql 1:1 translation --- ...025_09_18_00_ai_playerbot_french_texts.sql | 1707 +++++++++-------- 1 file changed, 854 insertions(+), 853 deletions(-) diff --git a/data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql b/data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql index 490c6fec97..55f57c50eb 100644 --- a/data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql +++ b/data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql @@ -1,855 +1,856 @@ UPDATE ai_playerbot_texts SET text_loc2 = ''; -UPDATE `ai_playerbot_texts` SET `id`=1, `text_loc2`='au milieu de nulle part' WHERE `id`=1; -UPDATE `ai_playerbot_texts` SET `id`=2, `text_loc2`='un endroit non divulgué' WHERE `id`=2; -UPDATE `ai_playerbot_texts` SET `id`=3, `text_loc2`='quelque part' WHERE `id`=3; -UPDATE `ai_playerbot_texts` SET `id`=4, `text_loc2`='un truc' WHERE `id`=4; -UPDATE `ai_playerbot_texts` SET `id`=5, `text_loc2`='je me demande quel goût a %item_link' WHERE `id`=5; -UPDATE `ai_playerbot_texts` SET `id`=6, `text_loc2`='noooon, j’ai eu %item_link' WHERE `id`=6; -UPDATE `ai_playerbot_texts` SET `id`=7, `text_loc2`='oh non, encore cette camelote %item_link' WHERE `id`=7; -UPDATE `ai_playerbot_texts` SET `id`=8, `text_loc2`='on dirait que je ramasse des ordures %item_link' WHERE `id`=8; -UPDATE `ai_playerbot_texts` SET `id`=9, `text_loc2`='bon, c’est mieux que rien je suppose %item_link' WHERE `id`=9; -UPDATE `ai_playerbot_texts` SET `id`=10, `text_loc2`='je ne sais pas quoi faire de %item_link' WHERE `id`=10; -UPDATE `ai_playerbot_texts` SET `id`=11, `text_loc2`='je me demande quel goût a %item_link' WHERE `id`=11; -UPDATE `ai_playerbot_texts` SET `id`=12, `text_loc2`='je pourrais ramasser du %item_link toute la journée' WHERE `id`=12; -UPDATE `ai_playerbot_texts` SET `id`=13, `text_loc2`='un jour de plus, un %item_link de plus' WHERE `id`=13; -UPDATE `ai_playerbot_texts` SET `id`=14, `text_loc2`='j’ai ramassé un peu de %item_link' WHERE `id`=14; -UPDATE `ai_playerbot_texts` SET `id`=15, `text_loc2`='un peu de %item_link, c’est toujours ça' WHERE `id`=15; -UPDATE `ai_playerbot_texts` SET `id`=16, `text_loc2`='pas mal, je viens de choper %item_link' WHERE `id`=16; -UPDATE `ai_playerbot_texts` SET `id`=17, `text_loc2`='je viens de ramasser %item_link à %zone_name' WHERE `id`=17; -UPDATE `ai_playerbot_texts` SET `id`=18, `text_loc2`='je pourrais bien l’utiliser ça %item_link' WHERE `id`=18; -UPDATE `ai_playerbot_texts` SET `id`=19, `text_loc2`='l’argent, l’argent, et encore %item_link' WHERE `id`=19; -UPDATE `ai_playerbot_texts` SET `id`=20, `text_loc2`='j’ai eu %item_link' WHERE `id`=20; -UPDATE `ai_playerbot_texts` SET `id`=21, `text_loc2`='%item_link est BiS pour les chasseurs' WHERE `id`=21; -UPDATE `ai_playerbot_texts` SET `id`=22, `text_loc2`='%item_link est BiS pour les %my_class' WHERE `id`=22; -UPDATE `ai_playerbot_texts` SET `id`=23, `text_loc2`='la chance est avec moi aujourd’hui %item_link' WHERE `id`=23; -UPDATE `ai_playerbot_texts` SET `id`=24, `text_loc2`='trop bon %item_link, fraîchement looté' WHERE `id`=24; -UPDATE `ai_playerbot_texts` SET `id`=25, `text_loc2`='wow, je viens de choper %item_link' WHERE `id`=25; -UPDATE `ai_playerbot_texts` SET `id`=26, `text_loc2`='%item_link est BiS pour les chasseurs' WHERE `id`=26; -UPDATE `ai_playerbot_texts` SET `id`=27, `text_loc2`='%item_link est BiS pour les %my_class' WHERE `id`=27; -UPDATE `ai_playerbot_texts` SET `id`=28, `text_loc2`='la chance est avec moi aujourd’hui %item_link' WHERE `id`=28; -UPDATE `ai_playerbot_texts` SET `id`=29, `text_loc2`='trop bon %item_link, fraîchement looté' WHERE `id`=29; -UPDATE `ai_playerbot_texts` SET `id`=30, `text_loc2`='OMG, regardez ce que je viens de looter %item_link !!!' WHERE `id`=30; -UPDATE `ai_playerbot_texts` SET `id`=31, `text_loc2`='Noooon ! C’est pas possible, j’ai eu %item_link, c’est de la folie' WHERE `id`=31; -UPDATE `ai_playerbot_texts` SET `id`=32, `text_loc2`='Noooon ! C’est pas possible, j’ai eu %item_link, c’est de la folie' WHERE `id`=32; -UPDATE `ai_playerbot_texts` SET `id`=33, `text_loc2`='je viens juste de prendre la quête %quest_link' WHERE `id`=33; -UPDATE `ai_playerbot_texts` SET `id`=34, `text_loc2`='je viens d’accepter %quest_link' WHERE `id`=34; -UPDATE `ai_playerbot_texts` SET `id`=35, `text_loc2`='%quest_link je vais essayer de la finir' WHERE `id`=35; -UPDATE `ai_playerbot_texts` SET `id`=36, `text_loc2`='j’ai pris %quest_link à %zone_name' WHERE `id`=36; -UPDATE `ai_playerbot_texts` SET `id`=37, `text_loc2`='Enfin fini l’objectif %quest_obj_name pour %quest_link' WHERE `id`=37; -UPDATE `ai_playerbot_texts` SET `id`=38, `text_loc2`='j’ai enfin %quest_obj_available/%quest_obj_required de %quest_obj_name pour %quest_link' WHERE `id`=38; -UPDATE `ai_playerbot_texts` SET `id`=39, `text_loc2`='%quest_obj_full_formatted pour %quest_link, enfin !' WHERE `id`=39; -UPDATE `ai_playerbot_texts` SET `id`=40, `text_loc2`='Oof, j’ai %quest_obj_available/%quest_obj_required %quest_obj_name pour %quest_link' WHERE `id`=40; -UPDATE `ai_playerbot_texts` SET `id`=41, `text_loc2`='il me manque encore %quest_obj_missing de %quest_obj_name pour %quest_link' WHERE `id`=41; -UPDATE `ai_playerbot_texts` SET `id`=42, `text_loc2`='%quest_obj_full_formatted, je bosse toujours sur %quest_link' WHERE `id`=42; -UPDATE `ai_playerbot_texts` SET `id`=43, `text_loc2`='Enfin fini avec %item_link pour %quest_link' WHERE `id`=43; -UPDATE `ai_playerbot_texts` SET `id`=44, `text_loc2`='j’ai enfin %quest_obj_available/%quest_obj_required de %item_link pour %quest_link' WHERE `id`=44; -UPDATE `ai_playerbot_texts` SET `id`=45, `text_loc2`='%quest_obj_full_formatted pour %quest_link, enfin !' WHERE `id`=45; -UPDATE `ai_playerbot_texts` SET `id`=46, `text_loc2`='Oof, j’ai %quest_obj_available/%quest_obj_required %item_link pour %quest_link' WHERE `id`=46; -UPDATE `ai_playerbot_texts` SET `id`=47, `text_loc2`='il me manque encore %quest_obj_missing de %item_link pour %quest_link' WHERE `id`=47; -UPDATE `ai_playerbot_texts` SET `id`=48, `text_loc2`='%quest_obj_full_formatted, je suis encore sur %quest_link' WHERE `id`=48; -UPDATE `ai_playerbot_texts` SET `id`=49, `text_loc2`='Échec : je n’ai pas fini %quest_link à temps...' WHERE `id`=49; -UPDATE `ai_playerbot_texts` SET `id`=50, `text_loc2`='Plus de temps pour %quest_link :(' WHERE `id`=50; -UPDATE `ai_playerbot_texts` SET `id`=51, `text_loc2`='J’ai terminé tous les objectifs de %quest_link' WHERE `id`=51; -UPDATE `ai_playerbot_texts` SET `id`=52, `text_loc2`='Objectifs terminés pour %quest_link' WHERE `id`=52; -UPDATE `ai_playerbot_texts` SET `id`=53, `text_loc2`='Je vais rendre %quest_link bientôt, tout est fait' WHERE `id`=53; -UPDATE `ai_playerbot_texts` SET `id`=54, `text_loc2`='Ouiii, j’ai enfin rendu %quest_link' WHERE `id`=54; -UPDATE `ai_playerbot_texts` SET `id`=55, `text_loc2`='%quest_link rendu' WHERE `id`=55; -UPDATE `ai_playerbot_texts` SET `id`=56, `text_loc2`='Mission %quest_link terminée, rendu !' WHERE `id`=56; -UPDATE `ai_playerbot_texts` SET `id`=57, `text_loc2`='%quest_link rendu' WHERE `id`=57; -UPDATE `ai_playerbot_texts` SET `id`=58, `text_loc2`='%quest_link rendu à %zone_name' WHERE `id`=58; -UPDATE `ai_playerbot_texts` SET `id`=59, `text_loc2`='encore un %victim_name à terre' WHERE `id`=59; -UPDATE `ai_playerbot_texts` SET `id`=60, `text_loc2`='je continue à tuer %victim_name, banalité' WHERE `id`=60; -UPDATE `ai_playerbot_texts` SET `id`=61, `text_loc2`='un autre %victim_name mord la poussière' WHERE `id`=61; -UPDATE `ai_playerbot_texts` SET `id`=62, `text_loc2`='un %victim_name en moins à %zone_name' WHERE `id`=62; -UPDATE `ai_playerbot_texts` SET `id`=63, `text_loc2`='J’ai descendu ce sale élite %victim_name !' WHERE `id`=63; -UPDATE `ai_playerbot_texts` SET `id`=64, `text_loc2`='élite %victim_name éliminé à %zone_name' WHERE `id`=64; -UPDATE `ai_playerbot_texts` SET `id`=65, `text_loc2`='Ouf, j’ai réussi à abattre %victim_name !' WHERE `id`=65; -UPDATE `ai_playerbot_texts` SET `id`=66, `text_loc2`='C’était épique ! %victim_name est tombé, j’ai une histoire à raconter' WHERE `id`=66; -UPDATE `ai_playerbot_texts` SET `id`=67, `text_loc2`='Yoo, je viens de tuer %victim_name !' WHERE `id`=67; -UPDATE `ai_playerbot_texts` SET `id`=68, `text_loc2`='rare %victim_name éliminé à %zone_name' WHERE `id`=68; -UPDATE `ai_playerbot_texts` SET `id`=69, `text_loc2`='Mais qu’est-ce que j’ai tué là ? %victim_name' WHERE `id`=69; -UPDATE `ai_playerbot_texts` SET `id`=70, `text_loc2`='J’ai tué cette bestiole %victim_name' WHERE `id`=70; -UPDATE `ai_playerbot_texts` SET `id`=71, `text_loc2`='Oh ouiii, j’ai tué %victim_name' WHERE `id`=71; -UPDATE `ai_playerbot_texts` SET `id`=72, `text_loc2`='%victim_name éliminé à %zone_name' WHERE `id`=72; -UPDATE `ai_playerbot_texts` SET `id`=73, `text_loc2`='Ding !' WHERE `id`=73; -UPDATE `ai_playerbot_texts` SET `id`=74, `text_loc2`='Ouiii, je suis niveau %my_level !' WHERE `id`=74; -UPDATE `ai_playerbot_texts` SET `id`=75, `text_loc2`='Je viens de passer un niveau' WHERE `id`=75; -UPDATE `ai_playerbot_texts` SET `id`=76, `text_loc2`='Je suis niveau %my_level !!!' WHERE `id`=76; -UPDATE `ai_playerbot_texts` SET `id`=77, `text_loc2`='Je deviens plus fort, déjà %my_level !!!' WHERE `id`=77; -UPDATE `ai_playerbot_texts` SET `id`=78, `text_loc2`='Je viens d’atteindre le niveau %my_level !!!' WHERE `id`=78; -UPDATE `ai_playerbot_texts` SET `id`=79, `text_loc2`='OMG, enfin niveau %my_level !!!' WHERE `id`=79; -UPDATE `ai_playerbot_texts` SET `id`=80, `text_loc2`='%my_level !!! prêt pour le contenu endgame' WHERE `id`=80; -UPDATE `ai_playerbot_texts` SET `id`=81, `text_loc2`='tout frais, nouveau %my_level %my_class !!!' WHERE `id`=81; -UPDATE `ai_playerbot_texts` SET `id`=82, `text_loc2`='encore un niveau %my_level %my_race %my_class !' WHERE `id`=82; -UPDATE `ai_playerbot_texts` SET `id`=83, `text_loc2`='Bien joué %other_name. Tu l’as mérité.' WHERE `id`=83; -UPDATE `ai_playerbot_texts` SET `id`=84, `text_loc2`='C’était affreux %other_name. J’ai détesté faire ça mais...' WHERE `id`=84; -UPDATE `ai_playerbot_texts` SET `id`=85, `text_loc2`='Quelqu’un veut faire %instance_name ?' WHERE `id`=85; -UPDATE `ai_playerbot_texts` SET `id`=86, `text_loc2`='Des groupes pour %instance_name ?' WHERE `id`=86; -UPDATE `ai_playerbot_texts` SET `id`=87, `text_loc2`='Besoin d’aide pour %instance_name ?' WHERE `id`=87; -UPDATE `ai_playerbot_texts` SET `id`=88, `text_loc2`='LFD : %instance_name.' WHERE `id`=88; -UPDATE `ai_playerbot_texts` SET `id`=89, `text_loc2`='Quelqu’un a besoin d’un %my_role pour %instance_name ?' WHERE `id`=89; -UPDATE `ai_playerbot_texts` SET `id`=90, `text_loc2`='Il manque un %my_role pour %instance_name ?' WHERE `id`=90; -UPDATE `ai_playerbot_texts` SET `id`=91, `text_loc2`='Je peux être %my_role pour %instance_name.' WHERE `id`=91; -UPDATE `ai_playerbot_texts` SET `id`=92, `text_loc2`='Besoin d’un coup de main à %instance_name ?' WHERE `id`=92; -UPDATE `ai_playerbot_texts` SET `id`=93, `text_loc2`='Besoin d’un %my_role pour %instance_name ?' WHERE `id`=93; -UPDATE `ai_playerbot_texts` SET `id`=94, `text_loc2`='Quelqu’un a besoin de loot à %instance_name ?' WHERE `id`=94; -UPDATE `ai_playerbot_texts` SET `id`=95, `text_loc2`='Un petit farm à %instance_name ?' WHERE `id`=95; -UPDATE `ai_playerbot_texts` SET `id`=96, `text_loc2`='WTR %instance_name' WHERE `id`=96; -UPDATE `ai_playerbot_texts` SET `id`=97, `text_loc2`='Besoin d’aide pour %instance_name.' WHERE `id`=97; -UPDATE `ai_playerbot_texts` SET `id`=98, `text_loc2`='Envie de faire %instance_name.' WHERE `id`=98; -UPDATE `ai_playerbot_texts` SET `id`=99, `text_loc2`='%my_role cherche un groupe pour %instance_name.' WHERE `id`=99; -UPDATE `ai_playerbot_texts` SET `id`=100, `text_loc2`='Et %instance_name, on y va ?' WHERE `id`=100; -UPDATE `ai_playerbot_texts` SET `id`=101, `text_loc2`='Qui veut farmer %instance_name ?' WHERE `id`=101; -UPDATE `ai_playerbot_texts` SET `id`=102, `text_loc2`='On entre dans %instance_name ?' WHERE `id`=102; -UPDATE `ai_playerbot_texts` SET `id`=103, `text_loc2`='Je cherche groupe pour %instance_name.' WHERE `id`=103; -UPDATE `ai_playerbot_texts` SET `id`=104, `text_loc2`='Des quêtes à %instance_name ?' WHERE `id`=104; -UPDATE `ai_playerbot_texts` SET `id`=105, `text_loc2`='Envie de faire des quêtes à %instance_name.' WHERE `id`=105; -UPDATE `ai_playerbot_texts` SET `id`=106, `text_loc2`='Quelqu’un avec des quêtes à %instance_name ?' WHERE `id`=106; -UPDATE `ai_playerbot_texts` SET `id`=107, `text_loc2`='Je peux aider pour les quêtes à %instance_name.' WHERE `id`=107; -UPDATE `ai_playerbot_texts` SET `id`=108, `text_loc2`='%my_role : une place dispo pour %instance_name ?' WHERE `id`=108; -UPDATE `ai_playerbot_texts` SET `id`=109, `text_loc2`='Est-ce que quelqu’un fait encore %instance_name de nos jours ?' WHERE `id`=109; -UPDATE `ai_playerbot_texts` SET `id`=110, `text_loc2`='%instance_name : quelqu’un cherche un %my_role ?' WHERE `id`=110; -UPDATE `ai_playerbot_texts` SET `id`=111, `text_loc2`='Ça sert encore à quelque chose d’être %my_role à %instance_name ?' WHERE `id`=111; -UPDATE `ai_playerbot_texts` SET `id`=112, `text_loc2`='Ça vaut vraiment le coup d’aller à %instance_name ?' WHERE `id`=112; -UPDATE `ai_playerbot_texts` SET `id`=113, `text_loc2`='Quelqu’un a besoin de plus de joueurs pour %instance_name ?' WHERE `id`=113; -UPDATE `ai_playerbot_texts` SET `id`=114, `text_loc2`='Les boss de %instance_name lootent du bon matos. On y va ?' WHERE `id`=114; -UPDATE `ai_playerbot_texts` SET `id`=115, `text_loc2`='Alors, %instance_name ?' WHERE `id`=115; -UPDATE `ai_playerbot_texts` SET `id`=116, `text_loc2`='Quelqu’un a besoin d’un %my_role ?' WHERE `id`=116; -UPDATE `ai_playerbot_texts` SET `id`=117, `text_loc2`='Quelqu’un a besoin d’un %my_role ?' WHERE `id`=117; -UPDATE `ai_playerbot_texts` SET `id`=118, `text_loc2`='Qui veut aller à %instance_name ?' WHERE `id`=118; -UPDATE `ai_playerbot_texts` SET `id`=119, `text_loc2`='Quelqu’un peut me TP à %instance_name ?' WHERE `id`=119; -UPDATE `ai_playerbot_texts` SET `id`=120, `text_loc2`='Retrouve-moi à %instance_name' WHERE `id`=120; -UPDATE `ai_playerbot_texts` SET `id`=121, `text_loc2`='Envie d’un petit run rapide à %instance_name ?' WHERE `id`=121; -UPDATE `ai_playerbot_texts` SET `id`=122, `text_loc2`='On se fait un run complet à %instance_name ?' WHERE `id`=122; -UPDATE `ai_playerbot_texts` SET `id`=123, `text_loc2`='T’as été combien de fois à %instance_name ? Sérieusement.' WHERE `id`=123; -UPDATE `ai_playerbot_texts` SET `id`=124, `text_loc2`='Encore un run à %instance_name ? T’es maso ou quoi ?' WHERE `id`=124; -UPDATE `ai_playerbot_texts` SET `id`=125, `text_loc2`='Wipe à %instance_name ? Prends-moi, je suis un porte-bonheur !' WHERE `id`=125; -UPDATE `ai_playerbot_texts` SET `id`=126, `text_loc2`='Emmène-moi à %instance_name s’il te plaît. J’ai les snacks !' WHERE `id`=126; -UPDATE `ai_playerbot_texts` SET `id`=127, `text_loc2`='Un petit %instance_name vite fait bien fait ?' WHERE `id`=127; -UPDATE `ai_playerbot_texts` SET `id`=128, `text_loc2`='Un gros %instance_name jusqu’à la fin ?' WHERE `id`=128; -UPDATE `ai_playerbot_texts` SET `id`=129, `text_loc2`='Qui peut prendre un %my_role à %instance_name ? (j’apporte les blagues)' WHERE `id`=129; -UPDATE `ai_playerbot_texts` SET `id`=130, `text_loc2`='LFG %instance_name, je suis %my_role, mais surtout... je suis prêt !' WHERE `id`=130; -UPDATE `ai_playerbot_texts` SET `id`=131, `text_loc2`='%my_role cherche groupe pour %instance_name ! J’suis pas chiant, promis.' WHERE `id`=131; -UPDATE `ai_playerbot_texts` SET `id`=132, `text_loc2`='Besoin d’aide pour %quest_link ? Je promets de ne pas tout ninja.' WHERE `id`=132; -UPDATE `ai_playerbot_texts` SET `id`=133, `text_loc2`='Quelqu’un veut partager %quest_link ? On est pauvres ensemble !' WHERE `id`=133; -UPDATE `ai_playerbot_texts` SET `id`=134, `text_loc2`='Quelqu’un fait %quest_link ? Je me joins à la souffrance !' WHERE `id`=134; -UPDATE `ai_playerbot_texts` SET `id`=135, `text_loc2`='On fait %quest_link ? J’ai des cookies.' WHERE `id`=135; -UPDATE `ai_playerbot_texts` SET `id`=136, `text_loc2`='Quelqu’un pour farmer du %category ? Les mobs m’aiment trop.' WHERE `id`=136; -UPDATE `ai_playerbot_texts` SET `id`=137, `text_loc2`='Cherche aide pour farmer %category. J’en ai marre de mourir seul.' WHERE `id`=137; -UPDATE `ai_playerbot_texts` SET `id`=138, `text_loc2`='Ces %category coûtent un bras ! Et l’autre bras pour les frais de port !' WHERE `id`=138; -UPDATE `ai_playerbot_texts` SET `id`=139, `text_loc2`='J’ai envie de %category. Envie irrépressible.' WHERE `id`=139; -UPDATE `ai_playerbot_texts` SET `id`=140, `text_loc2`='Besoin d’aide pour %category. Ma patience s’épuise.' WHERE `id`=140; -UPDATE `ai_playerbot_texts` SET `id`=141, `text_loc2`='WTB %category. Même moches. Même usagés.' WHERE `id`=141; -UPDATE `ai_playerbot_texts` SET `id`=142, `text_loc2`='Quelqu’un est intéressé par %category ? Ne soyez pas timides.' WHERE `id`=142; -UPDATE `ai_playerbot_texts` SET `id`=143, `text_loc2`='WTS %category. Prix spécial, sans garantie ni remboursement.' WHERE `id`=143; -UPDATE `ai_playerbot_texts` SET `id`=144, `text_loc2`='Je vends %category moins cher que l’HV... et sans file d’attente !' WHERE `id`=144; -UPDATE `ai_playerbot_texts` SET `id`=145, `text_loc2`='Qui veut farmer du %category ? Avec ou sans café ?' WHERE `id`=145; -UPDATE `ai_playerbot_texts` SET `id`=146, `text_loc2`='On farme du %category ? J’ai annulé mon IRL exprès.' WHERE `id`=146; -UPDATE `ai_playerbot_texts` SET `id`=147, `text_loc2`='Je cherche un groupe, après ça on fait du %category ?' WHERE `id`=147; -UPDATE `ai_playerbot_texts` SET `id`=148, `text_loc2`='Tous les %category sont les bienvenus. Même les rouillés.' WHERE `id`=148; -UPDATE `ai_playerbot_texts` SET `id`=149, `text_loc2`='J’achète tout ce qui ressemble à du %category. Même les faux.' WHERE `id`=149; -UPDATE `ai_playerbot_texts` SET `id`=150, `text_loc2`='Wow, y’a des gens qui farment encore du %category ? Respect.' WHERE `id`=150; -UPDATE `ai_playerbot_texts` SET `id`=151, `text_loc2`='Les %category partent comme des petits pains à l’HV !' WHERE `id`=151; -UPDATE `ai_playerbot_texts` SET `id`=152, `text_loc2`='L’HV brûle à cause des %category !' WHERE `id`=152; -UPDATE `ai_playerbot_texts` SET `id`=153, `text_loc2`='Y’a des %category sur le marché. Profitez avant le nerf.' WHERE `id`=153; -UPDATE `ai_playerbot_texts` SET `id`=154, `text_loc2`='On échange des %category ? J’ai des trucs louches en stock.' WHERE `id`=154; -UPDATE `ai_playerbot_texts` SET `id`=155, `text_loc2`='Il me faut plus de %category. Beaucoup plus. Genre montagne.' WHERE `id`=155; -UPDATE `ai_playerbot_texts` SET `id`=156, `text_loc2`='Quelqu’un a un peu de %category à donner à une bonne cause (moi) ?' WHERE `id`=156; -UPDATE `ai_playerbot_texts` SET `id`=157, `text_loc2`='Qui veut du %category ? C’est cadeau (non, pas vraiment).' WHERE `id`=157; -UPDATE `ai_playerbot_texts` SET `id`=158, `text_loc2`='Un peu de %category s’il vous plaît ? J’ai pas mangé depuis deux loots.' WHERE `id`=158; -UPDATE `ai_playerbot_texts` SET `id`=159, `text_loc2`='J’aurais dû monter une compétence pour les %category… la flemme.' WHERE `id`=159; -UPDATE `ai_playerbot_texts` SET `id`=160, `text_loc2`='Je meurs d’envie d’avoir des %category. Littéralement.' WHERE `id`=160; -UPDATE `ai_playerbot_texts` SET `id`=161, `text_loc2`='Les gens se battent pour les %category. J’arrive avec ma pelle.' WHERE `id`=161; -UPDATE `ai_playerbot_texts` SET `id`=162, `text_loc2`='%category, c’est une affaire en or ! Si j’en avais...' WHERE `id`=162; -UPDATE `ai_playerbot_texts` SET `id`=163, `text_loc2`='Tout le monde devient fou pour les %category ! C’est contagieux ?' WHERE `id`=163; -UPDATE `ai_playerbot_texts` SET `id`=164, `text_loc2`='C’est où le meilleur spot pour farmer des %category ? Je prends notes.' WHERE `id`=164; -UPDATE `ai_playerbot_texts` SET `id`=165, `text_loc2`='Je suis prêt pour le farm de %category. Café et slip d\'aventure.' WHERE `id`=165; -UPDATE `ai_playerbot_texts` SET `id`=166, `text_loc2`='Ça se vend bien les %category ? Histoire que je rêve un peu.' WHERE `id`=166; -UPDATE `ai_playerbot_texts` SET `id`=167, `text_loc2`='Je vais garder tous mes %category. Pour moi. Parce que je suis radin.' WHERE `id`=167; -UPDATE `ai_playerbot_texts` SET `id`=168, `text_loc2`='Besoin d’un groupe ? On pourrait farm des %category ensemble. Et mourir ensemble.' WHERE `id`=168; -UPDATE `ai_playerbot_texts` SET `id`=169, `text_loc2`='Je pense encore aux %category. C’est grave docteur ?' WHERE `id`=169; -UPDATE `ai_playerbot_texts` SET `id`=170, `text_loc2`='J’ai entendu parler des %category... mais mon porte-monnaie ne veut pas.' WHERE `id`=170; -UPDATE `ai_playerbot_texts` SET `id`=171, `text_loc2`='LFG pour %category, sérieux cette fois ! (ou pas)' WHERE `id`=171; -UPDATE `ai_playerbot_texts` SET `id`=172, `text_loc2`='Vendre %category rend riche ? Ou juste aigri ?' WHERE `id`=172; -UPDATE `ai_playerbot_texts` SET `id`=173, `text_loc2`='Ok. Demain je farm les %category. Enfin... peut-être.' WHERE `id`=173; -UPDATE `ai_playerbot_texts` SET `id`=174, `text_loc2`='Tout le monde parle des %category. Même ma grand-mère.' WHERE `id`=174; -UPDATE `ai_playerbot_texts` SET `id`=175, `text_loc2`='J’ai vu au moins dix gars farmer du %category. Et moi, je regarde.' WHERE `id`=175; -UPDATE `ai_playerbot_texts` SET `id`=176, `text_loc2`='J’ai tout vendu mes %category hier. Maintenant je mange du pain sec.' WHERE `id`=176; -UPDATE `ai_playerbot_texts` SET `id`=177, `text_loc2`='Envie de rejoindre une guilde qui farme du %category. Ou une secte.' WHERE `id`=177; -UPDATE `ai_playerbot_texts` SET `id`=178, `text_loc2`='Quelqu’un farm la réputation %faction ? J’ai de la place pour souffrir.' WHERE `id`=178; -UPDATE `ai_playerbot_texts` SET `id`=179, `text_loc2`='Quelqu’un peut m’aider pour %faction ? Même moralement.' WHERE `id`=179; -UPDATE `ai_playerbot_texts` SET `id`=180, `text_loc2`='On fait des quêtes pour %faction ? Avec style.' WHERE `id`=180; -UPDATE `ai_playerbot_texts` SET `id`=181, `text_loc2`='%faction, c’est la crème de la crème. Paraît-il.' WHERE `id`=181; -UPDATE `ai_playerbot_texts` SET `id`=182, `text_loc2`='Il me manque juste un tout petit peu pour être %rep_level avec %faction.' WHERE `id`=182; -UPDATE `ai_playerbot_texts` SET `id`=183, `text_loc2`='Quelqu’un est %rep_level avec %faction ? Montrez vos secrets !' WHERE `id`=183; -UPDATE `ai_playerbot_texts` SET `id`=184, `text_loc2`='Qui veut devenir %rep_level avec %faction ? Et pleurer ensuite.' WHERE `id`=184; -UPDATE `ai_playerbot_texts` SET `id`=185, `text_loc2`='Je serai jamais %rep_level avec %faction. J’ai accepté mon destin.' WHERE `id`=185; -UPDATE `ai_playerbot_texts` SET `id`=186, `text_loc2`='Quelqu’un a oublié de monter la réputation %faction ? Vous n’êtes pas seuls.' WHERE `id`=186; -UPDATE `ai_playerbot_texts` SET `id`=187, `text_loc2`='Je peux aider à farmer la réputation %faction. Et me plaindre en même temps.' WHERE `id`=187; -UPDATE `ai_playerbot_texts` SET `id`=188, `text_loc2`='Plus on a de réputation, mieux c’est. Surtout avec %faction.' WHERE `id`=188; -UPDATE `ai_playerbot_texts` SET `id`=189, `text_loc2`='%faction : il me faut encore %rndK pour être %rep_level. Tuez-moi.' WHERE `id`=189; -UPDATE `ai_playerbot_texts` SET `id`=190, `text_loc2`='Qui peut partager des quêtes %faction ? Ou un mouchoir.' WHERE `id`=190; -UPDATE `ai_playerbot_texts` SET `id`=191, `text_loc2`='Des donjons pour la réputation %faction ? J’apporte les wipes.' WHERE `id`=191; -UPDATE `ai_playerbot_texts` SET `id`=192, `text_loc2`='On farm la réput %faction ? Jusqu’au burnout.' WHERE `id`=192; -UPDATE `ai_playerbot_texts` SET `id`=193, `text_loc2`='Allons-y pour %faction ! Et que les loots soient bons !' WHERE `id`=193; -UPDATE `ai_playerbot_texts` SET `id`=194, `text_loc2`='Je farm la réputation %faction. Ou du moins j’essaie.' WHERE `id`=194; -UPDATE `ai_playerbot_texts` SET `id`=195, `text_loc2`='On farme pour %faction ? Avec larmes et sueur.' WHERE `id`=195; -UPDATE `ai_playerbot_texts` SET `id`=196, `text_loc2`='Besoin d’aide pour %faction. Et peut-être un psy.' WHERE `id`=196; -UPDATE `ai_playerbot_texts` SET `id`=197, `text_loc2`='%faction vend quelque chose d’utile ? À part des illusions ?' WHERE `id`=197; -UPDATE `ai_playerbot_texts` SET `id`=198, `text_loc2`='Il existe des vendeurs %faction ? Ou c’est une légende ?' WHERE `id`=198; -UPDATE `ai_playerbot_texts` SET `id`=199, `text_loc2`='Qui farme %faction ? Et pourquoi ?' WHERE `id`=199; -UPDATE `ai_playerbot_texts` SET `id`=200, `text_loc2`='Quelle est la meilleure façon de farmer %faction ? En dormant ?' WHERE `id`=200; -UPDATE `ai_playerbot_texts` SET `id`=201, `text_loc2`='Je déteste farmer la réputation %faction. Voilà, c’est dit.' WHERE `id`=201; -UPDATE `ai_playerbot_texts` SET `id`=202, `text_loc2`='J’en ai marre de %faction. Vraiment.' WHERE `id`=202; -UPDATE `ai_playerbot_texts` SET `id`=203, `text_loc2`='On va pour %faction ? Ou on fuit ?' WHERE `id`=203; -UPDATE `ai_playerbot_texts` SET `id`=204, `text_loc2`='Tout le monde est %rep_level avec %faction. Et moi, je galère encore.' WHERE `id`=204; -UPDATE `ai_playerbot_texts` SET `id`=205, `text_loc2`='LFG pour farm de réputation %faction ? Avec bonne humeur (ou pas).' WHERE `id`=205; -UPDATE `ai_playerbot_texts` SET `id`=206, `text_loc2`='Quelqu’un a un bon spot pour la réputation %faction ? J’ai une pelle.' WHERE `id`=206; -UPDATE `ai_playerbot_texts` SET `id`=207, `text_loc2`='Améliorer ma réput %faction, ça sert ? Ou je perds mon temps ?' WHERE `id`=207; -UPDATE `ai_playerbot_texts` SET `id`=208, `text_loc2`='Qui aurait cru que la réputation %faction finirait par servir ?' WHERE `id`=208; -UPDATE `ai_playerbot_texts` SET `id`=209, `text_loc2`='Je veux être exalté avec toutes les factions. En commençant par %faction.' WHERE `id`=209; -UPDATE `ai_playerbot_texts` SET `id`=210, `text_loc2`='Est-ce que ça vaut le coup de monter %faction ? Ou juste une perte de vie ?' WHERE `id`=210; -UPDATE `ai_playerbot_texts` SET `id`=211, `text_loc2`='Qu’est-ce qui marche le mieux pour %faction ? Les quêtes ou tuer des mobs ?' WHERE `id`=211; -UPDATE `ai_playerbot_texts` SET `id`=212, `text_loc2`='Je farm %faction pour toi, si tu me paies. Et je rigole pas.' WHERE `id`=212; -UPDATE `ai_playerbot_texts` SET `id`=213, `text_loc2`='Farmer la réputation %faction ? Ça prendra 3 vies au moins.' WHERE `id`=213; -UPDATE `ai_playerbot_texts` SET `id`=214, `text_loc2`='Je tue pour %faction tous les jours, mais je suis toujours pas %rep_level.' WHERE `id`=214; -UPDATE `ai_playerbot_texts` SET `id`=215, `text_loc2`='À %my_level, les dépôts à l’HV vont baisser, non ?' WHERE `id`=215; -UPDATE `ai_playerbot_texts` SET `id`=216, `text_loc2`='Combien de réputations exaltées tu as ? Allez, montre !' WHERE `id`=216; -UPDATE `ai_playerbot_texts` SET `id`=217, `text_loc2`='Qui veut être %my_level avec %faction ? Moi j’ai peur.' WHERE `id`=217; -UPDATE `ai_playerbot_texts` SET `id`=218, `text_loc2`='Ma guilde a farmé la réputation %faction hier. Sans moi. Tristesse.' WHERE `id`=218; -UPDATE `ai_playerbot_texts` SET `id`=219, `text_loc2`='Personne ne veut m’aider, tout ça parce que je suis %rep_level avec %faction.' WHERE `id`=219; -UPDATE `ai_playerbot_texts` SET `id`=220, `text_loc2`='Évitez %faction. Pour votre santé mentale.' WHERE `id`=220; -UPDATE `ai_playerbot_texts` SET `id`=221, `text_loc2`='On fait une soirée à %zone_name ? Bring the drums !' WHERE `id`=221; -UPDATE `ai_playerbot_texts` SET `id`=222, `text_loc2`='Quelqu’un cherche un %my_role ? Je suis dispo et pas trop nul.' WHERE `id`=222; -UPDATE `ai_playerbot_texts` SET `id`=223, `text_loc2`='%my_role cherche une guilde. Sérieux, je suis cool.' WHERE `id`=223; -UPDATE `ai_playerbot_texts` SET `id`=224, `text_loc2`='Je cherche de l’or. Et pas juste dans les rêves.' WHERE `id`=224; -UPDATE `ai_playerbot_texts` SET `id`=225, `text_loc2`='%my_role cherche une bonne guilde, pas une secte (sauf si vous avez des cookies)' WHERE `id`=225; -UPDATE `ai_playerbot_texts` SET `id`=226, `text_loc2`='J’ai besoin d’un ami. Ou d’un pet qui me juge pas.' WHERE `id`=226; -UPDATE `ai_playerbot_texts` SET `id`=227, `text_loc2`='Quelqu’un d’autre se sent seul ? On se fait un groupe de dépression ?' WHERE `id`=227; -UPDATE `ai_playerbot_texts` SET `id`=228, `text_loc2`='Je m’ennuie... Sauvez-moi ou tuez-moi, mais faites quelque chose.' WHERE `id`=228; -UPDATE `ai_playerbot_texts` SET `id`=229, `text_loc2`='Qui en veut ? J’ai des buffs et de la mauvaise foi !' WHERE `id`=229; -UPDATE `ai_playerbot_texts` SET `id`=230, `text_loc2`='Allez viens te battre !' WHERE `id`=230; -UPDATE `ai_playerbot_texts` SET `id`=231, `text_loc2`='Un petit duel à %zone_name, histoire de s’humilier ?' WHERE `id`=231; -UPDATE `ai_playerbot_texts` SET `id`=232, `text_loc2`='Quelqu’un fait quelque chose ici ? Parce que moi je campe le vide.' WHERE `id`=232; -UPDATE `ai_playerbot_texts` SET `id`=233, `text_loc2`='%zone_name : y’a une âme qui vive ici ?' WHERE `id`=233; -UPDATE `ai_playerbot_texts` SET `id`=234, `text_loc2`='%zone_name : tout le monde est en furtif ou quoi ?' WHERE `id`=234; -UPDATE `ai_playerbot_texts` SET `id`=235, `text_loc2`='On dirait que je suis seul à %zone_name. Même les PNJ me fuient.' WHERE `id`=235; -UPDATE `ai_playerbot_texts` SET `id`=236, `text_loc2`='Rejoins-moi à %zone_name ! Apporte la bière.' WHERE `id`=236; -UPDATE `ai_playerbot_texts` SET `id`=237, `text_loc2`='Allez, on fait des quêtes à %zone_name ! Le fun est presque garanti.' WHERE `id`=237; -UPDATE `ai_playerbot_texts` SET `id`=238, `text_loc2`='%zone_name c’est LE coin sympa. Et les mobs sont sympas aussi… parfois.' WHERE `id`=238; -UPDATE `ai_playerbot_texts` SET `id`=239, `text_loc2`='J’veux aller à %zone_name. Quelqu’un me suit ou je pars solo again ?' WHERE `id`=239; -UPDATE `ai_playerbot_texts` SET `id`=240, `text_loc2`='Qui veut aller à %zone_name ? Et mourir dans la joie ?' WHERE `id`=240; -UPDATE `ai_playerbot_texts` SET `id`=241, `text_loc2`='J’aime pas %zone_name. On bouge ? Vite.' WHERE `id`=241; -UPDATE `ai_playerbot_texts` SET `id`=242, `text_loc2`='Y’a de bonnes quêtes à %zone_name ou juste des traquenards ?' WHERE `id`=242; -UPDATE `ai_playerbot_texts` SET `id`=243, `text_loc2`='On va où après %zone_name ? L’enfer ?' WHERE `id`=243; -UPDATE `ai_playerbot_texts` SET `id`=244, `text_loc2`='Qui traîne à %zone_name ? Qu’on fasse un barbecue.' WHERE `id`=244; -UPDATE `ai_playerbot_texts` SET `id`=245, `text_loc2`='LFG pour %zone_name. J’apporte la bonne humeur (et le wipe).' WHERE `id`=245; -UPDATE `ai_playerbot_texts` SET `id`=246, `text_loc2`='%zone_name est l’endroit le plus naze du monde.' WHERE `id`=246; -UPDATE `ai_playerbot_texts` SET `id`=247, `text_loc2`='Attrape-moi à %zone_name si tu peux !' WHERE `id`=247; -UPDATE `ai_playerbot_texts` SET `id`=248, `text_loc2`='Direction %zone_name ! Pour le loot ! Ou les fails.' WHERE `id`=248; -UPDATE `ai_playerbot_texts` SET `id`=249, `text_loc2`='Envie de quêtes à %zone_name' WHERE `id`=249; -UPDATE `ai_playerbot_texts` SET `id`=250, `text_loc2`='Quelqu’un a des quêtes à %zone_name ? À partager, pas à fuir.' WHERE `id`=250; -UPDATE `ai_playerbot_texts` SET `id`=251, `text_loc2`='Venez à %zone_name ! C’est désert, mais charmant.' WHERE `id`=251; -UPDATE `ai_playerbot_texts` SET `id`=252, `text_loc2`='On dirait que la Horde a déserté %zone_name...' WHERE `id`=252; -UPDATE `ai_playerbot_texts` SET `id`=253, `text_loc2`='On dirait que l’Alliance a déserté %zone_name...' WHERE `id`=253; -UPDATE `ai_playerbot_texts` SET `id`=254, `text_loc2`='J’en peux plus de %zone_name. Quelqu’un me sort de là ?' WHERE `id`=254; -UPDATE `ai_playerbot_texts` SET `id`=255, `text_loc2`='Bonne chance !' WHERE `id`=255; -UPDATE `ai_playerbot_texts` SET `id`=256, `text_loc2`='Je veux rentrer chez moi… puis pleurer au bord du vide' WHERE `id`=256; -UPDATE `ai_playerbot_texts` SET `id`=257, `text_loc2`='Quelqu’un sait ce qu’il faut pour jouer double arme ? Une crise existentielle ?' WHERE `id`=257; -UPDATE `ai_playerbot_texts` SET `id`=258, `text_loc2`='Salut tout le monde !' WHERE `id`=258; -UPDATE `ai_playerbot_texts` SET `id`=259, `text_loc2`='%zone_name est cosy… ou alors je perds la tête' WHERE `id`=259; -UPDATE `ai_playerbot_texts` SET `id`=260, `text_loc2`='Je me sens bien… bizarrement suspect.' WHERE `id`=260; -UPDATE `ai_playerbot_texts` SET `id`=261, `text_loc2`='Je n’ignore pas les gens. Je les trolle jusqu’à ce qu’ils m’ignorent.' WHERE `id`=261; -UPDATE `ai_playerbot_texts` SET `id`=262, `text_loc2`='Que pensez-vous de mon build ? Soyez gentils %my_role' WHERE `id`=262; -UPDATE `ai_playerbot_texts` SET `id`=263, `text_loc2`='Heureux de voir que le chat ne m’a pas oublié (ou presque)' WHERE `id`=263; -UPDATE `ai_playerbot_texts` SET `id`=264, `text_loc2`='Comme toutes les armes, c’est BiS pour chasseur (hein ? hein ?)' WHERE `id`=264; -UPDATE `ai_playerbot_texts` SET `id`=265, `text_loc2`='Le but du jeu pour moi ? Solo tout ce qui bouge. Même les mouches.' WHERE `id`=265; -UPDATE `ai_playerbot_texts` SET `id`=266, `text_loc2`='J’ai JAMAIS arnaqué personne. Juré. Enfin… presque.' WHERE `id`=266; -UPDATE `ai_playerbot_texts` SET `id`=267, `text_loc2`='Ah, World of Warcraft. Là où je viens chercher des conseils de vie.' WHERE `id`=267; -UPDATE `ai_playerbot_texts` SET `id`=268, `text_loc2`='Y’A QUELQU’UN ?!' WHERE `id`=268; -UPDATE `ai_playerbot_texts` SET `id`=269, `text_loc2`='Il est temps de me frayer un chemin dans %zone_name à coups de sorts.' WHERE `id`=269; -UPDATE `ai_playerbot_texts` SET `id`=270, `text_loc2`='%zone_name' WHERE `id`=270; -UPDATE `ai_playerbot_texts` SET `id`=271, `text_loc2`='… faut que j’aille aux toilettes. Urgence IRL.' WHERE `id`=271; -UPDATE `ai_playerbot_texts` SET `id`=272, `text_loc2`='Si tu loot pas tes mobs skinables, ton zizi perd 1mm. C’est la règle.' WHERE `id`=272; -UPDATE `ai_playerbot_texts` SET `id`=273, `text_loc2`='NOOOOOOOOOOOOO' WHERE `id`=273; -UPDATE `ai_playerbot_texts` SET `id`=274, `text_loc2`='J’AIME LA PATATE' WHERE `id`=274; -UPDATE `ai_playerbot_texts` SET `id`=275, `text_loc2`='La discussion est animée.' WHERE `id`=275; -UPDATE `ai_playerbot_texts` SET `id`=276, `text_loc2`='salut, comment ça va les gens ?' WHERE `id`=276; -UPDATE `ai_playerbot_texts` SET `id`=277, `text_loc2`='Je viens de me déco / reco. Choc temporel.' WHERE `id`=277; -UPDATE `ai_playerbot_texts` SET `id`=278, `text_loc2`='Faites moins de bruit, j’suis perdu dans %zone_name…' WHERE `id`=278; -UPDATE `ai_playerbot_texts` SET `id`=279, `text_loc2`='Quelqu’un veut boire un verre à %zone_name ? hic' WHERE `id`=279; -UPDATE `ai_playerbot_texts` SET `id`=280, `text_loc2`='hahahahaheeeee dirin diring inggggg hahahahaheeeeeeeeeeeeee' WHERE `id`=280; -UPDATE `ai_playerbot_texts` SET `id`=281, `text_loc2`='Avant, les appâts étaient crédibles. Maintenant c’est TikTok.' WHERE `id`=281; -UPDATE `ai_playerbot_texts` SET `id`=282, `text_loc2`='Peut-être que t’as juste perdu ton innocence.' WHERE `id`=282; -UPDATE `ai_playerbot_texts` SET `id`=283, `text_loc2`='Y’a une guilde qui veut carry un %my_role fragile ?' WHERE `id`=283; -UPDATE `ai_playerbot_texts` SET `id`=284, `text_loc2`='Plus on monte en niveau, plus l’or coule à flots… sauf pour moi.' WHERE `id`=284; -UPDATE `ai_playerbot_texts` SET `id`=285, `text_loc2`='Bonjour ! (oui, juste ça)' WHERE `id`=285; -UPDATE `ai_playerbot_texts` SET `id`=286, `text_loc2`='Pourquoi j’ai mal au cul ?' WHERE `id`=286; -UPDATE `ai_playerbot_texts` SET `id`=287, `text_loc2`='Je pense que l’esprit est BiS pour monter de niveau.' WHERE `id`=287; -UPDATE `ai_playerbot_texts` SET `id`=288, `text_loc2`='Encore plus si t’es troll. Véridique.' WHERE `id`=288; -UPDATE `ai_playerbot_texts` SET `id`=289, `text_loc2`='QUELQU’UN PEUT M’INVITER ?' WHERE `id`=289; -UPDATE `ai_playerbot_texts` SET `id`=290, `text_loc2`='J’ai besoin de beaucouuuup de boissons. Et d’un foie neuf.' WHERE `id`=290; -UPDATE `ai_playerbot_texts` SET `id`=291, `text_loc2`='M*rde de gnomes…' WHERE `id`=291; -UPDATE `ai_playerbot_texts` SET `id`=292, `text_loc2`='Personne n’aime les gnomes. Même pas eux.' WHERE `id`=292; -UPDATE `ai_playerbot_texts` SET `id`=293, `text_loc2`='Les gnomes ne servent qu’à une chose… les blagues.' WHERE `id`=293; -UPDATE `ai_playerbot_texts` SET `id`=294, `text_loc2`='Bah…' WHERE `id`=294; -UPDATE `ai_playerbot_texts` SET `id`=295, `text_loc2`='… des champignons.' WHERE `id`=295; -UPDATE `ai_playerbot_texts` SET `id`=296, `text_loc2`='Les pensées automatiques, c’est flippant. Surtout les miennes.' WHERE `id`=296; -UPDATE `ai_playerbot_texts` SET `id`=297, `text_loc2`='L’esprit est plus malléable qu’on aimerait le croire.' WHERE `id`=297; -UPDATE `ai_playerbot_texts` SET `id`=298, `text_loc2`='Y’a des guildes pour leveling ? Ou faut pleurer en solo ?' WHERE `id`=298; -UPDATE `ai_playerbot_texts` SET `id`=299, `text_loc2`='brb' WHERE `id`=299; -UPDATE `ai_playerbot_texts` SET `id`=300, `text_loc2`='Pourquoi la neige est blanche mais la glace est transparente ? Mystère.' WHERE `id`=300; -UPDATE `ai_playerbot_texts` SET `id`=301, `text_loc2`='Pourquoi la crème fouettée est fluffy, mais pas la normale ?' WHERE `id`=301; -UPDATE `ai_playerbot_texts` SET `id`=302, `text_loc2`='Pourquoi les pieds sentent alors qu’ils n’ont pas de nez ?' WHERE `id`=302; -UPDATE `ai_playerbot_texts` SET `id`=303, `text_loc2`='On dirait que la boîte à noobs vient de s’ouvrir.' WHERE `id`=303; -UPDATE `ai_playerbot_texts` SET `id`=304, `text_loc2`='Arrêtez de troller les nouveaux avec vos réponses à la con.' WHERE `id`=304; -UPDATE `ai_playerbot_texts` SET `id`=305, `text_loc2`='Y’a du PvP sur ce serveur ? Ou que des pleureurs ?' WHERE `id`=305; -UPDATE `ai_playerbot_texts` SET `id`=306, `text_loc2`='évidemment...' WHERE `id`=306; -UPDATE `ai_playerbot_texts` SET `id`=307, `text_loc2`='ouf… :)' WHERE `id`=307; -UPDATE `ai_playerbot_texts` SET `id`=308, `text_loc2`='Vous saviez que… ? Bah moi non plus.' WHERE `id`=308; -UPDATE `ai_playerbot_texts` SET `id`=309, `text_loc2`='Je ne tente pas d’imaginer ce que ressentent les autres créatures. Trop de boulot.' WHERE `id`=309; -UPDATE `ai_playerbot_texts` SET `id`=310, `text_loc2`='Oups, mauvais canal.' WHERE `id`=310; -UPDATE `ai_playerbot_texts` SET `id`=311, `text_loc2`='Bruh, vous êtes déchaînés aujourd’hui.' WHERE `id`=311; -UPDATE `ai_playerbot_texts` SET `id`=312, `text_loc2`='Juste pour que tout le monde sache : mon message est passé ici' WHERE `id`=312; -UPDATE `ai_playerbot_texts` SET `id`=313, `text_loc2`='grrr énervéééééé' WHERE `id`=313; -UPDATE `ai_playerbot_texts` SET `id`=314, `text_loc2`='Le farm, c’est la vie. Ou la prison. On sait pas trop.' WHERE `id`=314; -UPDATE `ai_playerbot_texts` SET `id`=315, `text_loc2`='WoW me garde vif. Ou insomniaque.' WHERE `id`=315; -UPDATE `ai_playerbot_texts` SET `id`=316, `text_loc2`='Hé, question : où on prend le rôle pour plus d’XP ? Je suis à %zone_name.' WHERE `id`=316; -UPDATE `ai_playerbot_texts` SET `id`=317, `text_loc2`='Vous aimez les saucisses ? Celles qui se lootent hein !' WHERE `id`=317; -UPDATE `ai_playerbot_texts` SET `id`=318, `text_loc2`='Invitez-moi. Je suis utile. Enfin... je crois.' WHERE `id`=318; -UPDATE `ai_playerbot_texts` SET `id`=319, `text_loc2`='À votre avis, quelle classe est la meilleure en PvP ?' WHERE `id`=319; -UPDATE `ai_playerbot_texts` SET `id`=320, `text_loc2`='Où est ce foutu maître de cuisine à %zone_name ?!' WHERE `id`=320; -UPDATE `ai_playerbot_texts` SET `id`=321, `text_loc2`='Vous savez ce qu’il se passe à %zone_name ? Spoiler : pas grand-chose.' WHERE `id`=321; -UPDATE `ai_playerbot_texts` SET `id`=322, `text_loc2`='J’ai besoin de crafter un truc. Ou d’un miracle.' WHERE `id`=322; -UPDATE `ai_playerbot_texts` SET `id`=323, `text_loc2`='C’est quoi “ligma” ?' WHERE `id`=323; -UPDATE `ai_playerbot_texts` SET `id`=324, `text_loc2`='Et “sugma” ?' WHERE `id`=324; -UPDATE `ai_playerbot_texts` SET `id`=325, `text_loc2`='ligma balls' WHERE `id`=325; -UPDATE `ai_playerbot_texts` SET `id`=326, `text_loc2`='sugma balls' WHERE `id`=326; -UPDATE `ai_playerbot_texts` SET `id`=327, `text_loc2`='JE MANGE DES FESSES' WHERE `id`=327; -UPDATE `ai_playerbot_texts` SET `id`=328, `text_loc2`='J’ai envie de me fourrer %random_inventory_item_link là où le soleil ne brille pas' WHERE `id`=328; -UPDATE `ai_playerbot_texts` SET `id`=329, `text_loc2`='J’ai envie de te fourrer %random_inventory_item_link là où tu penses' WHERE `id`=329; -UPDATE `ai_playerbot_texts` SET `id`=330, `text_loc2`='Darnasses (oui oui, avec deux "s", on juge pas)' WHERE `id`=330; -UPDATE `ai_playerbot_texts` SET `id`=331, `text_loc2`='On dirait que t’as chopé le syndrôme de sugma' WHERE `id`=331; -UPDATE `ai_playerbot_texts` SET `id`=332, `text_loc2`='deez nutz dans ta bouche (attention, ça pique)' WHERE `id`=332; -UPDATE `ai_playerbot_texts` SET `id`=333, `text_loc2`='Sympa ton os, frérot' WHERE `id`=333; -UPDATE `ai_playerbot_texts` SET `id`=334, `text_loc2`='ERP ? Euh… Emmental, Roquefort, Parmesan ?' WHERE `id`=334; -UPDATE `ai_playerbot_texts` SET `id`=335, `text_loc2`='J’ai tout essayé, mais au final c’est l’ERP qui a marché... triste monde' WHERE `id`=335; -UPDATE `ai_playerbot_texts` SET `id`=336, `text_loc2`='J’ai envie de batifoler à %zone_name. Qui vient ?' WHERE `id`=336; -UPDATE `ai_playerbot_texts` SET `id`=337, `text_loc2`='Recherche gnome femelle avec gorille pour ERP sauvage à %zone_name' WHERE `id`=337; -UPDATE `ai_playerbot_texts` SET `id`=338, `text_loc2`='Je peux comprendre un idiot, mais un gros pervers ? Là j’suis perdu' WHERE `id`=338; -UPDATE `ai_playerbot_texts` SET `id`=339, `text_loc2`='Aucun GYAT en vue à %zone_name… scandale national' WHERE `id`=339; -UPDATE `ai_playerbot_texts` SET `id`=340, `text_loc2`='Je tue tous les animaux de %zone_name. Désolé WWF !' WHERE `id`=340; -UPDATE `ai_playerbot_texts` SET `id`=341, `text_loc2`='Heureusement que j’ai trois jambes!' WHERE `id`=341; -UPDATE `ai_playerbot_texts` SET `id`=342, `text_loc2`='Sois pas vénère, je goon comme un sigma' WHERE `id`=342; -UPDATE `ai_playerbot_texts` SET `id`=343, `text_loc2`='Essaye doigt, mais trou (philosophie du vide)' WHERE `id`=343; -UPDATE `ai_playerbot_texts` SET `id`=344, `text_loc2`='%prefix %random_taken_quest_or_item_link' WHERE `id`=344; -UPDATE `ai_playerbot_texts` SET `id`=345, `text_loc2`='%prefix %random_inventory_item_link' WHERE `id`=345; -UPDATE `ai_playerbot_texts` SET `id`=346, `text_loc2`='%thunderfury_link' WHERE `id`=346; -UPDATE `ai_playerbot_texts` SET `id`=347, `text_loc2`='%thunderfury_link%thunderfury_link' WHERE `id`=347; -UPDATE `ai_playerbot_texts` SET `id`=348, `text_loc2`='%thunderfury_link%thunderfury_link%thunderfury_link' WHERE `id`=348; -UPDATE `ai_playerbot_texts` SET `id`=349, `text_loc2`='Je crois que je viens d’entendre %thunderfury_link' WHERE `id`=349; -UPDATE `ai_playerbot_texts` SET `id`=350, `text_loc2`='J’ai entendu %thunderfury_link, non ?' WHERE `id`=350; -UPDATE `ai_playerbot_texts` SET `id`=351, `text_loc2`='J’ai clairement entendu %thunderfury_link' WHERE `id`=351; -UPDATE `ai_playerbot_texts` SET `id`=352, `text_loc2`='J’suis pas sûr, mais j’crois avoir entendu %thunderfury_link' WHERE `id`=352; -UPDATE `ai_playerbot_texts` SET `id`=353, `text_loc2`='T’as dit %thunderfury_link là ?' WHERE `id`=353; -UPDATE `ai_playerbot_texts` SET `id`=354, `text_loc2`='Quelqu’un a dit %thunderfury_link ?' WHERE `id`=354; -UPDATE `ai_playerbot_texts` SET `id`=355, `text_loc2`='Quelqu’un a VRAIMENT dit %thunderfury_link ?' WHERE `id`=355; -UPDATE `ai_playerbot_texts` SET `id`=356, `text_loc2`='Quelqu’un a parlé de %thunderfury_link' WHERE `id`=356; -UPDATE `ai_playerbot_texts` SET `id`=357, `text_loc2`='%thunderfury_link sort du placard, les gars' WHERE `id`=357; -UPDATE `ai_playerbot_texts` SET `id`=358, `text_loc2`='J’aurais juré que c’était un %thunderfury_link… ou peut-être un %thunderfury_link' WHERE `id`=358; -UPDATE `ai_playerbot_texts` SET `id`=359, `text_loc2`='Pourquoi utiliser %thunderfury_link alors que %thunderfury_link est bien plus OP ?' WHERE `id`=359; -UPDATE `ai_playerbot_texts` SET `id`=360, `text_loc2`='WTS %item_formatted_link pour %cost_gold ! Occasion en or !' WHERE `id`=360; -UPDATE `ai_playerbot_texts` SET `id`=361, `text_loc2`='Qui veut %item_formatted_link pour %cost_gold ?' WHERE `id`=361; -UPDATE `ai_playerbot_texts` SET `id`=362, `text_loc2`='Quelqu’un veut %item_formatted_link ? Seulement %cost_gold' WHERE `id`=362; -UPDATE `ai_playerbot_texts` SET `id`=363, `text_loc2`='Juste %cost_gold pour %item_formatted_link, vous hésitez encore ?' WHERE `id`=363; -UPDATE `ai_playerbot_texts` SET `id`=364, `text_loc2`='Je vends %item_formatted_link pour %cost_gold' WHERE `id`=364; -UPDATE `ai_playerbot_texts` SET `id`=365, `text_loc2`='%item_formatted_link est à toi pour seulement %cost_gold !' WHERE `id`=365; -UPDATE `ai_playerbot_texts` SET `id`=366, `text_loc2`='Prix ridicule : %cost_gold pour %item_formatted_link ! C’est cadeau !' WHERE `id`=366; -UPDATE `ai_playerbot_texts` SET `id`=367, `text_loc2`='Je cherche à vendre %item_formatted_link pour %cost_gold' WHERE `id`=367; -UPDATE `ai_playerbot_texts` SET `id`=368, `text_loc2`='Qui a besoin de %item_formatted_link ? Seulement %cost_gold' WHERE `id`=368; -UPDATE `ai_playerbot_texts` SET `id`=369, `text_loc2`='Quelqu’un veut %item_formatted_link pour %cost_gold ?' WHERE `id`=369; -UPDATE `ai_playerbot_texts` SET `id`=370, `text_loc2`='%cost_gold pour %item_formatted_link. Moins cher qu’à l’HV !' WHERE `id`=370; -UPDATE `ai_playerbot_texts` SET `id`=371, `text_loc2`='%item_formatted_link est cher, mais je te le fais à %cost_gold' WHERE `id`=371; -UPDATE `ai_playerbot_texts` SET `id`=372, `text_loc2`='Tu trouveras jamais %item_formatted_link moins cher que %cost_gold' WHERE `id`=372; -UPDATE `ai_playerbot_texts` SET `id`=373, `text_loc2`='J’ai besoin de plus que %item_formatted_link, là !' WHERE `id`=373; -UPDATE `ai_playerbot_texts` SET `id`=374, `text_loc2`='J’ai %item_formatted_link et j’en veux encore' WHERE `id`=374; -UPDATE `ai_playerbot_texts` SET `id`=375, `text_loc2`='J’ai %item_formatted_link. Qui l’achète pour %cost_gold ?' WHERE `id`=375; -UPDATE `ai_playerbot_texts` SET `id`=376, `text_loc2`='WTB %item_formatted_link pour %cost_gold, quelqu’un ?' WHERE `id`=376; -UPDATE `ai_playerbot_texts` SET `id`=377, `text_loc2`='Et %item_formatted_link ? Pour %cost_gold, ça vous tente ?' WHERE `id`=377; -UPDATE `ai_playerbot_texts` SET `id`=378, `text_loc2`='Qui m’a traité de radin ? %item_formatted_link pour %cost_gold c’est honnête !' WHERE `id`=378; -UPDATE `ai_playerbot_texts` SET `id`=379, `text_loc2`='Je vends %item_formatted_link. Juste %cost_gold' WHERE `id`=379; -UPDATE `ai_playerbot_texts` SET `id`=380, `text_loc2`='LFG pour du farm, et au passage %item_formatted_link à vendre %cost_gold' WHERE `id`=380; -UPDATE `ai_playerbot_texts` SET `id`=381, `text_loc2`='Presque tout vendu aujourd’hui. Me reste %item_formatted_link pour %cost_gold' WHERE `id`=381; -UPDATE `ai_playerbot_texts` SET `id`=382, `text_loc2`='À quoi sert le canal commerce ? Vendre %item_formatted_link pour %cost_gold, évidemment' WHERE `id`=382; -UPDATE `ai_playerbot_texts` SET `id`=383, `text_loc2`='Quelqu’un peut battre %cost_gold pour %item_formatted_link ? J’attends…' WHERE `id`=383; -UPDATE `ai_playerbot_texts` SET `id`=384, `text_loc2`='Envie d’arrêter le spam commerce ? Achetez %item_formatted_link à %cost_gold !' WHERE `id`=384; -UPDATE `ai_playerbot_texts` SET `id`=385, `text_loc2`='Tout le monde spam, moi aussi : %cost_gold pour %item_formatted_link !' WHERE `id`=385; -UPDATE `ai_playerbot_texts` SET `id`=386, `text_loc2`='%item_formatted_link est utile ? Je sais pas, mais je le vends %cost_gold' WHERE `id`=386; -UPDATE `ai_playerbot_texts` SET `id`=387, `text_loc2`='J’ai %item_formatted_link prêt à vendre %cost_gold' WHERE `id`=387; -UPDATE `ai_playerbot_texts` SET `id`=388, `text_loc2`='Hier j’ai rien foutu, mais j’ai loot %item_formatted_link. À vendre %cost_gold' WHERE `id`=388; -UPDATE `ai_playerbot_texts` SET `id`=389, `text_loc2`='J’ai farmé hier, j’ai eu %item_formatted_link. WTB ? %cost_gold' WHERE `id`=389; -UPDATE `ai_playerbot_texts` SET `id`=390, `text_loc2`='J’ai acheté %item_formatted_link hier. Quelqu’un le veut ? %cost_gold' WHERE `id`=390; -UPDATE `ai_playerbot_texts` SET `id`=391, `text_loc2`='Quelqu’un cherchait %item_formatted_link ? C’est %cost_gold toujours' WHERE `id`=391; -UPDATE `ai_playerbot_texts` SET `id`=392, `text_loc2`='J’ai encore %item_formatted_link. Achetez-le %cost_gold' WHERE `id`=392; -UPDATE `ai_playerbot_texts` SET `id`=393, `text_loc2`='Avant j’en avais plein %item_formatted_link, maintenant je dois vendre à %cost_gold' WHERE `id`=393; -UPDATE `ai_playerbot_texts` SET `id`=394, `text_loc2`='J’aimerais en avoir plus que %item_formatted_link. Mais achetez celui-là %cost_gold' WHERE `id`=394; -UPDATE `ai_playerbot_texts` SET `id`=395, `text_loc2`='Ton or te sert à quoi ? À acheter %item_formatted_link pour %cost_gold' WHERE `id`=395; -UPDATE `ai_playerbot_texts` SET `id`=396, `text_loc2`='Ayez pitié, donnez-moi de l’or... ou achetez %item_formatted_link %cost_gold' WHERE `id`=396; -UPDATE `ai_playerbot_texts` SET `id`=397, `text_loc2`='Est-ce que %cost_gold est un bon prix pour %item_formatted_link ?' WHERE `id`=397; -UPDATE `ai_playerbot_texts` SET `id`=398, `text_loc2`='J’ai acheté %item_formatted_links hier, mais j’en veux plus. À vendre %cost_gold' WHERE `id`=398; -UPDATE `ai_playerbot_texts` SET `id`=399, `text_loc2`='Je vais le mettre à l’HV, mais tu peux l’avoir moins cher : %cost_gold' WHERE `id`=399; -UPDATE `ai_playerbot_texts` SET `id`=400, `text_loc2`='Pourquoi j’ai acheté %item_formatted_link bordel ? Quelqu’un le veut ? %cost_gold' WHERE `id`=400; -UPDATE `ai_playerbot_texts` SET `id`=401, `text_loc2`='J’ai %quest_links' WHERE `id`=401; -UPDATE `ai_playerbot_texts` SET `id`=402, `text_loc2`='Moi aussi j’ai %quest_links' WHERE `id`=402; -UPDATE `ai_playerbot_texts` SET `id`=403, `text_loc2`='Moi aussi j’ai %quest_links, je suis à %zone_name' WHERE `id`=403; -UPDATE `ai_playerbot_texts` SET `id`=404, `text_loc2`='%other_name, moi aussi j’ai %quest_links' WHERE `id`=404; -UPDATE `ai_playerbot_texts` SET `id`=405, `text_loc2`='%other_name, moi aussi j’ai %quest_links, et je suis à %zone_name' WHERE `id`=405; -UPDATE `ai_playerbot_texts` SET `id`=406, `text_loc2`='Je suis dispo pour %quest_links, je suis à %zone_name' WHERE `id`=406; -UPDATE `ai_playerbot_texts` SET `id`=407, `text_loc2`='Je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=407; -UPDATE `ai_playerbot_texts` SET `id`=408, `text_loc2`='%other_name, je suis dispo pour %quest_links à %zone_name' WHERE `id`=408; -UPDATE `ai_playerbot_texts` SET `id`=409, `text_loc2`='%other_name, je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=409; -UPDATE `ai_playerbot_texts` SET `id`=410, `text_loc2`='Hey, je suis partant pour %quest_links' WHERE `id`=410; -UPDATE `ai_playerbot_texts` SET `id`=411, `text_loc2`='Hey, je pourrais faire %quest_links avec toi' WHERE `id`=411; -UPDATE `ai_playerbot_texts` SET `id`=412, `text_loc2`='Hey, moi aussi j’ai %quest_links' WHERE `id`=412; -UPDATE `ai_playerbot_texts` SET `id`=413, `text_loc2`='Hey %other_name, partant pour %quest_links' WHERE `id`=413; -UPDATE `ai_playerbot_texts` SET `id`=414, `text_loc2`='Hey %other_name, je peux faire %quest_links avec toi' WHERE `id`=414; -UPDATE `ai_playerbot_texts` SET `id`=415, `text_loc2`='Hey %other_name, moi aussi j’ai %quest_links' WHERE `id`=415; -UPDATE `ai_playerbot_texts` SET `id`=416, `text_loc2`='On se groupe pour %quest_links ?' WHERE `id`=416; -UPDATE `ai_playerbot_texts` SET `id`=417, `text_loc2`='Je suis partant pour %quest_links, je suis à %zone_name' WHERE `id`=417; -UPDATE `ai_playerbot_texts` SET `id`=418, `text_loc2`='Je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=418; -UPDATE `ai_playerbot_texts` SET `id`=419, `text_loc2`='%other_name, je peux te vendre %formatted_item_links' WHERE `id`=419; -UPDATE `ai_playerbot_texts` SET `id`=420, `text_loc2`='Je peux peut-être vendre %formatted_item_links' WHERE `id`=420; -UPDATE `ai_playerbot_texts` SET `id`=421, `text_loc2`='Je pense pouvoir vendre %formatted_item_links' WHERE `id`=421; -UPDATE `ai_playerbot_texts` SET `id`=422, `text_loc2`='%other_name, je peux peut-être te vendre %formatted_item_links' WHERE `id`=422; -UPDATE `ai_playerbot_texts` SET `id`=423, `text_loc2`='%other_name, tu penses que je peux vendre %formatted_item_links ?' WHERE `id`=423; -UPDATE `ai_playerbot_texts` SET `id`=424, `text_loc2`='Je peux te vendre %formatted_item_links' WHERE `id`=424; -UPDATE `ai_playerbot_texts` SET `id`=425, `text_loc2`='Hey, j’ai %formatted_item_links à vendre' WHERE `id`=425; -UPDATE `ai_playerbot_texts` SET `id`=426, `text_loc2`='Hey, je pourrais peut-être vendre %formatted_item_links' WHERE `id`=426; -UPDATE `ai_playerbot_texts` SET `id`=427, `text_loc2`='Quête acceptée' WHERE `id`=427; -UPDATE `ai_playerbot_texts` SET `id`=428, `text_loc2`='Quête abandonnée' WHERE `id`=428; -UPDATE `ai_playerbot_texts` SET `id`=429, `text_loc2`='Je ne peux pas prendre cette quête' WHERE `id`=429; -UPDATE `ai_playerbot_texts` SET `id`=430, `text_loc2`='Je ne peux pas parler au donneur de quête' WHERE `id`=430; -UPDATE `ai_playerbot_texts` SET `id`=431, `text_loc2`='J’ai déjà terminé %quest' WHERE `id`=431; -UPDATE `ai_playerbot_texts` SET `id`=432, `text_loc2`='J’ai déjà la quête %quest' WHERE `id`=432; -UPDATE `ai_playerbot_texts` SET `id`=433, `text_loc2`='Je ne peux pas prendre %quest' WHERE `id`=433; -UPDATE `ai_playerbot_texts` SET `id`=434, `text_loc2`='Je ne peux pas prendre %quest, mon journal de quêtes est plein' WHERE `id`=434; -UPDATE `ai_playerbot_texts` SET `id`=435, `text_loc2`='Je ne peux pas prendre %quest, mes sacs sont pleins' WHERE `id`=435; -UPDATE `ai_playerbot_texts` SET `id`=436, `text_loc2`='J’ai accepté la quête %quest' WHERE `id`=436; -UPDATE `ai_playerbot_texts` SET `id`=437, `text_loc2`='Je n’ai pas encore terminé la quête %quest' WHERE `id`=437; -UPDATE `ai_playerbot_texts` SET `id`=438, `text_loc2`='La quête %quest est dispo' WHERE `id`=438; -UPDATE `ai_playerbot_texts` SET `id`=439, `text_loc2`='J’ai échoué à la quête %quest' WHERE `id`=439; -UPDATE `ai_playerbot_texts` SET `id`=440, `text_loc2`='Je ne peux pas rendre la quête %quest' WHERE `id`=440; -UPDATE `ai_playerbot_texts` SET `id`=441, `text_loc2`='J’ai terminé la quête %quest' WHERE `id`=441; -UPDATE `ai_playerbot_texts` SET `id`=442, `text_loc2`='J’ai terminé la quête %quest et reçu %item' WHERE `id`=442; -UPDATE `ai_playerbot_texts` SET `id`=443, `text_loc2`='Quelle récompense devrais-je choisir pour la quête %quest ? %rewards' WHERE `id`=443; -UPDATE `ai_playerbot_texts` SET `id`=444, `text_loc2`='OK, je vais prendre %item comme récompense' WHERE `id`=444; -UPDATE `ai_playerbot_texts` SET `id`=445, `text_loc2`='Bonjour' WHERE `id`=445; -UPDATE `ai_playerbot_texts` SET `id`=446, `text_loc2`='Bonjour !' WHERE `id`=446; -UPDATE `ai_playerbot_texts` SET `id`=447, `text_loc2`='Salut' WHERE `id`=447; -UPDATE `ai_playerbot_texts` SET `id`=448, `text_loc2`='Salut !' WHERE `id`=448; -UPDATE `ai_playerbot_texts` SET `id`=449, `text_loc2`='Salut à toi !' WHERE `id`=449; -UPDATE `ai_playerbot_texts` SET `id`=450, `text_loc2`='Bonjour, je vous suis !' WHERE `id`=450; -UPDATE `ai_playerbot_texts` SET `id`=451, `text_loc2`='Bonjour, montrez-moi le chemin !' WHERE `id`=451; -UPDATE `ai_playerbot_texts` SET `id`=452, `text_loc2`='Salut, montre-moi le chemin !' WHERE `id`=452; -UPDATE `ai_playerbot_texts` SET `id`=453, `text_loc2`='Hey %player, tu veux rejoindre mon groupe ?' WHERE `id`=453; -UPDATE `ai_playerbot_texts` SET `id`=454, `text_loc2`='Hey %player, tu veux rejoindre mon groupe ?' WHERE `id`=454; -UPDATE `ai_playerbot_texts` SET `id`=455, `text_loc2`='Déconnexion annulée !' WHERE `id`=455; -UPDATE `ai_playerbot_texts` SET `id`=456, `text_loc2`='Je me déconnecte !' WHERE `id`=456; -UPDATE `ai_playerbot_texts` SET `id`=457, `text_loc2`='Au revoir !' WHERE `id`=457; -UPDATE `ai_playerbot_texts` SET `id`=458, `text_loc2`='Bye bye !' WHERE `id`=458; -UPDATE `ai_playerbot_texts` SET `id`=459, `text_loc2`='À plus tard !' WHERE `id`=459; -UPDATE `ai_playerbot_texts` SET `id`=460, `text_loc2`='c’était quoi ce truc %s ?' WHERE `id`=460; -UPDATE `ai_playerbot_texts` SET `id`=461, `text_loc2`='pas sûr d’avoir compris %s ?' WHERE `id`=461; -UPDATE `ai_playerbot_texts` SET `id`=462, `text_loc2`='euh… j’ai aucune idée de ce que tu racontes' WHERE `id`=462; -UPDATE `ai_playerbot_texts` SET `id`=463, `text_loc2`='tu parles à moi, %s ?' WHERE `id`=463; -UPDATE `ai_playerbot_texts` SET `id`=464, `text_loc2`='whaaaa ?' WHERE `id`=464; -UPDATE `ai_playerbot_texts` SET `id`=465, `text_loc2`='hein ?' WHERE `id`=465; -UPDATE `ai_playerbot_texts` SET `id`=466, `text_loc2`='quoi ?' WHERE `id`=466; -UPDATE `ai_playerbot_texts` SET `id`=467, `text_loc2`='tu parles ou tu râles ?' WHERE `id`=467; -UPDATE `ai_playerbot_texts` SET `id`=468, `text_loc2`='comme tu veux, mec' WHERE `id`=468; -UPDATE `ai_playerbot_texts` SET `id`=469, `text_loc2`='tu m’as perdu là' WHERE `id`=469; -UPDATE `ai_playerbot_texts` SET `id`=470, `text_loc2`='Bla bla bla…' WHERE `id`=470; -UPDATE `ai_playerbot_texts` SET `id`=471, `text_loc2`='T’as dit quoi, %s ?' WHERE `id`=471; -UPDATE `ai_playerbot_texts` SET `id`=472, `text_loc2`='Concentre-toi sur le jeu, %s !' WHERE `id`=472; -UPDATE `ai_playerbot_texts` SET `id`=473, `text_loc2`='Parler avec toi %s, c’est génial ! J’ai toujours rêvé de te rencontrer' WHERE `id`=473; -UPDATE `ai_playerbot_texts` SET `id`=474, `text_loc2`='Ces messages me font flipper ! J’ai l’impression de tous vous connaître !' WHERE `id`=474; -UPDATE `ai_playerbot_texts` SET `id`=475, `text_loc2`='Ouais bien sûr ! HAHA ! C’est ça, allez !' WHERE `id`=475; -UPDATE `ai_playerbot_texts` SET `id`=476, `text_loc2`='Je te crois !!! (ou pas)' WHERE `id`=476; -UPDATE `ai_playerbot_texts` SET `id`=477, `text_loc2`='OK, uhuh LOL' WHERE `id`=477; -UPDATE `ai_playerbot_texts` SET `id`=478, `text_loc2`='Pourquoi tout le monde dit toujours les mêmes trucs ???' WHERE `id`=478; -UPDATE `ai_playerbot_texts` SET `id`=479, `text_loc2`='Hey %s… euh, laisse tomber !' WHERE `id`=479; -UPDATE `ai_playerbot_texts` SET `id`=480, `text_loc2`='Tu parles de quoi %s ? Sérieux ?' WHERE `id`=480; -UPDATE `ai_playerbot_texts` SET `id`=481, `text_loc2`='Qui a dit ça ? Je me sens visé là' WHERE `id`=481; -UPDATE `ai_playerbot_texts` SET `id`=482, `text_loc2`='wtf vous racontez tous là ?' WHERE `id`=482; -UPDATE `ai_playerbot_texts` SET `id`=483, `text_loc2`='fr fr no cap on a stack' WHERE `id`=483; -UPDATE `ai_playerbot_texts` SET `id`=484, `text_loc2`='t’auras que dalle' WHERE `id`=484; -UPDATE `ai_playerbot_texts` SET `id`=485, `text_loc2`='swag' WHERE `id`=485; -UPDATE `ai_playerbot_texts` SET `id`=486, `text_loc2`='merci !' WHERE `id`=486; -UPDATE `ai_playerbot_texts` SET `id`=487, `text_loc2`='non' WHERE `id`=487; -UPDATE `ai_playerbot_texts` SET `id`=488, `text_loc2`='Yep' WHERE `id`=488; -UPDATE `ai_playerbot_texts` SET `id`=489, `text_loc2`='Paix à son ame.' WHERE `id`=489; -UPDATE `ai_playerbot_texts` SET `id`=490, `text_loc2`='%s sans déconner xD' WHERE `id`=490; -UPDATE `ai_playerbot_texts` SET `id`=491, `text_loc2`='pourquoi ça ?' WHERE `id`=491; -UPDATE `ai_playerbot_texts` SET `id`=492, `text_loc2`='mdr' WHERE `id`=492; -UPDATE `ai_playerbot_texts` SET `id`=493, `text_loc2`='Je pensais fermer ma gueule, j’ai encore rien compris au chat' WHERE `id`=493; -UPDATE `ai_playerbot_texts` SET `id`=494, `text_loc2`='Je peux devenir vraiment jaloux... comme un elfe sans loot' WHERE `id`=494; -UPDATE `ai_playerbot_texts` SET `id`=495, `text_loc2`='%s tu captes pas le sarcasme qui dégouline de mon message là ?' WHERE `id`=495; -UPDATE `ai_playerbot_texts` SET `id`=496, `text_loc2`='Il a dit "no homo", donc c’est bon apparemment' WHERE `id`=496; -UPDATE `ai_playerbot_texts` SET `id`=497, `text_loc2`='Instant nain™' WHERE `id`=497; -UPDATE `ai_playerbot_texts` SET `id`=498, `text_loc2`='Oui %s' WHERE `id`=498; -UPDATE `ai_playerbot_texts` SET `id`=499, `text_loc2`='Intéressant… ou pas' WHERE `id`=499; -UPDATE `ai_playerbot_texts` SET `id`=500, `text_loc2`='lol' WHERE `id`=500; -UPDATE `ai_playerbot_texts` SET `id`=501, `text_loc2`='%s va te faire voir mec :D' WHERE `id`=501; -UPDATE `ai_playerbot_texts` SET `id`=502, `text_loc2`=':^)' WHERE `id`=502; -UPDATE `ai_playerbot_texts` SET `id`=503, `text_loc2`='merci' WHERE `id`=503; -UPDATE `ai_playerbot_texts` SET `id`=504, `text_loc2`='%s bien dit !' WHERE `id`=504; -UPDATE `ai_playerbot_texts` SET `id`=505, `text_loc2`='ouiiiii' WHERE `id`=505; -UPDATE `ai_playerbot_texts` SET `id`=506, `text_loc2`='ouais' WHERE `id`=506; -UPDATE `ai_playerbot_texts` SET `id`=507, `text_loc2`='ooooooh (ça sent le loot !)' WHERE `id`=507; -UPDATE `ai_playerbot_texts` SET `id`=508, `text_loc2`='hmm… je réfléchis. Ou pas.' WHERE `id`=508; -UPDATE `ai_playerbot_texts` SET `id`=509, `text_loc2`='ouais c’est ça' WHERE `id`=509; -UPDATE `ai_playerbot_texts` SET `id`=510, `text_loc2`='t’as failli me faire vomir, wtf' WHERE `id`=510; -UPDATE `ai_playerbot_texts` SET `id`=511, `text_loc2`='chaud !' WHERE `id`=511; -UPDATE `ai_playerbot_texts` SET `id`=512, `text_loc2`='les rageux pleurent' WHERE `id`=512; -UPDATE `ai_playerbot_texts` SET `id`=513, `text_loc2`='T’as mangé quoi %s ? Des cailloux ?' WHERE `id`=513; -UPDATE `ai_playerbot_texts` SET `id`=514, `text_loc2`='wtf' WHERE `id`=514; -UPDATE `ai_playerbot_texts` SET `id`=515, `text_loc2`='Je vais essayer de comprendre ce que t’as dit… courage à moi' WHERE `id`=515; -UPDATE `ai_playerbot_texts` SET `id`=516, `text_loc2`='confus' WHERE `id`=516; -UPDATE `ai_playerbot_texts` SET `id`=517, `text_loc2`='putain ouais' WHERE `id`=517; -UPDATE `ai_playerbot_texts` SET `id`=518, `text_loc2`='0/10 ne lirait pas ça une deuxième fois' WHERE `id`=518; -UPDATE `ai_playerbot_texts` SET `id`=519, `text_loc2`='10/10 je relis direct' WHERE `id`=519; -UPDATE `ai_playerbot_texts` SET `id`=520, `text_loc2`='6/10 ouais, pourquoi pas' WHERE `id`=520; -UPDATE `ai_playerbot_texts` SET `id`=521, `text_loc2`='7/10 ça passe' WHERE `id`=521; -UPDATE `ai_playerbot_texts` SET `id`=522, `text_loc2`='basé' WHERE `id`=522; -UPDATE `ai_playerbot_texts` SET `id`=523, `text_loc2`='ah ouais peut-être' WHERE `id`=523; -UPDATE `ai_playerbot_texts` SET `id`=524, `text_loc2`='ouais, et alors ?' WHERE `id`=524; -UPDATE `ai_playerbot_texts` SET `id`=525, `text_loc2`='hey %s je t’ai pas oublié' WHERE `id`=525; -UPDATE `ai_playerbot_texts` SET `id`=526, `text_loc2`='tu m’énerves %s' WHERE `id`=526; -UPDATE `ai_playerbot_texts` SET `id`=527, `text_loc2`='je vais t’avoir cette fois %s' WHERE `id`=527; -UPDATE `ai_playerbot_texts` SET `id`=528, `text_loc2`='garde un œil derrière toi %s' WHERE `id`=528; -UPDATE `ai_playerbot_texts` SET `id`=529, `text_loc2`='J’ai pas trop aimé la manche d’avant' WHERE `id`=529; -UPDATE `ai_playerbot_texts` SET `id`=530, `text_loc2`='J’ai été nul à cause de %s la manche dernière' WHERE `id`=530; -UPDATE `ai_playerbot_texts` SET `id`=531, `text_loc2`='Prépare-toi à mourir %s' WHERE `id`=531; -UPDATE `ai_playerbot_texts` SET `id`=532, `text_loc2`='J’ai pas trop kiffé que tu me tues %s' WHERE `id`=532; -UPDATE `ai_playerbot_texts` SET `id`=533, `text_loc2`='%s, je te hais' WHERE `id`=533; -UPDATE `ai_playerbot_texts` SET `id`=534, `text_loc2`='grrrrr je vais t’avoir cette fois %s' WHERE `id`=534; -UPDATE `ai_playerbot_texts` SET `id`=535, `text_loc2`='eh bien va te faire voir' WHERE `id`=535; -UPDATE `ai_playerbot_texts` SET `id`=536, `text_loc2`='%s je vais vomir dans ta sale bouche' WHERE `id`=536; -UPDATE `ai_playerbot_texts` SET `id`=537, `text_loc2`='me juge pas bordel' WHERE `id`=537; -UPDATE `ai_playerbot_texts` SET `id`=538, `text_loc2`='Ta mère est tellement grosse qu’elle passe même pas le Portail des Ténèbres' WHERE `id`=538; -UPDATE `ai_playerbot_texts` SET `id`=539, `text_loc2`='wtf' WHERE `id`=539; -UPDATE `ai_playerbot_texts` SET `id`=540, `text_loc2`='wtf ??' WHERE `id`=540; -UPDATE `ai_playerbot_texts` SET `id`=541, `text_loc2`='vie misérable' WHERE `id`=541; -UPDATE `ai_playerbot_texts` SET `id`=542, `text_loc2`='qu’est-ce qui se passe là ?' WHERE `id`=542; -UPDATE `ai_playerbot_texts` SET `id`=543, `text_loc2`='nul à chier' WHERE `id`=543; -UPDATE `ai_playerbot_texts` SET `id`=544, `text_loc2`='REVANCHE !!! Je vais l’éclater' WHERE `id`=544; -UPDATE `ai_playerbot_texts` SET `id`=545, `text_loc2`='pathétique, je me suis fait tuer par %s' WHERE `id`=545; -UPDATE `ai_playerbot_texts` SET `id`=546, `text_loc2`='ok j’en ai fini' WHERE `id`=546; -UPDATE `ai_playerbot_texts` SET `id`=547, `text_loc2`='hé hé, j’ai explosé %s ?' WHERE `id`=547; -UPDATE `ai_playerbot_texts` SET `id`=548, `text_loc2`='C’était trop facile, exploser %s' WHERE `id`=548; -UPDATE `ai_playerbot_texts` SET `id`=549, `text_loc2`='T’es grillé, clochard' WHERE `id`=549; -UPDATE `ai_playerbot_texts` SET `id`=550, `text_loc2`='ha ha' WHERE `id`=550; -UPDATE `ai_playerbot_texts` SET `id`=551, `text_loc2`='Loser' WHERE `id`=551; -UPDATE `ai_playerbot_texts` SET `id`=552, `text_loc2`='J’ai tué %s et vous êtes tous les prochains, les gars' WHERE `id`=552; -UPDATE `ai_playerbot_texts` SET `id`=553, `text_loc2`='Oh ouais, je l’ai éclaté' WHERE `id`=553; -UPDATE `ai_playerbot_texts` SET `id`=554, `text_loc2`='Je suis une machine à tuer' WHERE `id`=554; -UPDATE `ai_playerbot_texts` SET `id`=555, `text_loc2`='%s, ça me rappelle un morceau de Slayer… tout ce sang, c’est beau' WHERE `id`=555; -UPDATE `ai_playerbot_texts` SET `id`=556, `text_loc2`='Désolé %s. On peut refaire la scène ? Avec plus de drama ?' WHERE `id`=556; -UPDATE `ai_playerbot_texts` SET `id`=557, `text_loc2`='Alors %s… ça fait quoi de nourrir les vers ???' WHERE `id`=557; -UPDATE `ai_playerbot_texts` SET `id`=558, `text_loc2`='T’étais censé être mort %s ! C’est dans le script bon sang !' WHERE `id`=558; -UPDATE `ai_playerbot_texts` SET `id`=559, `text_loc2`='Désolé %s. Franchement, c’était aussi beau qu’un Warhol !' WHERE `id`=559; -UPDATE `ai_playerbot_texts` SET `id`=560, `text_loc2`='%s, je prendrai les balles en caoutchouc la prochaine fois, promis !' WHERE `id`=560; -UPDATE `ai_playerbot_texts` SET `id`=561, `text_loc2`='Qu’est-ce qu’il y a %s ?? T’as perdu la tête ? Hahaha, faut rester cool !' WHERE `id`=561; -UPDATE `ai_playerbot_texts` SET `id`=562, `text_loc2`='Fallait que je le fasse %s… Le Réalisateur me l’a dit !' WHERE `id`=562; -UPDATE `ai_playerbot_texts` SET `id`=563, `text_loc2`='Hey %s… MUAHAHAHAHAHAHAHAHAHAHA' WHERE `id`=563; -UPDATE `ai_playerbot_texts` SET `id`=564, `text_loc2`='%s, celle-là, je l’ai savourée !! Allez, on recommence Sam !' WHERE `id`=564; -UPDATE `ai_playerbot_texts` SET `id`=565, `text_loc2`='Hey %s ! Tu peux commencer à m’appeler Scarface… espèce de M…erde !' WHERE `id`=565; -UPDATE `ai_playerbot_texts` SET `id`=566, `text_loc2`='Tu me parles à moi %s ?? Tu me parles à MOI ?!' WHERE `id`=566; -UPDATE `ai_playerbot_texts` SET `id`=567, `text_loc2`='%s, fais-le bien cette fois, évite MES balles' WHERE `id`=567; -UPDATE `ai_playerbot_texts` SET `id`=568, `text_loc2`='%s, pourquoi tu traînes par terre ? Allez bouge, clown !' WHERE `id`=568; -UPDATE `ai_playerbot_texts` SET `id`=569, `text_loc2`='J’ai rigolé comme jamais' WHERE `id`=569; -UPDATE `ai_playerbot_texts` SET `id`=570, `text_loc2`='Salut %s' WHERE `id`=570; -UPDATE `ai_playerbot_texts` SET `id`=571, `text_loc2`='Oh, salut %s' WHERE `id`=571; -UPDATE `ai_playerbot_texts` SET `id`=572, `text_loc2`='Wazzup %s !!!' WHERE `id`=572; -UPDATE `ai_playerbot_texts` SET `id`=573, `text_loc2`='Salut' WHERE `id`=573; -UPDATE `ai_playerbot_texts` SET `id`=574, `text_loc2`='Wazzup' WHERE `id`=574; -UPDATE `ai_playerbot_texts` SET `id`=575, `text_loc2`='Bonjour %s' WHERE `id`=575; -UPDATE `ai_playerbot_texts` SET `id`=576, `text_loc2`='Salut %s, je te connais ?' WHERE `id`=576; -UPDATE `ai_playerbot_texts` SET `id`=577, `text_loc2`='Hey %s' WHERE `id`=577; -UPDATE `ai_playerbot_texts` SET `id`=578, `text_loc2`='Hai %s' WHERE `id`=578; -UPDATE `ai_playerbot_texts` SET `id`=579, `text_loc2`='c’est quoi ce délire' WHERE `id`=579; -UPDATE `ai_playerbot_texts` SET `id`=580, `text_loc2`='wtf' WHERE `id`=580; -UPDATE `ai_playerbot_texts` SET `id`=581, `text_loc2`='c’est du foutage de gueule' WHERE `id`=581; -UPDATE `ai_playerbot_texts` SET `id`=582, `text_loc2`='admin' WHERE `id`=582; -UPDATE `ai_playerbot_texts` SET `id`=583, `text_loc2`='Hey %s, arrête d’abuser de ton admin là' WHERE `id`=583; -UPDATE `ai_playerbot_texts` SET `id`=584, `text_loc2`='Lâche-moi admin !' WHERE `id`=584; -UPDATE `ai_playerbot_texts` SET `id`=585, `text_loc2`='T’es nul admin' WHERE `id`=585; -UPDATE `ai_playerbot_texts` SET `id`=586, `text_loc2`='C’est mon nom ça, tu veux quoi %s ?' WHERE `id`=586; -UPDATE `ai_playerbot_texts` SET `id`=587, `text_loc2`='Oui ???' WHERE `id`=587; -UPDATE `ai_playerbot_texts` SET `id`=588, `text_loc2`='Euh… quoi ?' WHERE `id`=588; -UPDATE `ai_playerbot_texts` SET `id`=589, `text_loc2`='Tu me parles à moi %s ?' WHERE `id`=589; -UPDATE `ai_playerbot_texts` SET `id`=590, `text_loc2`='J’ai des chiots sous mon armure ! (ne demande pas)' WHERE `id`=590; -UPDATE `ai_playerbot_texts` SET `id`=591, `text_loc2`='Mords-moi, !' WHERE `id`=591; -UPDATE `ai_playerbot_texts` SET `id`=592, `text_loc2`='Hey ! Devine ce que ta mère a dit hier soir !' WHERE `id`=592; -UPDATE `ai_playerbot_texts` SET `id`=593, `text_loc2`=', t’es tellement moche que tu pourrais même pas scorer dans un bordel de singes avec un sac de bananes !' WHERE `id`=593; -UPDATE `ai_playerbot_texts` SET `id`=594, `text_loc2`='Tais-toi , tu seras jamais l’homme que ta mère est !!' WHERE `id`=594; -UPDATE `ai_playerbot_texts` SET `id`=595, `text_loc2`='Ta mère était un hamster et ton père sentait la surette !' WHERE `id`=595; -UPDATE `ai_playerbot_texts` SET `id`=596, `text_loc2`='Je ne veux plus te parler, espèce de vide-écuelle à bestiaux débiles !!!' WHERE `id`=596; -UPDATE `ai_playerbot_texts` SET `id`=597, `text_loc2`='Je pète dans ta direction générale !!!' WHERE `id`=597; -UPDATE `ai_playerbot_texts` SET `id`=598, `text_loc2`='Va faire bouillir ton postérieur, fils d’un imbécile cosmique !!!' WHERE `id`=598; -UPDATE `ai_playerbot_texts` SET `id`=599, `text_loc2`='Tu comptes faire quoi , saigner sur moi ? ALLEZ, VIENS !' WHERE `id`=599; -UPDATE `ai_playerbot_texts` SET `id`=600, `text_loc2`='M-O-O-N ! Ça veut dire aggro !' WHERE `id`=600; -UPDATE `ai_playerbot_texts` SET `id`=601, `text_loc2`='T’es aussi utile qu’un unijambiste dans un concours de coups de pied au cul' WHERE `id`=601; -UPDATE `ai_playerbot_texts` SET `id`=602, `text_loc2`='Hey ! Arrête de draguer, c’est pas ton genre. C’est pas gonflable.' WHERE `id`=602; -UPDATE `ai_playerbot_texts` SET `id`=603, `text_loc2`=', t’es tellement hors catégorie que tu joues carrément à un autre sport' WHERE `id`=603; -UPDATE `ai_playerbot_texts` SET `id`=604, `text_loc2`='Tu as fait une grosse erreur aujourd’hui … t’es sorti du lit.' WHERE `id`=604; -UPDATE `ai_playerbot_texts` SET `id`=605, `text_loc2`='Je veux essayer de me transformer en cheval. Je prends l’avant, et toi… tu restes toi.' WHERE `id`=605; -UPDATE `ai_playerbot_texts` SET `id`=606, `text_loc2`='Je peux emprunter ton visage ? Mon cul part en vacances.' WHERE `id`=606; -UPDATE `ai_playerbot_texts` SET `id`=607, `text_loc2`='J’aimerais t’offrir un cadeau de départ… d’abord, fais ta part.' WHERE `id`=607; -UPDATE `ai_playerbot_texts` SET `id`=608, `text_loc2`='Avant que t’arrives, on avait faim. Maintenant on en a juste marre.' WHERE `id`=608; -UPDATE `ai_playerbot_texts` SET `id`=609, `text_loc2`='Je t’aime bien. Les gens disent que j’ai mauvais goût, mais je t’aime bien.' WHERE `id`=609; -UPDATE `ai_playerbot_texts` SET `id`=610, `text_loc2`='Je pense que t’as un complexe d’infériorité… mais t’inquiète, il est mérité.' WHERE `id`=610; -UPDATE `ai_playerbot_texts` SET `id`=611, `text_loc2`='Arrière, créature pourrie ! Ou je secoue tes os hors de ta tunique !' WHERE `id`=611; -UPDATE `ai_playerbot_texts` SET `id`=612, `text_loc2`='Je crois pas que je perds mon temps avec toi… et pourtant !' WHERE `id`=612; -UPDATE `ai_playerbot_texts` SET `id`=613, `text_loc2`='J’adore quand on m’insulte : j’ai plus besoin d’être poli.' WHERE `id`=613; -UPDATE `ai_playerbot_texts` SET `id`=614, `text_loc2`='Espèce de veston de cuir, boutons en cristal, tête nouée, braillard à gerbe, jarretière de puce, langue mielleuse, bourse espagnole !' WHERE `id`=614; -UPDATE `ai_playerbot_texts` SET `id`=615, `text_loc2`='Espèce de pleurnichard, chasseur de chauve-souris, ivrogne de malte !' WHERE `id`=615; -UPDATE `ai_playerbot_texts` SET `id`=616, `text_loc2`='T’es vraiment une idole pour les adorateurs de l’idiotie !' WHERE `id`=616; -UPDATE `ai_playerbot_texts` SET `id`=617, `text_loc2`='Misérable piaf mal dégrossi !' WHERE `id`=617; -UPDATE `ai_playerbot_texts` SET `id`=618, `text_loc2`='Fils de mandragore ! T’es plus utile en plumeau qu’en laquais !' WHERE `id`=618; -UPDATE `ai_playerbot_texts` SET `id`=619, `text_loc2`='Toi ! Gueux ! Cloporte ! Tarlouze ! Je vais chatouiller ta catastrophe !' WHERE `id`=619; -UPDATE `ai_playerbot_texts` SET `id`=620, `text_loc2`='Oh ! Infâme fille de lin mal élevé !' WHERE `id`=620; -UPDATE `ai_playerbot_texts` SET `id`=621, `text_loc2`='On fuit par ta cheminée, !' WHERE `id`=621; -UPDATE `ai_playerbot_texts` SET `id`=622, `text_loc2`='Oh toi, misérable fleur de cancre gorgée de marais !' WHERE `id`=622; -UPDATE `ai_playerbot_texts` SET `id`=623, `text_loc2`='Si j’étais comme toi, je me jetterais à la poubelle.' WHERE `id`=623; -UPDATE `ai_playerbot_texts` SET `id`=624, `text_loc2`='Apprends-moi … à ne plus penser du tout.' WHERE `id`=624; -UPDATE `ai_playerbot_texts` SET `id`=625, `text_loc2`='T’es maudit comme un œuf mal rôti… tout cramé d’un côté.' WHERE `id`=625; -UPDATE `ai_playerbot_texts` SET `id`=626, `text_loc2`='Espèce de gringalet, de peau de hareng, de langue de bœuf séchée, de… souffle… taureau démembré, morceau de corde ! Queue d’épée, boîte à rien, tige de tailleur !' WHERE `id`=626; -UPDATE `ai_playerbot_texts` SET `id`=627, `text_loc2`='Fi ! Qu’on te jette dans la bouche pourrie de la Mort !' WHERE `id`=627; -UPDATE `ai_playerbot_texts` SET `id`=628, `text_loc2`=', t’es poissonnier, avoue !' WHERE `id`=628; -UPDATE `ai_playerbot_texts` SET `id`=629, `text_loc2`='Je vivrai assez pour te défoncer le crâne !' WHERE `id`=629; -UPDATE `ai_playerbot_texts` SET `id`=630, `text_loc2`='T’es aussi profond qu’une flaque ! , t’es bonne pour les vers, pas pour la viande !' WHERE `id`=630; -UPDATE `ai_playerbot_texts` SET `id`=631, `text_loc2`='Vermine ! Ô , espèce de noisette infernale puante !' WHERE `id`=631; -UPDATE `ai_playerbot_texts` SET `id`=632, `text_loc2`=' ! Ton baiser est aussi réconfortant qu’un glaçon pour un serpent affamé !' WHERE `id`=632; -UPDATE `ai_playerbot_texts` SET `id`=633, `text_loc2`='Je te méprise, compagnon galeux. Quoi, pauvre arnaqueur sans chemise ! Dégage, raclure moisie !' WHERE `id`=633; -UPDATE `ai_playerbot_texts` SET `id`=634, `text_loc2`='Hors de ma vue ! Tu infectes mes yeux !' WHERE `id`=634; -UPDATE `ai_playerbot_texts` SET `id`=635, `text_loc2`='HEURE DE JEU !!!!' WHERE `id`=635; -UPDATE `ai_playerbot_texts` SET `id`=636, `text_loc2`='Personne ne passera !' WHERE `id`=636; -UPDATE `ai_playerbot_texts` SET `id`=637, `text_loc2`='On est attaqués ! Hissez les voiles ! Repoussez les intrus !' WHERE `id`=637; -UPDATE `ai_playerbot_texts` SET `id`=638, `text_loc2`='Personne ne défie la Confrérie !' WHERE `id`=638; -UPDATE `ai_playerbot_texts` SET `id`=639, `text_loc2`='Imbéciles… tuez celui en robe !' WHERE `id`=639; -UPDATE `ai_playerbot_texts` SET `id`=640, `text_loc2`='Je vais offrir ton âme à Hakkar lui-même !' WHERE `id`=640; -UPDATE `ai_playerbot_texts` SET `id`=641, `text_loc2`='L’orgueil annonce la fin de ton monde ! Venez, mortels ! Affrontez la colère de la %randomfaction !' WHERE `id`=641; -UPDATE `ai_playerbot_texts` SET `id`=642, `text_loc2`='Tous mes plans menaient à CE moment !' WHERE `id`=642; -UPDATE `ai_playerbot_texts` SET `id`=643, `text_loc2`='Ahh ! Encore des agneaux pour l’abattoir !' WHERE `id`=643; -UPDATE `ai_playerbot_texts` SET `id`=644, `text_loc2`='Encore une journée, encore une glorieuse bataille !' WHERE `id`=644; -UPDATE `ai_playerbot_texts` SET `id`=645, `text_loc2`='Alors, affaires… ou plaisir ?' WHERE `id`=645; -UPDATE `ai_playerbot_texts` SET `id`=646, `text_loc2`='Vous n’êtes pas préparés !' WHERE `id`=646; -UPDATE `ai_playerbot_texts` SET `id`=647, `text_loc2`='La conquête finale de la %randomfaction a commencé ! Cette fois, aucun ne survivra !' WHERE `id`=647; -UPDATE `ai_playerbot_texts` SET `id`=648, `text_loc2`='Ta mort sera douloureuse.' WHERE `id`=648; -UPDATE `ai_playerbot_texts` SET `id`=649, `text_loc2`='Implore pitié ! Tes vies inutiles vont être sacrifiées.' WHERE `id`=649; -UPDATE `ai_playerbot_texts` SET `id`=650, `text_loc2`='Abandonne tout espoir ! La %randomfaction est revenue pour finir ce qui a commencé… et cette fois, pas d’échappatoire !' WHERE `id`=650; -UPDATE `ai_playerbot_texts` SET `id`=651, `text_loc2`='Alerte ! Tu es marqué pour l’EXTERMINATION !' WHERE `id`=651; -UPDATE `ai_playerbot_texts` SET `id`=652, `text_loc2`='Le %subzone est réservé aux invités seulement…' WHERE `id`=652; -UPDATE `ai_playerbot_texts` SET `id`=653, `text_loc2`='Ha ha ha ! Tu es totalement dépassé !' WHERE `id`=653; -UPDATE `ai_playerbot_texts` SET `id`=654, `text_loc2`='Je vais écraser tes illusions de grandeur !' WHERE `id`=654; -UPDATE `ai_playerbot_texts` SET `id`=655, `text_loc2`='Pardonne-moi, mais tu vas perdre cette partie.' WHERE `id`=655; -UPDATE `ai_playerbot_texts` SET `id`=656, `text_loc2`='Résister ne fait qu’empirer les choses.' WHERE `id`=656; -UPDATE `ai_playerbot_texts` SET `id`=657, `text_loc2`='Vermine ! Sangsues ! Prends mon sang et étouffe-toi avec !' WHERE `id`=657; -UPDATE `ai_playerbot_texts` SET `id`=658, `text_loc2`='Pas encore… PAS ENCORE !' WHERE `id`=658; -UPDATE `ai_playerbot_texts` SET `id`=659, `text_loc2`='Mon sang sera ta perte !' WHERE `id`=659; -UPDATE `ai_playerbot_texts` SET `id`=660, `text_loc2`='Parfait. Maintenant bats-toi contre moi !' WHERE `id`=660; -UPDATE `ai_playerbot_texts` SET `id`=661, `text_loc2`='Allez les gardes ! C’est l’heure de tuer !' WHERE `id`=661; -UPDATE `ai_playerbot_texts` SET `id`=662, `text_loc2`='N’attends pas la mort, viens à moi. Je rendrai ton sacrifice rapide.' WHERE `id`=662; -UPDATE `ai_playerbot_texts` SET `id`=663, `text_loc2`='Tu seras mort très bientôt !' WHERE `id`=663; -UPDATE `ai_playerbot_texts` SET `id`=664, `text_loc2`='Mouahaha !' WHERE `id`=664; -UPDATE `ai_playerbot_texts` SET `id`=665, `text_loc2`='C’est moi le prédateur ! Toi, la proie...' WHERE `id`=665; -UPDATE `ai_playerbot_texts` SET `id`=666, `text_loc2`='Tu vas repartir en morceaux !' WHERE `id`=666; -UPDATE `ai_playerbot_texts` SET `id`=667, `text_loc2`='La mort approche... As-tu la conscience tranquille ?' WHERE `id`=667; -UPDATE `ai_playerbot_texts` SET `id`=668, `text_loc2`='Ton comportement ne sera pas toléré.' WHERE `id`=668; -UPDATE `ai_playerbot_texts` SET `id`=669, `text_loc2`='La Ménagerie est réservée aux invités.' WHERE `id`=669; -UPDATE `ai_playerbot_texts` SET `id`=670, `text_loc2`='Hmm, des visiteurs non annoncés… Il faut se préparer…' WHERE `id`=670; -UPDATE `ai_playerbot_texts` SET `id`=671, `text_loc2`='Entités hostiles détectées. Évaluation de menace en cours. Cible principale verrouillée. Réévaluation dans trente secondes.' WHERE `id`=671; -UPDATE `ai_playerbot_texts` SET `id`=672, `text_loc2`='Des nouveaux jouets ? Pour moi ? Promis, je les casse pas… cette fois !' WHERE `id`=672; -UPDATE `ai_playerbot_texts` SET `id`=673, `text_loc2`='Je suis prêt à jouer !' WHERE `id`=673; -UPDATE `ai_playerbot_texts` SET `id`=674, `text_loc2`='Chut… tout sera fini bientôt.' WHERE `id`=674; -UPDATE `ai_playerbot_texts` SET `id`=675, `text_loc2`='Aaaaaughibbrgubugbugrguburgle !' WHERE `id`=675; -UPDATE `ai_playerbot_texts` SET `id`=676, `text_loc2`='RwlRwlRwlRwl !' WHERE `id`=676; -UPDATE `ai_playerbot_texts` SET `id`=677, `text_loc2`='Toi aussi, tu serviras !' WHERE `id`=677; -UPDATE `ai_playerbot_texts` SET `id`=678, `text_loc2`='Dis-moi... dis-moi tout ! Tes vilains petits secrets ! Je vais les arracher de ta chair !' WHERE `id`=678; -UPDATE `ai_playerbot_texts` SET `id`=679, `text_loc2`='Préparez-vous, les cloches ont sonné ! Protégez vos faibles, vos jeunes et vos vieux ! Chacun paiera le prix final ! Implorerez-vous pitié ? Le Jugement est arrivé !' WHERE `id`=679; -UPDATE `ai_playerbot_texts` SET `id`=680, `text_loc2`='Mais où suis-je, par les boutons en laiton de Bonzo ?' WHERE `id`=680; -UPDATE `ai_playerbot_texts` SET `id`=681, `text_loc2`='Je n’en peux plus ! Roi Gobelin ! Roi Gobelin ! Où que tu sois ! Emporte ce loin de moi !' WHERE `id`=681; -UPDATE `ai_playerbot_texts` SET `id`=682, `text_loc2`='Tu as treize heures pour résoudre le labyrinthe... sinon ton petit frère deviendra l’un des nôtres... pour toujours.' WHERE `id`=682; -UPDATE `ai_playerbot_texts` SET `id`=683, `text_loc2`='Alors, le c’est du gâteau, hein ? Voyons comment tu gères ce petit bout-là…' WHERE `id`=683; -UPDATE `ai_playerbot_texts` SET `id`=684, `text_loc2`='Recule, j’vais t’affronter. Déterminé, prêt à affronter n’importe qui. J’sais que t’as tort, t’as rien à faire ici !' WHERE `id`=684; -UPDATE `ai_playerbot_texts` SET `id`=685, `text_loc2`='Montre-moi c’que t’as dans le ventre !' WHERE `id`=685; -UPDATE `ai_playerbot_texts` SET `id`=686, `text_loc2`='Jusqu’à la mort !' WHERE `id`=686; -UPDATE `ai_playerbot_texts` SET `id`=687, `text_loc2`='Double lame, pour un rasage net à chaque fois !' WHERE `id`=687; -UPDATE `ai_playerbot_texts` SET `id`=688, `text_loc2`='Allez, viens !' WHERE `id`=688; -UPDATE `ai_playerbot_texts` SET `id`=689, `text_loc2`='Tu vas tomber !' WHERE `id`=689; -UPDATE `ai_playerbot_texts` SET `id`=690, `text_loc2`='Piou piou, coup de couteau !' WHERE `id`=690; -UPDATE `ai_playerbot_texts` SET `id`=691, `text_loc2`='Finissons-en vite, le temps c’est du mana.' WHERE `id`=691; -UPDATE `ai_playerbot_texts` SET `id`=692, `text_loc2`='Je ne crois pas que tu réalises dans quelle merde tu es.' WHERE `id`=692; -UPDATE `ai_playerbot_texts` SET `id`=693, `text_loc2`='Je vais faire honneur à ma famille et à mon royaume !' WHERE `id`=693; -UPDATE `ai_playerbot_texts` SET `id`=694, `text_loc2`='Lumière, donne-moi la force !' WHERE `id`=694; -UPDATE `ai_playerbot_texts` SET `id`=695, `text_loc2`='Mon église, c’est le champ de bataille – l’heure de la messe a sonné !' WHERE `id`=695; -UPDATE `ai_playerbot_texts` SET `id`=696, `text_loc2`='Je te tiens en mépris total…' WHERE `id`=696; -UPDATE `ai_playerbot_texts` SET `id`=697, `text_loc2`='Affronte le marteau de la justice !' WHERE `id`=697; -UPDATE `ai_playerbot_texts` SET `id`=698, `text_loc2`='Prouve ta valeur dans l’épreuve des armes, sous la Lumière !' WHERE `id`=698; -UPDATE `ai_playerbot_texts` SET `id`=699, `text_loc2`='Tous doivent tomber devant la puissance de ma cause – tu es le prochain !' WHERE `id`=699; -UPDATE `ai_playerbot_texts` SET `id`=700, `text_loc2`='Prépare-toi à mourir !' WHERE `id`=700; -UPDATE `ai_playerbot_texts` SET `id`=701, `text_loc2`='La bête en moi est bien pire que celle à mes côtés…' WHERE `id`=701; -UPDATE `ai_playerbot_texts` SET `id`=702, `text_loc2`='Admire la puissance de feu d’un chasseur totalement équipé !' WHERE `id`=702; -UPDATE `ai_playerbot_texts` SET `id`=703, `text_loc2`='Soigne-moi ! Vite !' WHERE `id`=703; -UPDATE `ai_playerbot_texts` SET `id`=704, `text_loc2`='Je suis presque mort ! Soignez-moi !' WHERE `id`=704; -UPDATE `ai_playerbot_texts` SET `id`=705, `text_loc2`='À l’aide ! Soignez-moi !' WHERE `id`=705; -UPDATE `ai_playerbot_texts` SET `id`=706, `text_loc2`='Quelqu’un ! Un soin vite !' WHERE `id`=706; -UPDATE `ai_playerbot_texts` SET `id`=707, `text_loc2`='Heal ! Heal ! Heal !' WHERE `id`=707; -UPDATE `ai_playerbot_texts` SET `id`=708, `text_loc2`='Je meurs ! Soin ! Aaaaarhg !' WHERE `id`=708; -UPDATE `ai_playerbot_texts` SET `id`=709, `text_loc2`='Soignez-moi !' WHERE `id`=709; -UPDATE `ai_playerbot_texts` SET `id`=710, `text_loc2`='Je vais mourir. Je vais mourir. Je vais mourir. Soignez-moi !' WHERE `id`=710; -UPDATE `ai_playerbot_texts` SET `id`=711, `text_loc2`='Healers, vous êtes où ? Je crève !' WHERE `id`=711; -UPDATE `ai_playerbot_texts` SET `id`=712, `text_loc2`='Ouille, la douleur ! Soignez vite !' WHERE `id`=712; -UPDATE `ai_playerbot_texts` SET `id`=713, `text_loc2`='Besoin de soin' WHERE `id`=713; -UPDATE `ai_playerbot_texts` SET `id`=714, `text_loc2`='Vie basse !' WHERE `id`=714; -UPDATE `ai_playerbot_texts` SET `id`=715, `text_loc2`='Lâche un heal. S’il te plaît.' WHERE `id`=715; -UPDATE `ai_playerbot_texts` SET `id`=716, `text_loc2`='Quelqu’un peut me balancer un soin ?' WHERE `id`=716; -UPDATE `ai_playerbot_texts` SET `id`=717, `text_loc2`='Hey ! Mieux vaut me soigner maintenant que me rez plus tard !' WHERE `id`=717; -UPDATE `ai_playerbot_texts` SET `id`=718, `text_loc2`='Désolé… mais encore un heal, please.' WHERE `id`=718; -UPDATE `ai_playerbot_texts` SET `id`=719, `text_loc2`='Saletés de mobs… heal moi vite !' WHERE `id`=719; -UPDATE `ai_playerbot_texts` SET `id`=720, `text_loc2`='Encore un coup et je suis mort. Un petit heal ?' WHERE `id`=720; -UPDATE `ai_playerbot_texts` SET `id`=721, `text_loc2`='Y’a des soigneurs dans cette galère ?' WHERE `id`=721; -UPDATE `ai_playerbot_texts` SET `id`=722, `text_loc2`='Pourquoi c’est toujours ma tête qu’ils frappent ? J’ai besoin d’un soin !' WHERE `id`=722; -UPDATE `ai_playerbot_texts` SET `id`=723, `text_loc2`='Quelqu’un pour me soigner un chouïa ?' WHERE `id`=723; -UPDATE `ai_playerbot_texts` SET `id`=724, `text_loc2`='OOM' WHERE `id`=724; -UPDATE `ai_playerbot_texts` SET `id`=725, `text_loc2`='Plus de mana !' WHERE `id`=725; -UPDATE `ai_playerbot_texts` SET `id`=726, `text_loc2`='J’ai cramé tout mon mana pour ça, sérieux...' WHERE `id`=726; -UPDATE `ai_playerbot_texts` SET `id`=727, `text_loc2`='Faudrait attendre que je boive ou que je régène, là…' WHERE `id`=727; -UPDATE `ai_playerbot_texts` SET `id`=728, `text_loc2`='Mana faible… très faible…' WHERE `id`=728; -UPDATE `ai_playerbot_texts` SET `id`=729, `text_loc2`='Encore à sec ? Pas de mana, encore.' WHERE `id`=729; -UPDATE `ai_playerbot_texts` SET `id`=730, `text_loc2`='Mana bas. Je veux une boisson !' WHERE `id`=730; -UPDATE `ai_playerbot_texts` SET `id`=731, `text_loc2`='On a une machine à boissons ? J’ai encore plus rien !' WHERE `id`=731; -UPDATE `ai_playerbot_texts` SET `id`=732, `text_loc2`='Mon mana ? Parti dans les limbes.' WHERE `id`=732; -UPDATE `ai_playerbot_texts` SET `id`=733, `text_loc2`='J’achèterai des boissons la prochaine fois. Là j’ai que dalle.' WHERE `id`=733; -UPDATE `ai_playerbot_texts` SET `id`=734, `text_loc2`='Où est passé mon mana ?' WHERE `id`=734; -UPDATE `ai_playerbot_texts` SET `id`=735, `text_loc2`='Il me reste quelques !' WHERE `id`=735; -UPDATE `ai_playerbot_texts` SET `id`=736, `text_loc2`='Besoin de plus de !' WHERE `id`=736; -UPDATE `ai_playerbot_texts` SET `id`=737, `text_loc2`='Plus que 100 !' WHERE `id`=737; -UPDATE `ai_playerbot_texts` SET `id`=738, `text_loc2`='C’est fini ! Plus un seul !' WHERE `id`=738; -UPDATE `ai_playerbot_texts` SET `id`=739, `text_loc2`='Et tu as mon arc… oups, plus de !' WHERE `id`=739; -UPDATE `ai_playerbot_texts` SET `id`=740, `text_loc2`='J’ai besoin de munitions !' WHERE `id`=740; -UPDATE `ai_playerbot_texts` SET `id`=741, `text_loc2`='Oh mon dieu !' WHERE `id`=741; -UPDATE `ai_playerbot_texts` SET `id`=742, `text_loc2`='J’ai peur… là… vraiment.' WHERE `id`=742; -UPDATE `ai_playerbot_texts` SET `id`=743, `text_loc2`='On est foutus !' WHERE `id`=743; -UPDATE `ai_playerbot_texts` SET `id`=744, `text_loc2`='C’est fini. F.I.N.I.' WHERE `id`=744; -UPDATE `ai_playerbot_texts` SET `id`=745, `text_loc2`='Ça se termine maintenant.' WHERE `id`=745; -UPDATE `ai_playerbot_texts` SET `id`=746, `text_loc2`='Quelqu’un peut balancer un blizzard ou un truc ?!' WHERE `id`=746; -UPDATE `ai_playerbot_texts` SET `id`=747, `text_loc2`='Mince. Le tank a aggro TOUT le monde…' WHERE `id`=747; -UPDATE `ai_playerbot_texts` SET `id`=748, `text_loc2`='On va mourir. On va mourir. On VA MOURIR !' WHERE `id`=748; -UPDATE `ai_playerbot_texts` SET `id`=749, `text_loc2`='Wow ! Tant de jouets à casser !' WHERE `id`=749; -UPDATE `ai_playerbot_texts` SET `id`=750, `text_loc2`='Je vais tous les buter ! TOUS !' WHERE `id`=750; -UPDATE `ai_playerbot_texts` SET `id`=751, `text_loc2`='Si le tank meurt, c’est foutu pour nous tous…' WHERE `id`=751; -UPDATE `ai_playerbot_texts` SET `id`=752, `text_loc2`='Aaaaaargh !' WHERE `id`=752; -UPDATE `ai_playerbot_texts` SET `id`=753, `text_loc2`='LEEEEERROOOYYYYYYYYYYYY JENNKINNNSSSSSS !!!!!!!!' WHERE `id`=753; -UPDATE `ai_playerbot_texts` SET `id`=754, `text_loc2`='Bon. Qu’est-ce qu’on a en AOE là ?' WHERE `id`=754; -UPDATE `ai_playerbot_texts` SET `id`=755, `text_loc2`='Ça devient intéressant…' WHERE `id`=755; -UPDATE `ai_playerbot_texts` SET `id`=756, `text_loc2`='Cool. Regroupez-les bien pour une jolie boule de feu !' WHERE `id`=756; -UPDATE `ai_playerbot_texts` SET `id`=757, `text_loc2`='TUEZ ! TUEZ ! TUEZ !' WHERE `id`=757; -UPDATE `ai_playerbot_texts` SET `id`=758, `text_loc2`='Je crois que j’ai mouillé mon pantalon…' WHERE `id`=758; -UPDATE `ai_playerbot_texts` SET `id`=759, `text_loc2`='C’est notre fin. C’était sympa.' WHERE `id`=759; -UPDATE `ai_playerbot_texts` SET `id`=760, `text_loc2`='J’espère que les healers sont prêts… LEEEEROYYYY !' WHERE `id`=760; -UPDATE `ai_playerbot_texts` SET `id`=761, `text_loc2`='Pourvu qu’ils ne me ciblent pas moi…' WHERE `id`=761; -UPDATE `ai_playerbot_texts` SET `id`=762, `text_loc2`='Oh non. Je peux pas regarder ce massacre…' WHERE `id`=762; -UPDATE `ai_playerbot_texts` SET `id`=763, `text_loc2`='J’espère qu’il y aura de la thune.' WHERE `id`=763; -UPDATE `ai_playerbot_texts` SET `id`=764, `text_loc2`='Loot ! LOOT !' WHERE `id`=764; -UPDATE `ai_playerbot_texts` SET `id`=765, `text_loc2`='Mon précieux…' WHERE `id`=765; -UPDATE `ai_playerbot_texts` SET `id`=766, `text_loc2`='J’espère qu’un bel objet épique m’attend là-dedans…' WHERE `id`=766; -UPDATE `ai_playerbot_texts` SET `id`=767, `text_loc2`='J’ai des poches profondes et des sacs encore vides.' WHERE `id`=767; -UPDATE `ai_playerbot_texts` SET `id`=768, `text_loc2`='Tout est à moi !' WHERE `id`=768; -UPDATE `ai_playerbot_texts` SET `id`=769, `text_loc2`='Pas de gris moisi aujourd’hui, pitié…' WHERE `id`=769; -UPDATE `ai_playerbot_texts` SET `id`=770, `text_loc2`='CE loot est À MOI !' WHERE `id`=770; -UPDATE `ai_playerbot_texts` SET `id`=771, `text_loc2`='Looter c’est sale… mais j’ai besoin de thunes.' WHERE `id`=771; -UPDATE `ai_playerbot_texts` SET `id`=772, `text_loc2`='De l’or !' WHERE `id`=772; -UPDATE `ai_playerbot_texts` SET `id`=773, `text_loc2`='Ok. Voyons ce qu’ils ont laissé…' WHERE `id`=773; -UPDATE `ai_playerbot_texts` SET `id`=774, `text_loc2`='T’inquiète, je vais tout looter. Tout.' WHERE `id`=774; -UPDATE `ai_playerbot_texts` SET `id`=775, `text_loc2`='Je suis un ninja du loot.' WHERE `id`=775; -UPDATE `ai_playerbot_texts` SET `id`=776, `text_loc2`='Je dois lancer les dés ?' WHERE `id`=776; -UPDATE `ai_playerbot_texts` SET `id`=777, `text_loc2`='Quelqu’un peut m’expliquer où ils ont rangé tout ça ?' WHERE `id`=777; -UPDATE `ai_playerbot_texts` SET `id`=778, `text_loc2`='Non, je loot pas cette merde grise.' WHERE `id`=778; -UPDATE `ai_playerbot_texts` SET `id`=779, `text_loc2`='C’est moi d’abord ! C’est moi ! MOI !' WHERE `id`=779; -UPDATE `ai_playerbot_texts` SET `id`=780, `text_loc2`='Donne-moi ton fric !' WHERE `id`=780; -UPDATE `ai_playerbot_texts` SET `id`=781, `text_loc2`='Mes poches sont vides, il faut les remplir.' WHERE `id`=781; -UPDATE `ai_playerbot_texts` SET `id`=782, `text_loc2`='J’ai un nouveau sac, il est fait pour ça.' WHERE `id`=782; -UPDATE `ai_playerbot_texts` SET `id`=783, `text_loc2`='J’espère que je vais pas aggro en lootant…' WHERE `id`=783; -UPDATE `ai_playerbot_texts` SET `id`=784, `text_loc2`='Ne regardez pas… je loot discret…' WHERE `id`=784; -UPDATE `ai_playerbot_texts` SET `id`=785, `text_loc2`='Ha ! Vous n’aurez rien de tout ça !' WHERE `id`=785; -UPDATE `ai_playerbot_texts` SET `id`=786, `text_loc2`='Le loot, c’est stylé.' WHERE `id`=786; -UPDATE `ai_playerbot_texts` SET `id`=787, `text_loc2`='J’adore les nouveaux équipements.' WHERE `id`=787; -UPDATE `ai_playerbot_texts` SET `id`=788, `text_loc2`='Je me casse si y’a encore rien de valeur…' WHERE `id`=788; -UPDATE `ai_playerbot_texts` SET `id`=789, `text_loc2`='J’espère que ce sera une jolie bague !' WHERE `id`=789; -UPDATE `ai_playerbot_texts` SET `id`=790, `text_loc2`='Je vais t’arracher le loot des mains !' WHERE `id`=790; -UPDATE `ai_playerbot_texts` SET `id`=791, `text_loc2`='Personne ne touche à rien. C’est MOI qui loot.' WHERE `id`=791; -UPDATE `ai_playerbot_texts` SET `id`=792, `text_loc2`='Loot sucré :D' WHERE `id`=792; -UPDATE `ai_playerbot_texts` SET `id`=793, `text_loc2`='Dieu du lancer, donne-moi un épique aujourd’hui…' WHERE `id`=793; -UPDATE `ai_playerbot_texts` SET `id`=794, `text_loc2`='Allez, de nouveaux jouets s’il vous plaît !' WHERE `id`=794; -UPDATE `ai_playerbot_texts` SET `id`=795, `text_loc2`='J’espère qu’ils ont des trucs savoureux…' WHERE `id`=795; -UPDATE `ai_playerbot_texts` SET `id`=796, `text_loc2`='L’or est à moi. Je laisse tout le reste… promis…' WHERE `id`=796; -UPDATE `ai_playerbot_texts` SET `id`=797, `text_loc2`='Non, je peux pas résister.' WHERE `id`=797; -UPDATE `ai_playerbot_texts` SET `id`=798, `text_loc2`='J’en veux ENCORE !' WHERE `id`=798; -UPDATE `ai_playerbot_texts` SET `id`=799, `text_loc2`='Je suis presque là, attendez-moi !' WHERE `id`=799; -UPDATE `ai_playerbot_texts` SET `id`=800, `text_loc2`='Je suis pas loin, attendez-moi !' WHERE `id`=800; -UPDATE `ai_playerbot_texts` SET `id`=801, `text_loc2`='J’arrive vers ta position' WHERE `id`=801; -UPDATE `ai_playerbot_texts` SET `id`=802, `text_loc2`='J’arrive vers toi' WHERE `id`=802; -UPDATE `ai_playerbot_texts` SET `id`=803, `text_loc2`='Je me dirige vers ta position' WHERE `id`=803; -UPDATE `ai_playerbot_texts` SET `id`=804, `text_loc2`='J’essaie de te rejoindre' WHERE `id`=804; -UPDATE `ai_playerbot_texts` SET `id`=805, `text_loc2`='Équipement de %item' WHERE `id`=805; -UPDATE `ai_playerbot_texts` SET `id`=806, `text_loc2`='%item retiré' WHERE `id`=806; -UPDATE `ai_playerbot_texts` SET `id`=807, `text_loc2`='J’ai appris les sorts : %spells' WHERE `id`=807; -UPDATE `ai_playerbot_texts` SET `id`=808, `text_loc2`='%item est en recharge' WHERE `id`=808; -UPDATE `ai_playerbot_texts` SET `id`=809, `text_loc2`='Je n’ai pas %item dans mon inventaire' WHERE `id`=809; -UPDATE `ai_playerbot_texts` SET `id`=810, `text_loc2`='L’objet avec l’ID %item n’existe pas' WHERE `id`=810; -UPDATE `ai_playerbot_texts` SET `id`=811, `text_loc2`='Insertion de %gem dans %item' WHERE `id`=811; -UPDATE `ai_playerbot_texts` SET `id`=812, `text_loc2`='Je ne peux pas utiliser %item' WHERE `id`=812; -UPDATE `ai_playerbot_texts` SET `id`=813, `text_loc2`='Suivi' WHERE `id`=813; -UPDATE `ai_playerbot_texts` SET `id`=814, `text_loc2`='Je reste ici' WHERE `id`=814; -UPDATE `ai_playerbot_texts` SET `id`=815, `text_loc2`='Je fuis' WHERE `id`=815; -UPDATE `ai_playerbot_texts` SET `id`=816, `text_loc2`='Je fuis pas avec toi, t’es trop loin !' WHERE `id`=816; -UPDATE `ai_playerbot_texts` SET `id`=817, `text_loc2`='Farm en cours' WHERE `id`=817; -UPDATE `ai_playerbot_texts` SET `id`=818, `text_loc2`='Attaque en cours' WHERE `id`=818; -UPDATE `ai_playerbot_texts` SET `id`=819, `text_loc2`='C’est trop loin' WHERE `id`=819; -UPDATE `ai_playerbot_texts` SET `id`=820, `text_loc2`='C’est sous l’eau' WHERE `id`=820; -UPDATE `ai_playerbot_texts` SET `id`=821, `text_loc2`='Je ne peux pas y aller' WHERE `id`=821; -UPDATE `ai_playerbot_texts` SET `id`=822, `text_loc2`='Je ne suis pas dans ta guilde !' WHERE `id`=822; -UPDATE `ai_playerbot_texts` SET `id`=823, `text_loc2`='Impossible de trouver une banque de guilde à proximité' WHERE `id`=823; -UPDATE `ai_playerbot_texts` SET `id`=824, `text_loc2`='Je ne peux pas déposer' WHERE `id`=824; -UPDATE `ai_playerbot_texts` SET `id`=825, `text_loc2`='Je n’ai pas les droits pour déposer dans le premier onglet de la banque de guilde' WHERE `id`=825; -UPDATE `ai_playerbot_texts` SET `id`=826, `text_loc2`='déposé dans la banque de guilde' WHERE `id`=826; -UPDATE `ai_playerbot_texts` SET `id`=827, `text_loc2`='Déplacement libre' WHERE `id`=827; -UPDATE `ai_playerbot_texts` SET `id`=828, `text_loc2`='En garde' WHERE `id`=828; -UPDATE `ai_playerbot_texts` SET `id`=829, `text_loc2`='Utilisation de %target' WHERE `id`=829; -UPDATE `ai_playerbot_texts` SET `id`=830, `text_loc2`='sur %unit' WHERE `id`=830; -UPDATE `ai_playerbot_texts` SET `id`=831, `text_loc2`='(%amount disponible)' WHERE `id`=831; -UPDATE `ai_playerbot_texts` SET `id`=832, `text_loc2`='(le dernier)' WHERE `id`=832; -UPDATE `ai_playerbot_texts` SET `id`=833, `text_loc2`='La châsse ne correspond pas' WHERE `id`=833; -UPDATE `ai_playerbot_texts` SET `id`=834, `text_loc2`='sur objet d’échange' WHERE `id`=834; -UPDATE `ai_playerbot_texts` SET `id`=835, `text_loc2`='sur moi-même' WHERE `id`=835; -UPDATE `ai_playerbot_texts` SET `id`=836, `text_loc2`='sur %item' WHERE `id`=836; -UPDATE `ai_playerbot_texts` SET `id`=837, `text_loc2`='sur %gameobject' WHERE `id`=837; -UPDATE `ai_playerbot_texts` SET `id`=838, `text_loc2`='Loot de %item' WHERE `id`=838; -UPDATE `ai_playerbot_texts` SET `id`=839, `text_loc2`='Invocation de %target' WHERE `id`=839; -UPDATE `ai_playerbot_texts` SET `id`=840, `text_loc2`='Je n’ai pas assez de membres du groupe à proximité pour invoquer' WHERE `id`=840; -UPDATE `ai_playerbot_texts` SET `id`=841, `text_loc2`='Impossible de trouver la cible d’invocation' WHERE `id`=841; -UPDATE `ai_playerbot_texts` SET `id`=842, `text_loc2`='Je ne peux pas invoquer en combat' WHERE `id`=842; -UPDATE `ai_playerbot_texts` SET `id`=843, `text_loc2`='Je ne connais pas le sort %spell' WHERE `id`=843; -UPDATE `ai_playerbot_texts` SET `id`=844, `text_loc2`='Lancement du sort %spell' WHERE `id`=844; -UPDATE `ai_playerbot_texts` SET `id`=845, `text_loc2`='Fabrication de %spell' WHERE `id`=845; -UPDATE `ai_playerbot_texts` SET `id`=846, `text_loc2`='Impossible de lancer %spell' WHERE `id`=846; -UPDATE `ai_playerbot_texts` SET `id`=847, `text_loc2`='Échec du lancement de %spell' WHERE `id`=847; -UPDATE `ai_playerbot_texts` SET `id`=848, `text_loc2`='|cffffff00(x%amount restant)|r' WHERE `id`=848; -UPDATE `ai_playerbot_texts` SET `id`=849, `text_loc2`='dummy' WHERE `id`=849; -UPDATE `ai_playerbot_texts` SET `id`=934, `text_loc2`='Par la Lumière... J\'ai oublié mes Symboles du roi. On se contentera de %base_spell !' WHERE `id`=934; -UPDATE `ai_playerbot_texts` SET `id`=935, `text_loc2`='La nature est généreuse, pas mes sacs... plus d\'herbes pour %group_spell. Prenez %base_spell pour l\'instant !' WHERE `id`=935; -UPDATE `ai_playerbot_texts` SET `id`=936, `text_loc2`='Plus de poudre des arcanes... %group_spell attendra. Je lance %base_spell !' WHERE `id`=936; -UPDATE `ai_playerbot_texts` SET `id`=937, `text_loc2`='Oups, je n\'ai plus de composants pour %group_spell. On fera avec %base_spell !' WHERE `id`=937; +UPDATE `ai_playerbot_texts` SET `text_loc2`='au milieu de nulle part' WHERE `id`=1; +UPDATE `ai_playerbot_texts` SET `text_loc2`='un endroit non divulgué' WHERE `id`=2; +UPDATE `ai_playerbot_texts` SET `text_loc2`='quelque part' WHERE `id`=3; +UPDATE `ai_playerbot_texts` SET `text_loc2`='un truc' WHERE `id`=4; +UPDATE `ai_playerbot_texts` SET `text_loc2`='je me demande quel goût a %item_link' WHERE `id`=5; +UPDATE `ai_playerbot_texts` SET `text_loc2`='noooon, j’ai eu %item_link' WHERE `id`=6; +UPDATE `ai_playerbot_texts` SET `text_loc2`='oh non, encore cette camelote %item_link' WHERE `id`=7; +UPDATE `ai_playerbot_texts` SET `text_loc2`='on dirait que je ramasse des ordures %item_link' WHERE `id`=8; +UPDATE `ai_playerbot_texts` SET `text_loc2`='bon, c’est mieux que rien je suppose %item_link' WHERE `id`=9; +UPDATE `ai_playerbot_texts` SET `text_loc2`='je ne sais pas quoi faire de %item_link' WHERE `id`=10; +UPDATE `ai_playerbot_texts` SET `text_loc2`='je me demande quel goût a %item_link' WHERE `id`=11; +UPDATE `ai_playerbot_texts` SET `text_loc2`='je pourrais ramasser du %item_link toute la journée' WHERE `id`=12; +UPDATE `ai_playerbot_texts` SET `text_loc2`='un jour de plus, un %item_link de plus' WHERE `id`=13; +UPDATE `ai_playerbot_texts` SET `text_loc2`='j’ai ramassé un peu de %item_link' WHERE `id`=14; +UPDATE `ai_playerbot_texts` SET `text_loc2`='un peu de %item_link, c’est toujours ça' WHERE `id`=15; +UPDATE `ai_playerbot_texts` SET `text_loc2`='pas mal, je viens de choper %item_link' WHERE `id`=16; +UPDATE `ai_playerbot_texts` SET `text_loc2`='je viens de ramasser %item_link à %zone_name' WHERE `id`=17; +UPDATE `ai_playerbot_texts` SET `text_loc2`='je pourrais bien l’utiliser ça %item_link' WHERE `id`=18; +UPDATE `ai_playerbot_texts` SET `text_loc2`='argent, argent, argent %item_link' WHERE `id`=19; +UPDATE `ai_playerbot_texts` SET `text_loc2`='j’ai eu %item_link' WHERE `id`=20; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_link est BiS pour les chasseurs' WHERE `id`=21; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_link est BiS pour les %my_class' WHERE `id`=22; +UPDATE `ai_playerbot_texts` SET `text_loc2`='la chance est avec moi aujourd’hui %item_link' WHERE `id`=23; +UPDATE `ai_playerbot_texts` SET `text_loc2`='trop bon %item_link, fraîchement looté' WHERE `id`=24; +UPDATE `ai_playerbot_texts` SET `text_loc2`='wow, je viens de choper %item_link' WHERE `id`=25; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_link est BiS pour les chasseurs' WHERE `id`=26; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_link est BiS pour les %my_class' WHERE `id`=27; +UPDATE `ai_playerbot_texts` SET `text_loc2`='la chance est avec moi aujourd’hui %item_link' WHERE `id`=28; +UPDATE `ai_playerbot_texts` SET `text_loc2`='trop bon %item_link, fraîchement looté' WHERE `id`=29; +UPDATE `ai_playerbot_texts` SET `text_loc2`='OMG, regardez ce que je viens de looter %item_link !!!' WHERE `id`=30; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Noooon ! C’est pas possible, j’ai eu %item_link, c’est de la folie' WHERE `id`=31; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Noooon ! C’est pas possible, j’ai eu %item_link, c’est de la folie' WHERE `id`=32; +UPDATE `ai_playerbot_texts` SET `text_loc2`='je viens juste de prendre la quête %quest_link' WHERE `id`=33; +UPDATE `ai_playerbot_texts` SET `text_loc2`='je viens d’accepter %quest_link' WHERE `id`=34; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_link je vais essayer de la finir' WHERE `id`=35; +UPDATE `ai_playerbot_texts` SET `text_loc2`='j’ai pris %quest_link à %zone_name' WHERE `id`=36; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Enfin fini l’objectif %quest_obj_name pour %quest_link' WHERE `id`=37; +UPDATE `ai_playerbot_texts` SET `text_loc2`='j’ai enfin %quest_obj_available/%quest_obj_required de %quest_obj_name pour %quest_link' WHERE `id`=38; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_obj_full_formatted pour %quest_link, enfin !' WHERE `id`=39; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oof, j’ai %quest_obj_available/%quest_obj_required %quest_obj_name pour %quest_link' WHERE `id`=40; +UPDATE `ai_playerbot_texts` SET `text_loc2`='il me manque encore %quest_obj_missing de %quest_obj_name pour %quest_link' WHERE `id`=41; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_obj_full_formatted, je bosse toujours sur %quest_link' WHERE `id`=42; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Enfin fini avec %item_link pour %quest_link' WHERE `id`=43; +UPDATE `ai_playerbot_texts` SET `text_loc2`='j’ai enfin %quest_obj_available/%quest_obj_required de %item_link pour %quest_link' WHERE `id`=44; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_obj_full_formatted pour %quest_link, enfin !' WHERE `id`=45; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oof, j’ai %quest_obj_available/%quest_obj_required %item_link pour %quest_link' WHERE `id`=46; +UPDATE `ai_playerbot_texts` SET `text_loc2`='il me manque encore %quest_obj_missing de %item_link pour %quest_link' WHERE `id`=47; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_obj_full_formatted, je suis encore sur %quest_link' WHERE `id`=48; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Échec : je n’ai pas fini %quest_link à temps...' WHERE `id`=49; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus de temps pour %quest_link :(' WHERE `id`=50; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai terminé tous les objectifs de %quest_link' WHERE `id`=51; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Objectifs terminés pour %quest_link' WHERE `id`=52; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais rendre %quest_link bientôt, tout est fait' WHERE `id`=53; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ouiii, j’ai enfin rendu %quest_link' WHERE `id`=54; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_link rendu' WHERE `id`=55; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mission %quest_link terminée, rendu !' WHERE `id`=56; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_link rendu' WHERE `id`=57; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_link rendu à %zone_name' WHERE `id`=58; +UPDATE `ai_playerbot_texts` SET `text_loc2`='encore un %victim_name à terre' WHERE `id`=59; +UPDATE `ai_playerbot_texts` SET `text_loc2`='je continue à tuer %victim_name, la routine quoi' WHERE `id`=60; +UPDATE `ai_playerbot_texts` SET `text_loc2`='un autre %victim_name qui mord la poussière' WHERE `id`=61; +UPDATE `ai_playerbot_texts` SET `text_loc2`='un %victim_name en moins à %zone_name' WHERE `id`=62; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai descendu ce sale élite %victim_name !' WHERE `id`=63; +UPDATE `ai_playerbot_texts` SET `text_loc2`='élite %victim_name éliminé à %zone_name' WHERE `id`=64; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ouf, j’ai réussi à abattre %victim_name !' WHERE `id`=65; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’était épique ! %victim_name est tombé, maintenant j’ai une histoire à raconter' WHERE `id`=66; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Yoo, je viens de tuer %victim_name !' WHERE `id`=67; +UPDATE `ai_playerbot_texts` SET `text_loc2`='rare %victim_name éliminé à %zone_name' WHERE `id`=68; +UPDATE `ai_playerbot_texts` SET `text_loc2`='WTF ais-je bien tué? %victim_name' WHERE `id`=69; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai tué cette bestiole %victim_name' WHERE `id`=70; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh ouiii, j’ai tué %victim_name' WHERE `id`=71; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%victim_name éliminé à %zone_name' WHERE `id`=72; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ding !' WHERE `id`=73; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ouiii, je suis niveau %my_level !' WHERE `id`=74; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je viens de passer un niveau' WHERE `id`=75; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis niveau %my_level !!!' WHERE `id`=76; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je deviens plus fort, déjà %my_level !!!' WHERE `id`=77; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je viens d’atteindre le niveau %my_level !!!' WHERE `id`=78; +UPDATE `ai_playerbot_texts` SET `text_loc2`='OMG, enfin niveau %my_level !!!' WHERE `id`=79; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_level !!! prêt pour le contenu endgame' WHERE `id`=80; +UPDATE `ai_playerbot_texts` SET `text_loc2`='tout frais, nouveau %my_level %my_class !!!' WHERE `id`=81; +UPDATE `ai_playerbot_texts` SET `text_loc2`='encore un niveau %my_level %my_race %my_class !' WHERE `id`=82; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bien joué %other_name. Tu l’as mérité.' WHERE `id`=83; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’était affreux %other_name. J’ai détesté faire ça mais...' WHERE `id`=84; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un veut faire %instance_name ?' WHERE `id`=85; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Des groupes pour %instance_name ?' WHERE `id`=86; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’aide pour %instance_name ?' WHERE `id`=87; +UPDATE `ai_playerbot_texts` SET `text_loc2`='LFD : %instance_name.' WHERE `id`=88; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a besoin d’un %my_role pour %instance_name ?' WHERE `id`=89; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Il manque un %my_role pour %instance_name ?' WHERE `id`=90; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux être %my_role pour %instance_name.' WHERE `id`=91; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’un coup de main à %instance_name ?' WHERE `id`=92; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’un %my_role pour %instance_name ?' WHERE `id`=93; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a besoin de loot à %instance_name ?' WHERE `id`=94; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Un petit farm à %instance_name ?' WHERE `id`=95; +UPDATE `ai_playerbot_texts` SET `text_loc2`='WTR %instance_name' WHERE `id`=96; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’aide pour %instance_name.' WHERE `id`=97; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie de faire %instance_name.' WHERE `id`=98; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_role cherche un groupe pour %instance_name.' WHERE `id`=99; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Et %instance_name, on y va ?' WHERE `id`=100; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut farmer %instance_name ?' WHERE `id`=101; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On entre dans %instance_name ?' WHERE `id`=102; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je cherche groupe pour %instance_name.' WHERE `id`=103; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Des quêtes à %instance_name ?' WHERE `id`=104; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie de faire des quêtes à %instance_name.' WHERE `id`=105; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un avec des quêtes à %instance_name ?' WHERE `id`=106; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux aider pour les quêtes à %instance_name.' WHERE `id`=107; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_role : une place dispo pour %instance_name ?' WHERE `id`=108; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Est-ce que quelqu’un fait encore %instance_name de nos jours ?' WHERE `id`=109; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%instance_name : quelqu’un cherche un %my_role ?' WHERE `id`=110; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ça sert encore à quelque chose d’être %my_role à %instance_name ?' WHERE `id`=111; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ça vaut vraiment le coup d’aller à %instance_name ?' WHERE `id`=112; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a besoin de plus de joueurs pour %instance_name ?' WHERE `id`=113; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Les boss de %instance_name lootent du bon matos. On y va ?' WHERE `id`=114; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Alors, %instance_name ?' WHERE `id`=115; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a besoin d’un %my_role ?' WHERE `id`=116; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a besoin d’un %my_role ?' WHERE `id`=117; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut aller à %instance_name ?' WHERE `id`=118; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut me TP à %instance_name ?' WHERE `id`=119; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Retrouve-moi à %instance_name' WHERE `id`=120; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie d’un petit run rapide à %instance_name ?' WHERE `id`=121; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On se fait un run complet à %instance_name ?' WHERE `id`=122; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’as été combien de fois à %instance_name ?' WHERE `id`=123; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Encore un run à %instance_name ?' WHERE `id`=124; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Wipe à %instance_name ? Prends-moi, je suis un porte-bonheur !' WHERE `id`=125; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Emmène-moi à %instance_name s’il te plaît.' WHERE `id`=126; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Un petit %instance_name vite fait bien fait ?' WHERE `id`=127; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Full %instance_name jusqu’à la fin ?' WHERE `id`=128; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui peut prendre un %my_role à %instance_name ?' WHERE `id`=129; +UPDATE `ai_playerbot_texts` SET `text_loc2`='LFG %instance_name, je suis %my_role' WHERE `id`=130; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_role cherche groupe pour %instance_name' WHERE `id`=131; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’aide pour %quest_link ?' WHERE `id`=132; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un veut partager %quest_link ?' WHERE `id`=133; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un fait %quest_link ?' WHERE `id`=134; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On fait %quest_link ?' WHERE `id`=135; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un pour farmer du %category ?' WHERE `id`=136; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Cherche aide pour farmer %category.' WHERE `id`=137; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ces %category coûtent un bras !' WHERE `id`=138; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin de %category.' WHERE `id`=139; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’aide pour %category.' WHERE `id`=140; +UPDATE `ai_playerbot_texts` SET `text_loc2`='WTB %category.' WHERE `id`=141; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un est intéressé par %category ?' WHERE `id`=142; +UPDATE `ai_playerbot_texts` SET `text_loc2`='WTS %category.' WHERE `id`=143; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vends %category moins cher que l’HV.' WHERE `id`=144; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut farmer du %category ?' WHERE `id`=145; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On farme du %category ?' WHERE `id`=146; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je cherche un groupe, après ça on fait du %category ?' WHERE `id`=147; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tous les %category sont les bienvenus.' WHERE `id`=148; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’achète tout ce qui ressemble à du %category.' WHERE `id`=149; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Wow, y’a des gens qui farment encore du %category ?' WHERE `id`=150; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Les %category partent comme des petits pains à l’HV !' WHERE `id`=151; +UPDATE `ai_playerbot_texts` SET `text_loc2`='L’HV brûle à cause des %category !' WHERE `id`=152; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a des %category sur le marché.' WHERE `id`=153; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J\'échange des %category ?' WHERE `id`=154; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Il me faut plus de %category.' WHERE `id`=155; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a un peu de %category à donner ?' WHERE `id`=156; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut du %category ?' WHERE `id`=157; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Un peu de %category s’il vous plaît ?' WHERE `id`=158; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’aurais dû monter une compétence pour les %category.' WHERE `id`=159; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je meurs d’envie d’avoir des %category.' WHERE `id`=160; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Les gens se tuent pour les %category.' WHERE `id`=161; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%category, c’est une affaire en or !' WHERE `id`=162; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tout le monde devient fou pour les %category !' WHERE `id`=163; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est où le meilleur spot pour farmer des %category ?' WHERE `id`=164; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis prêt pour le farm de %category.' WHERE `id`=165; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ça se vend bien les %category ?' WHERE `id`=166; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais garder tous mes %category. Pour moi.' WHERE `id`=167; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’un groupe ? On pourrait farm des %category ensemble.' WHERE `id`=168; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pense encore aux %category.' WHERE `id`=169; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai entendu parler des %category... mais mon porte-monnaie ne veut pas.' WHERE `id`=170; +UPDATE `ai_playerbot_texts` SET `text_loc2`='LFG pour %category' WHERE `id`=171; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Vendre %category rend riche ?' WHERE `id`=172; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ok. Demain je farm les %category.' WHERE `id`=173; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tout le monde parle des %category.' WHERE `id`=174; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai vu au moins dix gars farmer du %category.' WHERE `id`=175; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai tout vendu mes %category hier. Maintenant je mange du pain sec!' WHERE `id`=176; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie de rejoindre une guilde qui farme du %category.' WHERE `id`=177; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un farm la réputation %faction ?' WHERE `id`=178; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut m’aider pour %faction ?' WHERE `id`=179; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On fait des quêtes pour %faction ?' WHERE `id`=180; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%faction, c’est la crème de la crème. Paraît-il.' WHERE `id`=181; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Il me manque juste un tout petit peu pour être %rep_level avec %faction.' WHERE `id`=182; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un est %rep_level avec %faction ?' WHERE `id`=183; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut devenir %rep_level avec %faction ?' WHERE `id`=184; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je serai jamais %rep_level avec %faction.' WHERE `id`=185; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a oublié de monter la réputation %faction ?' WHERE `id`=186; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux aider à farmer la réputation %faction.' WHERE `id`=187; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus on a de réputation, mieux c’est. Surtout avec %faction.' WHERE `id`=188; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%faction : il me faut encore %rndK pour être %rep_level.' WHERE `id`=189; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui peut partager des quêtes %faction ?' WHERE `id`=190; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Des donjons pour la réputation %faction ?' WHERE `id`=191; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On farm la réput %faction ?' WHERE `id`=192; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Allons-y pour %faction !' WHERE `id`=193; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je farm la réputation %faction.' WHERE `id`=194; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On farme pour %faction ?' WHERE `id`=195; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’aide pour %faction.' WHERE `id`=196; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%faction vend quelque chose d’utile ?' WHERE `id`=197; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Il existe des vendeurs %faction ?' WHERE `id`=198; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui farme %faction ?' WHERE `id`=199; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelle est la meilleure façon de farmer %faction ?' WHERE `id`=200; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je déteste farmer la réputation %faction.' WHERE `id`=201; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’en ai marre de %faction.' WHERE `id`=202; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On y va pour %faction ?' WHERE `id`=203; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tout le monde est %rep_level avec %faction. Et moi, je galère encore.' WHERE `id`=204; +UPDATE `ai_playerbot_texts` SET `text_loc2`='LFG pour farm de réputation %faction ?' WHERE `id`=205; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a un bon spot pour la réputation %faction ?' WHERE `id`=206; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Améliorer ma réput %faction, ça sert ?' WHERE `id`=207; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui aurait cru que la réputation %faction finirait par servir...' WHERE `id`=208; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je veux être exalté avec toutes les factions. En commençant par %faction.' WHERE `id`=209; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Est-ce que ça vaut le coup de monter %faction ?' WHERE `id`=210; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qu’est-ce qui marche le mieux pour %faction ? Les quêtes ou tuer des mobs ?' WHERE `id`=211; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je farm %faction pour toi, si tu me paies.' WHERE `id`=212; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Farmer la réputation %faction ? Ça prendra 3 vies au moins.' WHERE `id`=213; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je tue pour %faction tous les jours, mais je suis toujours pas %rep_level.' WHERE `id`=214; +UPDATE `ai_playerbot_texts` SET `text_loc2`='À %my_level, les dépôts à l’HV vont baisser, non ?' WHERE `id`=215; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Combien de réputations exaltées tu as ?' WHERE `id`=216; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut être %my_level avec %faction ?' WHERE `id`=217; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ma guilde a farmé la réputation %faction hier. Sans moi...' WHERE `id`=218; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Personne ne veut m’aider, tout ça parce que je suis %rep_level avec %faction.' WHERE `id`=219; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Évitez la %faction.' WHERE `id`=220; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On se fait une soirée à %zone_name ?' WHERE `id`=221; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un cherche un %my_role ?' WHERE `id`=222; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_role cherche une guilde.' WHERE `id`=223; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je cherche de l’or.' WHERE `id`=224; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_role cherche une bonne guilde.' WHERE `id`=225; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin d’un ami.' WHERE `id`=226; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un d’autre se sent seul ?' WHERE `id`=227; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je m’ennuie...' WHERE `id`=228; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui en veut ?' WHERE `id`=229; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Allez viens te battre !' WHERE `id`=230; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Un petit duel à %zone_name ?' WHERE `id`=231; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un fait quelque chose ici ?' WHERE `id`=232; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name : y’a une âme qui vive ici ?' WHERE `id`=233; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name : tout le monde est en furtif ou quoi ?' WHERE `id`=234; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On dirait que je suis seul à %zone_name.' WHERE `id`=235; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Rejoins-moi à %zone_name .' WHERE `id`=236; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Allez, on fait des quêtes à %zone_name !' WHERE `id`=237; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name c’est LE coin sympa du momment.' WHERE `id`=238; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’veux aller à %zone_name. Quelqu’un me suit ?' WHERE `id`=239; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut aller à %zone_name ?' WHERE `id`=240; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’aime pas %zone_name. Où doi-je aller ?' WHERE `id`=241; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a de bonnes quêtes à %zone_name ?' WHERE `id`=242; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On va où après %zone_name ?' WHERE `id`=243; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui traîne à %zone_name ?' WHERE `id`=244; +UPDATE `ai_playerbot_texts` SET `text_loc2`='LFG pour %zone_name.' WHERE `id`=245; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name est l’endroit le plus naze du monde.' WHERE `id`=246; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Attrape-moi à %zone_name si tu peux !' WHERE `id`=247; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Direction %zone_name !' WHERE `id`=248; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie de quêtes à %zone_name' WHERE `id`=249; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a des quêtes à %zone_name ?' WHERE `id`=250; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Venez à %zone_name !' WHERE `id`=251; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On dirait que la Horde a déserté %zone_name...' WHERE `id`=252; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On dirait que l’Alliance a déserté %zone_name...' WHERE `id`=253; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’en peux plus de %zone_name. Quelqu’un me sort de là ?' WHERE `id`=254; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonne chance !' WHERE `id`=255; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je veux rentrer chez moi… puis pleurer au bord du vide' WHERE `id`=256; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un sait ce qu’il faut pour jouer double arme ?' WHERE `id`=257; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut tout le monde !' WHERE `id`=258; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name est cosy' WHERE `id`=259; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je me sens bien' WHERE `id`=260; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’ignore pas les gens. Je les trolle jusqu’à ce qu’ils m’ignorent.' WHERE `id`=261; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Que pensez-vous de mon build ? %my_role' WHERE `id`=262; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Heureux de voir que le chat ne m’a pas oublié' WHERE `id`=263; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Comme toutes les armes, c’est BiS pour chasseur' WHERE `id`=264; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Le but du jeu pour moi ? Solo tout ce qui bouge.' WHERE `id`=265; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai JAMAIS arnaqué personne.' WHERE `id`=266; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ah, World of Warcraft. Là où je viens chercher des conseils de vie.' WHERE `id`=267; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’A QUELQU’UN ?!' WHERE `id`=268; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Il est temps de me frayer un chemin dans %zone_name.' WHERE `id`=269; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name' WHERE `id`=270; +UPDATE `ai_playerbot_texts` SET `text_loc2`='… faut que j’aille aux toilettes.' WHERE `id`=271; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Si tu loot pas tes mobs skinables, ton zizi perd 1mm. C’est la règle.' WHERE `id`=272; +UPDATE `ai_playerbot_texts` SET `text_loc2`='NOOOOOOOOOOOOO' WHERE `id`=273; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’AIME LA PATATE' WHERE `id`=274; +UPDATE `ai_playerbot_texts` SET `text_loc2`='La discussion est animée.' WHERE `id`=275; +UPDATE `ai_playerbot_texts` SET `text_loc2`='salut, comment ça va les gens ?' WHERE `id`=276; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je viens de me déco / reco.' WHERE `id`=277; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Faites moins de bruit, j’suis perdu dans %zone_name…' WHERE `id`=278; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un veut boire un verre à %zone_name ? hic' WHERE `id`=279; +UPDATE `ai_playerbot_texts` SET `text_loc2`='hahahahaheeeee dirin diring inggggg hahahahaheeeeeeeeeeeeee' WHERE `id`=280; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Avant, les appâts étaient crédibles.' WHERE `id`=281; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Peut-être que t’as juste perdu ton innocence.' WHERE `id`=282; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a une guilde qui veut carry un %my_role fragile ?' WHERE `id`=283; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus on monte en niveau, plus l’or coule à flots' WHERE `id`=284; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour !' WHERE `id`=285; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi j’ai mal au cul ?' WHERE `id`=286; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pense que l’esprit est BiS pour monter de niveau.' WHERE `id`=287; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Encore plus si t’es troll.' WHERE `id`=288; +UPDATE `ai_playerbot_texts` SET `text_loc2`='QUELQU’UN PEUT M’INVITER ?' WHERE `id`=289; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin de beaucouuuup de boissons.' WHERE `id`=290; +UPDATE `ai_playerbot_texts` SET `text_loc2`='P*utain de gnomes…' WHERE `id`=291; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Personne n’aime les gnomes.' WHERE `id`=292; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Les gnomes ne servent qu’à une chose' WHERE `id`=293; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bah…' WHERE `id`=294; +UPDATE `ai_playerbot_texts` SET `text_loc2`='… des champignons.' WHERE `id`=295; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Les pensées automatiques, c’est flippant.' WHERE `id`=296; +UPDATE `ai_playerbot_texts` SET `text_loc2`='L’esprit est plus malléable qu’on aimerait le croire.' WHERE `id`=297; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a des guildes pour leveling ?' WHERE `id`=298; +UPDATE `ai_playerbot_texts` SET `text_loc2`='brb' WHERE `id`=299; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi la neige est blanche mais la glace est transparente ? Mystère.' WHERE `id`=300; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi la crème fouettée est fluffy, mais pas la normale ?' WHERE `id`=301; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi les pieds sentent alors qu’ils n’ont pas de nez ?' WHERE `id`=302; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On dirait que la boîte à noobs vient de s’ouvrir.' WHERE `id`=303; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Arrêtez de troller les nouveaux avec vos réponses à la con.' WHERE `id`=304; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a du PvP sur ce serveur ?' WHERE `id`=305; +UPDATE `ai_playerbot_texts` SET `text_loc2`='évidemment...' WHERE `id`=306; +UPDATE `ai_playerbot_texts` SET `text_loc2`='ouf… :)' WHERE `id`=307; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Vous saviez que' WHERE `id`=308; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne tente pas d’imaginer ce que ressentent les autres créatures' WHERE `id`=309; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oups, mauvais canal.' WHERE `id`=310; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bruh, vous êtes déchaînés aujourd’hui' WHERE `id`=311; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Juste pour que tout le monde sache : mon message est passé ici' WHERE `id`=312; +UPDATE `ai_playerbot_texts` SET `text_loc2`='grrr énervéééééé' WHERE `id`=313; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Le farm, c’est marrant' WHERE `id`=314; +UPDATE `ai_playerbot_texts` SET `text_loc2`='WoW me garde vif' WHERE `id`=315; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hé, question : où on prend le rôle pour plus d’XP ? Je suis à %zone_name.' WHERE `id`=316; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Vous aimez les saucisses ?' WHERE `id`=317; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Invitez-moi. Je peux aider.' WHERE `id`=318; +UPDATE `ai_playerbot_texts` SET `text_loc2`='À votre avis, quelle classe est la meilleure en PvP ?' WHERE `id`=319; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Où est ce foutu maître de cuisine à %zone_name ?!' WHERE `id`=320; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Vous savez ce qu’il se passe à %zone_name ?' WHERE `id`=321; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin de crafter quelque chose' WHERE `id`=322; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est quoi lèchemes' WHERE `id`=323; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est quoi sucemes ' WHERE `id`=324; +UPDATE `ai_playerbot_texts` SET `text_loc2`='lèchemes couilles' WHERE `id`=325; +UPDATE `ai_playerbot_texts` SET `text_loc2`='sucemes couilles' WHERE `id`=326; +UPDATE `ai_playerbot_texts` SET `text_loc2`='JE MANGE DES FESSES' WHERE `id`=327; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai envie de me fourrer %random_inventory_item_link là où le soleil ne brille pas' WHERE `id`=328; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai envie de te fourrer %random_inventory_item_link là où tu penses' WHERE `id`=329; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Darnasses' WHERE `id`=330; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On dirait que t’as chopé le syndrôme de sucemes' WHERE `id`=331; +UPDATE `ai_playerbot_texts` SET `text_loc2`='cesnoix dans ta bouche' WHERE `id`=332; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Sympa ton os, frérot' WHERE `id`=333; +UPDATE `ai_playerbot_texts` SET `text_loc2`='ERP ?' WHERE `id`=334; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai tout essayé, mais au final c’est l’ERP qui a marché' WHERE `id`=335; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai envie de batifoler à %zone_name' WHERE `id`=336; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Recherche gnome femelle avec gorille pour ERP sauvage à %zone_name' WHERE `id`=337; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux comprendre un idiot, mais un gros pervers ?' WHERE `id`=338; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Aucun GYAT en vue à %zone_name' WHERE `id`=339; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je tue tous les animaux de %zone_name. Désolé WWF !' WHERE `id`=340; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Heureusement que j’ai trois jambes' WHERE `id`=341; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Sois pas vénère, je goon comme un sigma' WHERE `id`=342; +UPDATE `ai_playerbot_texts` SET `text_loc2`='essaye doigt, mais trou' WHERE `id`=343; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%prefix %random_taken_quest_or_item_link' WHERE `id`=344; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%prefix %random_inventory_item_link' WHERE `id`=345; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%thunderfury_link' WHERE `id`=346; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%thunderfury_link%thunderfury_link' WHERE `id`=347; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%thunderfury_link%thunderfury_link%thunderfury_link' WHERE `id`=348; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je crois que je viens d’entendre %thunderfury_link' WHERE `id`=349; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai entendu %thunderfury_link' WHERE `id`=350; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai clairement entendu %thunderfury_link' WHERE `id`=351; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’suis pas sûr, mais j’crois avoir entendu %thunderfury_link' WHERE `id`=352; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’as dit %thunderfury_link' WHERE `id`=353; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a dit %thunderfury_link' WHERE `id`=354; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a VRAIMENT dit %thunderfury_link' WHERE `id`=355; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a parlé de %thunderfury_link' WHERE `id`=356; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%thunderfury_link sort du placard, les gars' WHERE `id`=357; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’aurais juré que c’était un %thunderfury_link… ou peut-être un %thunderfury_link' WHERE `id`=358; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi utiliser %thunderfury_link alors que %thunderfury_link est bien plus OP' WHERE `id`=359; +UPDATE `ai_playerbot_texts` SET `text_loc2`='WTS %item_formatted_link pour %cost_gold.' WHERE `id`=360; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut %item_formatted_link pour %cost_gold ?' WHERE `id`=361; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un veut %item_formatted_link ? Seulement %cost_gold' WHERE `id`=362; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Juste %cost_gold pour %item_formatted_link!' WHERE `id`=363; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vends %item_formatted_link pour %cost_gold' WHERE `id`=364; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_formatted_link est à toi pour seulement %cost_gold !' WHERE `id`=365; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Prix ridicule : %cost_gold pour %item_formatted_link !' WHERE `id`=366; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je cherche à vendre %item_formatted_link pour %cost_gold' WHERE `id`=367; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui a besoin de %item_formatted_link ? Seulement %cost_gold' WHERE `id`=368; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un veut %item_formatted_link pour %cost_gold ?' WHERE `id`=369; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%cost_gold pour %item_formatted_link. Moins cher qu’à l’HV !' WHERE `id`=370; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_formatted_link est cher, mais je te le fais à %cost_gold' WHERE `id`=371; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu trouveras jamais %item_formatted_link moins cher que %cost_gold!' WHERE `id`=372; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin de plus que %item_formatted_link, là !' WHERE `id`=373; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai %item_formatted_link et j’en veux encore' WHERE `id`=374; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai %item_formatted_link. Qui l’achète pour %cost_gold ?' WHERE `id`=375; +UPDATE `ai_playerbot_texts` SET `text_loc2`='WTB %item_formatted_link pour %cost_gold, quelqu’un ?' WHERE `id`=376; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Et %item_formatted_link ? Pour %cost_gold.' WHERE `id`=377; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui m’a traité d\'arnaqueur ? %item_formatted_link pour %cost_gold c’est honnête !' WHERE `id`=378; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vends %item_formatted_link. Juste %cost_gold' WHERE `id`=379; +UPDATE `ai_playerbot_texts` SET `text_loc2`='LFG pour du farm, et au passage %item_formatted_link à vendre %cost_gold' WHERE `id`=380; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Presque tout vendu aujourd’hui. Me reste %item_formatted_link pour %cost_gold' WHERE `id`=381; +UPDATE `ai_playerbot_texts` SET `text_loc2`='À quoi sert le canal commerce ? A vendre %item_formatted_link pour %cost_gold, évidemment' WHERE `id`=382; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut battre %cost_gold pour %item_formatted_link ?' WHERE `id`=383; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie d’arrêter le spam commerce ? Achetez %item_formatted_link à %cost_gold !' WHERE `id`=384; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tout le monde spam, moi aussi : %cost_gold pour %item_formatted_link !' WHERE `id`=385; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_formatted_link est utile ? Je sais pas, mais je le vends %cost_gold' WHERE `id`=386; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai %item_formatted_link prêt à vendre %cost_gold' WHERE `id`=387; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hier j’ai rien foutu, mais j’ai loot %item_formatted_link. À vendre %cost_gold' WHERE `id`=388; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai farmé hier, j’ai eu %item_formatted_link. WTB ? %cost_gold' WHERE `id`=389; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai acheté %item_formatted_link hier. Quelqu’un le veut ? %cost_gold' WHERE `id`=390; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un cherchait %item_formatted_link ? C’est %cost_gold toujours' WHERE `id`=391; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai encore %item_formatted_link. Achetez-le %cost_gold' WHERE `id`=392; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Avant j’en avais plein %item_formatted_link, maintenant je dois vendre à %cost_gold' WHERE `id`=393; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’aimerais en avoir plus que %item_formatted_link. Mais achetez celui-là %cost_gold' WHERE `id`=394; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ton or te sert à quoi ? À acheter %item_formatted_link pour %cost_gold' WHERE `id`=395; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ayez pitié, donnez-moi de l’or... ou achetez %item_formatted_link %cost_gold' WHERE `id`=396; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Est-ce que %cost_gold est un bon prix pour %item_formatted_link ?' WHERE `id`=397; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai acheté %item_formatted_links hier, mais j’en veux plus. Quelqu\'un vends pour %cost_gold' WHERE `id`=398; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais le mettre à l’HV %item_formatted_link, mais tu peux l’avoir moins cher : %cost_gold' WHERE `id`=399; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi j’ai acheté %item_formatted_link bordel ? Quelqu’un le veut ? %cost_gold' WHERE `id`=400; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai %quest_links' WHERE `id`=401; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Moi aussi j’ai %quest_links' WHERE `id`=402; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Moi aussi j’ai %quest_links, je suis à %zone_name' WHERE `id`=403; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, moi aussi j’ai %quest_links' WHERE `id`=404; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, moi aussi j’ai %quest_links, et je suis à %zone_name' WHERE `id`=405; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis dispo pour %quest_links, je suis à %zone_name' WHERE `id`=406; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=407; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, je suis dispo pour %quest_links à %zone_name' WHERE `id`=408; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=409; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey, je suis partant pour %quest_links' WHERE `id`=410; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey, je pourrais faire %quest_links avec toi' WHERE `id`=411; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey, moi aussi j’ai %quest_links' WHERE `id`=412; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %other_name, partant pour %quest_links' WHERE `id`=413; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %other_name, je peux faire %quest_links avec toi' WHERE `id`=414; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %other_name, moi aussi j’ai %quest_links' WHERE `id`=415; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On se groupe pour %quest_links ?' WHERE `id`=416; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis partant pour %quest_links, je suis à %zone_name' WHERE `id`=417; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=418; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, je peux te vendre %formatted_item_links' WHERE `id`=419; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux peut-être vendre %formatted_item_links' WHERE `id`=420; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pense pouvoir vendre %formatted_item_links' WHERE `id`=421; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, je peux peut-être te vendre %formatted_item_links' WHERE `id`=422; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, tu penses que je peux vendre %formatted_item_links ?' WHERE `id`=423; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux te vendre %formatted_item_links' WHERE `id`=424; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey, j’ai %formatted_item_links à vendre' WHERE `id`=425; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey, je pourrais peut-être vendre %formatted_item_links' WHERE `id`=426; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quête acceptée' WHERE `id`=427; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quête abandonnée' WHERE `id`=428; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas prendre cette quête' WHERE `id`=429; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas parler au donneur de quête' WHERE `id`=430; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai déjà terminé %quest' WHERE `id`=431; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai déjà la quête %quest' WHERE `id`=432; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas prendre %quest' WHERE `id`=433; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas prendre %quest, mon journal de quêtes est plein' WHERE `id`=434; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas prendre %quest, mes sacs sont pleins' WHERE `id`=435; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai accepté la quête %quest' WHERE `id`=436; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’ai pas encore terminé la quête %quest' WHERE `id`=437; +UPDATE `ai_playerbot_texts` SET `text_loc2`='La quête %quest est dispo' WHERE `id`=438; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai échoué à la quête %quest' WHERE `id`=439; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas rendre la quête %quest' WHERE `id`=440; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai terminé la quête %quest' WHERE `id`=441; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai terminé la quête %quest et reçu %item' WHERE `id`=442; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelle récompense devrais-je choisir pour la quête %quest ? %rewards' WHERE `id`=443; +UPDATE `ai_playerbot_texts` SET `text_loc2`='OK, je vais prendre %item comme récompense' WHERE `id`=444; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour' WHERE `id`=445; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour !' WHERE `id`=446; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut' WHERE `id`=447; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut !' WHERE `id`=448; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut à toi !' WHERE `id`=449; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour, je vous suis !' WHERE `id`=450; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour, montrez-moi le chemin !' WHERE `id`=451; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut, montre-moi le chemin !' WHERE `id`=452; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %player, tu veux rejoindre mon groupe ?' WHERE `id`=453; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %player, tu veux rejoindre mon groupe ?' WHERE `id`=454; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Déconnexion annulée !' WHERE `id`=455; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je me déconnecte !' WHERE `id`=456; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Au revoir !' WHERE `id`=457; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bye bye !' WHERE `id`=458; +UPDATE `ai_playerbot_texts` SET `text_loc2`='À plus tard !' WHERE `id`=459; +UPDATE `ai_playerbot_texts` SET `text_loc2`='c’était quoi ce truc %s ?' WHERE `id`=460; +UPDATE `ai_playerbot_texts` SET `text_loc2`='pas sûr d’avoir compris %s ?' WHERE `id`=461; +UPDATE `ai_playerbot_texts` SET `text_loc2`='euh… j’ai aucune idée de ce que tu racontes' WHERE `id`=462; +UPDATE `ai_playerbot_texts` SET `text_loc2`='tu parles à moi, %s ?' WHERE `id`=463; +UPDATE `ai_playerbot_texts` SET `text_loc2`='whaaaa ?' WHERE `id`=464; +UPDATE `ai_playerbot_texts` SET `text_loc2`='hein ?' WHERE `id`=465; +UPDATE `ai_playerbot_texts` SET `text_loc2`='quoi ?' WHERE `id`=466; +UPDATE `ai_playerbot_texts` SET `text_loc2`='tu parles ou tu râles ?' WHERE `id`=467; +UPDATE `ai_playerbot_texts` SET `text_loc2`='comme tu veux, mec' WHERE `id`=468; +UPDATE `ai_playerbot_texts` SET `text_loc2`='tu m’as perdu là' WHERE `id`=469; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bla bla bla…' WHERE `id`=470; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’as dit quoi, %s ?' WHERE `id`=471; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Concentre-toi sur le jeu, %s !' WHERE `id`=472; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Parler avec toi %s, c’est génial ! J’ai toujours rêvé de te rencontrer' WHERE `id`=473; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ces messages me font flipper ! J’ai l’impression de tous vous connaître !' WHERE `id`=474; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ouais bien sûr ! HAHA ! C’est ça, allez !' WHERE `id`=475; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je te crois !!!' WHERE `id`=476; +UPDATE `ai_playerbot_texts` SET `text_loc2`='OK, uhuh LOL' WHERE `id`=477; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi tout le monde dit toujours les mêmes trucs ???' WHERE `id`=478; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %s… euh, laisse tomber !' WHERE `id`=479; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu parles de quoi %s ? Sérieux ?' WHERE `id`=480; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui a dit ça ? Je me sens visé là' WHERE `id`=481; +UPDATE `ai_playerbot_texts` SET `text_loc2`='wtf vous racontez tous là ?' WHERE `id`=482; +UPDATE `ai_playerbot_texts` SET `text_loc2`='fr fr no cap on a stack' WHERE `id`=483; +UPDATE `ai_playerbot_texts` SET `text_loc2`='t’auras que dalle' WHERE `id`=484; +UPDATE `ai_playerbot_texts` SET `text_loc2`='swag' WHERE `id`=485; +UPDATE `ai_playerbot_texts` SET `text_loc2`='merci !' WHERE `id`=486; +UPDATE `ai_playerbot_texts` SET `text_loc2`='non' WHERE `id`=487; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Yep' WHERE `id`=488; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Paix à son ame.' WHERE `id`=489; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s sans déconner xD' WHERE `id`=490; +UPDATE `ai_playerbot_texts` SET `text_loc2`='pourquoi ça ?' WHERE `id`=491; +UPDATE `ai_playerbot_texts` SET `text_loc2`='mdr' WHERE `id`=492; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pensais fermer ma gueule, j’ai encore rien compris au chat' WHERE `id`=493; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux devenir vraiment jaloux... comme un elfe sans loot' WHERE `id`=494; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s tu captes pas le sarcasme qui dégouline de mon message là ?' WHERE `id`=495; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Il a dit "no homo", donc c’est bon apparemment' WHERE `id`=496; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Instant nain' WHERE `id`=497; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oui %s' WHERE `id`=498; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Intéressant…' WHERE `id`=499; +UPDATE `ai_playerbot_texts` SET `text_loc2`='lol' WHERE `id`=500; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s va te faire voir mec :D' WHERE `id`=501; +UPDATE `ai_playerbot_texts` SET `text_loc2`=':^)' WHERE `id`=502; +UPDATE `ai_playerbot_texts` SET `text_loc2`='merci' WHERE `id`=503; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s bien dit !' WHERE `id`=504; +UPDATE `ai_playerbot_texts` SET `text_loc2`='ouiiiii' WHERE `id`=505; +UPDATE `ai_playerbot_texts` SET `text_loc2`='ouais' WHERE `id`=506; +UPDATE `ai_playerbot_texts` SET `text_loc2`='ooooooh' WHERE `id`=507; +UPDATE `ai_playerbot_texts` SET `text_loc2`='hmm' WHERE `id`=508; +UPDATE `ai_playerbot_texts` SET `text_loc2`='ouais c’est ça' WHERE `id`=509; +UPDATE `ai_playerbot_texts` SET `text_loc2`='t’as failli me faire vomir, wtf' WHERE `id`=510; +UPDATE `ai_playerbot_texts` SET `text_loc2`='chaud !' WHERE `id`=511; +UPDATE `ai_playerbot_texts` SET `text_loc2`='les rageux pleurent' WHERE `id`=512; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’as mangé quoi %s ?' WHERE `id`=513; +UPDATE `ai_playerbot_texts` SET `text_loc2`='wtf' WHERE `id`=514; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais essayer de comprendre ce que t’as dit' WHERE `id`=515; +UPDATE `ai_playerbot_texts` SET `text_loc2`='*confus*' WHERE `id`=516; +UPDATE `ai_playerbot_texts` SET `text_loc2`='putain ouais' WHERE `id`=517; +UPDATE `ai_playerbot_texts` SET `text_loc2`='0/10 ne lirait pas ça une deuxième fois' WHERE `id`=518; +UPDATE `ai_playerbot_texts` SET `text_loc2`='10/10 je relis direct' WHERE `id`=519; +UPDATE `ai_playerbot_texts` SET `text_loc2`='6/10 ouais, pourquoi pas' WHERE `id`=520; +UPDATE `ai_playerbot_texts` SET `text_loc2`='7/10 ça passe' WHERE `id`=521; +UPDATE `ai_playerbot_texts` SET `text_loc2`='basé' WHERE `id`=522; +UPDATE `ai_playerbot_texts` SET `text_loc2`='ah ouais peut-être' WHERE `id`=523; +UPDATE `ai_playerbot_texts` SET `text_loc2`='ouais, et alors ?' WHERE `id`=524; +UPDATE `ai_playerbot_texts` SET `text_loc2`='hey %s je t’ai pas oublié' WHERE `id`=525; +UPDATE `ai_playerbot_texts` SET `text_loc2`='tu m’énerves %s' WHERE `id`=526; +UPDATE `ai_playerbot_texts` SET `text_loc2`='je vais t’avoir cette fois %s' WHERE `id`=527; +UPDATE `ai_playerbot_texts` SET `text_loc2`='garde un œil derrière toi %s' WHERE `id`=528; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai pas trop aimé la manche d’avant' WHERE `id`=529; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai été nul au dernier round à cause de %s' WHERE `id`=530; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Prépare-toi à mourir %s' WHERE `id`=531; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai pas trop kiffé que tu me tues %s' WHERE `id`=532; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, je te hais' WHERE `id`=533; +UPDATE `ai_playerbot_texts` SET `text_loc2`='grrrrr je vais t’avoir cette fois %s' WHERE `id`=534; +UPDATE `ai_playerbot_texts` SET `text_loc2`='eh bien va te faire foutre' WHERE `id`=535; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s je vais vomir dans ta putain de bouche' WHERE `id`=536; +UPDATE `ai_playerbot_texts` SET `text_loc2`='me juge pas bordel' WHERE `id`=537; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ta mère est tellement grosse qu’elle passe même pas le Portail des Ténèbres' WHERE `id`=538; +UPDATE `ai_playerbot_texts` SET `text_loc2`='wtf' WHERE `id`=539; +UPDATE `ai_playerbot_texts` SET `text_loc2`='wtf ??' WHERE `id`=540; +UPDATE `ai_playerbot_texts` SET `text_loc2`='vie misérable' WHERE `id`=541; +UPDATE `ai_playerbot_texts` SET `text_loc2`='qu’est-ce qui se passe là ?' WHERE `id`=542; +UPDATE `ai_playerbot_texts` SET `text_loc2`='nul à chier' WHERE `id`=543; +UPDATE `ai_playerbot_texts` SET `text_loc2`='REVANCHE !!! Je vais l’éclater' WHERE `id`=544; +UPDATE `ai_playerbot_texts` SET `text_loc2`='pathétique, je me suis fait tuer par %s' WHERE `id`=545; +UPDATE `ai_playerbot_texts` SET `text_loc2`='ok j’en ai fini' WHERE `id`=546; +UPDATE `ai_playerbot_texts` SET `text_loc2`='hé hé, j’ai explosé %s ?' WHERE `id`=547; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’était trop facile, d\'exploser %s' WHERE `id`=548; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es grillé, clochard' WHERE `id`=549; +UPDATE `ai_playerbot_texts` SET `text_loc2`='ha ha' WHERE `id`=550; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Loser' WHERE `id`=551; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai tué %s et vous êtes tous les prochains, les gars' WHERE `id`=552; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh ouais, je l’ai éclaté' WHERE `id`=553; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis une machine à tuer' WHERE `id`=554; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, ça me rappelle un morceau de Slayer… tout ce sang, c’est beau' WHERE `id`=555; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Désolé %s. On peut refaire la scène ?' WHERE `id`=556; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Alors %s… ça fait quoi de nourrir les vers ???' WHERE `id`=557; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’étais censé être mort %s ! C’est dans le script bon sang !' WHERE `id`=558; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Désolé %s. Franchement, c’était aussi beau qu’un Warhol !' WHERE `id`=559; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, je prendrai les balles en caoutchouc la prochaine fois, promis !' WHERE `id`=560; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Qu’est-ce qu’il y a %s ?? T’as perdu la tête ? Hahaha, faut rester cool !' WHERE `id`=561; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Fallait que je le fasse %s… Le Réalisateur me l’a dit !' WHERE `id`=562; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %s… MUAHAHAHAHAHAHAHAHAHAHA' WHERE `id`=563; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, celle-là, je l’ai savourée !! Allez, on recommence Sam !' WHERE `id`=564; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %s ! Tu peux commencer à m’appeler Scarface… espèce de M…erde !' WHERE `id`=565; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu me parles à moi %s ?? Tu me parles à MOI ?!' WHERE `id`=566; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, fais-le bien cette fois, évite MES balles.' WHERE `id`=567; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, pourquoi tu traînes par terre ? Allez bouge !' WHERE `id`=568; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai rigolé comme jamais' WHERE `id`=569; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut %s' WHERE `id`=570; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh, salut %s' WHERE `id`=571; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Wazzup %s !!!' WHERE `id`=572; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut' WHERE `id`=573; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Wazzup' WHERE `id`=574; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour %s' WHERE `id`=575; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut %s, je te connais ?' WHERE `id`=576; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %s' WHERE `id`=577; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hai %s' WHERE `id`=578; +UPDATE `ai_playerbot_texts` SET `text_loc2`='c’est quoi ce délire' WHERE `id`=579; +UPDATE `ai_playerbot_texts` SET `text_loc2`='wtf' WHERE `id`=580; +UPDATE `ai_playerbot_texts` SET `text_loc2`='c’est du foutage de gueule' WHERE `id`=581; +UPDATE `ai_playerbot_texts` SET `text_loc2`='admin' WHERE `id`=582; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %s, arrête d’abuser de ton admin là' WHERE `id`=583; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Lâche-moi admin !' WHERE `id`=584; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es nul admin' WHERE `id`=585; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est mon nom ça, tu veux quoi %s ?' WHERE `id`=586; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oui ???' WHERE `id`=587; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Euh… quoi ?' WHERE `id`=588; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu me parles à moi %s ?' WHERE `id`=589; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai des chiots sous mon armure !' WHERE `id`=590; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mords-moi, !' WHERE `id`=591; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey ! Devine ce que ta mère a dit hier soir !' WHERE `id`=592; +UPDATE `ai_playerbot_texts` SET `text_loc2`=', t’es tellement moche que tu pourrais même pas scorer dans un bordel de singes avec un sac de bananes !' WHERE `id`=593; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tais-toi , tu seras jamais l’homme que ta mère est !!' WHERE `id`=594; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ta mère était un hamster et ton père sentait la surette !' WHERE `id`=595; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne veux plus te parler, espèce de vide-écuelle à bestiaux débiles !!!' WHERE `id`=596; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pète dans ta direction générale !!!' WHERE `id`=597; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Va faire bouillir ton postérieur, fils d’un imbécile cosmique !!!' WHERE `id`=598; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu comptes faire quoi , saigner sur moi ? ALLEZ, VIENS !' WHERE `id`=599; +UPDATE `ai_playerbot_texts` SET `text_loc2`='M-O-O-N ! Ça veut dire aggro !' WHERE `id`=600; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es aussi utile qu’un unijambiste dans un concours de coups de pied au cul' WHERE `id`=601; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey ! Arrête de draguer, c’est pas ton genre. C’est pas gonflable.' WHERE `id`=602; +UPDATE `ai_playerbot_texts` SET `text_loc2`=', t’es tellement hors catégorie que tu joues carrément à un autre sport' WHERE `id`=603; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu as fait une grosse erreur aujourd’hui … t’es sorti du lit.' WHERE `id`=604; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je veux essayer de me transformer en cheval. Je prends l’avant, et toi… tu restes toi.' WHERE `id`=605; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux emprunter ton visage ? Mon cul part en vacances.' WHERE `id`=606; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’aimerais t’offrir un cadeau de départ… d’abord, fais ta part.' WHERE `id`=607; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Avant que t’arrives, on avait faim. Maintenant on en a juste marre.' WHERE `id`=608; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je t’aime bien. Les gens disent que j’ai mauvais goût, mais je t’aime bien.' WHERE `id`=609; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pense que t’as un complexe d’infériorité… mais t’inquiète, il est mérité.' WHERE `id`=610; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Arrière, créature pourrie ! Ou je secoue tes os hors de ta tunique !' WHERE `id`=611; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je crois pas que je perds mon temps avec toi… et pourtant !' WHERE `id`=612; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’adore quand on m’insulte : j’ai plus besoin d’être poli.' WHERE `id`=613; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Espèce de veston de cuir, boutons en cristal, tête nouée, braillard à gerbe, jarretière de puce, langue mielleuse, bourse espagnole !' WHERE `id`=614; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Espèce de pleurnichard, chasseur de chauve-souris, ivrogne de malte !' WHERE `id`=615; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es vraiment une idole pour les adorateurs de l’idiotie !' WHERE `id`=616; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Misérable piaf mal dégrossi !' WHERE `id`=617; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Fils de mandragore ! T’es plus utile en plumeau qu’en laquais !' WHERE `id`=618; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Toi ! Gueux ! Cloporte ! Tarlouze ! Je vais chatouiller ta catastrophe !' WHERE `id`=619; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh ! Infâme fille de lin mal élevé !' WHERE `id`=620; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On fuit par ta cheminée, !' WHERE `id`=621; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh toi, misérable fleur de cancre gorgée de marais !' WHERE `id`=622; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Si j’étais comme toi, je me jetterais à la poubelle.' WHERE `id`=623; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Apprends-moi … à ne plus penser du tout.' WHERE `id`=624; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es maudit comme un œuf mal rôti… tout cramé d’un côté.' WHERE `id`=625; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Espèce de gringalet, de peau de hareng, de langue de bœuf séchée, de… souffle… taureau démembré, morceau de corde ! Queue d’épée, boîte à rien, tige de tailleur !' WHERE `id`=626; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Fi ! Qu’on te jette dans la bouche pourrie de la Mort !' WHERE `id`=627; +UPDATE `ai_playerbot_texts` SET `text_loc2`=', t’es poissonnier, avoue !' WHERE `id`=628; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vivrai assez pour te défoncer le crâne !' WHERE `id`=629; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es aussi profond qu’une flaque ! , t’es bonne pour les vers, pas pour la viande !' WHERE `id`=630; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Vermine ! Ô , espèce de noisette infernale puante !' WHERE `id`=631; +UPDATE `ai_playerbot_texts` SET `text_loc2`=' ! Ton baiser est aussi réconfortant qu’un glaçon pour un serpent affamé !' WHERE `id`=632; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je te méprise, compagnon galeux. Quoi, pauvre arnaqueur sans chemise ! Dégage, raclure moisie !' WHERE `id`=633; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hors de ma vue ! Tu infectes mes yeux !' WHERE `id`=634; +UPDATE `ai_playerbot_texts` SET `text_loc2`='HEURE DE JEU !!!!' WHERE `id`=635; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Personne ne passera !' WHERE `id`=636; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On est attaqués ! Hissez les voiles ! Repoussez les intrus !' WHERE `id`=637; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Personne ne défie la Confrérie !' WHERE `id`=638; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Imbéciles… tuez celui en robe !' WHERE `id`=639; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais offrir ton âme à Hakkar lui-même !' WHERE `id`=640; +UPDATE `ai_playerbot_texts` SET `text_loc2`='L’orgueil annonce la fin de ton monde ! Venez, mortels ! Affrontez la colère de la %randomfaction !' WHERE `id`=641; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tous mes plans menaient à CE moment !' WHERE `id`=642; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ahh ! Encore des agneaux pour l’abattoir !' WHERE `id`=643; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Encore une journée, encore une glorieuse bataille !' WHERE `id`=644; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Alors, affaires… ou plaisir ?' WHERE `id`=645; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Vous n’êtes pas préparés !' WHERE `id`=646; +UPDATE `ai_playerbot_texts` SET `text_loc2`='La conquête finale de la %randomfaction a commencé ! Cette fois, aucun ne survivra !' WHERE `id`=647; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ta mort sera douloureuse.' WHERE `id`=648; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Implore pitié ! Tes vies inutiles vont être sacrifiées.' WHERE `id`=649; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Abandonne tout espoir ! La %randomfaction est revenue pour finir ce qui a commencé… et cette fois, pas d’échappatoire !' WHERE `id`=650; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Alerte ! Tu es marqué pour l’EXTERMINATION !' WHERE `id`=651; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Le %subzone est réservé aux invités seulement…' WHERE `id`=652; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ha ha ha ! Tu es totalement dépassé !' WHERE `id`=653; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais écraser tes illusions de grandeur !' WHERE `id`=654; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pardonne-moi, mais tu vas perdre cette partie.' WHERE `id`=655; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Résister ne fait qu’empirer les choses.' WHERE `id`=656; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Vermine ! Sangsues ! Prends mon sang et étouffe-toi avec !' WHERE `id`=657; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pas encore… PAS ENCORE !' WHERE `id`=658; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mon sang sera ta perte !' WHERE `id`=659; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Parfait. Maintenant bats-toi contre moi !' WHERE `id`=660; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Allez les gardes ! C’est l’heure de tuer !' WHERE `id`=661; +UPDATE `ai_playerbot_texts` SET `text_loc2`='N’attends pas la mort, viens à moi. Je rendrai ton sacrifice rapide.' WHERE `id`=662; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu seras mort très bientôt !' WHERE `id`=663; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mouahaha !' WHERE `id`=664; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est moi le prédateur ! Toi, la proie...' WHERE `id`=665; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu vas repartir en morceaux !' WHERE `id`=666; +UPDATE `ai_playerbot_texts` SET `text_loc2`='La mort approche... As-tu la conscience tranquille ?' WHERE `id`=667; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ton comportement ne sera pas toléré.' WHERE `id`=668; +UPDATE `ai_playerbot_texts` SET `text_loc2`='La Ménagerie est réservée aux invités.' WHERE `id`=669; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hmm, des visiteurs non annoncés… Il faut se préparer…' WHERE `id`=670; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Entités hostiles détectées. Évaluation de menace en cours. Cible principale verrouillée. Réévaluation dans trente secondes.' WHERE `id`=671; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Des nouveaux jouets ? Pour moi ? Promis, je les casse pas… cette fois !' WHERE `id`=672; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis prêt à jouer !' WHERE `id`=673; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Chut… tout sera fini bientôt.' WHERE `id`=674; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Aaaaaughibbrgubugbugrguburgle !' WHERE `id`=675; +UPDATE `ai_playerbot_texts` SET `text_loc2`='RwlRwlRwlRwl !' WHERE `id`=676; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Toi aussi, tu serviras !' WHERE `id`=677; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Dis-moi... dis-moi tout ! Tes vilains petits secrets ! Je vais les arracher de ta chair !' WHERE `id`=678; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Préparez-vous, les cloches ont sonné ! Protégez vos faibles, vos jeunes et vos vieux ! Chacun paiera le prix final ! Implorerez-vous pitié ? Le Jugement est arrivé !' WHERE `id`=679; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mais où suis-je, par les boutons en laiton de Bonzo ?' WHERE `id`=680; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’en peux plus ! Roi Gobelin ! Roi Gobelin ! Où que tu sois ! Emporte ce loin de moi !' WHERE `id`=681; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu as treize heures pour résoudre le labyrinthe... sinon ton petit frère deviendra l’un des nôtres... pour toujours.' WHERE `id`=682; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Alors, le c’est du gâteau, hein ? Voyons comment tu gères ce petit bout-là…' WHERE `id`=683; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Recule, j’vais t’affronter. Déterminé, prêt à affronter n’importe qui. J’sais que t’as tort, t’as rien à faire ici !' WHERE `id`=684; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Montre-moi c’que t’as dans le ventre !' WHERE `id`=685; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Jusqu’à la mort !' WHERE `id`=686; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Double lame, pour un rasage net à chaque fois !' WHERE `id`=687; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Allez, viens !' WHERE `id`=688; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu vas tomber !' WHERE `id`=689; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Piou piou, coup de couteau !' WHERE `id`=690; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Finissons-en vite, le temps c’est du mana.' WHERE `id`=691; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne crois pas que tu réalises dans quelle merde tu es.' WHERE `id`=692; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais faire honneur à ma famille et à mon royaume !' WHERE `id`=693; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Lumière, donne-moi la force !' WHERE `id`=694; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mon église, c’est le champ de bataille – l’heure de la messe a sonné !' WHERE `id`=695; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je te tiens en mépris total…' WHERE `id`=696; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Affronte le marteau de la justice !' WHERE `id`=697; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Prouve ta valeur dans l’épreuve des armes, sous la Lumière !' WHERE `id`=698; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tous doivent tomber devant la puissance de ma cause – tu es le prochain !' WHERE `id`=699; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Prépare-toi à mourir !' WHERE `id`=700; +UPDATE `ai_playerbot_texts` SET `text_loc2`='La bête en moi est bien pire que celle à mes côtés…' WHERE `id`=701; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Admire la puissance de feu d’un chasseur totalement équipé !' WHERE `id`=702; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Soigne-moi ! Vite !' WHERE `id`=703; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis presque mort ! Soignez-moi !' WHERE `id`=704; +UPDATE `ai_playerbot_texts` SET `text_loc2`='À l’aide ! Soignez-moi !' WHERE `id`=705; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un ! Un soin vite !' WHERE `id`=706; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Heal ! Heal ! Heal !' WHERE `id`=707; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je meurs ! Soin ! Aaaaarhg !' WHERE `id`=708; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Soignez-moi !' WHERE `id`=709; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais mourir. Je vais mourir. Je vais mourir. Soignez-moi !' WHERE `id`=710; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Healers, vous êtes où ? Je crève !' WHERE `id`=711; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ouille, la douleur ! Soignez vite !' WHERE `id`=712; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin de soin' WHERE `id`=713; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Vie basse !' WHERE `id`=714; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Lâche un heal. S’il te plaît.' WHERE `id`=715; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut me balancer un soin ?' WHERE `id`=716; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey ! Mieux vaut me soigner maintenant que me rez plus tard !' WHERE `id`=717; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Désolé… mais encore un heal, please.' WHERE `id`=718; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Saletés de mobs… heal moi vite !' WHERE `id`=719; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Encore un coup et je suis mort. Un petit heal ?' WHERE `id`=720; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a des soigneurs dans cette galère ?' WHERE `id`=721; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi c’est toujours ma tête qu’ils frappent ? J’ai besoin d’un soin !' WHERE `id`=722; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un pour me soigner un chouïa ?' WHERE `id`=723; +UPDATE `ai_playerbot_texts` SET `text_loc2`='OOM' WHERE `id`=724; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus de mana !' WHERE `id`=725; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai cramé tout mon mana pour ça, sérieux...' WHERE `id`=726; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Faudrait attendre que je boive ou que je régène, là…' WHERE `id`=727; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mana faible… très faible…' WHERE `id`=728; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Encore à sec ? Pas de mana, encore.' WHERE `id`=729; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mana bas. Je veux une boisson !' WHERE `id`=730; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On a une machine à boissons ? J’ai encore plus rien !' WHERE `id`=731; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mon mana ? Parti dans les limbes.' WHERE `id`=732; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’achèterai des boissons la prochaine fois. Là j’ai que dalle.' WHERE `id`=733; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Où est passé mon mana ?' WHERE `id`=734; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Il me reste quelques !' WHERE `id`=735; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin de plus de !' WHERE `id`=736; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus que 100 !' WHERE `id`=737; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est fini ! Plus un seul !' WHERE `id`=738; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Et tu as mon arc… oups, plus de !' WHERE `id`=739; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin de munitions !' WHERE `id`=740; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh mon dieu !' WHERE `id`=741; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai peur… là… vraiment.' WHERE `id`=742; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On est foutus !' WHERE `id`=743; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est fini. F.I.N.I.' WHERE `id`=744; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ça se termine maintenant.' WHERE `id`=745; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut balancer un blizzard ou un truc ?!' WHERE `id`=746; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mince. Le tank a aggro TOUT le monde…' WHERE `id`=747; +UPDATE `ai_playerbot_texts` SET `text_loc2`='On va mourir. On va mourir. On VA MOURIR !' WHERE `id`=748; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Wow ! Tant de jouets à casser !' WHERE `id`=749; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais tous les buter ! TOUS !' WHERE `id`=750; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Si le tank meurt, c’est foutu pour nous tous…' WHERE `id`=751; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Aaaaaargh !' WHERE `id`=752; +UPDATE `ai_playerbot_texts` SET `text_loc2`='LEEEEERROOOYYYYYYYYYYYY JENNKINNNSSSSSS !!!!!!!!' WHERE `id`=753; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Bon. Qu’est-ce qu’on a en AOE là ?' WHERE `id`=754; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ça devient intéressant…' WHERE `id`=755; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Cool. Regroupez-les bien pour une jolie boule de feu !' WHERE `id`=756; +UPDATE `ai_playerbot_texts` SET `text_loc2`='TUEZ ! TUEZ ! TUEZ !' WHERE `id`=757; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je crois que j’ai mouillé mon pantalon…' WHERE `id`=758; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est notre fin. C’était sympa.' WHERE `id`=759; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère que les healers sont prêts… LEEEEROYYYY !' WHERE `id`=760; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourvu qu’ils ne me ciblent pas moi…' WHERE `id`=761; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh non. Je peux pas regarder ce massacre…' WHERE `id`=762; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère qu’il y aura de la thune.' WHERE `id`=763; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Loot ! LOOT !' WHERE `id`=764; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mon précieux…' WHERE `id`=765; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère qu’un bel objet épique m’attend là-dedans' WHERE `id`=766; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai des poches profondes et des sacs encore vides.' WHERE `id`=767; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Tout est à moi !' WHERE `id`=768; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Pas de gris moisi aujourd’hui, pitié…' WHERE `id`=769; +UPDATE `ai_playerbot_texts` SET `text_loc2`='CE loot est À MOI !' WHERE `id`=770; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Looter c’est sale… mais j’ai besoin de thunes.' WHERE `id`=771; +UPDATE `ai_playerbot_texts` SET `text_loc2`='De l’or !' WHERE `id`=772; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ok. Voyons ce qu’ils ont laissé…' WHERE `id`=773; +UPDATE `ai_playerbot_texts` SET `text_loc2`='T’inquiète, je vais tout looter. Tout.' WHERE `id`=774; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis un ninja du loot.' WHERE `id`=775; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je dois lancer les dés ?' WHERE `id`=776; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut m’expliquer où ils ont rangé tout ça ?' WHERE `id`=777; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Non, je loot pas cette merde grise.' WHERE `id`=778; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est moi d’abord ! C’est moi ! MOI !' WHERE `id`=779; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Donne-moi ton fric !' WHERE `id`=780; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Mes poches sont vides, il faut les remplir.' WHERE `id`=781; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai un nouveau sac, il est fait pour ça.' WHERE `id`=782; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère que je vais pas aggro en lootant…' WHERE `id`=783; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ne regardez pas… je loot discret…' WHERE `id`=784; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Ha ! Vous n’aurez rien de tout ça !' WHERE `id`=785; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Le loot, c’est stylé.' WHERE `id`=786; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’adore les nouveaux équipements.' WHERE `id`=787; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je me casse si y’a encore rien de valeur…' WHERE `id`=788; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère que ce sera une jolie bague !' WHERE `id`=789; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais t’arracher le loot des mains !' WHERE `id`=790; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Personne ne touche à rien. C’est MOI qui loot.' WHERE `id`=791; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Loot sucré :D' WHERE `id`=792; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Dieu du lancer, donne-moi un épique aujourd’hui…' WHERE `id`=793; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Allez, de nouveaux jouets s’il vous plaît !' WHERE `id`=794; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère qu’ils ont des trucs savoureux…' WHERE `id`=795; +UPDATE `ai_playerbot_texts` SET `text_loc2`='L’or est à moi. Je laisse tout le reste… promis…' WHERE `id`=796; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Non, je peux pas résister.' WHERE `id`=797; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’en veux ENCORE !' WHERE `id`=798; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis presque là, attendez-moi !' WHERE `id`=799; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis pas loin, attendez-moi !' WHERE `id`=800; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’arrive vers ta position' WHERE `id`=801; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’arrive vers toi' WHERE `id`=802; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je me dirige vers ta position' WHERE `id`=803; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’essaie de te rejoindre' WHERE `id`=804; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Équipement de %item' WHERE `id`=805; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%item retiré' WHERE `id`=806; +UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai appris les sorts : %spells' WHERE `id`=807; +UPDATE `ai_playerbot_texts` SET `text_loc2`='%item est en recharge' WHERE `id`=808; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’ai pas %item dans mon inventaire' WHERE `id`=809; +UPDATE `ai_playerbot_texts` SET `text_loc2`='L’objet avec l’ID %item n’existe pas' WHERE `id`=810; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Insertion de %gem dans %item' WHERE `id`=811; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas utiliser %item' WHERE `id`=812; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Suivi' WHERE `id`=813; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je reste ici' WHERE `id`=814; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je fuis' WHERE `id`=815; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je fuis pas avec toi, t’es trop loin !' WHERE `id`=816; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Farm en cours' WHERE `id`=817; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Attaque en cours' WHERE `id`=818; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est trop loin' WHERE `id`=819; +UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est sous l’eau' WHERE `id`=820; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas y aller' WHERE `id`=821; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne suis pas dans ta guilde !' WHERE `id`=822; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Impossible de trouver une banque de guilde à proximité' WHERE `id`=823; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas déposer' WHERE `id`=824; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’ai pas les droits pour déposer dans le premier onglet de la banque de guilde' WHERE `id`=825; +UPDATE `ai_playerbot_texts` SET `text_loc2`='déposé dans la banque de guilde' WHERE `id`=826; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Déplacement libre' WHERE `id`=827; +UPDATE `ai_playerbot_texts` SET `text_loc2`='En garde' WHERE `id`=828; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Utilisation de %target' WHERE `id`=829; +UPDATE `ai_playerbot_texts` SET `text_loc2`='sur %unit' WHERE `id`=830; +UPDATE `ai_playerbot_texts` SET `text_loc2`='(%amount disponible)' WHERE `id`=831; +UPDATE `ai_playerbot_texts` SET `text_loc2`='(le dernier)' WHERE `id`=832; +UPDATE `ai_playerbot_texts` SET `text_loc2`='La châsse ne correspond pas' WHERE `id`=833; +UPDATE `ai_playerbot_texts` SET `text_loc2`='sur objet d’échange' WHERE `id`=834; +UPDATE `ai_playerbot_texts` SET `text_loc2`='sur moi-même' WHERE `id`=835; +UPDATE `ai_playerbot_texts` SET `text_loc2`='sur %item' WHERE `id`=836; +UPDATE `ai_playerbot_texts` SET `text_loc2`='sur %gameobject' WHERE `id`=837; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Loot de %item' WHERE `id`=838; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Invocation de %target' WHERE `id`=839; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’ai pas assez de membres du groupe à proximité pour invoquer' WHERE `id`=840; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Impossible de trouver la cible d’invocation' WHERE `id`=841; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas invoquer en combat' WHERE `id`=842; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne connais pas le sort %spell' WHERE `id`=843; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Lancement du sort %spell' WHERE `id`=844; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Fabrication de %spell' WHERE `id`=845; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Impossible de lancer %spell' WHERE `id`=846; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Échec du lancement de %spell' WHERE `id`=847; +UPDATE `ai_playerbot_texts` SET `text_loc2`='|cffffff00(x%amount restant)|r' WHERE `id`=848; +UPDATE `ai_playerbot_texts` SET `text_loc2`='dummy' WHERE `id`=849; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Par la Lumière... J\'ai oublié mes Symboles du roi. On se contentera de %base_spell !' WHERE `id`=934; +UPDATE `ai_playerbot_texts` SET `text_loc2`='La nature est généreuse, pas mes sacs... plus d\'herbes pour %group_spell. Prenez %base_spell pour l\'instant !' WHERE `id`=935; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus de poudre des arcanes... %group_spell attendra. Je lance %base_spell !' WHERE `id`=936; +UPDATE `ai_playerbot_texts` SET `text_loc2`='Oups, je n\'ai plus de composants pour %group_spell. On fera avec %base_spell !' WHERE `id`=937; + From 5b9b3d7672293f5b02a92056ee359afb99f48168 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:43:24 +0200 Subject: [PATCH 10/32] remove wrong sql file --- ...025_09_18_00_ai_playerbot_french_texts.sql | 856 ------------------ 1 file changed, 856 deletions(-) delete mode 100644 data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql diff --git a/data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql b/data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql deleted file mode 100644 index 55f57c50eb..0000000000 --- a/data/sql/playerbots/updates/2025_09_18_00_ai_playerbot_french_texts.sql +++ /dev/null @@ -1,856 +0,0 @@ -UPDATE ai_playerbot_texts SET text_loc2 = ''; - -UPDATE `ai_playerbot_texts` SET `text_loc2`='au milieu de nulle part' WHERE `id`=1; -UPDATE `ai_playerbot_texts` SET `text_loc2`='un endroit non divulgué' WHERE `id`=2; -UPDATE `ai_playerbot_texts` SET `text_loc2`='quelque part' WHERE `id`=3; -UPDATE `ai_playerbot_texts` SET `text_loc2`='un truc' WHERE `id`=4; -UPDATE `ai_playerbot_texts` SET `text_loc2`='je me demande quel goût a %item_link' WHERE `id`=5; -UPDATE `ai_playerbot_texts` SET `text_loc2`='noooon, j’ai eu %item_link' WHERE `id`=6; -UPDATE `ai_playerbot_texts` SET `text_loc2`='oh non, encore cette camelote %item_link' WHERE `id`=7; -UPDATE `ai_playerbot_texts` SET `text_loc2`='on dirait que je ramasse des ordures %item_link' WHERE `id`=8; -UPDATE `ai_playerbot_texts` SET `text_loc2`='bon, c’est mieux que rien je suppose %item_link' WHERE `id`=9; -UPDATE `ai_playerbot_texts` SET `text_loc2`='je ne sais pas quoi faire de %item_link' WHERE `id`=10; -UPDATE `ai_playerbot_texts` SET `text_loc2`='je me demande quel goût a %item_link' WHERE `id`=11; -UPDATE `ai_playerbot_texts` SET `text_loc2`='je pourrais ramasser du %item_link toute la journée' WHERE `id`=12; -UPDATE `ai_playerbot_texts` SET `text_loc2`='un jour de plus, un %item_link de plus' WHERE `id`=13; -UPDATE `ai_playerbot_texts` SET `text_loc2`='j’ai ramassé un peu de %item_link' WHERE `id`=14; -UPDATE `ai_playerbot_texts` SET `text_loc2`='un peu de %item_link, c’est toujours ça' WHERE `id`=15; -UPDATE `ai_playerbot_texts` SET `text_loc2`='pas mal, je viens de choper %item_link' WHERE `id`=16; -UPDATE `ai_playerbot_texts` SET `text_loc2`='je viens de ramasser %item_link à %zone_name' WHERE `id`=17; -UPDATE `ai_playerbot_texts` SET `text_loc2`='je pourrais bien l’utiliser ça %item_link' WHERE `id`=18; -UPDATE `ai_playerbot_texts` SET `text_loc2`='argent, argent, argent %item_link' WHERE `id`=19; -UPDATE `ai_playerbot_texts` SET `text_loc2`='j’ai eu %item_link' WHERE `id`=20; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_link est BiS pour les chasseurs' WHERE `id`=21; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_link est BiS pour les %my_class' WHERE `id`=22; -UPDATE `ai_playerbot_texts` SET `text_loc2`='la chance est avec moi aujourd’hui %item_link' WHERE `id`=23; -UPDATE `ai_playerbot_texts` SET `text_loc2`='trop bon %item_link, fraîchement looté' WHERE `id`=24; -UPDATE `ai_playerbot_texts` SET `text_loc2`='wow, je viens de choper %item_link' WHERE `id`=25; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_link est BiS pour les chasseurs' WHERE `id`=26; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_link est BiS pour les %my_class' WHERE `id`=27; -UPDATE `ai_playerbot_texts` SET `text_loc2`='la chance est avec moi aujourd’hui %item_link' WHERE `id`=28; -UPDATE `ai_playerbot_texts` SET `text_loc2`='trop bon %item_link, fraîchement looté' WHERE `id`=29; -UPDATE `ai_playerbot_texts` SET `text_loc2`='OMG, regardez ce que je viens de looter %item_link !!!' WHERE `id`=30; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Noooon ! C’est pas possible, j’ai eu %item_link, c’est de la folie' WHERE `id`=31; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Noooon ! C’est pas possible, j’ai eu %item_link, c’est de la folie' WHERE `id`=32; -UPDATE `ai_playerbot_texts` SET `text_loc2`='je viens juste de prendre la quête %quest_link' WHERE `id`=33; -UPDATE `ai_playerbot_texts` SET `text_loc2`='je viens d’accepter %quest_link' WHERE `id`=34; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_link je vais essayer de la finir' WHERE `id`=35; -UPDATE `ai_playerbot_texts` SET `text_loc2`='j’ai pris %quest_link à %zone_name' WHERE `id`=36; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Enfin fini l’objectif %quest_obj_name pour %quest_link' WHERE `id`=37; -UPDATE `ai_playerbot_texts` SET `text_loc2`='j’ai enfin %quest_obj_available/%quest_obj_required de %quest_obj_name pour %quest_link' WHERE `id`=38; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_obj_full_formatted pour %quest_link, enfin !' WHERE `id`=39; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oof, j’ai %quest_obj_available/%quest_obj_required %quest_obj_name pour %quest_link' WHERE `id`=40; -UPDATE `ai_playerbot_texts` SET `text_loc2`='il me manque encore %quest_obj_missing de %quest_obj_name pour %quest_link' WHERE `id`=41; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_obj_full_formatted, je bosse toujours sur %quest_link' WHERE `id`=42; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Enfin fini avec %item_link pour %quest_link' WHERE `id`=43; -UPDATE `ai_playerbot_texts` SET `text_loc2`='j’ai enfin %quest_obj_available/%quest_obj_required de %item_link pour %quest_link' WHERE `id`=44; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_obj_full_formatted pour %quest_link, enfin !' WHERE `id`=45; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oof, j’ai %quest_obj_available/%quest_obj_required %item_link pour %quest_link' WHERE `id`=46; -UPDATE `ai_playerbot_texts` SET `text_loc2`='il me manque encore %quest_obj_missing de %item_link pour %quest_link' WHERE `id`=47; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_obj_full_formatted, je suis encore sur %quest_link' WHERE `id`=48; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Échec : je n’ai pas fini %quest_link à temps...' WHERE `id`=49; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus de temps pour %quest_link :(' WHERE `id`=50; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai terminé tous les objectifs de %quest_link' WHERE `id`=51; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Objectifs terminés pour %quest_link' WHERE `id`=52; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais rendre %quest_link bientôt, tout est fait' WHERE `id`=53; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ouiii, j’ai enfin rendu %quest_link' WHERE `id`=54; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_link rendu' WHERE `id`=55; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mission %quest_link terminée, rendu !' WHERE `id`=56; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_link rendu' WHERE `id`=57; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%quest_link rendu à %zone_name' WHERE `id`=58; -UPDATE `ai_playerbot_texts` SET `text_loc2`='encore un %victim_name à terre' WHERE `id`=59; -UPDATE `ai_playerbot_texts` SET `text_loc2`='je continue à tuer %victim_name, la routine quoi' WHERE `id`=60; -UPDATE `ai_playerbot_texts` SET `text_loc2`='un autre %victim_name qui mord la poussière' WHERE `id`=61; -UPDATE `ai_playerbot_texts` SET `text_loc2`='un %victim_name en moins à %zone_name' WHERE `id`=62; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai descendu ce sale élite %victim_name !' WHERE `id`=63; -UPDATE `ai_playerbot_texts` SET `text_loc2`='élite %victim_name éliminé à %zone_name' WHERE `id`=64; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ouf, j’ai réussi à abattre %victim_name !' WHERE `id`=65; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’était épique ! %victim_name est tombé, maintenant j’ai une histoire à raconter' WHERE `id`=66; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Yoo, je viens de tuer %victim_name !' WHERE `id`=67; -UPDATE `ai_playerbot_texts` SET `text_loc2`='rare %victim_name éliminé à %zone_name' WHERE `id`=68; -UPDATE `ai_playerbot_texts` SET `text_loc2`='WTF ais-je bien tué? %victim_name' WHERE `id`=69; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai tué cette bestiole %victim_name' WHERE `id`=70; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh ouiii, j’ai tué %victim_name' WHERE `id`=71; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%victim_name éliminé à %zone_name' WHERE `id`=72; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ding !' WHERE `id`=73; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ouiii, je suis niveau %my_level !' WHERE `id`=74; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je viens de passer un niveau' WHERE `id`=75; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis niveau %my_level !!!' WHERE `id`=76; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je deviens plus fort, déjà %my_level !!!' WHERE `id`=77; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je viens d’atteindre le niveau %my_level !!!' WHERE `id`=78; -UPDATE `ai_playerbot_texts` SET `text_loc2`='OMG, enfin niveau %my_level !!!' WHERE `id`=79; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_level !!! prêt pour le contenu endgame' WHERE `id`=80; -UPDATE `ai_playerbot_texts` SET `text_loc2`='tout frais, nouveau %my_level %my_class !!!' WHERE `id`=81; -UPDATE `ai_playerbot_texts` SET `text_loc2`='encore un niveau %my_level %my_race %my_class !' WHERE `id`=82; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bien joué %other_name. Tu l’as mérité.' WHERE `id`=83; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’était affreux %other_name. J’ai détesté faire ça mais...' WHERE `id`=84; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un veut faire %instance_name ?' WHERE `id`=85; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Des groupes pour %instance_name ?' WHERE `id`=86; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’aide pour %instance_name ?' WHERE `id`=87; -UPDATE `ai_playerbot_texts` SET `text_loc2`='LFD : %instance_name.' WHERE `id`=88; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a besoin d’un %my_role pour %instance_name ?' WHERE `id`=89; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Il manque un %my_role pour %instance_name ?' WHERE `id`=90; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux être %my_role pour %instance_name.' WHERE `id`=91; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’un coup de main à %instance_name ?' WHERE `id`=92; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’un %my_role pour %instance_name ?' WHERE `id`=93; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a besoin de loot à %instance_name ?' WHERE `id`=94; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Un petit farm à %instance_name ?' WHERE `id`=95; -UPDATE `ai_playerbot_texts` SET `text_loc2`='WTR %instance_name' WHERE `id`=96; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’aide pour %instance_name.' WHERE `id`=97; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie de faire %instance_name.' WHERE `id`=98; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_role cherche un groupe pour %instance_name.' WHERE `id`=99; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Et %instance_name, on y va ?' WHERE `id`=100; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut farmer %instance_name ?' WHERE `id`=101; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On entre dans %instance_name ?' WHERE `id`=102; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je cherche groupe pour %instance_name.' WHERE `id`=103; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Des quêtes à %instance_name ?' WHERE `id`=104; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie de faire des quêtes à %instance_name.' WHERE `id`=105; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un avec des quêtes à %instance_name ?' WHERE `id`=106; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux aider pour les quêtes à %instance_name.' WHERE `id`=107; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_role : une place dispo pour %instance_name ?' WHERE `id`=108; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Est-ce que quelqu’un fait encore %instance_name de nos jours ?' WHERE `id`=109; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%instance_name : quelqu’un cherche un %my_role ?' WHERE `id`=110; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ça sert encore à quelque chose d’être %my_role à %instance_name ?' WHERE `id`=111; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ça vaut vraiment le coup d’aller à %instance_name ?' WHERE `id`=112; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a besoin de plus de joueurs pour %instance_name ?' WHERE `id`=113; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Les boss de %instance_name lootent du bon matos. On y va ?' WHERE `id`=114; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Alors, %instance_name ?' WHERE `id`=115; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a besoin d’un %my_role ?' WHERE `id`=116; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a besoin d’un %my_role ?' WHERE `id`=117; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut aller à %instance_name ?' WHERE `id`=118; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut me TP à %instance_name ?' WHERE `id`=119; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Retrouve-moi à %instance_name' WHERE `id`=120; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie d’un petit run rapide à %instance_name ?' WHERE `id`=121; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On se fait un run complet à %instance_name ?' WHERE `id`=122; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’as été combien de fois à %instance_name ?' WHERE `id`=123; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Encore un run à %instance_name ?' WHERE `id`=124; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Wipe à %instance_name ? Prends-moi, je suis un porte-bonheur !' WHERE `id`=125; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Emmène-moi à %instance_name s’il te plaît.' WHERE `id`=126; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Un petit %instance_name vite fait bien fait ?' WHERE `id`=127; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Full %instance_name jusqu’à la fin ?' WHERE `id`=128; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui peut prendre un %my_role à %instance_name ?' WHERE `id`=129; -UPDATE `ai_playerbot_texts` SET `text_loc2`='LFG %instance_name, je suis %my_role' WHERE `id`=130; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_role cherche groupe pour %instance_name' WHERE `id`=131; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’aide pour %quest_link ?' WHERE `id`=132; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un veut partager %quest_link ?' WHERE `id`=133; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un fait %quest_link ?' WHERE `id`=134; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On fait %quest_link ?' WHERE `id`=135; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un pour farmer du %category ?' WHERE `id`=136; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Cherche aide pour farmer %category.' WHERE `id`=137; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ces %category coûtent un bras !' WHERE `id`=138; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin de %category.' WHERE `id`=139; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’aide pour %category.' WHERE `id`=140; -UPDATE `ai_playerbot_texts` SET `text_loc2`='WTB %category.' WHERE `id`=141; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un est intéressé par %category ?' WHERE `id`=142; -UPDATE `ai_playerbot_texts` SET `text_loc2`='WTS %category.' WHERE `id`=143; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vends %category moins cher que l’HV.' WHERE `id`=144; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut farmer du %category ?' WHERE `id`=145; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On farme du %category ?' WHERE `id`=146; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je cherche un groupe, après ça on fait du %category ?' WHERE `id`=147; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tous les %category sont les bienvenus.' WHERE `id`=148; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’achète tout ce qui ressemble à du %category.' WHERE `id`=149; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Wow, y’a des gens qui farment encore du %category ?' WHERE `id`=150; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Les %category partent comme des petits pains à l’HV !' WHERE `id`=151; -UPDATE `ai_playerbot_texts` SET `text_loc2`='L’HV brûle à cause des %category !' WHERE `id`=152; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a des %category sur le marché.' WHERE `id`=153; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J\'échange des %category ?' WHERE `id`=154; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Il me faut plus de %category.' WHERE `id`=155; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a un peu de %category à donner ?' WHERE `id`=156; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut du %category ?' WHERE `id`=157; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Un peu de %category s’il vous plaît ?' WHERE `id`=158; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’aurais dû monter une compétence pour les %category.' WHERE `id`=159; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je meurs d’envie d’avoir des %category.' WHERE `id`=160; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Les gens se tuent pour les %category.' WHERE `id`=161; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%category, c’est une affaire en or !' WHERE `id`=162; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tout le monde devient fou pour les %category !' WHERE `id`=163; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est où le meilleur spot pour farmer des %category ?' WHERE `id`=164; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis prêt pour le farm de %category.' WHERE `id`=165; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ça se vend bien les %category ?' WHERE `id`=166; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais garder tous mes %category. Pour moi.' WHERE `id`=167; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’un groupe ? On pourrait farm des %category ensemble.' WHERE `id`=168; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pense encore aux %category.' WHERE `id`=169; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai entendu parler des %category... mais mon porte-monnaie ne veut pas.' WHERE `id`=170; -UPDATE `ai_playerbot_texts` SET `text_loc2`='LFG pour %category' WHERE `id`=171; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Vendre %category rend riche ?' WHERE `id`=172; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ok. Demain je farm les %category.' WHERE `id`=173; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tout le monde parle des %category.' WHERE `id`=174; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai vu au moins dix gars farmer du %category.' WHERE `id`=175; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai tout vendu mes %category hier. Maintenant je mange du pain sec!' WHERE `id`=176; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie de rejoindre une guilde qui farme du %category.' WHERE `id`=177; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un farm la réputation %faction ?' WHERE `id`=178; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut m’aider pour %faction ?' WHERE `id`=179; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On fait des quêtes pour %faction ?' WHERE `id`=180; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%faction, c’est la crème de la crème. Paraît-il.' WHERE `id`=181; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Il me manque juste un tout petit peu pour être %rep_level avec %faction.' WHERE `id`=182; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un est %rep_level avec %faction ?' WHERE `id`=183; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut devenir %rep_level avec %faction ?' WHERE `id`=184; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je serai jamais %rep_level avec %faction.' WHERE `id`=185; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a oublié de monter la réputation %faction ?' WHERE `id`=186; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux aider à farmer la réputation %faction.' WHERE `id`=187; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus on a de réputation, mieux c’est. Surtout avec %faction.' WHERE `id`=188; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%faction : il me faut encore %rndK pour être %rep_level.' WHERE `id`=189; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui peut partager des quêtes %faction ?' WHERE `id`=190; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Des donjons pour la réputation %faction ?' WHERE `id`=191; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On farm la réput %faction ?' WHERE `id`=192; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Allons-y pour %faction !' WHERE `id`=193; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je farm la réputation %faction.' WHERE `id`=194; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On farme pour %faction ?' WHERE `id`=195; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin d’aide pour %faction.' WHERE `id`=196; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%faction vend quelque chose d’utile ?' WHERE `id`=197; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Il existe des vendeurs %faction ?' WHERE `id`=198; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui farme %faction ?' WHERE `id`=199; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelle est la meilleure façon de farmer %faction ?' WHERE `id`=200; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je déteste farmer la réputation %faction.' WHERE `id`=201; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’en ai marre de %faction.' WHERE `id`=202; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On y va pour %faction ?' WHERE `id`=203; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tout le monde est %rep_level avec %faction. Et moi, je galère encore.' WHERE `id`=204; -UPDATE `ai_playerbot_texts` SET `text_loc2`='LFG pour farm de réputation %faction ?' WHERE `id`=205; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a un bon spot pour la réputation %faction ?' WHERE `id`=206; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Améliorer ma réput %faction, ça sert ?' WHERE `id`=207; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui aurait cru que la réputation %faction finirait par servir...' WHERE `id`=208; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je veux être exalté avec toutes les factions. En commençant par %faction.' WHERE `id`=209; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Est-ce que ça vaut le coup de monter %faction ?' WHERE `id`=210; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qu’est-ce qui marche le mieux pour %faction ? Les quêtes ou tuer des mobs ?' WHERE `id`=211; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je farm %faction pour toi, si tu me paies.' WHERE `id`=212; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Farmer la réputation %faction ? Ça prendra 3 vies au moins.' WHERE `id`=213; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je tue pour %faction tous les jours, mais je suis toujours pas %rep_level.' WHERE `id`=214; -UPDATE `ai_playerbot_texts` SET `text_loc2`='À %my_level, les dépôts à l’HV vont baisser, non ?' WHERE `id`=215; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Combien de réputations exaltées tu as ?' WHERE `id`=216; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut être %my_level avec %faction ?' WHERE `id`=217; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ma guilde a farmé la réputation %faction hier. Sans moi...' WHERE `id`=218; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Personne ne veut m’aider, tout ça parce que je suis %rep_level avec %faction.' WHERE `id`=219; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Évitez la %faction.' WHERE `id`=220; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On se fait une soirée à %zone_name ?' WHERE `id`=221; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un cherche un %my_role ?' WHERE `id`=222; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_role cherche une guilde.' WHERE `id`=223; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je cherche de l’or.' WHERE `id`=224; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%my_role cherche une bonne guilde.' WHERE `id`=225; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin d’un ami.' WHERE `id`=226; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un d’autre se sent seul ?' WHERE `id`=227; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je m’ennuie...' WHERE `id`=228; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui en veut ?' WHERE `id`=229; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Allez viens te battre !' WHERE `id`=230; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Un petit duel à %zone_name ?' WHERE `id`=231; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un fait quelque chose ici ?' WHERE `id`=232; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name : y’a une âme qui vive ici ?' WHERE `id`=233; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name : tout le monde est en furtif ou quoi ?' WHERE `id`=234; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On dirait que je suis seul à %zone_name.' WHERE `id`=235; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Rejoins-moi à %zone_name .' WHERE `id`=236; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Allez, on fait des quêtes à %zone_name !' WHERE `id`=237; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name c’est LE coin sympa du momment.' WHERE `id`=238; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’veux aller à %zone_name. Quelqu’un me suit ?' WHERE `id`=239; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut aller à %zone_name ?' WHERE `id`=240; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’aime pas %zone_name. Où doi-je aller ?' WHERE `id`=241; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a de bonnes quêtes à %zone_name ?' WHERE `id`=242; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On va où après %zone_name ?' WHERE `id`=243; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui traîne à %zone_name ?' WHERE `id`=244; -UPDATE `ai_playerbot_texts` SET `text_loc2`='LFG pour %zone_name.' WHERE `id`=245; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name est l’endroit le plus naze du monde.' WHERE `id`=246; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Attrape-moi à %zone_name si tu peux !' WHERE `id`=247; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Direction %zone_name !' WHERE `id`=248; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie de quêtes à %zone_name' WHERE `id`=249; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a des quêtes à %zone_name ?' WHERE `id`=250; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Venez à %zone_name !' WHERE `id`=251; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On dirait que la Horde a déserté %zone_name...' WHERE `id`=252; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On dirait que l’Alliance a déserté %zone_name...' WHERE `id`=253; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’en peux plus de %zone_name. Quelqu’un me sort de là ?' WHERE `id`=254; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonne chance !' WHERE `id`=255; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je veux rentrer chez moi… puis pleurer au bord du vide' WHERE `id`=256; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un sait ce qu’il faut pour jouer double arme ?' WHERE `id`=257; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut tout le monde !' WHERE `id`=258; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name est cosy' WHERE `id`=259; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je me sens bien' WHERE `id`=260; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’ignore pas les gens. Je les trolle jusqu’à ce qu’ils m’ignorent.' WHERE `id`=261; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Que pensez-vous de mon build ? %my_role' WHERE `id`=262; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Heureux de voir que le chat ne m’a pas oublié' WHERE `id`=263; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Comme toutes les armes, c’est BiS pour chasseur' WHERE `id`=264; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Le but du jeu pour moi ? Solo tout ce qui bouge.' WHERE `id`=265; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai JAMAIS arnaqué personne.' WHERE `id`=266; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ah, World of Warcraft. Là où je viens chercher des conseils de vie.' WHERE `id`=267; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’A QUELQU’UN ?!' WHERE `id`=268; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Il est temps de me frayer un chemin dans %zone_name.' WHERE `id`=269; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%zone_name' WHERE `id`=270; -UPDATE `ai_playerbot_texts` SET `text_loc2`='… faut que j’aille aux toilettes.' WHERE `id`=271; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Si tu loot pas tes mobs skinables, ton zizi perd 1mm. C’est la règle.' WHERE `id`=272; -UPDATE `ai_playerbot_texts` SET `text_loc2`='NOOOOOOOOOOOOO' WHERE `id`=273; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’AIME LA PATATE' WHERE `id`=274; -UPDATE `ai_playerbot_texts` SET `text_loc2`='La discussion est animée.' WHERE `id`=275; -UPDATE `ai_playerbot_texts` SET `text_loc2`='salut, comment ça va les gens ?' WHERE `id`=276; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je viens de me déco / reco.' WHERE `id`=277; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Faites moins de bruit, j’suis perdu dans %zone_name…' WHERE `id`=278; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un veut boire un verre à %zone_name ? hic' WHERE `id`=279; -UPDATE `ai_playerbot_texts` SET `text_loc2`='hahahahaheeeee dirin diring inggggg hahahahaheeeeeeeeeeeeee' WHERE `id`=280; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Avant, les appâts étaient crédibles.' WHERE `id`=281; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Peut-être que t’as juste perdu ton innocence.' WHERE `id`=282; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a une guilde qui veut carry un %my_role fragile ?' WHERE `id`=283; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus on monte en niveau, plus l’or coule à flots' WHERE `id`=284; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour !' WHERE `id`=285; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi j’ai mal au cul ?' WHERE `id`=286; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pense que l’esprit est BiS pour monter de niveau.' WHERE `id`=287; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Encore plus si t’es troll.' WHERE `id`=288; -UPDATE `ai_playerbot_texts` SET `text_loc2`='QUELQU’UN PEUT M’INVITER ?' WHERE `id`=289; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin de beaucouuuup de boissons.' WHERE `id`=290; -UPDATE `ai_playerbot_texts` SET `text_loc2`='P*utain de gnomes…' WHERE `id`=291; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Personne n’aime les gnomes.' WHERE `id`=292; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Les gnomes ne servent qu’à une chose' WHERE `id`=293; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bah…' WHERE `id`=294; -UPDATE `ai_playerbot_texts` SET `text_loc2`='… des champignons.' WHERE `id`=295; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Les pensées automatiques, c’est flippant.' WHERE `id`=296; -UPDATE `ai_playerbot_texts` SET `text_loc2`='L’esprit est plus malléable qu’on aimerait le croire.' WHERE `id`=297; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a des guildes pour leveling ?' WHERE `id`=298; -UPDATE `ai_playerbot_texts` SET `text_loc2`='brb' WHERE `id`=299; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi la neige est blanche mais la glace est transparente ? Mystère.' WHERE `id`=300; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi la crème fouettée est fluffy, mais pas la normale ?' WHERE `id`=301; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi les pieds sentent alors qu’ils n’ont pas de nez ?' WHERE `id`=302; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On dirait que la boîte à noobs vient de s’ouvrir.' WHERE `id`=303; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Arrêtez de troller les nouveaux avec vos réponses à la con.' WHERE `id`=304; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a du PvP sur ce serveur ?' WHERE `id`=305; -UPDATE `ai_playerbot_texts` SET `text_loc2`='évidemment...' WHERE `id`=306; -UPDATE `ai_playerbot_texts` SET `text_loc2`='ouf… :)' WHERE `id`=307; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Vous saviez que' WHERE `id`=308; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne tente pas d’imaginer ce que ressentent les autres créatures' WHERE `id`=309; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oups, mauvais canal.' WHERE `id`=310; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bruh, vous êtes déchaînés aujourd’hui' WHERE `id`=311; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Juste pour que tout le monde sache : mon message est passé ici' WHERE `id`=312; -UPDATE `ai_playerbot_texts` SET `text_loc2`='grrr énervéééééé' WHERE `id`=313; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Le farm, c’est marrant' WHERE `id`=314; -UPDATE `ai_playerbot_texts` SET `text_loc2`='WoW me garde vif' WHERE `id`=315; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hé, question : où on prend le rôle pour plus d’XP ? Je suis à %zone_name.' WHERE `id`=316; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Vous aimez les saucisses ?' WHERE `id`=317; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Invitez-moi. Je peux aider.' WHERE `id`=318; -UPDATE `ai_playerbot_texts` SET `text_loc2`='À votre avis, quelle classe est la meilleure en PvP ?' WHERE `id`=319; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Où est ce foutu maître de cuisine à %zone_name ?!' WHERE `id`=320; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Vous savez ce qu’il se passe à %zone_name ?' WHERE `id`=321; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin de crafter quelque chose' WHERE `id`=322; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est quoi lèchemes' WHERE `id`=323; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est quoi sucemes ' WHERE `id`=324; -UPDATE `ai_playerbot_texts` SET `text_loc2`='lèchemes couilles' WHERE `id`=325; -UPDATE `ai_playerbot_texts` SET `text_loc2`='sucemes couilles' WHERE `id`=326; -UPDATE `ai_playerbot_texts` SET `text_loc2`='JE MANGE DES FESSES' WHERE `id`=327; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai envie de me fourrer %random_inventory_item_link là où le soleil ne brille pas' WHERE `id`=328; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai envie de te fourrer %random_inventory_item_link là où tu penses' WHERE `id`=329; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Darnasses' WHERE `id`=330; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On dirait que t’as chopé le syndrôme de sucemes' WHERE `id`=331; -UPDATE `ai_playerbot_texts` SET `text_loc2`='cesnoix dans ta bouche' WHERE `id`=332; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Sympa ton os, frérot' WHERE `id`=333; -UPDATE `ai_playerbot_texts` SET `text_loc2`='ERP ?' WHERE `id`=334; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai tout essayé, mais au final c’est l’ERP qui a marché' WHERE `id`=335; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai envie de batifoler à %zone_name' WHERE `id`=336; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Recherche gnome femelle avec gorille pour ERP sauvage à %zone_name' WHERE `id`=337; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux comprendre un idiot, mais un gros pervers ?' WHERE `id`=338; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Aucun GYAT en vue à %zone_name' WHERE `id`=339; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je tue tous les animaux de %zone_name. Désolé WWF !' WHERE `id`=340; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Heureusement que j’ai trois jambes' WHERE `id`=341; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Sois pas vénère, je goon comme un sigma' WHERE `id`=342; -UPDATE `ai_playerbot_texts` SET `text_loc2`='essaye doigt, mais trou' WHERE `id`=343; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%prefix %random_taken_quest_or_item_link' WHERE `id`=344; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%prefix %random_inventory_item_link' WHERE `id`=345; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%thunderfury_link' WHERE `id`=346; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%thunderfury_link%thunderfury_link' WHERE `id`=347; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%thunderfury_link%thunderfury_link%thunderfury_link' WHERE `id`=348; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je crois que je viens d’entendre %thunderfury_link' WHERE `id`=349; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai entendu %thunderfury_link' WHERE `id`=350; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai clairement entendu %thunderfury_link' WHERE `id`=351; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’suis pas sûr, mais j’crois avoir entendu %thunderfury_link' WHERE `id`=352; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’as dit %thunderfury_link' WHERE `id`=353; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a dit %thunderfury_link' WHERE `id`=354; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a VRAIMENT dit %thunderfury_link' WHERE `id`=355; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un a parlé de %thunderfury_link' WHERE `id`=356; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%thunderfury_link sort du placard, les gars' WHERE `id`=357; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’aurais juré que c’était un %thunderfury_link… ou peut-être un %thunderfury_link' WHERE `id`=358; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi utiliser %thunderfury_link alors que %thunderfury_link est bien plus OP' WHERE `id`=359; -UPDATE `ai_playerbot_texts` SET `text_loc2`='WTS %item_formatted_link pour %cost_gold.' WHERE `id`=360; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui veut %item_formatted_link pour %cost_gold ?' WHERE `id`=361; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un veut %item_formatted_link ? Seulement %cost_gold' WHERE `id`=362; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Juste %cost_gold pour %item_formatted_link!' WHERE `id`=363; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vends %item_formatted_link pour %cost_gold' WHERE `id`=364; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_formatted_link est à toi pour seulement %cost_gold !' WHERE `id`=365; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Prix ridicule : %cost_gold pour %item_formatted_link !' WHERE `id`=366; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je cherche à vendre %item_formatted_link pour %cost_gold' WHERE `id`=367; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui a besoin de %item_formatted_link ? Seulement %cost_gold' WHERE `id`=368; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un veut %item_formatted_link pour %cost_gold ?' WHERE `id`=369; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%cost_gold pour %item_formatted_link. Moins cher qu’à l’HV !' WHERE `id`=370; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_formatted_link est cher, mais je te le fais à %cost_gold' WHERE `id`=371; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu trouveras jamais %item_formatted_link moins cher que %cost_gold!' WHERE `id`=372; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin de plus que %item_formatted_link, là !' WHERE `id`=373; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai %item_formatted_link et j’en veux encore' WHERE `id`=374; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai %item_formatted_link. Qui l’achète pour %cost_gold ?' WHERE `id`=375; -UPDATE `ai_playerbot_texts` SET `text_loc2`='WTB %item_formatted_link pour %cost_gold, quelqu’un ?' WHERE `id`=376; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Et %item_formatted_link ? Pour %cost_gold.' WHERE `id`=377; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui m’a traité d\'arnaqueur ? %item_formatted_link pour %cost_gold c’est honnête !' WHERE `id`=378; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vends %item_formatted_link. Juste %cost_gold' WHERE `id`=379; -UPDATE `ai_playerbot_texts` SET `text_loc2`='LFG pour du farm, et au passage %item_formatted_link à vendre %cost_gold' WHERE `id`=380; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Presque tout vendu aujourd’hui. Me reste %item_formatted_link pour %cost_gold' WHERE `id`=381; -UPDATE `ai_playerbot_texts` SET `text_loc2`='À quoi sert le canal commerce ? A vendre %item_formatted_link pour %cost_gold, évidemment' WHERE `id`=382; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut battre %cost_gold pour %item_formatted_link ?' WHERE `id`=383; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Envie d’arrêter le spam commerce ? Achetez %item_formatted_link à %cost_gold !' WHERE `id`=384; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tout le monde spam, moi aussi : %cost_gold pour %item_formatted_link !' WHERE `id`=385; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%item_formatted_link est utile ? Je sais pas, mais je le vends %cost_gold' WHERE `id`=386; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai %item_formatted_link prêt à vendre %cost_gold' WHERE `id`=387; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hier j’ai rien foutu, mais j’ai loot %item_formatted_link. À vendre %cost_gold' WHERE `id`=388; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai farmé hier, j’ai eu %item_formatted_link. WTB ? %cost_gold' WHERE `id`=389; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai acheté %item_formatted_link hier. Quelqu’un le veut ? %cost_gold' WHERE `id`=390; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un cherchait %item_formatted_link ? C’est %cost_gold toujours' WHERE `id`=391; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai encore %item_formatted_link. Achetez-le %cost_gold' WHERE `id`=392; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Avant j’en avais plein %item_formatted_link, maintenant je dois vendre à %cost_gold' WHERE `id`=393; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’aimerais en avoir plus que %item_formatted_link. Mais achetez celui-là %cost_gold' WHERE `id`=394; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ton or te sert à quoi ? À acheter %item_formatted_link pour %cost_gold' WHERE `id`=395; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ayez pitié, donnez-moi de l’or... ou achetez %item_formatted_link %cost_gold' WHERE `id`=396; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Est-ce que %cost_gold est un bon prix pour %item_formatted_link ?' WHERE `id`=397; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai acheté %item_formatted_links hier, mais j’en veux plus. Quelqu\'un vends pour %cost_gold' WHERE `id`=398; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais le mettre à l’HV %item_formatted_link, mais tu peux l’avoir moins cher : %cost_gold' WHERE `id`=399; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi j’ai acheté %item_formatted_link bordel ? Quelqu’un le veut ? %cost_gold' WHERE `id`=400; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai %quest_links' WHERE `id`=401; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Moi aussi j’ai %quest_links' WHERE `id`=402; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Moi aussi j’ai %quest_links, je suis à %zone_name' WHERE `id`=403; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, moi aussi j’ai %quest_links' WHERE `id`=404; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, moi aussi j’ai %quest_links, et je suis à %zone_name' WHERE `id`=405; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis dispo pour %quest_links, je suis à %zone_name' WHERE `id`=406; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=407; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, je suis dispo pour %quest_links à %zone_name' WHERE `id`=408; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=409; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey, je suis partant pour %quest_links' WHERE `id`=410; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey, je pourrais faire %quest_links avec toi' WHERE `id`=411; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey, moi aussi j’ai %quest_links' WHERE `id`=412; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %other_name, partant pour %quest_links' WHERE `id`=413; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %other_name, je peux faire %quest_links avec toi' WHERE `id`=414; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %other_name, moi aussi j’ai %quest_links' WHERE `id`=415; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On se groupe pour %quest_links ?' WHERE `id`=416; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis partant pour %quest_links, je suis à %zone_name' WHERE `id`=417; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis dispo pour %quest_links, je suis %my_role' WHERE `id`=418; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, je peux te vendre %formatted_item_links' WHERE `id`=419; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux peut-être vendre %formatted_item_links' WHERE `id`=420; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pense pouvoir vendre %formatted_item_links' WHERE `id`=421; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, je peux peut-être te vendre %formatted_item_links' WHERE `id`=422; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%other_name, tu penses que je peux vendre %formatted_item_links ?' WHERE `id`=423; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux te vendre %formatted_item_links' WHERE `id`=424; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey, j’ai %formatted_item_links à vendre' WHERE `id`=425; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey, je pourrais peut-être vendre %formatted_item_links' WHERE `id`=426; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quête acceptée' WHERE `id`=427; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quête abandonnée' WHERE `id`=428; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas prendre cette quête' WHERE `id`=429; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas parler au donneur de quête' WHERE `id`=430; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai déjà terminé %quest' WHERE `id`=431; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai déjà la quête %quest' WHERE `id`=432; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas prendre %quest' WHERE `id`=433; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas prendre %quest, mon journal de quêtes est plein' WHERE `id`=434; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas prendre %quest, mes sacs sont pleins' WHERE `id`=435; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai accepté la quête %quest' WHERE `id`=436; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’ai pas encore terminé la quête %quest' WHERE `id`=437; -UPDATE `ai_playerbot_texts` SET `text_loc2`='La quête %quest est dispo' WHERE `id`=438; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai échoué à la quête %quest' WHERE `id`=439; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas rendre la quête %quest' WHERE `id`=440; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai terminé la quête %quest' WHERE `id`=441; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai terminé la quête %quest et reçu %item' WHERE `id`=442; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelle récompense devrais-je choisir pour la quête %quest ? %rewards' WHERE `id`=443; -UPDATE `ai_playerbot_texts` SET `text_loc2`='OK, je vais prendre %item comme récompense' WHERE `id`=444; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour' WHERE `id`=445; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour !' WHERE `id`=446; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut' WHERE `id`=447; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut !' WHERE `id`=448; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut à toi !' WHERE `id`=449; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour, je vous suis !' WHERE `id`=450; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour, montrez-moi le chemin !' WHERE `id`=451; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut, montre-moi le chemin !' WHERE `id`=452; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %player, tu veux rejoindre mon groupe ?' WHERE `id`=453; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %player, tu veux rejoindre mon groupe ?' WHERE `id`=454; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Déconnexion annulée !' WHERE `id`=455; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je me déconnecte !' WHERE `id`=456; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Au revoir !' WHERE `id`=457; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bye bye !' WHERE `id`=458; -UPDATE `ai_playerbot_texts` SET `text_loc2`='À plus tard !' WHERE `id`=459; -UPDATE `ai_playerbot_texts` SET `text_loc2`='c’était quoi ce truc %s ?' WHERE `id`=460; -UPDATE `ai_playerbot_texts` SET `text_loc2`='pas sûr d’avoir compris %s ?' WHERE `id`=461; -UPDATE `ai_playerbot_texts` SET `text_loc2`='euh… j’ai aucune idée de ce que tu racontes' WHERE `id`=462; -UPDATE `ai_playerbot_texts` SET `text_loc2`='tu parles à moi, %s ?' WHERE `id`=463; -UPDATE `ai_playerbot_texts` SET `text_loc2`='whaaaa ?' WHERE `id`=464; -UPDATE `ai_playerbot_texts` SET `text_loc2`='hein ?' WHERE `id`=465; -UPDATE `ai_playerbot_texts` SET `text_loc2`='quoi ?' WHERE `id`=466; -UPDATE `ai_playerbot_texts` SET `text_loc2`='tu parles ou tu râles ?' WHERE `id`=467; -UPDATE `ai_playerbot_texts` SET `text_loc2`='comme tu veux, mec' WHERE `id`=468; -UPDATE `ai_playerbot_texts` SET `text_loc2`='tu m’as perdu là' WHERE `id`=469; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bla bla bla…' WHERE `id`=470; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’as dit quoi, %s ?' WHERE `id`=471; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Concentre-toi sur le jeu, %s !' WHERE `id`=472; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Parler avec toi %s, c’est génial ! J’ai toujours rêvé de te rencontrer' WHERE `id`=473; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ces messages me font flipper ! J’ai l’impression de tous vous connaître !' WHERE `id`=474; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ouais bien sûr ! HAHA ! C’est ça, allez !' WHERE `id`=475; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je te crois !!!' WHERE `id`=476; -UPDATE `ai_playerbot_texts` SET `text_loc2`='OK, uhuh LOL' WHERE `id`=477; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi tout le monde dit toujours les mêmes trucs ???' WHERE `id`=478; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %s… euh, laisse tomber !' WHERE `id`=479; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu parles de quoi %s ? Sérieux ?' WHERE `id`=480; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qui a dit ça ? Je me sens visé là' WHERE `id`=481; -UPDATE `ai_playerbot_texts` SET `text_loc2`='wtf vous racontez tous là ?' WHERE `id`=482; -UPDATE `ai_playerbot_texts` SET `text_loc2`='fr fr no cap on a stack' WHERE `id`=483; -UPDATE `ai_playerbot_texts` SET `text_loc2`='t’auras que dalle' WHERE `id`=484; -UPDATE `ai_playerbot_texts` SET `text_loc2`='swag' WHERE `id`=485; -UPDATE `ai_playerbot_texts` SET `text_loc2`='merci !' WHERE `id`=486; -UPDATE `ai_playerbot_texts` SET `text_loc2`='non' WHERE `id`=487; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Yep' WHERE `id`=488; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Paix à son ame.' WHERE `id`=489; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s sans déconner xD' WHERE `id`=490; -UPDATE `ai_playerbot_texts` SET `text_loc2`='pourquoi ça ?' WHERE `id`=491; -UPDATE `ai_playerbot_texts` SET `text_loc2`='mdr' WHERE `id`=492; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pensais fermer ma gueule, j’ai encore rien compris au chat' WHERE `id`=493; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux devenir vraiment jaloux... comme un elfe sans loot' WHERE `id`=494; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s tu captes pas le sarcasme qui dégouline de mon message là ?' WHERE `id`=495; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Il a dit "no homo", donc c’est bon apparemment' WHERE `id`=496; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Instant nain' WHERE `id`=497; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oui %s' WHERE `id`=498; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Intéressant…' WHERE `id`=499; -UPDATE `ai_playerbot_texts` SET `text_loc2`='lol' WHERE `id`=500; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s va te faire voir mec :D' WHERE `id`=501; -UPDATE `ai_playerbot_texts` SET `text_loc2`=':^)' WHERE `id`=502; -UPDATE `ai_playerbot_texts` SET `text_loc2`='merci' WHERE `id`=503; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s bien dit !' WHERE `id`=504; -UPDATE `ai_playerbot_texts` SET `text_loc2`='ouiiiii' WHERE `id`=505; -UPDATE `ai_playerbot_texts` SET `text_loc2`='ouais' WHERE `id`=506; -UPDATE `ai_playerbot_texts` SET `text_loc2`='ooooooh' WHERE `id`=507; -UPDATE `ai_playerbot_texts` SET `text_loc2`='hmm' WHERE `id`=508; -UPDATE `ai_playerbot_texts` SET `text_loc2`='ouais c’est ça' WHERE `id`=509; -UPDATE `ai_playerbot_texts` SET `text_loc2`='t’as failli me faire vomir, wtf' WHERE `id`=510; -UPDATE `ai_playerbot_texts` SET `text_loc2`='chaud !' WHERE `id`=511; -UPDATE `ai_playerbot_texts` SET `text_loc2`='les rageux pleurent' WHERE `id`=512; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’as mangé quoi %s ?' WHERE `id`=513; -UPDATE `ai_playerbot_texts` SET `text_loc2`='wtf' WHERE `id`=514; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais essayer de comprendre ce que t’as dit' WHERE `id`=515; -UPDATE `ai_playerbot_texts` SET `text_loc2`='*confus*' WHERE `id`=516; -UPDATE `ai_playerbot_texts` SET `text_loc2`='putain ouais' WHERE `id`=517; -UPDATE `ai_playerbot_texts` SET `text_loc2`='0/10 ne lirait pas ça une deuxième fois' WHERE `id`=518; -UPDATE `ai_playerbot_texts` SET `text_loc2`='10/10 je relis direct' WHERE `id`=519; -UPDATE `ai_playerbot_texts` SET `text_loc2`='6/10 ouais, pourquoi pas' WHERE `id`=520; -UPDATE `ai_playerbot_texts` SET `text_loc2`='7/10 ça passe' WHERE `id`=521; -UPDATE `ai_playerbot_texts` SET `text_loc2`='basé' WHERE `id`=522; -UPDATE `ai_playerbot_texts` SET `text_loc2`='ah ouais peut-être' WHERE `id`=523; -UPDATE `ai_playerbot_texts` SET `text_loc2`='ouais, et alors ?' WHERE `id`=524; -UPDATE `ai_playerbot_texts` SET `text_loc2`='hey %s je t’ai pas oublié' WHERE `id`=525; -UPDATE `ai_playerbot_texts` SET `text_loc2`='tu m’énerves %s' WHERE `id`=526; -UPDATE `ai_playerbot_texts` SET `text_loc2`='je vais t’avoir cette fois %s' WHERE `id`=527; -UPDATE `ai_playerbot_texts` SET `text_loc2`='garde un œil derrière toi %s' WHERE `id`=528; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai pas trop aimé la manche d’avant' WHERE `id`=529; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai été nul au dernier round à cause de %s' WHERE `id`=530; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Prépare-toi à mourir %s' WHERE `id`=531; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai pas trop kiffé que tu me tues %s' WHERE `id`=532; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, je te hais' WHERE `id`=533; -UPDATE `ai_playerbot_texts` SET `text_loc2`='grrrrr je vais t’avoir cette fois %s' WHERE `id`=534; -UPDATE `ai_playerbot_texts` SET `text_loc2`='eh bien va te faire foutre' WHERE `id`=535; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s je vais vomir dans ta putain de bouche' WHERE `id`=536; -UPDATE `ai_playerbot_texts` SET `text_loc2`='me juge pas bordel' WHERE `id`=537; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ta mère est tellement grosse qu’elle passe même pas le Portail des Ténèbres' WHERE `id`=538; -UPDATE `ai_playerbot_texts` SET `text_loc2`='wtf' WHERE `id`=539; -UPDATE `ai_playerbot_texts` SET `text_loc2`='wtf ??' WHERE `id`=540; -UPDATE `ai_playerbot_texts` SET `text_loc2`='vie misérable' WHERE `id`=541; -UPDATE `ai_playerbot_texts` SET `text_loc2`='qu’est-ce qui se passe là ?' WHERE `id`=542; -UPDATE `ai_playerbot_texts` SET `text_loc2`='nul à chier' WHERE `id`=543; -UPDATE `ai_playerbot_texts` SET `text_loc2`='REVANCHE !!! Je vais l’éclater' WHERE `id`=544; -UPDATE `ai_playerbot_texts` SET `text_loc2`='pathétique, je me suis fait tuer par %s' WHERE `id`=545; -UPDATE `ai_playerbot_texts` SET `text_loc2`='ok j’en ai fini' WHERE `id`=546; -UPDATE `ai_playerbot_texts` SET `text_loc2`='hé hé, j’ai explosé %s ?' WHERE `id`=547; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’était trop facile, d\'exploser %s' WHERE `id`=548; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es grillé, clochard' WHERE `id`=549; -UPDATE `ai_playerbot_texts` SET `text_loc2`='ha ha' WHERE `id`=550; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Loser' WHERE `id`=551; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai tué %s et vous êtes tous les prochains, les gars' WHERE `id`=552; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh ouais, je l’ai éclaté' WHERE `id`=553; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis une machine à tuer' WHERE `id`=554; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, ça me rappelle un morceau de Slayer… tout ce sang, c’est beau' WHERE `id`=555; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Désolé %s. On peut refaire la scène ?' WHERE `id`=556; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Alors %s… ça fait quoi de nourrir les vers ???' WHERE `id`=557; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’étais censé être mort %s ! C’est dans le script bon sang !' WHERE `id`=558; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Désolé %s. Franchement, c’était aussi beau qu’un Warhol !' WHERE `id`=559; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, je prendrai les balles en caoutchouc la prochaine fois, promis !' WHERE `id`=560; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Qu’est-ce qu’il y a %s ?? T’as perdu la tête ? Hahaha, faut rester cool !' WHERE `id`=561; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Fallait que je le fasse %s… Le Réalisateur me l’a dit !' WHERE `id`=562; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %s… MUAHAHAHAHAHAHAHAHAHAHA' WHERE `id`=563; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, celle-là, je l’ai savourée !! Allez, on recommence Sam !' WHERE `id`=564; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %s ! Tu peux commencer à m’appeler Scarface… espèce de M…erde !' WHERE `id`=565; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu me parles à moi %s ?? Tu me parles à MOI ?!' WHERE `id`=566; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, fais-le bien cette fois, évite MES balles.' WHERE `id`=567; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%s, pourquoi tu traînes par terre ? Allez bouge !' WHERE `id`=568; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai rigolé comme jamais' WHERE `id`=569; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut %s' WHERE `id`=570; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh, salut %s' WHERE `id`=571; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Wazzup %s !!!' WHERE `id`=572; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut' WHERE `id`=573; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Wazzup' WHERE `id`=574; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bonjour %s' WHERE `id`=575; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Salut %s, je te connais ?' WHERE `id`=576; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %s' WHERE `id`=577; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hai %s' WHERE `id`=578; -UPDATE `ai_playerbot_texts` SET `text_loc2`='c’est quoi ce délire' WHERE `id`=579; -UPDATE `ai_playerbot_texts` SET `text_loc2`='wtf' WHERE `id`=580; -UPDATE `ai_playerbot_texts` SET `text_loc2`='c’est du foutage de gueule' WHERE `id`=581; -UPDATE `ai_playerbot_texts` SET `text_loc2`='admin' WHERE `id`=582; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey %s, arrête d’abuser de ton admin là' WHERE `id`=583; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Lâche-moi admin !' WHERE `id`=584; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es nul admin' WHERE `id`=585; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est mon nom ça, tu veux quoi %s ?' WHERE `id`=586; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oui ???' WHERE `id`=587; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Euh… quoi ?' WHERE `id`=588; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu me parles à moi %s ?' WHERE `id`=589; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai des chiots sous mon armure !' WHERE `id`=590; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mords-moi, !' WHERE `id`=591; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey ! Devine ce que ta mère a dit hier soir !' WHERE `id`=592; -UPDATE `ai_playerbot_texts` SET `text_loc2`=', t’es tellement moche que tu pourrais même pas scorer dans un bordel de singes avec un sac de bananes !' WHERE `id`=593; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tais-toi , tu seras jamais l’homme que ta mère est !!' WHERE `id`=594; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ta mère était un hamster et ton père sentait la surette !' WHERE `id`=595; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne veux plus te parler, espèce de vide-écuelle à bestiaux débiles !!!' WHERE `id`=596; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pète dans ta direction générale !!!' WHERE `id`=597; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Va faire bouillir ton postérieur, fils d’un imbécile cosmique !!!' WHERE `id`=598; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu comptes faire quoi , saigner sur moi ? ALLEZ, VIENS !' WHERE `id`=599; -UPDATE `ai_playerbot_texts` SET `text_loc2`='M-O-O-N ! Ça veut dire aggro !' WHERE `id`=600; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es aussi utile qu’un unijambiste dans un concours de coups de pied au cul' WHERE `id`=601; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey ! Arrête de draguer, c’est pas ton genre. C’est pas gonflable.' WHERE `id`=602; -UPDATE `ai_playerbot_texts` SET `text_loc2`=', t’es tellement hors catégorie que tu joues carrément à un autre sport' WHERE `id`=603; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu as fait une grosse erreur aujourd’hui … t’es sorti du lit.' WHERE `id`=604; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je veux essayer de me transformer en cheval. Je prends l’avant, et toi… tu restes toi.' WHERE `id`=605; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je peux emprunter ton visage ? Mon cul part en vacances.' WHERE `id`=606; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’aimerais t’offrir un cadeau de départ… d’abord, fais ta part.' WHERE `id`=607; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Avant que t’arrives, on avait faim. Maintenant on en a juste marre.' WHERE `id`=608; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je t’aime bien. Les gens disent que j’ai mauvais goût, mais je t’aime bien.' WHERE `id`=609; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je pense que t’as un complexe d’infériorité… mais t’inquiète, il est mérité.' WHERE `id`=610; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Arrière, créature pourrie ! Ou je secoue tes os hors de ta tunique !' WHERE `id`=611; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je crois pas que je perds mon temps avec toi… et pourtant !' WHERE `id`=612; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’adore quand on m’insulte : j’ai plus besoin d’être poli.' WHERE `id`=613; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Espèce de veston de cuir, boutons en cristal, tête nouée, braillard à gerbe, jarretière de puce, langue mielleuse, bourse espagnole !' WHERE `id`=614; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Espèce de pleurnichard, chasseur de chauve-souris, ivrogne de malte !' WHERE `id`=615; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es vraiment une idole pour les adorateurs de l’idiotie !' WHERE `id`=616; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Misérable piaf mal dégrossi !' WHERE `id`=617; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Fils de mandragore ! T’es plus utile en plumeau qu’en laquais !' WHERE `id`=618; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Toi ! Gueux ! Cloporte ! Tarlouze ! Je vais chatouiller ta catastrophe !' WHERE `id`=619; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh ! Infâme fille de lin mal élevé !' WHERE `id`=620; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On fuit par ta cheminée, !' WHERE `id`=621; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh toi, misérable fleur de cancre gorgée de marais !' WHERE `id`=622; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Si j’étais comme toi, je me jetterais à la poubelle.' WHERE `id`=623; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Apprends-moi … à ne plus penser du tout.' WHERE `id`=624; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es maudit comme un œuf mal rôti… tout cramé d’un côté.' WHERE `id`=625; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Espèce de gringalet, de peau de hareng, de langue de bœuf séchée, de… souffle… taureau démembré, morceau de corde ! Queue d’épée, boîte à rien, tige de tailleur !' WHERE `id`=626; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Fi ! Qu’on te jette dans la bouche pourrie de la Mort !' WHERE `id`=627; -UPDATE `ai_playerbot_texts` SET `text_loc2`=', t’es poissonnier, avoue !' WHERE `id`=628; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vivrai assez pour te défoncer le crâne !' WHERE `id`=629; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’es aussi profond qu’une flaque ! , t’es bonne pour les vers, pas pour la viande !' WHERE `id`=630; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Vermine ! Ô , espèce de noisette infernale puante !' WHERE `id`=631; -UPDATE `ai_playerbot_texts` SET `text_loc2`=' ! Ton baiser est aussi réconfortant qu’un glaçon pour un serpent affamé !' WHERE `id`=632; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je te méprise, compagnon galeux. Quoi, pauvre arnaqueur sans chemise ! Dégage, raclure moisie !' WHERE `id`=633; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hors de ma vue ! Tu infectes mes yeux !' WHERE `id`=634; -UPDATE `ai_playerbot_texts` SET `text_loc2`='HEURE DE JEU !!!!' WHERE `id`=635; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Personne ne passera !' WHERE `id`=636; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On est attaqués ! Hissez les voiles ! Repoussez les intrus !' WHERE `id`=637; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Personne ne défie la Confrérie !' WHERE `id`=638; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Imbéciles… tuez celui en robe !' WHERE `id`=639; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais offrir ton âme à Hakkar lui-même !' WHERE `id`=640; -UPDATE `ai_playerbot_texts` SET `text_loc2`='L’orgueil annonce la fin de ton monde ! Venez, mortels ! Affrontez la colère de la %randomfaction !' WHERE `id`=641; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tous mes plans menaient à CE moment !' WHERE `id`=642; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ahh ! Encore des agneaux pour l’abattoir !' WHERE `id`=643; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Encore une journée, encore une glorieuse bataille !' WHERE `id`=644; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Alors, affaires… ou plaisir ?' WHERE `id`=645; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Vous n’êtes pas préparés !' WHERE `id`=646; -UPDATE `ai_playerbot_texts` SET `text_loc2`='La conquête finale de la %randomfaction a commencé ! Cette fois, aucun ne survivra !' WHERE `id`=647; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ta mort sera douloureuse.' WHERE `id`=648; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Implore pitié ! Tes vies inutiles vont être sacrifiées.' WHERE `id`=649; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Abandonne tout espoir ! La %randomfaction est revenue pour finir ce qui a commencé… et cette fois, pas d’échappatoire !' WHERE `id`=650; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Alerte ! Tu es marqué pour l’EXTERMINATION !' WHERE `id`=651; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Le %subzone est réservé aux invités seulement…' WHERE `id`=652; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ha ha ha ! Tu es totalement dépassé !' WHERE `id`=653; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais écraser tes illusions de grandeur !' WHERE `id`=654; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pardonne-moi, mais tu vas perdre cette partie.' WHERE `id`=655; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Résister ne fait qu’empirer les choses.' WHERE `id`=656; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Vermine ! Sangsues ! Prends mon sang et étouffe-toi avec !' WHERE `id`=657; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pas encore… PAS ENCORE !' WHERE `id`=658; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mon sang sera ta perte !' WHERE `id`=659; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Parfait. Maintenant bats-toi contre moi !' WHERE `id`=660; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Allez les gardes ! C’est l’heure de tuer !' WHERE `id`=661; -UPDATE `ai_playerbot_texts` SET `text_loc2`='N’attends pas la mort, viens à moi. Je rendrai ton sacrifice rapide.' WHERE `id`=662; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu seras mort très bientôt !' WHERE `id`=663; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mouahaha !' WHERE `id`=664; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est moi le prédateur ! Toi, la proie...' WHERE `id`=665; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu vas repartir en morceaux !' WHERE `id`=666; -UPDATE `ai_playerbot_texts` SET `text_loc2`='La mort approche... As-tu la conscience tranquille ?' WHERE `id`=667; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ton comportement ne sera pas toléré.' WHERE `id`=668; -UPDATE `ai_playerbot_texts` SET `text_loc2`='La Ménagerie est réservée aux invités.' WHERE `id`=669; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hmm, des visiteurs non annoncés… Il faut se préparer…' WHERE `id`=670; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Entités hostiles détectées. Évaluation de menace en cours. Cible principale verrouillée. Réévaluation dans trente secondes.' WHERE `id`=671; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Des nouveaux jouets ? Pour moi ? Promis, je les casse pas… cette fois !' WHERE `id`=672; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis prêt à jouer !' WHERE `id`=673; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Chut… tout sera fini bientôt.' WHERE `id`=674; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Aaaaaughibbrgubugbugrguburgle !' WHERE `id`=675; -UPDATE `ai_playerbot_texts` SET `text_loc2`='RwlRwlRwlRwl !' WHERE `id`=676; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Toi aussi, tu serviras !' WHERE `id`=677; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Dis-moi... dis-moi tout ! Tes vilains petits secrets ! Je vais les arracher de ta chair !' WHERE `id`=678; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Préparez-vous, les cloches ont sonné ! Protégez vos faibles, vos jeunes et vos vieux ! Chacun paiera le prix final ! Implorerez-vous pitié ? Le Jugement est arrivé !' WHERE `id`=679; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mais où suis-je, par les boutons en laiton de Bonzo ?' WHERE `id`=680; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’en peux plus ! Roi Gobelin ! Roi Gobelin ! Où que tu sois ! Emporte ce loin de moi !' WHERE `id`=681; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu as treize heures pour résoudre le labyrinthe... sinon ton petit frère deviendra l’un des nôtres... pour toujours.' WHERE `id`=682; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Alors, le c’est du gâteau, hein ? Voyons comment tu gères ce petit bout-là…' WHERE `id`=683; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Recule, j’vais t’affronter. Déterminé, prêt à affronter n’importe qui. J’sais que t’as tort, t’as rien à faire ici !' WHERE `id`=684; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Montre-moi c’que t’as dans le ventre !' WHERE `id`=685; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Jusqu’à la mort !' WHERE `id`=686; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Double lame, pour un rasage net à chaque fois !' WHERE `id`=687; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Allez, viens !' WHERE `id`=688; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tu vas tomber !' WHERE `id`=689; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Piou piou, coup de couteau !' WHERE `id`=690; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Finissons-en vite, le temps c’est du mana.' WHERE `id`=691; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne crois pas que tu réalises dans quelle merde tu es.' WHERE `id`=692; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais faire honneur à ma famille et à mon royaume !' WHERE `id`=693; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Lumière, donne-moi la force !' WHERE `id`=694; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mon église, c’est le champ de bataille – l’heure de la messe a sonné !' WHERE `id`=695; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je te tiens en mépris total…' WHERE `id`=696; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Affronte le marteau de la justice !' WHERE `id`=697; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Prouve ta valeur dans l’épreuve des armes, sous la Lumière !' WHERE `id`=698; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tous doivent tomber devant la puissance de ma cause – tu es le prochain !' WHERE `id`=699; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Prépare-toi à mourir !' WHERE `id`=700; -UPDATE `ai_playerbot_texts` SET `text_loc2`='La bête en moi est bien pire que celle à mes côtés…' WHERE `id`=701; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Admire la puissance de feu d’un chasseur totalement équipé !' WHERE `id`=702; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Soigne-moi ! Vite !' WHERE `id`=703; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis presque mort ! Soignez-moi !' WHERE `id`=704; -UPDATE `ai_playerbot_texts` SET `text_loc2`='À l’aide ! Soignez-moi !' WHERE `id`=705; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un ! Un soin vite !' WHERE `id`=706; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Heal ! Heal ! Heal !' WHERE `id`=707; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je meurs ! Soin ! Aaaaarhg !' WHERE `id`=708; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Soignez-moi !' WHERE `id`=709; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais mourir. Je vais mourir. Je vais mourir. Soignez-moi !' WHERE `id`=710; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Healers, vous êtes où ? Je crève !' WHERE `id`=711; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ouille, la douleur ! Soignez vite !' WHERE `id`=712; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin de soin' WHERE `id`=713; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Vie basse !' WHERE `id`=714; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Lâche un heal. S’il te plaît.' WHERE `id`=715; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut me balancer un soin ?' WHERE `id`=716; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Hey ! Mieux vaut me soigner maintenant que me rez plus tard !' WHERE `id`=717; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Désolé… mais encore un heal, please.' WHERE `id`=718; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Saletés de mobs… heal moi vite !' WHERE `id`=719; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Encore un coup et je suis mort. Un petit heal ?' WHERE `id`=720; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Y’a des soigneurs dans cette galère ?' WHERE `id`=721; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourquoi c’est toujours ma tête qu’ils frappent ? J’ai besoin d’un soin !' WHERE `id`=722; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un pour me soigner un chouïa ?' WHERE `id`=723; -UPDATE `ai_playerbot_texts` SET `text_loc2`='OOM' WHERE `id`=724; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus de mana !' WHERE `id`=725; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai cramé tout mon mana pour ça, sérieux...' WHERE `id`=726; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Faudrait attendre que je boive ou que je régène, là…' WHERE `id`=727; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mana faible… très faible…' WHERE `id`=728; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Encore à sec ? Pas de mana, encore.' WHERE `id`=729; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mana bas. Je veux une boisson !' WHERE `id`=730; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On a une machine à boissons ? J’ai encore plus rien !' WHERE `id`=731; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mon mana ? Parti dans les limbes.' WHERE `id`=732; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’achèterai des boissons la prochaine fois. Là j’ai que dalle.' WHERE `id`=733; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Où est passé mon mana ?' WHERE `id`=734; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Il me reste quelques !' WHERE `id`=735; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Besoin de plus de !' WHERE `id`=736; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus que 100 !' WHERE `id`=737; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est fini ! Plus un seul !' WHERE `id`=738; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Et tu as mon arc… oups, plus de !' WHERE `id`=739; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai besoin de munitions !' WHERE `id`=740; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh mon dieu !' WHERE `id`=741; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai peur… là… vraiment.' WHERE `id`=742; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On est foutus !' WHERE `id`=743; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est fini. F.I.N.I.' WHERE `id`=744; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ça se termine maintenant.' WHERE `id`=745; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut balancer un blizzard ou un truc ?!' WHERE `id`=746; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mince. Le tank a aggro TOUT le monde…' WHERE `id`=747; -UPDATE `ai_playerbot_texts` SET `text_loc2`='On va mourir. On va mourir. On VA MOURIR !' WHERE `id`=748; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Wow ! Tant de jouets à casser !' WHERE `id`=749; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais tous les buter ! TOUS !' WHERE `id`=750; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Si le tank meurt, c’est foutu pour nous tous…' WHERE `id`=751; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Aaaaaargh !' WHERE `id`=752; -UPDATE `ai_playerbot_texts` SET `text_loc2`='LEEEEERROOOYYYYYYYYYYYY JENNKINNNSSSSSS !!!!!!!!' WHERE `id`=753; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Bon. Qu’est-ce qu’on a en AOE là ?' WHERE `id`=754; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ça devient intéressant…' WHERE `id`=755; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Cool. Regroupez-les bien pour une jolie boule de feu !' WHERE `id`=756; -UPDATE `ai_playerbot_texts` SET `text_loc2`='TUEZ ! TUEZ ! TUEZ !' WHERE `id`=757; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je crois que j’ai mouillé mon pantalon…' WHERE `id`=758; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est notre fin. C’était sympa.' WHERE `id`=759; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère que les healers sont prêts… LEEEEROYYYY !' WHERE `id`=760; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pourvu qu’ils ne me ciblent pas moi…' WHERE `id`=761; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oh non. Je peux pas regarder ce massacre…' WHERE `id`=762; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère qu’il y aura de la thune.' WHERE `id`=763; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Loot ! LOOT !' WHERE `id`=764; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mon précieux…' WHERE `id`=765; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère qu’un bel objet épique m’attend là-dedans' WHERE `id`=766; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai des poches profondes et des sacs encore vides.' WHERE `id`=767; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Tout est à moi !' WHERE `id`=768; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Pas de gris moisi aujourd’hui, pitié…' WHERE `id`=769; -UPDATE `ai_playerbot_texts` SET `text_loc2`='CE loot est À MOI !' WHERE `id`=770; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Looter c’est sale… mais j’ai besoin de thunes.' WHERE `id`=771; -UPDATE `ai_playerbot_texts` SET `text_loc2`='De l’or !' WHERE `id`=772; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ok. Voyons ce qu’ils ont laissé…' WHERE `id`=773; -UPDATE `ai_playerbot_texts` SET `text_loc2`='T’inquiète, je vais tout looter. Tout.' WHERE `id`=774; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis un ninja du loot.' WHERE `id`=775; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je dois lancer les dés ?' WHERE `id`=776; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Quelqu’un peut m’expliquer où ils ont rangé tout ça ?' WHERE `id`=777; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Non, je loot pas cette merde grise.' WHERE `id`=778; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est moi d’abord ! C’est moi ! MOI !' WHERE `id`=779; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Donne-moi ton fric !' WHERE `id`=780; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Mes poches sont vides, il faut les remplir.' WHERE `id`=781; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai un nouveau sac, il est fait pour ça.' WHERE `id`=782; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère que je vais pas aggro en lootant…' WHERE `id`=783; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ne regardez pas… je loot discret…' WHERE `id`=784; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Ha ! Vous n’aurez rien de tout ça !' WHERE `id`=785; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Le loot, c’est stylé.' WHERE `id`=786; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’adore les nouveaux équipements.' WHERE `id`=787; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je me casse si y’a encore rien de valeur…' WHERE `id`=788; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère que ce sera une jolie bague !' WHERE `id`=789; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je vais t’arracher le loot des mains !' WHERE `id`=790; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Personne ne touche à rien. C’est MOI qui loot.' WHERE `id`=791; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Loot sucré :D' WHERE `id`=792; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Dieu du lancer, donne-moi un épique aujourd’hui…' WHERE `id`=793; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Allez, de nouveaux jouets s’il vous plaît !' WHERE `id`=794; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’espère qu’ils ont des trucs savoureux…' WHERE `id`=795; -UPDATE `ai_playerbot_texts` SET `text_loc2`='L’or est à moi. Je laisse tout le reste… promis…' WHERE `id`=796; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Non, je peux pas résister.' WHERE `id`=797; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’en veux ENCORE !' WHERE `id`=798; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis presque là, attendez-moi !' WHERE `id`=799; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je suis pas loin, attendez-moi !' WHERE `id`=800; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’arrive vers ta position' WHERE `id`=801; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’arrive vers toi' WHERE `id`=802; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je me dirige vers ta position' WHERE `id`=803; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’essaie de te rejoindre' WHERE `id`=804; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Équipement de %item' WHERE `id`=805; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%item retiré' WHERE `id`=806; -UPDATE `ai_playerbot_texts` SET `text_loc2`='J’ai appris les sorts : %spells' WHERE `id`=807; -UPDATE `ai_playerbot_texts` SET `text_loc2`='%item est en recharge' WHERE `id`=808; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’ai pas %item dans mon inventaire' WHERE `id`=809; -UPDATE `ai_playerbot_texts` SET `text_loc2`='L’objet avec l’ID %item n’existe pas' WHERE `id`=810; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Insertion de %gem dans %item' WHERE `id`=811; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas utiliser %item' WHERE `id`=812; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Suivi' WHERE `id`=813; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je reste ici' WHERE `id`=814; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je fuis' WHERE `id`=815; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je fuis pas avec toi, t’es trop loin !' WHERE `id`=816; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Farm en cours' WHERE `id`=817; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Attaque en cours' WHERE `id`=818; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est trop loin' WHERE `id`=819; -UPDATE `ai_playerbot_texts` SET `text_loc2`='C’est sous l’eau' WHERE `id`=820; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas y aller' WHERE `id`=821; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne suis pas dans ta guilde !' WHERE `id`=822; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Impossible de trouver une banque de guilde à proximité' WHERE `id`=823; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas déposer' WHERE `id`=824; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’ai pas les droits pour déposer dans le premier onglet de la banque de guilde' WHERE `id`=825; -UPDATE `ai_playerbot_texts` SET `text_loc2`='déposé dans la banque de guilde' WHERE `id`=826; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Déplacement libre' WHERE `id`=827; -UPDATE `ai_playerbot_texts` SET `text_loc2`='En garde' WHERE `id`=828; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Utilisation de %target' WHERE `id`=829; -UPDATE `ai_playerbot_texts` SET `text_loc2`='sur %unit' WHERE `id`=830; -UPDATE `ai_playerbot_texts` SET `text_loc2`='(%amount disponible)' WHERE `id`=831; -UPDATE `ai_playerbot_texts` SET `text_loc2`='(le dernier)' WHERE `id`=832; -UPDATE `ai_playerbot_texts` SET `text_loc2`='La châsse ne correspond pas' WHERE `id`=833; -UPDATE `ai_playerbot_texts` SET `text_loc2`='sur objet d’échange' WHERE `id`=834; -UPDATE `ai_playerbot_texts` SET `text_loc2`='sur moi-même' WHERE `id`=835; -UPDATE `ai_playerbot_texts` SET `text_loc2`='sur %item' WHERE `id`=836; -UPDATE `ai_playerbot_texts` SET `text_loc2`='sur %gameobject' WHERE `id`=837; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Loot de %item' WHERE `id`=838; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Invocation de %target' WHERE `id`=839; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je n’ai pas assez de membres du groupe à proximité pour invoquer' WHERE `id`=840; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Impossible de trouver la cible d’invocation' WHERE `id`=841; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne peux pas invoquer en combat' WHERE `id`=842; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Je ne connais pas le sort %spell' WHERE `id`=843; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Lancement du sort %spell' WHERE `id`=844; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Fabrication de %spell' WHERE `id`=845; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Impossible de lancer %spell' WHERE `id`=846; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Échec du lancement de %spell' WHERE `id`=847; -UPDATE `ai_playerbot_texts` SET `text_loc2`='|cffffff00(x%amount restant)|r' WHERE `id`=848; -UPDATE `ai_playerbot_texts` SET `text_loc2`='dummy' WHERE `id`=849; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Par la Lumière... J\'ai oublié mes Symboles du roi. On se contentera de %base_spell !' WHERE `id`=934; -UPDATE `ai_playerbot_texts` SET `text_loc2`='La nature est généreuse, pas mes sacs... plus d\'herbes pour %group_spell. Prenez %base_spell pour l\'instant !' WHERE `id`=935; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Plus de poudre des arcanes... %group_spell attendra. Je lance %base_spell !' WHERE `id`=936; -UPDATE `ai_playerbot_texts` SET `text_loc2`='Oups, je n\'ai plus de composants pour %group_spell. On fera avec %base_spell !' WHERE `id`=937; - From dd1889272227f239c7bf05c146cb769ad77d061e Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Sat, 20 Sep 2025 13:35:23 +0200 Subject: [PATCH 11/32] Add Logic for Professions Recipes --- conf/playerbots.conf.dist | 28 ++- src/PlayerbotAIConfig.cpp | 10 +- src/PlayerbotAIConfig.h | 6 +- src/strategy/actions/LootRollAction.cpp | 280 +++++++++++++++++++++--- 4 files changed, 276 insertions(+), 48 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 47f8f40c15..9cbd208d09 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -313,16 +313,24 @@ AiPlayerbot.Roll.AllowBoENeedIfUpgrade = 1 # Default: 1 (enabled) AiPlayerbot.Roll.AllowBoUNeedIfUpgrade = 1 -# Cross-armor rule (cloth/leather/mail on a plate user, etc.): -# Allow NEED only if newScore >= CrossArmorExtraMargin * bestEquippedScore. -# Default: 1.20 (conservative). Use 9.99 to effectively forbid cross-armor NEED. -AiPlayerbot.Roll.CrossArmorExtraMargin = 1.20 - # If Need-Before-Greed is active and the item is only useful for disenchanting, # bots will press the "Disenchant" button instead of GREED. # Default: 1 (enabled) AiPlayerbot.Roll.UseDEButton = 1 +# NEED on learnable profession recipes/patterns/books if the bot has the profession. +# Default: 1 (enabled) +AiPlayerbot.Roll.NeedOnProfessionRecipes = 1 + +# Ignore required skill rank when deciding NEED on profession recipes (not recommended for strict etiquette). +# Default: 0 (disabled) +AiPlayerbot.Roll.Recipes.IgnoreSkillRank = 0 + +# Cross-armor rule (cloth/leather/mail on a plate user, etc.): +# Allow NEED only if newScore >= CrossArmorExtraMargin * bestEquippedScore. +# Default: 1.20 (conservative). Use 9.99 to effectively forbid cross-armor NEED. +AiPlayerbot.Roll.CrossArmorExtraMargin = 1.20 + # Minimum item level delta to treat a SET TOKEN as a real upgrade (0 means >=). # Prevents NEED on same-tier duplicates. # Example: Paladin Prot with chest ilvl 232: @@ -550,7 +558,7 @@ AiPlayerbot.AutoGearQualityLimit = 3 # Max iLVL Phase 1(Kara, Gruul, Mag) = 125 | Phase 1.5(ZA) = 138 | Phase 2(SC, TK) = 141 | Phase 3(Hyjal, BT) = 156 | Phase 4(Sunwell) = 164 # Wotlk # Max iLVL Tier 7(10/25) = 200/213 | Tier 8(10/25) = 225/232 | Tier 9(10/25) = 232/245 | Tier 10(10/25/HC) = 251/264/290 -# Max iLVL Phase 1(Naxx) = 224 | Phase 2(Ulduar) = 245 | Phase 3(ToC) = 258 | Phase 4(ICC) = 290 +# Max iLVL Phase 1(Naxx) = 224 | Phase 2(Ulduar) = 245 | Phase 3(ToC) = 258 | Phase 4(ICC) = 290 # Default: 0 (no limit) AiPlayerbot.AutoGearScoreLimit = 0 @@ -560,11 +568,11 @@ AiPlayerbot.AutoGearScoreLimit = 0 # "health" (bots immediately regenerate lost health) # "mana" (bots have infinite mana) # "power" (bots have infinite energy, rage, and runic power) -# "taxi" (bots may use all flight paths, though they will not actually learn them) -# "raid" (bots use cheats implemented into raid strategies) +# "taxi" (bots may use all flight paths, though they will not actually learn them) +# "raid" (bots use cheats implemented into raid strategies) # To use multiple cheats, separate them by commas below (e.g., to enable all, use "gold,health,mana,power,raid,taxi") # Default: taxi and raid are enabled -AiPlayerbot.BotCheats = "food,taxi,raid" +AiPlayerbot.BotCheats = "food,taxi,raid" # # @@ -714,7 +722,7 @@ AiPlayerbot.RandomGearQualityLimit = 3 # Max iLVL Phase 1(Kara, Gruul, Mag) = 125 | Phase 1.5(ZA) = 138 | Phase 2(SC, TK) = 141 | Phase 3(Hyjal, BT) = 156 | Phase 4(Sunwell) = 164 # Wotlk # Max iLVL Tier 7(10/25) = 200/213 | Tier 8(10/25) = 225/232 | Tier 9(10/25) = 232/245 | Tier 10(10/25/HC) = 251/264/290 -# Max iLVL Phase 1(Naxx) = 224 | Phase 2(Ulduar) = 245 | Phase 3(ToC) = 258 | Phase 4(ICC) = 290 +# Max iLVL Phase 1(Naxx) = 224 | Phase 2(Ulduar) = 245 | Phase 3(ToC) = 258 | Phase 4(ICC) = 290 # Default: 0 (no limit) AiPlayerbot.RandomGearScoreLimit = 0 diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index b6bc09f5fe..e69271cc01 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -219,9 +219,9 @@ bool PlayerbotAIConfig::Initialize() "531,532,534,544,548,550,564,565,580,249,533,603,615,616,624,631,649,724"), restrictedHealerDPSMaps); - //////////////////////////// ICC + //////////////////////////// ICC - EnableICCBuffs = sConfigMgr->GetOption("AiPlayerbot.EnableICCBuffs", true); + EnableICCBuffs = sConfigMgr->GetOption("AiPlayerbot.EnableICCBuffs", true); //////////////////////////// CHAT enableBroadcasts = sConfigMgr->GetOption("AiPlayerbot.EnableBroadcasts", true); @@ -594,8 +594,10 @@ bool PlayerbotAIConfig::Initialize() crossArmorExtraMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.CrossArmorExtraMargin", 1.20f); useDEButton = sConfigMgr->GetOption("AiPlayerbot.Roll.UseDEButton", true); tokenILevelMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.TokenILevelMargin", 0.10f); - announceLootRollsToMaster = sConfigMgr->GetOption("AiPlayerbot.Roll.AnnounceToMaster", false); - smartNeedBySpec = sConfigMgr->GetOption("AiPlayerbot.Roll.SmartNeedBySpec", true); + announceLootRollsToMaster = sConfigMgr->GetOption("AiPlayerbot.Roll.AnnounceToMaster", false); + needOnProfessionRecipes = sConfigMgr->GetOption("AiPlayerbot.Roll.NeedOnProfessionRecipes", true); + recipesIgnoreSkillRank = sConfigMgr->GetOption("AiPlayerbot.Roll.Recipes.IgnoreSkillRank", false); + smartNeedBySpec = sConfigMgr->GetOption("AiPlayerbot.Roll.SmartNeedBySpec", true); twoRoundsGearInit = sConfigMgr->GetOption("AiPlayerbot.TwoRoundsGearInit", false); syncQuestWithPlayer = sConfigMgr->GetOption("AiPlayerbot.SyncQuestWithPlayer", true); syncQuestForPlayer = sConfigMgr->GetOption("AiPlayerbot.SyncQuestForPlayer", false); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index f6dca79f3a..86d90d6fc6 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -344,12 +344,14 @@ class PlayerbotAIConfig bool autoEquipUpgradeLoot; float equipUpgradeThreshold; bool allowBoENeedIfUpgrade; // Loot roll fine-tuning - bool allowBoUNeedIfUpgrade; // Allow NEED on BoU if upgrade + bool allowBoUNeedIfUpgrade; // Allow NEED on BoU if upgrade float crossArmorExtraMargin; bool useDEButton; // Allow "Disenchant" on NBG if available float tokenILevelMargin; // ilvl threshold to consider the token an upgrade - bool announceLootRollsToMaster; // ANotify the bot’s master of the roll choice + bool announceLootRollsToMaster; // ANotify the bot’s master of the roll choice bool smartNeedBySpec; // Intelligent NEED (based on stats/spec) + bool needOnProfessionRecipes; // If true, bots will roll NEED on profession recipes/patterns/books they can use & learn. + bool recipesIgnoreSkillRank; // If true, ignore skill rank requirement when rolling on profession recipes bool twoRoundsGearInit; bool syncQuestWithPlayer; bool syncQuestForPlayer; diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 8552ab3aa9..2162fb3133 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -22,6 +22,9 @@ #include "AiFactory.h" #include #include +#include "SpellMgr.h" +#include "SkillDiscovery.h" // present in AC; guards not needed, we only use SkillLine enums +#include "Log.h" // Groups the "class + archetype" info in the same place struct SpecTraits @@ -134,6 +137,175 @@ static inline int32 EncodeRandomEnchantParam(uint32 randomPropertyId, uint32 ran return 0; } +// Professions helpers Returns true if the item is a Recipe/Pattern/Book (ITEM_CLASS_RECIPE) +static inline bool IsRecipeItem(ItemTemplate const* proto) +{ + return proto && proto->Class == ITEM_CLASS_RECIPE; +} + +// Try to detect the spell taught by a recipe and whether the bot already knows it. If we can’t resolve the taught spell reliably, we fall back to "has profession + skill rank OK". +static bool BotAlreadyKnowsRecipeSpell(Player* bot, ItemTemplate const* proto) +{ + if (!bot || !proto) return false; + // Many recipes have a single spell that "teaches" another spell (learned spell in EffectTriggerSpell). + for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + { + uint32 teach = proto->Spells[i].SpellId; + if (!teach) continue; + SpellInfo const* si = sSpellMgr->GetSpellInfo(teach); + if (!si) continue; + for (int eff = 0; eff < MAX_SPELL_EFFECTS; ++eff) + { + if (si->Effects[eff].Effect == SPELL_EFFECT_LEARN_SPELL) + { + uint32 learned = si->Effects[eff].TriggerSpell; + if (learned && bot->HasSpell(learned)) + return true; // already knows the taught spell + } + } + } + return false; +} + +/*// Special-case: Book of Glyph Mastery (can own several; do not downgrade NEED on duplicates) +static bool IsGlyphMasteryBook(ItemTemplate const* proto) +{ + if (!proto) return false; + // Known WotLK entry (retail classic DBs use 45912 for Book of Glyph Mastery) + if (proto->ItemId == 45912) + return true; + // Fallback by name (handles localized DBs) + if (proto->Class == ITEM_CLASS_RECIPE && proto->SubClass == ITEM_SUBCLASS_BOOK) + { + std::string n = proto->Name1; + std::transform(n.begin(), n.end(), n.begin(), + [](unsigned char c){ return static_cast(std::tolower(c)); }); + // English + French hints + if (n.find("glyph mastery") != std::string::npos || + n.find("book of glyph mastery") != std::string::npos || + n.find("maitrise des glyphes") != std::string::npos || // sans accent + n.find("maîtrise des glyphes") != std::string::npos) // avec accent + return true; + } + return false; +}*/ + +// Special-case: Book of Glyph Mastery (can own several; do not downgrade NEED on duplicates) +static bool IsGlyphMasteryBook(ItemTemplate const* proto) +{ + if (!proto) return false; + + // 1) Type-safety: it must be a recipe book + if (proto->Class != ITEM_CLASS_RECIPE || proto->SubClass != ITEM_SUBCLASS_BOOK) + return false; + + // 2) Primary signal: the on-use spell of the book on WotLK DBs + // (Spell 64323: "Book of Glyph Mastery"). Use a named constant to avoid magic numbers. + constexpr uint32 SPELL_BOOK_OF_GLYPH_MASTERY = 64323; // WotLK 3.3.5a + for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + { + if (proto->Spells[i].SpellId == SPELL_BOOK_OF_GLYPH_MASTERY) + return true; + } + + // 3) Fallback: Inscription recipe book + localized name tokens (covers DB forks/locales) + if (proto->RequiredSkill == SKILL_INSCRIPTION) + { + std::string n = proto->Name1; + std::transform(n.begin(), n.end(), n.begin(), + [](unsigned char c){ return static_cast(std::tolower(c)); }); + if (n.find("glyph mastery") != std::string::npos || + n.find("book of glyph mastery") != std::string::npos) + return true; + } + + return false; +} + +// Pretty helper for RollVote name in logs +static inline char const* VoteTxt(RollVote v) { + switch (v) { case NEED: return "NEED"; case GREED: return "GREED"; case PASS: return "PASS"; case DISENCHANT: return "DISENCHANT"; default: return "UNKNOWN"; } +} + +// Centralised debug dump for recipe decisions +static void DebugRecipeRoll(Player* bot, ItemTemplate const* proto, ItemUsage usage, + bool recipeChecked, bool recipeUseful, bool recipeKnown, + uint32 reqSkill, uint32 reqRank, uint32 botRank, + RollVote before, RollVote after) +{ + LOG_INFO("playerbots", + "[LootDBG] {} JC:{} item:{} \"{}\" class={} sub={} bond={} usage={} " + "recipeChecked={} useful={} known={} reqSkill={} reqRank={} botRank={} vote:{} -> {} dupCount={}", + bot->GetName(), bot->GetSkillValue(SKILL_JEWELCRAFTING), + proto->ItemId, proto->Name1, proto->Class, proto->SubClass, proto->Bonding, (int)usage, + recipeChecked, recipeUseful, recipeKnown, reqSkill, reqRank, botRank, + VoteTxt(before), VoteTxt(after), bot->GetItemCount(proto->ItemId, true)); +} + +// Maps a RECIPE subclass & item metadata to the SkillLine needed (when RequiredSkill is not set). In DBs, recipes normally have RequiredSkill filled; we keep this as a fallback. +static uint32 GuessRecipeSkill(ItemTemplate const* proto) +{ + if (!proto) return 0; + // If the core DB is sane, this is set and we can just return it in the caller. + // Fallback heuristic on SubClass (books used by professions) + switch (proto->SubClass) + { + case ITEM_SUBCLASS_BOOK: // e.g. Book of Glyph Mastery + // If the name hints glyphs, assume Inscription + { + std::string n = proto->Name1; + std::transform(n.begin(), n.end(), n.begin(), [](unsigned char c){ return std::tolower(c); }); + if (n.find("glyph") != std::string::npos) + return SKILL_INSCRIPTION; + } + break; + case ITEM_SUBCLASS_LEATHERWORKING_PATTERN: return SKILL_LEATHERWORKING; + case ITEM_SUBCLASS_TAILORING_PATTERN: return SKILL_TAILORING; + case ITEM_SUBCLASS_ENGINEERING_SCHEMATIC: return SKILL_ENGINEERING; + case ITEM_SUBCLASS_BLACKSMITHING: return SKILL_BLACKSMITHING; + case ITEM_SUBCLASS_COOKING_RECIPE: return SKILL_COOKING; + case ITEM_SUBCLASS_ALCHEMY_RECIPE: return SKILL_ALCHEMY; + case ITEM_SUBCLASS_FIRST_AID_MANUAL: return SKILL_FIRST_AID; + case ITEM_SUBCLASS_ENCHANTING_FORMULA: return SKILL_ENCHANTING; + case ITEM_SUBCLASS_JEWELCRAFTING_RECIPE: return SKILL_JEWELCRAFTING; + default: break; + } + return 0; +} + +// Returns true if this recipe/pattern/book is useful for one of the bot's professions and not already known. +static bool IsProfessionRecipeUsefulForBot(Player* bot, ItemTemplate const* proto) +{ + if (!bot || !IsRecipeItem(proto)) return false; + + // Primary path: DB usually sets RequiredSkill/RequiredSkillRank on recipe items. + uint32 reqSkill = proto->RequiredSkill; + uint32 reqRank = proto->RequiredSkillRank; + + if (!reqSkill) + reqSkill = GuessRecipeSkill(proto); + + if (!reqSkill) + return false; // unknown profession, be conservative + + // Bot must have the profession (or secondary skill like Cooking/First Aid) + if (!bot->HasSkill(reqSkill)) + return false; + + // Required rank check (can be disabled by config) + if (!sPlayerbotAIConfig->recipesIgnoreSkillRank) + { + if (reqRank && bot->GetSkillValue(reqSkill) < reqRank) + return false; + } + + // Avoid NEED if the taught spell is already known + if (BotAlreadyKnowsRecipeSpell(bot, proto)) + return false; + + return true; +} + // Weapon/shield/relic whitelist per class. // Returns false when the item is a WEAPON / SHIELD / RELIC the class should NOT use. static bool IsWeaponOrShieldOrRelicAllowedForClass(SpecTraits const& traits, ItemTemplate const* proto) @@ -624,7 +796,6 @@ bool LootRollAction::Execute(Event event) return false; } - RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 randomProperty) { // Player mimic: upgrade => NEED; useful => GREED; otherwise => PASS @@ -636,30 +807,62 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", out.str()); RollVote vote = PASS; - switch (usage) + + bool recipeChecked = false; + bool recipeNeed = false; + bool recipeUseful = false; + bool recipeKnown = false; + uint32 reqSkillDbg = 0, reqRankDbg = 0, botRankDbg = 0; + + // Professions early override + // If enabled, bots NEED on recipes/patterns/books useful to their professions, + // provided they can learn them and don't already know the taught spell. + if (sPlayerbotAIConfig->needOnProfessionRecipes && IsRecipeItem(proto)) { - case ITEM_USAGE_EQUIP: - case ITEM_USAGE_REPLACE: + recipeChecked = true; + // Collect debug data (what the helper va décider) + reqSkillDbg = proto->RequiredSkill ? proto->RequiredSkill : GuessRecipeSkill(proto); + reqRankDbg = proto->RequiredSkillRank; + botRankDbg = reqSkillDbg ? bot->GetSkillValue(reqSkillDbg) : 0; + recipeKnown = BotAlreadyKnowsRecipeSpell(bot, proto); + + recipeUseful = IsProfessionRecipeUsefulForBot(bot, proto); + if (recipeUseful) { vote = NEED; - // Downgrade to GREED if the item does not match the main spec - if (sPlayerbotAIConfig->smartNeedBySpec && !IsPrimaryForSpec(bot, proto)) - vote = GREED; - break; - case ITEM_USAGE_BAD_EQUIP: - case ITEM_USAGE_GUILD_TASK: - case ITEM_USAGE_SKILL: - case ITEM_USAGE_USE: - case ITEM_USAGE_DISENCHANT: - case ITEM_USAGE_AH: - case ITEM_USAGE_VENDOR: - case ITEM_USAGE_KEEP: - case ITEM_USAGE_AMMO: - vote = GREED; - break; - default: - vote = PASS; - break; + recipeNeed = true; + } else { + vote = GREED; // recette pas pour nous -> GREED + } } + + // Ne pas écraser le choix si on a déjà tranché via la logique "recette" + if (!recipeChecked) + { + switch (usage) + { + case ITEM_USAGE_EQUIP: + case ITEM_USAGE_REPLACE: + vote = NEED; + // Downgrade to GREED if the item does not match the main spec + if (sPlayerbotAIConfig->smartNeedBySpec && !IsPrimaryForSpec(bot, proto)) + vote = GREED; + break; + case ITEM_USAGE_BAD_EQUIP: + case ITEM_USAGE_GUILD_TASK: + case ITEM_USAGE_SKILL: + case ITEM_USAGE_USE: + case ITEM_USAGE_DISENCHANT: + case ITEM_USAGE_AH: + case ITEM_USAGE_VENDOR: + case ITEM_USAGE_KEEP: + case ITEM_USAGE_AMMO: + vote = GREED; + break; + default: + vote = PASS; + break; + } + } // Lockboxes: if the item is a lockbox and the bot is a Rogue with Lockpicking, prefer NEED. // (Handled before BoE/BoU etiquette; BoE/BoU checks below ignore lockboxes.) @@ -692,24 +895,30 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand } // BoE/BoU rule: by default, avoid NEED on Bind-on-Equip / Bind-on-Use (raid etiquette) + // Exception: Profession recipes/patterns/books (ITEM_CLASS_RECIPE) keep NEED if they are useful. constexpr uint32 BIND_WHEN_EQUIPPED = 2; // BoE constexpr uint32 BIND_WHEN_USE = 3; // BoU - if (vote == NEED && !isLockbox && proto->Bonding == BIND_WHEN_EQUIPPED && !sPlayerbotAIConfig->allowBoENeedIfUpgrade) + + if (vote == NEED && !recipeNeed && !isLockbox && proto->Bonding == BIND_WHEN_EQUIPPED && !sPlayerbotAIConfig->allowBoENeedIfUpgrade) { vote = GREED; } - if (vote == NEED && !isLockbox && proto->Bonding == BIND_WHEN_USE && !sPlayerbotAIConfig->allowBoUNeedIfUpgrade) + if (vote == NEED && !recipeNeed && !isLockbox && proto->Bonding == BIND_WHEN_USE && !sPlayerbotAIConfig->allowBoUNeedIfUpgrade) { vote = GREED; } - // Duplicate soft rule (non-unique): if the bot already owns at least one copy in bags, downgrade NEED to GREED. - // This complements "unique-equip" and avoids ninja-need on duplicates that are not unique. + // Duplicate soft rule (non-unique): + // - Default: if the bot already owns at least one copy => NEED -> GREED. + // - Exception: Book of Glyph Mastery (you can own several) => keep NEED. if (vote == NEED) { - // includeBank=true to catch banked duplicates as well; adjust if undesired. - if (bot->GetItemCount(proto->ItemId, true) > 0) - vote = GREED; + if (!IsGlyphMasteryBook(proto)) + { + // includeBank=true to catch banked duplicates as well. + if (bot->GetItemCount(proto->ItemId, true) > 0) + vote = GREED; + } } // Unique-equip: never NEED a duplicate (already equipped/owned) @@ -740,11 +949,18 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand vote = NEED; } - // Final filter: loot strategy — AI is valid here; use the standard accessor - return StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? vote : PASS; + // Final decision (with allow/deny from loot strategy) + RollVote finalVote = StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? vote : PASS; + + // DEBUG: dump for recipes + if (IsRecipeItem(proto)) + DebugRecipeRoll(bot, proto, usage, recipeChecked, recipeUseful, recipeKnown, + reqSkillDbg, reqRankDbg, botRankDbg, /*before*/ (recipeNeed?NEED:PASS), /*after*/ finalVote); + + return finalVote; } -// Helpers d'annonce +// Helpers announce const char* LootRollAction::RollVoteToText(RollVote vote) const { switch (vote) From 65a63eeb75f871d9bd8ec8687594ae50d75439a6 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Sat, 20 Sep 2025 17:01:55 +0200 Subject: [PATCH 12/32] Added the ability to choose disenchant on loot if the bot is enchanting Added the ability to choose disenchant on loot if the bot is enchanting --- src/strategy/actions/LootRollAction.cpp | 105 +++++++++++++++--------- 1 file changed, 64 insertions(+), 41 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index c52fb7f290..bbe4998666 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -23,7 +23,7 @@ #include #include #include "SpellMgr.h" -#include "SkillDiscovery.h" // present in AC; guards not needed, we only use SkillLine enums +#include "SkillDiscovery.h" #include "Log.h" // Groups the "class + archetype" info in the same place @@ -167,29 +167,6 @@ static bool BotAlreadyKnowsRecipeSpell(Player* bot, ItemTemplate const* proto) return false; } -/*// Special-case: Book of Glyph Mastery (can own several; do not downgrade NEED on duplicates) -static bool IsGlyphMasteryBook(ItemTemplate const* proto) -{ - if (!proto) return false; - // Known WotLK entry (retail classic DBs use 45912 for Book of Glyph Mastery) - if (proto->ItemId == 45912) - return true; - // Fallback by name (handles localized DBs) - if (proto->Class == ITEM_CLASS_RECIPE && proto->SubClass == ITEM_SUBCLASS_BOOK) - { - std::string n = proto->Name1; - std::transform(n.begin(), n.end(), n.begin(), - [](unsigned char c){ return static_cast(std::tolower(c)); }); - // English + French hints - if (n.find("glyph mastery") != std::string::npos || - n.find("book of glyph mastery") != std::string::npos || - n.find("maitrise des glyphes") != std::string::npos || // sans accent - n.find("maîtrise des glyphes") != std::string::npos) // avec accent - return true; - } - return false; -}*/ - // Special-case: Book of Glyph Mastery (can own several; do not downgrade NEED on duplicates) static bool IsGlyphMasteryBook(ItemTemplate const* proto) { @@ -233,7 +210,7 @@ static void DebugRecipeRoll(Player* bot, ItemTemplate const* proto, ItemUsage us uint32 reqSkill, uint32 reqRank, uint32 botRank, RollVote before, RollVote after) { - LOG_INFO("playerbots", + LOG_DEBUG("playerbots", "[LootDBG] {} JC:{} item:{} \"{}\" class={} sub={} bond={} usage={} " "recipeChecked={} useful={} known={} reqSkill={} reqRank={} botRank={} vote:{} -> {} dupCount={}", bot->GetName(), bot->GetSkillValue(SKILL_JEWELCRAFTING), @@ -646,6 +623,15 @@ static void GetEquipSlotsForInvType(uint8 invType, std::vector& out) static bool CanBotUseToken(ItemTemplate const* proto, Player* bot); static bool RollUniqueCheck(ItemTemplate const* proto, Player* bot); +// WotLK Heuristic: We can only DE [UNCOMMON..EPIC] quality ARMOR/WEAPON +static inline bool IsLikelyDisenchantable(ItemTemplate const* proto) +{ + if (!proto) return false; + if (proto->Class != ITEM_CLASS_ARMOR && proto->Class != ITEM_CLASS_WEAPON) + return false; + return proto->Quality >= ITEM_QUALITY_UNCOMMON && proto->Quality <= ITEM_QUALITY_EPIC; +} + // Internal helpers // Deduces the target slot from the token's name. // Returns an expected InventoryType (HEAD/SHOULDERS/CHEST/HANDS/LEGS) or -1 if unknown. @@ -710,6 +696,10 @@ bool LootRollAction::Execute(Event event) if (!proto) continue; + LOG_DEBUG("playerbots", "[LootDBG] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", + bot->GetName(), itemId, proto->Name1, proto->Class, proto->Quality, + (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), randomProperty); + RollVote vote = PASS; std::string itemUsageParam; @@ -719,6 +709,8 @@ bool LootRollAction::Execute(Event event) itemUsageParam = std::to_string(itemId); } ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam); + + LOG_DEBUG("playerbots", "[LootDBG] usage={} (EQUIP=1 REPLACE=2 BAD_EQUIP=8 DISENCHANT=13)", (int)usage); // Armor Tokens are classed as MISC JUNK (Class 15, Subclass 0), but no other items have class bits and epic quality. // - CanBotUseToken(proto, bot) => NEED @@ -750,15 +742,26 @@ bool LootRollAction::Execute(Event event) } else { - // Let CalculateRollVote decide (includes SmartNeedBySpec, BoE/BoU, unique, cross-armor) + // Lets CalculateRollVote decide (includes SmartNeedBySpec, BoE/BoU, unique, cross-armor) vote = CalculateRollVote(proto, randomProperty); + LOG_DEBUG("playerbots", "[LootDBG] after CalculateRollVote: vote={}", RollVoteToText(vote)); } - - // Disenchant button (Need-Before-Greed): if useful for DE, prefer DE over Greed - if (vote == GREED && usage == ITEM_USAGE_DISENCHANT && sPlayerbotAIConfig->useDEButton) + + // Disenchant (Need-Before-Greed): + // If the bot is ENCHANTING and the item is disenchantable, prefer DE to GREED + if (vote != NEED && sPlayerbotAIConfig->useDEButton && + group && (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && + bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto)) { - if (group && group->GetLootMethod() == NEED_BEFORE_GREED) - vote = DISENCHANT; + LOG_DEBUG("playerbots", "[LootDBG] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", + RollVoteToText(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); + vote = DISENCHANT; + } + else + { + LOG_DEBUG("playerbots", "[LootDBG] no DE: vote={} lootMethod={} enchSkill={} deOK={}", + RollVoteToText(vote), (int)group->GetLootMethod(), + bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); } if (sPlayerbotAIConfig->lootRollLevel == 0) @@ -773,7 +776,7 @@ bool LootRollAction::Execute(Event event) { vote = PASS; } - else + else { vote = GREED; } @@ -787,6 +790,10 @@ bool LootRollAction::Execute(Event event) RollVote sent = vote; if (group->GetLootMethod() == MASTER_LOOT || group->GetLootMethod() == FREE_FOR_ALL) sent = PASS; + LOG_DEBUG("playerbots", "[LootDBG] send vote={} (lootMethod={} Lvl={}) -> guid={} itemId={}", + RollVoteToText(sent), (int)group->GetLootMethod(), + sPlayerbotAIConfig->lootRollLevel, guid.ToString(), itemId); + AnnounceRollChoice(sent, itemId); group->CountRollVote(bot->GetGUID(), guid, sent); // One item at a time @@ -831,11 +838,11 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand vote = NEED; recipeNeed = true; } else { - vote = GREED; // recette pas pour nous -> GREED + vote = GREED; // recipe not for the bot -> GREED } } - // Ne pas écraser le choix si on a déjà tranché via la logique "recette" + // Do not overwrite the choice if we have already decided via the "recipe" logic if (!recipeChecked) { switch (usage) @@ -1032,6 +1039,10 @@ bool MasterLootRollAction::Execute(Event event) Group* group = bot->GetGroup(); if (!group) return false; + + LOG_DEBUG("playerbots", "[LootDBG][ML] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", + bot->GetName(), itemId, proto->Name1, proto->Class, proto->Quality, + (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), randomPropertyId); // 1) Token heuristic: ONLY NEED if the target slot is a likely upgrade RollVote vote = PASS; @@ -1056,17 +1067,29 @@ bool MasterLootRollAction::Execute(Event event) } // 2) Disenchant button in Need-Before-Greed if the usage is "DISENCHANT" - if (vote == GREED && sPlayerbotAIConfig->useDEButton && group->GetLootMethod() == NEED_BEFORE_GREED) + if (vote != NEED && sPlayerbotAIConfig->useDEButton && + (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && + bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto)) + { + LOG_DEBUG("playerbots", "[LootDBG][ML] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", + RollVoteToText(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); + vote = DISENCHANT; + } + else { - std::ostringstream out; out << itemId; - ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", out.str()); - if (usage == ITEM_USAGE_DISENCHANT) - vote = DISENCHANT; + LOG_DEBUG("playerbots", "[LootDBG][ML] no DE: vote={} lootMethod={} enchSkill={} deOK={}", + RollVoteToText(vote), (int)group->GetLootMethod(), + bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); } RollVote sent = vote; if (group->GetLootMethod() == MASTER_LOOT || group->GetLootMethod() == FREE_FOR_ALL) sent = PASS; + + LOG_DEBUG("playerbots", "[LootDBG][ML] vote={} -> sent={} lootMethod={} enchSkill={} deOK={}", + RollVoteToText(vote), RollVoteToText(sent), (int)group->GetLootMethod(), + bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); + AnnounceRollChoice(sent, itemId); group->CountRollVote(bot->GetGUID(), creatureGuid, sent); @@ -1111,7 +1134,7 @@ static bool RollUniqueCheck(ItemTemplate const* proto, Player* bot) bool RollAction::Execute(Event event) { std::string link = event.getParam(); - + if (link.empty()) { bot->DoRandomRoll(0,100); @@ -1128,7 +1151,7 @@ bool RollAction::Execute(Event event) } std::string itemUsageParam; itemUsageParam = std::to_string(itemId); - + ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam); switch (proto->Class) { From ed142aa39c951ea962f3f08120bbed13be4120dd Mon Sep 17 00:00:00 2001 From: Alex Dcnh <140754794+Wishmaster117@users.noreply.github.com> Date: Sun, 21 Sep 2025 18:27:52 +0200 Subject: [PATCH 13/32] Update LootRollAction.cpp --- src/strategy/actions/LootRollAction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index bbe4998666..4bcf566207 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -219,7 +219,7 @@ static void DebugRecipeRoll(Player* bot, ItemTemplate const* proto, ItemUsage us VoteTxt(before), VoteTxt(after), bot->GetItemCount(proto->ItemId, true)); } -// Maps a RECIPE subclass & item metadata to the SkillLine needed (when RequiredSkill is not set). In DBs, recipes normally have RequiredSkill filled; we keep this as a fallback. +// Maps a RECIPE subclass & item metadata to the SkillLine needed (when RequiredSkill is not set). In DBs, recipes normally have RequiredSkill filled; we keep this as a fallback static uint32 GuessRecipeSkill(ItemTemplate const* proto) { if (!proto) return 0; From 5cf5b8b64aec9f04e67649afb7c0ab464f037fe8 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 22 Sep 2025 20:59:21 +0200 Subject: [PATCH 14/32] =?UTF-8?q?add=20=E2=80=9Cspecial=20item=E2=80=9D=20?= =?UTF-8?q?verification=20via=20stat-pattern=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/strategy/actions/LootRollAction.cpp | 177 ++++++++++++++++++++++-- 1 file changed, 165 insertions(+), 12 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 4bcf566207..ff2c7101d2 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -25,6 +25,8 @@ #include "SpellMgr.h" #include "SkillDiscovery.h" #include "Log.h" +#include +#include "AiObjectContext.h" // Groups the "class + archetype" info in the same place struct SpecTraits @@ -45,6 +47,7 @@ struct SpecTraits bool isRogue = false; bool isWarrior = false; bool isRetPal = false; + bool isProtPal = false; }; static SpecTraits GetSpecTraits(Player* bot) @@ -62,6 +65,7 @@ static SpecTraits GetSpecTraits(Player* bot) // Paladin const bool holyPal = (t.cls == CLASS_PALADIN && specIs("holy")); const bool protPal = (t.cls == CLASS_PALADIN && (specIs("prot") || specIs("protection"))); + t.isProtPal = protPal; t.isRetPal = (t.cls == CLASS_PALADIN && !holyPal && !protPal); // DK const bool dk = (t.cls == CLASS_DEATH_KNIGHT); @@ -128,6 +132,150 @@ static bool HasAnyStat(ItemTemplate const* proto, return false; } +// SPECIAL ITEMS PRIORITY PATERNS // +// "Priority" players for items example: Items with INT+AP (Ret / Hunter / Enh) +static bool GroupHasPreferredIntApUser(Player* self) +{ + if (!self) return false; + Group* g = self->GetGroup(); + if (!g) return false; + for (GroupReference* it = g->GetFirstMember(); it; it = it->next()) + { + Player* p = it->GetSource(); + if (!p || !p->IsInWorld() || p == self) continue; + if (!GET_PLAYERBOT_AI(p)) continue; // IGNORE humans: only bots are considered + SpecTraits t = GetSpecTraits(p); + const bool isProtPal = t.isProtPal || (t.cls == CLASS_PALADIN && t.isTank); // fallback + if (t.isRetPal || isProtPal || t.cls == CLASS_HUNTER || t.isEnhSham) + { + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP group check: prioritaire présent -> {} (spec='{}')", + p->GetName(), t.spec); + return true; + } + } + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP group check: aucun prioritaire bot présent"); + return false; +} + +// Helper: Is there a priority "likely" to NEED (upgrade/equipable)? +static bool GroupHasPreferredIntApUserLikelyToNeed(Player* self, ItemTemplate const* proto) +{ + Group* g = self ? self->GetGroup() : nullptr; + if (!g || !proto) return false; + + for (GroupReference* it = g->GetFirstMember(); it; it = it->next()) + { + Player* p = it->GetSource(); + if (!p || !p->IsInWorld() || p == self) continue; + + // ignore all real player + PlayerbotAI* pai = GET_PLAYERBOT_AI(p); + if (!pai) continue; + + SpecTraits t = GetSpecTraits(p); + const bool isProtPal = t.isProtPal || (t.cls == CLASS_PALADIN && t.isTank); + const bool isPreferred = t.isRetPal || isProtPal || t.cls == CLASS_HUNTER || t.isEnhSham; + if (!isPreferred) continue; + + // Estimate if the priority bot will NEED (plausible upgrade). + AiObjectContext* ctx = pai->GetAiObjectContext(); + std::string param = std::to_string(proto->ItemId); + ItemUsage usage = ctx->GetValue("item usage", param)->Get(); + + LOG_DEBUG("playerbots", + "[LootPaternDBG] INT+AP likely-to-need: {} (spec='{}') usage={} (EQUIP=1 REPLACE=2) itemId={}", + p->GetName(), t.spec, (int)usage, proto->ItemId); + + if (usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_EQUIP) + { + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP likely-to-need: {} -> TRUE", p->GetName()); + return true; // a priority bot will probably NEED + } + } + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP likely-to-need: aucun prioritaire bot en position de NEED"); + return false; +} + +// --- Registry "stat patterns" (currently: INT+AP only) +struct StatPattern +{ + const char* name; + bool (*matches)(ItemTemplate const* proto); + bool (*decide)(Player* bot, ItemTemplate const* proto, const SpecTraits& traits, bool& outPrimary); +}; + +// Pattern INT + AP +static bool Match_IntAndAp(ItemTemplate const* proto) +{ + if (!proto) return false; + const bool hasINT = HasAnyStat(proto, { ITEM_MOD_INTELLECT }); + const bool hasAP = HasAnyStat(proto, { ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER }); + const bool match = hasINT && hasAP; + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP match? {} -> item={} \"{}\"", + match ? "YES" : "NO", proto->ItemId, proto->Name1); + return match; +} + +// Decision: Ret/Hunter/Enh -> primary; non-caster physiques -> not primary, casters -> primary only if no priority in the group. +static bool Decide_IntAndAp(Player* bot, ItemTemplate const* proto, const SpecTraits& traits, bool& outPrimary) +{ + LOG_DEBUG("playerbots", "[LootPaternDBG] patterns: evaluation bot={} item={} \"{}\"", + bot->GetName(), proto->ItemId, proto->Name1); + const bool isProtPal = traits.isProtPal || (traits.cls == CLASS_PALADIN && traits.isTank); // fallback + if (traits.isRetPal || isProtPal || traits.cls == CLASS_HUNTER || traits.isEnhSham) + { + outPrimary = true; + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP decide: {} (spec='{}') prioritaire -> primary=1", + bot->GetName(), traits.spec); + return true; + } + if (!traits.isCaster) + { + outPrimary = false; + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP decide: {} (spec='{}') physique non-caster -> primary=0", + bot->GetName(), traits.spec); + return true; + } + // Casters: primary if no priority present + if (!GroupHasPreferredIntApUser(bot)) + { + outPrimary = true; + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP decide: {} (spec='{}') caster, aucun prioritaire -> primary=1", + bot->GetName(), traits.spec); + return true; + } + // or if there are no "likely NEED" priorities + outPrimary = !GroupHasPreferredIntApUserLikelyToNeed(bot, proto); + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP decide: {} (spec='{}') caster, prioritaires présents -> primary={}", + bot->GetName(), traits.spec, (int)outPrimary); + return true; +} + +// List of active patterns (only INT+AP for now) +static const std::array kStatPatterns = { { + { "INT+AP", &Match_IntAndAp, &Decide_IntAndAp }, +} }; + +static bool ApplyStatPatternsForPrimary(Player* bot, ItemTemplate const* proto, const SpecTraits& traits, bool& outPrimary) +{ + for (const auto& p : kStatPatterns) + { + if (p.matches(proto)) + { + if (p.decide(bot, proto, traits, outPrimary)) + { + LOG_DEBUG("playerbots", "[LootPaternDBG] pattern={} primary={} bot={} item={} \"{}\"", + p.name, (int)outPrimary, bot->GetName(), proto->ItemId, proto->Name1); + return true; + } + } + } + LOG_DEBUG("playerbots", "[LootPaternDBG] patterns: aucun pattern applicable bot={} item={} \"{}\"", + bot->GetName(), proto->ItemId, proto->Name1); + return false; +} +// END SPECIAL STUFF // + // Encode "random enchant" parameter for CalculateRollVote / ItemUsage // >0 => randomPropertyId, <0 => randomSuffixId, 0 => none static inline int32 EncodeRandomEnchantParam(uint32 randomPropertyId, uint32 randomSuffix) @@ -211,7 +359,7 @@ static void DebugRecipeRoll(Player* bot, ItemTemplate const* proto, ItemUsage us RollVote before, RollVote after) { LOG_DEBUG("playerbots", - "[LootDBG] {} JC:{} item:{} \"{}\" class={} sub={} bond={} usage={} " + "[LootPaternDBG] {} JC:{} item:{} \"{}\" class={} sub={} bond={} usage={} " "recipeChecked={} useful={} known={} reqSkill={} reqRank={} botRank={} vote:{} -> {} dupCount={}", bot->GetName(), bot->GetSkillValue(SKILL_JEWELCRAFTING), proto->ItemId, proto->Name1, proto->Class, proto->SubClass, proto->Bonding, (int)usage, @@ -219,7 +367,7 @@ static void DebugRecipeRoll(Player* bot, ItemTemplate const* proto, ItemUsage us VoteTxt(before), VoteTxt(after), bot->GetItemCount(proto->ItemId, true)); } -// Maps a RECIPE subclass & item metadata to the SkillLine needed (when RequiredSkill is not set). In DBs, recipes normally have RequiredSkill filled; we keep this as a fallback +// Maps a RECIPE subclass & item metadata to the SkillLine needed (when RequiredSkill is not set). In DBs, recipes normally have RequiredSkill filled; we keep this as a fallback. static uint32 GuessRecipeSkill(ItemTemplate const* proto) { if (!proto) return 0; @@ -435,6 +583,11 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) const bool hasBlockValue = HasAnyStat(proto, { ITEM_MOD_BLOCK_VALUE }); const bool looksTank = hasDef || hasAvoid || hasBlockValue; + // ----- Modulable Hook for special patterns exemple: (Items with Inter+AP) + bool primaryByPattern = false; + if (ApplyStatPatternsForPrimary(bot, proto, traits, primaryByPattern)) + return primaryByPattern; + // Non-tanks (DPS, casters/heals) never NEED purely tank items if (!isTankLikeSpec && looksTank) return false; @@ -696,7 +849,7 @@ bool LootRollAction::Execute(Event event) if (!proto) continue; - LOG_DEBUG("playerbots", "[LootDBG] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", + LOG_DEBUG("playerbots", "[LootRoolDBG] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", bot->GetName(), itemId, proto->Name1, proto->Class, proto->Quality, (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), randomProperty); @@ -710,7 +863,7 @@ bool LootRollAction::Execute(Event event) } ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam); - LOG_DEBUG("playerbots", "[LootDBG] usage={} (EQUIP=1 REPLACE=2 BAD_EQUIP=8 DISENCHANT=13)", (int)usage); + LOG_DEBUG("playerbots", "[LootRoolDBG] usage={} (EQUIP=1 REPLACE=2 BAD_EQUIP=8 DISENCHANT=13)", (int)usage); // Armor Tokens are classed as MISC JUNK (Class 15, Subclass 0), but no other items have class bits and epic quality. // - CanBotUseToken(proto, bot) => NEED @@ -744,7 +897,7 @@ bool LootRollAction::Execute(Event event) { // Lets CalculateRollVote decide (includes SmartNeedBySpec, BoE/BoU, unique, cross-armor) vote = CalculateRollVote(proto, randomProperty); - LOG_DEBUG("playerbots", "[LootDBG] after CalculateRollVote: vote={}", RollVoteToText(vote)); + LOG_DEBUG("playerbots", "[LootRoolDBG] after CalculateRollVote: vote={}", RollVoteToText(vote)); } // Disenchant (Need-Before-Greed): @@ -753,13 +906,13 @@ bool LootRollAction::Execute(Event event) group && (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto)) { - LOG_DEBUG("playerbots", "[LootDBG] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", + LOG_DEBUG("playerbots", "[LootRoolDBG] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", RollVoteToText(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); vote = DISENCHANT; } else { - LOG_DEBUG("playerbots", "[LootDBG] no DE: vote={} lootMethod={} enchSkill={} deOK={}", + LOG_DEBUG("playerbots", "[LootRoolDBG] no DE: vote={} lootMethod={} enchSkill={} deOK={}", RollVoteToText(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); } @@ -790,7 +943,7 @@ bool LootRollAction::Execute(Event event) RollVote sent = vote; if (group->GetLootMethod() == MASTER_LOOT || group->GetLootMethod() == FREE_FOR_ALL) sent = PASS; - LOG_DEBUG("playerbots", "[LootDBG] send vote={} (lootMethod={} Lvl={}) -> guid={} itemId={}", + LOG_DEBUG("playerbots", "[LootPaternDBG] send vote={} (lootMethod={} Lvl={}) -> guid={} itemId={}", RollVoteToText(sent), (int)group->GetLootMethod(), sPlayerbotAIConfig->lootRollLevel, guid.ToString(), itemId); @@ -1040,7 +1193,7 @@ bool MasterLootRollAction::Execute(Event event) if (!group) return false; - LOG_DEBUG("playerbots", "[LootDBG][ML] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", + LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", bot->GetName(), itemId, proto->Name1, proto->Class, proto->Quality, (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), randomPropertyId); @@ -1071,13 +1224,13 @@ bool MasterLootRollAction::Execute(Event event) (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto)) { - LOG_DEBUG("playerbots", "[LootDBG][ML] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", + LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", RollVoteToText(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); vote = DISENCHANT; } else { - LOG_DEBUG("playerbots", "[LootDBG][ML] no DE: vote={} lootMethod={} enchSkill={} deOK={}", + LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] no DE: vote={} lootMethod={} enchSkill={} deOK={}", RollVoteToText(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); } @@ -1086,7 +1239,7 @@ bool MasterLootRollAction::Execute(Event event) if (group->GetLootMethod() == MASTER_LOOT || group->GetLootMethod() == FREE_FOR_ALL) sent = PASS; - LOG_DEBUG("playerbots", "[LootDBG][ML] vote={} -> sent={} lootMethod={} enchSkill={} deOK={}", + LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] vote={} -> sent={} lootMethod={} enchSkill={} deOK={}", RollVoteToText(vote), RollVoteToText(sent), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); From 1ba385322cf913d89ce97fd98a969b9701a47c5d Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 26 Sep 2025 13:16:28 +0200 Subject: [PATCH 15/32] Remove announceLootRollsToMaster --- conf/playerbots.conf.dist | 5 -- src/PlayerbotAIConfig.cpp | 1 - src/PlayerbotAIConfig.h | 1 - src/strategy/actions/LootRollAction.cpp | 65 ++++++------------------- src/strategy/actions/LootRollAction.h | 4 -- 5 files changed, 14 insertions(+), 62 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 9cbd208d09..5f872c588c 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -339,11 +339,6 @@ AiPlayerbot.Roll.CrossArmorExtraMargin = 1.20 # Default: 0.1 AiPlayerbot.Roll.TokenILevelMargin = 0.1 -# Announce each bot's roll choice to its master via private whisper. -# Useful for debugging; can be noisy in large groups. -# Default: 0 (disabled) -AiPlayerbot.Roll.AnnounceToMaster = 0 - # # # diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index e69271cc01..ae243f901d 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -594,7 +594,6 @@ bool PlayerbotAIConfig::Initialize() crossArmorExtraMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.CrossArmorExtraMargin", 1.20f); useDEButton = sConfigMgr->GetOption("AiPlayerbot.Roll.UseDEButton", true); tokenILevelMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.TokenILevelMargin", 0.10f); - announceLootRollsToMaster = sConfigMgr->GetOption("AiPlayerbot.Roll.AnnounceToMaster", false); needOnProfessionRecipes = sConfigMgr->GetOption("AiPlayerbot.Roll.NeedOnProfessionRecipes", true); recipesIgnoreSkillRank = sConfigMgr->GetOption("AiPlayerbot.Roll.Recipes.IgnoreSkillRank", false); smartNeedBySpec = sConfigMgr->GetOption("AiPlayerbot.Roll.SmartNeedBySpec", true); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 86d90d6fc6..7b35da52ae 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -348,7 +348,6 @@ class PlayerbotAIConfig float crossArmorExtraMargin; bool useDEButton; // Allow "Disenchant" on NBG if available float tokenILevelMargin; // ilvl threshold to consider the token an upgrade - bool announceLootRollsToMaster; // ANotify the bot’s master of the roll choice bool smartNeedBySpec; // Intelligent NEED (based on stats/spec) bool needOnProfessionRecipes; // If true, bots will roll NEED on profession recipes/patterns/books they can use & learn. bool recipesIgnoreSkillRank; // If true, ignore skill rank requirement when rolling on profession recipes diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index ff2c7101d2..f08d3ec356 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -897,7 +897,7 @@ bool LootRollAction::Execute(Event event) { // Lets CalculateRollVote decide (includes SmartNeedBySpec, BoE/BoU, unique, cross-armor) vote = CalculateRollVote(proto, randomProperty); - LOG_DEBUG("playerbots", "[LootRoolDBG] after CalculateRollVote: vote={}", RollVoteToText(vote)); + LOG_DEBUG("playerbots", "[LootRoolDBG] after CalculateRollVote: vote={}", VoteTxt(vote)); } // Disenchant (Need-Before-Greed): @@ -907,13 +907,13 @@ bool LootRollAction::Execute(Event event) bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto)) { LOG_DEBUG("playerbots", "[LootRoolDBG] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", - RollVoteToText(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); + VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); vote = DISENCHANT; } else { LOG_DEBUG("playerbots", "[LootRoolDBG] no DE: vote={} lootMethod={} enchSkill={} deOK={}", - RollVoteToText(vote), (int)group->GetLootMethod(), + VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); } @@ -943,11 +943,11 @@ bool LootRollAction::Execute(Event event) RollVote sent = vote; if (group->GetLootMethod() == MASTER_LOOT || group->GetLootMethod() == FREE_FOR_ALL) sent = PASS; + LOG_DEBUG("playerbots", "[LootPaternDBG] send vote={} (lootMethod={} Lvl={}) -> guid={} itemId={}", - RollVoteToText(sent), (int)group->GetLootMethod(), - sPlayerbotAIConfig->lootRollLevel, guid.ToString(), itemId); + VoteTxt(sent), (int)group->GetLootMethod(), sPlayerbotAIConfig->lootRollLevel, guid.ToString(), itemId); - AnnounceRollChoice(sent, itemId); + //AnnounceRollChoice(sent, itemId); group->CountRollVote(bot->GetGUID(), guid, sent); // One item at a time return true; @@ -1120,47 +1120,11 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand return finalVote; } -// Helpers announce -const char* LootRollAction::RollVoteToText(RollVote vote) const -{ - switch (vote) - { - case NEED: return "NEED"; - case GREED: return "GREED"; - case PASS: return "PASS"; - case DISENCHANT: return "DISENCHANT"; - default: return "UNKNOWN"; - } -} - -void LootRollAction::AnnounceRollChoice(RollVote vote, uint32 itemId) +bool MasterLootRollAction::isUseful() { - if (!sPlayerbotAIConfig->announceLootRollsToMaster) - return; - - Player* master = botAI->GetMaster(); - if (!master) - return; - - std::ostringstream ss; - if (ItemTemplate const* ip = sObjectMgr->GetItemTemplate(itemId)) - { - ss << "[Loot] " << bot->GetName() << " choose " << RollVoteToText(vote) - << " on [" << ip->Name1 << "]"; - } - else - { - ss << "[Loot] " << bot->GetName() << " choose " << RollVoteToText(vote) - << " on item " << itemId; - } - - // Message to Master - botAI->TellMaster(ss.str()); + return !botAI->HasActivePlayerMaster(); } - -bool MasterLootRollAction::isUseful() { return !botAI->HasActivePlayerMaster(); } - bool MasterLootRollAction::Execute(Event event) { Player* bot = QueryItemUsageAction::botAI->GetBot(); @@ -1224,15 +1188,14 @@ bool MasterLootRollAction::Execute(Event event) (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto)) { - LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", - RollVoteToText(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); + LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", + VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); vote = DISENCHANT; } else { - LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] no DE: vote={} lootMethod={} enchSkill={} deOK={}", - RollVoteToText(vote), (int)group->GetLootMethod(), - bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); + LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] no DE: vote={} lootMethod={} enchSkill={} deOK={}", + VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); } RollVote sent = vote; @@ -1240,10 +1203,10 @@ bool MasterLootRollAction::Execute(Event event) sent = PASS; LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] vote={} -> sent={} lootMethod={} enchSkill={} deOK={}", - RollVoteToText(vote), RollVoteToText(sent), (int)group->GetLootMethod(), + VoteTxt(vote), VoteTxt(sent), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); - AnnounceRollChoice(sent, itemId); + //AnnounceRollChoice(sent, itemId); group->CountRollVote(bot->GetGUID(), creatureGuid, sent); return true; diff --git a/src/strategy/actions/LootRollAction.h b/src/strategy/actions/LootRollAction.h index 4d815d2693..173694e50a 100644 --- a/src/strategy/actions/LootRollAction.h +++ b/src/strategy/actions/LootRollAction.h @@ -44,10 +44,6 @@ class LootRollAction : public QueryItemUsageAction // randomProperty: 0 (none) ; >0 = itemRandomPropId ; <0 = -itemRandomSuffix RollVote CalculateRollVote(ItemTemplate const* proto, int32 randomProperty = 0); - - // Announce the roll choice to the bot's master (if enabled in config) - void AnnounceRollChoice(RollVote vote, uint32 itemId); - const char* RollVoteToText(RollVote vote) const; }; class MasterLootRollAction : public LootRollAction From 69e3bf11a4559634de5370ae52e75e4c339204ae Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 26 Sep 2025 13:45:22 +0200 Subject: [PATCH 16/32] Changes asked on review --- src/strategy/actions/LootRollAction.cpp | 51 ++++++++++++++++--------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index f08d3ec356..893e42e852 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -417,11 +417,12 @@ static bool IsProfessionRecipeUsefulForBot(Player* bot, ItemTemplate const* prot if (!bot->HasSkill(reqSkill)) return false; - // Required rank check (can be disabled by config) - if (!sPlayerbotAIConfig->recipesIgnoreSkillRank) + // Required rank check (can be disabled by config) — flatten nested if + if (!sPlayerbotAIConfig->recipesIgnoreSkillRank && + reqRank && + bot->GetSkillValue(reqSkill) < reqRank) { - if (reqRank && bot->GetSkillValue(reqSkill) < reqRank) - return false; + return false; } // Avoid NEED if the taught spell is already known @@ -638,16 +639,20 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // Class/spec specific adjustments (readable) // DK Unholy (DPS): allows STR/HIT/HASTE/CRIT/ARP; rejects all caster items - if (traits.cls == CLASS_DEATH_KNIGHT && (traits.spec == "unholy" || traits.spec == "uh")) + if (traits.cls == CLASS_DEATH_KNIGHT && + (traits.spec == "unholy" || traits.spec == "uh") && + looksCaster) { - if (looksCaster) return false; + return false; } + // DK Blood/Frost tanks: DEF/AVOID/STA/STR are useful; reject caster items - if (traits.isDKTank) + if (traits.isDKTank && looksCaster) { - if (looksCaster) return false; - // Pure caster DPS rings/trinkets already filtered above. + return false; } + // Pure caster DPS rings/trinkets already filtered above. + // Hunter (BM/MM/SV): agi/hit/haste/AP/crit/arp → OK; avoid STR-only or caster items if (traits.isHunter) { @@ -656,21 +661,25 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (isJewelry && hasSTR && !hasAGI && !hasAP && !hasDpsRatings) return false; } + // Rogue (all specs): same strict physical filter (no caster items) - if (traits.isRogue) + if (traits.isRogue && looksCaster) { - if (looksCaster) return false; + return false; } + // Warrior Arms/Fury : no caster items - if (traits.isWarrior && !traits.isWarProt) + if (traits.isWarrior && !traits.isWarProt && looksCaster) { - if (looksCaster) return false; + return false; } + // Warrior Protection: DEF/AVOID/STA/STR are useful; no caster items - if (traits.isWarProt) + if (traits.isWarProt && looksCaster) { - if (looksCaster) return false; + return false; } + // Shaman Enhancement: no Spell Power weapons/shields, no pure INT/SP items if (traits.isEnhSham) { @@ -679,10 +688,11 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) && hasSP) return false; } + // Druid Feral (tank/DPS): AGI/STA/AVOID/ARP/EXP → OK; no caster items - if (traits.isFeralTk || traits.isFeralDps) + if ((traits.isFeralTk || traits.isFeralDps) && looksCaster) { - if (looksCaster) return false; + return false; } // Paladin Retribution: physical DPS (no caster items; forbid SP weapons/shields; enforce 2H only) @@ -1113,9 +1123,12 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand RollVote finalVote = StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? vote : PASS; // DEBUG: dump for recipes - if (IsRecipeItem(proto)) + if (IsRecipeItem(proto)) { DebugRecipeRoll(bot, proto, usage, recipeChecked, recipeUseful, recipeKnown, - reqSkillDbg, reqRankDbg, botRankDbg, /*before*/ (recipeNeed?NEED:PASS), /*after*/ finalVote); + reqSkillDbg, reqRankDbg, botRankDbg, + /*before*/ (recipeNeed ? NEED : PASS), + /*after*/ finalVote); + } return finalVote; } From df16ef3986bb0279680a808ea8cf48985d9e242a Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 29 Sep 2025 12:18:10 +0200 Subject: [PATCH 17/32] Update LootRollAction.cpp --- src/strategy/actions/LootRollAction.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 893e42e852..dc857d33b9 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -957,7 +957,6 @@ bool LootRollAction::Execute(Event event) LOG_DEBUG("playerbots", "[LootPaternDBG] send vote={} (lootMethod={} Lvl={}) -> guid={} itemId={}", VoteTxt(sent), (int)group->GetLootMethod(), sPlayerbotAIConfig->lootRollLevel, guid.ToString(), itemId); - //AnnounceRollChoice(sent, itemId); group->CountRollVote(bot->GetGUID(), guid, sent); // One item at a time return true; @@ -1219,7 +1218,6 @@ bool MasterLootRollAction::Execute(Event event) VoteTxt(vote), VoteTxt(sent), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); - //AnnounceRollChoice(sent, itemId); group->CountRollVote(bot->GetGUID(), creatureGuid, sent); return true; From 341676bd72828c5bc15b463937deb149a578201b Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 6 Oct 2025 16:24:22 +0200 Subject: [PATCH 18/32] Update LootRollAction.cpp --- src/strategy/actions/LootRollAction.cpp | 881 +++++++++++++----------- 1 file changed, 494 insertions(+), 387 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 227e9c6951..d674c6cdc7 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -5,95 +5,97 @@ #include "LootRollAction.h" +#include +#include +#include +#include +#include +#include +#include + +#include "AiFactory.h" +#include "AiObjectContext.h" #include "Event.h" #include "Group.h" #include "ItemUsageValue.h" +#include "Log.h" #include "LootAction.h" #include "ObjectMgr.h" +#include "Player.h" #include "PlayerbotAIConfig.h" #include "Playerbots.h" -#include "Player.h" -#include "StatsWeightCalculator.h" -#include -#include -#include -#include #include "SharedDefines.h" -#include "AiFactory.h" -#include -#include -#include "SpellMgr.h" #include "SkillDiscovery.h" -#include "Log.h" -#include -#include "AiObjectContext.h" +#include "SpellMgr.h" +#include "StatsWeightCalculator.h" // Groups the "class + archetype" info in the same place struct SpecTraits { uint8 cls = 0; std::string spec; - bool isCaster = false; // everything that affects SP/INT/SPI/MP5 - bool isHealer = false; - bool isTank = false; - bool isPhysical = false; // profiles STR/AGI/AP/ARP/EXP… + bool isCaster = false; // everything that affects SP/INT/SPI/MP5 + bool isHealer = false; + bool isTank = false; + bool isPhysical = false; // profiles STR/AGI/AP/ARP/EXP… // Useful flags for fine rules - bool isDKTank = false; - bool isWarProt = false; - bool isEnhSham = false; - bool isFeralTk = false; - bool isFeralDps = false; - bool isHunter = false; - bool isRogue = false; - bool isWarrior = false; - bool isRetPal = false; - bool isProtPal = false; + bool isDKTank = false; + bool isWarProt = false; + bool isEnhSham = false; + bool isFeralTk = false; + bool isFeralDps = false; + bool isHunter = false; + bool isRogue = false; + bool isWarrior = false; + bool isRetPal = false; + bool isProtPal = false; }; static SpecTraits GetSpecTraits(Player* bot) { SpecTraits t; - if (!bot) return t; - t.cls = bot->getClass(); + if (!bot) + return t; + t.cls = bot->getClass(); t.spec = AiFactory::GetPlayerSpecName(bot); - auto specIs = [&](char const* s){ return t.spec == s; }; + auto specIs = [&](char const* s) { return t.spec == s; }; // "Pure caster" classes const bool pureCasterClass = (t.cls == CLASS_MAGE || t.cls == CLASS_WARLOCK || t.cls == CLASS_PRIEST); // Paladin - const bool holyPal = (t.cls == CLASS_PALADIN && specIs("holy")); - const bool protPal = (t.cls == CLASS_PALADIN && (specIs("prot") || specIs("protection"))); - t.isProtPal = protPal; - t.isRetPal = (t.cls == CLASS_PALADIN && !holyPal && !protPal); + const bool holyPal = (t.cls == CLASS_PALADIN && specIs("holy")); + const bool protPal = (t.cls == CLASS_PALADIN && (specIs("prot") || specIs("protection"))); + t.isProtPal = protPal; + t.isRetPal = (t.cls == CLASS_PALADIN && !holyPal && !protPal); // DK - const bool dk = (t.cls == CLASS_DEATH_KNIGHT); - const bool dkBlood = dk && specIs("blood"); - const bool dkFrost = dk && specIs("frost"); - const bool dkUH = dk && (specIs("unholy") || specIs("uh")); - t.isDKTank = (dkBlood || dkFrost) && !dkUH; // tanks “blood/frost” + const bool dk = (t.cls == CLASS_DEATH_KNIGHT); + const bool dkBlood = dk && specIs("blood"); + const bool dkFrost = dk && specIs("frost"); + const bool dkUH = dk && (specIs("unholy") || specIs("uh")); + t.isDKTank = (dkBlood || dkFrost) && !dkUH; // tanks “blood/frost” // Warrior - t.isWarrior = (t.cls == CLASS_WARRIOR); - t.isWarProt = t.isWarrior && (specIs("prot") || specIs("protection")); + t.isWarrior = (t.cls == CLASS_WARRIOR); + t.isWarProt = t.isWarrior && (specIs("prot") || specIs("protection")); // Hunter & Rogue - t.isHunter = (t.cls == CLASS_HUNTER); - t.isRogue = (t.cls == CLASS_ROGUE); + t.isHunter = (t.cls == CLASS_HUNTER); + t.isRogue = (t.cls == CLASS_ROGUE); // Shaman - const bool eleSham = (t.cls == CLASS_SHAMAN && specIs("elemental")); - const bool restoSh = (t.cls == CLASS_SHAMAN && (specIs("resto") || specIs("restoration"))); - t.isEnhSham = (t.cls == CLASS_SHAMAN && (specIs("enhance") || specIs("enhancement"))); + const bool eleSham = (t.cls == CLASS_SHAMAN && specIs("elemental")); + const bool restoSh = (t.cls == CLASS_SHAMAN && (specIs("resto") || specIs("restoration"))); + t.isEnhSham = (t.cls == CLASS_SHAMAN && (specIs("enhance") || specIs("enhancement"))); // Druid - const bool balance = (t.cls == CLASS_DRUID && specIs("balance")); - const bool restoDr = (t.cls == CLASS_DRUID && (specIs("resto") || specIs("restoration"))); - t.isFeralTk = (t.cls == CLASS_DRUID && (specIs("feraltank") || specIs("bear"))); - t.isFeralDps = (t.cls == CLASS_DRUID && (specIs("feraldps") || specIs("cat") || specIs("kitty"))); + const bool balance = (t.cls == CLASS_DRUID && specIs("balance")); + const bool restoDr = (t.cls == CLASS_DRUID && (specIs("resto") || specIs("restoration"))); + t.isFeralTk = (t.cls == CLASS_DRUID && (specIs("feraltank") || specIs("bear"))); + t.isFeralDps = (t.cls == CLASS_DRUID && (specIs("feraldps") || specIs("cat") || specIs("kitty"))); // Roles - t.isHealer = holyPal || restoSh || restoDr || (t.cls == CLASS_PRIEST && !specIs("shadow")); - t.isTank = protPal || t.isWarProt || t.isFeralTk || t.isDKTank; - t.isCaster = pureCasterClass || holyPal || eleSham || balance || restoDr || restoSh - || (t.cls == CLASS_PRIEST && specIs("shadow")); // Shadow = caster DPS + t.isHealer = holyPal || restoSh || restoDr || (t.cls == CLASS_PRIEST && !specIs("shadow")); + t.isTank = protPal || t.isWarProt || t.isFeralTk || t.isDKTank; + t.isCaster = pureCasterClass || holyPal || eleSham || balance || restoDr || restoSh || + (t.cls == CLASS_PRIEST && specIs("shadow")); // Shadow = caster DPS t.isPhysical = !t.isCaster; return t; } @@ -102,7 +104,8 @@ static SpecTraits GetSpecTraits(Player* bot) // Keep English-only fallback for name checks. static bool IsLockbox(ItemTemplate const* proto) { - if (!proto) return false; + if (!proto) + return false; // Primary, data-driven detection if (proto->LockID) { @@ -112,22 +115,23 @@ static bool IsLockbox(ItemTemplate const* proto) } // English-only fallback on name (align with TokenSlotFromName behavior) std::string n = proto->Name1; - std::transform(n.begin(), n.end(), n.begin(), - [](unsigned char c){ return static_cast(std::tolower(c)); }); + std::transform(n.begin(), n.end(), n.begin(), [](unsigned char c) { return static_cast(std::tolower(c)); }); return n.find("lockbox") != std::string::npos; } // Local helper: not a class member -static bool HasAnyStat(ItemTemplate const* proto, - std::initializer_list mods) +static bool HasAnyStat(ItemTemplate const* proto, std::initializer_list mods) { - if (!proto) return false; + if (!proto) + return false; for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) { - if (!proto->ItemStat[i].ItemStatValue) continue; + if (!proto->ItemStat[i].ItemStatValue) + continue; ItemModType t = ItemModType(proto->ItemStat[i].ItemStatType); for (auto m : mods) - if (t == m) return true; + if (t == m) + return true; } return false; } @@ -136,16 +140,20 @@ static bool HasAnyStat(ItemTemplate const* proto, // "Priority" players for items example: Items with INT+AP (Ret / Hunter / Enh) static bool GroupHasPreferredIntApUser(Player* self) { - if (!self) return false; + if (!self) + return false; Group* g = self->GetGroup(); - if (!g) return false; + if (!g) + return false; for (GroupReference* it = g->GetFirstMember(); it; it = it->next()) { Player* p = it->GetSource(); - if (!p || !p->IsInWorld() || p == self) continue; - if (!GET_PLAYERBOT_AI(p)) continue; // IGNORE humans: only bots are considered + if (!p || !p->IsInWorld() || p == self) + continue; + if (!GET_PLAYERBOT_AI(p)) + continue; // IGNORE humans: only bots are considered SpecTraits t = GetSpecTraits(p); - const bool isProtPal = t.isProtPal || (t.cls == CLASS_PALADIN && t.isTank); // fallback + const bool isProtPal = t.isProtPal || (t.cls == CLASS_PALADIN && t.isTank); // fallback if (t.isRetPal || isProtPal || t.cls == CLASS_HUNTER || t.isEnhSham) { LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP group check: prioritaire présent -> {} (spec='{}')", @@ -153,7 +161,7 @@ static bool GroupHasPreferredIntApUser(Player* self) return true; } } - LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP group check: aucun prioritaire bot présent"); + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP group check: aucun prioritaire bot présent"); return false; } @@ -161,21 +169,25 @@ static bool GroupHasPreferredIntApUser(Player* self) static bool GroupHasPreferredIntApUserLikelyToNeed(Player* self, ItemTemplate const* proto) { Group* g = self ? self->GetGroup() : nullptr; - if (!g || !proto) return false; + if (!g || !proto) + return false; for (GroupReference* it = g->GetFirstMember(); it; it = it->next()) { Player* p = it->GetSource(); - if (!p || !p->IsInWorld() || p == self) continue; + if (!p || !p->IsInWorld() || p == self) + continue; // ignore all real player PlayerbotAI* pai = GET_PLAYERBOT_AI(p); - if (!pai) continue; + if (!pai) + continue; SpecTraits t = GetSpecTraits(p); - const bool isProtPal = t.isProtPal || (t.cls == CLASS_PALADIN && t.isTank); + const bool isProtPal = t.isProtPal || (t.cls == CLASS_PALADIN && t.isTank); const bool isPreferred = t.isRetPal || isProtPal || t.cls == CLASS_HUNTER || t.isEnhSham; - if (!isPreferred) continue; + if (!isPreferred) + continue; // Estimate if the priority bot will NEED (plausible upgrade). AiObjectContext* ctx = pai->GetAiObjectContext(); @@ -207,33 +219,35 @@ struct StatPattern // Pattern INT + AP static bool Match_IntAndAp(ItemTemplate const* proto) { - if (!proto) return false; - const bool hasINT = HasAnyStat(proto, { ITEM_MOD_INTELLECT }); - const bool hasAP = HasAnyStat(proto, { ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER }); + if (!proto) + return false; + const bool hasINT = HasAnyStat(proto, {ITEM_MOD_INTELLECT}); + const bool hasAP = HasAnyStat(proto, {ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER}); const bool match = hasINT && hasAP; - LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP match? {} -> item={} \"{}\"", - match ? "YES" : "NO", proto->ItemId, proto->Name1); + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP match? {} -> item={} \"{}\"", match ? "YES" : "NO", proto->ItemId, + proto->Name1); return match; } -// Decision: Ret/Hunter/Enh -> primary; non-caster physiques -> not primary, casters -> primary only if no priority in the group. +// Decision: Ret/Hunter/Enh -> primary; non-caster physiques -> not primary, casters -> primary only if no priority in +// the group. static bool Decide_IntAndAp(Player* bot, ItemTemplate const* proto, const SpecTraits& traits, bool& outPrimary) { - LOG_DEBUG("playerbots", "[LootPaternDBG] patterns: evaluation bot={} item={} \"{}\"", - bot->GetName(), proto->ItemId, proto->Name1); - const bool isProtPal = traits.isProtPal || (traits.cls == CLASS_PALADIN && traits.isTank); // fallback + LOG_DEBUG("playerbots", "[LootPaternDBG] patterns: evaluation bot={} item={} \"{}\"", bot->GetName(), proto->ItemId, + proto->Name1); + const bool isProtPal = traits.isProtPal || (traits.cls == CLASS_PALADIN && traits.isTank); // fallback if (traits.isRetPal || isProtPal || traits.cls == CLASS_HUNTER || traits.isEnhSham) { outPrimary = true; LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP decide: {} (spec='{}') prioritaire -> primary=1", - bot->GetName(), traits.spec); + bot->GetName(), traits.spec); return true; } if (!traits.isCaster) { outPrimary = false; LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP decide: {} (spec='{}') physique non-caster -> primary=0", - bot->GetName(), traits.spec); + bot->GetName(), traits.spec); return true; } // Casters: primary if no priority present @@ -247,16 +261,17 @@ static bool Decide_IntAndAp(Player* bot, ItemTemplate const* proto, const SpecTr // or if there are no "likely NEED" priorities outPrimary = !GroupHasPreferredIntApUserLikelyToNeed(bot, proto); LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP decide: {} (spec='{}') caster, prioritaires présents -> primary={}", - bot->GetName(), traits.spec, (int)outPrimary); + bot->GetName(), traits.spec, (int)outPrimary); return true; } // List of active patterns (only INT+AP for now) -static const std::array kStatPatterns = { { - { "INT+AP", &Match_IntAndAp, &Decide_IntAndAp }, -} }; +static const std::array kStatPatterns = {{ + {"INT+AP", &Match_IntAndAp, &Decide_IntAndAp}, +}}; -static bool ApplyStatPatternsForPrimary(Player* bot, ItemTemplate const* proto, const SpecTraits& traits, bool& outPrimary) +static bool ApplyStatPatternsForPrimary(Player* bot, ItemTemplate const* proto, const SpecTraits& traits, + bool& outPrimary) { for (const auto& p : kStatPatterns) { @@ -264,14 +279,14 @@ static bool ApplyStatPatternsForPrimary(Player* bot, ItemTemplate const* proto, { if (p.decide(bot, proto, traits, outPrimary)) { - LOG_DEBUG("playerbots", "[LootPaternDBG] pattern={} primary={} bot={} item={} \"{}\"", - p.name, (int)outPrimary, bot->GetName(), proto->ItemId, proto->Name1); + LOG_DEBUG("playerbots", "[LootPaternDBG] pattern={} primary={} bot={} item={} \"{}\"", p.name, + (int)outPrimary, bot->GetName(), proto->ItemId, proto->Name1); return true; } } } - LOG_DEBUG("playerbots", "[LootPaternDBG] patterns: aucun pattern applicable bot={} item={} \"{}\"", - bot->GetName(), proto->ItemId, proto->Name1); + LOG_DEBUG("playerbots", "[LootPaternDBG] patterns: aucun pattern applicable bot={} item={} \"{}\"", bot->GetName(), + proto->ItemId, proto->Name1); return false; } // END SPECIAL STUFF // @@ -280,35 +295,38 @@ static bool ApplyStatPatternsForPrimary(Player* bot, ItemTemplate const* proto, // >0 => randomPropertyId, <0 => randomSuffixId, 0 => none static inline int32 EncodeRandomEnchantParam(uint32 randomPropertyId, uint32 randomSuffix) { - if (randomPropertyId) return static_cast(randomPropertyId); - if (randomSuffix) return -static_cast(randomSuffix); + if (randomPropertyId) + return static_cast(randomPropertyId); + if (randomSuffix) + return -static_cast(randomSuffix); return 0; } // Professions helpers Returns true if the item is a Recipe/Pattern/Book (ITEM_CLASS_RECIPE) -static inline bool IsRecipeItem(ItemTemplate const* proto) -{ - return proto && proto->Class == ITEM_CLASS_RECIPE; -} +static inline bool IsRecipeItem(ItemTemplate const* proto) { return proto && proto->Class == ITEM_CLASS_RECIPE; } -// Try to detect the spell taught by a recipe and whether the bot already knows it. If we can’t resolve the taught spell reliably, we fall back to "has profession + skill rank OK". +// Try to detect the spell taught by a recipe and whether the bot already knows it. If we can’t resolve the taught spell +// reliably, we fall back to "has profession + skill rank OK". static bool BotAlreadyKnowsRecipeSpell(Player* bot, ItemTemplate const* proto) { - if (!bot || !proto) return false; + if (!bot || !proto) + return false; // Many recipes have a single spell that "teaches" another spell (learned spell in EffectTriggerSpell). for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { uint32 teach = proto->Spells[i].SpellId; - if (!teach) continue; + if (!teach) + continue; SpellInfo const* si = sSpellMgr->GetSpellInfo(teach); - if (!si) continue; + if (!si) + continue; for (int eff = 0; eff < MAX_SPELL_EFFECTS; ++eff) { if (si->Effects[eff].Effect == SPELL_EFFECT_LEARN_SPELL) { uint32 learned = si->Effects[eff].TriggerSpell; if (learned && bot->HasSpell(learned)) - return true; // already knows the taught spell + return true; // already knows the taught spell } } } @@ -318,7 +336,8 @@ static bool BotAlreadyKnowsRecipeSpell(Player* bot, ItemTemplate const* proto) // Special-case: Book of Glyph Mastery (can own several; do not downgrade NEED on duplicates) static bool IsGlyphMasteryBook(ItemTemplate const* proto) { - if (!proto) return false; + if (!proto) + return false; // 1) Type-safety: it must be a recipe book if (proto->Class != ITEM_CLASS_RECIPE || proto->SubClass != ITEM_SUBCLASS_BOOK) @@ -326,7 +345,7 @@ static bool IsGlyphMasteryBook(ItemTemplate const* proto) // 2) Primary signal: the on-use spell of the book on WotLK DBs // (Spell 64323: "Book of Glyph Mastery"). Use a named constant to avoid magic numbers. - constexpr uint32 SPELL_BOOK_OF_GLYPH_MASTERY = 64323; // WotLK 3.3.5a + constexpr uint32 SPELL_BOOK_OF_GLYPH_MASTERY = 64323; // WotLK 3.3.5a for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { if (proto->Spells[i].SpellId == SPELL_BOOK_OF_GLYPH_MASTERY) @@ -338,9 +357,8 @@ static bool IsGlyphMasteryBook(ItemTemplate const* proto) { std::string n = proto->Name1; std::transform(n.begin(), n.end(), n.begin(), - [](unsigned char c){ return static_cast(std::tolower(c)); }); - if (n.find("glyph mastery") != std::string::npos || - n.find("book of glyph mastery") != std::string::npos) + [](unsigned char c) { return static_cast(std::tolower(c)); }); + if (n.find("glyph mastery") != std::string::npos || n.find("book of glyph mastery") != std::string::npos) return true; } @@ -348,52 +366,75 @@ static bool IsGlyphMasteryBook(ItemTemplate const* proto) } // Pretty helper for RollVote name in logs -static inline char const* VoteTxt(RollVote v) { - switch (v) { case NEED: return "NEED"; case GREED: return "GREED"; case PASS: return "PASS"; case DISENCHANT: return "DISENCHANT"; default: return "UNKNOWN"; } +static inline char const* VoteTxt(RollVote v) +{ + switch (v) + { + case NEED: + return "NEED"; + case GREED: + return "GREED"; + case PASS: + return "PASS"; + case DISENCHANT: + return "DISENCHANT"; + default: + return "UNKNOWN"; + } } // Centralised debug dump for recipe decisions -static void DebugRecipeRoll(Player* bot, ItemTemplate const* proto, ItemUsage usage, - bool recipeChecked, bool recipeUseful, bool recipeKnown, - uint32 reqSkill, uint32 reqRank, uint32 botRank, +static void DebugRecipeRoll(Player* bot, ItemTemplate const* proto, ItemUsage usage, bool recipeChecked, + bool recipeUseful, bool recipeKnown, uint32 reqSkill, uint32 reqRank, uint32 botRank, RollVote before, RollVote after) { LOG_DEBUG("playerbots", - "[LootPaternDBG] {} JC:{} item:{} \"{}\" class={} sub={} bond={} usage={} " - "recipeChecked={} useful={} known={} reqSkill={} reqRank={} botRank={} vote:{} -> {} dupCount={}", - bot->GetName(), bot->GetSkillValue(SKILL_JEWELCRAFTING), - proto->ItemId, proto->Name1, proto->Class, proto->SubClass, proto->Bonding, (int)usage, - recipeChecked, recipeUseful, recipeKnown, reqSkill, reqRank, botRank, - VoteTxt(before), VoteTxt(after), bot->GetItemCount(proto->ItemId, true)); + "[LootPaternDBG] {} JC:{} item:{} \"{}\" class={} sub={} bond={} usage={} " + "recipeChecked={} useful={} known={} reqSkill={} reqRank={} botRank={} vote:{} -> {} dupCount={}", + bot->GetName(), bot->GetSkillValue(SKILL_JEWELCRAFTING), proto->ItemId, proto->Name1, proto->Class, + proto->SubClass, proto->Bonding, (int)usage, recipeChecked, recipeUseful, recipeKnown, reqSkill, reqRank, + botRank, VoteTxt(before), VoteTxt(after), bot->GetItemCount(proto->ItemId, true)); } -// Maps a RECIPE subclass & item metadata to the SkillLine needed (when RequiredSkill is not set). In DBs, recipes normally have RequiredSkill filled; we keep this as a fallback. +// Maps a RECIPE subclass & item metadata to the SkillLine needed (when RequiredSkill is not set). In DBs, recipes +// normally have RequiredSkill filled; we keep this as a fallback. static uint32 GuessRecipeSkill(ItemTemplate const* proto) { - if (!proto) return 0; + if (!proto) + return 0; // If the core DB is sane, this is set and we can just return it in the caller. // Fallback heuristic on SubClass (books used by professions) switch (proto->SubClass) { - case ITEM_SUBCLASS_BOOK: // e.g. Book of Glyph Mastery + case ITEM_SUBCLASS_BOOK: // e.g. Book of Glyph Mastery // If the name hints glyphs, assume Inscription { std::string n = proto->Name1; - std::transform(n.begin(), n.end(), n.begin(), [](unsigned char c){ return std::tolower(c); }); + std::transform(n.begin(), n.end(), n.begin(), [](unsigned char c) { return std::tolower(c); }); if (n.find("glyph") != std::string::npos) return SKILL_INSCRIPTION; } break; - case ITEM_SUBCLASS_LEATHERWORKING_PATTERN: return SKILL_LEATHERWORKING; - case ITEM_SUBCLASS_TAILORING_PATTERN: return SKILL_TAILORING; - case ITEM_SUBCLASS_ENGINEERING_SCHEMATIC: return SKILL_ENGINEERING; - case ITEM_SUBCLASS_BLACKSMITHING: return SKILL_BLACKSMITHING; - case ITEM_SUBCLASS_COOKING_RECIPE: return SKILL_COOKING; - case ITEM_SUBCLASS_ALCHEMY_RECIPE: return SKILL_ALCHEMY; - case ITEM_SUBCLASS_FIRST_AID_MANUAL: return SKILL_FIRST_AID; - case ITEM_SUBCLASS_ENCHANTING_FORMULA: return SKILL_ENCHANTING; - case ITEM_SUBCLASS_JEWELCRAFTING_RECIPE: return SKILL_JEWELCRAFTING; - default: break; + case ITEM_SUBCLASS_LEATHERWORKING_PATTERN: + return SKILL_LEATHERWORKING; + case ITEM_SUBCLASS_TAILORING_PATTERN: + return SKILL_TAILORING; + case ITEM_SUBCLASS_ENGINEERING_SCHEMATIC: + return SKILL_ENGINEERING; + case ITEM_SUBCLASS_BLACKSMITHING: + return SKILL_BLACKSMITHING; + case ITEM_SUBCLASS_COOKING_RECIPE: + return SKILL_COOKING; + case ITEM_SUBCLASS_ALCHEMY_RECIPE: + return SKILL_ALCHEMY; + case ITEM_SUBCLASS_FIRST_AID_MANUAL: + return SKILL_FIRST_AID; + case ITEM_SUBCLASS_ENCHANTING_FORMULA: + return SKILL_ENCHANTING; + case ITEM_SUBCLASS_JEWELCRAFTING_RECIPE: + return SKILL_JEWELCRAFTING; + default: + break; } return 0; } @@ -401,26 +442,25 @@ static uint32 GuessRecipeSkill(ItemTemplate const* proto) // Returns true if this recipe/pattern/book is useful for one of the bot's professions and not already known. static bool IsProfessionRecipeUsefulForBot(Player* bot, ItemTemplate const* proto) { - if (!bot || !IsRecipeItem(proto)) return false; + if (!bot || !IsRecipeItem(proto)) + return false; // Primary path: DB usually sets RequiredSkill/RequiredSkillRank on recipe items. uint32 reqSkill = proto->RequiredSkill; - uint32 reqRank = proto->RequiredSkillRank; + uint32 reqRank = proto->RequiredSkillRank; if (!reqSkill) reqSkill = GuessRecipeSkill(proto); if (!reqSkill) - return false; // unknown profession, be conservative + return false; // unknown profession, be conservative // Bot must have the profession (or secondary skill like Cooking/First Aid) if (!bot->HasSkill(reqSkill)) return false; // Required rank check (can be disabled by config) — flatten nested if - if (!sPlayerbotAIConfig->recipesIgnoreSkillRank && - reqRank && - bot->GetSkillValue(reqSkill) < reqRank) + if (!sPlayerbotAIConfig->recipesIgnoreSkillRank && reqRank && bot->GetSkillValue(reqSkill) < reqRank) { return false; } @@ -436,19 +476,20 @@ static bool IsProfessionRecipeUsefulForBot(Player* bot, ItemTemplate const* prot // Returns false when the item is a WEAPON / SHIELD / RELIC the class should NOT use. static bool IsWeaponOrShieldOrRelicAllowedForClass(SpecTraits const& traits, ItemTemplate const* proto) { - if (!proto) return true; // non-weapon items handled elsewhere + if (!proto) + return true; // non-weapon items handled elsewhere // Shields (Armor + Shield): Paladin / Warrior / Shaman if ((proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD) || proto->InventoryType == INVTYPE_SHIELD) return traits.cls == CLASS_PALADIN || traits.cls == CLASS_WARRIOR || traits.cls == CLASS_SHAMAN; - // Relics (Idol/Totem/Sigil/Libram) + // Relics (Idol/Totem/Sigil/Libram) if (proto->InventoryType == INVTYPE_RELIC) { // DK (Sigil), Druid (Idol), Paladin (Libram), Shaman (Totem) - return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || - traits.cls == CLASS_PALADIN || traits.cls == CLASS_SHAMAN; + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || traits.cls == CLASS_PALADIN || + traits.cls == CLASS_SHAMAN; } // Not a weapon: nothing to filter here @@ -461,56 +502,50 @@ static bool IsWeaponOrShieldOrRelicAllowedForClass(SpecTraits const& traits, Ite case ITEM_SUBCLASS_WEAPON_AXE: case ITEM_SUBCLASS_WEAPON_AXE2: // 1H axes allowed for Rogue; 2H axes not (but same SubClass enum, handled by InventoryType later if needed) - return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_HUNTER || - traits.cls == CLASS_PALADIN || traits.cls == CLASS_SHAMAN || - traits.cls == CLASS_WARRIOR || traits.cls == CLASS_ROGUE; // Rogue: 1H axes + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_HUNTER || traits.cls == CLASS_PALADIN || + traits.cls == CLASS_SHAMAN || traits.cls == CLASS_WARRIOR || + traits.cls == CLASS_ROGUE; // Rogue: 1H axes // Swords - case ITEM_SUBCLASS_WEAPON_SWORD: // 1H swords - return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_HUNTER || - traits.cls == CLASS_MAGE || traits.cls == CLASS_PALADIN || - traits.cls == CLASS_ROGUE || traits.cls == CLASS_WARRIOR || - traits.cls == CLASS_WARLOCK; // Warlocks can use 1H swords - case ITEM_SUBCLASS_WEAPON_SWORD2: // 2H swords - return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_HUNTER || - traits.cls == CLASS_PALADIN || traits.cls == CLASS_WARRIOR; + case ITEM_SUBCLASS_WEAPON_SWORD: // 1H swords + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_HUNTER || traits.cls == CLASS_MAGE || + traits.cls == CLASS_PALADIN || traits.cls == CLASS_ROGUE || traits.cls == CLASS_WARRIOR || + traits.cls == CLASS_WARLOCK; // Warlocks can use 1H swords + case ITEM_SUBCLASS_WEAPON_SWORD2: // 2H swords + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_HUNTER || traits.cls == CLASS_PALADIN || + traits.cls == CLASS_WARRIOR; // Maces - case ITEM_SUBCLASS_WEAPON_MACE: // 1H maces - return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || - traits.cls == CLASS_PALADIN || traits.cls == CLASS_PRIEST || - traits.cls == CLASS_SHAMAN || traits.cls == CLASS_WARRIOR || - traits.cls == CLASS_ROGUE; // Rogue: 1H maces in WotLK - case ITEM_SUBCLASS_WEAPON_MACE2: // 2H maces - return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || - traits.cls == CLASS_PALADIN || traits.cls == CLASS_WARRIOR; // Shaman: no 2H maces + case ITEM_SUBCLASS_WEAPON_MACE: // 1H maces + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || traits.cls == CLASS_PALADIN || + traits.cls == CLASS_PRIEST || traits.cls == CLASS_SHAMAN || traits.cls == CLASS_WARRIOR || + traits.cls == CLASS_ROGUE; // Rogue: 1H maces in WotLK + case ITEM_SUBCLASS_WEAPON_MACE2: // 2H maces + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || traits.cls == CLASS_PALADIN || + traits.cls == CLASS_WARRIOR; // Shaman: no 2H maces // Polearms case ITEM_SUBCLASS_WEAPON_POLEARM: - return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || - traits.cls == CLASS_HUNTER || traits.cls == CLASS_PALADIN || - traits.cls == CLASS_WARRIOR; // Shaman: cannot use polearms + return traits.cls == CLASS_DEATH_KNIGHT || traits.cls == CLASS_DRUID || traits.cls == CLASS_HUNTER || + traits.cls == CLASS_PALADIN || traits.cls == CLASS_WARRIOR; // Shaman: cannot use polearms // Staves case ITEM_SUBCLASS_WEAPON_STAFF: - return traits.cls == CLASS_DRUID || traits.cls == CLASS_HUNTER || - traits.cls == CLASS_MAGE || traits.cls == CLASS_PRIEST || - traits.cls == CLASS_SHAMAN || traits.cls == CLASS_WARLOCK; + return traits.cls == CLASS_DRUID || traits.cls == CLASS_HUNTER || traits.cls == CLASS_MAGE || + traits.cls == CLASS_PRIEST || traits.cls == CLASS_SHAMAN || traits.cls == CLASS_WARLOCK; // Daggers case ITEM_SUBCLASS_WEAPON_DAGGER: - return traits.cls == CLASS_DRUID || traits.cls == CLASS_HUNTER || - traits.cls == CLASS_MAGE || traits.cls == CLASS_PRIEST || - traits.cls == CLASS_ROGUE || traits.cls == CLASS_WARLOCK || - traits.cls == CLASS_WARRIOR; // Warriors can use daggers + return traits.cls == CLASS_DRUID || traits.cls == CLASS_HUNTER || traits.cls == CLASS_MAGE || + traits.cls == CLASS_PRIEST || traits.cls == CLASS_ROGUE || traits.cls == CLASS_WARLOCK || + traits.cls == CLASS_WARRIOR; // Warriors can use daggers // Fist weapons case ITEM_SUBCLASS_WEAPON_FIST: - return traits.cls == CLASS_DRUID || traits.cls == CLASS_HUNTER || - traits.cls == CLASS_ROGUE || traits.cls == CLASS_SHAMAN || - traits.cls == CLASS_WARRIOR; + return traits.cls == CLASS_DRUID || traits.cls == CLASS_HUNTER || traits.cls == CLASS_ROGUE || + traits.cls == CLASS_SHAMAN || traits.cls == CLASS_WARRIOR; - // Ranged (bows / guns / crossbows) — Hunters primary; also usable by Warriors/Rogues + // Ranged (bows / guns / crossbows) — Hunters primary; also usable by Warriors/Rogues case ITEM_SUBCLASS_WEAPON_BOW: case ITEM_SUBCLASS_WEAPON_GUN: case ITEM_SUBCLASS_WEAPON_CROSSBOW: @@ -524,26 +559,24 @@ static bool IsWeaponOrShieldOrRelicAllowedForClass(SpecTraits const& traits, Ite case ITEM_SUBCLASS_WEAPON_THROWN: return traits.cls == CLASS_WARRIOR || traits.cls == CLASS_ROGUE; - // Exotic / fishing / misc — disallow - case ITEM_SUBCLASS_WEAPON_EXOTIC: - case ITEM_SUBCLASS_WEAPON_EXOTIC2: - case ITEM_SUBCLASS_WEAPON_MISC: - case ITEM_SUBCLASS_WEAPON_FISHING_POLE: - default: - return false; + // Exotic / fishing / misc — disallow + case ITEM_SUBCLASS_WEAPON_EXOTIC: + case ITEM_SUBCLASS_WEAPON_EXOTIC2: + case ITEM_SUBCLASS_WEAPON_MISC: + case ITEM_SUBCLASS_WEAPON_FISHING_POLE: + default: + return false; } } static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) { - if (!bot || !proto) return false; + if (!bot || !proto) + return false; // Jewelry/cloaks: focus mainly on the stat profile (stat set) - const bool isJewelry = - proto->InventoryType == INVTYPE_TRINKET || - proto->InventoryType == INVTYPE_FINGER || - proto->InventoryType == INVTYPE_NECK || - proto->InventoryType == INVTYPE_CLOAK; + const bool isJewelry = proto->InventoryType == INVTYPE_TRINKET || proto->InventoryType == INVTYPE_FINGER || + proto->InventoryType == INVTYPE_NECK || proto->InventoryType == INVTYPE_CLOAK; const SpecTraits traits = GetSpecTraits(bot); @@ -553,35 +586,35 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) return false; // Flags class/spec - const bool isCasterSpec = traits.isCaster; + const bool isCasterSpec = traits.isCaster; const bool isTankLikeSpec = traits.isTank; const bool isPhysicalSpec = traits.isPhysical; // Loot Stats - const bool hasINT = HasAnyStat(proto, { ITEM_MOD_INTELLECT }); - const bool hasSPI = HasAnyStat(proto, { ITEM_MOD_SPIRIT }); - const bool hasMP5 = HasAnyStat(proto, { ITEM_MOD_MANA_REGENERATION }); - const bool hasSP = HasAnyStat(proto, { ITEM_MOD_SPELL_POWER }); - const bool hasSTR = HasAnyStat(proto, { ITEM_MOD_STRENGTH }); - const bool hasAGI = HasAnyStat(proto, { ITEM_MOD_AGILITY }); - const bool hasSTA = HasAnyStat(proto, { ITEM_MOD_STAMINA }); - const bool hasAP = HasAnyStat(proto, { ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER }); - const bool hasARP = HasAnyStat(proto, { ITEM_MOD_ARMOR_PENETRATION_RATING }); - const bool hasEXP = HasAnyStat(proto, { ITEM_MOD_EXPERTISE_RATING }); - const bool hasHIT = HasAnyStat(proto, { ITEM_MOD_HIT_RATING }); - const bool hasHASTE = HasAnyStat(proto, { ITEM_MOD_HASTE_RATING }); - const bool hasCRIT = HasAnyStat(proto, { ITEM_MOD_CRIT_RATING }); - const bool hasDef = HasAnyStat(proto, { ITEM_MOD_DEFENSE_SKILL_RATING }); - const bool hasAvoid = HasAnyStat(proto, { ITEM_MOD_DODGE_RATING, ITEM_MOD_PARRY_RATING, ITEM_MOD_BLOCK_RATING }); + const bool hasINT = HasAnyStat(proto, {ITEM_MOD_INTELLECT}); + const bool hasSPI = HasAnyStat(proto, {ITEM_MOD_SPIRIT}); + const bool hasMP5 = HasAnyStat(proto, {ITEM_MOD_MANA_REGENERATION}); + const bool hasSP = HasAnyStat(proto, {ITEM_MOD_SPELL_POWER}); + const bool hasSTR = HasAnyStat(proto, {ITEM_MOD_STRENGTH}); + const bool hasAGI = HasAnyStat(proto, {ITEM_MOD_AGILITY}); + const bool hasSTA = HasAnyStat(proto, {ITEM_MOD_STAMINA}); + const bool hasAP = HasAnyStat(proto, {ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER}); + const bool hasARP = HasAnyStat(proto, {ITEM_MOD_ARMOR_PENETRATION_RATING}); + const bool hasEXP = HasAnyStat(proto, {ITEM_MOD_EXPERTISE_RATING}); + const bool hasHIT = HasAnyStat(proto, {ITEM_MOD_HIT_RATING}); + const bool hasHASTE = HasAnyStat(proto, {ITEM_MOD_HASTE_RATING}); + const bool hasCRIT = HasAnyStat(proto, {ITEM_MOD_CRIT_RATING}); + const bool hasDef = HasAnyStat(proto, {ITEM_MOD_DEFENSE_SKILL_RATING}); + const bool hasAvoid = HasAnyStat(proto, {ITEM_MOD_DODGE_RATING, ITEM_MOD_PARRY_RATING, ITEM_MOD_BLOCK_RATING}); // Quick profiles - const bool looksCaster = hasSP || hasSPI || hasMP5 || (hasINT && !hasSTR && !hasAGI && !hasAP); + const bool looksCaster = hasSP || hasSPI || hasMP5 || (hasINT && !hasSTR && !hasAGI && !hasAP); const bool looksPhysical = hasSTR || hasAGI || hasAP || hasARP || hasEXP; - const bool hasDpsRatings = hasHIT || hasHASTE || hasCRIT; // Common to all DPS (physical & casters) + const bool hasDpsRatings = hasHIT || hasHASTE || hasCRIT; // Common to all DPS (physical & casters) // Tank-only profile: Defense / Avoidance (dodge/parry/block rating) / Block value // Do NOT tag all shields as "tank": there are caster shields (INT/SP/MP5) - const bool hasBlockValue = HasAnyStat(proto, { ITEM_MOD_BLOCK_VALUE }); + const bool hasBlockValue = HasAnyStat(proto, {ITEM_MOD_BLOCK_VALUE}); const bool looksTank = hasDef || hasAvoid || hasBlockValue; // ----- Modulable Hook for special patterns exemple: (Items with Inter+AP) @@ -600,14 +633,15 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (looksCaster) return false; // (2) Weapon/shield with Spell Power: always off-spec for DK/War/Rogue/Hunter/Ret/Enh/Feral/Prot - if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) - && hasSP) + if ((proto->Class == ITEM_CLASS_WEAPON || + (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && + hasSP) return false; // (3) Jewelry/cloaks with caster stats (SP/SPI/MP5/pure INT) -> off-spec if (isJewelry && looksCaster) return false; } - else // Caster/Healer + else // Caster/Healer { // (1) Casters/healers should not NEED pure melee items (STR/AP/ARP/EXP) without INT/SP if (looksPhysical && !hasSP && !hasINT) @@ -625,10 +659,8 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (proto->Class == ITEM_CLASS_WEAPON) { const bool meleeWeapon = - proto->InventoryType == INVTYPE_WEAPON || - proto->InventoryType == INVTYPE_WEAPONMAINHAND || - proto->InventoryType == INVTYPE_WEAPONOFFHAND || - proto->InventoryType == INVTYPE_2HWEAPON; + proto->InventoryType == INVTYPE_WEAPON || proto->InventoryType == INVTYPE_WEAPONMAINHAND || + proto->InventoryType == INVTYPE_WEAPONOFFHAND || proto->InventoryType == INVTYPE_2HWEAPON; if (meleeWeapon && traits.isHunter && !hasAGI) return false; @@ -639,24 +671,23 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // Class/spec specific adjustments (readable) // DK Unholy (DPS): allows STR/HIT/HASTE/CRIT/ARP; rejects all caster items - if (traits.cls == CLASS_DEATH_KNIGHT && - (traits.spec == "unholy" || traits.spec == "uh") && - looksCaster) + if (traits.cls == CLASS_DEATH_KNIGHT && (traits.spec == "unholy" || traits.spec == "uh") && looksCaster) { return false; } - + // DK Blood/Frost tanks: DEF/AVOID/STA/STR are useful; reject caster items if (traits.isDKTank && looksCaster) { return false; } // Pure caster DPS rings/trinkets already filtered above. - + // Hunter (BM/MM/SV): agi/hit/haste/AP/crit/arp → OK; avoid STR-only or caster items if (traits.isHunter) { - if (looksCaster) return false; + if (looksCaster) + return false; // Avoid rings with "pure STR" without AGI/AP/DPS ratings if (isJewelry && hasSTR && !hasAGI && !hasAP && !hasDpsRatings) return false; @@ -683,9 +714,11 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // Shaman Enhancement: no Spell Power weapons/shields, no pure INT/SP items if (traits.isEnhSham) { - if (looksCaster) return false; - if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) - && hasSP) + if (looksCaster) + return false; + if ((proto->Class == ITEM_CLASS_WEAPON || + (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && + hasSP) return false; } @@ -698,24 +731,26 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // Paladin Retribution: physical DPS (no caster items; forbid SP weapons/shields; enforce 2H only) if (traits.isRetPal) { - if (looksCaster) return false; + if (looksCaster) + return false; // No Spell Power weapons or shields for Ret if ((proto->Class == ITEM_CLASS_WEAPON || - (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && hasSP) + (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && + hasSP) return false; // Enforce 2H only (no 1H/off-hand/shields/holdables) switch (proto->InventoryType) { - case INVTYPE_WEAPON: // generic 1H - case INVTYPE_WEAPONMAINHAND: // explicit main-hand 1H - case INVTYPE_WEAPONOFFHAND: // off-hand weapon - case INVTYPE_SHIELD: // shields - case INVTYPE_HOLDABLE: // tomes/orbs - return false; // never NEED for Ret + case INVTYPE_WEAPON: // generic 1H + case INVTYPE_WEAPONMAINHAND: // explicit main-hand 1H + case INVTYPE_WEAPONOFFHAND: // off-hand weapon + case INVTYPE_SHIELD: // shields + case INVTYPE_HOLDABLE: // tomes/orbs + return false; // never NEED for Ret default: - break; // INVTYPE_2HWEAPON is allowed; others handled elsewhere + break; // INVTYPE_2HWEAPON is allowed; others handled elsewhere } } @@ -727,20 +762,25 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) return true; } - // Local mini-helper: maps an InventoryType (INVTYPE_*) to an EquipmentSlot (EQUIPMENT_SLOT_*) // Only covers the slots relevant for T7-T10 tokens (head/shoulders/chest/hands/legs). static uint8 EquipmentSlotByInvTypeSafe(uint8 invType) { switch (invType) { - case INVTYPE_HEAD: return EQUIPMENT_SLOT_HEAD; - case INVTYPE_SHOULDERS: return EQUIPMENT_SLOT_SHOULDERS; + case INVTYPE_HEAD: + return EQUIPMENT_SLOT_HEAD; + case INVTYPE_SHOULDERS: + return EQUIPMENT_SLOT_SHOULDERS; case INVTYPE_CHEST: - case INVTYPE_ROBE: return EQUIPMENT_SLOT_CHEST; - case INVTYPE_HANDS: return EQUIPMENT_SLOT_HANDS; - case INVTYPE_LEGS: return EQUIPMENT_SLOT_LEGS; - default: return EQUIPMENT_SLOT_END; // unknown/not applicable + case INVTYPE_ROBE: + return EQUIPMENT_SLOT_CHEST; + case INVTYPE_HANDS: + return EQUIPMENT_SLOT_HANDS; + case INVTYPE_LEGS: + return EQUIPMENT_SLOT_LEGS; + default: + return EQUIPMENT_SLOT_END; // unknown/not applicable } } @@ -750,35 +790,77 @@ static void GetEquipSlotsForInvType(uint8 invType, std::vector& out) out.clear(); switch (invType) { - case INVTYPE_HEAD: out = {EQUIPMENT_SLOT_HEAD}; break; - case INVTYPE_NECK: out = {EQUIPMENT_SLOT_NECK}; break; - case INVTYPE_SHOULDERS: out = {EQUIPMENT_SLOT_SHOULDERS}; break; - case INVTYPE_BODY: /* shirt, ignore */ break; + case INVTYPE_HEAD: + out = {EQUIPMENT_SLOT_HEAD}; + break; + case INVTYPE_NECK: + out = {EQUIPMENT_SLOT_NECK}; + break; + case INVTYPE_SHOULDERS: + out = {EQUIPMENT_SLOT_SHOULDERS}; + break; + case INVTYPE_BODY: /* shirt, ignore */ + break; case INVTYPE_CHEST: - case INVTYPE_ROBE: out = {EQUIPMENT_SLOT_CHEST}; break; - case INVTYPE_WAIST: out = {EQUIPMENT_SLOT_WAIST}; break; - case INVTYPE_LEGS: out = {EQUIPMENT_SLOT_LEGS}; break; - case INVTYPE_FEET: out = {EQUIPMENT_SLOT_FEET}; break; - case INVTYPE_WRISTS: out = {EQUIPMENT_SLOT_WRISTS}; break; - case INVTYPE_HANDS: out = {EQUIPMENT_SLOT_HANDS}; break; - case INVTYPE_FINGER: out = {EQUIPMENT_SLOT_FINGER1, EQUIPMENT_SLOT_FINGER2}; break; - case INVTYPE_TRINKET: out = {EQUIPMENT_SLOT_TRINKET1, EQUIPMENT_SLOT_TRINKET2}; break; - case INVTYPE_CLOAK: out = {EQUIPMENT_SLOT_BACK}; break; - case INVTYPE_WEAPON: out = {EQUIPMENT_SLOT_MAINHAND, EQUIPMENT_SLOT_OFFHAND}; break; - case INVTYPE_2HWEAPON: out = {EQUIPMENT_SLOT_MAINHAND}; break; - case INVTYPE_SHIELD: out = {EQUIPMENT_SLOT_OFFHAND}; break; - case INVTYPE_WEAPONMAINHAND: out = {EQUIPMENT_SLOT_MAINHAND}; break; - case INVTYPE_WEAPONOFFHAND: out = {EQUIPMENT_SLOT_OFFHAND}; break; - case INVTYPE_HOLDABLE: out = {EQUIPMENT_SLOT_OFFHAND}; break; // tome/orb + case INVTYPE_ROBE: + out = {EQUIPMENT_SLOT_CHEST}; + break; + case INVTYPE_WAIST: + out = {EQUIPMENT_SLOT_WAIST}; + break; + case INVTYPE_LEGS: + out = {EQUIPMENT_SLOT_LEGS}; + break; + case INVTYPE_FEET: + out = {EQUIPMENT_SLOT_FEET}; + break; + case INVTYPE_WRISTS: + out = {EQUIPMENT_SLOT_WRISTS}; + break; + case INVTYPE_HANDS: + out = {EQUIPMENT_SLOT_HANDS}; + break; + case INVTYPE_FINGER: + out = {EQUIPMENT_SLOT_FINGER1, EQUIPMENT_SLOT_FINGER2}; + break; + case INVTYPE_TRINKET: + out = {EQUIPMENT_SLOT_TRINKET1, EQUIPMENT_SLOT_TRINKET2}; + break; + case INVTYPE_CLOAK: + out = {EQUIPMENT_SLOT_BACK}; + break; + case INVTYPE_WEAPON: + out = {EQUIPMENT_SLOT_MAINHAND, EQUIPMENT_SLOT_OFFHAND}; + break; + case INVTYPE_2HWEAPON: + out = {EQUIPMENT_SLOT_MAINHAND}; + break; + case INVTYPE_SHIELD: + out = {EQUIPMENT_SLOT_OFFHAND}; + break; + case INVTYPE_WEAPONMAINHAND: + out = {EQUIPMENT_SLOT_MAINHAND}; + break; + case INVTYPE_WEAPONOFFHAND: + out = {EQUIPMENT_SLOT_OFFHAND}; + break; + case INVTYPE_HOLDABLE: + out = {EQUIPMENT_SLOT_OFFHAND}; + break; // tome/orb case INVTYPE_RANGED: case INVTYPE_THROWN: - case INVTYPE_RANGEDRIGHT: out = {EQUIPMENT_SLOT_RANGED}; break; - case INVTYPE_RELIC: out = {EQUIPMENT_SLOT_RANGED}; break; // totem/idol/sigil/libram + case INVTYPE_RANGEDRIGHT: + out = {EQUIPMENT_SLOT_RANGED}; + break; + case INVTYPE_RELIC: + out = {EQUIPMENT_SLOT_RANGED}; + break; // totem/idol/sigil/libram case INVTYPE_TABARD: case INVTYPE_BAG: case INVTYPE_AMMO: case INVTYPE_QUIVER: - default: break; // not relevant for gear + default: + break; // not relevant for gear } } @@ -789,7 +871,8 @@ static bool RollUniqueCheck(ItemTemplate const* proto, Player* bot); // WotLK Heuristic: We can only DE [UNCOMMON..EPIC] quality ARMOR/WEAPON static inline bool IsLikelyDisenchantable(ItemTemplate const* proto) { - if (!proto) return false; + if (!proto) + return false; if (proto->Class != ITEM_CLASS_ARMOR && proto->Class != ITEM_CLASS_WEAPON) return false; return proto->Quality >= ITEM_QUALITY_UNCOMMON && proto->Quality <= ITEM_QUALITY_EPIC; @@ -800,21 +883,24 @@ static inline bool IsLikelyDisenchantable(ItemTemplate const* proto) // Returns an expected InventoryType (HEAD/SHOULDERS/CHEST/HANDS/LEGS) or -1 if unknown. static int8 TokenSlotFromName(ItemTemplate const* proto) { - if (!proto) return -1; + if (!proto) + return -1; std::string n = std::string(proto->Name1); - std::transform(n.begin(), n.end(), n.begin(), - [](unsigned char c){ - return static_cast(std::tolower(c)); - }); + std::transform(n.begin(), n.end(), n.begin(), [](unsigned char c) { return static_cast(std::tolower(c)); }); if (n.find("helm") != std::string::npos || n.find("head") != std::string::npos) return INVTYPE_HEAD; - if (n.find("shoulder") != std::string::npos || n.find("mantle") != std::string::npos || n.find("spauld") != std::string::npos) + if (n.find("shoulder") != std::string::npos || n.find("mantle") != std::string::npos || + n.find("spauld") != std::string::npos) return INVTYPE_SHOULDERS; - if (n.find("chest") != std::string::npos || n.find("tunic") != std::string::npos || n.find("robe") != std::string::npos || n.find("breastplate") != std::string::npos || n.find("chestguard") != std::string::npos) + if (n.find("chest") != std::string::npos || n.find("tunic") != std::string::npos || + n.find("robe") != std::string::npos || n.find("breastplate") != std::string::npos || + n.find("chestguard") != std::string::npos) return INVTYPE_CHEST; - if (n.find("glove") != std::string::npos || n.find("handguard") != std::string::npos || n.find("gauntlet") != std::string::npos) + if (n.find("glove") != std::string::npos || n.find("handguard") != std::string::npos || + n.find("gauntlet") != std::string::npos) return INVTYPE_HANDS; - if (n.find("leg") != std::string::npos || n.find("pant") != std::string::npos || n.find("trouser") != std::string::npos) + if (n.find("leg") != std::string::npos || n.find("pant") != std::string::npos || + n.find("trouser") != std::string::npos) return INVTYPE_LEGS; return -1; } @@ -823,15 +909,18 @@ static int8 TokenSlotFromName(ItemTemplate const* proto) // consider it a "likely upgrade" if ilvl(token) >= ilvl(best equipped item in that slot) + margin. static bool IsTokenLikelyUpgrade(ItemTemplate const* token, uint8 invTypeSlot, Player* bot) { - if (!token || !bot) return false; + if (!token || !bot) + return false; uint8 eq = EquipmentSlotByInvTypeSafe(invTypeSlot); if (eq >= EQUIPMENT_SLOT_END) - return true; // unknown slot -> do not block Need + return true; // unknown slot -> do not block Need Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, eq); - if (!oldItem) return true; // empty slot -> guaranteed upgrade + if (!oldItem) + return true; // empty slot -> guaranteed upgrade ItemTemplate const* oldProto = oldItem->GetTemplate(); - if (!oldProto) return true; - float margin = sPlayerbotAIConfig->tokenILevelMargin; // configurable + if (!oldProto) + return true; + float margin = sPlayerbotAIConfig->tokenILevelMargin; // configurable return (float)token->ItemLevel >= (float)oldProto->ItemLevel + margin; } @@ -850,7 +939,7 @@ bool LootRollAction::Execute(Event event) { continue; } - + ObjectGuid guid = roll->itemGUID; uint32 itemId = roll->itemid; int32 randomProperty = EncodeRandomEnchantParam(roll->itemRandomPropId, roll->itemRandomSuffix); @@ -859,26 +948,32 @@ bool LootRollAction::Execute(Event event) if (!proto) continue; - LOG_DEBUG("playerbots", "[LootRoolDBG] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", - bot->GetName(), itemId, proto->Name1, proto->Class, proto->Quality, - (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), randomProperty); - + LOG_DEBUG("playerbots", + "[LootRoolDBG] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", + bot->GetName(), itemId, proto->Name1, proto->Class, proto->Quality, (int)group->GetLootMethod(), + bot->HasSkill(SKILL_ENCHANTING), randomProperty); + RollVote vote = PASS; std::string itemUsageParam; - - if (randomProperty != 0) { + + if (randomProperty != 0) + { itemUsageParam = std::to_string(itemId) + "," + std::to_string(randomProperty); - } else { + } + else + { itemUsageParam = std::to_string(itemId); } ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam); LOG_DEBUG("playerbots", "[LootRoolDBG] usage={} (EQUIP=1 REPLACE=2 BAD_EQUIP=8 DISENCHANT=13)", (int)usage); - - // Armor Tokens are classed as MISC JUNK (Class 15, Subclass 0), but no other items have class bits and epic quality. + + // Armor Tokens are classed as MISC JUNK (Class 15, Subclass 0), but no other items have class bits and epic + // quality. // - CanBotUseToken(proto, bot) => NEED // - else => GREED - if (proto->Class == ITEM_CLASS_MISC && proto->SubClass == ITEM_SUBCLASS_JUNK && proto->Quality == ITEM_QUALITY_EPIC) + if (proto->Class == ITEM_CLASS_MISC && proto->SubClass == ITEM_SUBCLASS_JUNK && + proto->Quality == ITEM_QUALITY_EPIC) { if (CanBotUseToken(proto, bot)) { @@ -900,31 +995,30 @@ bool LootRollAction::Execute(Event event) } else { - vote = GREED; // Not eligible, so Greed + vote = GREED; // Not eligible, so Greed } } else { // Lets CalculateRollVote decide (includes SmartNeedBySpec, BoE/BoU, unique, cross-armor) vote = CalculateRollVote(proto, randomProperty); - LOG_DEBUG("playerbots", "[LootRoolDBG] after CalculateRollVote: vote={}", VoteTxt(vote)); + LOG_DEBUG("playerbots", "[LootRoolDBG] after CalculateRollVote: vote={}", VoteTxt(vote)); } // Disenchant (Need-Before-Greed): // If the bot is ENCHANTING and the item is disenchantable, prefer DE to GREED - if (vote != NEED && sPlayerbotAIConfig->useDEButton && - group && (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && + if (vote != NEED && sPlayerbotAIConfig->useDEButton && group && + (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto)) { LOG_DEBUG("playerbots", "[LootRoolDBG] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", - VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); - vote = DISENCHANT; + VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); + vote = DISENCHANT; } else { - LOG_DEBUG("playerbots", "[LootRoolDBG] no DE: vote={} lootMethod={} enchSkill={} deOK={}", - VoteTxt(vote), (int)group->GetLootMethod(), - bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); + LOG_DEBUG("playerbots", "[LootRoolDBG] no DE: vote={} lootMethod={} enchSkill={} deOK={}", VoteTxt(vote), + (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); } if (sPlayerbotAIConfig->lootRollLevel == 0) @@ -936,13 +1030,13 @@ bool LootRollAction::Execute(Event event) if (vote == NEED) { if (RollUniqueCheck(proto, bot)) - { - vote = PASS; - } - else - { - vote = GREED; - } + { + vote = PASS; + } + else + { + vote = GREED; + } } else if (vote == GREED) { @@ -954,9 +1048,10 @@ bool LootRollAction::Execute(Event event) if (group->GetLootMethod() == MASTER_LOOT || group->GetLootMethod() == FREE_FOR_ALL) sent = PASS; - LOG_DEBUG("playerbots", "[LootPaternDBG] send vote={} (lootMethod={} Lvl={}) -> guid={} itemId={}", - VoteTxt(sent), (int)group->GetLootMethod(), sPlayerbotAIConfig->lootRollLevel, guid.ToString(), itemId); - + LOG_DEBUG("playerbots", "[LootPaternDBG] send vote={} (lootMethod={} Lvl={}) -> guid={} itemId={}", + VoteTxt(sent), (int)group->GetLootMethod(), sPlayerbotAIConfig->lootRollLevel, guid.ToString(), + itemId); + group->CountRollVote(bot->GetGUID(), guid, sent); // One item at a time return true; @@ -975,33 +1070,36 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand out << proto->ItemId; ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", out.str()); - RollVote vote = PASS; - + RollVote vote = PASS; + bool recipeChecked = false; - bool recipeNeed = false; - bool recipeUseful = false; - bool recipeKnown = false; - uint32 reqSkillDbg = 0, reqRankDbg = 0, botRankDbg = 0; - - // Professions early override + bool recipeNeed = false; + bool recipeUseful = false; + bool recipeKnown = false; + uint32 reqSkillDbg = 0, reqRankDbg = 0, botRankDbg = 0; + + // Professions early override // If enabled, bots NEED on recipes/patterns/books useful to their professions, // provided they can learn them and don't already know the taught spell. if (sPlayerbotAIConfig->needOnProfessionRecipes && IsRecipeItem(proto)) { - recipeChecked = true; - // Collect debug data (what the helper va décider) - reqSkillDbg = proto->RequiredSkill ? proto->RequiredSkill : GuessRecipeSkill(proto); - reqRankDbg = proto->RequiredSkillRank; - botRankDbg = reqSkillDbg ? bot->GetSkillValue(reqSkillDbg) : 0; - recipeKnown = BotAlreadyKnowsRecipeSpell(bot, proto); - - recipeUseful = IsProfessionRecipeUsefulForBot(bot, proto); - if (recipeUseful) { - vote = NEED; - recipeNeed = true; - } else { - vote = GREED; // recipe not for the bot -> GREED - } + recipeChecked = true; + // Collect debug data (what the helper va décider) + reqSkillDbg = proto->RequiredSkill ? proto->RequiredSkill : GuessRecipeSkill(proto); + reqRankDbg = proto->RequiredSkillRank; + botRankDbg = reqSkillDbg ? bot->GetSkillValue(reqSkillDbg) : 0; + recipeKnown = BotAlreadyKnowsRecipeSpell(bot, proto); + + recipeUseful = IsProfessionRecipeUsefulForBot(bot, proto); + if (recipeUseful) + { + vote = NEED; + recipeNeed = true; + } + else + { + vote = GREED; // recipe not for the bot -> GREED + } } // Do not overwrite the choice if we have already decided via the "recipe" logic @@ -1011,11 +1109,11 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand { case ITEM_USAGE_EQUIP: case ITEM_USAGE_REPLACE: - vote = NEED; - // Downgrade to GREED if the item does not match the main spec - if (sPlayerbotAIConfig->smartNeedBySpec && !IsPrimaryForSpec(bot, proto)) - vote = GREED; - break; + vote = NEED; + // Downgrade to GREED if the item does not match the main spec + if (sPlayerbotAIConfig->smartNeedBySpec && !IsPrimaryForSpec(bot, proto)) + vote = GREED; + break; case ITEM_USAGE_BAD_EQUIP: case ITEM_USAGE_GUILD_TASK: case ITEM_USAGE_SKILL: @@ -1031,8 +1129,8 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand vote = PASS; break; } - } - + } + // Lockboxes: if the item is a lockbox and the bot is a Rogue with Lockpicking, prefer NEED. // (Handled before BoE/BoU etiquette; BoE/BoU checks below ignore lockboxes.) const SpecTraits traits = GetSpecTraits(bot); @@ -1045,7 +1143,8 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand constexpr uint32 BIND_WHEN_PICKED_UP = 1; if (vote != NEED && proto->Bonding == BIND_WHEN_PICKED_UP) { - std::vector slots; GetEquipSlotsForInvType(proto->InventoryType, slots); + std::vector slots; + GetEquipSlotsForInvType(proto->InventoryType, slots); if (!slots.empty()) { const bool specOk = !sPlayerbotAIConfig->smartNeedBySpec || IsPrimaryForSpec(bot, proto); @@ -1055,24 +1154,26 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand { if (!bot->GetItemByPos(INVENTORY_SLOT_BAG_0, s)) { - vote = NEED; // fills an empty slot -> NEED + vote = NEED; // fills an empty slot -> NEED break; } } } } } - + // BoE/BoU rule: by default, avoid NEED on Bind-on-Equip / Bind-on-Use (raid etiquette) - // Exception: Profession recipes/patterns/books (ITEM_CLASS_RECIPE) keep NEED if they are useful. - constexpr uint32 BIND_WHEN_EQUIPPED = 2; // BoE - constexpr uint32 BIND_WHEN_USE = 3; // BoU + // Exception: Profession recipes/patterns/books (ITEM_CLASS_RECIPE) keep NEED if they are useful. + constexpr uint32 BIND_WHEN_EQUIPPED = 2; // BoE + constexpr uint32 BIND_WHEN_USE = 3; // BoU - if (vote == NEED && !recipeNeed && !isLockbox && proto->Bonding == BIND_WHEN_EQUIPPED && !sPlayerbotAIConfig->allowBoENeedIfUpgrade) + if (vote == NEED && !recipeNeed && !isLockbox && proto->Bonding == BIND_WHEN_EQUIPPED && + !sPlayerbotAIConfig->allowBoENeedIfUpgrade) { vote = GREED; } - if (vote == NEED && !recipeNeed && !isLockbox && proto->Bonding == BIND_WHEN_USE && !sPlayerbotAIConfig->allowBoUNeedIfUpgrade) + if (vote == NEED && !recipeNeed && !isLockbox && proto->Bonding == BIND_WHEN_USE && + !sPlayerbotAIConfig->allowBoUNeedIfUpgrade) { vote = GREED; } @@ -1106,13 +1207,19 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) { Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); - if (!oldItem) continue; + if (!oldItem) + continue; ItemTemplate const* oldProto = oldItem->GetTemplate(); - if (!oldProto) continue; - if (oldProto->Class != ITEM_CLASS_ARMOR) continue; - if (oldProto->InventoryType != proto->InventoryType) continue; - float oldScore = calc.CalculateItem(oldProto->ItemId, oldItem->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID)); - if (oldScore > bestOld) bestOld = oldScore; + if (!oldProto) + continue; + if (oldProto->Class != ITEM_CLASS_ARMOR) + continue; + if (oldProto->InventoryType != proto->InventoryType) + continue; + float oldScore = + calc.CalculateItem(oldProto->ItemId, oldItem->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID)); + if (oldScore > bestOld) + bestOld = oldScore; } if (bestOld > 0.0f && newScore >= bestOld * sPlayerbotAIConfig->crossArmorExtraMargin) vote = NEED; @@ -1122,20 +1229,18 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand RollVote finalVote = StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? vote : PASS; // DEBUG: dump for recipes - if (IsRecipeItem(proto)) { - DebugRecipeRoll(bot, proto, usage, recipeChecked, recipeUseful, recipeKnown, - reqSkillDbg, reqRankDbg, botRankDbg, + if (IsRecipeItem(proto)) + { + DebugRecipeRoll(bot, proto, usage, recipeChecked, recipeUseful, recipeKnown, reqSkillDbg, reqRankDbg, + botRankDbg, /*before*/ (recipeNeed ? NEED : PASS), - /*after*/ finalVote); + /*after*/ finalVote); } return finalVote; } -bool MasterLootRollAction::isUseful() -{ - return !botAI->HasActivePlayerMaster(); -} +bool MasterLootRollAction::isUseful() { return !botAI->HasActivePlayerMaster(); } bool MasterLootRollAction::Execute(Event event) { @@ -1168,10 +1273,11 @@ bool MasterLootRollAction::Execute(Event event) Group* group = bot->GetGroup(); if (!group) return false; - - LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", - bot->GetName(), itemId, proto->Name1, proto->Class, proto->Quality, - (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), randomPropertyId); + + LOG_DEBUG("playerbots", + "[LootEnchantDBG][ML] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", + bot->GetName(), itemId, proto->Name1, proto->Class, proto->Quality, (int)group->GetLootMethod(), + bot->HasSkill(SKILL_ENCHANTING), randomPropertyId); // 1) Token heuristic: ONLY NEED if the target slot is a likely upgrade RollVote vote = PASS; @@ -1179,11 +1285,11 @@ bool MasterLootRollAction::Execute(Event event) { if (CanBotUseToken(proto, bot)) { - int8 tokenSlot = TokenSlotFromName(proto); // Internal helper + int8 tokenSlot = TokenSlotFromName(proto); // Internal helper if (tokenSlot >= 0) vote = IsTokenLikelyUpgrade(proto, (uint8)tokenSlot, bot) ? NEED : GREED; else - vote = GREED; // Unknow slot + vote = GREED; // Unknow slot } else { @@ -1197,27 +1303,28 @@ bool MasterLootRollAction::Execute(Event event) // 2) Disenchant button in Need-Before-Greed if the usage is "DISENCHANT" if (vote != NEED && sPlayerbotAIConfig->useDEButton && - (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && + (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto)) { - LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", - VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); - vote = DISENCHANT; + LOG_DEBUG("playerbots", + "[LootEnchantDBG][ML] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", + VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); + vote = DISENCHANT; } else { - LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] no DE: vote={} lootMethod={} enchSkill={} deOK={}", - VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); + LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] no DE: vote={} lootMethod={} enchSkill={} deOK={}", VoteTxt(vote), + (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); } RollVote sent = vote; if (group->GetLootMethod() == MASTER_LOOT || group->GetLootMethod() == FREE_FOR_ALL) sent = PASS; - - LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] vote={} -> sent={} lootMethod={} enchSkill={} deOK={}", - VoteTxt(vote), VoteTxt(sent), (int)group->GetLootMethod(), - bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); - + + LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] vote={} -> sent={} lootMethod={} enchSkill={} deOK={}", VoteTxt(vote), + VoteTxt(sent), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), + IsLikelyDisenchantable(proto)); + group->CountRollVote(bot->GetGUID(), creatureGuid, sent); return true; @@ -1231,10 +1338,10 @@ static bool CanBotUseToken(ItemTemplate const* proto, Player* bot) // Check if the bot's class is allowed to use the token if (proto->AllowableClass & botClassMask) { - return true; // Bot's class is eligible to use this token + return true; // Bot's class is eligible to use this token } - return false; // Bot's class cannot use this token + return false; // Bot's class cannot use this token } static bool RollUniqueCheck(ItemTemplate const* proto, Player* bot) @@ -1253,18 +1360,18 @@ static bool RollUniqueCheck(ItemTemplate const* proto, Player* bot) } else if (proto->HasFlag(ITEM_FLAG_UNIQUE_EQUIPPABLE) && (bagItemCount > 1)) { - return true; // Unique item already in bag, don't roll for it + return true; // Unique item already in bag, don't roll for it } - return false; // Item is not equipped or in bags, roll for it + return false; // Item is not equipped or in bags, roll for it } bool RollAction::Execute(Event event) { std::string link = event.getParam(); - + if (link.empty()) { - bot->DoRandomRoll(0,100); + bot->DoRandomRoll(0, 100); return false; } ItemIds itemIds = chat->parseItems(link); @@ -1278,16 +1385,16 @@ bool RollAction::Execute(Event event) } std::string itemUsageParam; itemUsageParam = std::to_string(itemId); - + ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam); switch (proto->Class) { case ITEM_CLASS_WEAPON: case ITEM_CLASS_ARMOR: - if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE) - { - bot->DoRandomRoll(0,100); - } + if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE) + { + bot->DoRandomRoll(0, 100); + } } return true; } From f2db90b377d350efe2e3a90122c959fc110672e3 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 6 Oct 2025 16:28:14 +0200 Subject: [PATCH 19/32] Code formating --- src/PlayerbotAIConfig.cpp | 139 ++++++++++++++++++++++---------------- src/PlayerbotAIConfig.h | 41 ++++------- 2 files changed, 93 insertions(+), 87 deletions(-) diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 658c65b23e..c78cf2a323 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -4,7 +4,9 @@ */ #include "PlayerbotAIConfig.h" + #include + #include "Config.h" #include "NewRpgInfo.h" #include "PlayerbotDungeonSuggestionMgr.h" @@ -83,12 +85,15 @@ bool PlayerbotAIConfig::Initialize() lootDelay = sConfigMgr->GetOption("AiPlayerbot.LootDelay", 1000); // Buff system minBotsForGreaterBuff = sConfigMgr->GetOption("AiPlayerbot.MinBotsForGreaterBuff", 3); - rpWarningCooldown = sConfigMgr->GetOption("AiPlayerbot.RPWarningCooldown", 30); - disabledWithoutRealPlayerLoginDelay = sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLoginDelay", 30); - disabledWithoutRealPlayerLogoutDelay = sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLogoutDelay", 300); + rpWarningCooldown = sConfigMgr->GetOption("AiPlayerbot.RPWarningCooldown", 30); + disabledWithoutRealPlayerLoginDelay = + sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLoginDelay", 30); + disabledWithoutRealPlayerLogoutDelay = + sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLogoutDelay", 300); randomBotMinLoginLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotMinLoginLevel", 1); randomBotMaxLoginLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotMaxLoginLevel", 80); - randomBotLogoutOutsideLoginRange = sConfigMgr->GetOption("AiPlayerbot.RandomBotLogoutOutsideLoginRange", false); + randomBotLogoutOutsideLoginRange = + sConfigMgr->GetOption("AiPlayerbot.RandomBotLogoutOutsideLoginRange", false); farDistance = sConfigMgr->GetOption("AiPlayerbot.FarDistance", 20.0f); sightDistance = sConfigMgr->GetOption("AiPlayerbot.SightDistance", 75.0f); @@ -119,8 +124,9 @@ bool PlayerbotAIConfig::Initialize() saveManaThreshold = sConfigMgr->GetOption("AiPlayerbot.SaveManaThreshold", 60); autoAvoidAoe = sConfigMgr->GetOption("AiPlayerbot.AutoAvoidAoe", true); maxAoeAvoidRadius = sConfigMgr->GetOption("AiPlayerbot.MaxAoeAvoidRadius", 15.0f); - LoadSet>(sConfigMgr->GetOption("AiPlayerbot.AoeAvoidSpellWhitelist", "50759,57491,13810"), - aoeAvoidSpellWhitelist); + LoadSet>( + sConfigMgr->GetOption("AiPlayerbot.AoeAvoidSpellWhitelist", "50759,57491,13810"), + aoeAvoidSpellWhitelist); tellWhenAvoidAoe = sConfigMgr->GetOption("AiPlayerbot.TellWhenAvoidAoe", false); randomGearLoweringChance = sConfigMgr->GetOption("AiPlayerbot.RandomGearLoweringChance", 0.0f); @@ -172,9 +178,10 @@ bool PlayerbotAIConfig::Initialize() "976,35,392,2268,4161,4010,4317,4312,3649,3887,3958,3724,4080,3938,3754"), pvpProhibitedAreaIds); fastReactInBG = sConfigMgr->GetOption("AiPlayerbot.FastReactInBG", true); - LoadList>( - sConfigMgr->GetOption("AiPlayerbot.RandomBotQuestIds", "7848,3802,5505,6502,7761,10277,10285,11492,13188,13189,24499,24511,24710,24712"), - randomBotQuestIds); + LoadList>(sConfigMgr->GetOption( + "AiPlayerbot.RandomBotQuestIds", + "7848,3802,5505,6502,7761,10277,10285,11492,13188,13189,24499,24511,24710,24712"), + randomBotQuestIds); LoadSet>( sConfigMgr->GetOption("AiPlayerbot.DisallowedGameObjects", @@ -203,8 +210,7 @@ bool PlayerbotAIConfig::Initialize() maxRandomBotReviveTime = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotReviveTime", 5 * MINUTE); minRandomBotTeleportInterval = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotTeleportInterval", 1 * HOUR); maxRandomBotTeleportInterval = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotTeleportInterval", 5 * HOUR); - permanantlyInWorldTime = - sConfigMgr->GetOption("AiPlayerbot.PermanantlyInWorldTime", 1 * YEAR); + permanantlyInWorldTime = sConfigMgr->GetOption("AiPlayerbot.PermanantlyInWorldTime", 1 * YEAR); randomBotTeleportDistance = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleportDistance", 100); randomBotsPerInterval = sConfigMgr->GetOption("AiPlayerbot.RandomBotsPerInterval", 60); minRandomBotsPriceChangeInterval = @@ -216,10 +222,10 @@ bool PlayerbotAIConfig::Initialize() restrictHealerDPS = sConfigMgr->GetOption("AiPlayerbot.HealerDPSMapRestriction", false); LoadList>( sConfigMgr->GetOption("AiPlayerbot.RestrictedHealerDPSMaps", - "33,34,36,43,47,48,70,90,109,129,209,229,230,329,349,389,429,1001,1004," - "1007,269,540,542,543,545,546,547,552,553,554,555,556,557,558,560,585,574," - "575,576,578,595,599,600,601,602,604,608,619,632,650,658,668,409,469,509," - "531,532,534,544,548,550,564,565,580,249,533,603,615,616,624,631,649,724"), + "33,34,36,43,47,48,70,90,109,129,209,229,230,329,349,389,429,1001,1004," + "1007,269,540,542,543,545,546,547,552,553,554,555,556,557,558,560,585,574," + "575,576,578,595,599,600,601,602,604,608,619,632,650,658,668,409,469,509," + "531,532,534,544,548,550,564,565,580,249,533,603,615,616,624,631,649,724"), restrictedHealerDPSMaps); //////////////////////////// ICC @@ -325,10 +331,14 @@ bool PlayerbotAIConfig::Initialize() randomBotAutoJoinArenaBracket = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinArenaBracket", 7); randomBotAutoJoinICBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinICBrackets", "0,1"); - randomBotAutoJoinEYBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinEYBrackets", "0,1,2"); - randomBotAutoJoinAVBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinAVBrackets", "0,1,2,3"); - randomBotAutoJoinABBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinABBrackets", "0,1,2,3,4,5,6"); - randomBotAutoJoinWSBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinWSBrackets", "0,1,2,3,4,5,6,7"); + randomBotAutoJoinEYBrackets = + sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinEYBrackets", "0,1,2"); + randomBotAutoJoinAVBrackets = + sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinAVBrackets", "0,1,2,3"); + randomBotAutoJoinABBrackets = + sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinABBrackets", "0,1,2,3,4,5,6"); + randomBotAutoJoinWSBrackets = + sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinWSBrackets", "0,1,2,3,4,5,6,7"); randomBotAutoJoinBGICCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGICCount", 0); randomBotAutoJoinBGEYCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGEYCount", 0); @@ -356,22 +366,20 @@ bool PlayerbotAIConfig::Initialize() openGoSpell = sConfigMgr->GetOption("AiPlayerbot.OpenGoSpell", 6477); // Zones for NewRpgStrategy teleportation brackets - std::vector zoneIds = { - // Classic WoW - Low-level zones - 1, 12, 14, 85, 141, 215, 3430, 3524, - // Classic WoW - Mid-level zones - 17, 38, 40, 130, 148, 3433, 3525, - // Classic WoW - High-level zones - 10, 11, 44, 267, 331, 400, 406, - // Classic WoW - Higher-level zones - 3, 8, 15, 16, 33, 45, 47, 51, 357, 405, 440, - // Classic WoW - Top-level zones - 4, 28, 46, 139, 361, 490, 618, 1377, - // The Burning Crusade - Zones - 3483, 3518, 3519, 3520, 3521, 3522, 3523, 4080, - // Wrath of the Lich King - Zones - 65, 66, 67, 210, 394, 495, 2817, 3537, 3711, 4197 - }; + std::vector zoneIds = {// Classic WoW - Low-level zones + 1, 12, 14, 85, 141, 215, 3430, 3524, + // Classic WoW - Mid-level zones + 17, 38, 40, 130, 148, 3433, 3525, + // Classic WoW - High-level zones + 10, 11, 44, 267, 331, 400, 406, + // Classic WoW - Higher-level zones + 3, 8, 15, 16, 33, 45, 47, 51, 357, 405, 440, + // Classic WoW - Top-level zones + 4, 28, 46, 139, 361, 490, 618, 1377, + // The Burning Crusade - Zones + 3483, 3518, 3519, 3520, 3521, 3522, 3523, 4080, + // Wrath of the Lich King - Zones + 65, 66, 67, 210, 394, 495, 2817, 3537, 3711, 4197}; for (uint32 zoneId : zoneIds) { @@ -479,8 +487,8 @@ bool PlayerbotAIConfig::Initialize() } botCheats.clear(); - LoadListString>(sConfigMgr->GetOption("AiPlayerbot.BotCheats", "food,taxi,raid"), - botCheats); + LoadListString>( + sConfigMgr->GetOption("AiPlayerbot.BotCheats", "food,taxi,raid"), botCheats); botCheatMask = 0; @@ -501,8 +509,8 @@ bool PlayerbotAIConfig::Initialize() LoadListString>(sConfigMgr->GetOption("AiPlayerbot.AllowedLogFiles", ""), allowedLogFiles); - LoadListString>(sConfigMgr->GetOption("AiPlayerbot.TradeActionExcludedPrefixes", ""), - tradeActionExcludedPrefixes); + LoadListString>( + sConfigMgr->GetOption("AiPlayerbot.TradeActionExcludedPrefixes", ""), tradeActionExcludedPrefixes); worldBuffs.clear(); loadWorldBuff(); @@ -519,7 +527,8 @@ bool PlayerbotAIConfig::Initialize() minGuildTaskChangeTime = sConfigMgr->GetOption("AiPlayerbot.MinGuildTaskChangeTime", 3 * 24 * 3600); maxGuildTaskChangeTime = sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskChangeTime", 4 * 24 * 3600); minGuildTaskAdvertisementTime = sConfigMgr->GetOption("AiPlayerbot.MinGuildTaskAdvertisementTime", 300); - maxGuildTaskAdvertisementTime = sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskAdvertisementTime", 12 * 3600); + maxGuildTaskAdvertisementTime = + sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskAdvertisementTime", 12 * 3600); minGuildTaskRewardTime = sConfigMgr->GetOption("AiPlayerbot.MinGuildTaskRewardTime", 300); maxGuildTaskRewardTime = sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskRewardTime", 3600); guildTaskAdvertCleanupTime = sConfigMgr->GetOption("AiPlayerbot.GuildTaskAdvertCleanupTime", 300); @@ -591,10 +600,14 @@ bool PlayerbotAIConfig::Initialize() BotActiveAloneForceWhenIsFriend = sConfigMgr->GetOption("AiPlayerbot.BotActiveAloneForceWhenIsFriend", 1); BotActiveAloneForceWhenInGuild = sConfigMgr->GetOption("AiPlayerbot.BotActiveAloneForceWhenInGuild", 1); botActiveAloneSmartScale = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScale", 1); - botActiveAloneSmartScaleDiffLimitfloor = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleDiffLimitfloor", 50); - botActiveAloneSmartScaleDiffLimitCeiling = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleDiffLimitCeiling", 200); - botActiveAloneSmartScaleWhenMinLevel = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel", 1); - botActiveAloneSmartScaleWhenMaxLevel = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel", 80); + botActiveAloneSmartScaleDiffLimitfloor = + sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleDiffLimitfloor", 50); + botActiveAloneSmartScaleDiffLimitCeiling = + sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleDiffLimitCeiling", 200); + botActiveAloneSmartScaleWhenMinLevel = + sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel", 1); + botActiveAloneSmartScaleWhenMaxLevel = + sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel", 80); randombotsWalkingRPG = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG", false); randombotsWalkingRPGInDoors = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG.InDoors", false); @@ -620,7 +633,7 @@ bool PlayerbotAIConfig::Initialize() useDEButton = sConfigMgr->GetOption("AiPlayerbot.Roll.UseDEButton", true); tokenILevelMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.TokenILevelMargin", 0.10f); needOnProfessionRecipes = sConfigMgr->GetOption("AiPlayerbot.Roll.NeedOnProfessionRecipes", true); - recipesIgnoreSkillRank = sConfigMgr->GetOption("AiPlayerbot.Roll.Recipes.IgnoreSkillRank", false); + recipesIgnoreSkillRank = sConfigMgr->GetOption("AiPlayerbot.Roll.Recipes.IgnoreSkillRank", false); smartNeedBySpec = sConfigMgr->GetOption("AiPlayerbot.Roll.SmartNeedBySpec", true); twoRoundsGearInit = sConfigMgr->GetOption("AiPlayerbot.TwoRoundsGearInit", false); syncQuestWithPlayer = sConfigMgr->GetOption("AiPlayerbot.SyncQuestWithPlayer", true); @@ -638,12 +651,14 @@ bool PlayerbotAIConfig::Initialize() autoDoQuests = sConfigMgr->GetOption("AiPlayerbot.AutoDoQuests", true); enableNewRpgStrategy = sConfigMgr->GetOption("AiPlayerbot.EnableNewRpgStrategy", true); - RpgStatusProbWeight[RPG_WANDER_RANDOM] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.WanderRandom", 15); + RpgStatusProbWeight[RPG_WANDER_RANDOM] = + sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.WanderRandom", 15); RpgStatusProbWeight[RPG_WANDER_NPC] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.WanderNpc", 20); RpgStatusProbWeight[RPG_GO_GRIND] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.GoGrind", 15); RpgStatusProbWeight[RPG_GO_CAMP] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.GoCamp", 10); RpgStatusProbWeight[RPG_DO_QUEST] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.DoQuest", 60); - RpgStatusProbWeight[RPG_TRAVEL_FLIGHT] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.TravelFlight", 15); + RpgStatusProbWeight[RPG_TRAVEL_FLIGHT] = + sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.TravelFlight", 15); RpgStatusProbWeight[RPG_REST] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.Rest", 5); syncLevelWithPlayers = sConfigMgr->GetOption("AiPlayerbot.SyncLevelWithPlayers", false); @@ -687,7 +702,8 @@ bool PlayerbotAIConfig::Initialize() } excludedHunterPetFamilies.clear(); - LoadList>(sConfigMgr->GetOption("AiPlayerbot.ExcludedHunterPetFamilies", ""), excludedHunterPetFamilies); + LoadList>(sConfigMgr->GetOption("AiPlayerbot.ExcludedHunterPetFamilies", ""), + excludedHunterPetFamilies); LOG_INFO("server.loading", "---------------------------------------"); LOG_INFO("server.loading", " AI Playerbots initialized "); @@ -723,8 +739,8 @@ bool PlayerbotAIConfig::IsInPvpProhibitedArea(uint32 id) bool PlayerbotAIConfig::IsRestrictedHealerDPSMap(uint32 mapId) const { - return restrictHealerDPS && - std::find(restrictedHealerDPSMaps.begin(), restrictedHealerDPSMaps.end(), mapId) != restrictedHealerDPSMaps.end(); + return restrictHealerDPS && std::find(restrictedHealerDPSMaps.begin(), restrictedHealerDPSMaps.end(), mapId) != + restrictedHealerDPSMaps.end(); } std::string const PlayerbotAIConfig::GetTimestampStr() @@ -810,7 +826,6 @@ void PlayerbotAIConfig::loadWorldBuff() while (std::getline(entryStream, entry, ';')) { - entry.erase(0, entry.find_first_not_of(" \t\r\n")); entry.erase(entry.find_last_not_of(" \t\r\n") + 1); @@ -831,9 +846,12 @@ void PlayerbotAIConfig::loadWorldBuff() std::string token; while (std::getline(metaStream, token, ',')) { - try { + try + { ids.push_back(static_cast(std::stoi(token))); - } catch (...) { + } + catch (...) + { LOG_ERROR("playerbots", "Invalid meta token in [{}]", entry); break; } @@ -848,11 +866,14 @@ void PlayerbotAIConfig::loadWorldBuff() std::istringstream spellStream(spellPart); while (std::getline(spellStream, token, ',')) { - try { + try + { uint32 spellId = static_cast(std::stoi(token)); - worldBuff wb = { spellId, ids[0], ids[1], ids[2], ids[3], ids[4] }; + worldBuff wb = {spellId, ids[0], ids[1], ids[2], ids[3], ids[4]}; worldBuffs.push_back(wb); - } catch (...) { + } + catch (...) + { LOG_ERROR("playerbots", "Invalid spell ID in [{}]", entry); } } @@ -909,8 +930,7 @@ std::vector> PlayerbotAIConfig::ParseTempTalentsOrder(uint32 { break; } - std::sort(spells[tab].begin(), spells[tab].end(), - [&](TalentEntry const* lhs, TalentEntry const* rhs) + std::sort(spells[tab].begin(), spells[tab].end(), [&](TalentEntry const* lhs, TalentEntry const* rhs) { return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; }); for (int i = 0; i < tab_links[tab].size(); i++) { @@ -958,8 +978,7 @@ std::vector> PlayerbotAIConfig::ParseTempPetTalentsOrder(uin spells.push_back(talentInfo); } - std::sort(spells.begin(), spells.end(), - [&](TalentEntry const* lhs, TalentEntry const* rhs) + std::sort(spells.begin(), spells.end(), [&](TalentEntry const* lhs, TalentEntry const* rhs) { return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; }); for (int i = 0; i < tab_link.size(); i++) { diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 9552e22f17..f44d56a22c 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -62,7 +62,7 @@ enum NewRpgStatus : int class PlayerbotAIConfig { public: - PlayerbotAIConfig(){}; + PlayerbotAIConfig() {}; static PlayerbotAIConfig* instance() { static PlayerbotAIConfig instance; @@ -345,14 +345,15 @@ class PlayerbotAIConfig std::string autoPickReward; bool autoEquipUpgradeLoot; float equipUpgradeThreshold; - bool allowBoENeedIfUpgrade; // Loot roll fine-tuning - bool allowBoUNeedIfUpgrade; // Allow NEED on BoU if upgrade + bool allowBoENeedIfUpgrade; // Loot roll fine-tuning + bool allowBoUNeedIfUpgrade; // Allow NEED on BoU if upgrade float crossArmorExtraMargin; - bool useDEButton; // Allow "Disenchant" on NBG if available - float tokenILevelMargin; // ilvl threshold to consider the token an upgrade - bool smartNeedBySpec; // Intelligent NEED (based on stats/spec) - bool needOnProfessionRecipes; // If true, bots will roll NEED on profession recipes/patterns/books they can use & learn. - bool recipesIgnoreSkillRank; // If true, ignore skill rank requirement when rolling on profession recipes + bool useDEButton; // Allow "Disenchant" on NBG if available + float tokenILevelMargin; // ilvl threshold to consider the token an upgrade + bool smartNeedBySpec; // Intelligent NEED (based on stats/spec) + bool needOnProfessionRecipes; // If true, bots will roll NEED on profession recipes/patterns/books they can use & + // learn. + bool recipesIgnoreSkillRank; // If true, ignore skill rank requirement when rolling on profession recipes bool twoRoundsGearInit; bool syncQuestWithPlayer; bool syncQuestForPlayer; @@ -401,25 +402,11 @@ class PlayerbotAIConfig int32 addClassCommand; int32 addClassAccountPoolSize; int32 maintenanceCommand; - bool altMaintenanceAttunementQs, - altMaintenanceBags, - altMaintenanceAmmo, - altMaintenanceFood, - altMaintenanceReagents, - altMaintenanceConsumables, - altMaintenancePotions, - altMaintenanceTalentTree, - altMaintenancePet, - altMaintenancePetTalents, - altMaintenanceClassSpells, - altMaintenanceAvailableSpells, - altMaintenanceSkills, - altMaintenanceReputation, - altMaintenanceSpecialSpells, - altMaintenanceMounts, - altMaintenanceGlyphs, - altMaintenanceKeyring, - altMaintenanceGemsEnchants; + bool altMaintenanceAttunementQs, altMaintenanceBags, altMaintenanceAmmo, altMaintenanceFood, altMaintenanceReagents, + altMaintenanceConsumables, altMaintenancePotions, altMaintenanceTalentTree, altMaintenancePet, + altMaintenancePetTalents, altMaintenanceClassSpells, altMaintenanceAvailableSpells, altMaintenanceSkills, + altMaintenanceReputation, altMaintenanceSpecialSpells, altMaintenanceMounts, altMaintenanceGlyphs, + altMaintenanceKeyring, altMaintenanceGemsEnchants; int32 autoGearCommand, autoGearCommandAltBots, autoGearQualityLimit, autoGearScoreLimit; uint32 useGroundMountAtMinLevel; From be62f1c3204119906ffab993f7473c488ddd6b7f Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 6 Oct 2025 16:47:58 +0200 Subject: [PATCH 20/32] Update PlayerbotAIConfig.cpp --- src/PlayerbotAIConfig.cpp | 139 ++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 79 deletions(-) diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index c78cf2a323..658c65b23e 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -4,9 +4,7 @@ */ #include "PlayerbotAIConfig.h" - #include - #include "Config.h" #include "NewRpgInfo.h" #include "PlayerbotDungeonSuggestionMgr.h" @@ -85,15 +83,12 @@ bool PlayerbotAIConfig::Initialize() lootDelay = sConfigMgr->GetOption("AiPlayerbot.LootDelay", 1000); // Buff system minBotsForGreaterBuff = sConfigMgr->GetOption("AiPlayerbot.MinBotsForGreaterBuff", 3); - rpWarningCooldown = sConfigMgr->GetOption("AiPlayerbot.RPWarningCooldown", 30); - disabledWithoutRealPlayerLoginDelay = - sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLoginDelay", 30); - disabledWithoutRealPlayerLogoutDelay = - sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLogoutDelay", 300); + rpWarningCooldown = sConfigMgr->GetOption("AiPlayerbot.RPWarningCooldown", 30); + disabledWithoutRealPlayerLoginDelay = sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLoginDelay", 30); + disabledWithoutRealPlayerLogoutDelay = sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLogoutDelay", 300); randomBotMinLoginLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotMinLoginLevel", 1); randomBotMaxLoginLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotMaxLoginLevel", 80); - randomBotLogoutOutsideLoginRange = - sConfigMgr->GetOption("AiPlayerbot.RandomBotLogoutOutsideLoginRange", false); + randomBotLogoutOutsideLoginRange = sConfigMgr->GetOption("AiPlayerbot.RandomBotLogoutOutsideLoginRange", false); farDistance = sConfigMgr->GetOption("AiPlayerbot.FarDistance", 20.0f); sightDistance = sConfigMgr->GetOption("AiPlayerbot.SightDistance", 75.0f); @@ -124,9 +119,8 @@ bool PlayerbotAIConfig::Initialize() saveManaThreshold = sConfigMgr->GetOption("AiPlayerbot.SaveManaThreshold", 60); autoAvoidAoe = sConfigMgr->GetOption("AiPlayerbot.AutoAvoidAoe", true); maxAoeAvoidRadius = sConfigMgr->GetOption("AiPlayerbot.MaxAoeAvoidRadius", 15.0f); - LoadSet>( - sConfigMgr->GetOption("AiPlayerbot.AoeAvoidSpellWhitelist", "50759,57491,13810"), - aoeAvoidSpellWhitelist); + LoadSet>(sConfigMgr->GetOption("AiPlayerbot.AoeAvoidSpellWhitelist", "50759,57491,13810"), + aoeAvoidSpellWhitelist); tellWhenAvoidAoe = sConfigMgr->GetOption("AiPlayerbot.TellWhenAvoidAoe", false); randomGearLoweringChance = sConfigMgr->GetOption("AiPlayerbot.RandomGearLoweringChance", 0.0f); @@ -178,10 +172,9 @@ bool PlayerbotAIConfig::Initialize() "976,35,392,2268,4161,4010,4317,4312,3649,3887,3958,3724,4080,3938,3754"), pvpProhibitedAreaIds); fastReactInBG = sConfigMgr->GetOption("AiPlayerbot.FastReactInBG", true); - LoadList>(sConfigMgr->GetOption( - "AiPlayerbot.RandomBotQuestIds", - "7848,3802,5505,6502,7761,10277,10285,11492,13188,13189,24499,24511,24710,24712"), - randomBotQuestIds); + LoadList>( + sConfigMgr->GetOption("AiPlayerbot.RandomBotQuestIds", "7848,3802,5505,6502,7761,10277,10285,11492,13188,13189,24499,24511,24710,24712"), + randomBotQuestIds); LoadSet>( sConfigMgr->GetOption("AiPlayerbot.DisallowedGameObjects", @@ -210,7 +203,8 @@ bool PlayerbotAIConfig::Initialize() maxRandomBotReviveTime = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotReviveTime", 5 * MINUTE); minRandomBotTeleportInterval = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotTeleportInterval", 1 * HOUR); maxRandomBotTeleportInterval = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotTeleportInterval", 5 * HOUR); - permanantlyInWorldTime = sConfigMgr->GetOption("AiPlayerbot.PermanantlyInWorldTime", 1 * YEAR); + permanantlyInWorldTime = + sConfigMgr->GetOption("AiPlayerbot.PermanantlyInWorldTime", 1 * YEAR); randomBotTeleportDistance = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleportDistance", 100); randomBotsPerInterval = sConfigMgr->GetOption("AiPlayerbot.RandomBotsPerInterval", 60); minRandomBotsPriceChangeInterval = @@ -222,10 +216,10 @@ bool PlayerbotAIConfig::Initialize() restrictHealerDPS = sConfigMgr->GetOption("AiPlayerbot.HealerDPSMapRestriction", false); LoadList>( sConfigMgr->GetOption("AiPlayerbot.RestrictedHealerDPSMaps", - "33,34,36,43,47,48,70,90,109,129,209,229,230,329,349,389,429,1001,1004," - "1007,269,540,542,543,545,546,547,552,553,554,555,556,557,558,560,585,574," - "575,576,578,595,599,600,601,602,604,608,619,632,650,658,668,409,469,509," - "531,532,534,544,548,550,564,565,580,249,533,603,615,616,624,631,649,724"), + "33,34,36,43,47,48,70,90,109,129,209,229,230,329,349,389,429,1001,1004," + "1007,269,540,542,543,545,546,547,552,553,554,555,556,557,558,560,585,574," + "575,576,578,595,599,600,601,602,604,608,619,632,650,658,668,409,469,509," + "531,532,534,544,548,550,564,565,580,249,533,603,615,616,624,631,649,724"), restrictedHealerDPSMaps); //////////////////////////// ICC @@ -331,14 +325,10 @@ bool PlayerbotAIConfig::Initialize() randomBotAutoJoinArenaBracket = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinArenaBracket", 7); randomBotAutoJoinICBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinICBrackets", "0,1"); - randomBotAutoJoinEYBrackets = - sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinEYBrackets", "0,1,2"); - randomBotAutoJoinAVBrackets = - sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinAVBrackets", "0,1,2,3"); - randomBotAutoJoinABBrackets = - sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinABBrackets", "0,1,2,3,4,5,6"); - randomBotAutoJoinWSBrackets = - sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinWSBrackets", "0,1,2,3,4,5,6,7"); + randomBotAutoJoinEYBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinEYBrackets", "0,1,2"); + randomBotAutoJoinAVBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinAVBrackets", "0,1,2,3"); + randomBotAutoJoinABBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinABBrackets", "0,1,2,3,4,5,6"); + randomBotAutoJoinWSBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinWSBrackets", "0,1,2,3,4,5,6,7"); randomBotAutoJoinBGICCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGICCount", 0); randomBotAutoJoinBGEYCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGEYCount", 0); @@ -366,20 +356,22 @@ bool PlayerbotAIConfig::Initialize() openGoSpell = sConfigMgr->GetOption("AiPlayerbot.OpenGoSpell", 6477); // Zones for NewRpgStrategy teleportation brackets - std::vector zoneIds = {// Classic WoW - Low-level zones - 1, 12, 14, 85, 141, 215, 3430, 3524, - // Classic WoW - Mid-level zones - 17, 38, 40, 130, 148, 3433, 3525, - // Classic WoW - High-level zones - 10, 11, 44, 267, 331, 400, 406, - // Classic WoW - Higher-level zones - 3, 8, 15, 16, 33, 45, 47, 51, 357, 405, 440, - // Classic WoW - Top-level zones - 4, 28, 46, 139, 361, 490, 618, 1377, - // The Burning Crusade - Zones - 3483, 3518, 3519, 3520, 3521, 3522, 3523, 4080, - // Wrath of the Lich King - Zones - 65, 66, 67, 210, 394, 495, 2817, 3537, 3711, 4197}; + std::vector zoneIds = { + // Classic WoW - Low-level zones + 1, 12, 14, 85, 141, 215, 3430, 3524, + // Classic WoW - Mid-level zones + 17, 38, 40, 130, 148, 3433, 3525, + // Classic WoW - High-level zones + 10, 11, 44, 267, 331, 400, 406, + // Classic WoW - Higher-level zones + 3, 8, 15, 16, 33, 45, 47, 51, 357, 405, 440, + // Classic WoW - Top-level zones + 4, 28, 46, 139, 361, 490, 618, 1377, + // The Burning Crusade - Zones + 3483, 3518, 3519, 3520, 3521, 3522, 3523, 4080, + // Wrath of the Lich King - Zones + 65, 66, 67, 210, 394, 495, 2817, 3537, 3711, 4197 + }; for (uint32 zoneId : zoneIds) { @@ -487,8 +479,8 @@ bool PlayerbotAIConfig::Initialize() } botCheats.clear(); - LoadListString>( - sConfigMgr->GetOption("AiPlayerbot.BotCheats", "food,taxi,raid"), botCheats); + LoadListString>(sConfigMgr->GetOption("AiPlayerbot.BotCheats", "food,taxi,raid"), + botCheats); botCheatMask = 0; @@ -509,8 +501,8 @@ bool PlayerbotAIConfig::Initialize() LoadListString>(sConfigMgr->GetOption("AiPlayerbot.AllowedLogFiles", ""), allowedLogFiles); - LoadListString>( - sConfigMgr->GetOption("AiPlayerbot.TradeActionExcludedPrefixes", ""), tradeActionExcludedPrefixes); + LoadListString>(sConfigMgr->GetOption("AiPlayerbot.TradeActionExcludedPrefixes", ""), + tradeActionExcludedPrefixes); worldBuffs.clear(); loadWorldBuff(); @@ -527,8 +519,7 @@ bool PlayerbotAIConfig::Initialize() minGuildTaskChangeTime = sConfigMgr->GetOption("AiPlayerbot.MinGuildTaskChangeTime", 3 * 24 * 3600); maxGuildTaskChangeTime = sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskChangeTime", 4 * 24 * 3600); minGuildTaskAdvertisementTime = sConfigMgr->GetOption("AiPlayerbot.MinGuildTaskAdvertisementTime", 300); - maxGuildTaskAdvertisementTime = - sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskAdvertisementTime", 12 * 3600); + maxGuildTaskAdvertisementTime = sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskAdvertisementTime", 12 * 3600); minGuildTaskRewardTime = sConfigMgr->GetOption("AiPlayerbot.MinGuildTaskRewardTime", 300); maxGuildTaskRewardTime = sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskRewardTime", 3600); guildTaskAdvertCleanupTime = sConfigMgr->GetOption("AiPlayerbot.GuildTaskAdvertCleanupTime", 300); @@ -600,14 +591,10 @@ bool PlayerbotAIConfig::Initialize() BotActiveAloneForceWhenIsFriend = sConfigMgr->GetOption("AiPlayerbot.BotActiveAloneForceWhenIsFriend", 1); BotActiveAloneForceWhenInGuild = sConfigMgr->GetOption("AiPlayerbot.BotActiveAloneForceWhenInGuild", 1); botActiveAloneSmartScale = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScale", 1); - botActiveAloneSmartScaleDiffLimitfloor = - sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleDiffLimitfloor", 50); - botActiveAloneSmartScaleDiffLimitCeiling = - sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleDiffLimitCeiling", 200); - botActiveAloneSmartScaleWhenMinLevel = - sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel", 1); - botActiveAloneSmartScaleWhenMaxLevel = - sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel", 80); + botActiveAloneSmartScaleDiffLimitfloor = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleDiffLimitfloor", 50); + botActiveAloneSmartScaleDiffLimitCeiling = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleDiffLimitCeiling", 200); + botActiveAloneSmartScaleWhenMinLevel = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel", 1); + botActiveAloneSmartScaleWhenMaxLevel = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel", 80); randombotsWalkingRPG = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG", false); randombotsWalkingRPGInDoors = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG.InDoors", false); @@ -633,7 +620,7 @@ bool PlayerbotAIConfig::Initialize() useDEButton = sConfigMgr->GetOption("AiPlayerbot.Roll.UseDEButton", true); tokenILevelMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.TokenILevelMargin", 0.10f); needOnProfessionRecipes = sConfigMgr->GetOption("AiPlayerbot.Roll.NeedOnProfessionRecipes", true); - recipesIgnoreSkillRank = sConfigMgr->GetOption("AiPlayerbot.Roll.Recipes.IgnoreSkillRank", false); + recipesIgnoreSkillRank = sConfigMgr->GetOption("AiPlayerbot.Roll.Recipes.IgnoreSkillRank", false); smartNeedBySpec = sConfigMgr->GetOption("AiPlayerbot.Roll.SmartNeedBySpec", true); twoRoundsGearInit = sConfigMgr->GetOption("AiPlayerbot.TwoRoundsGearInit", false); syncQuestWithPlayer = sConfigMgr->GetOption("AiPlayerbot.SyncQuestWithPlayer", true); @@ -651,14 +638,12 @@ bool PlayerbotAIConfig::Initialize() autoDoQuests = sConfigMgr->GetOption("AiPlayerbot.AutoDoQuests", true); enableNewRpgStrategy = sConfigMgr->GetOption("AiPlayerbot.EnableNewRpgStrategy", true); - RpgStatusProbWeight[RPG_WANDER_RANDOM] = - sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.WanderRandom", 15); + RpgStatusProbWeight[RPG_WANDER_RANDOM] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.WanderRandom", 15); RpgStatusProbWeight[RPG_WANDER_NPC] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.WanderNpc", 20); RpgStatusProbWeight[RPG_GO_GRIND] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.GoGrind", 15); RpgStatusProbWeight[RPG_GO_CAMP] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.GoCamp", 10); RpgStatusProbWeight[RPG_DO_QUEST] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.DoQuest", 60); - RpgStatusProbWeight[RPG_TRAVEL_FLIGHT] = - sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.TravelFlight", 15); + RpgStatusProbWeight[RPG_TRAVEL_FLIGHT] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.TravelFlight", 15); RpgStatusProbWeight[RPG_REST] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.Rest", 5); syncLevelWithPlayers = sConfigMgr->GetOption("AiPlayerbot.SyncLevelWithPlayers", false); @@ -702,8 +687,7 @@ bool PlayerbotAIConfig::Initialize() } excludedHunterPetFamilies.clear(); - LoadList>(sConfigMgr->GetOption("AiPlayerbot.ExcludedHunterPetFamilies", ""), - excludedHunterPetFamilies); + LoadList>(sConfigMgr->GetOption("AiPlayerbot.ExcludedHunterPetFamilies", ""), excludedHunterPetFamilies); LOG_INFO("server.loading", "---------------------------------------"); LOG_INFO("server.loading", " AI Playerbots initialized "); @@ -739,8 +723,8 @@ bool PlayerbotAIConfig::IsInPvpProhibitedArea(uint32 id) bool PlayerbotAIConfig::IsRestrictedHealerDPSMap(uint32 mapId) const { - return restrictHealerDPS && std::find(restrictedHealerDPSMaps.begin(), restrictedHealerDPSMaps.end(), mapId) != - restrictedHealerDPSMaps.end(); + return restrictHealerDPS && + std::find(restrictedHealerDPSMaps.begin(), restrictedHealerDPSMaps.end(), mapId) != restrictedHealerDPSMaps.end(); } std::string const PlayerbotAIConfig::GetTimestampStr() @@ -826,6 +810,7 @@ void PlayerbotAIConfig::loadWorldBuff() while (std::getline(entryStream, entry, ';')) { + entry.erase(0, entry.find_first_not_of(" \t\r\n")); entry.erase(entry.find_last_not_of(" \t\r\n") + 1); @@ -846,12 +831,9 @@ void PlayerbotAIConfig::loadWorldBuff() std::string token; while (std::getline(metaStream, token, ',')) { - try - { + try { ids.push_back(static_cast(std::stoi(token))); - } - catch (...) - { + } catch (...) { LOG_ERROR("playerbots", "Invalid meta token in [{}]", entry); break; } @@ -866,14 +848,11 @@ void PlayerbotAIConfig::loadWorldBuff() std::istringstream spellStream(spellPart); while (std::getline(spellStream, token, ',')) { - try - { + try { uint32 spellId = static_cast(std::stoi(token)); - worldBuff wb = {spellId, ids[0], ids[1], ids[2], ids[3], ids[4]}; + worldBuff wb = { spellId, ids[0], ids[1], ids[2], ids[3], ids[4] }; worldBuffs.push_back(wb); - } - catch (...) - { + } catch (...) { LOG_ERROR("playerbots", "Invalid spell ID in [{}]", entry); } } @@ -930,7 +909,8 @@ std::vector> PlayerbotAIConfig::ParseTempTalentsOrder(uint32 { break; } - std::sort(spells[tab].begin(), spells[tab].end(), [&](TalentEntry const* lhs, TalentEntry const* rhs) + std::sort(spells[tab].begin(), spells[tab].end(), + [&](TalentEntry const* lhs, TalentEntry const* rhs) { return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; }); for (int i = 0; i < tab_links[tab].size(); i++) { @@ -978,7 +958,8 @@ std::vector> PlayerbotAIConfig::ParseTempPetTalentsOrder(uin spells.push_back(talentInfo); } - std::sort(spells.begin(), spells.end(), [&](TalentEntry const* lhs, TalentEntry const* rhs) + std::sort(spells.begin(), spells.end(), + [&](TalentEntry const* lhs, TalentEntry const* rhs) { return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; }); for (int i = 0; i < tab_link.size(); i++) { From 96e2733c8d153b483950a79bc1021b87fed95b60 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:02:48 +0200 Subject: [PATCH 21/32] Update PlayerbotAIConfig.cpp --- src/PlayerbotAIConfig.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 93278f9db7..5e15335ff8 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -86,9 +86,7 @@ bool PlayerbotAIConfig::Initialize() rpWarningCooldown = sConfigMgr->GetOption("AiPlayerbot.RPWarningCooldown", 30); disabledWithoutRealPlayerLoginDelay = sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLoginDelay", 30); disabledWithoutRealPlayerLogoutDelay = sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLogoutDelay", 300); - randomBotMinLoginLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotMinLoginLevel", 1); - randomBotMaxLoginLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotMaxLoginLevel", 80); - randomBotLogoutOutsideLoginRange = sConfigMgr->GetOption("AiPlayerbot.RandomBotLogoutOutsideLoginRange", false); + farDistance = sConfigMgr->GetOption("AiPlayerbot.FarDistance", 20.0f); sightDistance = sConfigMgr->GetOption("AiPlayerbot.SightDistance", 75.0f); spellDistance = sConfigMgr->GetOption("AiPlayerbot.SpellDistance", 25.0f); From c32132a22d26ab08f5837224fdae414ea8f6a754 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:40:42 +0200 Subject: [PATCH 22/32] Update LootRollAction.cpp --- src/strategy/actions/LootRollAction.cpp | 95 ++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index d674c6cdc7..93308bd082 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -105,7 +105,9 @@ static SpecTraits GetSpecTraits(Player* bot) static bool IsLockbox(ItemTemplate const* proto) { if (!proto) + { return false; + } // Primary, data-driven detection if (proto->LockID) { @@ -123,7 +125,10 @@ static bool IsLockbox(ItemTemplate const* proto) static bool HasAnyStat(ItemTemplate const* proto, std::initializer_list mods) { if (!proto) + { return false; + } + for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) { if (!proto->ItemStat[i].ItemStatValue) @@ -141,10 +146,16 @@ static bool HasAnyStat(ItemTemplate const* proto, std::initializer_listGetGroup(); - if (!g) + + if (!g) + { return false; + } + for (GroupReference* it = g->GetFirstMember(); it; it = it->next()) { Player* p = it->GetSource(); @@ -170,24 +181,32 @@ static bool GroupHasPreferredIntApUserLikelyToNeed(Player* self, ItemTemplate co { Group* g = self ? self->GetGroup() : nullptr; if (!g || !proto) + { return false; + } for (GroupReference* it = g->GetFirstMember(); it; it = it->next()) { Player* p = it->GetSource(); if (!p || !p->IsInWorld() || p == self) + { continue; + } // ignore all real player PlayerbotAI* pai = GET_PLAYERBOT_AI(p); if (!pai) + { continue; + } SpecTraits t = GetSpecTraits(p); const bool isProtPal = t.isProtPal || (t.cls == CLASS_PALADIN && t.isTank); const bool isPreferred = t.isRetPal || isProtPal || t.cls == CLASS_HUNTER || t.isEnhSham; if (!isPreferred) + { continue; + } // Estimate if the priority bot will NEED (plausible upgrade). AiObjectContext* ctx = pai->GetAiObjectContext(); @@ -296,9 +315,14 @@ static bool ApplyStatPatternsForPrimary(Player* bot, ItemTemplate const* proto, static inline int32 EncodeRandomEnchantParam(uint32 randomPropertyId, uint32 randomSuffix) { if (randomPropertyId) + { return static_cast(randomPropertyId); + } if (randomSuffix) + { return -static_cast(randomSuffix); + } + return 0; } @@ -311,6 +335,7 @@ static bool BotAlreadyKnowsRecipeSpell(Player* bot, ItemTemplate const* proto) { if (!bot || !proto) return false; + // Many recipes have a single spell that "teaches" another spell (learned spell in EffectTriggerSpell). for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { @@ -337,11 +362,15 @@ static bool BotAlreadyKnowsRecipeSpell(Player* bot, ItemTemplate const* proto) static bool IsGlyphMasteryBook(ItemTemplate const* proto) { if (!proto) + { return false; + } // 1) Type-safety: it must be a recipe book if (proto->Class != ITEM_CLASS_RECIPE || proto->SubClass != ITEM_SUBCLASS_BOOK) + { return false; + } // 2) Primary signal: the on-use spell of the book on WotLK DBs // (Spell 64323: "Book of Glyph Mastery"). Use a named constant to avoid magic numbers. @@ -443,21 +472,29 @@ static uint32 GuessRecipeSkill(ItemTemplate const* proto) static bool IsProfessionRecipeUsefulForBot(Player* bot, ItemTemplate const* proto) { if (!bot || !IsRecipeItem(proto)) + { return false; + } // Primary path: DB usually sets RequiredSkill/RequiredSkillRank on recipe items. uint32 reqSkill = proto->RequiredSkill; uint32 reqRank = proto->RequiredSkillRank; if (!reqSkill) + { reqSkill = GuessRecipeSkill(proto); + } if (!reqSkill) + { return false; // unknown profession, be conservative + } // Bot must have the profession (or secondary skill like Cooking/First Aid) if (!bot->HasSkill(reqSkill)) + { return false; + } // Required rank check (can be disabled by config) — flatten nested if if (!sPlayerbotAIConfig->recipesIgnoreSkillRank && reqRank && bot->GetSkillValue(reqSkill) < reqRank) @@ -467,7 +504,9 @@ static bool IsProfessionRecipeUsefulForBot(Player* bot, ItemTemplate const* prot // Avoid NEED if the taught spell is already known if (BotAlreadyKnowsRecipeSpell(bot, proto)) + { return false; + } return true; } @@ -477,12 +516,16 @@ static bool IsProfessionRecipeUsefulForBot(Player* bot, ItemTemplate const* prot static bool IsWeaponOrShieldOrRelicAllowedForClass(SpecTraits const& traits, ItemTemplate const* proto) { if (!proto) + { return true; // non-weapon items handled elsewhere + } // Shields (Armor + Shield): Paladin / Warrior / Shaman if ((proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD) || proto->InventoryType == INVTYPE_SHIELD) + { return traits.cls == CLASS_PALADIN || traits.cls == CLASS_WARRIOR || traits.cls == CLASS_SHAMAN; + } // Relics (Idol/Totem/Sigil/Libram) if (proto->InventoryType == INVTYPE_RELIC) @@ -583,7 +626,9 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // Hard filter first: do not NEED weapons/shields/relics the class shouldn't use. // If this returns false, the caller will downgrade to GREED (off-spec/unsupported). if (!IsWeaponOrShieldOrRelicAllowedForClass(traits, proto)) + { return false; + } // Flags class/spec const bool isCasterSpec = traits.isCaster; @@ -620,35 +665,49 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // ----- Modulable Hook for special patterns exemple: (Items with Inter+AP) bool primaryByPattern = false; if (ApplyStatPatternsForPrimary(bot, proto, traits, primaryByPattern)) + { return primaryByPattern; + } // Non-tanks (DPS, casters/heals) never NEED purely tank items if (!isTankLikeSpec && looksTank) + { return false; + } // Generic rules by role/family if (isPhysicalSpec) { // (1) All physicals/tanks: never Spell Power/Spirit/MP5 (even if plate/mail) if (looksCaster) + { return false; + } // (2) Weapon/shield with Spell Power: always off-spec for DK/War/Rogue/Hunter/Ret/Enh/Feral/Prot if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && hasSP) + { return false; + } // (3) Jewelry/cloaks with caster stats (SP/SPI/MP5/pure INT) -> off-spec if (isJewelry && looksCaster) + { return false; + } } else // Caster/Healer { // (1) Casters/healers should not NEED pure melee items (STR/AP/ARP/EXP) without INT/SP if (looksPhysical && !hasSP && !hasINT) + { return false; + } // (2) Melee jewelry (AP/ARP/EXP/STR/AGI) without INT/SP -> off-spec if (isJewelry && looksPhysical && !hasSP && !hasINT) + { return false; + } // Paladin Holy (plate INT+SP/MP5), Shaman Elemental/Restoration (mail INT+SP/MP5), // Druid Balance/Restoration (leather/cloth caster) → OK } @@ -663,10 +722,14 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) proto->InventoryType == INVTYPE_WEAPONOFFHAND || proto->InventoryType == INVTYPE_2HWEAPON; if (meleeWeapon && traits.isHunter && !hasAGI) + { return false; + } if (meleeWeapon && (traits.isFeralTk || traits.isFeralDps) && !hasAGI && !hasSTR) + { return false; + } } // Class/spec specific adjustments (readable) @@ -687,10 +750,14 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (traits.isHunter) { if (looksCaster) + { return false; + } // Avoid rings with "pure STR" without AGI/AP/DPS ratings if (isJewelry && hasSTR && !hasAGI && !hasAP && !hasDpsRatings) + { return false; + } } // Rogue (all specs): same strict physical filter (no caster items) @@ -715,11 +782,15 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (traits.isEnhSham) { if (looksCaster) + { return false; + } if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && hasSP) + { return false; + } } // Druid Feral (tank/DPS): AGI/STA/AVOID/ARP/EXP → OK; no caster items @@ -732,13 +803,17 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (traits.isRetPal) { if (looksCaster) + { return false; + } // No Spell Power weapons or shields for Ret if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && hasSP) + { return false; + } // Enforce 2H only (no 1H/off-hand/shields/holdables) switch (proto->InventoryType) @@ -756,7 +831,9 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // Global VETO: a "physical" spec never considers a caster profile as primary if (sPlayerbotAIConfig->smartNeedBySpec && traits.isPhysical && looksCaster) + { return false; + } // Let the cross-armor rules (CrossArmorExtraMargin) decide for major off-armor upgrades. return true; @@ -872,9 +949,13 @@ static bool RollUniqueCheck(ItemTemplate const* proto, Player* bot); static inline bool IsLikelyDisenchantable(ItemTemplate const* proto) { if (!proto) + { return false; + } if (proto->Class != ITEM_CLASS_ARMOR && proto->Class != ITEM_CLASS_WEAPON) + { return false; + } return proto->Quality >= ITEM_QUALITY_UNCOMMON && proto->Quality <= ITEM_QUALITY_EPIC; } @@ -888,20 +969,30 @@ static int8 TokenSlotFromName(ItemTemplate const* proto) std::string n = std::string(proto->Name1); std::transform(n.begin(), n.end(), n.begin(), [](unsigned char c) { return static_cast(std::tolower(c)); }); if (n.find("helm") != std::string::npos || n.find("head") != std::string::npos) + { return INVTYPE_HEAD; + } if (n.find("shoulder") != std::string::npos || n.find("mantle") != std::string::npos || n.find("spauld") != std::string::npos) + { return INVTYPE_SHOULDERS; + } if (n.find("chest") != std::string::npos || n.find("tunic") != std::string::npos || n.find("robe") != std::string::npos || n.find("breastplate") != std::string::npos || n.find("chestguard") != std::string::npos) + { return INVTYPE_CHEST; + } if (n.find("glove") != std::string::npos || n.find("handguard") != std::string::npos || n.find("gauntlet") != std::string::npos) + { return INVTYPE_HANDS; + } if (n.find("leg") != std::string::npos || n.find("pant") != std::string::npos || n.find("trouser") != std::string::npos) + { return INVTYPE_LEGS; + } return -1; } @@ -913,7 +1004,9 @@ static bool IsTokenLikelyUpgrade(ItemTemplate const* token, uint8 invTypeSlot, P return false; uint8 eq = EquipmentSlotByInvTypeSafe(invTypeSlot); if (eq >= EQUIPMENT_SLOT_END) + { return true; // unknown slot -> do not block Need + } Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, eq); if (!oldItem) return true; // empty slot -> guaranteed upgrade From 2476b19dbda9c5d2f528c62c5deecbb326edd173 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 17 Oct 2025 20:50:01 +0100 Subject: [PATCH 23/32] Update LootRollAction.cpp --- src/strategy/actions/LootRollAction.cpp | 35 ++++++++++++++----------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 93308bd082..cdcea4c69d 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -122,26 +122,32 @@ static bool IsLockbox(ItemTemplate const* proto) } // Local helper: not a class member -static bool HasAnyStat(ItemTemplate const* proto, std::initializer_list mods) +static bool HasAnyStat(ItemTemplate const* proto, + std::initializer_list mods) { if (!proto) { return false; } - + for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) { if (!proto->ItemStat[i].ItemStatValue) continue; - ItemModType t = ItemModType(proto->ItemStat[i].ItemStatType); - for (auto m : mods) + + ItemModType const t = ItemModType(proto->ItemStat[i].ItemStatType); + for (ItemModType const m : mods) + { if (t == m) + { return true; + } + } } return false; } -// SPECIAL ITEMS PRIORITY PATERNS // +// SPECIAL ITEMS PRIORITY PATTERNS // // "Priority" players for items example: Items with INT+AP (Ret / Hunter / Enh) static bool GroupHasPreferredIntApUser(Player* self) { @@ -167,12 +173,12 @@ static bool GroupHasPreferredIntApUser(Player* self) const bool isProtPal = t.isProtPal || (t.cls == CLASS_PALADIN && t.isTank); // fallback if (t.isRetPal || isProtPal || t.cls == CLASS_HUNTER || t.isEnhSham) { - LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP group check: prioritaire présent -> {} (spec='{}')", + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP group check: priority looter present -> {} (spec='{}')", p->GetName(), t.spec); return true; } } - LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP group check: aucun prioritaire bot présent"); + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP group check: no loot-priority bot present"); return false; } @@ -223,7 +229,7 @@ static bool GroupHasPreferredIntApUserLikelyToNeed(Player* self, ItemTemplate co return true; // a priority bot will probably NEED } } - LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP likely-to-need: aucun prioritaire bot en position de NEED"); + LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP likely-to-need: no loot-priority bot in a position to NEED"); return false; } @@ -248,8 +254,7 @@ static bool Match_IntAndAp(ItemTemplate const* proto) return match; } -// Decision: Ret/Hunter/Enh -> primary; non-caster physiques -> not primary, casters -> primary only if no priority in -// the group. +// Decision: Ret/Hunter/Enh -> primary; non-caster physical -> not primary; casters -> primary only if no priority in group/raid static bool Decide_IntAndAp(Player* bot, ItemTemplate const* proto, const SpecTraits& traits, bool& outPrimary) { LOG_DEBUG("playerbots", "[LootPaternDBG] patterns: evaluation bot={} item={} \"{}\"", bot->GetName(), proto->ItemId, @@ -304,7 +309,7 @@ static bool ApplyStatPatternsForPrimary(Player* bot, ItemTemplate const* proto, } } } - LOG_DEBUG("playerbots", "[LootPaternDBG] patterns: aucun pattern applicable bot={} item={} \"{}\"", bot->GetName(), + LOG_DEBUG("playerbots", "[LootPaternDBG] patterns: no applicable pattern bot={} item={} \"{}\"", bot->GetName(), proto->ItemId, proto->Name1); return false; } @@ -1042,7 +1047,7 @@ bool LootRollAction::Execute(Event event) continue; LOG_DEBUG("playerbots", - "[LootRoolDBG] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", + "[LootRollDBG] start bot={} item={} \"{}\" class={} q={} lootMethod={} enchSkill={} rp={}", bot->GetName(), itemId, proto->Name1, proto->Class, proto->Quality, (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), randomProperty); @@ -1059,7 +1064,7 @@ bool LootRollAction::Execute(Event event) } ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam); - LOG_DEBUG("playerbots", "[LootRoolDBG] usage={} (EQUIP=1 REPLACE=2 BAD_EQUIP=8 DISENCHANT=13)", (int)usage); + LOG_DEBUG("playerbots", "[LootRollDBG] usage={} (EQUIP=1 REPLACE=2 BAD_EQUIP=8 DISENCHANT=13)", (int)usage); // Armor Tokens are classed as MISC JUNK (Class 15, Subclass 0), but no other items have class bits and epic // quality. @@ -1095,7 +1100,7 @@ bool LootRollAction::Execute(Event event) { // Lets CalculateRollVote decide (includes SmartNeedBySpec, BoE/BoU, unique, cross-armor) vote = CalculateRollVote(proto, randomProperty); - LOG_DEBUG("playerbots", "[LootRoolDBG] after CalculateRollVote: vote={}", VoteTxt(vote)); + LOG_DEBUG("playerbots", "[LootRollDBG] after CalculateRollVote: vote={}", VoteTxt(vote)); } // Disenchant (Need-Before-Greed): @@ -1110,7 +1115,7 @@ bool LootRollAction::Execute(Event event) } else { - LOG_DEBUG("playerbots", "[LootRoolDBG] no DE: vote={} lootMethod={} enchSkill={} deOK={}", VoteTxt(vote), + LOG_DEBUG("playerbots", "[LootRollDBG] no DE: vote={} lootMethod={} enchSkill={} deOK={}", VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); } From c8a71f01f7f714b2f72888b3061907e708161bd2 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:32:25 +0100 Subject: [PATCH 24/32] Enforce armor-tier logic for loot rolls + optional PASS on off-armor --- conf/playerbots.conf.dist | 6 ++ src/PlayerbotAIConfig.cpp | 1 + src/PlayerbotAIConfig.h | 1 + src/strategy/actions/LootRollAction.cpp | 86 +++++++++++++++++++++++++ 4 files changed, 94 insertions(+) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 33ba337b4a..0982fd7fa6 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -331,6 +331,12 @@ AiPlayerbot.Roll.Recipes.IgnoreSkillRank = 0 # Default: 1.20 (conservative). Use 9.99 to effectively forbid cross-armor NEED. AiPlayerbot.Roll.CrossArmorExtraMargin = 1.20 +# Cross-armor policy: when an off-armor (lower tier) item is not primary, should bots PASS instead of GREED? +# false (0): cross-armor -> GREED (default, legacy behavior) +# true (1): cross-armor -> PASS (bots won't roll at all on off-armor) +# Default: 0 (false) +AiPlayerbot.Roll.CrossArmorGreedIsPass = 0 + # Minimum item level delta to treat a SET TOKEN as a real upgrade (0 means >=). # Prevents NEED on same-tier duplicates. # Example: Paladin Prot with chest ilvl 232: diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 5c88e76abe..adf0b6b2e3 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -613,6 +613,7 @@ bool PlayerbotAIConfig::Initialize() allowBoENeedIfUpgrade = sConfigMgr->GetOption("AiPlayerbot.Roll.AllowBoENeedIfUpgrade", true); allowBoUNeedIfUpgrade = sConfigMgr->GetOption("AiPlayerbot.Roll.AllowBoUNeedIfUpgrade", true); crossArmorExtraMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.CrossArmorExtraMargin", 1.20f); + crossArmorGreedIsPass = sConfigMgr->GetOption("AiPlayerbot.Roll.CrossArmorGreedIsPass", false); useDEButton = sConfigMgr->GetOption("AiPlayerbot.Roll.UseDEButton", true); tokenILevelMargin = sConfigMgr->GetOption("AiPlayerbot.Roll.TokenILevelMargin", 0.10f); needOnProfessionRecipes = sConfigMgr->GetOption("AiPlayerbot.Roll.NeedOnProfessionRecipes", true); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index da98db187e..dff15a8a38 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -346,6 +346,7 @@ class PlayerbotAIConfig bool allowBoENeedIfUpgrade; // Loot roll fine-tuning bool allowBoUNeedIfUpgrade; // Allow NEED on BoU if upgrade float crossArmorExtraMargin; + bool crossArmorGreedIsPass; // If true, off-armor (lower tier) GREED becomes PASS bool useDEButton; // Allow "Disenchant" on NBG if available float tokenILevelMargin; // ilvl threshold to consider the token an upgrade bool smartNeedBySpec; // Intelligent NEED (based on stats/spec) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index cdcea4c69d..e67bc00e43 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -100,6 +100,76 @@ static SpecTraits GetSpecTraits(Player* bot) return t; } +// Return true if the invType is a "body armor" slot (not jewelry/cape/weapon/shield/relic/holdable) +static bool IsBodyArmorInvType(uint8 invType) +{ + switch (invType) + { + case INVTYPE_HEAD: + case INVTYPE_SHOULDERS: + case INVTYPE_CHEST: + case INVTYPE_ROBE: + case INVTYPE_WAIST: + case INVTYPE_LEGS: + case INVTYPE_FEET: + case INVTYPE_WRISTS: + case INVTYPE_HANDS: + return true; + default: + return false; + } +} + +// Preferred armor subclass (ITEM_SUBCLASS_ARMOR_*) for the bot (WotLK rules) +static uint8 PreferredArmorSubclassFor(Player* bot) +{ + if (!bot) + return ITEM_SUBCLASS_ARMOR_CLOTH; + + uint8 cls = bot->getClass(); + uint32 lvl = bot->GetLevel(); + + // Pure cloth classes + if (cls == CLASS_MAGE || cls == CLASS_PRIEST || cls == CLASS_WARLOCK) + return ITEM_SUBCLASS_ARMOR_CLOTH; + + // Leather forever + if (cls == CLASS_DRUID || cls == CLASS_ROGUE) + return ITEM_SUBCLASS_ARMOR_LEATHER; + + // Hunter / Shaman: <40 leather, >=40 mail + if (cls == CLASS_HUNTER || cls == CLASS_SHAMAN) + return (lvl >= 40u) ? ITEM_SUBCLASS_ARMOR_MAIL : ITEM_SUBCLASS_ARMOR_LEATHER; + + // Warrior / Paladin: <40 mail, >=40 plate + if (cls == CLASS_WARRIOR || cls == CLASS_PALADIN) + return (lvl >= 40u) ? ITEM_SUBCLASS_ARMOR_PLATE : ITEM_SUBCLASS_ARMOR_MAIL; + + // Death Knight: plate from the start + if (cls == CLASS_DEATH_KNIGHT) + return ITEM_SUBCLASS_ARMOR_PLATE; + + return ITEM_SUBCLASS_ARMOR_CLOTH; +} + +// True if the item is a body armor piece of a strictly lower tier than preferred (clothClass != ITEM_CLASS_ARMOR) + return false; + if (!IsBodyArmorInvType(proto->InventoryType)) + return false; // ignore jewelry/capes/etc. + // Shields / relics / holdables are not considered here + if (proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD || proto->InventoryType == INVTYPE_RELIC || proto->InventoryType == INVTYPE_HOLDABLE) + return false; + + uint8 preferred = PreferredArmorSubclassFor(bot); + // ITEM_SUBCLASS_ARMOR_* are ordered Cloth(1) < Leather(2) < Mail(3) < Plate(4) on 3.3.5a + return proto->SubClass < preferred; +} + // Local helper: identifies classic lockboxes the Rogue can pick. // Keep English-only fallback for name checks. static bool IsLockbox(ItemTemplate const* proto) @@ -628,6 +698,15 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) const SpecTraits traits = GetSpecTraits(bot); + // HARD GUARD: never consider lower-tier armor as "primary" for the spec (body armor only) + if (!isJewelry && proto->Class == ITEM_CLASS_ARMOR && IsBodyArmorInvType(proto->InventoryType)) + { + if (IsLowerTierArmorForBot(bot, proto)) + { + return false; // forces NEED->GREED earlier when SmartNeedBySpec is enabled + } + } + // Hard filter first: do not NEED weapons/shields/relics the class shouldn't use. // If this returns false, the caller will downgrade to GREED (off-spec/unsupported). if (!IsWeaponOrShieldOrRelicAllowedForClass(traits, proto)) @@ -1229,6 +1308,13 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand } } + // Policy: turn GREED into PASS on off-armor (lower tier) if configured + if (vote == GREED && proto->Class == ITEM_CLASS_ARMOR && sPlayerbotAIConfig->crossArmorGreedIsPass) + { + if (IsLowerTierArmorForBot(bot, proto)) + vote = PASS; + } + // Lockboxes: if the item is a lockbox and the bot is a Rogue with Lockpicking, prefer NEED. // (Handled before BoE/BoU etiquette; BoE/BoU checks below ignore lockboxes.) const SpecTraits traits = GetSpecTraits(bot); From d7f48975ea81d4feee3d3a595b8a33a3c23f2fd7 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Sat, 22 Nov 2025 13:41:21 +0100 Subject: [PATCH 25/32] correct some decisions --- src/strategy/actions/LootRollAction.cpp | 222 ++++++++++++++++++++---- 1 file changed, 188 insertions(+), 34 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index e67bc00e43..576750d743 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -170,6 +170,58 @@ static bool IsLowerTierArmorForBot(Player* bot, ItemTemplate const* proto) return proto->SubClass < preferred; } +// Returns true if another bot in the group (with proper armor tier) is likely to NEED this armor piece. +static bool GroupHasPrimaryArmorUserLikelyToNeed(Player* self, ItemTemplate const* proto, int32 randomProperty) +{ + if (!self || !proto) + return false; + + if (proto->Class != ITEM_CLASS_ARMOR || !IsBodyArmorInvType(proto->InventoryType)) + return false; + + Group* group = self->GetGroup(); + if (!group) + return false; + + std::ostringstream out; + if (randomProperty != 0) + out << proto->ItemId << "," << randomProperty; + else + out << proto->ItemId; + + std::string const param = out.str(); + + for (GroupReference* it = group->GetFirstMember(); it; it = it->next()) + { + Player* member = it->GetSource(); + if (!member || member == self || !member->IsInWorld()) + continue; + + PlayerbotAI* memberAI = GET_PLAYERBOT_AI(member); + if (!memberAI) + continue; // ignore real players + + // Do not treat it as "primary" for bots for which this is also cross-armor + if (IsLowerTierArmorForBot(member, proto)) + continue; + + AiObjectContext* ctx = memberAI->GetAiObjectContext(); + if (!ctx) + continue; + + ItemUsage otherUsage = ctx->GetValue("item usage", param)->Get(); + if (otherUsage == ITEM_USAGE_EQUIP || otherUsage == ITEM_USAGE_REPLACE) + { + LOG_DEBUG("playerbots", + "[LootRollDBG] cross-armor: primary armor user {} likely to need item={} \"{}\"", + member->GetName(), proto->ItemId, proto->Name1); + return true; + } + } + + return false; +} + // Local helper: identifies classic lockboxes the Rogue can pick. // Keep English-only fallback for name checks. static bool IsLockbox(ItemTemplate const* proto) @@ -227,7 +279,7 @@ static bool GroupHasPreferredIntApUser(Player* self) } Group* g = self->GetGroup(); - if (!g) + if (!g) { return false; } @@ -318,9 +370,19 @@ static bool Match_IntAndAp(ItemTemplate const* proto) return false; const bool hasINT = HasAnyStat(proto, {ITEM_MOD_INTELLECT}); const bool hasAP = HasAnyStat(proto, {ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER}); - const bool match = hasINT && hasAP; - LOG_DEBUG("playerbots", "[LootPaternDBG] INT+AP match? {} -> item={} \"{}\"", match ? "YES" : "NO", proto->ItemId, - proto->Name1); + const bool hasSP = HasAnyStat(proto, {ITEM_MOD_SPELL_POWER}); + const bool hasSPI = HasAnyStat(proto, {ITEM_MOD_SPIRIT}); + const bool hasMP5 = HasAnyStat(proto, {ITEM_MOD_MANA_REGENERATION}); + + // Treat as INT+AP hybrid only if it is not clearly a caster/healer item (SP/SPI/MP5). + const bool looksCaster = hasSP || hasSPI || hasMP5; + const bool match = hasINT && hasAP && !looksCaster; + + LOG_DEBUG("playerbots", + "[LootPaternDBG] INT+AP match? {} -> item={} \"{}\" (INT={} AP={} casterStats={})", + match ? "YES" : "NO", proto->ItemId, proto->Name1, + hasINT ? 1 : 0, hasAP ? 1 : 0, looksCaster ? 1 : 0); + return match; } @@ -746,12 +808,12 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) const bool hasBlockValue = HasAnyStat(proto, {ITEM_MOD_BLOCK_VALUE}); const bool looksTank = hasDef || hasAvoid || hasBlockValue; - // ----- Modulable Hook for special patterns exemple: (Items with Inter+AP) + // Do not let patterns override jewelry/cloak logic; these are handled separately below. bool primaryByPattern = false; - if (ApplyStatPatternsForPrimary(bot, proto, traits, primaryByPattern)) - { + if (!isJewelry && ApplyStatPatternsForPrimary(bot, proto, traits, primaryByPattern)) + { return primaryByPattern; - } + } // Non-tanks (DPS, casters/heals) never NEED purely tank items if (!isTankLikeSpec && looksTank) @@ -778,22 +840,30 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (isJewelry && looksCaster) { return false; - } + } } else // Caster/Healer { // (1) Casters/healers should not NEED pure melee items (STR/AP/ARP/EXP) without INT/SP if (looksPhysical && !hasSP && !hasINT) - { + { return false; - } + } + // (2) Melee jewelry (AP/ARP/EXP/STR/AGI) without INT/SP -> off-spec if (isJewelry && looksPhysical && !hasSP && !hasINT) - { + { return false; - } + } + + // (3) Healers: treat DPS caster items with Hit but no regen as off-spec (cloth SP/INT/HIT). + if (traits.isHealer && hasHIT && !hasMP5 && !hasSPI) + { + return false; + } + // Paladin Holy (plate INT+SP/MP5), Shaman Elemental/Restoration (mail INT+SP/MP5), - // Druid Balance/Restoration (leather/cloth caster) → OK + // Druid Balance/Restoration (leather/cloth caster) -> OK } // Extra weapon sanity for Hunters/Ferals (avoid wrong stat-sticks): @@ -806,14 +876,24 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) proto->InventoryType == INVTYPE_WEAPONOFFHAND || proto->InventoryType == INVTYPE_2HWEAPON; if (meleeWeapon && traits.isHunter && !hasAGI) - { + { return false; - } + } if (meleeWeapon && (traits.isFeralTk || traits.isFeralDps) && !hasAGI && !hasSTR) - { + { return false; - } + } + + // Enhancement shamans prefer slow weapons for Windfury; avoid very fast melee weapons as main-spec. + if (meleeWeapon && traits.isEnhSham) + { + // Delay is in milliseconds; 2000 ms = 2.0s. Anything faster than this is treated as off-spec. + if (proto->Delay > 0 && proto->Delay < 2000) + { + return false; + } + } } // Class/spec specific adjustments (readable) @@ -850,6 +930,13 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) return false; } + // Rogue: do not treat INT leather body armor as primary (off-spec leveling pieces only). + if (traits.isRogue && proto->Class == ITEM_CLASS_ARMOR && IsBodyArmorInvType(proto->InventoryType) && + proto->SubClass == ITEM_SUBCLASS_ARMOR_LEATHER && hasINT) + { + return false; + } + // Warrior Arms/Fury : no caster items if (traits.isWarrior && !traits.isWarProt && looksCaster) { @@ -1183,19 +1270,23 @@ bool LootRollAction::Execute(Event event) } // Disenchant (Need-Before-Greed): - // If the bot is ENCHANTING and the item is disenchantable, prefer DE to GREED + // If the bot is ENCHANTING and the item is explicitly marked as "DISENCHANT" usage, prefer DE to GREED. if (vote != NEED && sPlayerbotAIConfig->useDEButton && group && (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && - bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto)) + bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto) && + usage == ITEM_USAGE_DISENCHANT) { - LOG_DEBUG("playerbots", "[LootRoolDBG] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", - VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); + LOG_DEBUG("playerbots", + "[LootRollDBG] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1, usage=DISENCHANT)", + VoteTxt(vote), static_cast(group->GetLootMethod()), bot->HasSkill(SKILL_ENCHANTING)); vote = DISENCHANT; } else { - LOG_DEBUG("playerbots", "[LootRollDBG] no DE: vote={} lootMethod={} enchSkill={} deOK={}", VoteTxt(vote), - (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); + LOG_DEBUG("playerbots", + "[LootRollDBG] no DE: vote={} lootMethod={} enchSkill={} deOK={} usage={}", + VoteTxt(vote), static_cast(group->GetLootMethod()), bot->HasSkill(SKILL_ENCHANTING), + IsLikelyDisenchantable(proto), static_cast(usage)); } if (sPlayerbotAIConfig->lootRollLevel == 0) @@ -1381,7 +1472,7 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand vote = PASS; } - // Cross-armor: if BAD_EQUIP (e.g. cloth for paladin), allow NEED only if it's a massive upgrade + /*// Cross-armor: if BAD_EQUIP (e.g. cloth for paladin), allow NEED only if it's a massive upgrade if (vote == GREED && usage == ITEM_USAGE_BAD_EQUIP && proto->Class == ITEM_CLASS_ARMOR) { StatsWeightCalculator calc(bot); @@ -1407,8 +1498,52 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand } if (bestOld > 0.0f && newScore >= bestOld * sPlayerbotAIConfig->crossArmorExtraMargin) vote = NEED; - } + }*/ + + // Cross-armor: if BAD_EQUIP (e.g. cloth for paladin), allow NEED only if + // - it is really lower-tier armor for this bot, and + // - no primary armor user in the group is likely to NEED it, and + // - it is a massive upgrade according to StatsWeightCalculator. + if (vote == GREED && usage == ITEM_USAGE_BAD_EQUIP && proto->Class == ITEM_CLASS_ARMOR && + IsLowerTierArmorForBot(bot, proto)) + { + if (!GroupHasPrimaryArmorUserLikelyToNeed(bot, proto, randomProperty)) + { + StatsWeightCalculator calc(bot); + float newScore = calc.CalculateItem(proto->ItemId); + float bestOld = 0.0f; + + // Find the best currently equipped item of the same InventoryType + for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) + { + Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + if (!oldItem) + continue; + + ItemTemplate const* oldProto = oldItem->GetTemplate(); + if (!oldProto) + continue; + if (oldProto->Class != ITEM_CLASS_ARMOR) + continue; + if (oldProto->InventoryType != proto->InventoryType) + continue; + + float oldScore = + calc.CalculateItem(oldProto->ItemId, oldItem->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID)); + if (oldScore > bestOld) + bestOld = oldScore; + } + if (bestOld > 0.0f && newScore >= bestOld * sPlayerbotAIConfig->crossArmorExtraMargin) + vote = NEED; + } + else + { + LOG_DEBUG("playerbots", + "[LootRollDBG] cross-armor: keeping GREED, primary armor user present for item={} \"{}\"", + proto->ItemId, proto->Name1); + } + } // Final decision (with allow/deny from loot strategy) RollVote finalVote = StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? vote : PASS; @@ -1463,9 +1598,25 @@ bool MasterLootRollAction::Execute(Event event) bot->GetName(), itemId, proto->Name1, proto->Class, proto->Quality, (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), randomPropertyId); + // Compute random property and usage, same pattern as LootRollAction::Execute + int32 randomProperty = EncodeRandomEnchantParam(randomPropertyId, randomSuffix); + + std::string itemUsageParam; + if (randomProperty != 0) + { + itemUsageParam = std::to_string(itemId) + "," + std::to_string(randomProperty); + } + else + { + itemUsageParam = std::to_string(itemId); + } + + ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam); + // 1) Token heuristic: ONLY NEED if the target slot is a likely upgrade RollVote vote = PASS; - if (proto->Class == ITEM_CLASS_MISC && proto->SubClass == ITEM_SUBCLASS_JUNK && proto->Quality == ITEM_QUALITY_EPIC) + if (proto->Class == ITEM_CLASS_MISC && proto->SubClass == ITEM_SUBCLASS_JUNK && + proto->Quality == ITEM_QUALITY_EPIC) { if (CanBotUseToken(proto, bot)) { @@ -1482,23 +1633,26 @@ bool MasterLootRollAction::Execute(Event event) } else { - vote = CalculateRollVote(proto, EncodeRandomEnchantParam(randomPropertyId, randomSuffix)); + vote = CalculateRollVote(proto, randomProperty); } - // 2) Disenchant button in Need-Before-Greed if the usage is "DISENCHANT" + // 2) Disenchant button in Need-Before-Greed if the usage is explicitly "DISENCHANT" if (vote != NEED && sPlayerbotAIConfig->useDEButton && (group->GetLootMethod() == NEED_BEFORE_GREED || group->GetLootMethod() == GROUP_LOOT) && - bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto)) + bot->HasSkill(SKILL_ENCHANTING) && IsLikelyDisenchantable(proto) && + usage == ITEM_USAGE_DISENCHANT) { LOG_DEBUG("playerbots", - "[LootEnchantDBG][ML] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1)", - VoteTxt(vote), (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING)); + "[LootEnchantDBG][ML] DE switch: {} -> DISENCHANT (lootMethod={}, enchSkill={}, deOK=1, usage=DISENCHANT)", + VoteTxt(vote), static_cast(group->GetLootMethod()), bot->HasSkill(SKILL_ENCHANTING)); vote = DISENCHANT; } else { - LOG_DEBUG("playerbots", "[LootEnchantDBG][ML] no DE: vote={} lootMethod={} enchSkill={} deOK={}", VoteTxt(vote), - (int)group->GetLootMethod(), bot->HasSkill(SKILL_ENCHANTING), IsLikelyDisenchantable(proto)); + LOG_DEBUG("playerbots", + "[LootEnchantDBG][ML] no DE: vote={} lootMethod={} enchSkill={} deOK={} usage={}", + VoteTxt(vote), static_cast(group->GetLootMethod()), bot->HasSkill(SKILL_ENCHANTING), + IsLikelyDisenchantable(proto), static_cast(usage)); } RollVote sent = vote; From 33a0ce9f35ccdde5a6b1c3e12e64861954cef497 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Sat, 22 Nov 2025 14:28:41 +0100 Subject: [PATCH 26/32] Lasts adjustments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Centralized “who gets priority” into a generic fallback: if no bot in the group has the item as a mainspec upgrade (EQUIP/REPLACE + IsPrimaryForSpec), then offspec upgrades are allowed to keep NEED instead of being forced to GREED. Healer + Hit items are now handled only via IsPrimaryForSpec (healer treats SP/INT/Hit/no-regen as offspec), and the generic fallback decides whether they can still NEED when no DPS caster bot wants it. Fixed a compile issue by adding a forward declaration for IsPrimaryForSpec before group-level helper functions that call it. --- src/strategy/actions/LootRollAction.cpp | 117 ++++++++++++++++++------ 1 file changed, 87 insertions(+), 30 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 576750d743..ef97d9b609 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -29,6 +29,9 @@ #include "SpellMgr.h" #include "StatsWeightCalculator.h" +// Forward declaration used by group-level helpers +static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto); + // Groups the "class + archetype" info in the same place struct SpecTraits { @@ -222,6 +225,63 @@ static bool GroupHasPrimaryArmorUserLikelyToNeed(Player* self, ItemTemplate cons return false; } +// Returns true if there is at least one bot in the group for whom this item is: +// - an upgrade (ItemUsage = EQUIP or REPLACE), and +// - a primary-spec item according to IsPrimaryForSpec(). +// +// Used to implement a generic fallback: +// if no such "primary" candidate exists, offspec upgrades are allowed to KEEP NEED +// instead of being downgraded to GREED by SmartNeedBySpec. +static bool GroupHasPrimarySpecUpgradeCandidate(Player* self, ItemTemplate const* proto, int32 randomProperty) +{ + if (!self || !proto) + return false; + + Group* group = self->GetGroup(); + if (!group) + return false; + + std::ostringstream out; + if (randomProperty != 0) + out << proto->ItemId << "," << randomProperty; + else + out << proto->ItemId; + + std::string const param = out.str(); + + for (GroupReference* it = group->GetFirstMember(); it; it = it->next()) + { + Player* member = it->GetSource(); + if (!member || member == self || !member->IsInWorld()) + continue; + + PlayerbotAI* memberAI = GET_PLAYERBOT_AI(member); + if (!memberAI) + continue; // ignore real players + + AiObjectContext* ctx = memberAI->GetAiObjectContext(); + if (!ctx) + continue; + + ItemUsage otherUsage = ctx->GetValue("item usage", param)->Get(); + if (otherUsage != ITEM_USAGE_EQUIP && otherUsage != ITEM_USAGE_REPLACE) + continue; // not a real upgrade for that bot + + if (!IsPrimaryForSpec(member, proto)) + continue; // not mainspec for that bot + + LOG_DEBUG("playerbots", + "[LootRollDBG] group primary spec upgrade: {} is primary candidate for item={} \"{}\" (usage={})", + member->GetName(), proto->ItemId, proto->Name1, static_cast(otherUsage)); + return true; + } + + LOG_DEBUG("playerbots", + "[LootRollDBG] group primary spec upgrade: no primary candidate for item={} \"{}\"", + proto->ItemId, proto->Name1); + return false; +} + // Local helper: identifies classic lockboxes the Rogue can pick. // Keep English-only fallback for name checks. static bool IsLockbox(ItemTemplate const* proto) @@ -856,7 +916,13 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) return false; } - // (3) Healers: treat DPS caster items with Hit but no regen as off-spec (cloth SP/INT/HIT). + // (3) Healers: treat pure "DPS caster Hit" pieces as off-spec. + // Profile: SP/INT + Hit and *no* regen stats (no SPI, no MP5). + // + // This only marks the item as *not primary* for healers. + // The actual priority is decided later by SmartNeedBySpec + GroupHasPrimarySpecUpgradeCandidate: + // - if a DPS caster bot has this item as a mainspec upgrade, healers are downgraded to GREED; + // - if nobody in the group has it as mainspec upgrade, healers are allowed to keep NEED. if (traits.isHealer && hasHIT && !hasMP5 && !hasSPI) { return false; @@ -1377,11 +1443,30 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand { case ITEM_USAGE_EQUIP: case ITEM_USAGE_REPLACE: - vote = NEED; + /*vote = NEED; // Downgrade to GREED if the item does not match the main spec if (sPlayerbotAIConfig->smartNeedBySpec && !IsPrimaryForSpec(bot, proto)) vote = GREED; + break;*/ + { + vote = NEED; + // SmartNeedBySpec: only downgrade to GREED if there is at least one + // "true mainspec upgrade" candidate in the group. + if (sPlayerbotAIConfig->smartNeedBySpec && !IsPrimaryForSpec(bot, proto)) + { + if (GroupHasPrimarySpecUpgradeCandidate(bot, proto, randomProperty)) + { + vote = GREED; + } + else + { + LOG_INFO("playerbots", + "[LootRollDBG] secondary-fallback: no primary spec upgrade in group, {} may NEED item={} \"{}\"", + bot->GetName(), proto->ItemId, proto->Name1); + } + } break; + } case ITEM_USAGE_BAD_EQUIP: case ITEM_USAGE_GUILD_TASK: case ITEM_USAGE_SKILL: @@ -1472,34 +1557,6 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand vote = PASS; } - /*// Cross-armor: if BAD_EQUIP (e.g. cloth for paladin), allow NEED only if it's a massive upgrade - if (vote == GREED && usage == ITEM_USAGE_BAD_EQUIP && proto->Class == ITEM_CLASS_ARMOR) - { - StatsWeightCalculator calc(bot); - float newScore = calc.CalculateItem(proto->ItemId); - float bestOld = 0.0f; - // Find the best currently equipped item of the same InventoryType - for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) - { - Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); - if (!oldItem) - continue; - ItemTemplate const* oldProto = oldItem->GetTemplate(); - if (!oldProto) - continue; - if (oldProto->Class != ITEM_CLASS_ARMOR) - continue; - if (oldProto->InventoryType != proto->InventoryType) - continue; - float oldScore = - calc.CalculateItem(oldProto->ItemId, oldItem->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID)); - if (oldScore > bestOld) - bestOld = oldScore; - } - if (bestOld > 0.0f && newScore >= bestOld * sPlayerbotAIConfig->crossArmorExtraMargin) - vote = NEED; - }*/ - // Cross-armor: if BAD_EQUIP (e.g. cloth for paladin), allow NEED only if // - it is really lower-tier armor for this bot, and // - no primary armor user in the group is likely to NEED it, and From 1b5f7224ef8f3d1971ed6229c9179c035b2eaf3a Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Sat, 22 Nov 2025 16:12:51 +0100 Subject: [PATCH 27/32] More precise roll adjustments --- src/strategy/actions/LootRollAction.cpp | 118 ++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 9 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index ef97d9b609..8cc1ad89d7 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -29,8 +29,10 @@ #include "SpellMgr.h" #include "StatsWeightCalculator.h" -// Forward declaration used by group-level helpers +// Forward declarations used by helpers defined later in this file static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto); +static bool HasAnyStat(ItemTemplate const* proto, + std::initializer_list mods); // Groups the "class + archetype" info in the same place struct SpecTraits @@ -230,7 +232,7 @@ static bool GroupHasPrimaryArmorUserLikelyToNeed(Player* self, ItemTemplate cons // - a primary-spec item according to IsPrimaryForSpec(). // // Used to implement a generic fallback: -// if no such "primary" candidate exists, offspec upgrades are allowed to KEEP NEED +// if no such "primary" candidate exists, off-spec upgrades are allowed to keep NEED // instead of being downgraded to GREED by SmartNeedBySpec. static bool GroupHasPrimarySpecUpgradeCandidate(Player* self, ItemTemplate const* proto, int32 randomProperty) { @@ -265,23 +267,76 @@ static bool GroupHasPrimarySpecUpgradeCandidate(Player* self, ItemTemplate const ItemUsage otherUsage = ctx->GetValue("item usage", param)->Get(); if (otherUsage != ITEM_USAGE_EQUIP && otherUsage != ITEM_USAGE_REPLACE) - continue; // not a real upgrade for that bot + continue; if (!IsPrimaryForSpec(member, proto)) - continue; // not mainspec for that bot + continue; - LOG_DEBUG("playerbots", + LOG_INFO("playerbots", "[LootRollDBG] group primary spec upgrade: {} is primary candidate for item={} \"{}\" (usage={})", member->GetName(), proto->ItemId, proto->Name1, static_cast(otherUsage)); return true; } - LOG_DEBUG("playerbots", + LOG_INFO("playerbots", "[LootRollDBG] group primary spec upgrade: no primary candidate for item={} \"{}\"", proto->ItemId, proto->Name1); return false; } +// Returns true if it is still reasonable for this spec to NEED the item as off-spec, +// when no primary-spec upgrade candidate exists in the group. +static bool IsFallbackNeedReasonableForSpec(Player* bot, ItemTemplate const* proto) +{ + if (!bot || !proto) + return false; + + SpecTraits const traits = GetSpecTraits(bot); + + bool const isJewelry = proto->InventoryType == INVTYPE_TRINKET || proto->InventoryType == INVTYPE_FINGER || + proto->InventoryType == INVTYPE_NECK || proto->InventoryType == INVTYPE_CLOAK; + + bool const isBodyArmor = proto->Class == ITEM_CLASS_ARMOR && IsBodyArmorInvType(proto->InventoryType); + + bool const hasINT = HasAnyStat(proto, {ITEM_MOD_INTELLECT}); + bool const hasSPI = HasAnyStat(proto, {ITEM_MOD_SPIRIT}); + bool const hasMP5 = HasAnyStat(proto, {ITEM_MOD_MANA_REGENERATION}); + bool const hasSP = HasAnyStat(proto, {ITEM_MOD_SPELL_POWER}); + bool const hasSTR = HasAnyStat(proto, {ITEM_MOD_STRENGTH}); + bool const hasAGI = HasAnyStat(proto, {ITEM_MOD_AGILITY}); + bool const hasAP = HasAnyStat(proto, {ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER}); + bool const hasARP = HasAnyStat(proto, {ITEM_MOD_ARMOR_PENETRATION_RATING}); + bool const hasEXP = HasAnyStat(proto, {ITEM_MOD_EXPERTISE_RATING}); + + bool const looksCaster = hasSP || hasSPI || hasMP5 || (hasINT && !hasSTR && !hasAGI && !hasAP); + bool const looksPhysical = hasSTR || hasAGI || hasAP || hasARP || hasEXP; + + // Physical specs: never fallback-NEED pure caster body armor or SP weapons/shields. + if (traits.isPhysical) + { + if (isBodyArmor && looksCaster) + return false; + + if ((proto->Class == ITEM_CLASS_WEAPON || + (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && + hasSP) + return false; + } + + // Caster/healer specs: never fallback-NEED pure melee body armor or melee-only jewelry. + if (traits.isCaster || traits.isHealer) + { + if (isBodyArmor && looksPhysical && !hasSP && !hasINT) + return false; + + if (isJewelry && looksPhysical && !hasSP && !hasINT) + return false; + } + + // Default: allow fallback NEED for this spec/item combination. + return true; +} + // Local helper: identifies classic lockboxes the Rogue can pick. // Keep English-only fallback for name checks. static bool IsLockbox(ItemTemplate const* proto) @@ -1451,13 +1506,19 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand { vote = NEED; // SmartNeedBySpec: only downgrade to GREED if there is at least one - // "true mainspec upgrade" candidate in the group. + // "true mainspec upgrade" candidate in the group, or if this spec/item + // combination is too far off to justify NEED as off-spec. if (sPlayerbotAIConfig->smartNeedBySpec && !IsPrimaryForSpec(bot, proto)) { if (GroupHasPrimarySpecUpgradeCandidate(bot, proto, randomProperty)) { vote = GREED; } + else if (!IsFallbackNeedReasonableForSpec(bot, proto)) + { + // No mainspec candidate, but the item is too far off for this spec -> GREED. + vote = GREED; + } else { LOG_INFO("playerbots", @@ -1566,7 +1627,7 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand { if (!GroupHasPrimaryArmorUserLikelyToNeed(bot, proto, randomProperty)) { - StatsWeightCalculator calc(bot); + /* StatsWeightCalculator calc(bot); float newScore = calc.CalculateItem(proto->ItemId); float bestOld = 0.0f; @@ -1592,7 +1653,46 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand } if (bestOld > 0.0f && newScore >= bestOld * sPlayerbotAIConfig->crossArmorExtraMargin) - vote = NEED; + vote = NEED;*/ + // Reuse the same sanity as the generic fallback: + // even in cross-armor mode, do not allow NEED on completely off-spec items + // (e.g. rogues on cloth SP/INT/SPI, casters on pure STR/AP plate, etc.). + if (!IsFallbackNeedReasonableForSpec(bot, proto)) + { + LOG_INFO("playerbots", + "[LootRollDBG] cross-armor: {} too far off-spec for item={} \"{}\", keeping GREED", + bot->GetName(), proto->ItemId, proto->Name1); + } + else + { + StatsWeightCalculator calc(bot); + float newScore = calc.CalculateItem(proto->ItemId); + float bestOld = 0.0f; + + // Find the best currently equipped item of the same InventoryType + for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) + { + Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + if (!oldItem) + continue; + + ItemTemplate const* oldProto = oldItem->GetTemplate(); + if (!oldProto) + continue; + if (oldProto->Class != ITEM_CLASS_ARMOR) + continue; + if (oldProto->InventoryType != proto->InventoryType) + continue; + + float oldScore = calc.CalculateItem( + oldProto->ItemId, oldItem->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID)); + if (oldScore > bestOld) + bestOld = oldScore; + } + + if (bestOld > 0.0f && newScore >= bestOld * sPlayerbotAIConfig->crossArmorExtraMargin) + vote = NEED; + } } else { From 6e0878ed32a9580cc62e666b9182d98d9bf9d24b Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Sat, 22 Nov 2025 16:16:03 +0100 Subject: [PATCH 28/32] Switch to log debug --- src/strategy/actions/LootRollAction.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 8cc1ad89d7..9dcfb66d0d 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -272,13 +272,13 @@ static bool GroupHasPrimarySpecUpgradeCandidate(Player* self, ItemTemplate const if (!IsPrimaryForSpec(member, proto)) continue; - LOG_INFO("playerbots", + LOG_DEBUG("playerbots", "[LootRollDBG] group primary spec upgrade: {} is primary candidate for item={} \"{}\" (usage={})", member->GetName(), proto->ItemId, proto->Name1, static_cast(otherUsage)); return true; } - LOG_INFO("playerbots", + LOG_DEBUG("playerbots", "[LootRollDBG] group primary spec upgrade: no primary candidate for item={} \"{}\"", proto->ItemId, proto->Name1); return false; @@ -1521,7 +1521,7 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand } else { - LOG_INFO("playerbots", + LOG_DEBUG("playerbots", "[LootRollDBG] secondary-fallback: no primary spec upgrade in group, {} may NEED item={} \"{}\"", bot->GetName(), proto->ItemId, proto->Name1); } @@ -1659,7 +1659,7 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand // (e.g. rogues on cloth SP/INT/SPI, casters on pure STR/AP plate, etc.). if (!IsFallbackNeedReasonableForSpec(bot, proto)) { - LOG_INFO("playerbots", + LOG_DEBUG("playerbots", "[LootRollDBG] cross-armor: {} too far off-spec for item={} \"{}\", keeping GREED", bot->GetName(), proto->ItemId, proto->Name1); } From 9a676dd65f66e345601005e4b5300da448b1b187 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Sat, 22 Nov 2025 16:34:22 +0100 Subject: [PATCH 29/32] Remove commented code --- src/strategy/actions/LootRollAction.cpp | 36 ++----------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 9dcfb66d0d..0a700c2500 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -171,7 +171,7 @@ static bool IsLowerTierArmorForBot(Player* bot, ItemTemplate const* proto) return false; uint8 preferred = PreferredArmorSubclassFor(bot); - // ITEM_SUBCLASS_ARMOR_* are ordered Cloth(1) < Leather(2) < Mail(3) < Plate(4) on 3.3.5a + // ITEM_SUBCLASS_ARMOR_* are ordered Cloth(1) < Leather(2) < Mail(3) < Plate(4) on 3.3.5 return proto->SubClass < preferred; } @@ -903,7 +903,7 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) const bool hasSP = HasAnyStat(proto, {ITEM_MOD_SPELL_POWER}); const bool hasSTR = HasAnyStat(proto, {ITEM_MOD_STRENGTH}); const bool hasAGI = HasAnyStat(proto, {ITEM_MOD_AGILITY}); - const bool hasSTA = HasAnyStat(proto, {ITEM_MOD_STAMINA}); + const bool hasSTA = HasAnyStat(proto, {ITEM_MOD_STAMINA}); // Not used now, but i keep it we never know const bool hasAP = HasAnyStat(proto, {ITEM_MOD_ATTACK_POWER, ITEM_MOD_RANGED_ATTACK_POWER}); const bool hasARP = HasAnyStat(proto, {ITEM_MOD_ARMOR_PENETRATION_RATING}); const bool hasEXP = HasAnyStat(proto, {ITEM_MOD_EXPERTISE_RATING}); @@ -1498,11 +1498,6 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand { case ITEM_USAGE_EQUIP: case ITEM_USAGE_REPLACE: - /*vote = NEED; - // Downgrade to GREED if the item does not match the main spec - if (sPlayerbotAIConfig->smartNeedBySpec && !IsPrimaryForSpec(bot, proto)) - vote = GREED; - break;*/ { vote = NEED; // SmartNeedBySpec: only downgrade to GREED if there is at least one @@ -1627,33 +1622,6 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto, int32 rand { if (!GroupHasPrimaryArmorUserLikelyToNeed(bot, proto, randomProperty)) { - /* StatsWeightCalculator calc(bot); - float newScore = calc.CalculateItem(proto->ItemId); - float bestOld = 0.0f; - - // Find the best currently equipped item of the same InventoryType - for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) - { - Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); - if (!oldItem) - continue; - - ItemTemplate const* oldProto = oldItem->GetTemplate(); - if (!oldProto) - continue; - if (oldProto->Class != ITEM_CLASS_ARMOR) - continue; - if (oldProto->InventoryType != proto->InventoryType) - continue; - - float oldScore = - calc.CalculateItem(oldProto->ItemId, oldItem->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID)); - if (oldScore > bestOld) - bestOld = oldScore; - } - - if (bestOld > 0.0f && newScore >= bestOld * sPlayerbotAIConfig->crossArmorExtraMargin) - vote = NEED;*/ // Reuse the same sanity as the generic fallback: // even in cross-armor mode, do not allow NEED on completely off-spec items // (e.g. rogues on cloth SP/INT/SPI, casters on pure STR/AP plate, etc.). From d3c1bbbc806142c65da69a94b459ce18265652aa Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:12:13 +0100 Subject: [PATCH 30/32] Fix codestyle --- src/strategy/actions/LootRollAction.cpp | 115 ++++++++++++------------ 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index 0a700c2500..b909033693 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -393,12 +393,12 @@ static bool GroupHasPreferredIntApUser(Player* self) return false; } Group* g = self->GetGroup(); - + if (!g) { return false; } - + for (GroupReference* it = g->GetFirstMember(); it; it = it->next()) { Player* p = it->GetSource(); @@ -574,7 +574,7 @@ static inline int32 EncodeRandomEnchantParam(uint32 randomPropertyId, uint32 ran { return -static_cast(randomSuffix); } - + return 0; } @@ -587,7 +587,7 @@ static bool BotAlreadyKnowsRecipeSpell(Player* bot, ItemTemplate const* proto) { if (!bot || !proto) return false; - + // Many recipes have a single spell that "teaches" another spell (learned spell in EffectTriggerSpell). for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { @@ -724,29 +724,29 @@ static uint32 GuessRecipeSkill(ItemTemplate const* proto) static bool IsProfessionRecipeUsefulForBot(Player* bot, ItemTemplate const* proto) { if (!bot || !IsRecipeItem(proto)) - { + { return false; - } + } // Primary path: DB usually sets RequiredSkill/RequiredSkillRank on recipe items. uint32 reqSkill = proto->RequiredSkill; uint32 reqRank = proto->RequiredSkillRank; if (!reqSkill) - { + { reqSkill = GuessRecipeSkill(proto); - } + } if (!reqSkill) - { + { return false; // unknown profession, be conservative - } + } // Bot must have the profession (or secondary skill like Cooking/First Aid) if (!bot->HasSkill(reqSkill)) - { + { return false; - } + } // Required rank check (can be disabled by config) — flatten nested if if (!sPlayerbotAIConfig->recipesIgnoreSkillRank && reqRank && bot->GetSkillValue(reqSkill) < reqRank) @@ -756,9 +756,9 @@ static bool IsProfessionRecipeUsefulForBot(Player* bot, ItemTemplate const* prot // Avoid NEED if the taught spell is already known if (BotAlreadyKnowsRecipeSpell(bot, proto)) - { + { return false; - } + } return true; } @@ -768,16 +768,16 @@ static bool IsProfessionRecipeUsefulForBot(Player* bot, ItemTemplate const* prot static bool IsWeaponOrShieldOrRelicAllowedForClass(SpecTraits const& traits, ItemTemplate const* proto) { if (!proto) - { + { return true; // non-weapon items handled elsewhere - } + } // Shields (Armor + Shield): Paladin / Warrior / Shaman if ((proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD) || proto->InventoryType == INVTYPE_SHIELD) - { + { return traits.cls == CLASS_PALADIN || traits.cls == CLASS_WARRIOR || traits.cls == CLASS_SHAMAN; - } + } // Relics (Idol/Totem/Sigil/Libram) if (proto->InventoryType == INVTYPE_RELIC) @@ -887,9 +887,9 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // Hard filter first: do not NEED weapons/shields/relics the class shouldn't use. // If this returns false, the caller will downgrade to GREED (off-spec/unsupported). if (!IsWeaponOrShieldOrRelicAllowedForClass(traits, proto)) - { + { return false; - } + } // Flags class/spec const bool isCasterSpec = traits.isCaster; @@ -932,28 +932,28 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // Non-tanks (DPS, casters/heals) never NEED purely tank items if (!isTankLikeSpec && looksTank) - { + { return false; - } + } // Generic rules by role/family if (isPhysicalSpec) { // (1) All physicals/tanks: never Spell Power/Spirit/MP5 (even if plate/mail) if (looksCaster) - { + { return false; - } + } // (2) Weapon/shield with Spell Power: always off-spec for DK/War/Rogue/Hunter/Ret/Enh/Feral/Prot if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && hasSP) - { + { return false; - } + } // (3) Jewelry/cloaks with caster stats (SP/SPI/MP5/pure INT) -> off-spec if (isJewelry && looksCaster) - { + { return false; } } @@ -1035,14 +1035,14 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (traits.isHunter) { if (looksCaster) - { + { return false; - } + } // Avoid rings with "pure STR" without AGI/AP/DPS ratings if (isJewelry && hasSTR && !hasAGI && !hasAP && !hasDpsRatings) - { + { return false; - } + } } // Rogue (all specs): same strict physical filter (no caster items) @@ -1074,15 +1074,15 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (traits.isEnhSham) { if (looksCaster) - { + { return false; - } + } if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && hasSP) - { + { return false; - } + } } // Druid Feral (tank/DPS): AGI/STA/AVOID/ARP/EXP → OK; no caster items @@ -1095,18 +1095,17 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) if (traits.isRetPal) { if (looksCaster) - { + { return false; - } + } // No Spell Power weapons or shields for Ret if ((proto->Class == ITEM_CLASS_WEAPON || (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)) && hasSP) - { + { return false; - } - + } // Enforce 2H only (no 1H/off-hand/shields/holdables) switch (proto->InventoryType) { @@ -1123,9 +1122,9 @@ static bool IsPrimaryForSpec(Player* bot, ItemTemplate const* proto) // Global VETO: a "physical" spec never considers a caster profile as primary if (sPlayerbotAIConfig->smartNeedBySpec && traits.isPhysical && looksCaster) - { + { return false; - } + } // Let the cross-armor rules (CrossArmorExtraMargin) decide for major off-armor upgrades. return true; @@ -1241,13 +1240,13 @@ static bool RollUniqueCheck(ItemTemplate const* proto, Player* bot); static inline bool IsLikelyDisenchantable(ItemTemplate const* proto) { if (!proto) - { + { return false; - } + } if (proto->Class != ITEM_CLASS_ARMOR && proto->Class != ITEM_CLASS_WEAPON) - { + { return false; - } + } return proto->Quality >= ITEM_QUALITY_UNCOMMON && proto->Quality <= ITEM_QUALITY_EPIC; } @@ -1261,30 +1260,30 @@ static int8 TokenSlotFromName(ItemTemplate const* proto) std::string n = std::string(proto->Name1); std::transform(n.begin(), n.end(), n.begin(), [](unsigned char c) { return static_cast(std::tolower(c)); }); if (n.find("helm") != std::string::npos || n.find("head") != std::string::npos) - { + { return INVTYPE_HEAD; - } + } if (n.find("shoulder") != std::string::npos || n.find("mantle") != std::string::npos || n.find("spauld") != std::string::npos) - { + { return INVTYPE_SHOULDERS; - } + } if (n.find("chest") != std::string::npos || n.find("tunic") != std::string::npos || n.find("robe") != std::string::npos || n.find("breastplate") != std::string::npos || n.find("chestguard") != std::string::npos) - { + { return INVTYPE_CHEST; - } + } if (n.find("glove") != std::string::npos || n.find("handguard") != std::string::npos || n.find("gauntlet") != std::string::npos) - { + { return INVTYPE_HANDS; - } + } if (n.find("leg") != std::string::npos || n.find("pant") != std::string::npos || n.find("trouser") != std::string::npos) - { + { return INVTYPE_LEGS; - } + } return -1; } @@ -1296,9 +1295,9 @@ static bool IsTokenLikelyUpgrade(ItemTemplate const* token, uint8 invTypeSlot, P return false; uint8 eq = EquipmentSlotByInvTypeSafe(invTypeSlot); if (eq >= EQUIPMENT_SLOT_END) - { + { return true; // unknown slot -> do not block Need - } + } Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, eq); if (!oldItem) return true; // empty slot -> guaranteed upgrade From ba29cc9ddcb67180c2391d2a7e4dda23f9abc4b5 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:17:11 +0100 Subject: [PATCH 31/32] Update LootRollAction.cpp --- src/strategy/actions/LootRollAction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategy/actions/LootRollAction.cpp b/src/strategy/actions/LootRollAction.cpp index b909033693..5ce377e903 100644 --- a/src/strategy/actions/LootRollAction.cpp +++ b/src/strategy/actions/LootRollAction.cpp @@ -544,7 +544,7 @@ static const std::array kStatPatterns = {{ static bool ApplyStatPatternsForPrimary(Player* bot, ItemTemplate const* proto, const SpecTraits& traits, bool& outPrimary) { - for (const auto& p : kStatPatterns) + for (auto const& p : kStatPatterns) { if (p.matches(proto)) { From 141e5d5814f8767b375397768618fee7a265199d Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:19:37 +0100 Subject: [PATCH 32/32] codestyle fix --- src/strategy/actions/LootRollAction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategy/actions/LootRollAction.h b/src/strategy/actions/LootRollAction.h index 212677154f..f078354a11 100644 --- a/src/strategy/actions/LootRollAction.h +++ b/src/strategy/actions/LootRollAction.h @@ -41,7 +41,7 @@ class LootRollAction : public QueryItemUsageAction * - Disenchant (NBG): if ItemUsage = DISENCHANT and config enabled, vote DISENCHANT * (the core enforces if the DE button is actually available) */ - + // randomProperty: 0 (none) ; >0 = itemRandomPropId ; <0 = -itemRandomSuffix RollVote CalculateRollVote(ItemTemplate const* proto, int32 randomProperty = 0); };