L0ndl3m
12.06.2014, 14:27
Многие люди спрашивали как сделать систему достижения, сейчас я попробую показать как это делать.
Попробуем сделать систему достижений из 3 штук.
Достижения
Вынос мозга
Вершина мира
Маньяк
В начало мода, создадим глобально ( то есть ко всем new )
const
MAX_ACHIEVEMENT_NAME = 13,
DIALOG_ACHIEVEMENTS = 512,
DIALOG_ACHIEVEMENTS_EXP = 1024;
static const
achievement_names[][MAX_ACHIEVEMENT_NAME] =
{
"Вынос мозга", "Вершина мира", "Маньяк"
};
new
achievement[MAX_PLAYERS],
ach_progress[MAX_PLAYERS][2 char];
#if !defined BODY_PART_TORSO
enum
{
BODY_PART_TORSO = 3,
BODY_PART_GROIN,
BODY_PART_LEFT_ARM,
BODY_PART_RIGHT_ARM,
BODY_PART_LEFT_LEG,
BODY_PART_RIGHT_LEG,
BODY_PART_HEAD
};
#endif
enum(<<= 1)
{
ACHIEVEMENT_BRAINFUCK = 1,
ACHIEVEMENT_TOP_OF_THE_WORLD,
ACHIEVEMENT_MANIAC
};
Начнём с первого достижения: Вынос мозга.
Суть достижения заключается в том, чтобы за один сеанс игры убить 5 человек в голову.
Реализация будет выглядеть так: добавляем в public OnPlayerGiveDamage
if(damagedid != INVALID_PLAYER_ID && bodypart == BODY_PART_HEAD)
{
SetPlayerHealth(damagedid, 0.0);
if(((achievement[playerid] & ACHIEVEMENT_BRAINFUCK) == 0) && ++ach_progress[playerid]{0} == 5)
{
UnlockPlayerAchievement(playerid, 0);
GivePlayerMoney(playerid, 100000);
SendClientMessage(playerid, -1, "Вы получили вознаграждение: {FF0000}$100000");
}
}
Реализация первого достижения готова.
Теперь начнём со второго достижения: Вершина мира
Суть достижения заключается в том, чтобы залезть на вершину горы чиллиад (это самая высокая точка на карте).
Попытаемся реализовать достижение:
Добавляем в public OnGameModeInit:
SetTimer("@__achievement_update", 1000, 1);
В любое место в моде, можно ко всем public'ам:
@__achievement_update();
@__achievement_update()
{
new
i = GetMaxPlayers();
do
{
--i;
if(IsPlayerConnected(i) && (0 == (achievement[i] & ACHIEVEMENT_TOP_OF_THE_WORLD)) && IsPlayerInRangeOfPoint(i, 2.0, -2432.7881, -1620.0902, 526.8478))
{
UnlockPlayerAchievement(i, 1);
GivePlayerWeapon(i, 38, 150);
SendClientMessage(i, -1, "Вы получили: {FF0000}150 патронов к оружию Minigun");
}
}
while(i);
}
Реализация второго достижения готова.
Приступим к последнему, третьему достижению: Маньяк.
Суть достижения заключается в том, чтобы убить пятерых игроков лопастями вертолёта.
Реализуем достижение, добавив в public OnPlayerDeath:
if(reason == 50 && killerid != INVALID_PLAYER_ID && ((achievement[killerid] & ACHIEVEMENT_MANIAC) == 0) && ++ach_progress[killerid]{1} == 5)
{
UnlockPlayerAchievement(killerid, 2);
SetPlayerHealth(killerid, 500.0);
SendClientMessage(killerid, -1, "Вы получили: {FF0000}500 единиц здоровья.");
}
Реализация трёх достижений готова.
Создадим отдельный сток, который будет показывать какой игрок разблокировал достижение, в любое место скрипта (ко всем stock'ам):
stock UnlockPlayerAchievement(const playerid, const id)
{
achievement[playerid] |= 1 << id;
static const
fmt_str[] = "• {FF0000}%s (%i){AAAADD} разблокировал достижение: {FF0000}%s";
new
str[sizeof(fmt_str) - 2 + MAX_PLAYER_NAME - 2 + 3 - 2 + MAX_ACHIEVEMENT_NAME];
GetPlayerName(playerid, str, sizeof(str));
format(str, sizeof(str), fmt_str, str, playerid, achievement_names[id]);
SendClientMessageToAll(-1, str);
}
Добавим команду, в которой будет видно, разблокировал ли игрок какое-либо достижение:
CMD:achs(playerid, params[]) // if(strcmp(cmdtext, "/achs", true, 5) == 0)
{
return ShowPlayerAchievementsDialog(playerid);
}
В конец мода, функцию показа диалога:
ShowPlayerAchievementsDialog(const playerid)
{
static const
fmt_str[] = "\
1. Вынос мозга [%s{FFFFFF}]\n\
2. Вершина мира [%s{FFFFFF}]\n\
3. Маньяк [%s{FFFFFF}]",
lock_str[][] =
{
{"{FF0000}Заблокировано"},
{"{00CC00}Разблокировано"}
};
new
str[(sizeof(fmt_str) - 2 + 21) * sizeof(achievement_names)];
format
(
str, sizeof(str), fmt_str,
lock_str[(achievement[playerid] & ACHIEVEMENT_BRAINFUCK) != 0],
lock_str[(achievement[playerid] & ACHIEVEMENT_TOP_OF_THE_WORLD) != 0],
lock_str[(achievement[playerid] & ACHIEVEMENT_MANIAC) != 0]
);
return ShowPlayerDialog(playerid, DIALOG_ACHIEVEMENTS, DIALOG_STYLE_LIST, "Список достижений", str, "Выбрать", "Закрыть");
}
Добавим распознавание диалогов, в public OnDialogResponse:
if(dialogid == DIALOG_ACHIEVEMENTS) // case DIALOG_ACHIEVEMENTS:
{
if(response == 0)
return 1;
static const
achievement_explans[][] =
{
"Цель: Убить 5 игроков в голову за один сеанс игры\nНаграда: {FF0000}$100000",
"Цель: Залезть на вершину горы чиллиад (это самая высокая точка на карте)\nНаграда: {FF0000}150 патронов к оружию Minigun",
"Цель: Убить 5 игроков лопастями вертолёта за один сеанс игры\nНаграда: {FF0000}500 единиц здоровья"
};
return ShowPlayerDialog(playerid, DIALOG_ACHIEVEMENTS_EXP, DIALOG_STYLE_MSGBOX, "Описание достижения", achievement_explans[listitem], "Закрыть", "Назад");
}
if(dialogid == DIALOG_ACHIEVEMENTS_EXP) // case DIALOG_ACHIEVEMENTS_EXP:
{
return (response == 0) ? (ShowPlayerAchievementsDialog(playerid)) : (1);
}
С "игровой" частью мы справились. Осталось сделать сохранение достижении игрока, добавим в любое место в моде (ко всем stock'ам):
stock SavePlayerAchievements(const playerid)
{
if(PlayerInfo[playerid][pLogged] == 0)
return;
// Здесь вы выставляете свою проверку на логин игрока,
// если игрок не залогинен его достижения не сохранятся
static const
acc_str[] = "AchievementProgress/%s.ini";
new
str[sizeof(acc_str) - 2 + MAX_PLAYER_NAME];
GetPlayerName(playerid, str, sizeof(str));
format(str, sizeof(str), acc_str, str);
new
File: file = fopen(str, io_write);
if(file == File: 0)
return;
valstr(str, achievement[playerid]);
fwrite(file, str);
fclose(file);
}
stock LoadPlayerAchievements(const playerid)
{
static const
acc_str[] = "AchievementProgress/%s.ini";
new
str[sizeof(acc_str) - 2 + MAX_PLAYER_NAME];
GetPlayerName(playerid, str, sizeof(str));
format(str, sizeof(str), acc_str, str);
if(fexist(str) == 0)
return;
new
File: file = fopen(str, io_read);
if(file == File: 0)
return;
fread(file, str);
achievement[playerid] = strval(str);
fclose(file);
}
Добавляем сохранение достижений в public OnPlayerDisconnect:
SavePlayerAchievements(playerid);
ach_progress[playerid]{0} = 0;
ach_progress[playerid]{1} = 0;
Добавляем загрузку достижений туда, где у вас загружается аккаунт (например OnPlayerLogin):
LoadPlayerAchievements(playerid);
В общем-то и всё.
http://ihost.pro-pawn.ru/image.php?di=PEIX
http://ihost.pro-pawn.ru/image.php?di=CH1C
http://ihost.pro-pawn.ru/image.php?di=Y7CX
Автор: L0ndl3m (https://pro-pawn.ru/member.php?2057-L0ndl3m)
Специально для: Pro-Pawn.Ru (http://pro-pawn.ru)
Копирование данной статьи без разрешения автора запрещено!
Попробуем сделать систему достижений из 3 штук.
Достижения
Вынос мозга
Вершина мира
Маньяк
В начало мода, создадим глобально ( то есть ко всем new )
const
MAX_ACHIEVEMENT_NAME = 13,
DIALOG_ACHIEVEMENTS = 512,
DIALOG_ACHIEVEMENTS_EXP = 1024;
static const
achievement_names[][MAX_ACHIEVEMENT_NAME] =
{
"Вынос мозга", "Вершина мира", "Маньяк"
};
new
achievement[MAX_PLAYERS],
ach_progress[MAX_PLAYERS][2 char];
#if !defined BODY_PART_TORSO
enum
{
BODY_PART_TORSO = 3,
BODY_PART_GROIN,
BODY_PART_LEFT_ARM,
BODY_PART_RIGHT_ARM,
BODY_PART_LEFT_LEG,
BODY_PART_RIGHT_LEG,
BODY_PART_HEAD
};
#endif
enum(<<= 1)
{
ACHIEVEMENT_BRAINFUCK = 1,
ACHIEVEMENT_TOP_OF_THE_WORLD,
ACHIEVEMENT_MANIAC
};
Начнём с первого достижения: Вынос мозга.
Суть достижения заключается в том, чтобы за один сеанс игры убить 5 человек в голову.
Реализация будет выглядеть так: добавляем в public OnPlayerGiveDamage
if(damagedid != INVALID_PLAYER_ID && bodypart == BODY_PART_HEAD)
{
SetPlayerHealth(damagedid, 0.0);
if(((achievement[playerid] & ACHIEVEMENT_BRAINFUCK) == 0) && ++ach_progress[playerid]{0} == 5)
{
UnlockPlayerAchievement(playerid, 0);
GivePlayerMoney(playerid, 100000);
SendClientMessage(playerid, -1, "Вы получили вознаграждение: {FF0000}$100000");
}
}
Реализация первого достижения готова.
Теперь начнём со второго достижения: Вершина мира
Суть достижения заключается в том, чтобы залезть на вершину горы чиллиад (это самая высокая точка на карте).
Попытаемся реализовать достижение:
Добавляем в public OnGameModeInit:
SetTimer("@__achievement_update", 1000, 1);
В любое место в моде, можно ко всем public'ам:
@__achievement_update();
@__achievement_update()
{
new
i = GetMaxPlayers();
do
{
--i;
if(IsPlayerConnected(i) && (0 == (achievement[i] & ACHIEVEMENT_TOP_OF_THE_WORLD)) && IsPlayerInRangeOfPoint(i, 2.0, -2432.7881, -1620.0902, 526.8478))
{
UnlockPlayerAchievement(i, 1);
GivePlayerWeapon(i, 38, 150);
SendClientMessage(i, -1, "Вы получили: {FF0000}150 патронов к оружию Minigun");
}
}
while(i);
}
Реализация второго достижения готова.
Приступим к последнему, третьему достижению: Маньяк.
Суть достижения заключается в том, чтобы убить пятерых игроков лопастями вертолёта.
Реализуем достижение, добавив в public OnPlayerDeath:
if(reason == 50 && killerid != INVALID_PLAYER_ID && ((achievement[killerid] & ACHIEVEMENT_MANIAC) == 0) && ++ach_progress[killerid]{1} == 5)
{
UnlockPlayerAchievement(killerid, 2);
SetPlayerHealth(killerid, 500.0);
SendClientMessage(killerid, -1, "Вы получили: {FF0000}500 единиц здоровья.");
}
Реализация трёх достижений готова.
Создадим отдельный сток, который будет показывать какой игрок разблокировал достижение, в любое место скрипта (ко всем stock'ам):
stock UnlockPlayerAchievement(const playerid, const id)
{
achievement[playerid] |= 1 << id;
static const
fmt_str[] = "• {FF0000}%s (%i){AAAADD} разблокировал достижение: {FF0000}%s";
new
str[sizeof(fmt_str) - 2 + MAX_PLAYER_NAME - 2 + 3 - 2 + MAX_ACHIEVEMENT_NAME];
GetPlayerName(playerid, str, sizeof(str));
format(str, sizeof(str), fmt_str, str, playerid, achievement_names[id]);
SendClientMessageToAll(-1, str);
}
Добавим команду, в которой будет видно, разблокировал ли игрок какое-либо достижение:
CMD:achs(playerid, params[]) // if(strcmp(cmdtext, "/achs", true, 5) == 0)
{
return ShowPlayerAchievementsDialog(playerid);
}
В конец мода, функцию показа диалога:
ShowPlayerAchievementsDialog(const playerid)
{
static const
fmt_str[] = "\
1. Вынос мозга [%s{FFFFFF}]\n\
2. Вершина мира [%s{FFFFFF}]\n\
3. Маньяк [%s{FFFFFF}]",
lock_str[][] =
{
{"{FF0000}Заблокировано"},
{"{00CC00}Разблокировано"}
};
new
str[(sizeof(fmt_str) - 2 + 21) * sizeof(achievement_names)];
format
(
str, sizeof(str), fmt_str,
lock_str[(achievement[playerid] & ACHIEVEMENT_BRAINFUCK) != 0],
lock_str[(achievement[playerid] & ACHIEVEMENT_TOP_OF_THE_WORLD) != 0],
lock_str[(achievement[playerid] & ACHIEVEMENT_MANIAC) != 0]
);
return ShowPlayerDialog(playerid, DIALOG_ACHIEVEMENTS, DIALOG_STYLE_LIST, "Список достижений", str, "Выбрать", "Закрыть");
}
Добавим распознавание диалогов, в public OnDialogResponse:
if(dialogid == DIALOG_ACHIEVEMENTS) // case DIALOG_ACHIEVEMENTS:
{
if(response == 0)
return 1;
static const
achievement_explans[][] =
{
"Цель: Убить 5 игроков в голову за один сеанс игры\nНаграда: {FF0000}$100000",
"Цель: Залезть на вершину горы чиллиад (это самая высокая точка на карте)\nНаграда: {FF0000}150 патронов к оружию Minigun",
"Цель: Убить 5 игроков лопастями вертолёта за один сеанс игры\nНаграда: {FF0000}500 единиц здоровья"
};
return ShowPlayerDialog(playerid, DIALOG_ACHIEVEMENTS_EXP, DIALOG_STYLE_MSGBOX, "Описание достижения", achievement_explans[listitem], "Закрыть", "Назад");
}
if(dialogid == DIALOG_ACHIEVEMENTS_EXP) // case DIALOG_ACHIEVEMENTS_EXP:
{
return (response == 0) ? (ShowPlayerAchievementsDialog(playerid)) : (1);
}
С "игровой" частью мы справились. Осталось сделать сохранение достижении игрока, добавим в любое место в моде (ко всем stock'ам):
stock SavePlayerAchievements(const playerid)
{
if(PlayerInfo[playerid][pLogged] == 0)
return;
// Здесь вы выставляете свою проверку на логин игрока,
// если игрок не залогинен его достижения не сохранятся
static const
acc_str[] = "AchievementProgress/%s.ini";
new
str[sizeof(acc_str) - 2 + MAX_PLAYER_NAME];
GetPlayerName(playerid, str, sizeof(str));
format(str, sizeof(str), acc_str, str);
new
File: file = fopen(str, io_write);
if(file == File: 0)
return;
valstr(str, achievement[playerid]);
fwrite(file, str);
fclose(file);
}
stock LoadPlayerAchievements(const playerid)
{
static const
acc_str[] = "AchievementProgress/%s.ini";
new
str[sizeof(acc_str) - 2 + MAX_PLAYER_NAME];
GetPlayerName(playerid, str, sizeof(str));
format(str, sizeof(str), acc_str, str);
if(fexist(str) == 0)
return;
new
File: file = fopen(str, io_read);
if(file == File: 0)
return;
fread(file, str);
achievement[playerid] = strval(str);
fclose(file);
}
Добавляем сохранение достижений в public OnPlayerDisconnect:
SavePlayerAchievements(playerid);
ach_progress[playerid]{0} = 0;
ach_progress[playerid]{1} = 0;
Добавляем загрузку достижений туда, где у вас загружается аккаунт (например OnPlayerLogin):
LoadPlayerAchievements(playerid);
В общем-то и всё.
http://ihost.pro-pawn.ru/image.php?di=PEIX
http://ihost.pro-pawn.ru/image.php?di=CH1C
http://ihost.pro-pawn.ru/image.php?di=Y7CX
Автор: L0ndl3m (https://pro-pawn.ru/member.php?2057-L0ndl3m)
Специально для: Pro-Pawn.Ru (http://pro-pawn.ru)
Копирование данной статьи без разрешения автора запрещено!