PDA

Просмотр полной версии : [patch/dev] Рандомные Виклики/Дейлики


alien
23.07.2010, 01:17
В общем решил написать патч на поддержку рандомных деликов и викликов.
Чтобы сразу понятно было вот вам скриншоты
http://img693.imageshack.us/img693/8967/wowscrnshot072310004205.jpg (http://img693.imageshack.us/i/wowscrnshot072310004205.jpg/)http://img693.imageshack.us/img693/7278/wowscrnshot072310004756.jpg (http://img693.imageshack.us/i/wowscrnshot072310004756.jpg/)
Так выглядит на оффе виклик...............................вот к примеру дейлик

А вот как выглядит это все на мангосе
http://img708.imageshack.us/img708/3272/wowscrnshot072310005948.jpg (http://img708.imageshack.us/i/wowscrnshot072310005948.jpg/)http://img196.imageshack.us/img196/3953/wowscrnshot072310010004.jpg
(http://img196.imageshack.us/i/wowscrnshot072310010004.jpg/)
виклик- - -- - -- - - - - -- - - -- -- - - - -- - - - - - -- - -- - - дейлик


Собственно патч

diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 5746f7d..c497bf7 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -6968,6 +6968,84 @@ void ObjectMgr::LoadCreatureInvolvedRelations()
}
}

