summaryrefslogtreecommitdiff
path: root/src/map/quest.c
blob: aef112a831484a2a6fb88f31fc87f3d5d5d1c754 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL.
// Copyright (c) 2014 Evol developers

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../../../common/HPMi.h"
#include "../../../common/malloc.h"
#include "../../../common/mmo.h"
#include "../../../common/socket.h"
#include "../../../common/strlib.h"
#include "../../../map/itemdb.h"
#include "../../../map/quest.h"

#include "map/quest.h"

/**
 * Reads and parses an entry from the quest_db.
 *
 * @param cs     The config setting containing the entry.
 * @param n      The sequential index of the current config setting.
 * @param source The source configuration file.
 * @return The parsed quest entry.
 * @retval NULL in case of errors.
 */
struct quest_db *equest_read_db_sub(config_setting_t *cs, int *nPtr, const char *source)
{
    struct quest_db *entry = NULL;
    config_setting_t *t = NULL;
    int i32 = 0, quest_id;
    const char *str = NULL;
    const int n = *nPtr;

    /*
     * Id: Quest ID                    [int]
     * Name: Quest Name                [string]
     * TimeLimit: Time Limit (seconds) [int, optional]
     * Targets: (                      [array, optional]
     *     {
     *         MobId: Mob ID           [int]
     *         Count:                  [int]
     *     },
     *     ... (can repeated up to MAX_QUEST_OBJECTIVES times)
     * )
     * Drops: (
     *     {
     *         ItemId: Item ID to drop [int]
     *         Rate: Drop rate         [int]
     *         MobId: Mob ID to match  [int, optional]
     *     },
     *     ... (can be repeated)
     * )
     */

    if (!libconfig->setting_lookup_int(cs, "Id", &quest_id)) {
        ShowWarning("quest_read_db: Missing id in \"%s\", entry #%d, skipping.\n", source, n);
        return NULL;
    }
    if (quest_id < 0 || quest_id >= MAX_QUEST_DB) {
        ShowWarning("quest_read_db: Invalid quest ID '%d' in \"%s\", entry #%d (min: 0, max: %d), skipping.\n", quest_id, source, n, MAX_QUEST_DB);
        return NULL;
    }

    if (!libconfig->setting_lookup_string(cs, "Name", &str) || !*str) {
        ShowWarning("quest_read_db_sub: Missing Name in quest %d of \"%s\", skipping.\n", quest_id, source);
        return NULL;
    }

    CREATE(entry, struct quest_db, 1);
    entry->id = quest_id;
    //safestrncpy(entry->name, str, sizeof(entry->name));

    if (libconfig->setting_lookup_int(cs, "TimeLimit", &i32)) // This is an unsigned value, do not check for >= 0
        entry->time = (unsigned int)i32;

    if ((t=libconfig->setting_get_member(cs, "Targets")) && config_setting_is_list(t)) {
/*
        int i, len = libconfig->setting_length(t);
        for (i = 0; i < len && entry->objectives_count < MAX_QUEST_OBJECTIVES; i++) {
            // Note: We ensure that objectives_count < MAX_QUEST_OBJECTIVES because
            //       quest_log (as well as the client) expect this maximum size.
            config_setting_t *tt = libconfig->setting_get_elem(t, i);
            int mob_id = 0, count = 0;
            if (!tt)
                break;
            if (!config_setting_is_group(tt))
                continue;
            if (!libconfig->setting_lookup_int(tt, "MobId", &mob_id) || mob_id <= 0)
                continue;
            if (!libconfig->setting_lookup_int(tt, "Count", &count) || count <= 0)
                continue;
            RECREATE(entry->objectives, struct quest_objective, ++entry->objectives_count);
            entry->objectives[entry->objectives_count-1].mob = mob_id;
            entry->objectives[entry->objectives_count-1].count = count;
        }
*/
        entry->objectives_count = 1;
        RECREATE(entry->objectives, struct quest_objective, 1);
        entry->objectives[0].mob = 1;
        entry->objectives[0].count = 0;
    }

    if ((t=libconfig->setting_get_member(cs, "Drops")) && config_setting_is_list(t)) {
        int i, len = libconfig->setting_length(t);
        for (i = 0; i < len; i++) {
            config_setting_t *tt = libconfig->setting_get_elem(t, i);
            int mob_id = 0, nameid = 0, rate = 0;
            if (!tt)
                break;
            if (!config_setting_is_group(tt))
                continue;
            if (!libconfig->setting_lookup_int(tt, "MobId", &mob_id))
                mob_id = 0; // Zero = any monster
            if (mob_id < 0)
                continue;
            if (!libconfig->setting_lookup_int(tt, "ItemId", &nameid) || !itemdb->exists(nameid))
                continue;
            if (!libconfig->setting_lookup_int(tt, "Rate", &rate) || rate <= 0)
                continue;
            RECREATE(entry->dropitem, struct quest_dropitem, ++entry->dropitem_count);
            entry->dropitem[entry->dropitem_count-1].mob_id = mob_id;
            entry->dropitem[entry->dropitem_count-1].nameid = nameid;
            entry->dropitem[entry->dropitem_count-1].rate = rate;
        }
    }
    return entry;
}