Форум Pawn-Wiki.Ru - Воплоти мечту в реальность!: Система Квестов (by: Saibot) - Форум Pawn-Wiki.Ru - Воплоти мечту в реальность!

Перейти к содержимому

  • (2 Страниц) +
  • 1
  • 2
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

[ Scr ][ All ]
Система Квестов (by: Saibot)
Оценка: -----

#1
Пользователь офлайн   Saibot 

  • Прохожий
  • Вставить ник
  • Раскрыть информацию
Уникальная система квестов

Обновление:

* Добавлена система личного рекорда прохождения квеста.
* Один тот самый квест, можно будет проходить много раз, только деньги Вы будете получать если побьете свой предыдущий рекорд.
* Сохранение квестов на SQLite.
* Переделаны диалоги ботов, теперь у них есть своя история.
* Заменил PVar`s на переменные.
* Добавлен новый квест Big Smoke и его трава
* Немного изменил Охота на Оленей, теперь олени обозначаются на радаре.
* Изменил название квестов
(Охота на Оленей - Джонни проклятые олени |Пьяный Тони - Старый друг Тони |Тачка для Виктора - Украсть тачку для Виктора)


Примечание:
Сохранение квестов сделано на SQLite. Б-Д Вы сможете скачать по ссылке ниже.

//----Ковсем переменным

new DB:SqlConnect;

const   QUEST_NAME_HUNTER = 0,
        QUEST_NAME_TONY = 1,
        QUEST_NAME_VICTOR = 2,
        QUEST_NAME_BIG_SMOKE = 3;

new quest_speed_record[MAX_PLAYERS],
    bool: quest_gps_chekpoint[MAX_PLAYERS char],
    bool: quest_get_mission[MAX_PLAYERS char],
    Text: quest_text_later_TD[3];

new quest_hunter_object_deer[MAX_PLAYERS],
    quest_hunter_kill_deer[MAX_PLAYERS char];

new quest_tony_pickup[2],
    quest_tony_vehicle[MAX_PLAYERS] = {-1, ...},
    bool: quest_tony_delivered_vehicle[MAX_PLAYERS char];

new Text: quest_victor_TD[MAX_PLAYERS][4],
    quest_victor_vehicle[MAX_PLAYERS] = {-1, ...},
    bool: quest_victor_delivered_vehicle[MAX_PLAYERS char],
    bool: quest_victor_break_car[MAX_PLAYERS char],
    quest_victor_press_button[MAX_PLAYERS],
    quest_victor_progress_button[MAX_PLAYERS char];

new quest_big_smoke_vehicle[MAX_PLAYERS],
    quest_big_smoke_object[MAX_PLAYERS],
    quest_big_smoke_pickup[MAX_PLAYERS][14],
    quest_big_smoke_get_medic[MAX_PLAYERS char];

enum e_qDialogID
{
    qDialogGPS = 1000,
    qDialogHunter = 1001,
    qDialogTony = 1002,
    qDialogVictor = 1003,
    qDialogBigSmoke = 1004
};

public OnGameModeInit()
{
    SqlConnect = db_open("quests.db");

    new quest_hunter_actor = CreateActor(158, -382.6907, -1422.1689, 25.7266, 257.3999);
    ApplyActorAnimation(quest_hunter_actor, !"", !"", 4.0, 1, 0, 0, 0, 0);

    Create3DTextLabel(!"Джонни", 0xC2A2DAFF, -382.6907, -1422.1689, 26.8266, 10.0, 0, -1);
    CreateDynamicCP(-381.9926, -1422.0990, 25.7266, 0.5, -1, -1, -1, 0.8);
    Create3DTextLabel(!"Нажмите L.Alt", 0xF5DEB3FF, -381.9926, -1422.0990, 25.7266, 10.0, 0, -1);

    new quest_tony_actor = CreateActor(3, 491.6751, -71.8107, 999.2266, 182.4833);
    ApplyActorAnimation(quest_tony_actor, !"BEACH", !"ParkSit_M_loop", 4.0, 1, 0, 0, 0, 0);
    SetActorVirtualWorld(quest_tony_actor, 70);

    Create3DTextLabel(!"Тони", 0xC2A2DAFF, 491.6751, -71.8107, 999.6266, 10.0, 70, -1);
    CreateDynamicCP(491.5851, -74.6300, 998.7578, 0.5, -1, -1, -1, 0.8);
    Create3DTextLabel(!"Нажмите L.Alt", 0xF5DEB3FF, 491.5851, -74.6300, 998.7578, 10.0, 70, -1);
    Create3DTextLabel(!"Quest #2", 0xC2A2DAFF, 2506.8147, 2120.5903, 10.8399, 10.0, 0, -1);

    quest_tony_pickup[0] = CreatePickup(19130, 23, 2506.8147, 2120.5903, 10.8399, 0);
    quest_tony_pickup[1] = CreatePickup(19130, 23, 501.9530, -67.7680, 998.7578, 70);

    new quest_victor_actor = CreateActor(106, 1054.8143, 2152.5227, 10.8203, 88.6209);
    ApplyActorAnimation(quest_victor_actor, !"SMOKING", !"M_smklean_loop", 4.0, 1, 0, 0, 0, 0);

    Create3DTextLabel(!"Виктор", 0xC2A2DAFF, 1054.8143, 2152.8227, 11.8203, 10.0, 0, -1);
    CreateDynamicCP(1054.0326, 2152.5652, 10.8203,  0.5, -1, -1, -1, 0.8);
    Create3DTextLabel(!"Нажмите L.Alt", 0xF5DEB3FF, 1054.0326, 2152.5652, 10.8203, 10.0, 0, -1);

    new quest_big_smoke_actor = CreateActor(149, 149.4932,-1954.3687,3.7734,111.9026);
    ApplyActorAnimation(quest_big_smoke_actor, !"SMOKING", !"M_smk_drag", 4.0, 1, 0, 0, 0, 0);

    Create3DTextLabel(!"Big Smoke", 0xC2A2DAFF, 149.4932, -1954.3687, 4.9734, 10.0, 0, -1);
    CreateDynamicCP(148.7361, -1954.7906, 3.7734, 0.5, -1, -1, -1, 0.8);
    Create3DTextLabel(!"Нажмите L.Alt", 0xF5DEB3FF, 148.7361, -1954.7906, 3.7734, 10.0, 0, -1);

//--TD
    quest_text_later_TD[0] = TextDrawCreate(641.583312, 1.500000, !"usebox");
    TextDrawLetterSize(quest_text_later_TD[0], 0.000000, 49.403495);
    TextDrawTextSize(quest_text_later_TD[0], -2.000000, 0.000000);
    TextDrawAlignment(quest_text_later_TD[0], 1);
    TextDrawColor(quest_text_later_TD[0], 0);
    TextDrawUseBox(quest_text_later_TD[0], true);
    TextDrawBoxColor(quest_text_later_TD[0], 255);
    TextDrawSetShadow(quest_text_later_TD[0], 0);
    TextDrawSetOutline(quest_text_later_TD[0], 0);
    TextDrawBackgroundColor(quest_text_later_TD[0], 255);
    TextDrawFont(quest_text_later_TD[0], 0);

    quest_text_later_TD[1] = TextDrawCreate(154.583343, 242.666778, !"LD_pool:ball");
    TextDrawLetterSize(quest_text_later_TD[1], 0.038333, 3.717221);
    TextDrawTextSize(quest_text_later_TD[1], 322.083007, 3.111139);
    TextDrawAlignment(quest_text_later_TD[1], 1);
    TextDrawColor(quest_text_later_TD[1], -1378294017);
    TextDrawUseBox(quest_text_later_TD[1], true);
    TextDrawBoxColor(quest_text_later_TD[1], 0);
    TextDrawSetShadow(quest_text_later_TD[1], 0);
    TextDrawSetOutline(quest_text_later_TD[1], 0);
    TextDrawFont(quest_text_later_TD[1], 4);

    quest_text_later_TD[2] = TextDrawCreate(194.166778, 201.703567, !"A few moments later");
    TextDrawLetterSize(quest_text_later_TD[2], 0.476667, 3.471851);
    TextDrawAlignment(quest_text_later_TD[2], 1);
    TextDrawColor(quest_text_later_TD[2], -1);
    TextDrawSetShadow(quest_text_later_TD[2], 0);
    TextDrawSetOutline(quest_text_later_TD[2], 10);
    TextDrawBackgroundColor(quest_text_later_TD[2], 51);
    TextDrawFont(quest_text_later_TD[2], 1);
    TextDrawSetProportional(quest_text_later_TD[2], 1);

    return 1;
}

public OnPlayerStateChange(playerid, newstate, oldstate)
{
    if(newstate == PLAYER_STATE_DRIVER)
    {
        if(GetPlayerVehicleID(playerid) == quest_tony_vehicle[playerid])
        {
            SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Отвезите машину Тони на СТО.");

            DisablePlayerRaceCheckpoint(playerid);
            SetPlayerRaceCheckpoint(playerid, 2, 720.1812,-473.7469,16.3437,0.0,0.0,0.0,4.0);
            quest_tony_delivered_vehicle{playerid} = true;
        }
    }
    if(newstate == PLAYER_STATE_DRIVER)
    {
        if(GetPlayerVehicleID(playerid) == quest_victor_vehicle[playerid])
        {
            DisablePlayerRaceCheckpoint(playerid);
            TogglePlayerControllable(playerid, 0);
            quest_victor_break_car{playerid} = true;
            QuestVictorRandomButton(playerid);

            TextDrawTextSize(quest_victor_TD[playerid][2], 1.0, 19.185184);
            SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Взломайте замок зажигания.");

            TextDrawShowForPlayer(playerid, quest_victor_TD[playerid][0]);
            TextDrawShowForPlayer(playerid, quest_victor_TD[playerid][1]);
            TextDrawShowForPlayer(playerid, quest_victor_TD[playerid][2]);
            TextDrawShowForPlayer(playerid, quest_victor_TD[playerid][3]);
        }
    }
    return 1;
}

public OnPlayerPickUpPickup(playerid,pickupid)
{
    if(pickupid == quest_tony_pickup[0])
    {
        SetPlayerInterior(playerid, 11);
        SetPlayerVirtualWorld(playerid, 70);
        SetPlayerPos(playerid, 502.2196, -69.7190, 998.7578);
        SetPlayerFacingAngle(playerid, 187.6651);
        SetCameraBehindPlayer(playerid);
    }
    if(pickupid == quest_tony_pickup[1])
    {
        SetPlayerInterior(playerid, 0);
        SetPlayerVirtualWorld(playerid, 0);
          SetPlayerPos(playerid, 2506.7793,2122.6790,10.8404);
        SetPlayerFacingAngle(playerid, 358.7466);
        SetCameraBehindPlayer(playerid);
    }
    if(quest_get_mission{playerid} == true && pickupid >= quest_big_smoke_pickup[playerid][0] && pickupid <= quest_big_smoke_pickup[playerid][13])
    {
        if(++ quest_big_smoke_get_medic{playerid} == 14)
        {
            SendClientMessage(playerid, 0xF5DEB3FF, "[Квест]: Собрано аптечек 14/14.");

            DestroyObject(quest_big_smoke_object[playerid]);
            DestroyVehicle(quest_tony_vehicle[playerid]);

            quest_big_smoke_vehicle[playerid] = -1;
            quest_big_smoke_object[playerid] = -1;
            quest_get_mission{playerid} = false;
            quest_big_smoke_get_medic{playerid} = 0;

            SetPlayerPos(playerid, 362.6274,-1890.5061,1.9069);
            SetPlayerFacingAngle(playerid, 110.7732);
            SetPlayerVirtualWorld(playerid, 0);
            SetCameraBehindPlayer(playerid);
            RemovePlayerMapIcon(playerid, 13);

            QuestGetSpeedRecord(playerid, QUEST_NAME_BIG_SMOKE);
        }
        else
        {
            new fmt_str[32];
            format(fmt_str, sizeof(fmt_str), "[Квест]: Собрано аптечек %d/14.", quest_big_smoke_get_medic{playerid});
            SendClientMessage(playerid, 0xF5DEB3FF, fmt_str);
            RemovePlayerMapIcon(playerid, quest_big_smoke_get_medic{playerid}-1);
        }
    }
    return 1;
}

public OnPlayerConnect(playerid)
{
//Quest Victor
    quest_victor_TD[playerid][0] = TextDrawCreate(416.166687, 167.425979, !"usebox");
    TextDrawLetterSize(quest_victor_TD[playerid][0], 0.000000, 2.218311);
    TextDrawTextSize(quest_victor_TD[playerid][0], 211.749969, 0.000000);
    TextDrawBoxColor(quest_victor_TD[playerid][0], 133);
    TextDrawUseBox(quest_victor_TD[playerid][0], true);

    quest_victor_TD[playerid][1] = TextDrawCreate(415.333404, 168.462966, !"usebox");
    TextDrawLetterSize(quest_victor_TD[playerid][1], 0.000000, 1.968311);
    TextDrawTextSize(quest_victor_TD[playerid][1], 212.999923, 0.000000);
    TextDrawBoxColor(quest_victor_TD[playerid][1], 862348901);
    TextDrawUseBox(quest_victor_TD[playerid][1], true);

    quest_victor_TD[playerid][2] = TextDrawCreate(214.999954, 167.999984, !"LD_SPAC:white");
    TextDrawLetterSize(quest_victor_TD[playerid][2], 0.000000, 0.000000);
    TextDrawTextSize(quest_victor_TD[playerid][2], 198.333312, 19.185184);
    TextDrawAlignment(quest_victor_TD[playerid][2], 1);
    TextDrawColor(quest_victor_TD[playerid][2], 862349514);
    TextDrawSetShadow(quest_victor_TD[playerid][2], 0);
    TextDrawSetOutline(quest_victor_TD[playerid][2], 0);
    TextDrawFont(quest_victor_TD[playerid][2], 4);

    quest_victor_TD[playerid][3] = TextDrawCreate(312.083312, 143.629562, !"PRESS Y");
    TextDrawLetterSize(quest_victor_TD[playerid][3], 0.582500, 2.372594);
    TextDrawAlignment(quest_victor_TD[playerid][3], 2);
    TextDrawColor(quest_victor_TD[playerid][3], -1);
    TextDrawSetShadow(quest_victor_TD[playerid][3], 0);
    TextDrawSetOutline(quest_victor_TD[playerid][3], 1);
    TextDrawBackgroundColor(quest_victor_TD[playerid][3], 255);
    TextDrawFont(quest_victor_TD[playerid][3], 2);
    TextDrawSetProportional(quest_victor_TD[playerid][3], 1);
    return 1;
}

public OnVehicleDeath(vehicleid, killerid)
{
    if(quest_tony_vehicle[killerid] == vehicleid)
    {
        DestroyVehicle(vehicleid);
        DisablePlayerRaceCheckpoint(killerid);

        quest_tony_vehicle[killerid] = -1;
        quest_tony_delivered_vehicle{killerid} = false;
        quest_get_mission{killerid} = false;
        quest_speed_record[killerid] = 0;
        SendClientMessage(killerid, 0xF5DEB3FF, !"[Квест]: Миссия провалена, Вы разбили машину Тони!");
    }
    if(quest_victor_vehicle[killerid] == vehicleid && quest_victor_vehicle[killerid])
    {
        DestroyVehicle(vehicleid);
        DisablePlayerRaceCheckpoint(killerid);
        quest_victor_vehicle[killerid] = -1;
        quest_victor_delivered_vehicle{killerid} = false;
        quest_get_mission{killerid} = false;
        quest_speed_record[killerid] = 0;
        SendClientMessage(killerid, 0xF5DEB3FF, !"[Квест]: Миссия провалена, Вы разбили ворованною машину для Виктора!");
    }
    return 1;
}

public OnPlayerExitVehicle(playerid, vehicleid)
{
    if(vehicleid == quest_big_smoke_vehicle[playerid])
    {
        ClearAnimations(playerid, 1);
        PutPlayerInVehicle(playerid, vehicleid, 0);
    }
    return 1;
}

public OnPlayerEnterRaceCheckpoint(playerid)
{
    if(quest_gps_chekpoint{playerid} == true)
    {
        quest_gps_chekpoint{playerid} = false;
        DisablePlayerRaceCheckpoint(playerid);
        SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Вы прибыли до места назначения.");
    }
    if(quest_tony_delivered_vehicle{playerid} == true)
    {
        SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Вы успешно доставили машину Тони на СТО.");
        DisablePlayerRaceCheckpoint(playerid);
        DestroyVehicle(quest_tony_vehicle[playerid]);

        QuestGetSpeedRecord(playerid, QUEST_NAME_TONY);
        SetPlayerDrunkLevel(playerid, 0);

        quest_tony_vehicle[playerid] = -1;
        quest_tony_delivered_vehicle{playerid} = false;
        quest_get_mission{playerid} = false;
    }
    if(quest_victor_delivered_vehicle{playerid} == true)
    {
        SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Вы успешно доставил ворованною машину Виктору.");
        DisablePlayerRaceCheckpoint(playerid);
        DestroyVehicle(quest_victor_vehicle[playerid]);

        QuestGetSpeedRecord(playerid, QUEST_NAME_VICTOR);
        quest_victor_vehicle[playerid] = -1;
        quest_victor_delivered_vehicle{playerid} = false;
        quest_get_mission{playerid} = false;
    }
    return 1;
}

public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
    if(newkeys == KEY_WALK)
    {
        if(IsPlayerInRangeOfPoint(playerid, 2.0, -381.9890,-1422.1569,25.7266))
        {
            if(quest_get_mission{playerid} == true)
                return SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Вы уже начали Quest");

            ShowPlayerDialog(playerid, qDialogHunter, DIALOG_STYLE_MSGBOX,
                !"Квест",
                !"{ffffff}Джонни\t{F5DEB3}-\tЭээ, молодой человек, что ты делаешь у меня на ферме?\n\n\
                {ffffff}Игрок\t\t{F5DEB3}-\tЯ просто проходил мимо, думаю... зайду, может Вам нужна какая-то помощь?\n\
                {F5DEB3}\t\t\tЯ бы её сделал, а Вы бы мне заплатили, мне как раз нужны деньги.\n\n\
                 {ffffff}Джонни\t{F5DEB3}-\tХмм... Ну, есть тут у меня одна проблема.\n\
                {F5DEB3}\t\t\tПроклятые оленьи, которые портят мой урожай.\n\
                {F5DEB3}\t\t\tТы умеешь стрелять?\n\n\
                {ffffff}Игрок\t\t{F5DEB3}-\tДа, я умею стрелять.\n\
                {F5DEB3}\t\t\tЯ уже бывал на охоте, как раз охотились на оленя.\n\n\
                {ffffff}Джонни\t{F5DEB3}-\tЗамечательно, тогда сможешь их убить, что бы они не портили мой урожай?",
                !"Принять", !"Отказаться"
            );
        }
        if(IsPlayerInRangeOfPoint(playerid, 2.0, 491.5851,-74.6300,998.7578))
        {
            if(quest_get_mission{playerid} == true)
                return SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Ты уже начал Quest");

            ShowPlayerDialog(playerid, qDialogTony, DIALOG_STYLE_MSGBOX,
                !"Квест",
                !"{ffffff}Тони\t{F5DEB3}-\tВот это да...\n\
                {F5DEB3}\t\tЗдравствуй дружище! Сколько лет сколько зим!\n\n\
                {ffffff}Игрок\t{F5DEB3}-\tЗдравствуй дружище! Да... давненько мы уже не виделись.\n\n\
                {ffffff}Тони\t{F5DEB3}-\tИ не говори, люди столько не живут.\n\
                {F5DEB3}\t\tКак тебе мой новый Бар?\n\n\
                {ffffff}Игрок\t{F5DEB3}-\tЗамечательный, слышал, что очень популярный в этом районе.\n\
                {F5DEB3}\t\tЖаль, что раньше сюда не заходил.\n\n\
                {ffffff}Тони\t{F5DEB3}-\tХах... Ты бы опустошил бы все винные запасы.\n\
                {F5DEB3}\t\tСадись дружище, выпьем, я угощаю.",
                !"Принять", !"Отказаться"
            );
        }
        if(IsPlayerInRangeOfPoint(playerid, 2.0, 1053.7129, 2152.6824, 10.8203))
        {
            if(quest_get_mission{playerid} == true)
                return SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Ты уже начал Quest");

            ShowPlayerDialog(playerid, qDialogVictor, DIALOG_STYLE_MSGBOX,
                !"Квест",
                !"{ffffff}Виктор\t{F5DEB3}-\tWhat's up, bro?\n\n\
                {ffffff}Игрок\t{F5DEB3}-\tWhat's up, bro?\n\n\
                {ffffff}Виктор\t{F5DEB3}-\tBro! Я бы не хотел тебя втягивать в это, но мне нужна твоя помощь.\n\n\
                {ffffff}Игрок\t{F5DEB3}-\tBro! Что стрехлось?\n\n\
                {ffffff}Виктор\t{F5DEB3}-\tМесяц назад копы накрыли мой наркопритон.\n\
                {F5DEB3}\t\tПоловину денег, которые я с него получал, я отдавал большим боссам за долги.\n\
                {F5DEB3}\t\tТеперь я на нуле, и торчу большую сумму.\n\
                {F5DEB3}\t\tЕсли я не верну долг через 3 дня, меня убьют.\n\n\
                {ffffff}Игрок\t{F5DEB3}-\tBro! Чем я могу тебя помочь?\n\n\
                {ffffff}Виктор\t{F5DEB3}-\tЯ тут присмотрел одну дорогую тачку.\n\
                {F5DEB3}\t\tBro! Если бы ты смог ее украсть для меня, я бы этой тачкой рассчитался за долги, поможешь?",
                !"Принять", !"Отказаться"
            );
        }
        if(IsPlayerInRangeOfPoint(playerid, 2.0, 148.7361, -1954.7906, 3.7734))
        {
            if(quest_get_mission{playerid} == true)
                return SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Ты уже начал Quest");

            ShowPlayerDialog(playerid, qDialogBigSmoke, DIALOG_STYLE_MSGBOX,
                !"Квест",
                !"\
                {ffffff}Big Smoke{F5DEB3}\t-\tOh My God!!!\n\
                {F5DEB3}\t\t\tЭто лучшая травка, которую я пробовал.\n\n\
                {ffffff}Игрок{F5DEB3}\t\t-\tСколько тебя знаю, но, еще без косяка не видел тебя.\n\n\
                {ffffff}Big Smoke{F5DEB3}\t-\tХа-ха, и наверное не увидишь, я с косяком - одно целое, ха-ха.\n\
                {F5DEB3}\t\t\tХочешь попробовать?\n\n\
                {ffffff}Игрок\t\t{F5DEB3}-\tНет, спасибо, я еще жить хочу.\n\n\
                {ffffff}Big Smoke{F5DEB3}\t-\tOh Boy! Да ты попробуй один раз, эта шмаль того стоит!\n\
                {F5DEB3}\t\t\tПод этой травкой, я себя ощущал Большой Белой Акулой, я бы назвал эту шмаль Shark Drug.\n\
                {F5DEB3}\t\t\tПопробуй, я даже заплачу тебя за это деньги.\n\n\
                {ffffff}Игрок{F5DEB3}\t\t-\tХмм... Говоришь Акулой? Ну, думаю один раз можно.\n\n\
                {ffffff}Big Smoke{F5DEB3}\t-\tВот держи, как раз осталось для тебя.",
                !"Принять", !"Отказаться"
            );
        }
    }
    if(quest_victor_break_car{playerid} == true)
    {
        if(newkeys == quest_victor_press_button[playerid])
        {
            TextDrawTextSize(quest_victor_TD[playerid][2], ++ quest_victor_progress_button{playerid} *15, 19.185184);
            TextDrawShowForPlayer(playerid, quest_victor_TD[playerid][2]);
            QuestVictorRandomButton(playerid);

            if(quest_victor_progress_button{playerid} >= 14)
            {
                SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Отвезите ворованную машину к Виктору.");
                SetPlayerRaceCheckpoint(playerid, 2, 1050.9625, 2134.3640, 10.8203, 0.0, 0.0, 0.0, 4.0);
                SetVehicleParamsEx(GetPlayerVehicleID(playerid), 1, 0, 0, 0, 0, 0, 0 );

                TogglePlayerControllable(playerid, 1);

                quest_victor_press_button[playerid] = 0;
                quest_victor_progress_button{playerid} = 0;
                quest_victor_delivered_vehicle{playerid} = true;
                quest_victor_break_car{playerid} = false;

                TextDrawHideForPlayer(playerid, quest_victor_TD[playerid][0]);
                TextDrawHideForPlayer(playerid, quest_victor_TD[playerid][1]);
                TextDrawHideForPlayer(playerid, quest_victor_TD[playerid][2]);
                TextDrawHideForPlayer(playerid, quest_victor_TD[playerid][3]);
            }
        }
    }
    return 1;
}

public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)
{
    if(quest_get_mission{playerid} == true && hittype == BULLET_HIT_TYPE_PLAYER_OBJECT && hitid == quest_hunter_object_deer[playerid])
    {
        DestroyPlayerObject(playerid, quest_hunter_object_deer[playerid]);

        if(++ quest_hunter_kill_deer{playerid} == 5)
        {
            SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Убито Оленей 5/5.");

            QuestGetSpeedRecord(playerid, QUEST_NAME_HUNTER);
            ResetPlayerWeapons(playerid);
            quest_get_mission{playerid} = false;
            quest_hunter_kill_deer{playerid} = 0;
            quest_hunter_object_deer[playerid] = 0;
            RemovePlayerMapIcon(playerid, 0);
        }
        else
        {
            switch(quest_hunter_kill_deer{playerid})
            {
                case 1:
                {
                    quest_hunter_object_deer[playerid] = CreatePlayerObject(playerid, 19315, -599.41, -1496.85, 11.91, 0.00, 0.00, 0.00);
                    SetPlayerMapIcon(playerid, 0, -599.41, -1496.85, 11.91, 19, 0, MAPICON_GLOBAL);
                }
                case 2:
                {
                    quest_hunter_object_deer[playerid] = CreatePlayerObject(playerid, 19315, -271.72, -1187.65, 12.60, 0.00, 0.00, 0.00);
                    SetPlayerMapIcon(playerid, 0, -271.72, -1187.65, 12.60, 19, 0, MAPICON_GLOBAL);
                }
                case 3:
                {
                    quest_hunter_object_deer[playerid] = CreatePlayerObject(playerid, 19315, -315.88, -1435.65, 14.50, 0.00, 0.00, 0.00);
                    SetPlayerMapIcon(playerid, 0, -315.88, -1435.65, 14.50, 19, 0, MAPICON_GLOBAL);
                }
                case 4:
                {
                    quest_hunter_object_deer[playerid] = CreatePlayerObject(playerid, 19315, -380.89, -1736.42, 12.30, 0.00, 0.00, 0.00);
                    SetPlayerMapIcon(playerid, 0, -380.89, -1736.42, 12.30, 19, 0, MAPICON_GLOBAL);
                }
            }
            new fmt_str[30];
            format(fmt_str, sizeof(fmt_str), "[Квест]: Убито Оленей %d/5.", quest_hunter_kill_deer{playerid});
            SendClientMessage(playerid, 0xF5DEB3FF, fmt_str);
        }

    }
    return true;
}

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    switch(dialogid)
    {
        case qDialogGPS:
        {
            if(!response) return true;

            switch(listitem)
            {
                case 0: SetPlayerRaceCheckpoint(playerid,2, -382.6907, -1422.1689, 26.2266, 0.0, 0.0, 0.0, 6.0);
                case 1: SetPlayerRaceCheckpoint(playerid, 2, 2506.8147, 2120.5903, 10.8399, 0.0, 0.0, 0.0, 6.0);
                case 2: SetPlayerRaceCheckpoint(playerid, 2, 1054.0326, 2152.5652, 10.8203, 0.0, 0.0, 0.0, 6.0);
                case 3: SetPlayerRaceCheckpoint(playerid, 2, 148.7361, -1954.7906, 3.7734, 0.0, 0.0, 0.0, 6.0);
            }
            quest_gps_chekpoint{playerid} = true;
            SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Место расположения Quest`a расположено на мини карте!");
        }
        case qDialogHunter:
        {
            if(!response) return true;

            GivePlayerWeapon(playerid, 33, 10);
            quest_get_mission{playerid} = true;

            quest_hunter_object_deer[playerid] = CreatePlayerObject(playerid,19315, -550.15, -1860.14, 17.00, 0.00, 0.00, 0.00);
            SetPlayerMapIcon(playerid, 0, -550.15, -1860.14, 17.00, 19, 0, MAPICON_GLOBAL);

            SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Убейте 5 оленей, оружие Вам выдано!");

            SetTimerEx(!"@_QuestRecordTimer", 1000, false, !"d", playerid);
        }
        case qDialogTony:
        {
            if(!response) return true;

            SetPlayerVirtualWorld(playerid, 99);

            TextDrawShowForPlayer(playerid, quest_text_later_TD[0]);
            TextDrawShowForPlayer(playerid, quest_text_later_TD[1]);
            TextDrawShowForPlayer(playerid, quest_text_later_TD[2]);


            quest_get_mission{playerid} = true;
            TogglePlayerControllable(playerid, 0);
            SetTimerEx(!"@_QuestTonyTimer", 5000, false, !"d", playerid);
        }
        case qDialogVictor:
        {
            if(!response) return true;

            quest_get_mission{playerid} = true;
            quest_victor_vehicle[playerid] = CreateVehicle(545, 2823.9351, 939.0333, 10.7500, 357.2911, -1, -1, 80);

            SetPlayerRaceCheckpoint(playerid, 2, 2823.9351, 939.0333, 10.7500, 0.0, 0.0, 0.0, 2.0);
            SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Машина которая нужна Виктору обозначена - на радаре!");
            SetTimerEx(!"@_QuestRecordTimer", 1000, false, !"d", playerid);
        }
        case qDialogBigSmoke:
        {
            if(!response) return true;
            SetPlayerVirtualWorld(playerid, 99);

            quest_get_mission{playerid} = true;

            TextDrawShowForPlayer(playerid, quest_text_later_TD[0]);
            TextDrawShowForPlayer(playerid, quest_text_later_TD[1]);
            TextDrawShowForPlayer(playerid, quest_text_later_TD[2]);

            quest_get_mission{playerid} = true;
            TogglePlayerControllable(playerid, 0);
            SetTimerEx(!"@_QuestBigSmokeTimer", 5000, false, !"d", playerid);
        }
    }
    return 1;
}