+void ObjectMgr::LoadCurentWeekly()
+{
+ mCurWeekly.clear();
+
+ QueryResult *result = WorldDatabase.Query("SELECT quest_group,quest FROM quest_curent_weekly");
+
+ uint32 count = 0;
+
+ if( !result )
+ {
+ barGoLink bar( 1 );
+ bar.step();
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u curent weekly", count );
+ return;
+ }
+
+ barGoLink bar((int) result->GetRowCount() );
+
+ Field* fields;
+ do
+ {
+ bar.step();
+ fields = result->Fetch();
+ uint32 group=fields[0].GetUInt32();
+ uint32 quest=fields[1].GetUInt32();
+
+ sObjectMgr.mCurWeekly.insert(std::make_pair(group, quest));
+
+ ++count;
+ } while ( result->NextRow() );
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u curent weekly", count );
+}
+
+void ObjectMgr::LoadCurentDaily()
+{
+ mCurDaily.clear();
+
+ QueryResult *result = WorldDatabase.Query("SELECT quest_group,quest FROM quest_curent_daily");
+
+ uint32 count = 0;
+
+ if( !result )
+ {
+ barGoLink bar( 1 );
+ bar.step();
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u curent daily", count );
+ return;
+ }
+
+ barGoLink bar((int) result->GetRowCount() );
+
+ Field* fields;
+ do
+ {
+ bar.step();
+ fields = result->Fetch();
+ uint32 group=fields[0].GetUInt32();
+ uint32 quest=fields[1].GetUInt32();
+
+ sObjectMgr.mCurDaily.insert(std::make_pair(group,q uest));
+
+ ++count;
+ } while ( result->NextRow() );
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u curent daily", count );
+}
+
void ObjectMgr::LoadReservedPlayersNames()
{
m_ReservedNames.clear(); // need for reload case
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
index 9afc138..670c48b 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -209,6 +209,7 @@ typedef UNORDERED_MAP<uint32,PageTextLocale> PageTextLocaleMap;
typedef UNORDERED_MAP<int32,MangosStringLocale> MangosStringLocaleMap;
typedef UNORDERED_MAP<uint32,GossipMenuItemsLocale> GossipMenuItemsLocaleMap;
typedef UNORDERED_MAP<uint32,PointOfInterestLocale> PointOfInterestLocaleMap;
+typedef std::map<uint32,uint32> CurWeeklyOrDaily;

typedef std::multimap<uint32,uint32> QuestRelations;
typedef std::multimap<uint32,ItemRequiredTarget> ItemRequiredTargetMap;
@@ -629,11 +630,16 @@ class ObjectMgr
void LoadGameobjectInvolvedRelations();
void LoadCreatureQuestRelations();
void LoadCreatureInvolvedRelations();
+ void LoadCurentWeekly();
+ void LoadCurentDaily();

QuestRelations mGOQuestRelations;
QuestRelations mGOQuestInvolvedRelations;
QuestRelations mCreatureQuestRelations;
QuestRelations mCreatureQuestInvolvedRelations;
+
+ CurWeeklyOrDaily mCurWeekly;
+ CurWeeklyOrDaily mCurDaily;

void LoadGameObjectScripts();
void LoadQuestEndScripts();
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index e1be3a8..fcd077e 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -13058,6 +13061,9 @@ void Player::PrepareQuestMenu( uint64 guid )
Quest const* pQuest = sObjectMgr.GetQuestTemplate(quest_id);
if(!pQuest) continue;

+ if(!pQuest->IsCurWeeklyOrDaily(pObject->GetEntry()))
+ continue;
QuestStatus status = GetQuestStatus( quest_id );

if (pQuest->IsAutoComplete() && CanTakeQuest(pQuest, false))
diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp
index e2d86ca..a1594f0 100644
--- a/src/game/QuestDef.cpp
+++ b/src/game/QuestDef.cpp
@@ -270,3 +270,24 @@ bool Quest::IsAllowedInRaid() const

return sWorld.getConfig(CONFIG_BOOL_QUEST_IGNORE_RAID);
}
+
+bool Quest::IsCurWeeklyOrDaily(uint32 Entry) const
+{
+ if(!IsDailyOrWeekly() || !ExclusiveGroup) return true;
+ CurWeeklyOrDaily* CurQuest=IsWeekly()?&sObjectMgr.mCurWeekly:&sObjectMgr.mCurDaily;
+ CurWeeklyOrDaily::iterator it=CurQuest->find(ExclusiveGroup);
+ if(it==CurQuest->end())
+ {
+ QuestRelations* pObjectQR = &sObjectMgr.mCreatureQuestRelations;
+ std::vector<int> qList;
+ for(QuestRelations::const_iterator i = pObjectQR->lower_bound(Entry); i != pObjectQR->upper_bound(Entry); ++i)
+ qList.push_back(i->second);
+
+ uint32 randQuest=qList[urand(0,qList.size()-1)];
+ CurQuest->insert(std::make_pair(ExclusiveGroup,randQuest));
+ WorldDatabase.PExecute("INSERT INTO quest_curent_%s (quest_group,quest) VALUES ('%u','%u')",IsWeekly()?"weekly":"daily",ExclusiveGroup,randQuest);
+
+ if(CurQuest->find(ExclusiveGroup)->second==QuestId) return true;
+ } else if(it->second==QuestId) return true;
+ return false;
+}
diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h
index 6e62e37..ec418fa 100644
--- a/src/game/QuestDef.h
+++ b/src/game/QuestDef.h
@@ -259,7 +259,7 @@ class Quest
bool IsDailyOrWeekly() const { return QuestFlags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY); }
bool IsAutoAccept() const { return QuestFlags & QUEST_FLAGS_AUTO_ACCEPT; }
bool IsAllowedInRaid() const;
-
+ bool IsCurWeeklyOrDaily(uint32 Entry) const;
// multiple values
std::string ObjectiveText[QUEST_OBJECTIVES_COUNT];
uint32 ReqItemId[QUEST_ITEM_OBJECTIVES_COUNT];
diff --git a/src/game/World.cpp b/src/game/World.cpp
index f29bc10..3f5c59f 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -1052,6 +1052,12 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Quests..." );
sObjectMgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables

+ sLog.outString( "Loading Curent Weekly..." );
+ sObjectMgr.LoadCurentWeekly();
+
+ sLog.outString( "Loading Curent Daily..." );
+ sObjectMgr.LoadCurentDaily();
+
sLog.outString( "Loading Quest POI" );
sObjectMgr.LoadQuestPOI();

