Всем привет. Ни для кого не секрет, что тренеровочных манекенов завезли только в WOTLK, и в ранних билдах они не доступны. Однако в игре есть модель, и нет препятствий для того, чтобы их реализовать.
Шаг первый: ИИ
Воспользуемся существующим SD npcs_special , чтобы добавить наш скрипт:
src/game/AI/ScriptDevAI/scripts/world/npcs_special.cpp
struct npc_training_dummyAI : public Scripted_NoMovementAI
{
uint32 combat_timer;
std::map<uint64, pAttackMap*> AttackMap;
npc_training_dummyAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature)
{
Reset();
}
void Reset() override
{
combat_timer = 0;
}
void DamageTaken(Unit* pDealer, uint32& damage, DamageEffectType /*damagetype*/, SpellEntry const* /*spellInfo*/) override
{
combat_timer = 0;
if(m_creature->GetHealthPercent() < 25) {
m_creature->ModifyHealth(m_creature->GetMaxHealth() / 5);
}
uint64 guid = pDealer->GetObjectGuid();
pAttackMap *data = AttackMap[guid];
if(!data)
{
data = new pAttackMap();
AttackMap[guid] = data;
data->guid = guid;
}
data->timer = 6000;
}
void UpdateAI(const uint32 diff) override
{
m_creature->addUnitState(UNIT_STAT_STUNNED);
if(m_creature->GetHealthPercent() < 20) {
m_creature->ModifyHealth(m_creature->GetMaxHealth() / 5);
}
if (!m_creature->SelectHostileTarget() || !m_creature->GetVictim())
return;
combat_timer += diff;
if (combat_timer > 1000)
{
for (std::map<uint64, pAttackMap*>::iterator itr = AttackMap.begin(); itr != AttackMap.end(); ++itr)
{
ObjectGuid oGuid;
oGuid.Set(itr->second->guid);
Player* pPlayer = m_creature->GetMap()->GetPlayer(oGuid);
itr->second->timer -= 1000;
if (itr->second->timer < 1 && oGuid.IsPlayer()) //drop aggro only for players.
{
pPlayer->CombatStop(true);
pPlayer->AttackStop(false);
pPlayer->CombatStopWithPets(true);
pPlayer->ClearInCombat();
AttackMap.erase(itr->second->guid);
delete itr->second;
}
if (AttackMap.empty())
{
m_creature->CombatStop();
}
}
combat_timer = 0;
}
}
};
UnitAI* GetAI_npc_training_dummy(Creature* pCreature)
{
return new npc_training_dummyAI(pCreature);
}
Данная реализация будет держать HP манекена на отметке в 5% для добивающих приёмов и не даст манекену атаковать игрока. Если игрок прекратит атаку, спустя короткое время (6000мс=6сек) манекен сам потеряет к нему интерес и остановит бой
Итак, метод для манекена у нас есть, осталось его зарегистрировать. В npcs_special есть метод void AddSC_npcs_special(), в котором регистрируются все скрипты данного SD. В этот метод нам нужно добавить и наш манекен:
pNewScript = new Script;
pNewScript->Name = "npc_training_dummy";
pNewScript->GetAI = &GetAI_npc_training_dummy;
pNewScript->RegisterSelf();
Кодовая часть завершена, можно смело компилить ядро и отправляться в БД
Шаг второй: База
Итак, в creature_template нам потребуется найти подходящий тип существа, чтоб добавить ему скрипт.
Путём длительного подбора я вычленил субъект под ID: 1921 . Нам потребуется его немного изменить, добавить ему HP, чтоб его не убили с одного удара, и установить ему подходящий уровень:
UPDATE `creature_template`
SET `MinLevel`=70, `Scale`='1.4', `CreatureType`=7, `MaxLevel`=70, `HealthMultiplier`=15,
`RegenerateStats`=2,
`MechanicImmuneMask`=0,
`ScriptName`='npc_training_dummy'
WHERE `Entry`=1921;
Шаг третий: Игра
После проделанной операции поднимаем сервер и идём добавлять NPC:
на этом всё, можно лупить до потери пульса, в т.ч. и толпой))