CMD:quest(playerid)
{
    new fmt_str[220 + 4*4],
        player_name[MAX_PLAYER_NAME];

    GetPlayerName(playerid, player_name, MAX_PLAYER_NAME);

    format(fmt_str, sizeof(fmt_str), "SELECT * FROM `quests` WHERE `player_name` = '%s'",
        player_name
    );
    new DBResult: dbResult = db_query(SqlConnect, fmt_str);

    new record_hunter,
        record_tony,
        record_victor,
        record_big_smoke;

    if(db_num_rows(dbResult))
    {
        record_hunter = db_get_field_assoc_int(dbResult, "player_record_hunter");
        record_tony = db_get_field_assoc_int(dbResult, "player_record_tony");
        record_victor = db_get_field_assoc_int(dbResult, "player_record_victor");
        record_big_smoke = db_get_field_assoc_int(dbResult, "player_record_big_smoke");
    }
    db_free_result(dbResult);

    format(fmt_str, sizeof(fmt_str),
        "Название:\tВремя прохождения:\n\
        {eee6a3}#1 Джонни и проклятые олени\t{ffffff}%s\n\
        {eee6a3}#2 Старый друг Тони\t{ffffff}%s\n\
        {eee6a3}#3 Украсть тачку для Виктора\t{ffffff}%s\n\
        {eee6a3}#4 Big Smoke и его травка\t{ffffff}%s",
        QuestConvectorTime(record_hunter),
        QuestConvectorTime(record_tony),
        QuestConvectorTime(record_victor),
        QuestConvectorTime(record_big_smoke)
    );
    ShowPlayerDialog(playerid, qDialogGPS, DIALOG_STYLE_TABLIST_HEADERS, "Quest", fmt_str, !"Выбрать", !"Выход");
    return true;
}

