|
Новичкам Информация для всех новичков, новичкам рекомендуется задавать свои вопросы здесь |
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
31.05.2010, 14:03 | #1 |
Гость
Сообщений: n/a
|
Помощь в написании условия в SD2
Добрый день, прошу вашей помощи, я хочу написать скрипт для рунического оружия (может и кривой, но сам факт в работе )
У меня есть персонаж, owner, его пет - руническое оружие. Как написать проверку типа "Если owner использует спелл *ид*", ну а дальше всё понятно. Примерно такую проверочку бы, но ф-ция CastSpell типа void, поэтому проверку нельзя сделать . Код:
if( owner->CastSpell(owner->getVictim(),H_STRIKE, true)) Код:
void Reset() { Unit * owner = m_creature->GetOwner(); if (!owner || owner->GetTypeId() != TYPEID_PLAYER) return; // Cannot be Selected or Attacked m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetDisplayId(20024); if (owner && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) { m_creature->GetMotionMaster()->Clear(false); m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); } // Add visible weapon if (Item const * item = ((Player *)owner)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, item->GetProto()->ItemId); // Add stats scaling int32 damageDone=owner->CalculateDamage(BASE_ATTACK, true); // might be average damage instead ? int32 meleeSpeed=owner->m_modAttackSpeedPct[BASE_ATTACK]; m_creature->CastCustomSpell(m_creature, 51906, &damageDone, &meleeSpeed, NULL, true); //тут проверка на спелл if( owner->CastSpell(owner->getVictim(),H_STRIKE, true)) if(owner->getVictim()->isAlive()) { m_creature->CastSpell(owner->getVictim(),H_STRIKE, true); }else{ return; } // Visual Glow m_creature->CastSpell(m_creature, 53160, true); } Код:
enum { H_STRIKE = 55262, ICY_TOUCH = 49909, OBLITERATE = 51425, DEATH_COIL = 49895, DEATH_STRIKE = 49924, PLAGUE_STRIKE = 49921 }; |
31.05.2010, 15:14 | #2 |
Гость
Сообщений: n/a
|
CastSpell вообще не предназначен для проверки, что именно сейчас кастуется. Эта функция лишь запускает каст спелла.
Вообще я считаю, что Вы неправильный путь выбрали. Судя по enum Вы собираетесь перечислять все спеллы, которые могут повторяться руническим клинком. А ранги спеллов как обрабатывать будете? Да и уверены, что все-все перечислить сможете? Я уж молчу о том, что точно знать, что именно игрок кастует, можно лишь непосредственно в момент каста. Особенно актуальным это станет, если мангос когда-нибудь к многопоточности придёт. Скрипты больше подходят для мобов, "живущих своей жизнью". Дам подсказку. При призыве меча на игрока аура вешается. Научите её "прокать" от всех возможных атак/спеллов игрока. Это реально сделать, я делал. А далее обрабатывайте, что именно прокнуло. Гораздо легче описать, какие действия меч _НЕ_ должен повторять за игроком. Дерзайте. |
01.06.2010, 03:47 | #3 | |
Гость
Сообщений: n/a
|
Цитата:
|
|
01.06.2010, 06:01 | #4 |
Модератор
|
Unit.cpp - HandleDummyAuraProc
прокаем ауру, висящую на мече, от кастов, каст игрока в данном случае будет procSpell, и ничего не мешает задать маску в spell_proc_event для конкретных спеллов и написать что-то вроде Код:
// Dancing Rune Weapon if (dummySpell->Id == 49028) { // 1 dummy aura for dismiss rune blade if (effIndex!=2) return false; if (!pVictim) return false; if (!procSpell) return false; Unit * caster = triggeredByAura->GetCaster(); if (!caster || caster != this) return false; Unit * rune_weapon = caster->GetPet(); if (!rune_weapon) return false; rune_weapon->CastSpell(caster->getVictim(), procSpell->Id, true); break; } |
01.06.2010, 10:14 | #5 | |
Гость
Сообщений: n/a
|
Цитата:
Может что не так в табличке с проками? Там изначально было в поле "procFlags" <65552>, так и должно быть? <65536> + <16>, тоесть PROC_FLAG_DODGE и PROC_FLAG_CRIT_SPELL, или я что-то не так понял? В "ProcEx" <65536>, тоесть PROC_EX_EX_TRIGGER_ALWAYS - ну тут вроде верно. Как я понимаю SpellFamilyMask из DBC брать, посмотрел, поля нашол , дальше так и заполнить 0-1-1 в таблицу ? И ещё вопрос можно ли сделать через код, есть сильная разница? Я имею введу дюжину подобных условий... Код:
if(procSpell && procSpell->Id == H_STRIKE) { rune_weapon->CastSpell(caster->getVictim(), procSpell->Id, true); } Последний раз редактировалось Prefect; 01.06.2010 в 11:03. |
|
01.06.2010, 10:45 | #6 | |
Ученый
Регистрация: 09.03.2010
Адрес: Кыргызстан
Сообщений: 266
Сказал(а) спасибо: 41
Поблагодарили 115 раз(а) в 34 сообщениях
|
Цитата:
|
|
01.06.2010, 08:22 | #7 |
Ученый
Регистрация: 09.03.2010
Адрес: Кыргызстан
Сообщений: 266
Сказал(а) спасибо: 41
Поблагодарили 115 раз(а) в 34 сообщениях
|
Совет на будущее:
Если ты создаешь условие, то знай, как "Отче наш", одно правило - почти все значимые события обрабатываются с приставкой Get. Пример: Код:
if(m_creature->GetGUID() == id_guid) if(m_creature->GetEntry() == entry ) Код:
if(m_uiPhase == 1) |
01.06.2010, 11:06 | #8 |
Гость
Сообщений: n/a
|
Как не пишу, не хочет работать
Код:
// Dancing Rune Weapon if (dummySpell->Id == 49028) { if (effIndex!=2) return false; if (!pVictim) return false; Unit * caster = triggeredByAura->GetCaster(); if (!caster || caster != this) return false; Unit * rune_weapon = caster->GetPet(); if (!rune_weapon) return false; rune_weapon->CastSpell(caster->getVictim(), procSpell->Id, true); break; } Что тут не так? п.с. SD2 выключил вообще. Появляеться инфернал с мечем, бьет только авто-атакой мою цель. (а где описываеться в коде его появление?). Сделал небольшую "отладку". Текст в cmd : Код:
Loading spell 49028 Loading spell 49028 49028 1st param normal. 49028 2nd param normal. 49028 caster targeted. 49028 3th param normal. 49028 npc targeted. Код:
sLog.outError("Loading spell 49028"); if (effIndex!=2) return false; sLog.outError("49028 1st param normal."); if (!pVictim) return false; sLog.outError("49028 2nd param normal."); Unit * caster = triggeredByAura->GetCaster(); sLog.outError("49028 caster targeted."); if (!caster || caster != this) return false; sLog.outError("49028 3th param normal."); Unit * rune_weapon = caster->GetPet(); sLog.outError("49028 npc targeted."); if (!rune_weapon) return false; sLog.outError("49028 4th param normal."); rune_weapon->CastSpell(caster->getVictim(), procSpell->Id, true); sLog.outError("49028 use a spell. Good."); И странно что спелл 2 раза написало... Со спеллом - то ладно, функция возвращает 0, кто-то может подсказать как создать "пета" ? Нашол, где создаеться пет, попытаюсь сделать его по типу summon'а в mirror_images Последний раз редактировалось Prefect; 01.06.2010 в 14:29. |
01.06.2010, 18:04 | #9 |
Гость
Сообщений: n/a
|
Ну вот кто Вам запрещает отладку сделать, прицепившись к запущенному процессу и расставив по коду точки останова? Удобнее ведь намного, чем по выводу в консоль определять, что работает, а что нет.
|
01.06.2010, 19:31 | #10 |
Модератор
|
2 раза написало спелл - 2 эффекта прокали, а руническое оружие - надо смотреть тип сумона, мб это гвард, тогда там немного по-другому писать надо
|
01.06.2010, 20:19 | #11 |
Гость
Сообщений: n/a
|
Ответить в теме
Ну отладку никогда не делал, нужно будет попробовать
Всем спасибо, всё работает! В коде я малость нафлудил Unit.cpp Код:
enum { ICE_TOUCH_1 = 45477, ICE_TOUCH_2 = 49896, ICE_TOUCH_3 = 49903, ICE_TOUCH_4 = 49904, ICE_TOUCH_5 = 49909, PLAGUE_STRIKE_1 = 45462, PLAGUE_STRIKE_2 = 49917, PLAGUE_STRIKE_3 = 49918, PLAGUE_STRIKE_4 = 49919, PLAGUE_STRIKE_5 = 49920, PLAGUE_STRIKE_6 = 49921, DEATH_STRIKE_1 = 49998, DEATH_STRIKE_2 = 49999, DEATH_STRIKE_3 = 45463, DEATH_STRIKE_4 = 49923, DEATH_STRIKE_5 = 49924, OBLITERATE_1 = 49020, OBLITERATE_2 = 51423, OBLITERATE_3 = 51424, OBLITERATE_4 = 51425, DETH_COIL_1 = 47541, DETH_COIL_2 = 49892, DETH_COIL_3 = 49893, DETH_COIL_4 = 49894, DETH_COIL_5 = 49895, HEART_STRIKE_1 = 55050, HEART_STRIKE_2 = 55258, HEART_STRIKE_3 = 55259, HEART_STRIKE_4 = 55260, HEART_STRIKE_5 = 55261, HEART_STRIKE_6 = 55262 }; Код:
// Dancing Rune Weapon if (dummySpell->Id == 49028) { if (effIndex != EFFECT_INDEX_1) return false; if(!pVictim) return false; Unit * caster = triggeredByAura->GetCaster(); if(!caster) return false; Pet* runeBlade = FindGuardianWithEntry(27893); if(!runeBlade) return false; if(!procSpell) return false; runeBlade->SetAttackTime(BASE_ATTACK,caster->GetAttackTime(BASE_ATTACK)); runeBlade->SetStat(STAT_STRENGTH,caster->GetStat(STAT_STRENGTH)); int32 base = irand((int32)caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE)); damage += int32(float(base) + caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.1f); if (procSpell->Id == ICE_TOUCH_1 || procSpell->Id == ICE_TOUCH_2 || procSpell->Id == ICE_TOUCH_3 || procSpell->Id == ICE_TOUCH_4 || procSpell->Id == ICE_TOUCH_5 || procSpell->Id == PLAGUE_STRIKE_1 || procSpell->Id == PLAGUE_STRIKE_2 || procSpell->Id == PLAGUE_STRIKE_3 || procSpell->Id == PLAGUE_STRIKE_4 || procSpell->Id == PLAGUE_STRIKE_5 || procSpell->Id == PLAGUE_STRIKE_6 || procSpell->Id == DEATH_STRIKE_1 || procSpell->Id == DEATH_STRIKE_2 || procSpell->Id == DEATH_STRIKE_3 || procSpell->Id == DEATH_STRIKE_4 || procSpell->Id == DEATH_STRIKE_5 || procSpell->Id == OBLITERATE_1 || procSpell->Id == OBLITERATE_2 || procSpell->Id == OBLITERATE_3 || procSpell->Id == OBLITERATE_4 || procSpell->Id == DETH_COIL_1 || procSpell->Id == DETH_COIL_2 || procSpell->Id == DETH_COIL_3 || procSpell->Id == DETH_COIL_4 || procSpell->Id == DETH_COIL_5 || procSpell->Id == HEART_STRIKE_1 || procSpell->Id == HEART_STRIKE_2 || procSpell->Id == HEART_STRIKE_3 || procSpell->Id == HEART_STRIKE_4 || procSpell->Id == HEART_STRIKE_5 || procSpell->Id == HEART_STRIKE_6) { int32 procDmg = damage * 0.5; runeBlade->CastCustomSpell(pVictim, procSpell->Id, &procDmg, NULL, NULL, true, NULL, NULL, runeBlade->GetGUID()); SendSpellNonMeleeDamageLog(pVictim, procSpell->Id, procDmg, SPELL_SCHOOL_MASK_NORMAL, 0, 0, false, 0, false); break; } else break; } Код:
struct MANGOS_DLL_DECL runeBladeAI : public ScriptedAI { runeBladeAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} bool inCombat; void Reset() { Unit *owner = m_creature->GetOwner(); if (!owner) return; m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetDisplayId(20242); if (owner && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) { m_creature->GetMotionMaster()->Clear(false); m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); } if (Item const * item = ((Player *)owner)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, item->GetProto()->ItemId); m_creature->CastSpell(m_creature, 53160, true); inCombat = false; } void AttackStart(Unit* pWho) { if (!pWho) return; if (m_creature->Attack(pWho, true)) { m_creature->clearUnitState(UNIT_STAT_FOLLOW); m_creature->GetMotionMaster()->MoveChase(pWho); m_creature->getVictim()->AddThreat(m_creature); inCombat = true; } } void EnterEvadeMode() { if (m_creature->IsInEvadeMode() || !m_creature->isAlive()) return; inCombat = false; Unit *owner = m_creature->GetCharmerOrOwner(); m_creature->AttackStop(); m_creature->CombatStop(true); if (owner && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) { m_creature->GetMotionMaster()->Clear(false); m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); } } void UpdateAI(const uint32 diff) { if (!m_creature->getVictim()) { Unit *owner = m_creature->GetCharmerOrOwner(); if (owner && owner->getVictim()) m_creature->AI()->AttackStart(owner->getVictim()); } if (inCombat && !m_creature->getVictim()) { EnterEvadeMode(); return; } if (!m_creature->getVictim()) return; DoMeleeAttackIfReady(); } }; CreatureAI* GetAI_runeBlade(Creature* pCreature) { return new runeBladeAI(pCreature); } Код:
------------------------------------ newscript = new Script; newscript->Name = "npc_runeblade"; newscript->GetAI = &GetAI_runeBlade; newscript->RegisterSelf(); Делайте замечания - буду рад выслушать, как сделать лучше. **Может кому пригодится Последний раз редактировалось Prefect; 01.06.2010 в 20:21. |
01.06.2010, 20:49 | #12 |
MaNGOS Dev
Регистрация: 09.03.2010
Сообщений: 33
Сказал(а) спасибо: 27
Поблагодарили 26 раз(а) в 11 сообщениях
|
Код:
int32 procDmg = damage * 0.5; |
02.06.2010, 08:38 | #13 | |
Гость
Сообщений: n/a
|
Цитата:
|
|
01.06.2010, 23:54 | #14 |
Модератор
|
Не надо перечислять все спеллы по ИД, достаточно сформировать маску для прока в spell_proc_event - например с помощью спелворка
Отладка - наилучший способ понять работу того или иного участка или посмотреть параметры функций в процессе |
02.06.2010, 00:53 | #15 |
Гость
Сообщений: n/a
|
За такой вот if из "over 9000" элементов я сотрудникам своим руки бы оторвал напрочь В spell_proc_event можно на самом деле задавать маску на базе флагов нужных спеллов. Почитайте wiki на эту тему.
Для поиска флагов кто чем пользуется. Кому-то SpellWork нравится, я в mysql перегнал Spell.dbc и с ним работаю, ибо возможности формирования условий фильтрации шире намного. |
02.06.2010, 08:37 | #16 | |
Гость
Сообщений: n/a
|
Цитата:
Будем грызть гранит spell_proc event Последний раз редактировалось Prefect; 02.06.2010 в 08:46. |
|
|
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Помощь по scriptdev2 | Alexes | Корзина | 7 | 06.10.2010 21:11 |
Условия завершения квестов | deadangel | Баг-репорты | 4 | 30.09.2010 16:47 |
WWW Помощь с Капчей | terrible | Новичкам | 13 | 28.09.2010 12:29 |
Нужна помощь | koly2000 | Корзина | 0 | 12.04.2010 12:49 |
помощь id инстас | frenk | Баг-репорты | 1 | 15.03.2010 09:19 |