@@ -1980,11 +1998,13 @@ void World::InitDailyQuestResetTime()
void World::ResetDailyQuests()
{
DETAIL_LOG("Daily quests reset for all characters.");
CharacterDatabase.Execute("DELETE FROM character_queststatus_daily");
+ WorldDatabase.Execute("DELETE FROM quest_curent_daily");
for(SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
if (itr->second->GetPlayer())
itr->second->GetPlayer()->ResetDailyQuestStatus();
-
+ if(!sObjectMgr.mCurDaily.empty())
+ sObjectMgr.mCurDaily.clear();
m_NextDailyQuestReset = time_t(m_NextDailyQuestReset + DAY);
CharacterDatabase.PExecute("UPDATE saved_variables SET NextDailyQuestResetTime = '"UI64FMTD"'", uint64(m_NextDailyQuestReset));
}
@@ -1993,10 +2013,12 @@ void World::ResetWeeklyQuests()
{
DETAIL_LOG("Weekly quests reset for all characters.");
CharacterDatabase.Execute("DELETE FROM character_queststatus_weekly");
+ WorldDatabase.Execute("DELETE FROM quest_curent_weekly");
for(SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
if (itr->second->GetPlayer())
itr->second->GetPlayer()->ResetWeeklyQuestStatus();
-
+ if(!sObjectMgr.mCurWeekly.empty())
+ sObjectMgr.mCurWeekly.clear();
m_NextWeeklyQuestReset = time_t(m_NextWeeklyQuestReset + WEEK);
CharacterDatabase.PExecute("UPDATE saved_variables SET NextWeeklyQuestResetTime = '"UI64FMTD"'", uint64(m_NextWeeklyQuestReset));
}


CREATE TABLE `quest_curent_daily` (
`quest_group` int(10) unsigned NOT NULL default '0',
`quest` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`quest_group`,`quest`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for quest_curent_weekly
-- ----------------------------
CREATE TABLE `quest_curent_weekly` (
`quest_group` int(10) unsigned NOT NULL default '0',
`quest` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`quest_group`,`quest`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Есть небольшой баг. если дейлик/виклик одной группы но разные задания находятся у разных НПЦ то у того НПС которому не повезло с квестом значек над головой остается. Щас этим займусь.
Может придется переписать немного(
В общем сейчас загрузка и сохранение рандомных квестов есть и также их сброс.

zhenya
23.07.2010, 04:24
quest_curent_weekly и quest_curent_daily для хранения списков текущих дейликов и викликов.
можно добавить флаг в базу и использовать 1 таблицу. типа flag == 0x00 daily, flag == 0x01 weekly.

virusav
23.07.2010, 08:58
Выполняемые игроком дейли и викли квесты итак хранятся в базе.
Есди не ошибаюсь, то при взятии квеста с одним значением ExclusiveGroup остальные исчезают из списка.
Что именно планируется загружать из базы?

alien
23.07.2010, 10:44
virusav,
вот именно что исчезают из списка только после взятия. а у нас сразу в списке должен быть только один. неужели по скрину непонятно?
zhenya,
просто если посмотреть на то как реализовано запоминание дейликов и викликов которые выполнил игрок то там тоже две таблицы видимо чтобы было удобней таблицу очищать.

zergtmn
23.07.2010, 10:59
У меня была мысль показывать 1 квест в зависимости от даты, чтобы в базе ничего не хранить... А на оффе они совершенно случайно выбираются?

BoLT
23.07.2010, 11:11
А на оффе они совершенно случайно выбираются?

Да! При чём на разных рилмах разные..

alien
23.07.2010, 11:12
Да.
Может подряд несколько недель быть один и тотже.
Тоесть обычный рандом.

LordJZ
23.07.2010, 11:17
Имхо, проще делать через game_event

alien
23.07.2010, 11:36
И какимже образом через гем_евент реализовать эту туеву кучу викликов и дейликов? ведь это не 1 и не 2 гивера. их около 100 наверно в игре кто дает рандомные квесты.

virusav
23.07.2010, 12:04
virusav,
вот именно что исчезают из списка только после взятия. а у нас сразу в списке должен быть только один. неужели по скрину непонятно?

Перед выводом списка квестов одной группы проверяем, есть ли на руках квест этой же группы.
Если да, то выводим его.
Если нет, то запускаем твой код и выбираем случайным образом один квест из группы.

Таким образом игроку будет показан один случайный квест из группы.

alien
23.07.2010, 12:24
Перед выводом списка квестов одной группы проверяем, есть ли на руках квест этой же группы.
Если да, то выводим его.
Дак это и так реализованно.
А вот если на руках нету ни одного квеста из квест группы то тогда выбираем рандомный квест запоминаем его, записываем в базу и всем остальным просто предлагаем этот квест.

virusav
23.07.2010, 13:03
Зачем? Разве случайный квест выпадает всем игрокам один и тот же?
Мне кажется, что надо делать выбор случайного квеста для каждого игрока заново при открытии списка квестов нпц или го.

Тут уже нужна инфа с офа, как там.

alien
23.07.2010, 13:41
Да случный квест для всех 1(если дейлик в течении дня, если виклик в течении недели)

LordJZ
23.07.2010, 14:24
И какимже образом через гем_евент реализовать эту туеву кучу викликов и дейликов? ведь это не 1 и не 2 гивера. их около 100 наверно в игре кто дает рандомные квесты.Можно выделить какой-то отдельный номер в game_event и туда сохранять. И никаких дополнительных таблиц или имплементаций в ядре ненужно. Вероятно, правда, каким-то флагом или еще как-то обозначить те ExclusiveGroup, какие должны быть рандомными.

alien
23.07.2010, 14:43
И зачем такая морока? То есть добавили близы новый список дейликов/викликов и заносить в game_event.
Да и в game_event это сохронять не логично.(темболее не представляю даже как там это реализовать.)

LordJZ
23.07.2010, 14:50
Нет, ничего не придется заносить, это делать будет сервер (или вы собрались каждый день дейлики туда заносить?). При появлении новых дейликов вам, как и в вашем-же способе, придется как-то их обозначить. Только в моем случае не нужно никаких дополнительных изобретений и таблиц.

alien
23.07.2010, 15:00
Ну хорошо тогда как вы представляете реализацию через game_event.
Я что-то не догоняю как это можно реализовать.

LordJZ
23.07.2010, 15:01
При сбросе дейликов пересчитывать новые, рандомные, и добавлять их в game_event (на случай отключения сервера) под определенным номером.

alien
23.07.2010, 15:13
Тоесть сервер при сбросе будет пробегать по всем квестам, выбирать рандомный из группы и заносить в гем-евент?

LordJZ
23.07.2010, 15:30
Примерно так

alien
23.07.2010, 15:53
А нафига лишним сервер нагружать при старте?
Просто в моем случае квесты выбираются по мере надобности(или просто подгружается уже составленный список из базы)
А так придется при первом старте пробегатся по ВСЕМ квестам(или хранить список всех груп квестов которые являются дейликами/викликами в какойто таблици или еще гдето.) да и вот еще что-то не представляю как в самом гем-евенте хранить запись о выбранном виклике/дейлике?

LordJZ
23.07.2010, 15:59
Не при старте, а раз в день, при сбросе дейликов. Квестов достаточно мало — всего около 9000, с ExclusiveGroup != 0 всего 630. Проверка по всем квестам пройдет за считанные миллисекунды.

У вас же при каждом обращении к любому квестеру идет поиск в загруженной таблице, т.п.

Система написана, документация есть, все работает без ошибок — зачем вам знать, как она работает? И зачем создавать аналоги?

alien
23.07.2010, 16:28
Вобщето идет проверка только если квест дейлик/виклик. и не по таблици а по map'у
и вот только если нету в мапе записи об этой ExclusiveGroup то тогда запускаем генерацию рандом квеста.

Так а теперь глобальный вопрос приведите пример как вы видите запись в game_event?
Я например не вижу оптимального пути использования game_event даже если убрать поиск и выбор квестов.
Тоесть возьмем пример на этой недели у нас у NPC 20735 квест 24586.
Это значит нам надо создать запись в game_event текущей даты а потом в Game_event_creature_quest добавить запись с ID из game_event и ID НПС и квеста и так для каждого НПС.
Потом когда будет другой квест нам придется править все ID квестов .
И еще сервер не перезагружает game_event при своей работе тоесть придется делать чтобы перезагружал. А это совершенно неверно.
В общем я не вижу ни одного + в пользу game_event а только сплошные -

Vladimir
23.07.2010, 20:40
Для каждого квеста заводится event c единсвенным элементом game_event_creature_quest - ну возможно с негативными для остальных в группе
на время когда он будет показываться.
Вы уверены что они случайные а не идут просто по цеочке...

Energy
23.07.2010, 20:44
Для каждого квеста заводится event c единсвенным элементом game_event_creature_quest - ну возможно с негативными для остальных в группе
на время когда он будет показываться.
Вы уверены что они случайные а не идут просто по цеочке...

Случайные. Реализовать, действительно, логичнее с помощью системы эвентов. Просто доработаеть ее чтобы была возможность запуска рандомного эвента из группы

Vladimir
23.07.2010, 20:55
возможно если quest из exclusive group - а имеено галвный в ней - то интерпретировать это как бырать случайный из?
Так как странно в нормальном случае иметь в event quest exclusive c квестами не в event... ?

Можно ограничить повторяемыми

alien
23.07.2010, 21:00
Вы уверены что они случайные а не идут просто по цеочке...
Да уверен на все 100% ))
и немного не понял что вы тут хотели сказать.
возможно если quest из exclusive group - а имеено галвный в ней - то интерпретировать это как бырать случайный из?
Так как странно в нормальном случае иметь в event quest exclusive c квестами не в event... ?

Ладно щас попробую придумать как это реализовать при помощи game_event

Energy
23.07.2010, 21:20
Советую обратить внимание на квестгивера, дающего викли на боссов в вотлк рейдах.
Возле него за стенкой вращается моделька босса, которого необходимо кокнуть по текущему виклику, соответственно это стопудово система эвентов.
Просто нужно реализовать группировку эвентов, либо предусмотреть вообще тип эвента - случайный викли или случайный дейли, которые будут меняться одновременно с резетом дейликов/викликов

LordJZ
23.07.2010, 21:35
Для каждого квеста заводится event c единсвенным элементом game_event_creature_quest - ну возможно с негативными для остальных в группе
на время когда он будет показываться.
Вы уверены что они случайные а не идут просто по цеочке...А зачем создавать для каждого квеста свой id?.. Пусть они хранятся в каком-нибудь -1 или -2 (викли/дейли). Просто придется удалить лишнюю сотнб записей из creature_questrelation.

Vladimir
23.07.2010, 21:53
Я про свой говорил пока не написал про exсlude group

alien
23.07.2010, 23:42
Такая идея реализации.
game_event.holiday разрешить отрицательные значения(типа эвенты которых нету в Holidays.dbc но которые надо как-то обработать по своему), дальше для каждой рандомной группы вручную создаем запись.
Также заполняем game_event_creature_quest всеми квестами из этой группы и просто
в GameEventMgr::UpdateEventQuests(uint16 event_id, bool Activate) обрабатываем по своему запись с отрицательным числом(например для -1 это будет выдать только рандом) и собственно
if (Activate) // Add the pair(id,quest) to the multimap
CreatureQuestMap.insert(QuestRelations::value_type (entry, randomQuest));
-2 можно будет сделать для обработки мобов за http://ru.wowhead.com/npc=20735
там может и -3 подтянется ))

LordJZ
23.07.2010, 23:54
Скажите, ну вот скажите, ну вот зачем эти holiday, -3, Верховный маг Лан'далок?

Почему бы просто не создать эвенты -1 (дейлики) и -2 (виклики), и туда складывать и мобов-призраков, и дополнительные квестовые НПС (Ристалище), и сами записи из game_event_creature_quests (или как она там называется)?

alien
24.07.2010, 00:01
Тогда и -2 не нужне.
так с точки зрения события они отличаются только длительностью а длительность задается в start_time,end_time,occurence

LordJZ
24.07.2010, 00:04
Да, можно сделать один и на виклики, и на дейлики. Но тогда вам придется очищать game_event таблицы с id=-1 вручную, проверяя каждый квест на виклик, это в 100 раз замедлит работу и в 10 раз увеличит количество кода.

alien
24.07.2010, 00:18
Подождите а зачем что-то удалять из game_event?
Просто делаем записи так. Что у евента длительность 23 часа а повторять каждые 24 часа.
Виклики соответственно 6д и 23ч длительность а повторение каждые 7 дней
Вот и все. И ничего удалять не придется или я неправ?

LordJZ
24.07.2010, 00:20
Удалять придется, чтобы сменить текущие дейлики. Это делается во время их сброса.

alien
24.07.2010, 00:26
Подождите зачем?
вот стандартный код из геймевентманаджера.
QuestRelations &CreatureQuestMap = sObjectMgr.mCreatureQuestRelations;
if (Activate) // Add the pair(id,quest) to the multimap
CreatureQuestMap.insert(QuestRelations::value_type (itr->first, itr->second));
else
{ // Remove the pair(id,quest) from the multimap
QuestRelations::iterator qitr = CreatureQuestMap.find(itr->first);
if (qitr == CreatureQuestMap.end())
continue;
QuestRelations::iterator lastElement = CreatureQuestMap.upper_bound(itr->first);
for ( ;qitr != lastElement;++qitr)
{
if (qitr->second == itr->second)
{
CreatureQuestMap.erase(qitr); // iterator is now no more valid
break; // but we can exit loop since the element is found
}
}
}
Нам его чутка переделать чтобы вместо того чтобы добавлять ВСЕ квесты из game_event_creature_quest он добавлял рандомный. А удаление квеста можно и в текужем виде вобще оставить.
Тоесть когда евент у нас останавливается у нас просто из sObjectMgr.mCreatureQuestRelations удаляется все квесты которые были в game_event_creature_quest а как только стартует то в mCreatureQuestRelations заносится. Дак вот в нашем случае надо не все квесты заносить в а 1 рандомный из списка который хранится под этим евентом.

LordJZ
24.07.2010, 00:50
Под этим эвентом хранится УЖЕ срандомленный, один на группы, единственный-избранный квест. И его надо будет удалить ИЗ БАЗЫ.

Всего вам нужно написать:
— удаление данных из базы
— добавление данных в базу
Все остальное уже написано.

Причем делать это можно, если вам очень хочется, даже не сервером!

Vladimir
24.07.2010, 00:58
Зачем удалять из базы если планируется в коде выбор случайного для активации из статичесокго набора....

LordJZ
24.07.2010, 01:04
Я имею ввиду удалять из базы старые квесты, когда из групп выбираются новые.

alien
24.07.2010, 01:09
LordJZ, так мороки больше.
Мы храним ВСЕ квесты и все Евенты мы их не вообще базу game_event и базу квестов принадлежащих евенту.
А вот евентманаджер выбирает рандом и заносит этот рандомный квест в mCreatureQuestRelations.
Хотя тут тоже есть проблема. А если свервер упадет или его надо перезапустить.
Тоесть придется сохранять Id выбранного квеста.
UPD:
Во можно посто под -(минус) использовать id текущего выбранного квеста.
тоесть как только евентманаджер выбрал для текущего евента квест то он в holiday пишет -randomQuestID
и если сервер падает то когда его поднимают он оттуда берет выбранный квест.

LordJZ
24.07.2010, 01:31
game_event делает все эти операции за вас

alien
24.07.2010, 01:39
Какие именно? выбор рандомного квеста?
или сохранение рандомного квеста?
а вот добавлять/удялять записи в game_event и в game_event_creature_quest вовремя работы сервера это както хаково притом сильно хаково. так-как сервер по умолчанию не перезагружает эти таблици во время своей работы.
И тогда надо будет добавлять перезагрузку этих таблиц.
Или что тоже как-то хаково править переменные в которых хрянится загруженная инфа из бызы.

LordJZ
24.07.2010, 02:25
Чем вам мешает сохранение данных в game_event таблицы, тем более что они не перезагружаемые? В вашем случае реализовать половину функций рандом дейликов вообще не получится — те же Image-ы, к примеру.

alien
24.07.2010, 02:36
Это почему еще?
Спокойно реализуется все.
Просто нужно гдето хранить соответствие QuestId-CreatureID для отобржения.
Можно даже в коде прямо хранить Просто масивом из структуры. Благо там не более 10 записей.
--
Ну хорошо давайте над вашим способом подумаем в game_event мы записали некоторый делик а в game_event_creature_quest записали ID нового эвента и квест который должен быть. Дальше то что? как мы заставим сервер подхватить их Он же уже давно это таблицу прогрузил.

LordJZ
24.07.2010, 03:14
И вы опять будете писать костыли, спавнить НПС, давать им анимации, еще что-то... Ради чего, скажите мне? Это все можно сделать через game_event.

И почему вы считаете что в рантайме нельзя изменить данные эвента? Очень даже можно.


П.С. Спор бессмысленный, я смотрю, вы так и будете стоять на своем — создание новых таблиц, новых решений и прочего. Больше я вас призывать к использованию существующих возможностей не буду — кодьте, на здоровье!

alien
24.07.2010, 03:39
Ну я как-бы и использую существующие возможности.
У гейм_евент есть такая таблица game_event_creature
в которую помещаются записи критчеров которые надо показать в мире при запуске евента. притом GameEventMgr сам их заспавнит и сам уберет.

Мне чтобы заработало все как нужно надо только дописать в GameEventMgr пару строчек чтобы он выбирал рандомно квест(ну и критчера к этому рандом квесту если надо).
ВСЕ остальное делает сам GameEventMgr код добавления в sObjectMgr.mCreatureQuestRelations уже в нем есть его надо только под рандомность подогнать удаление из sObjectMgr.mCreatureQuestRelations можно вообще оставить.

В итоге что у нас получается.
1)Заполняем таблицу game_event всеми нужными дейликами/викликами ставя holiday = -1
2) Удаляем из creature_questrelation все записи о тех квестах которые реализуем через game_event
3) Добавляем в game_event_creature_quest наш список квестов и связываем с нужными записями в таблицы game_event.
4) Тоже самое если нужно делаем с game_event_creature
5) Правим GameEventMgr так чтобы он если holiday <0 и время обновить евент выбирал рандомный квест из текущего евента(и получал по этому квестИД если нужно соответствующего критчер) также записываем на место holiday -(CurQuestId)чтобы если сервер упал или перезагрузили то был тот-же квест.
ВСЕ Больще нам делать нечего, все остальное уже есть в GameEventMgr