stock QuestVictorRandomButton(playerid)
{
    new str_fmt[10];
    static const press_button[2] = {65536, 131072};
    static const name_button[2][11] = {!"PRESS ~r~Y", !"PRESS ~g~N"};

    new random_button = random(2);
    strcat(str_fmt, name_button[random_button]);
    TextDrawSetString(quest_victor_TD[playerid][3], str_fmt);

    quest_victor_press_button[playerid] = press_button[random_button];
    return true;
}
stock QuestConvectorTime(const time)
{
    new fmt_str[11];
    format(fmt_str,sizeof(fmt_str),"%02d:%02d", time / 60, time % 60);
    return fmt_str;
}

@_QuestRecordTimer(playerid);
@_QuestRecordTimer(playerid)
{
    GameTextForPlayer(playerid, QuestConvectorTime(++ quest_speed_record[playerid]), 1000, 6);

    if(quest_get_mission{playerid} == true)
        SetTimerEx("@_QuestRecordTimer", 1000, false, "d", playerid);
}

@_QuestBigSmokeTimer(playerid);
@_QuestBigSmokeTimer(playerid)
{
    if(IsPlayerConnected(playerid))
    {
        TextDrawHideForPlayer(playerid, quest_text_later_TD[0]);
        TextDrawHideForPlayer(playerid, quest_text_later_TD[1]);
        TextDrawHideForPlayer(playerid, quest_text_later_TD[2]);

        ShowPlayerDialog(playerid, 0000, DIALOG_STYLE_MSGBOX,
            !"Квест",
            !"{ffffff}Игрок\t\t{F5DEB3}-\tBig Smoke, черт возьми, что со мной и где я?\n\n\
            {ffffff}Big Smoke\t{F5DEB3}-\tBro! Ты в раю.\n\n\
            {ffffff}Игрок\t\t{F5DEB3}-\tЭто не смешно, как мне прийти в себя?\n\n\
            {ffffff}Big Smoke{F5DEB3}\t-\tСобери все Аптечки и тебя отпустит.\n\
            {F5DEB3}\t\t\tМеня отпустило после этого.",
            !"Закрыть", !""
        );
        quest_big_smoke_object[playerid] = CreateObject(1608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
        quest_big_smoke_vehicle[playerid] = CreateVehicle(473, 592.5674,-2568.9495,6.5056,14.7267, -1, -1, -1);
        AttachObjectToVehicle(quest_big_smoke_object[playerid], quest_big_smoke_vehicle[playerid], 0.0,0.0,0.0,0.0,0.0,0.0);


        SetVehicleVirtualWorld(quest_big_smoke_vehicle[playerid], 99) ;
        PutPlayerInVehicle(playerid, quest_big_smoke_vehicle[playerid], 0);
        LinkVehicleToInterior(quest_big_smoke_vehicle[playerid], 1);

        TogglePlayerControllable(playerid, 1);

        static const Float: position[14][3] =
        {
            {639.1937, -2520.2842, 0.7717},
            {644.7472, -2432.3411, 0.6610},
            {675.8980, -2337.6265, 0.5165},
            {801.0114, -2256.0903, 0.5034},
            {841.3019, -2274.4890, 0.2422},
            {880.5114, -2359.3933, 0.1886},
            {932.5243, -2457.9888, 0.7591},
            {1025.3154, -2541.9641, 0.6807},
            {1023.4229, -2643.5759, -0.2621},
            {1022.7764, -2733.8777, 0.1372},
            {1035.1910, -2800.1226, -0.2826},
            {919.9339, -2714.0374, 0.1137},
            {824.9225, -2682.2432, 0.1222},
            {767.5128, -2662.1121, -0.9035}
        };
        for(new i = 0; i < 14; i ++)
        {
            quest_big_smoke_pickup[playerid][i] = CreatePickup(11738, 14, position[i][0], position[i][1], position[i][2], 99);
            SetPlayerMapIcon(playerid, i, position[i][0], position[i][1], position[i][2], 22, 0, MAPICON_GLOBAL);
        }
        SetTimerEx(!"@_QuestRecordTimer", 1000, false, !"d", playerid);
        SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Собери все Аптечки.");
    }
    return true;
}

@_QuestTonyTimer(playerid);
@_QuestTonyTimer(playerid)
{
    if(IsPlayerConnected(playerid))
    {
        TextDrawHideForPlayer(playerid, quest_text_later_TD[0]);
        TextDrawHideForPlayer(playerid, quest_text_later_TD[1]);
        TextDrawHideForPlayer(playerid, quest_text_later_TD[2]);

        ShowPlayerDialog(playerid, 0000, DIALOG_STYLE_MSGBOX,
            !"Квест",
            !"{ffffff}Тони\t{F5DEB3}-\tДружище, вот это мы выпили, я даже встать не могу. (Телефонный звонок)\n\
            {F5DEB3}\t-\tДа, я слушаю? Ох черт забирай, спасибо, что напомнили.\n\n\
            {ffffff}Игрок\t{F5DEB3}-\tЧто случилось?\n\n\
            {ffffff}Тони\t{F5DEB3}-\tЯ забыл, что мне нужно было сегодня отвезти машину на СТО.\n\
            {F5DEB3}\t-\tНо, я уже даже встать не могу.\n\n\
            {ffffff}Игрок\t{F5DEB3}-\tЯ, еще не настолько пьян, могу это сделать вместо тебя.\n\n\
            {ffffff}Тони\t{F5DEB3}-\tДружище, ты меня выручил, держи ключи.",
            !"Закрыть", !""
        );
        SetTimerEx(!"@_QuestRecordTimer", 1000, false, !"d", playerid);
        quest_tony_vehicle[playerid] = CreateVehicle(533, 2507.6040, 2131.5884, 10.6719, 88.6859, -1, -1, 0);
        SetPlayerRaceCheckpoint(playerid, 2, 2507.6040, 2131.5884, 10.6719, 0.0, 0.0, 0.0, 2.0);
        SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Машина Тони находится на улице.");
        TogglePlayerControllable(playerid, 1);
        SetPlayerVirtualWorld(playerid, 70);
        SetPlayerDrunkLevel(playerid, 10000);
    }
    return true;
}
stock QuestGetSpeedRecord(playerid, const questid)
{
    new fmt_str[58 + MAX_PLAYER_NAME + 30 + 11],
        player_name[MAX_PLAYER_NAME];

    GetPlayerName(playerid, player_name, MAX_PLAYER_NAME);

    format(fmt_str, sizeof(fmt_str), "SELECT * FROM `quests` WHERE `player_name` = '%s'",
        player_name
    );
    new DBResult: dbResult = db_query(SqlConnect, fmt_str);
    new speed_record[4];

    if(db_num_rows(dbResult) == 0)
    {
        format(fmt_str, sizeof(fmt_str), "INSERT INTO `quests` (`player_name`) VALUES ('%s')",
            player_name
        );
        db_free_result(db_query(SqlConnect, fmt_str));
    }
    else
    {
        speed_record[QUEST_NAME_HUNTER] = db_get_field_assoc_int(dbResult, "player_record_hunter");
        speed_record[QUEST_NAME_TONY] = db_get_field_assoc_int(dbResult, "player_record_tony");
        speed_record[QUEST_NAME_VICTOR] = db_get_field_assoc_int(dbResult, "player_record_victor");
        speed_record[QUEST_NAME_BIG_SMOKE] = db_get_field_assoc_int(dbResult, "player_record_big_smoke");
    }
    new quest_name[30];
    switch(questid)
    {
        case QUEST_NAME_HUNTER: quest_name = "player_record_hunter";
        case QUEST_NAME_TONY: quest_name = "player_record_tony";
        case QUEST_NAME_VICTOR: quest_name = "player_record_victor";
        case QUEST_NAME_BIG_SMOKE: quest_name = "player_record_big_smoke";
    }
    db_free_result(dbResult);

    if(quest_speed_record[playerid] < speed_record[questid] || speed_record[questid] == 0)
    {
        format(fmt_str, sizeof(fmt_str), "UPDATE `quests` SET `%s` = '%d' WHERE `player_name` = '%s'",
            quest_name,
            quest_speed_record[playerid],
            player_name
        );
        db_free_result(db_query(SqlConnect, fmt_str));

        QuestGetPlayerMoney(playerid, questid);
        SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Вы установил свой рекорд по прохождению данного Квеста.");


    }
    else SendClientMessage(playerid, 0xF5DEB3FF, !"[Квест]: Вы не смогли побить свой предыдущий рекорд.");
}
stock QuestGetPlayerMoney(playerid, const questid)
{
    switch(questid)
    {
        case QUEST_NAME_HUNTER:
        {
            ShowPlayerDialog(playerid, 0000, DIALOG_STYLE_MSGBOX,
                !"Квест",
                !"{ffffff}Телефонный звонок...\t\tДжонни \t>>>>>\tИгрок\n\n\
                {ffffff}Джонни\t{F5DEB3}-\tСынок, я слышал пять выстрелов, неужели ты убил этих проклятых оленей?\n\n\
                {ffffff}Игрок\t\t{F5DEB3}-\tНе скажу, что это было легко, но я это сделал.\n\n\
                {ffffff}Джонни\t{F5DEB3}-\tНаконец то, мой урожай не будут страдать из-а них\n\
                {F5DEB3}\t\t\tДеньги я перечислил тебе на счет, спасибо большое!\n",
                !"Закрыть",!""
            );
        }
        case QUEST_NAME_TONY:
        {
            ShowPlayerDialog(playerid, 0000, DIALOG_STYLE_MSGBOX,
                !"Квест",
                !"{ffffff}Телефонный звонок...\t\tИгрок\t>>>>>\tТони\
n\n\
                {ffffff}Игрок\t{F5DEB3}-\tТони, я отвез твою машина на СТО.\n\n\
                {ffffff}Тони\t{F5DEB3}-\tДружище, большое тебе спасибо.\n\
                {F5DEB3}\t\tКак говорится, мой бар - твой бар.\n\
                {F5DEB3}\t\tБуду рад видеть тебя в моем баре снова.\n\
                {F5DEB3}\t\tДеньги я перечислил тебя на счет, спасибо, еще раз.",
                !"Закрыть",!""
            );
        }
        case QUEST_NAME_VICTOR:
        {
            ShowPlayerDialog(playerid, 0000, DIALOG_STYLE_MSGBOX,
                !"Квест",
                !"{ffffff}Телефонный звонок...\t\tИгрок\t>>>>>\tВиктор\
n\n\
                {ffffff}Игрок\t{F5DEB3}-\tВиктор, я пригнал машину, которую ты хотел.\n\n\
                {ffffff}Виктор\t{F5DEB3}-\tBro! Ты просто спас меня.\n\
                {ffffff}\t{F5DEB3}-\tТеперь я смогу рассчитаться с долгами.\n\
                {F5DEB3}\t\tДеньги я перечислил тебя на счет, спасибо большое.",
                !"Закрыть",!""
            );
        }
        case QUEST_NAME_BIG_SMOKE:
        {
            ShowPlayerDialog(playerid, 0000, DIALOG_STYLE_MSGBOX,
                !"Квест",
                !"{ffffff}Телефонный звонок...\t\tBig Smoke\t>>>>>\tИгрок\n\n\
                {ffffff}Big Smoke{F5DEB3}\t-\tХах, я же тебе говорил, что это отменная шмаль?\n\n\
                {ffffff}Игрок{F5DEB3}\t\t-\tЧерт побери, я думал, что я уже умер и попал в АД.\n\n\
                {ffffff}Big Smoke{F5DEB3}\t-\tНет, это особое место, я его называю - Рай\n\
                {F5DEB3}\t\t\tКак я и обещал, деньги уже перечислил тебе на счет.\n\
                {F5DEB3}\t\t\tЕсли захочешь опять расслабиться, приходи.",
                !"Закрыть",!""
            );
        }
    }
    GivePlayerMoney(playerid, 5000);
    quest_speed_record[playerid] = 0;
}


База Данных: >> Б-Д - Кидаем этот файл в scriptfiles





Автор: Saibot

Сообщение отредактировал Saibot: 16 сентября 2020 - 14:08

4

#2
Пользователь офлайн   Foxed 

  • Местный
  • Вставить ник
  • Раскрыть информацию
с акулой угарнул xD прикольно, тоже дуумаю какие нибудь квестики сделать
0

#3
Пользователь офлайн   CL1FF 

  • Местный
  • Вставить ник
  • Раскрыть информацию
Оригинальная работа, и по коду все читабельно и приятно для глаз.

P.S. Соглашусь с предыдущим комментатором, тоже с акулы угарнул)
0

