Идентификация, или кто есть кто |
Здравствуйте, гость ( Вход | Регистрация )
Идентификация, или кто есть кто |
Jun 17 2004, 11:36
Сообщение
#1
|
|
Level 9 Класс: Волшебник Характер: Chaotic Good Раса: Дракон NWN: Скриптинг [PW] |
Любой скриптер когда-нибудь сталкивается с такой задачей - однозначно идентифицировать персонажа.
Обычные варианты логин+СДКЕЙ+имя персонажа - не являются 100% надежными, ведь можно создать второго персонажа с таким же именем. Вот скрипт, "считающих" всех персонажей и выдающий им номер. Для простоты\быстроты номер хранится в Deity, но проверяется в любом случае. Версия скрипта еще не последняя и возможны ошибки, но в целом - скрипт проверенный и работоспособный. Код //возвращает UNIQ_ID, -1 - если ошибка int ID_GetID(object oPC); //возвращает объект-игрока с номером ID или OBJECT_INVALID - если такого игрока нет онлайн object ID_FindPC(int ID); /////////////////////////////////////////////////////////////////////// object ID_FindPC(int ID) { object oPC = GetFirstPC(); while (GetIsObjectValid(oPC)) { if ( GetLocalInt(oPC,"UNIQ_ID") == ID) return oPC; oPC = GetNextPC(); } return OBJECT_INVALID; } int ID_GetID(object oPC) { while (GetIsObjectValid(GetMaster(oPC))) { oPC=GetMaster(oPC); } if (!GetIsPC(oPC)) { return -1; } //кэширование результата, чтобы не лазить в БД каждый раз int id = GetLocalInt(oPC,"UNIQ_ID"); if (id > 0) { return id; } //длЯ ДМ-ов упрощенна проверка if (GetIsDM(oPC)) { id = GetCampaignInt("ident_dm",GetPCPublicCDKey(oPC)+"_"+GetPCPlayerName(oPC)); if (id > 0) { SetLocalInt(oPC,"UNIQ_ID",id); return id; } //maybe first time? assign new ID int id = GetCampaignInt("ident_dm","LAST_UNIQ_ID"); if (id == 0) { //ДМ-ы получают номера начинаЯ с 101 id = 100; } id++; SetCampaignInt("ident_dm","LAST_UNIQ_ID",id); SetLocalInt(oPC,"UNIQ_ID",id); SetCampaignInt("ident_dm",GetPCPublicCDKey(oPC)+"_"+GetPCPlayerName(oPC),id); return id; } //проверочнаЯ строка, котораЯ записываетсЯ в БД string sID_STRING = "mg_ident"+"_"+GetPCPublicCDKey(oPC)+"_"+GetPCPlayerName(oPC)+"_"+GetName(oPC); int iDeity = StringToInt(GetDeity(oPC)); //Если игрок в первый раз пришел - обнулим ему поле Deity. //!!! Не забудьте выдать игроку хотЯ-бы 1 XP, чтобы он не считалсЯ впервые зашедшим на щард if (GetXP(oPC) == 0) { iDeity =0; SetDeity(oPC,""); } //Если в Deity есть число - проверЯем по базе с ID_STRING //Сама база устроена в виде записей номер:ID_строка if (iDeity > 0) { string sDB = GetCampaignString("ident",IntToString(iDeity)); if (sDB == sID_STRING) { //check ok! cache & return SetLocalInt(oPC,"UNIQ_ID",iDeity); return iDeity; } else if (sDB != "") //may be corrupted DB? //Вариант, если испортилась БД (например удалили всех персонажей, но не почистили каталог с БД. { BootPC(oPC); return -1; } } //Если дошли до сюда - видимо новый персонаж, провери его имЯ и логин по всей базе и если найдем такого-же - значит кто-то пытаетсЯ создать "дублЯ" int iLastPC = GetCampaignInt("ident","LAST_UNIQ_ID"); if (iLastPC == 0) { iLastPC = 1000; //Игроки нумеруютсЯ с 1001 } int k; string sTest; for (k = 1000;k <= iLastPC; k++) { sTest =GetCampaignString("ident",IntToString(k)); if (sTest == sID_STRING) { //Ага, это читер. Выбрасываем его. BootPC(oPC) return -1; } } //Все нормально, просто новый игрок - запишем его в БД и выставим ему Deity- длЯ более быстрого поиска в следующий раз iLastPC++; SetCampaignInt("ident","LAST_UNIQ_ID",iLastPC); SetLocalInt(oPC,"UNIQ_ID",iLastPC); SetCampaignString("ident",IntToString(iLastPC),sID_STRING); SetDeity(oPC,IntToString(iLastPC)); //На всЯкий запишем персонажа DelayCommand(4.0,ExportSingleCharacter(oPC)); //и вернем номер. return iLastPC; } После такой нумерации мы получаем уникальный номер для каждого персонажа, что открывает нам новые возможности - мы можем сохранять инфромацию в базе данных для персонажа даже когда сам игрок не на шарде (оффлайн) Если на шарде используется БД - очень удобно хранить всю информацию, относящиюся к данному игроку, в отдельной БД (лучше несколько маленьких БД, чем одна большая - скорость куда выше). Как это сделанно у нас - есть библиотека для работы с БД, очень похожая на обычные SetLocal*, GetLocal*, только пишет инфу кроме памяти в БД (если флаг стоит). Она хранится в памяти, использую в виде префикса номер игрока, поэтому переменные с одним именем не пересекаются для разных игроков. Кроме того, позволяет писать в БД информацию по оффлайн-игрокам (к примеру нужно для обработки события onClientLeve) |
Oct 31 2005, 17:44
Сообщение
#2
|
|
Level 7 Класс: Бард Характер: Lawful Good Раса: Фея |
А как бороться с проблемой создания чара с таким же именем?
|
Oct 31 2005, 21:48
Сообщение
#3
|
|||
Level 11 Класс: Вор Характер: Neutral Evil Раса: Эльф NWN: Скриптинг [PW] Validor2 |
помоему ответ на этот вопрос был где-то на этом форуме... если в кратце, то это будет выглядеть так... при входе проверяем наличие в базе данных записи со значением "имя+акк"... если такой записи нет - добавляем и пропускаем чара.. + даем чару 1 экспу... если запись есть - то проверяем кол-во экспы на чаре... если экспы больше 0, то то легальный чар - пропускаем... если экспа равна 0, значит чар только что создан - бутим... |
||
Текстовая версия | Сейчас: 28th April 2024 - 00:12 |