Просмотр полной версии : Начинающим разбираться в коде MaNGOS
Помню гдето был патч на комманду ст, при использование ее, когда ты дух, тебя телепортировало на близайщее кладбище, воскрещало и кидало
Собственно патч данный я не смог найти, решил сам написать
Вроде все нормально при юзание комманды ст, он тп к кладбищу и воскрещается, но немогу реализовать добавление ауры (http://www.wowhead.com/?spell=15007) к персу, лазил в коде искал примеры, конкретного ничего не нашел(может и видел, но собственно незнаю как она зовется там)
Кто знает прошу помочь
BombermaG
09.03.2010, 13:20
Для начала стоит ссылочки указывать на wowhead, а не какой-то лан сайт :)
Для начала стоит ссылочки указывать на wowhead, а не какой-то лан сайт :)
чтож бывает, как вы заметили это лан сайт, где мне удобней работать, чем на вовхеде
В скрипте СД2 использовал:
pPlayer->CastSpell(pPlayer,SPELL_ID,false);
, где Player* pPlayer.
Работает, подставь свой спелл вместо SPELL_ID и проверь.
В скрипте СД2 использовал:
pPlayer->CastSpell(pPlayer,SPELL_ID,false);
, где Player* pPlayer.
Работает, подставь свой спелл вместо SPELL_ID и проверь.
Спасибо
chr->CastSpell(chr,15007,false);
Не подскажите для чего в свойствах функции, последнее свойство, тру, фолс?
Если не ошибаюсь, последний параметр отвечает за триггерность спелла, т.е. если спелл триггерный, то ставим true, иначе false.
virusav
Спасибо за оказанное время и помощь, вроде проект обучающий но помогаете один только вы
Предлагаю тему переименовать в "Изучение кода мангоса", помнится такая была на предыдущем форуме и автор был ее Kirix, столько полезной инфы было в ней:sorry:
Еще 1 вопрос
что нужно подключить или прописать чтобы данный код работал
if(int32(getLevel()) < startLevel+9)
{
int32 delta = (int32(getLevel()) - startLevel + 1)*MINUTE;
if(Aura * aur = GetAura(15007, GetGUID()))
}
При попытке скомпилировать выдает ошибку в неизвестных идентификаторах
virusav
Спасибо за оказанное время и помощь, вроде проект обучающий но помогаете один только вы
Предлагаю тему переименовать в "Изучение кода мангоса", помнится такая была на предыдущем форуме и автор был ее Kirix, столько полезной инфы было в ней:sorry:
Еще 1 вопрос
что нужно подключить или прописать чтобы данный код работал
if(int32(getLevel()) < startLevel+9)
{
int32 delta = (int32(getLevel()) - startLevel + 1)*MINUTE;
if(Aura * aur = GetAura(15007, GetGUID()))
}
При попытке скомпилировать выдает ошибку в неизвестных идентификаторах
1) Не все успевают моментально ответить на появляющиеся вопросы. Лично я три своих выходных полностью посвятил настройке форума, было не до заполнения. А сейчас я работаю - времени мало... А вообще моя жена на меня сильно обиделась, когда я потратил на форум все свои выходные и совершенно (стыдно :sorry:) не уделил внимания ей... Так что вполне вероятно меня домашним арестом на время от интернета вообще "отлучат"...
2) Спасибо что напомнили о хорошей теме. Ваше пожелание учтено =)
Еще 1 вопрос
что нужно подключить или прописать чтобы данный код работал
if(int32(getLevel()) < startLevel+9)
{
int32 delta = (int32(getLevel()) - startLevel + 1)*MINUTE;
if(Aura * aur = GetAura(15007, GetGUID()))
}
При попытке скомпилировать выдает ошибку в неизвестных идентификаторах
ищи где описаны getLevel() GetAura() и чей GetGUID() тебе нужен
потом прописывай эти хеадеры(*.h файлы) в своём .cpp файле
А что, функции воскрешения отсутствует или она отделена от наложения маски воскрешения?
Сейчас на работе - под рукой нет исходников =)
А что, функции воскрешения отсутствует или она отделена от наложения маски воскрешения?
отделена,
воскрешение прописано так chr->ResurrectPlayer(0.0f, false);
ищи где описаны getLevel() GetAura() и чей GetGUID() тебе нужен
потом прописывай эти хеадеры(*.h файлы) в своём .cpp файле
Прописывал эти самые *.h файлы в инклуде, но ошибка таже, неизсветный идентификатор
getLevel, GetGUID, предполагаю они конкретно не определены в *.h файлах, а определяются при юзание опредленно какихто моментов
если муть несу, то не пинайте пожалуйста, я пытаюсь понять неизвестное мне
if(Aura * aur = GetAura(15007, EFFECT_INDEX_0))
GetGUID() тут ни к чему.
использование функций GetAura() и getLevel() напрямую можно только в Player.cpp, Unit.cpp. Это аналогично this->getLevel(), this->GetAura(). В остальных случаях требуется игрок(или юнит), с которого мы получаем левел или ауру
Т.е
plr->getLevel()
plr->GetAura(..)
PS : и как могут быть не определены эти ф-ци в .h файлах, если вы используете файлы исходников, а не свои добавленные
использование функций GetAura() и getLevel() напрямую можно только в Player.cpp, Unit.cpp. Это аналогично this->getLevel(), this->GetAura(). В остальных случаях требуется игрок(или юнит), с которого мы получаем левел или ауру
Т.е
plr->getLevel()
plr->GetAura(..)
PS : и как могут быть не определены эти ф-ци в .h файлах, если вы используете файлы исходников, а не свои добавленные
Спасибо на многие вопросы сразу получил вопрос
if(Aura * aur = GetAura(15007, EFFECT_INDEX_0))
GetGUID() тут ни к чему.
собственно EFFECT_INDEX_0 я вообще в коде не нашел существование ее
Вот реализовал что хотел, в игре вроде все отлично работает, ошибок в коде нет?
// if player is dead and stuck, send ghost to graveyard
chr->RepopAtGraveyard();
chr->ResurrectPlayer(0.0f, false);
int32 startLevel = sWorld.getConfig(CONFIG_DEATH_SICKNESS_LEVEL);
if(int32(chr->getLevel()) >= startLevel)
{
// set resurrection sickness
chr->CastSpell(chr,15007,false);
// not full duration
if(int32(chr->getLevel()) < startLevel+9)
{
int32 delta = (int32(chr->getLevel()) - startLevel + 1)*MINUTE;
if(Aura * aur = chr->GetAura(15007, chr->GetGUID()))
{
aur->SetDuration(delta*IN_MILISECONDS);
}
}
}
return true;
}
// cast spell Stuck
chr->RepopAtGraveyard();
return true;
и еще пару вопросов
1.unit64,unit32,unit8 и тд, что значит это? и какая разница между ими?
2.Можно ли гдето в коде посмотреть описание функций? к примеру
CastSpell(Обект на который будет задействовано,ИД спелла,Тригерность);
// if player is dead and stuck, send ghost to graveyard
chr->RepopAtGraveyard();
chr->ResurrectPlayer(0.0f, false);
int32 startLevel = sWorld.getConfig(CONFIG_DEATH_SICKNESS_LEVEL);
if(int32(chr->getLevel()) >= startLevel)
{
// set resurrection sickness
chr->CastSpell(chr,15007,false);
// not full duration
if(int32(chr->getLevel()) < startLevel+9)
{
int32 delta = (int32(chr->getLevel()) - startLevel + 1)*MINUTE;
if(Aura * aur = chr->GetAura(15007, chr->GetGUID()))
{
aur->SetDuration(delta*IN_MILISECONDS);
aur->SetAuraMaxDuration(delta * IN_MILISECONDS);
aur->RefreshAura();
}
}
}
return true;
}
// cast spell Stuck
chr->RepopAtGraveyard();
return true;
1. в GetAura второй параметр нужен индекс эффекта, сейчас не знаю как, а раньше всегда было 0, щас мб EFF_INDEX_0, т.к enum, вобщем смотреть по коду
2. ЧТоб установить свою длительность ауры, надо установить макс. длительность а потом ее зарефрешить
PS - каст маски 15007 лучше делать true, т.к true- означает триггерный спелл, кастуется инстантом, не требуя ни энергии(маны, ярости и т.д), ни реагентов, игонря любые эффекты LOS
chr->CastSpell(chr,15007,true);
PS2 - Visual Studio там есть такая вещь как "Go to Definition", "Go to Declaration" - в контекст меню правым целчком мыши на ф-ции в коде, первое к самой функции, второе - к ее обьявлению,
uint8, uint16, uint32, uint64 - unsigned int, беззнаковый целочисленный тип, цифра - битовость
беззнаковый - биты могут быть либо 0, либо положительными, за счет отрицательных значений мы вдвое расширяем диапазон, uint32 - 0 to 65536
Это обьясняет и любимый всеми баг с уходом спд в минус и появлятся 65536 при значении < 0
Подскажите еще 2 функции
1. На проверку у персонажа итема
пробовал так GetItemByEntry(entry);
либо нето либо не догнал как прописать
2. На удаление Итема у персонажа
также пробовал RemoveItem
но не догоняю почему при комплиляции ему ненравится она:resent:
По первому вопросу нашел ответ на форуме
Подскажите еще 2 функции
1. На проверку у персонажа итема
пробовал так GetItemByEntry(entry);
либо нето либо не догнал как прописать
Player->HasItemCount()
2. 2. На удаление Итема у персонажа
также пробовал RemoveItem
void Player::RemoveItem( uint8 bag, uint8 slot, bool update )
А она разве не для замены? А то есть если true - то замена, false - не замена??
void Player::RemoveItem( uint8 bag, uint8 slot, bool update )
А она разве не для замены? А то есть если true - то замена, false - не замена??
Нет, не для замены:
if( IsInWorld() && update )
pItem->SendCreateUpdateToPlayer( this );
Обновлять ли состояние игрока для самомго игрока или нет. Полагаю, если не обновлять, то итем будет видим для игрока, но будет отсутствовать для сервера.
собственно EFFECT_INDEX_0 я вообще в коде не нашел существование ее
Список индексов для спеллов лежит в DBCEnums.h
enum SpellEffectIndex
{
EFFECT_INDEX_0 = 0,
EFFECT_INDEX_1 = 1,
EFFECT_INDEX_2 = 2
};
1.unit64,unit32,unit8 и тд, что значит это? и какая разница между ими?
Описание каждого из типов можно посмотреть в ACE_Wrapper/ace/Basic_Types.h
2.Можно ли гдето в коде посмотреть описание функций? к примеру
CastSpell(Обект на который будет задействовано,ИД спелла,Тригерность);
Ну это можно сделать либо в докси, но те что я видел были староватыми, однако инфы там много.
Но самый эффективный вариант (имхо) - просмотр кода.
CastSpell - перегруженный метод, имеющий 4 разных перегрузки.
Используемая нами:
void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem = NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0);
========================
А вообще для лучшего понимания кода, советую пройтись по иерархии классов сущностей. Начиная с Object и вниз. А если вы пользуетесь ВС, то советую сделать следующее:
правой кнопкой мыши по проекту game, в выпадающем меню выбираем "Перейти к схеме классов", ВС немного потупит, но в конце концов успешно создаст схему.
Простите, а что такое тригерность?
Слово слышу очень давно, но до сих пор не разобрался с этим понятием. :(
С английского языка, естественно (если глагол), переводится как вызывать.
Поясните, пожалуйста, добрые человеки :(
Спасибо, Anti! Выручил :)
Простите, а что такое тригерность?
Слово слышу очень давно, но до сих пор не разобрался с этим понятием. :(
С английского языка, естественно (если глагол), переводится как вызывать.
Поясните, пожалуйста, добрые человеки :(
Спел вызывается другим спелом, ну и судя по всему обрабатывается каким-то специфическим способом.
При осмотре кода Scriptdev увидел такую функцию void ScriptsFree(), void ScriptsFree()
{
// Free Spell Summary
delete []SpellSummary;
// Free resources before library unload
for(int i=0; i<MAX_SCRIPTS; ++i)
delete m_scripts[i];
num_sc_scripts = 0;
} Меня интересует вот эта строка delete []SpellSummary;Правильна ли она?
При осмотре кода Scriptdev увидел такую функцию void ScriptsFree(), void ScriptsFree()
{
// Free Spell Summary
delete []SpellSummary;
// Free resources before library unload
for(int i=0; i<MAX_SCRIPTS; ++i)
delete m_scripts[i];
num_sc_scripts = 0;
} Меня интересует вот эта строка delete []SpellSummary;Правильна ли она?
http://www.google.ru/search?hl=ru&source=hp&q=%D0%A1%2B%2B+%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%B D%D0%B8%D0%B5+%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8 %D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B3%D0%BE+%D0%BC% D0%B0%D1%81%D1%81%D0%B8%D0%B2%D0%B0&lr=&aq=f&aqi=&aql=&oq=&gs_rfai=
Обычное удаление динамического массива.
Насколько я понимаю по коду, триггерные спеллы не требуют реагентов и энергии, кастятся без учета ЛОС, и видимо инстант
Подскажите как правильно удалить итем
не могу разобраться с RemoveItem
RemoveItem(мешок, слот,Обновлять ли состояние игрока для самомго игрока или нет)
Возникает еще один вопрос
Как определить в каком мешке, слоту лежит итем?
Я код мангоса плохо знаю, но можно так, через цикл, сделать проверку на определенный итим.
Возникает еще один вопрос
Как определить в каком мешке, слоту лежит итем?
Посмотрите Player::HasItemCount ну и пишите 2 функции.
Chestarfild
30.03.2010, 14:32
Есть ли на данный момент у ГО поддержка функции Update(), как у мобов?
Есть ли на данный момент у ГО поддержка функции Update(), как у мобов?По коду видно, что да.
void GameObject::Update(uint32 /*p_time*/)
Обрабатывает состояния объектов.
Описания некоторых функций из фаила Item.cpp
void AddItemsSetItem(Player*player,Item *item) - Добавление набора предметов игроку. В объявление все понятно.
void RemoveItemsSetItem(Player*player,ItemPrototype const *proto) - Удаления набора предметов.
bool ItemCanGoIntoBag(ItemPrototype const *pProto, ItemPrototype const *pBagProto) - Проверка предмета в сумке игрока.(Возвращает лож)
bool Item::Create( uint32 guidlow, uint32 itemid, Player const* owner) - Создание предмета(????), возвращает истину
void Item::UpdateDuration(Player* owner, uint32 diff - ????
void Item::SaveToDB() - сохранить в базе данных
bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result) - загрузить предмет из БД, (индификатор, владелец, результат запроса), возвращает истину
void Item::DeleteFromDB() - удалить предмет из Бд
void Item::DeleteFromInventoryDB() - удалить из списка Бд(????)
void Item::SetItemRandomProperties(int32 randomPropId) - установить предмету случайные свойства
bool Item::UpdateItemSuffixFactor() - (???)
void Item::SetState(ItemUpdateState state, Player *forplayer) - определение состояния, void Item::SetState(состояние, для какого игрока)
void Item::AddToUpdateQueueOf(Player *player) - Добавить из очереди(????), void Item::AddToUpdateQueueOf(игрок)
void Item::RemoveFromUpdateQueueOf(Player *player) Удалить из очереди(???), объявляется так же как предыдущая
bool Item::IsEquipped() const - (???)
bool Item::CanBeTraded(bool mail) - поверка, продается ли предмет, возвращает истину
bool Item::IsBoundByEnchant() - проверка, на инчант, возвращает лож
bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) - подходить ли для определенного заклинания, возвращает истину
bool Item::IsTargetValidForItemUse(Unit* pUnitTarget) - (???)
void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges) - установка инчанта, void Item::SetEnchantment(слот чар, id, продолжительность, расходы)
void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration) - установка временного инчанта.
void Item::SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges) - (???)
void Item::ClearEnchantment(EnchantmentSlot slot) - удаления инчанта
bool Item::GemsFitSockets() const - (???)
bool Item::IsLimitedToAnotherMapOrZone( uint32 cur_mapId, uint32 cur_zoneId) const - ограничения использование предмета в другой зоне(????)
void Item::SendTimeUpdate(Player* owner) - (????)
bool Item::IsBindedNotWith( Player const* player ) const - (???)
void Item::AddToClientUpdateList() - добавить предмет в список обновления клиента
void Item::RemoveFromClientUpdateList() - удалить предмет из списка обновления клиента
void Item::BuildUpdateData(UpdateDataMapType& update_players) - ???
bool ItemRequiredTarget::IsFitToRequirements( Unit* pUnitTarget ) const - ???
bool Item::HasMaxCharges() const - ???
void Item::RestoreCharges() - ???
Chestarfild
03.04.2010, 10:44
Интересует, как правильно деспавнить ГО в инсте. Например Скорбь в залах, когда её Артас забирает.
Интересует, как правильно деспавнить ГО в инсте. Например Скорбь в залах, когда её Артас забирает.
Могу посоветовать посмотреть как это делает rsa в своём скрипте Колизея.
http://github.com/rsa/scriptdev2/blob/master/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp
Смотрите скрипт Артоса, он там ломает пол.
Chestarfild
18.04.2010, 10:17
По коду видно, что да.
Вот только как это привязать к скрипту? Смотрел в Script, там GetAI() только для креатур, а для го это сделать какнить можно?
Вот только как это привязать к скрипту? Смотрел в Script, там GetAI() только для креатур, а для го это сделать какнить можно?
А что реализовываем? Со скриптами ГО не сильно знакомился, но могу достаточно быстро разобраться.
Chestarfild
18.04.2010, 13:13
Нужно реализовать таймер в го, чтобы например он каждые 20 секунд выполнял на себя определенный метод. С тригерными нпц не особо охото мучацо, да и не близзлайк это наверное.
ЗЫ: Какими махинациями можно сделать неюзабельный го юзабельным?)
Нужно реализовать таймер в го, чтобы например он каждые 20 секунд выполнял на себя определенный метод. С тригерными нпц не особо охото мучацо, да и не близзлайк это наверное.
ЗЫ: Какими махинациями можно сделать неюзабельный го юзабельным?)
Похоже, что не получиться такое реализовать без переписывания большой части кода, да и ан сколько я знаю Го у нас сейчас не кастуют в принципе. Так что лучше "не лезть вперёд батьки", а делать через триггеры.
стамим ГО флаг = 4 - после удаляем (например скриптом).
Chestarfild
18.04.2010, 14:40
стамим ГО флаг = 4 - после удаляем (например скриптом).
Я немного не так сказал) Вобщем например, есть сундук в Очищении Стратхольма, он там стоит по дефлоту неюзабельный. Каким флагом/методом/функцией можно его через код сделать юзабельным?
Я тоже имел его ввиду :)
Вроде можно делать через базу, но я предпочитаю через С++ скрипт делать.
В скрипте инста будет примерно такая штука:
setData(uint32 case,uint32 data)
{
...
case MALGANIS:
if (data == DONE)
if (GameObject *pGo = instance->GetGameObject(MalganisChest))
pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND) ;
...
}
А в го_темплейте для этого го ставим значение flags = 4.
Скриптуем моба тоже через С++. И как он умирает и отсылает данные в скрипт инста, тут то мы и делаем ГО юзабильным.
Пара спеллов:
http://ru.wowhead.com/spell=38736
http://ru.wowhead.com/spell=57853
Проблема в следующем - при юзе итема, на котором они висят, они кастуются, но триггера спелла, висящего на них, не происходит. Не могу понять куда копать... Есть идеи?
Пара спеллов:
http://ru.wowhead.com/spell=38736
http://ru.wowhead.com/spell=57853
Проблема в следующем - при юзе итема, на котором они висят, они кастуются, но триггера спелла, висящего на них, не происходит. Не могу понять куда копать... Есть идеи?
Ясно... Спелл имеет TARGET_SCRIPT. Значит эффект вешается на цель, указанную в базе и уже эта цель триггерит спелл. А нам надо триггерить спелл от кастера...
SpellAuras.cpp
Есть такая функция, которая вызывается при каждом тике триггерных аур
void Aura::TriggerSpell()
Ищем место где в коде будет
else
{
// Spell exist but require custom code
switch(auraId)
{
И здесь на нужное место вставляем тот же самый каст спелла, но уже на кастера, что-то вроде
case 38736:
{
if (Unit * caster = GetCaster())
caster->CastSpell(caster, trigger_spell_id, true, NULL, this, casterGUID);
return;
}
Спасибо, как раз не мог найти этот обработчик =)
Но судя по данным ДБЦ спелла, создаётся впечатление, что надо в таблицу spell_script_target есть смысл добавить новый тип цели - self... Или же подобные спеллы просто добавлять в исключение в код - примут ли?
Это ответвление и было специально создано для таких случаев, перевод коммента
'триггер спелла есть, но требуется другой код'
В триггерном эффекте стоит квест-комплит с таргет-селф, я думаю, что этот эффект точно должен применятся на кастера-игрока
И если просмотреть все эти исключения, некоторые один в один повторяют основную обработку каста в самом конце :) как бы они уже не нужны, но стоят
Это ответвление и было специально создано для таких случаев, перевод коммента
'триггер спелла есть, но требуется другой код'
В триггерном эффекте стоит квест-комплит с таргет-селф, я думаю, что этот эффект точно должен применятся на кастера-игрока
*И если просмотреть все эти исключения, некоторые один в один повторяют основную обработку каста в самом конце :) как бы они уже не нужны, но стоят
Я сообщение твоё получил на работе - коммент не читал вообще. Спасибо за комментарий.
Вот только последнего (под звёздочкой) я не очень понял смысл... Таких спеллов несколько минимум, которые используют TARGET_SCRIPT, но по логике триггерного спелла должны кастоваться от кастера. Есть ли смысл добавлять тип цели спелла - кастер?
Пытаюсь сделать, чтобы моб в момент смерти кастовал АоЕ спелл, например http://ru.wowhead.com/spell=62598 (с помощью EAI или SD2, не важно). Анимация есть, но спелл промахивается в 100% случаев (кастуется как triggered). В чем дело? (:
Ревизия 9808.
Пытаюсь сделать, чтобы моб в момент смерти кастовал АоЕ спелл, например http://ru.wowhead.com/spell=62598 (с помощью EAI или SD2, не важно). Анимация есть, но спелл промахивается в 100% случаев (кастуется как triggered). В чем дело? (:
Ревизия 9808.А как вы делаете? Через JustDied?
А как вы делаете? Через JustDied?
Да, в EventAI это EVENT_T_DEATH (6). Можете сами убедиться:
UPDATE creature_template SET AIName = 'EventAI', ScriptName = '' WHERE entry IN (32918);
DELETE FROM creature_ai_scripts WHERE creature_id IN (32918);
INSERT INTO creature_ai_scripts VALUES
('3291801','32918','0','0','100','7','5000','10000 ','10000','12000','11','62608','1','0','0','0','0' ,'0','0','0','0','0','Detonating Lasher - Cast Flame Lash'),
('3291802','32918','6','0','100','2','0', '0', '0', '0', '11','62598','0','3','0','0','0','0','0','0','0',' 0','Detonating Lasher (Normal) - Cast Detonate on Death'),
('3291803','32918','6','0','100','4','0', '0', '0', '0', '11','62937','0','3','0','0','0','0','0','0','0',' 0','Detonating Lasher (Heroic) - Cast Detonate on Death');
Ох уж это EventAI... :)
Попробуйте поставить мобу 1 хп INVINCIBILITY_LEVEL (кажется так), и на 1 хп кастануть этот спелл и умереть.
Сделал новый тип события EVENT_T_JUST_BEFORE_DEATH, который обрабатывается в DamageTaken при получении последнего удара.
Подскажите где проверяется разница рейтов арены. Дапустим у одной тимы 300 а у другой 800.Они не могут участвовать в месте, потому что разница большая.
В конфиге есть такой параметр, по дефолту вроде 150, думаю с него и надо начинать поиск.
pavelzubkov
18.08.2010, 15:53
Помогите разобраться в коде. Mangos 0.12 кум 6928
Я тут посмотрел написал комментарии по правьте если ошибся. Я может и понимаю код, но что, для чего и зачем мне не понятно. Опишите пожалуйста функции которые в примере. Как я понимаю эта процедура почти стартовая при исполнение кода спеллов(еще старше та которая ее вызывает=))
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
CHECK_PACKET_SIZE(recvPacket,4+1+2);
uint32 spellId;//Объявление двух переменных. Со SpellId понятно
uint8 cast_count;//Что храниться здесь??? И для ВНЕЗАПНОГО УДАРА и для ЛЕДЯННОЙ СТРЕЛЫ - 0.
recvPacket >> spellId;
recvPacket >> cast_count;
sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i",
spellId, cast_count, recvPacket.size()); //Логи
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
/*
В SpellEntry содержется описание ячеек из spell.dbc
клик по sSpellStore >>>> GO TO DEFINITION приводит к DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt); судя по всему, описание какого-то DBC????
клик по LookupEntry >>>> GO TO DEFINITION приводит к T const* LookupEntry(uint32 id) const { return (id>=nCount)?NULL:indexTable[id]; }
не могу понять конструкцию, вроде тут условие и возвращение какого-то id???
судя по *SpellInfo...ммм, название говорит само за себя.
*/
if(!spellInfo)//проверка на успешное создание spellInfo
{
sLog.outError("WORLD: unknown spell id %u", spellId);
return;
}
// not have spell or spell passive and not casted by client(с английским проблемы) что-то вроде: не имеется спелл или спел пассивный и нет каста от клиента. вроде так.
if ( !_player->HasSpell (spellId) || IsPassiveSpell(spellId) )//Проверка на читерство???
{
//cheater? kick? ban?
return;
}
// client provided targets
SpellCastTargets targets;//Создание таргета
if(!targets.read(&recvPacket,_player))//Проверка на существование таргета?
return;
// auto-selection buff level base at target level (in spellInfo) Это мне не дано перевсти: авто-выбор полезного эфекта базового уровня....бррр......
if(targets.getUnitTarget())
{
SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(spellInfo,ta rgets.getUnitTarget()->getLevel());
/*
GO TO DEFINITION(SelectAuraRankForPlayerLevel) - SpellEntry const* SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const;// --- это прототип функции??
//А где тело функции описывается...хм...spellmrg.cpp
//go to definition привело меня в spellmrg.h, понятно.
SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const //посмотрим чё тут=)
{
// ignore passive spells игнорирование пассивных спеллов
if(IsPassiveSpell(spellInfo->Id))
return spellInfo; //Возвращаем изначальное спеллинфо
bool needRankSelection = false;//объявляем буль
for(int i=0;i<3;i++)//такс цикл
{
if( IsPositiveEffect(spellInfo->Id, i) && ( spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY ) )
{//Если в spell.dbc хоть одна из ячеек effect равна SPELL_EFFECT_APPLY_AURA ||(или) SPELL_EFFECT_APPLY_AREA_AURA_PARTY
//а вот IsPositiveEffect(spellInfo->Id, i) как Я ПОНЯЛ там внутри идет проверка из множества свитч
кэйсов и другой бурды
//на полезный или вредный эффект спелла(всмысле эффект у спела положительный(хилит, бафает)
или отрицательный(урон...))
needRankSelection = true; //еслив хоть раз условие верно буль будет истин
break;//и выходим из цикла
}
}
// not required
if(!needRankSelection)//т.к буль НЕ истин
return spellInfo;//Возвращаем изначальное спеллинфо
for(uint32 nextSpellId = spellInfo->Id; nextSpellId != 0; nextSpellId = GetPrevSpellInChain(nextSpellId))
{
SpellEntry const *nextSpellInfo = sSpellStore.LookupEntry(nextSpellId);//опять шесть сот двадцать пять
if(!nextSpellInfo)//а есть ли оно?
break;//нет
// if found appropriate level
if(playerLevel + 10 >= nextSpellInfo->spellLevel)//больши или равен левел игрока уровня спелла??
return nextSpellInfo; //возвращаем nextSpellInfo
// one rank less then
}
// not found
return NULL;//ничего
}//Вообщем, я не понял что эта функция делает=)моски надо купить
*/
// if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message
if(actualSpellInfo)//если не нулл
spellInfo = actualSpellInfo;
}
Spell *spell = new Spell(_player, spellInfo, false);//конструктор,хм _player, spellInfo, false. false - это тригерность???
spell->m_cast_count = cast_count; // set count of casts пожалуйста скажите для чего cast_count
spell->prepare(&targets);//Это следующее что я должен смотреть если хочу идти по следам спелла???
}//фуу вот и все
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
CHECK_PACKET_SIZE(recvPacket,4+1+2);
uint32 spellId; // ID спелла
uint8 cast_count; // количество кастов, увеличивается с каждым новым кастом для конкретного спелла
recvPacket >> spellId;
recvPacket >> cast_count;
sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i",
spellId, cast_count, recvPacket.size()); //Логи
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
/* Обьект SpellEntry - получение информации по спеллу из DBC */
/* т.е мы можем обращатся к полям структуры, типа spellInfo->ID, spellInfo->SpellIconID, см. DBCStructure.h, struct SpellEntry */
if(!spellInfo)//проверка на успешное создание spellInfo
{
sLog.outError("WORLD: unknown spell id %u", spellId);
return;
}
// not have spell or spell passive and not casted by client (нет данного спелла у игрока или спелл пассивный - а значит НИКАК не может быть скастован клиентом => читер
if ( !_player->HasSpell (spellId) || IsPassiveSpell(spellId) )//Проверка на читерство???
{
//cheater? kick? ban?
return;
}
// client provided targets
SpellCastTargets targets; //Создание таргета
if(!targets.read(&recvPacket,_player)) // Чтение целей из пакета и занесение их в таргет обработку
return;
// auto-selection buff level base at target level (in spellInfo) (выбор уровня спелла согласно левелу чара)
if(targets.getUnitTarget())
{
SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(spellInfo,ta rgets.getUnitTarget()->getLevel());
/*
GO TO DEFINITION(SelectAuraRankForPlayerLevel) - SpellEntry const* SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const; --- это прототип функции?? А где тело функции описывается...хм...spellmrg.cpp go to definition привело меня в spellmrg.h, понятно.
SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const //посмотрим чё тут=)
{
// ignore passive spells игнорирование пассивных спеллов
if(IsPassiveSpell(spellInfo->Id))
return spellInfo; //Возвращаем изначальное спеллинфо
bool needRankSelection = false;//объявляем буль
for(int i=0;i<3;i++)//такс цикл
{
if( IsPositiveEffect(spellInfo->Id, i) && ( spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY ) )
{//Если в spell.dbc хоть одна из ячеек effect равна SPELL_EFFECT_APPLY_AURA ||(или) SPELL_EFFECT_APPLY_AREA_AURA_PARTY
//а вот IsPositiveEffect(spellInfo->Id, i) как Я ПОНЯЛ там внутри идет проверка из множества свитч кэйсов и другой бурды
//на полезный или вредный эффект спелла(всмысле эффект у спела положительный(хилит, бафает) или отрицательный(урон...))
needRankSelection = true; //еслив хоть раз условие верно буль будет истин
break;//и выходим из цикла
}
}
// not required
if(!needRankSelection)//т.к буль НЕ истин
return spellInfo;//Возвращаем изначальное спеллинфо
for(uint32 nextSpellId = spellInfo->Id; nextSpellId != 0; nextSpellId = GetPrevSpellInChain(nextSpellId))
{
SpellEntry const *nextSpellInfo = sSpellStore.LookupEntry(nextSpellId);//опять шесть сот двадцать пять
if(!nextSpellInfo)//а есть ли оно?
break;//нет
// if found appropriate level
if(playerLevel + 10 >= nextSpellInfo->spellLevel)//больши или равен левел игрока уровня спелла??
return nextSpellInfo; //возвращаем nextSpellInfo
// one rank less then
}
// not found
return NULL;//ничего
}//Вообщем я ни понял что эта функция делает=)моски надо купить
*/
// if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message
if(actualSpellInfo)//если не нулл
spellInfo = actualSpellInfo;
}
Spell *spell = new Spell(_player, spellInfo, false);
// конструктор - создаем обьект Spell
// Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered)
spell->m_cast_count = cast_count; // устаналиваем количество кастов в глобальную переменнную для дальнейших расчетов
spell->prepare(&targets);// Переход в фазу подготовки спелла
}//фуу вот и все
Это же не с лича пакет, я так понимаю, структура не совпадает, это классик или тбц
Я изменил комменты кое-где, почитай - возникнут вопросы - пиши
pavelzubkov
18.08.2010, 18:14
так значит функция sSpellStore.LookupEntry(spellId) возвращает данные о спелле из dbc.
uint8 cast_count; // количество кастов, увеличивается с каждым новым кастом для конкретного спелла
А для чего это используеться? Что бы подсчитать стаки как-либо эффектов? Диминишинг?
// auto-selection buff level base at target level (in spellInfo) (выбор уровня спелла согласно левелу чара)
Всмысле? Т.е. в функции SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const - определяеться какй уровень спелла использовал player?В actualSpellInfo данные о спелле соответственного уровня.
cast_count, вроде бы, в мангосе не используется, но я могу ошибаться.
Используется.
Для чего - не знаю, мб для вычислений, например предотвращения зацикливания триггера в deadloop, обработки мульти-кастов и т.д
Насчет уровня спелла - да
pavelzubkov
19.08.2010, 10:20
Я правильно понял? Критика моим комментариям приветствуется=)
void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura)/*Подготовка спелла*/
{
m_targets = *targets;/*Аргумент *targets нужен только для этого присваивания(еще не придумал как выразиться(*/
m_spellState = SPELL_STATE_PREPARING;/*Статистика спелла - подготовка*/
m_castPositionX = m_caster->GetPositionX();
m_castPositionY = m_caster->GetPositionY();
m_castPositionZ = m_caster->GetPositionZ();
m_castOrientation = m_caster->GetOrientation();
/*Получение координат и ориентации кастера*/
if(triggeredByAura)/**/
m_triggeredByAuraSpell = triggeredByAura->GetSpellProto();
// create and add update event for this spell Создание события для спелла?
SpellEvent* Event = new SpellEvent(this);//Создаем ЭВЕНТ для нашего спелла
m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1));/*Что за тайм считается? Время создания ЭВЕНТА? И для чего он создаеться?*/
/*Если не ошибаюсь ЭВЕНТ - событие. Создается событие для спелла?*/
//Prevent casting at cast another spell (ServerSide check) ??? /*Английский под учим, потом.*/
if(m_caster->IsNonMeleeSpellCasted(false, true) && m_cast_count)/*Милишный спелл и m_cast_count*/
{
/*Я прав что тут условие вида: if (m_caster->IsNonMeleeSpellCasted(false, true) == true && m_cast_count == true) {...}
но ведь m_cast_count не bool. Или он false если равен нулю и true если не равен нулю, ведь так?*/
SendCastResult(SPELL_FAILED_SPELL_IN_PROGRESS);//Отправка клиенту сведений о неудачном касте.
finish(false);/*Finish(bool) - это процедура говорящая о конце подготовки еслив на false то подготовка окончилась не удачей?*/
return;
}
// Fill cost data /*Данные о затратах на спелл(мана, энергия, ярость)*/
m_powerCost = CalculatePowerCost();/*CalculatePowerCost() подсчитывает затраты*/
uint8 result = CanCast(true);/*В CanCast проверяется возможность каста??*/
if(result != 0 && !IsAutoRepeat()) /*Всегда повторяем каст...*/ //always cast autorepeat dummy for triggering
{
if(triggeredByAura)/*Опять проверка на аргумент, который мы не передавали из WorldSession::HandleCastSpellOpcode*/
{/*И если он есть что-то делаем...*/
SendChannelUpdate(0);
triggeredByAura->SetAuraDuration(0);
}
SendCastResult(result);/*Посылка клиенту сведений о неудачи?????*/
finish(false);
return;
}
// calculate cast time (calculated after first CanCast check to prevent charge counting for first CanCast fail)
m_casttime = GetSpellCastTime(m_spellInfo, this);/*Достаем время каста спелла*/
// set timer base at cast time
ReSetTimer();/*Какой-то таймер ресаем*/
/*void ReSetTimer() { m_timer = m_casttime > 0 ? m_casttime : 0; } эта констция значит*/
// :
//void ReSetTimer()
//{
// if (m_casttime > 0)
// {
// m_timer = m_casttime;
// }
// else {m_timer = 0;}
//}
// stealth must be removed at cast starting (at show channel bar) Незаметность должна быть отменена при старте спелла?
// skip triggered spell (item equip spell casting and other not explicit character casts/item uses) Пропуск триггерного спелла?
if ( !m_IsTriggeredSpell && isSpellBreakStealth(m_spellInfo) )/*функция isSpellBreakStealth(m_spellInfo) определяет выводит ли спелл из режима незаметности??*/
{
m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);/*Выход из стелса*/
m_caster->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);/*Воскрешение????*/
}
if(m_IsTriggeredSpell)/*Тригерный ли спелл, если да каст(тру)*/
cast(true);/*Кастуется то что вызывает тригер??*/
else
{/*нет*/
m_caster->SetCurrentCastedSpell( this );/*Установление значений каста спелла. Там определяется крита, мисс, доджи, блок, пар...?*/
m_selfContainer = &(m_caster->m_currentSpells[GetCurrentContainer()]);/*?*/
SendSpellStart();/*Передача данных о старте спелла??*/
}
}
Vladimir
19.08.2010, 14:08
Используется.
Для чего - не знаю, мб для вычислений, например предотвращения зацикливания триггера в deadloop, обработки мульти-кастов и т.д
Насчет уровня спелла - да
Насколько помню в 2.x клиенте появилась возможность старта каста до подтверждения сервера об окончании предыдущего.
Т.е. игрок жмет каст - клиент видит что сервер не сообщил об окончании предыдущего каста, но посылает пакет каста серверу с +1 номером в упомянутом поле.
Сервер уже сам разбирается можно разрешить каст или нет.
Помогает при лагах когда клиент раньше не давал кастовать из-за лагов хотя по времени формально каст должен был уже закончится предыдущий.
pavelzubkov
19.08.2010, 18:54
Небольшой вопрос(на примере) по функциям в с++:
есть функция void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) из которой вызываеться другая функция void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura) и вот при вызове второй функции указываеться только один аргумент SpellCastTargets * targets, а второй нет. Как я понимаю на примере в предыдущих сообщениях функция вызовется, НО triggeredByAura(второй аргумент последней функции) будет не инициализирован. Я поторопился...нашел в spell.h прототип этой функции
void prepare(SpellCastTargets * targets, Aura* triggeredByAura = NULL); zergtmn стараюсь читать=)
Советую вам почитать книжки по С++.
Снова нужна помощь
решил переделать определение уровня гма, мне удобней чтобы все аккаунты на которые я захожу со своего айпи бали гмские
в accountmgr.cpp я прописываю
std::string IP_str = GetRemoteAddress();
и меняю запрос на нужный мне
при компиляции пишет неизвестный индификатор
пробовал так
player()->Getsesion()->GetRemoteAddress();
тоже неможет найти индефикатор
Подскажите что поправить:sorry:
Feel the Power
18.01.2011, 19:28
Снова нужна помощь
решил переделать определение уровня гма, мне удобней чтобы все аккаунты на которые я захожу со своего айпи бали гмские
в accountmgr.cpp я прописываю
std::string IP_str = GetRemoteAddress();
и меняю запрос на нужный мне
при компиляции пишет неизвестный индификатор
пробовал так
player()->Getsesion()->GetRemoteAddress();
тоже неможет найти индефикатор
Подскажите что поправить:sorry:
А библиотека std подключена в accountmgr.cpp?
тоже неможет найти индефикатор
я ваще тупой, тоже немогу найти ИНДЕФИКАТОР... и мне даже представить слабО что это такое...
А библиотека std подключена в accountmgr.cpp?
std подключена
WorldSocket.h подключаю, также выдает ошибку что найти не может
Имхо AccMgr это менеджер для работы с базой акков и не более. Тебе нужно копать WorldSession или AuthSocket.
HuntsMan
20.03.2011, 09:20
Каким образом экстрактор определяет что определенная карта должна иметь флаг DARKWATER? Старая тема от andstan'a на old.ru-mangos.ru не полностью :(
HuntsMan
14.05.2011, 15:05
Подскажите пожалуйста, какой SpellCastResult посылается клиенту, если спелл кастуется в движении, но в движении этот спелл кастовать нельзя?
SPELL_FAILED_MOVING = 51, // Невозможно делать это на ходу.
как можно задать шанс крита спелу?
Например если весит аура ток спел с вероятностью в x% должен нанести крит урон
bool Unit::IsSpellCrit(...)
vBulletin® v3.8.4, Copyright ©2000-2024, Jelsoft Enterprises Ltd. Перевод: zCarot