#4
Пользователь офлайн   DeimoS 

  • Evil Scripter
  • Вставить ник
  • Раскрыть информацию
С высказываниями про читабельность не соглашусь. Тот ворох глобальных переменных гораздо опрятнее было бы объединить в один или несколько массивов через enum, а не городить десяток переменных с длиннющими названиями.

Да и давать глобальным переменным имена в нижнем регистре - крайне сомнительный пример какой-либо читаемости.

И о какой читаемости вообще речь, если в коде магические числа присутствуют?

Цитата

static const press_button[2] = {65536, 131072};
static const name_button[2][11] = {!"PRESS ~r~Y", !"PRESS ~g~N"};

Почему ID клавиш нельзя было написать макросами KEY_YES/KEY_NO? Да и вообще, зачем их хранить в переменной, если можно сделать так:
new random_button = random(2);
quest_victor_press_button[playerid] = (random_button == 0 ? KEY_YES : KEY_NO);

Если, в случае с текстом, разницы никакой нет, ибо, прописывая текст напрямую, мы, фактически, всё так же создаём в сегменте данных массив, в который текст и помещается, то в случае с числами всё работает иначе и число в код помещается как константа, в отличии от переменной, на обращение к которой тратится время.

Цитата

    new random_button = random(2);
    strcat(str_fmt, name_button[random_button]);
    TextDrawSetString(quest_victor_TD[playerid][3], str_fmt);

