diff --git a/sql/sylvania/quetes_jumelles_specialisation.sql b/sql/sylvania/quetes_jumelles_specialisation.sql new file mode 100644 index 0000000..5f7a235 --- /dev/null +++ b/sql/sylvania/quetes_jumelles_specialisation.sql @@ -0,0 +1,48 @@ +-- ===================================================================== +-- « Arrêtez Gul'dan ! » proposée en double — quêtes jumelles de spé +-- +-- Signalé en jeu, à répétition : Maiev propose DEUX fois la même quête. +-- +-- 38723 et 40253 portent le même titre, le même prérequis (38690), le +-- même tri (-407) et sont ouvertes à TOUTES les races +-- (AllowableRaces = 0xFFFFFFFFFFFFFFFF). Rien, absolument rien dans les +-- données ne les départageait : les deux étaient donc offertes ensemble. +-- +-- Ce ne sont PAS des variantes Horde / Alliance, malgré le nom trompeur +-- des constantes du core (QUEST_STOP_GULDAN_H / _A). Le même fichier les +-- nomme correctement plus bas : +-- QUEST_STOP_GULDAN_DMG_SPEC = 38723, -> Dévastation +-- QUEST_STOP_GULDAN_TANK_SPEC = 40253, -> Vengeance +-- Ce sont des jumelles de SPÉCIALISATION. +-- +-- Pourquoi une modification du moteur a été nécessaire +-- Le gestionnaire de conditions n'avait aucun moyen de tester la +-- spécialisation d'un joueur. Le contournement évident — tester un sort +-- caractéristique de chaque spé — ne tient pas debout ici : les sorts de +-- spécialisation ne sont quasiment pas enseignés sur ce serveur (les +-- trois Chasseurs de démons existants ne connaissent que Morsure de +-- démon ; celui de niveau 98 n'a même pas sa Métamorphose). Une +-- condition bâtie là-dessus aurait masqué les DEUX quêtes. +-- CONDITION_SPECIALIZATION (53) a donc été ajoutée au core, et elle lit +-- directement `Player::GetPrimarySpecialization()`. +-- +-- Choix de formulation : la quête Vengeance exige la spé Vengeance ; la +-- quête Dévastation exige de NE PAS être Vengeance, au lieu d'exiger +-- Dévastation. Ainsi il y a TOUJOURS exactement une quête proposée, même +-- pour un personnage dont la spécialisation serait à zéro ou inattendue. +-- Un doublon est agaçant ; zéro quête serait bloquant. +-- +-- Ce n'est pas un cas isolé : le serveur compte 1488 paires de quêtes +-- homonymes partageant prérequis et races. La nouvelle condition servira +-- ailleurs. +-- +-- Rechargeable à chaud : reload conditions (après redémarrage du binaire) +-- ===================================================================== + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=19 AND `SourceEntry` IN (38723,40253); +INSERT INTO `conditions` + (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`, + `ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`, + `NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(19,0,40253,0,0, 53,0,581,0,0, 0,0,0,'', 'Arretez Guldan ! version Vengeance - uniquement si spe Vengeance (581)'), +(19,0,38723,0,0, 53,0,581,0,0, 1,0,0,'', 'Arretez Guldan ! version Devastation - uniquement si spe PAS Vengeance'); diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index db2b8a7..f76736f 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -126,6 +126,7 @@ ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[COND { "Aura stack amount", true, true, false }, { "Object Entry or Guid", true, true, true }, { "Object TypeMask", true, false, false }, + { "Specialization", true, false, false }, }; // Checks if object meets the condition @@ -341,6 +342,12 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) const condMeets = object->isType(ConditionValue1); break; } + case CONDITION_SPECIALIZATION: + { + if (Player* player = object->ToPlayer()) + condMeets = player->GetPrimarySpecialization() == ConditionValue1; + break; + } case CONDITION_RELATION_TO: { if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1]) @@ -656,6 +663,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition() const if (ConditionValue1 & TYPEMASK_AREATRIGGER) mask |= GRID_MAP_TYPE_MASK_AREATRIGGER; break; + case CONDITION_SPECIALIZATION: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; case CONDITION_RELATION_TO: mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; break; @@ -2164,6 +2174,15 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) const } break; } + case CONDITION_SPECIALIZATION: + { + if (!sChrSpecializationStore.LookupEntry(cond->ConditionValue1)) + { + TC_LOG_ERROR("sql.sql", "%s has non existing specialization (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); + return false; + } + break; + } case CONDITION_RELATION_TO: { if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets()) diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index 5b0b4ad..7db4311 100644 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -104,6 +104,7 @@ enum ConditionTypes CONDITION_AURA_STACK_AMOUNT = 50, // spell_id stack 0 true if player (or target) has aura of spell_id with stack amount CONDITION_OBJECT_ENTRY_GUID = 51, // TypeID entry guid true if object is type TypeID and the entry is 0 or matches entry of the object or matches guid of the object CONDITION_TYPE_MASK = 52, // TypeMask 0 0 true if object is type object's TypeMask matches provided TypeMask + CONDITION_SPECIALIZATION = 53, // specId 0 0 true if player's primary specialization is specId (ChrSpecialization) CONDITION_MAX };