Energy
24.07.2010, 05:51
А почему бы не сделать вот так?
1) добавляем в таблицу game_event колонку (например ExclusiveGroup по аналогии с quest_template). В ней для всех эвентов, которые должны исключать друг друга, будет стоять идшник первого из них
2) создаем обычные эвенты с обычным ид, но, допустим с -1 HolidayID для викликов и -2 HolydayID для дейликов. start_time, end_time и occurrence по нулям.
3) в коде мы случайным образом выбираем новый эвент с HolydayID -1 и -2 и запускаем его, там где происходит резет дейликов и викликов соответственно.
4) дальше всю работу сделает для нас система эвентов. Мы можем отспавнить другую модельку рядом с квестгивером, или напялить на квестгивера другой DisplayID, либо вообще все что угодно :)

Собственно вопрос. При текущей реализации системы эвентов, квесты перестают сдаваться после окончания эвента, или просто перестают выдаваться? Например, если человек взял и сделал дейлик сегодня, а сдать он его решит, например, завтра(когда фактически уже будет активен другой эвент). у него это получится?

Можно так же доработать саму систему эвентов, и полноценно реализовать поддержку эксклюзивных эвентов. Например так:

есть эвент с данными о начале, продолжительности, и т. д. у него допустим ид 3000. в поле ExclusiveGroup тоже 3000. есть еще эвенты с 3001 по 3010, у которых пропущены данные о продолжительности, но в поле ExclusiveGroup тоже стоит число 3000. Когда приходит время старта эвента с номером 3000, выбирается случайным образом один из эвентов с полем ExclusiveGroup 3000, и запускается.