Тут ты тоже странные махинации совершаешь. Зачем ты копируешь текст из одной переменной в другую, если он никак не изменяется? Можно спокойно убрать str_fmt и сделать так:
    new random_button = random(2);
    TextDrawSetString(quest_victor_TD[playerid][3], name_button[random_button]);





Функция QuestConvectorTime - растратчик стека. Вот в этом месте
format(fmt_str, sizeof(fmt_str),
        "Название:\tВремя прохождения:\n\
        {eee6a3}#1 Джонни и проклятые олени\t{ffffff}%s\n\
        {eee6a3}#2 Старый друг Тони\t{ffffff}%s\n\
        {eee6a3}#3 Украсть тачку для Виктора\t{ffffff}%s\n\
        {eee6a3}#4 Big Smoke и его травка\t{ffffff}%s",
        QuestConvectorTime(record_hunter),
        QuestConvectorTime(record_tony),
        QuestConvectorTime(record_victor),
        QuestConvectorTime(record_big_smoke)
    );

За счёт вызова QuestConvectorTime, ты ~70 ячеек тратишь из-за того, что в QuestConvectorTime возвращается текст. Хотя ну совершенно ничего не мешает тебе напрямую прописать в format "%02d:%02d" вместо "%s" и сделать нужные махинации с переменными. Код от этого менее читаемым не станет.



Это не всё, что ещё можно поправить, но, думаю, пока и этого хватит. Всё равно нынче на форуме на критику реагируют, примерно, так:

Просмотр сообщенияMavi (10 сентября 2020 - 13:21) писал:

А я как понимаю тебе вообще насрать на то, что ты пишешь, лишь бы поп*здеть на чью-то работу.

:happy:

Сообщение отредактировал DeimoS: 16 сентября 2020 - 03:15

0

#5
Пользователь офлайн   Saibot 

  • Прохожий
  • Вставить ник
  • Раскрыть информацию
@DeimoS, Ну вот, что у меня получилось, даже не знаю, в худшую или в лучшую сторону.

Скрытый текст [Показать]


К критике - я отношусь адекватно и всегда делаю выводы.
1

#6
Пользователь офлайн   OKStyle 

  • Прохожий
  • Вставить ник
  • Раскрыть информацию
Идея с акулой мне напомнила глюки с кактусами GTA V :)
0

#7
Пользователь офлайн   DeimoS 

  • Evil Scripter
  • Вставить ник
  • Раскрыть информацию

Просмотр сообщенияSaibot (16 сентября 2020 - 14:07) писал:

Нажмите сюда, чтобы прочитать это сообщение. [Показать]



Тебе следует научиться расставлять "return" в условиях, чтоб если в том же OnPlayerPickUpPickup сработало условие для первого пикапа, то сервер не начал впустую дальше проверять условия для следующих пикапов. И это не только в OnPlayerPickUpPickup у тебя так.