С помощью эксклюзивных эвентов так же можно будет реализовать живность в городах, вроде гуляющих именных мобов в Даларане.


Правда для корректной работы данной фишки нужно реализовать так же и возможность сохранения таких данных, как то, какой из вручную (т.е. при резете квестов) запущенных эвентов был активен на момент последнего сейва сервера. И вообще помнится был патч на систему эвентов, позволяющий сохранять ворлдстейты, и реализовывать многоступенчатые эвенты вроде открытия санвелла или AQ War Effort

alien
24.07.2010, 11:53
Собственно вопрос. При текущей реализации системы эвентов, квесты перестают сдаваться после окончания эвента, или просто перестают выдаваться?
просто перестают выдаваться.
так-как за прием квеста отвечает другая таблица которая в гем_евент не участвует.

Vladimir
24.07.2010, 12:21
сдать неполучиться только если с event окончанием удаляется и сам npc.
Но в данном случае речь об этом не идет.

alien
20.09.2010, 18:06
Возвращаемся к нашим баранам... :)
1) Самым проблемным для реализации через game_event является виклики у
http://ru.wowhead.com/npc=20735
Тут либо надо хардкодить связь Creature которые находятся сзади с выбираемым квестом, либо создавать еще одну таблицу в которой хранить эту связь. Но и тут не так все просто так-как вначале надо выбирать не квест а Creature так-как вначале отрабатываются то какие Creature будут заспавнены, а только потом квесты.
Да и если в
void GameEventMgr::UpdateEventQuests(uint16 event_id, bool Activate) (http://github.com/mangos/mangos/blob/master/src/game/GameEventMgr.cpp#L793) легко добавить выбор рандомного квеста и пропуск остальных. то вот в void GameEventMgr::GameEventSpawn(int16 event_id) (http://github.com/mangos/mangos/blob/master/src/game/GameEventMgr.cpp#L532) и void GameEventMgr::GameEventUnspawn(int16 event_id) (http://github.com/mangos/mangos/blob/master/src/game/GameEventMgr.cpp#L641) не так то и просто добавить спавн одного и унспавн других NPC.
Кто нибудь, что нибудь подскажет по этому поводу?

2) Дальше следующая проблема.
Как организовать перезапуск евента?
а)
например можно сделать вот так.
Длительность эвента 1339 минут а стартует каждые 1440.
В итоге у нас будет минута в течении которой квесты будет недоступен.
б)
Добавить в гайм_евент функцию
void GameEventMgr::ResetEvent(uint16 event_id)
{
StopEvent(event_id);
StartEvent(event_id);
}
И соответственно в void World::ResetDailyQuests() (http://github.com/mangos/mangos/blob/master/src/game/World.cpp#L1993) вызывать эту функцию с нужными ID
Мне кажется что так правильнее.
Или просто в void World::ResetDailyQuests() (http://github.com/mangos/mangos/blob/master/src/game/World.cpp#L1993) вызыв последовательность StopEvent(event_id);
StartEvent(event_id);
Тут есть огромный + мы можем очистить в game_event поле(СМ п 3.б)
и все довольно удобно.

3)
Как хранить(и где) состояние выбранного рандомного виклика дейлика?
а) Добавить еще одну таблицу в которой хранится креатуре которому принадлежит квест и квест id.
б) В game_event добавить еще одно поле которое будет просто хранить рандомный номер(тоесть номер записи в mGameEventQuests[event_id])
Выбор квеста например сейчас выглядит так
mGameEvent[event_id].RandQuest=mGameEventQuests[event_id][urand(0,mGameEventQuests[event_id].size()-1)];
В базу можно например сохранять просто результат
urand(0,mGameEventQuests[event_id].size()-1).

Если бы не надобность выбирать для http://ru.wowhead.com/npc=20735 то все делалось довольно тривиально, а так приходится извращаться немного
=============================
В общем у кого какие идеи?

Lordronn
20.09.2010, 18:13
На тринити это уже сделали, нужные данные хранят в базе чарактерс, там только квест Иды вроде. Попробую откопать коммит

alien
20.09.2010, 18:53
Хмм... что-то просмотрев код тринити по диагонали не заметил куда они это запихнули. в Гейм_евенте нету.

UPD:
Может ты про обычные виклики и дейлик?
Там да просто сохраняется ID выполненного квеста.