Ещё вот этот код

Цитата

    new random_button = random(2);
    
    TextDrawSetString(QuestVictorTD[playerid][3], (random_button == 0 ? (!"PRESS ~r~Y") : (!"PRESS ~g~N")));
    
    pQuest[playerid][qVictorButton] = (random_button == 0 ? KEY_YES : KEY_NO);


Логичнее сделать так
if(random(2) == 0)
{
    TextDrawSetString(QuestVictorTD[playerid][3], !"PRESS ~r~Y");
    pQuest[playerid][qVictorButton] = KEY_YES;
}
else
{
    TextDrawSetString(QuestVictorTD[playerid][3], !"PRESS ~g~N");
    pQuest[playerid][qVictorButton] = KEY_NO;
}

Тем самым, во-первых, вместо двух одинаковых условий в виде тернарок мы делаем всего 1 условие, а, во-вторых, мы так же убираем ненужную переменную.




Так же с префиксами я предложил бы поработать иначе. Если всюду лепить префикс "q", то это не будет особо информативно. У тех же диалогов гораздо логичнее делать префикс "d" и убирать из названия слово "dialog", а-ля: "dQuest_Hunter", - тут и за счёт префикса видно, что это именно диалог, и так же видно, что диалог относится к системе квестов. Хотя ещё лучше давать названия, которые указывают на функционал диалога, а-ля: "dQuest_Hunter_StartQuest", где "dQuest_" - это общий префикс для всех диалогов конкретной системы, "Hunter_" - это префикс, связывающий диалог с квестами на охоту, а "StartQuest" - это уже описание функционала диалога. Это будет наиболее информативно как при чтении кода, так и при попытке вспомнить то, какое название ты указал для того или иного диалога, если вдруг понадобится его найти или использовать где-то ещё в коде.
То же самое касается и пикапов/текстдравов. Да вообще всего. Я, например, для текстдравов использую стиль написания: "td_TextDrawName"/"ptd_PlayerTextDrawName", а для пикапов - "pickup_PickupName".




От магических чисел следует отучаться. Это очень плохая практика, которая сильно усложняет поддержку кода и увеличивает шанс на допущение багов.
То бишь, вот такой код:

Цитата

        static const Float: position[14][3] =
        {
            // Тут координаты
        };
        for(new i = 0; i < 14; i ++)
        {
            pQuest[playerid][qSmokePickup][i] = CreatePickup(11738, 14, position[i][0], position[i][1], position[i][2], 99);
            SetPlayerMapIcon(playerid, i, position[i][0], position[i][1], position[i][2], 22, 0, MAPICON_GLOBAL);
        }


Лучше заменить на такой
        static const Float: position[14][3] =
        {
            // Тут координаты
        };
        for(new i = 0; i < sizeof(position); i ++)
        {
            pQuest[playerid][qSmokePickup][i] = CreatePickup(11738, 14, position[i][0], position[i][1], position[i][2], 99);
            SetPlayerMapIcon(playerid, i, position[i][0], position[i][1], position[i][2], 22, 0, MAPICON_GLOBAL);
        }

Заменив в цикле "14" на "sizeof(position)", мы обезопасили себя от возможного бага, если вдруг однажды решим изменить количество координат в массиве и вдруг забудем изменить количество итераций в самом цикле. Теперь число итераций будет автоматически подстраиваться под размер массива. Это и удобнее, и безопаснее.

То же самое в случае с максимальной длинной названия для квеста, например, вот тут:

Цитата

    new fmt_str[58 + MAX_PLAYER_NAME + 30 + 11],
    //...
    new quest_name[30];
    switch(questid)
    {
        case QUEST_NAME_HUNTER: quest_name = "player_record_hunter";
        case QUEST_NAME_TONY: quest_name = "player_record_tony";
        case QUEST_NAME_VICTOR: quest_name = "player_record_victor";
        case QUEST_NAME_BIG_SMOKE: quest_name = "player_record_big_smoke";
    }


Гораздо лучше завести константу или макрос, который будет равен 30, а уже в массивах и проверках использовать имя созданной константы/макроса, а не прописывать напрямую "30".
const MAX_QUEST_NAME = 30;
//...
new fmt_str[58 + MAX_PLAYER_NAME + MAX_QUEST_NAME+ 11],
    //...
    new quest_name[MAX_QUEST_NAME+1];
    switch(questid)
    {
        case QUEST_NAME_HUNTER: quest_name = "player_record_hunter";
        case QUEST_NAME_TONY: quest_name = "player_record_tony";
        case QUEST_NAME_VICTOR: quest_name = "player_record_victor";
        case QUEST_NAME_BIG_SMOKE: quest_name = "player_record_big_smoke";
    }

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




Так же советую перестать лепить всюду "return true;/return false;", если функция сама по себе не возвращает именно булевые значения. Научись придерживаться правильной типизации данных. Это сделает твой код более читаемым и аккуратным. А если ты это изначально делал ради подсветки, то просто выкинь уже в помойку Pawno и скачай нормальный редактор кода, который и без всего этого говнокода с "true/false" будет подсвечивать return нормально.




Ну и так же полезно будет научиться не ставить return в тех функциях, для которых не так важно то, какое значение возвращает функция. То бишь, например, в той же функции QuestVictorRandomButton совершенно не важно какое именно значение функция возвращает, ибо там просто обрабатывается код внутри функции. В итоге return только занимает лишнюю строчку в коде скрипта. Если return убрать, компилятор всё равно подставит возврат в конец функции. Просто возвращаться уже будет не 1, а 0 - но для твоей функции это не важно совершенно.
А даже если вдруг тебе нужно по условию обрывать выполнение функции, но всё равно не важно какое значение функция возвращает (то бишь, в том месте, где ты вызываешь функцию, ты потом не записываешь значение, которое функция возвращает, и не делаешь с этим значением никаких проверок), то, опять же, можно обойтись без лишнего возврата в конце. Для того, чтоб делать возврат в таких случаях, следует использовать "return;" - это говорит компилятору, что ты не требуешь от функции возвращать какое-то определённое значение, поэтому компилятор не станет ругаться, если ты вдруг не пропишешь в конце функции return.
Вот простой пример:

main()
{
    SomeFunc(5);// Мы просто вызываем функцию. Нам не важно какое значение она вернёт.
    SomeFunc(1);
    SomeFunc(111);
}

stock SomeFunc(value)
{
    if(value == 5)// Сделаем проверку значения
        return; // И добавим прекращение обработки кода

    printf("value = %d", value);
    // Так как выше мы использовали "return;", тут нам return указывать не обязательно
}

Но нужно помнить, что одновременно использовать "return;" и "return *значение*;" внутри функции нельзя, так как если указать значение хотя бы для одного return - компилятор будет ожидать значение и в других return этой функции. Точно так же нельзя будет в return такой функции возвращать значение другой функции или значение этой функции возвращать в return какой-то другой функции. В любом случае все эти ошибки не смертельны и компилятор сразу о них сообщит.

На первый взгляд это может показаться не очень важным и бесполезным, но на деле это очень повысит читаемость кода, ибо если ты начнёшь использовать такой подход по всему скрипту, то, при чтении кода, будет сразу видно, что если какая-то функция возвращает, например, "1"/"0", то значит, что в том месте, где эта функция вызывается, происходят какие-то действия с результатом этой самой функции.
То бишь, вот в таком коде:
stock SomeFunc(value)
{
    if(value < 5)
        return 0;
    // Какой-то код
    // Какой-то код
    // Какой-то код
    // Какой-то код
    // Какой-то код
    // Какой-то код
    // Какой-то код
    // Какой-то код
    // Какой-то код
    // Какой-то код
    // Какой-то код
    // Какой-то код
    // Какой-то код
    return 1;
}

Ты сразу поймёшь, что там, где вызывается SomeFunc, 100% есть код, в стиле:
if(SomeFunc(5) != 0)// Тут мы получаем результат, который возвращает функция и проверяем, не равен ли он нулю
    return 1;


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




Вот тут
    new fmt_str[250 + 4*4],
        player_name[MAX_PLAYER_NAME];

    GetPlayerName(playerid, player_name, MAX_PLAYER_NAME);
    format(fmt_str, sizeof(fmt_str), "SELECT * FROM `quests` WHERE `player_name` = '%s'",
        player_name
    );


Можно избавиться от массива player_name и записать ник в fmt_str.




Текстдравы лучше бы перерисовать или просто подредактировать координаты, если возможно это сделать, не сломав их. Важно, чтоб координаты были в виде целых чисел. Тогда, если у игрока будет разрешение экрана больше или меньше того, при котором ты рисовал текстдравы, SAMP сможет подогнать размер твоих текстдравов максимально точно, с минимальными искажениями.




Цитата

if(pQuest[playerid][qGetMission] == true && pickupid >= pQuest[playerid][qSmokePickup][0] && pickupid <= pQuest[playerid][qSmokePickup][13])

Вот эта проверка будет работать некорректно на реальном сервере, так как пикапы qSmokePickup у тебя создаются при взятии квеста и если в этот момент на сервере по тем или иным причинам какие-то пикапы удалялись, то твои пикапы вполне могут создаться с ID вразнобой.
То бишь, допустим, сначала на сервере было 5 пикапов с ID от 0 до 4. Потом какая-то система удалила пикап под ID 2. Теперь срабатывает твой код и твои пикапы займут ID не по порядку, а один из пикапов займёт ID 2, в результате чего твоя проверка будет охватывать не только нужные тебе пикапы.
Ну и так же в этой проверке тоже следует избавиться от магических чисел. Как минимум, "[13]" можно заменить на "[sizeof(pQuest[])-1]".




Название массива pQuest тоже не кажется очень удачным. Это больше похоже на название одной из именованных констант в enum от массива игрока. Уж лучше сделай название, в стиле: "QuestInfo", - оно будет и информативным, и уникальным.




Цитата

ShowPlayerDialog(playerid, 0000, DIALOG_STYLE_MSGBOX,


В своих старых модах я часто нулевой ID диалога выделял под диалог регистрации. Так что в них твой код уже работал бы некорректно :)
Это я к тому, что непонятно почему для этого диалога ты не выделил константу, как для всех остальных.




Пока что как-то так.

Сообщение отредактировал DeimoS: 17 сентября 2020 - 03:47

1

#8
Пользователь офлайн   Saibot 

  • Прохожий
  • Вставить ник
  • Раскрыть информацию

Цитата

Текстдравы лучше бы перерисовать или просто подредактировать координаты, если возможно это сделать, не сломав их. Важно, чтоб координаты были в виде целых чисел.

Заменить
QuestLaterTD[0] = TextDrawCreate(641.583312, 1.500000, !"usebox");

на
QuestLaterTD[0] = TextDrawCreate(641, 2, !"usebox");

Так? или я не правильно понял?

Цитата

Вот эта проверка будет работать некорректно на реальном сервере, так как пикапы qSmokePickup у тебя создаются при взятии квеста и если в этот момент на сервере по тем или иным причинам какие-то пикапы удалялись, то твои пикапы вполне могут создаться с ID вразнобой.

Я так понял, что лучше сделать так?
if(QuestInfo[playerid][qGetMission] == true
&& pickupid == QuestInfo[playerid][qSmokePickup][0]
|| pickupid == QuestInfo[playerid][qSmokePickup][1]
|| pickupid == QuestInfo[playerid][qSmokePickup][2]
|| pickupid == QuestInfo[playerid][qSmokePickup][3]
|| pickupid == QuestInfo[playerid][qSmokePickup][4]
|| pickupid == QuestInfo[playerid][qSmokePickup][5]
|| pickupid == QuestInfo[playerid][qSmokePickup][6]
|| pickupid == QuestInfo[playerid][qSmokePickup][7])

0

#9
Пользователь офлайн   DeimoS 

  • Evil Scripter
  • Вставить ник
  • Раскрыть информацию

Просмотр сообщенияSaibot (17 сентября 2020 - 13:27) писал:

Заменить
QuestLaterTD[0] = TextDrawCreate(641.583312, 1.500000, !"usebox");

на
QuestLaterTD[0] = TextDrawCreate(641, 2, !"usebox");

Так? или я не правильно понял?


Почти. Типизацию сохранять не забудь, чтоб не было вызова функции float
QuestLaterTD[0] = TextDrawCreate(641.0, 2.0, !"usebox");



Просмотр сообщенияSaibot (17 сентября 2020 - 13:27) писал:

Я так понял, что лучше сделать так?
if(QuestInfo[playerid][qGetMission] == true
&& pickupid == QuestInfo[playerid][qSmokePickup][0]
|| pickupid == QuestInfo[playerid][qSmokePickup][1]
|| pickupid == QuestInfo[playerid][qSmokePickup][2]
|| pickupid == QuestInfo[playerid][qSmokePickup][3]
|| pickupid == QuestInfo[playerid][qSmokePickup][4]
|| pickupid == QuestInfo[playerid][qSmokePickup][5]
|| pickupid == QuestInfo[playerid][qSmokePickup][6]
|| pickupid == QuestInfo[playerid][qSmokePickup][7])

const MAX_QUEST_PICKUP__SMOKE = 14;
enum e_QUEST_INFO
{
	qSmokePickup[MAX_QUEST_PICKUP__SMOKE],
}


//.............
//.............
//.............

if(QuestInfo[playerid][qGetMission] == true)
{
	for(new i; i < MAX_QUEST_PICKUP__SMOKE; i++)
	{
		if(pickupid == QuestInfo[playerid][qSmokePickup][i])
		{
			// Тут код пикапа
			return 1;
		}
	}
}

Сообщение отредактировал DeimoS: 17 сентября 2020 - 15:01

0

#10
Пользователь офлайн   Pa4enka 

  • Эксперт
  • Вставить ник
  • Раскрыть информацию
А есть ли вообще смысл придираться к стилистике оформления кода? Ведь, у каждого разработчика собственный уникальный и выработанный годами стиль, который, более того, с годами еще и немного корректируется. К тому же, если человеку действительно удобнее читать "dialog", то нововведения по типу префикса "d" привнесут лишь путаницу. И в чем тогда профит? Согласен, теоретически все эти замечания звучат правильно и к месту, но практически могут усложнить написания кода, если не дойти к этому самому и постепенно.

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

И еще. Аргументация "работа для форума, а значит все должно быть по канонам", "писать надо изначально правильно" здесь не прокатит. У автора изначально хороший среднестатистический код. В названии переменных и функций отсутствует транслит. Код разбит на логические блоки. Активно использует перенос длинных строк. Имхо, это уже хороший код для форума. А если подтянуть всякие нюансы, а-ля "магические числа", константы, то вообще цены бы ему не было.

UPD: как-то не очень связано получилось написать, сори.

Сообщение отредактировал Pa4enka: 17 сентября 2020 - 21:54

2

Поделиться темой:


  • (2 Страниц) +
  • 1
  • 2
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

1 человек читают эту тему
0 пользователей, 1 гостей, 0 скрытых пользователей


Яндекс.Метрика