[Ajuda] Warnings Dificil
#1

C:\Users\Cone\Desktop\Brasil Trucker Life\pawno\include\DOF2.inc(1391) : warning 219: local variable "a" shadows a variable at a preceding level
C:\Users\Cone\Desktop\Brasil Trucker Life\pawno\include\DOF2.inc(1391) : warning 219: local variable "b" shadows a variable at a preceding level
C:\Users\Cone\Desktop\Brasil Trucker Life\pawno\include\PPC_MissionsLixeiro.inc(7 : warning 204: symbol is assigned a value that is never used: "LoadMsgs"
C:\Users\Cone\Desktop\Brasil Trucker Life\pawno\include\PPC_MissionsPizza.inc(7 : warning 204: symbol is assigned a value that is never used: "LoadMsgs"
Pawn compiler 3.2.3664 Copyright © 1997-2006, ITB CompuPhase


4 Warnings.

Include DOF2.inc

PHP код:
#if defined _dof2_included
    #endinput
#endif
#define _dof2_included
#include <a_samp>
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
 * This is a new version of the INI script Double-O-Files.
 * However, it's has completely been rewritten and has now a much better performance.
 * There is also the support for sections in the INI file. (But there is no support for comments.)
 * Double-O-Files 2 is compatible with DUDB, DINI, Double-O-Files and possibly y_ini since it
 * can handle sections and entry of the format "key = value", not only "key=value".
 * The number of spaces between the equal sign and key and value can actually be arbitrary.
 * I've added some comments below. You may see that I've mentioned the big-O-notation,
 * 'n' always Entries.Count.
 * Double-O-Files 2 should also be useful for Russian letter because I'm using
 * the functions fgetchar and fputchar to write and read the files.
 *
 * There is another new feature which has been inspired by ZCMD and y_ini:
 * The OnParseFile callbacks. To learn more about it, read the description in
 * the SA-MP forums if you haven't already.
 * THE END
 */
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
native DOF2_SetFile(file[]);
native DOF2_LoadFile();
native DOF2_SaveFile();
native DOF2_ParseFile(file[],extraid,bool:callback=true);
native DOF2_ReparseFile(file[],extraid,bool:callback=true);
native DOF2_WriteFile();
native DOF2_PrintFile(comment[]="");
native DOF2_GetString(file[],key[],tag[]="");
native DOF2_GetStringEx(file[],key[],result[],size,tag[]="");
native Float:DOF2_GetFloat(file[],key[]);
native DOF2_GetInt(file[],key[],tag[]="");
native DOF2_GetHex(file[],key[],tag[]="");
native DOF2_GetBin(file[],key[],tag[]="");
native bool:DOF2_GetBool(file[],key[],tag[]="");
native DOF2_SetString(file[],key[],value[],tag[]="");
native DOF2_SetFloat(file[],key[],Float:value);
native DOF2_SetInt(file[],key[],value,tag[]="");
native DOF2_SetHex(file[],key[],value,tag[]="");
native DOF2_SetBin(file[],key[],value,tag[]="");
native DOF2_SetBool(file[],key[],bool:value,tag[]="");
native DOF2_IsSet(file[],key[],tag[]="");
native DOF2_Unset(file[],key[],tag[]="");
native DOF2_FileExists(file[]);
native DOF2_RemoveFile(file[]);
native DOF2_CreateFile(file[],password[]="");
native DOF2_RenameFile(oldfile[],newfile[]);
native DOF2_RenameKey(file[],oldkey[],newkey[],tag[]="");
native DOF2_CopyFile(filetocopy[],newfile[]);
native DOF2_CheckLogin(file[],password[]);
native DOF2_File(user[]);
native DOF2_ParseInt();
native DOF2_ParseFloat();
native DOF2_ParseBool();
native DOF2_ParseBin();
native DOF2_ParseHex();
native DOF2_SetUTF8(bool:set);
native bool:DOF2_GetUTF8();
native DOF2_GetFile();
native DOF2_MakeBackup(file[]);
native DOF2_RemoveSection (file [], tag []);
native DOF2_SectionExists (file [], tag []);
native DOF2_SortSection (file [], tag [], bool: ignorecase = true, bool: ascending = true);
native DOF2_SortAllSections (file [], bool: ignorecase = true, bool: ascending = true);
native DOF2_SetCaseSensitivity (bool: set);
native DOF2_GetCaseSensitivity ();
*/
#define DOF2_TagExists  DOF2_SectionExists
#define DOF2_RemoveTag  DOF2_RemoveSection
// OnParseFile <Tag><Key>(extraid, value [])
// OnParseFile <><Key>(extraid, value [])
// OnDefaultParseFile (extraid, value [], key [], tag [], file [])
// The arguments of your OnParseFile functions may have arbitrary names but must be an integer followed by a string.
// Function must return a value.
#define OnParseFile<%0><%1>(%2) \
    
forward _OnParseFile_%0_%(extraidvalue []); \
    public 
_OnParseFile_%0_%(extraidvalue []) \
        return 
__OnParseFile_%0_%(extraid, (value [0] == '\1' && value [1] == '\0') ? ("") : value); \
    
stock __OnParseFile_%0_%(%2)
// Also here: The argument names may be arbitrary but must be an integer followed by 4 strings.
// Function must return a value.
#define OnDefaultParseFile(%0) \
    
forward _OnDefaultParseFile (extraidvalue [], key [], tag [], file []); \
    public 
_OnDefaultParseFile (extraidvalue [], key [], tag [], file []) \
        return 
__OnDefaultParseFile (extraid, (value [0] == '\1' && value [1] == '\0') ? ("") : valuekey, (tag [0] == '\1' && tag [1] == '\0') ? ("") : tagfile); \
    
stock __OnDefaultParseFile (%0)
#define DOF2_ParseBool() \
    
(strval (value) || (value [0] && !strcmp (value"true"true)))
#define DOF2_ParseInt() \
    
(strval (value))
#define DOF2_ParseFloat() \
    
(floatstr (value))
#define DOF2_ParseBin() \
    
(DOF2_strbin (value))
#define DOF2_ParseHex() \
    
(DOF2_strhex (value))
#define DOF2_LoadFile() \
    
DOF2_ParseFile (CurrentFile, -1false)
#define DOF2_SaveFile \
    
DOF2_WriteFile
#define DOF2_FileExists \
    
fexist
#define Sections. \
    
Sections_
#define Entries. \
    
Entries_
#define DOF2:: \
    
DOF2_
    
#if !defined private
    #define private         static stock
#endif
    
#pragma dynamic 65536
/*
#define MAX_SECTION_TAG        (32)
#define MAX_LINE_SIZE       (128)
#define MAX_SECTIONS            (32)
#define MAX_ENTRIES         (256)
#define MAX_FILE_SIZE       (64)
#define USER_FILE_PATH         "Users/%s.ini"
*/
// The maximum length of the name of a tag.
#if !defined MAX_SECTION_TAG
    #define MAX_SECTION_TAG        (32)
#endif
// The maximum length of a line (including key and value).
#if !defined MAX_LINE_SIZE
    #define MAX_LINE_SIZE       (128)
#endif
// The maximum number of sections which can be handled. Be careful: MUST NOT be higher than 255.
#if !defined MAX_SECTIONS
    #define MAX_SECTIONS           (32)
#endif
// The maximum number of entries which can be loaded into the cache.
#if !defined MAX_ENTRIES
    #define MAX_ENTRIES         (256)
#endif
// The maximum length of the name of a file.
#if !defined MAX_FILE_SIZE
    #define MAX_FILE_SIZE       (64)
#endif
/*
If PACK_CONTENT == true tag names and lines (key + value) will get stored in cache as packed strings.
The result is less memory usage. However, you won't be able to use special characters like russian or chinese ones.
*/
#if !defined PACK_CONTENT
    #define PACK_CONTENT        (false)
#endif
#define INVALID_ENTRY           (-1)
#define INVALID_SECTION         (-1)
// Do you want to emulate DUDB?
#if !defined DUDB_CONVERT && 0 // Change to 1 to enable.
    #define DUDB_CONVERT
#endif
#if !defined USER_FILE_PATH
    #if defined DUDB_CONVERT
        #define USER_FILE_PATH     "%s.dudb.sav"
    #else
        #define USER_FILE_PATH     "%s.ini"
    #endif
#endif
#if !defined USER_PW_HASH_KEY
    #if defined DUDB_CONVERT
        #define USER_PW_HASH_KEY "password_hash"
    #else
        #define USER_PW_HASH_KEY "password"
    #endif
#endif
    
// Do you want to emulate DINI?
#if !defined DINI_CONVERT && 0 // Change to 1 to enable.
    #define DINI_CONVERT
#endif
/*
#if MAX_SECTIONS >= 256
    #error MAX_SECTIONS must not be greater than 255.
#endif
*/
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
private
    
boolUseUTF8 PACK_CONTENT,
    
boolCaseSensitive false,
    
CurrentFile [MAX_FILE_SIZE],
    
boolFileChanged,
    
Sections.FirstEntry [MAX_SECTIONS] = {INVALID_ENTRY, ...},
    
Sections.LastEntry [MAX_SECTIONS] = {INVALID_ENTRY, ...},
    
Sections.Count,
#if PACK_CONTENT == true
    
Sections.Tag [MAX_SECTIONS][MAX_SECTION_TAG char],
    
Entries.Line [MAX_ENTRIES][MAX_LINE_SIZE char],
    
Entries.Tag [MAX_ENTRIES][MAX_SECTION_TAG char],
#else
    
Sections.Tag [MAX_SECTIONS][MAX_SECTION_TAG],
    
Entries.Line [MAX_ENTRIES][MAX_LINE_SIZE],
    
Entries.Tag [MAX_ENTRIES][MAX_SECTION_TAG],
#endif
#if MAX_SECTIONS >= 256
    
Entries.Section [MAX_ENTRIES],
#else
    
Entries.Section [MAX_ENTRIES char],
#endif
    
Entries.NextEntry [MAX_ENTRIES] = {INVALID_ENTRY, ...},
    
Entries.PreviousEntry [MAX_ENTRIES] = {INVALID_ENTRY, ...},
    
Entries.Count,
    
SortedEntryList [MAX_ENTRIES][2]; // Index 0: Hashcode, Index 1: EntryID
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
stock DOF2::Exit ()
    
DOF2::WriteFile ();
stock DOF2::SetUTF8 (boolset)
    
UseUTF8 set;
stock boolDOF2::GetUTF8 ()
    return 
UseUTF8;
stock boolDOF2::SetCaseSensitivity (boolset)
    
CaseSensitive set;
    
stock boolDOF2::GetCaseSensitivity ()
    return 
CaseSensitive;
stock DOF2::SetFile (file [])
    
DOF2::strcpy (CurrentFilefile);
stock DOF2::GetFile ()
    return 
CurrentFile;
stock DOF2::CreateFile (file [], password [] = "")
{
    if (!
DOF2::FileExists (file))
    {
        new 
Filefopen (fileio_append);
        
        if (
fclose (f))
        {
            if (
password [0])
                return 
DOF2::SetInt (fileUSER_PW_HASH_KEYDOF2::num_hash (password));
            return 
1;
        }
    }
    return 
0;
}
stock DOF2::RenameFile (oldfile [], newfile [])
{
    if (!
DOF2::FileExists (newfile))
    {
        
// If 'CurrentFile' is 'oldfile', write it if it has been changed.
        
if (CurrentFile [0] && !strcmp (CurrentFileoldfile) && FileChanged)
            
DOF2::WriteFile ();
        else if (!
DOF2::ParseFile (oldfile, -1false)) // Otherwise parse 'oldfile'.
            
return 0;
            
        
DOF2::SetFile (newfile);
        if (
DOF2::WriteFile ())
            return 
fremove (oldfile);
    }
    return 
0;
}
stock DOF2::CopyFile (filetocopy [], newfile [])
{
    if (!
DOF2::FileExists (newfile))
    {
        if (
CurrentFile [0] && !strcmp (CurrentFilefiletocopy) && FileChanged)
            
DOF2::WriteFile ();
        else if(!
DOF2::ParseFile (filetocopy, -1false))
            return 
0;
            
        
DOF2::SetFile (newfile);
        return 
DOF2::WriteFile ();
    }
    return 
0;
}
stock DOF2::RemoveFile (file [])
{
    if (
file [0])
    {
        if (
CurrentFile [0] && !strcmp (CurrentFilefile))
            
CurrentFile [0] = '\0';
        return 
fremove (file);
    }
    return 
0;
}
stock DOF2::MakeBackup (file [])
{
    new
        
year,
        
month,
        
day,
        
hour,
        
minute,
        
second,
        
backupfile [MAX_FILE_SIZE];
    
getdate (yearmonthday);
    
gettime (hourminutesecond);
    
format (backupfilesizeof (backupfile), "%s.%02d_%02d_%02d.%02d_%02d_%02d_%02d.bak"CurrentFilemonthdayyearhourminutesecondGetTickCount ());
    return 
DOF2::CopyFile (CurrentFilebackupfile);
}
stock boolDOF2::SectionExists (file [], tag [])
{
    if (
file [0]) // You can't remove the empty Sections.
    
{
        if (!
tag [0])
            return 
true// Emptry section always exists. In every file.
        
if (!CurrentFile [0] || strcmp (CurrentFilefile)) // No file in buffer or the file you want to read from is not the file in the buffer.
            
if (!DOF2::ParseFile (file, -1false))
                return 
false;
    
#if PACK_CONTENT == true
        
new buf [MAX_SECTION_TAG];
    
#endif
    
        
for (new 1Sections.Count; ++i)
        {
        
#if PACK_CONTENT == true
            
strunpack (bufSections.Tag [i]);
            if (!
strcmp (buftag, !CaseSensitive))
                return 
true;
        
#else
            
if (!strcmp (Sections.Tag [i], tag, !CaseSensitive))
                return 
true;
        
#endif
        
}
    }
    return 
false;
}
stock DOF2::RemoveSection (file [], tag [])
{
    
// Removes tag 'tag' with all it's entries.
    
if (file [0] && tag [0]) // You can't remove the empty Sections.
    
{
        if (!
CurrentFile [0] || strcmp (CurrentFilefile)) // No file in buffer or the file you want to read from is not the file in the buffer.
            
if (!DOF2::ParseFile (file, -1false))
                return 
0;
        new
        
#if PACK_CONTENT == true
            
line [MAX_LINE_SIZE],
        
#endif
            
buf [MAX_SECTION_TAG],
            
section INVALID_SECTION,
            
entry,
            
key [MAX_LINE_SIZE];
        for (new 
1Sections.Count; ++i)
        {
        
#if PACK_CONTENT == true
            
strunpack (bufSections.Tag [i]);
            if (!
strcmp (buftag, !CaseSensitive))
            {
                
section i;
                break;
            }
        
#else
            
if (!strcmp (Sections.Tag [i], tag, !CaseSensitive))
            {
                
section i;
                break;
            }
        
#endif
        
}
        if (
section != INVALID_SECTION)
        {
            
entry Sections.FirstEntry [section];
            while (
entry != INVALID_ENTRY)
            {
                
// Remove all entries under the current Sections.
            #if PACK_CONTENT == true
                
strunpack (lineEntries.Line [entry]);
                
DOF2::ParseLine (linekeybuf);
            
#else
                
DOF2::ParseLine (Entries.Line [entry], keybuf);
            
#endif
                
DOF2::Unset (filekeytag);
                
entry Entries.NextEntry [entry];
            }
            
// Move the last tag to the position of the current tag. Creates a little mess.
            
--Sections.Count;
            
Sections.Tag [section] = Sections.Tag [Sections.Count];
            
Sections.FirstEntry [section] = Sections.FirstEntry [Sections.Count];
            
Sections.LastEntry [section] = Sections.LastEntry [Sections.Count];
            
// Adjust the tag IDs of the entries.
            
entry Sections.FirstEntry [section];
            while (
entry != INVALID_ENTRY)
            {
            
#if MAX_SECTIONS >= 256
                
Entries.Section [entry] = section;
            
#else
                
Entries.Section {entry} = section;
            
#endif
                
entry Entries.NextEntry [entry];
            }
            
FileChanged true;
            return 
1;
        }
    }
    return 
0;
}
private 
DOF2::SearchEntry (key [], tag [], keybuf [], valbuf [], &poskeybufsize sizeof (keybuf), valbufsize sizeof (valbuf))
{
    if (
key [0] && Entries.Count)
    {
        new
            
entry INVALID_ENTRY,
            
l,
            
m,
            
r,
            
h,
        
#if PACK_CONTENT == true
            
line [MAX_LINE_SIZE],
            
buf [MAX_SECTION_TAG],
        
#endif
            
i;
        
DOF2::HashKey (key);
        
0;
        
Entries.Count 1;
        
/*
         * Binary search in a sorted list of entries in O(log n) time. This algorithm makes for example with 256 elements a maximum of ~8 steps until the entry is found if it exists.
         * A sequential search would take up to 256 steps. That was the case in the first Double-O-Files script.
         */
        
while (<= r)
        {
            if ((
l) < 2)
            {
                if (
== SortedEntryList [l][0])
                {
                    
l;
                    
entry SortedEntryList [l][1];
                }
                else if (
&& == SortedEntryList [r][0])
                {
                    
r;
                    
entry SortedEntryList [r][1];
                }
                break;
            }
            else
            {
                
+ (l) / 2;
                if (
== SortedEntryList [m][0])
                {
                    
entry SortedEntryList [m][1];
                    break;
                }
                else if (
SortedEntryList [m][0])
                    
1;
                else
                    
1;
            }
        }
        
// Candidate found?
        
if (entry != INVALID_ENTRY)
        {
            
// Check if it's the entry we want.
          #if PACK_CONTENT == true
            
strunpack (lineEntries.Line [entry]);
            
DOF2::ParseLine (linekeybufvalbufkeybufsizevalbufsize);
            
strunpack (bufEntries.Tag [entry]);
            if (!
strcmp (keybufkey, !CaseSensitive) && ((!tag [0] && !buf [0]) || (tag [0] && buf [0] && !strcmp (tagbuf, !CaseSensitive))))
        
#else
            
DOF2::ParseLine (Entries.Line [entry], keybufvalbufkeybufsizevalbufsize);
            if (!
strcmp (keybufkey, !CaseSensitive) && ((!tag [0] && !Entries.Tag [entry][0]) || (tag [0] && Entries.Tag [entry][0] && !strcmp (tagEntries.Tag [entry], !CaseSensitive))))
        
#endif
                
return (pos mentry);
            else
            {
                
// If not, look left and right in the list for entries with the same hash code. This can be collisions or entries with the same key from another section.
                
for (1>= && == SortedEntryList [i][0]; --i)
                {
                    
entry SortedEntryList [i][1];
                 
#if PACK_CONTENT == true
                    
strunpack (lineEntries.Line [entry]);
                    
DOF2::ParseLine (linekeybufvalbufkeybufsizevalbufsize);
                    
strunpack (bufEntries.Tag [entry]);
                    if (!
strcmp (keybufkey, !CaseSensitive) && ((!tag [0] && !buf [0]) || (tag [0] && buf [0] && !strcmp (tagbuf, !CaseSensitive))))
                
#else
                    
DOF2::ParseLine (Entries.Line [entry], keybufvalbufkeybufsizevalbufsize);
                    if (!
strcmp (keybufkey, !CaseSensitive) && ((!tag [0] && !Entries.Tag [entry][0]) || (tag [0] && Entries.Tag [entry][0] && !strcmp (tagEntries.Tag [entry], !CaseSensitive))))
                
#endif
                        
return (pos ientry);
                }
                for (
1Entries.Count && == SortedEntryList [i][0]; ++i)
                {
                    
entry SortedEntryList [i][1];
                 
#if PACK_CONTENT == true
                    
strunpack (lineEntries.Line [entry]);
                    
DOF2::ParseLine (linekeybufvalbufkeybufsizevalbufsize);
                    
strunpack (bufEntries.Tag [entry]);
                    if (!
strcmp (keybufkey, !CaseSensitive) && ((!tag [0] && !buf [0]) || (tag [0] && buf [0] && !strcmp (tagbuf, !CaseSensitive))))
                
#else
                    
DOF2::ParseLine (Entries.Line [entry], keybufvalbufkeybufsizevalbufsize);
                    if (!
strcmp (keybufkey, !CaseSensitive) && ((!tag [0] && !Entries.Tag [entry][0]) || (tag [0] && Entries.Tag [entry][0] && !strcmp (tagEntries.Tag [entry], !CaseSensitive))))
                
#endif
                        
return (pos ientry);
                }
            }
        }
    }
    
    
keybuf [0] = valbuf [0] = '\0';
    return 
INVALID_ENTRY;
}
stock DOF2::SetString (file [], key [], value [], tag [] = "")
{
    if (
file [0] && key [0])
    {
        new
            
entry,
            
pos,
            
section INVALID_SECTION,
            
keybuf [MAX_LINE_SIZE],
            
valbuf [MAX_LINE_SIZE],
        
#if PACK_CONTENT == true
            
buf [MAX_SECTION_TAG],
            
line [MAX_LINE_SIZE],
        
#endif
            
i;
        if (!
CurrentFile [0] || strcmp (CurrentFilefile)) // No file in buffer or the file you want to read from is not the file in the buffer.
            
if (!DOF2::ParseFile (file, -1false))
                return 
0;
        
entry DOF2::SearchEntry (keytagkeybufvalbufpos);
        
// If the entry has been found, just change it's content.
        
if (entry != INVALID_ENTRY)
        {
            
FileChanged true;
        
#if PACK_CONTENT == true
            
format (linesizeof (line), "%s = %s"keyvalue [0] ? value : ("(null)"));
            return 
strpack (Entries.Line [entry], line);
        
#else
            
format (Entries.Line [entry], sizeof (Entries.Line []), "%s = %s"keyvalue [0] ? value : ("(null)"));
            return 
1;
        
#endif
        
}
        if (
Entries.Count >= MAX_ENTRIES)
            return 
0;
        
// Search for the section where the entry belongs.
        
if (!tag [0])
            
section 0;
        else
        {
            for (
1Sections.Count; ++i)
            {
            
#if PACK_CONTENT == true
                
strunpack (bufSections.Tag [i]);
                if (
buf [0] && !strcmp (tagbuf, !CaseSensitive))
                {
                    
section i;
                    break;
                }
            
#else
                
if (Sections.Tag [i][0] && !strcmp (tagSections.Tag [i], !CaseSensitive))
                {
                    
section i;
                    break;
                }
            
#endif
            
}
        }
        
// Section we want does not exist, create new one if possible.
        
if (section == INVALID_SECTION)
        {
            if (
Sections.Count >= MAX_SECTIONS)
                return 
0;
            
section Sections.Count++;
        
#if PACK_CONTENT == true
            
strpack (Sections.Tag [section], tag);
        
#else
            
DOF2::strcpy (Sections.Tag [section], tag);
        
#endif
            
Sections.FirstEntry [section] = Sections.LastEntry [section] = INVALID_ENTRY;
        }
        
// Add the entry to the section. Section's content is defined by a linear two way list.
    #if PACK_CONTENT == true
        
format (linesizeof (line), "%s = %s"keyvalue [0] ? value : ("(null)"));
        
strpack (Entries.Line [Entries.Count], line);
    
#else
        
format (Entries.Line [Entries.Count], sizeof (Entries.Line []), "%s = %s"keyvalue [0] ? value : ("(null)"));
    
#endif
        
Entries.Tag [Entries.Count] = Sections.Tag [section];
    
#if MAX_SECTIONS >= 256
        
Entries.Section [Entries.Count] = section;
    
#else
        
Entries.Section {Entries.Count} = section;
    
#endif
        
Entries.NextEntry [Entries.Count] = INVALID_ENTRY;
        
// Add entry to sorted list of entries and move to right correct position in O(n) time.
        
SortedEntryList [Entries.Count][0] = DOF2::HashKey (key);
        
SortedEntryList [Entries.Count][1] = Entries.Count;
        
Entries.Count 1;
        while (
>= && SortedEntryList [i][0] > SortedEntryList [1][0])
        {
            
DOF2::SwapSortedEntries (SortedEntryList [i], SortedEntryList [1]);
            --
i;
        }
        if (
Sections.LastEntry [section] == INVALID_ENTRY// No entry in this section.
        
{
            
Sections.FirstEntry [section] = Sections.LastEntry [section] = Entries.Count;
            
Entries.PreviousEntry [Entries.Count] = INVALID_ENTRY;
        }
        else
        {
            
Entries.NextEntry [Sections.LastEntry [section]] = Entries.Count;
            
Entries.PreviousEntry [Entries.Count] = Sections.LastEntry [section];
            
Sections.LastEntry [section] = Entries.Count;
        }
        ++
Entries.Count;
        
FileChanged true;
    }
    return 
1;
}
stock DOF2::GetString (file [], key [], tag [] = "")
{
    new 
buf [MAX_LINE_SIZE];
    
DOF2::GetStringEx (filekeybufsizeof (buf), tag);
    return 
buf;
}
stock DOF2::GetStringEx (file [], key [], result [], sizetag [] = "")
{
    if (
file [0] && key [0])
    {
        new
            
pos,
            
keybuf [MAX_LINE_SIZE];
        if (!
CurrentFile [0] || strcmp (CurrentFilefile))
        {
            if (!
DOF2::ParseFile (file, -1false))
            {
                
result [0] = '\0';
                return 
0;
            }
        }
        
// Find entry and assign the result with it's value.
        
return (DOF2::SearchEntry (keytagkeybufresultpossizeof (keybuf), size) != INVALID_ENTRY);
    }
    return 
0;
}
stock DOF2::Unset (file [], key [], tag [] = "")
{
    if (
file [0] && key [0])
    {
        new
            
entry,
            
pos,
            
keybuf [MAX_LINE_SIZE],
            
valbuf [MAX_LINE_SIZE];
        if (!
CurrentFile [0] || strcmp (CurrentFilefile))
            if (!
DOF2::ParseFile (file, -1false))
                return 
0;
        if ((
entry DOF2::SearchEntry (keytagkeybufvalbufpos)) != INVALID_ENTRY)
        {
            
// Remove entry from it's section.
        #if MAX_SECTIONS >= 256
            
if (Sections.FirstEntry [Entries.Section [entry]] == entry// Is the entry the first entry in the section? Make it's next entry the first entry.
        #else
            
if (Sections.FirstEntry [Entries.Section {entry}] == entry)
        
#endif
            
{
            
#if MAX_SECTIONS >= 256
                
Sections.FirstEntry [Entries.Section [entry]] = Entries.NextEntry [entry];
            
#else
                
Sections.FirstEntry [Entries.Section {entry}] = Entries.NextEntry [entry];
            
#endif
                
if (Entries.NextEntry [entry] != INVALID_ENTRY)
                    
Entries.PreviousEntry [Entries.NextEntry [entry]] = INVALID_ENTRY;
            }
            else
            {
                
Entries.NextEntry [Entries.PreviousEntry [entry]] = Entries.NextEntry [entry];
                if (
Entries.NextEntry [entry] != INVALID_ENTRY)
                    
Entries.PreviousEntry [Entries.NextEntry [entry]] = Entries.PreviousEntry [entry];
            }
        
#if MAX_SECTIONS >= 256
            
if (Sections.LastEntry [Entries.Section [entry]] == entry)
        
#else
            
if (Sections.LastEntry [Entries.Section {entry}] == entry)
        
#endif
            
{
            
#if MAX_SECTIONS >= 256
                
Sections.LastEntry [Entries.Section [entry]] = Entries.PreviousEntry [entry];
            
#else
                
Sections.LastEntry [Entries.Section {entry}] = Entries.PreviousEntry [entry];
            
#endif
                
if (Entries.PreviousEntry [entry] != INVALID_ENTRY)
                    
Entries.NextEntry [Entries.PreviousEntry [entry]] = INVALID_ENTRY;
            }
            else
            {
                
Entries.PreviousEntry [Entries.NextEntry [entry]] = Entries.PreviousEntry [entry];
                if (
Entries.PreviousEntry [entry] != INVALID_ENTRY)
                    
Entries.NextEntry [Entries.PreviousEntry [entry]] = Entries.NextEntry [entry];
            }
            
// Move the entry to the end of the sorted list and decrement Entries.Count to forget about the unset Entries.
            
while (pos < (Entries.Count 1))
            {
                
DOF2::SwapSortedEntries (SortedEntryList [pos], SortedEntryList [pos 1]);
                ++
pos;
            }
            --
Entries.Count;
            
FileChanged true;
            return 
1;
        }
    }
    return 
0;
}
stock DOF2::RenameKey (file [], oldkey [], newkey [], tag [] = "")
{
    if (
file [0] && oldkey [0])
    {
        new
            
entry,
            
pos,
        
#if PACK_CONTENT == true
            
line [MAX_LINE_SIZE],
        
#endif
            
keybuf [MAX_LINE_SIZE],
            
valbuf [MAX_LINE_SIZE];
        if (!
CurrentFile [0] || strcmp (CurrentFilefile))
            if (!
DOF2::ParseFile (file, -1false))
                return 
0;
        if ((
entry DOF2::SearchEntry (oldkeytagkeybufvalbufpos)) != INVALID_ENTRY)
        {
            
// Change content of Entries.
        #if PACK_CONTENT == true
            
format (linesizeof (line), "%s = %s"newkeyvalbuf [0] ? valbuf : ("(null)"));
            
strpack (Entries.Line [entry], line);
        
#else
            
format (Entries.Line [entry], sizeof (Entries.Line []), "%s = %s"newkeyvalbuf [0] ? valbuf : ("(null)"));
        
#endif
            // Because the hashcode has been changed, the entry has to move in the list.
            
SortedEntryList [pos][0] = DOF2::HashKey (newkey);
            if (
pos < (MAX_ENTRIES 1) && SortedEntryList [pos][0] > SortedEntryList [pos 1][0])
            {
                
// Hash value of key is greater than the hash value of it's right neighbor, move to the right by swapping the 2 entries.
                
while (pos < (MAX_ENTRIES 1) && SortedEntryList [pos][0] > SortedEntryList [pos 1][0])
                {
                    
DOF2::SwapSortedEntries (SortedEntryList [pos], SortedEntryList [pos 1]);
                    ++
pos;
                }
            }
            else if (
pos && SortedEntryList [pos][0] < SortedEntryList [pos 1][0])
            {
                
// Hash value of key is smaller than the hash value of it' left neighbor, move to the left by swapping the 2 entries.
                
while (pos && SortedEntryList [pos][0] < SortedEntryList [pos 1][0])
                {
                    
DOF2::SwapSortedEntries (SortedEntryList [pos], SortedEntryList [pos 1]);
                    --
pos;
                }
            }
            
FileChanged true;
            return 
1;
        }
    }
    return 
0;
}
stock boolDOF2::IsSet (file [], key [], tag [] = "")
{
    new
        
pos,
        
keybuf [MAX_LINE_SIZE],
        
valbuf [MAX_LINE_SIZE];
    if (!
CurrentFile [0] || strcmp (CurrentFilefile))
        if (!
DOF2::ParseFile (file, -1false))
            return 
false;
    
// Try to find the Entries.
    
return (DOF2::SearchEntry (keytagkeybufvalbufpos) != INVALID_ENTRY);
}
stock DOF2::SetInt (file [], key [], valuetag [] = "")
{
    new 
buf [16];
    
format (bufsizeof (buf), "%d"value);
    return 
DOF2::SetString (filekeybuftag);
}
stock DOF2::GetInt (file [], key [], tag [] = "")
{
    new 
buf [16];
    
DOF2::GetStringEx (filekeybufsizeof (buf), tag);
    return 
strval (buf);
}
stock DOF2::SetHex (file [], key [], valuetag [] = "")
{
    new 
buf [16];
    
DOF2::hexstr (valuebuf);
    return 
DOF2::SetString (filekeybuftag);
}
stock DOF2::GetHex (file [], key [], tag [] = "")
{
    new 
buf [16];
    
DOF2::GetStringEx (filekeybufsizeof (buf), tag);
    return 
DOF2::strhex (buf);
}
stock DOF2::SetBin (file [], key [], valuetag [] = "")
{
    new 
buf [35];
    
DOF2::binstr (valuebuf);
    return 
DOF2::SetString (filekeybuftag);
}
stock DOF2::GetBin (file [], key [], tag [] = "")
{
    new 
buf [35];
    
DOF2::GetStringEx (filekeybufsizeof (buf), tag);
    return 
DOF2::strbin (buf);
}
stock DOF2::SetFloat (file [], key [], Floatvaluetag [] = "")
{
    new 
buf [32];
    
format (bufsizeof (buf), "%.8f"value);
    return 
DOF2::SetString (filekeybuftag);
}
stock FloatDOF2::GetFloat (file [], key [], tag [] = "")
{
    new 
buf [32];
    
DOF2::GetStringEx (filekeybufsizeof (buf), tag);
    return 
floatstr (buf);
}
stock boolDOF2::GetBool (file [], key [], tag [] = "")
{
    new 
buf [16];
    
DOF2::GetStringEx (filekeybufsizeof (buf), tag);
    return (
strval (buf) || (buf [0] && !strcmp (buf"true"true)));
}
stock DOF2::SetBool (file [], key [], boolvaluetag [] = "")
    return 
DOF2::SetString (filekeyvalue ? ("true") : ("false"), tag);
    
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
stock DOF2::PrintFile (comment [] = "")
{
    if (
CurrentFile [0])
    {
        new
            
boolfirstline true,
            
entry,
        
#if PACK_CONTENT == true
            
buf [MAX_LINE_SIZE],
        
#endif
            
entries,
            
i;
        
printf ("[DOF] Current file: %s"CurrentFile);
        for ( ; 
Sections.Count; ++i)
        {
            if (
i)
            {
                if (!
firstline)
                    print (
" ");
                else
                    
firstline false;
            
#if PACK_CONTENT == true
                
strunpack (bufSections.Tag [i]);
                
printf ("[%s]"buf);
            
#else
                
printf ("[%s]"Sections.Tag [i]);
            
#endif
            
}
            
entry Sections.FirstEntry [i];
            while (
entry != INVALID_ENTRY)
            {
            
#if PACK_CONTENT == true
                
strunpack (bufEntries.Line [entry]);
                print (
buf);
            
#else
                
print (Entries.Line [entry]);
            
#endif
                
entry Entries.NextEntry [entry];
                
firstline false;
                ++
entries;
            }
        }
        
printf ("* %d sections, %d entries"ientries);
        if (
comment [0])
            
printf ("* Comment: %s"comment);
        return 
1;
    }
    return 
0;
}
stock DOF2::WriteFile ()
{
    if (
CurrentFile [0])
    {
        new
            
Filefopen (CurrentFileio_write),
            
boolfirstline true,
            
entry;
        if (
f)
        {
            for (new 
iSections.Count; ++i)
            {
                if (
Sections.FirstEntry [i] != INVALID_ENTRY// Do not write when empty.
                
{
                    if (
i)
                    {
                        if (!
firstline)
                        {
                            
fputchar (f'\r'UseUTF8);
                            
fputchar (f'\n'UseUTF8);
                        }
                        else
                            
firstline false;
                        
fputchar (f'['UseUTF8);
                        
fwritechars (fSections.Tag [i]);
                        
fputchar (f']'UseUTF8);
                        
fputchar (f'\r'UseUTF8);
                        
fputchar (f'\n'UseUTF8);
                    }
                    
entry Sections.FirstEntry [i];
                    while (
entry != INVALID_ENTRY)
                    {
                        
fwritechars (fEntries.Line [entry]);
                        
fputchar (f'\r'UseUTF8);
                        
fputchar (f'\n'UseUTF8);
                        
entry Entries.NextEntry [entry];
                        
firstline false;
                    }
                }
            }
            
FileChanged false;
            return 
fclose (f);
        }
    }
    return 
0;
}
stock DOF2::ParseFile (file [], extraid = -1boolcallback false)
{
    if (
file [0] && DOF2::FileExists (file))
    {
        
/*
        Write the file in the buffer when:
        - There is actually a file in the buffer
        - The file in the buffer is not the file you want to parse and this file has been changed.
        - Or the current file is the file you want to and has been changed.
        */
        //if (CurrentFile [0] && ((strcmp (CurrentFile, file) && FileChanged) || FileChanged))
        
if (CurrentFile [0] && FileChanged// Equal to the query above but shorter.
            
DOF2::WriteFile ();
        new
            
Filefopen (fileio_readwrite),
            
buf [MAX_LINE_SIZE],
        
#if PACK_CONTENT == true
            
line [MAX_LINE_SIZE char],
            
tag [MAX_SECTION_TAG],
        
#else
            
line [MAX_LINE_SIZE],
        
#endif
            
key [MAX_LINE_SIZE],
            
value [MAX_LINE_SIZE],
            
c,
            
pos;
        if (
f)
        {
            
FileChanged false;
            
DOF2::SetFile (file);
            
Sections.Count 1;
            
Entries.Count 0;
            
Sections.FirstEntry [0] = Sections.LastEntry [0] = INVALID_ENTRY;
            for (new 
isize flength (f); size; ++i)
            {
                
fgetchar (f0UseUTF8);
                if (
pos == MAX_LINE_SIZE || == '\n' || == '\r')
                    
'\0';
            
#if PACK_CONTENT == true
                
line {pos++} = c;
            
#else
                
line [pos++] = c;
            
#endif
                
if (== '\0')
                {
                    
// A new section found. Add the section to the list of sections.
                #if PACK_CONTENT == true
                    
if (line {0} == '[')
                
#else
                    
if (line [0] == '[')
                
#endif
                    
{
                        if (
Sections.Count MAX_SECTIONS)
                        {
                            
pos 1;
                        
#if PACK_CONTENT == true
                            
while (line {pos} && line {pos} != ']' && (pos 1) < MAX_SECTION_TAG)
                            {
                                
Sections.Tag [Sections.Count]{pos 1} = line {pos};
                                ++
pos;
                            }
                            
Sections.Tag [Sections.Count]{pos 1} = '\0';
                        
#else
                            
while (line [pos] && line [pos] != ']' && (pos 1) < MAX_SECTION_TAG)
                            {
                                
Sections.Tag [Sections.Count][pos 1] = line [pos];
                                ++
pos;
                            }
                            
Sections.Tag [Sections.Count][pos 1] = '\0';
                        
#endif
                            
Sections.FirstEntry [Sections.Count] = Sections.LastEntry [Sections.Count] = INVALID_ENTRY;
                            ++
Sections.Count;
                        }
                    }
                    else
                    {
                    
#if PACK_CONTENT == true
                        
if (line {0})
                    
#else
                        
if (line [0])
                    
#endif
                        
{
                        
#if PACK_CONTENT == true
                            
strunpack (bufline);
                            
DOF2::ParseLine (bufkeyvalue);
                            
strunpack (tagSections.Tag [Sections.Count 1]);
                            
// Call a specific function for a specific entry - ZCMD-style!
                            
if (callback)
                            {
                                
format (bufsizeof (buf), "_OnParseFile_%s_%s"tagkey);
                                if (!
CallRemoteFunction (buf"is"extraidvalue))
                                    
CallRemoteFunction ("_OnDefaultParseFile""issss"extraidvalue [0] ? value : ("\1"), keySections.Tag [Sections.Count 1][0] ? Sections.Tag [Sections.Count 1] : ("\1"), file);
                            }
                        
#else
                            
DOF2::ParseLine (linekeyvalue);
                            
// Call a specific function for a specific entry - ZCMD-style!
                            
if (callback)
                            {
                                
format (bufsizeof (buf), "_OnParseFile_%s_%s"Sections.Tag [Sections.Count 1], key);
                                if (!
CallRemoteFunction (buf"is"extraidvalue))
                                    
CallRemoteFunction ("_OnDefaultParseFile""issss"extraidvalue [0] ? value : ("\1"), keySections.Tag [Sections.Count 1][0] ? Sections.Tag [Sections.Count 1] : ("\1"), file);
                            }
                        
#endif
                            // Add entry to it's section and to the list which will be sorted.
                            
Entries.Line [Entries.Count] = line;
                            
Entries.Tag [Entries.Count] = Sections.Tag [Sections.Count 1];
                        
#if MAX_SECTIONS >= 256
                            
Entries.Section [Entries.Count] = Sections.Count 1;
                        
#else
                            
Entries.Section {Entries.Count} = Sections.Count 1;
                        
#endif
                            
Entries.NextEntry [Entries.Count] = INVALID_ENTRY;
                            
SortedEntryList [Entries.Count][0] = DOF2::HashKey (key);
                            
SortedEntryList [Entries.Count][1] = Entries.Count;
                            if (
Sections.LastEntry [Sections.Count 1] == INVALID_ENTRY)
                            {
                                
Sections.FirstEntry [Sections.Count 1] = Sections.LastEntry [Sections.Count 1] = Entries.Count;
                                
Entries.PreviousEntry [Entries.Count] = INVALID_ENTRY;
                            }
                            else
                            {
                                
Entries.NextEntry [Sections.LastEntry [Sections.Count 1]] = Entries.Count;
                                
Entries.PreviousEntry [Entries.Count] = Sections.LastEntry [Sections.Count 1];
                                
Sections.LastEntry [Sections.Count 1] = Entries.Count;
                            }
                            ++
Entries.Count;
                        }
                    }
                    
pos 0;
                }
            }
            
/*
             * Sort list of entries by it's hashcodes in O(n * log n) time.
             * (Worst case is actually O(n * n), however, this QuickSort implementation chooses a randomized pivot
             * to minimize the chance for the worst case.)
             */
            
DOF2::SortEntries (SortedEntryList0Entries.Count 1true);
            return 
fclose (f);
        }
    }
    return 
0;
}
// Rather useless.
stock DOF2::ReparseFile (file [], extraidboolcallback true)
{
    if (
file [0] && CurrentFile [0] && !strcmp (fileCurrentFile))
    {
        
CurrentFile [0] = '\0';
        return 
DOF2::ParseFile (fileextraidcallback);
    }
    return 
0;
}
private 
DOF2::ParseLine (line [], key [], value [], keysize sizeof (key), valuesize sizeof (value))
{
    new
        
pos,
        
readpos;
    if ((
pos charfind (line'=')) != -1)
    {
        
// Read key and value.
        
readpos pos 1;
        while (
readpos >= && line [readpos] == ' ')
            --
readpos;
        if (
readpos >= && keysize > (readpos 1))
        {
            
key [readpos 1] = '\0';
            while (
readpos >= 0)
            {
                
key [readpos] = line [readpos];
                --
readpos;
            }
        }
        else
            return 
0;
        
readpos pos 1;
        ++
pos;
        while (
line [readpos] == ' ')
        {
            ++
pos;
            ++
readpos;
        }
        if (
line [readpos])
        {
            while (
readpos >= && line [readpos] && valuesize > (readpos pos 1))
            {
                
value [readpos pos] = line [readpos];
                ++
readpos;
            }
            
value [readpos pos] = '\0';
        }
        else
        {
            
key [0] = value [0] = '\0';
            return 
0;
        }
        
        if (!
strcmp (value"(null)"true))
            
value [0] = '\0';
        return 
1;
    }
    
key [0] = value [0] = '\0';
    return 
0;
}
stock DOF2::File (user [])
{
    new 
newfile [MAX_FILE_SIZE];
    
format (newfilesizeof (newfile), USER_FILE_PATHDOF2::udb_encode (user));
    return 
newfile;
}
stock boolDOF2::CheckLogin (file [], password [])
    return (
file [0] && password [0] && DOF2::num_hash (password) == DOF2::GetInt (fileUSER_PW_HASH_KEY));
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
stock DOF2::binstr (valuedest [], size sizeof (dest))
{
    new 
buf [32 3] = "0b";
    for (new 
032; ++i)
        
buf [2] = '0' + ((value >>> (31 i)) & 1);
    
DOF2::strcpy (destbufsize);
}
    
//format (dest, size, "0b%b", value);
stock DOF2::hexstr (valuedest [], size sizeof (dest))
{
    static const 
characters [] =
    {
        
'0''1''2''3',
        
'4''5''6''7',
        
'8''9''A''B',
        
'C''D''E''F'
    
};
    
    new 
buf [3] = "0x";
    
    for (new 
08; ++i)
        
buf [i] = characters [(value >>> ((i) << 2)) & 0x0F];
    
DOF2::strcpy (destbufsize);
}
    
//format (dest, size, "0x%x", value);
stock DOF2::strhex (string [])
{
    new
        
i,
        
value;
        
    if (
string [0] == '0' && (string [1] == 'x' || string [1] == 'X'))
        
2;
    while (
string [i])
    {
        
value <<= 4;
        switch (
string [i])
        {
            case 
'0' .. '9':
                
value |= string [i] - '0';
            case 
'A' .. 'F':
                
value |= string [i] - 'A' 10;
            case 
'a' .. 'f':
                
value |= string [i] - 'a' 10;
            default:
                return 
0;
        }
        ++
i;
    }
    return 
value;
}
stock DOF2::strbin (string [])
{
    new
        
i,
        
value;
    if (
string [0] == '0' && (string [1] == 'b' || string [1] == 'B'))
        
2;
    while (
string [i])
    {
        if (
string [i] != '1' && string [i] != '0')
            return 
0;
        
value <<= 1;
        
value |= (string [i] - '0');
        ++
i;
    }
    return 
value;
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
private charfind (string [], c)
{
    for (new 
ilen strlen (string); len; ++i)
        if (
string [i] == c)
            return 
i;
    return -
1;
}
private 
fwritechars (Filehandle[])
{
    new 
pos;
#if PACK_CONTENT == true
    
while ({pos})
        
fputchar (handle{pos++}, UseUTF8);
#else
    
while ([pos])
        
fputchar (handle[pos++], UseUTF8);
#endif
}
private 
DOF2::SortEntries (entries [][2], lrboolrandomize true)
{
    if (
l)
    {
        if (
randomize)
        {
            new 
+ (random (65535) % (1));
              
DOF2::SwapSortedEntries (entries [k], entries [r]);
        }
        new
            
1,
            
r,
            
pivot entries [r][0];
        while (
j)
        {
            do
                ++
i;
            while (
entries [i][0] <= pivot && r);
            do
                --
j;
            while (
entries [j][0] >= pivot && l);
            if (
j)
                
DOF2::SwapSortedEntries (entries [i], entries [j]);
        }
        
DOF2::SwapSortedEntries (entries [i], entries [r]);
        
DOF2::SortEntries (entriesl1randomize);
        
DOF2::SortEntries (entries1rrandomize);
    }
}
private 
DOF2::SwapSortedEntries ([2], [2])
{
     new 
[2];
    
[0] = [0];
    
[1] = [1];
    
[0] = [0];
    
[1] = [1];
    
[0] = [0];
    
[1] = [1];
}
stock DOF2::SortAllSections (file [], boolignorecase trueboolascending true)
{
    if (
file [0])
    {
        if (!
CurrentFile [0] || strcmp (CurrentFilefile)) // No file in buffer or the file you want to read from is not the file in the buffer.
            
if (!DOF2::ParseFile (file, -1false))
                return 
0;
        new
            
entries [MAX_ENTRIES],
            
keys [MAX_ENTRIES][MAX_LINE_SIZE],
            
key [MAX_LINE_SIZE],
            
value [MAX_LINE_SIZE],
        
#if PACK_CONTENT == true
            
line [MAX_LINE_SIZE],
        
#endif
            
entry,
            
i;
        for (new 
section 0section Sections.Count; ++section)
        {
            
0;
            
entry Sections.FirstEntry [section];
            while (
entry != INVALID_ENTRY)
            {
            
#if PACK_CONTENT == true
                
strunpack (lineEntries.Line [entry]);
                
DOF2::ParseLine (linekeyvalue);
            
#else
                
DOF2::ParseLine (Entries.Line [entry], keyvalue);
            
#endif
                
keys [i][0] = '\0';
                
strcat (keys [i], key);
                
entries [i] = entry;
                
entry Entries.NextEntry [entry];
                ++
i;
            }
            if (
0)
                
DOF2::SortSection_Internal (sectionentrieskeys01ignorecaseascending);
        }
        return 
1;
    }
    return 
0;
}
stock DOF2::SortSection (file [], tag [], boolignorecase trueboolascending true)
{
    if (
file [0])
    {
        if (!
CurrentFile [0] || strcmp (CurrentFilefile)) // No file in buffer or the file you want to read from is not the file in the buffer.
            
if (!DOF2::ParseFile (file, -1false))
                return 
0;
        new
            
section INVALID_SECTION,
            
entries [MAX_ENTRIES],
            
keys [MAX_ENTRIES][MAX_LINE_SIZE],
            
key [MAX_LINE_SIZE],
            
buf [MAX_LINE_SIZE],
        
#if PACK_CONTENT == true
            
line [MAX_LINE_SIZE],
        
#endif
            
entry,
            
i;
        if (!
tag [0])
            
section 0;
        else
        {
            for (
1Sections.Count; ++i)
            {
            
#if PACK_CONTENT == true
                
strunpack (bufSections.Tag [i]);
                if (
buf [0] && !strcmp (tagbuf, !CaseSensitive))
                {
                    
section i;
                    break;
                }
            
#else
                
if (Sections.Tag [i][0] && !strcmp (tagSections.Tag [i], !CaseSensitive))
                {
                    
section i;
                    break;
                }
            
#endif
            
}
        }
        if (
section != INVALID_SECTION)
        {
            
0;
            
entry Sections.FirstEntry [section];
            while (
entry != INVALID_ENTRY)
            {
            
#if PACK_CONTENT == true
                
strunpack (lineEntries.Line [entry]);
                
DOF2::ParseLine (linekeybuf);
            
#else
                
DOF2::ParseLine (Entries.Line [entry], keybuf);
            
#endif
                
keys [i][0] = '\0';
                
strcat (keys [i], key);
                
entries [i] = entry;
                
entry Entries.NextEntry [entry];
                ++
i;
            }
            if (
0)
            {
                
DOF2::SortSection_Internal (sectionentrieskeys01ignorecaseascending);
                return 
1;
            }
        }
    }
    return 
0;
}
private 
DOF2::SortSection_Internal (sectionentries [], keys [][], lrboolignorecase trueboolascending true)
{
    
// Entries must be stored into an array...
    
if (<= section Sections.Count && l)
    {
        new
            
1,
            
r,
            
buf [MAX_LINE_SIZE];
        static
            
pivot [MAX_LINE_SIZE]; // Must be static, otherwise too much memory usage during recursion ==> Script will crash!
        
pivot [0] = '\0';
        
strcat (pivotkeys [r]);
        while (
j)
        {
            if (
ascending)
            {
                do
                    ++
i;
                while (
strcmp (keys [i], pivot,  ignorecase) <= && r);
                do
                    --
j;
                while (
strcmp (keys [j], pivotignorecase) >= && l);
            }
            else
            {
                do
                    ++
i;
                while (
strcmp (keys [i], pivot,  ignorecase) >= && r);
                do
                    --
j;
                while (
strcmp (keys [j], pivotignorecase) <= && l);
            }
            if (
j)
            {
                
DOF2::SwapEntries (sectionentries [i], entries [j]);
                
DOF2::strcpy (bufkeys [i]);
                
DOF2::strcpy (keys [i], keys [j], MAX_LINE_SIZE);
                
DOF2::strcpy (keys [j], bufMAX_LINE_SIZE);
                
entries [i] ^= entries [j];
                
entries [j] ^= entries [i];
                
entries [i] ^= entries [j];
            }
        }
        if (
!= r)
        {
            
DOF2::SwapEntries (sectionentries [i], entries [r]);
            
DOF2::strcpy (bufkeys [i]);
            
DOF2::strcpy (keys [i], keys [r], MAX_LINE_SIZE);
            
DOF2::strcpy (keys [r], bufMAX_LINE_SIZE);
            
entries [i] ^= entries [r];
            
entries [r] ^= entries [i];
            
entries [i] ^= entries [r];
        }
        
DOF2::SortSection_Internal (sectionentrieskeysl1ignorecaseascending);
        
DOF2::SortSection_Internal (sectionentrieskeys1rignorecaseascending);
    }
}
private 
DOF2::SwapEntries (sectionentry1entry2)
{
    
// This swaps two entries in the entry list of a section. (Pointers are swapped)
    
if (<= section Sections.Count && <= entry1 <= Entries.Count && <= entry2 <= Entries.Count)
    {
        if (
entry1 == Sections.FirstEntry [section])
            
Sections.FirstEntry [section] = entry2;
        else if (
entry2 == Sections.FirstEntry [section])
            
Sections.FirstEntry [section] = entry1;
        if (
entry1 == Sections.LastEntry [section])
            
Sections.LastEntry [section] = entry2;
        else if (
entry2 == Sections.LastEntry [section])
            
Sections.LastEntry [section] = entry1;
        if (
Entries.NextEntry [entry1] == entry2)
        {
            
Entries.NextEntry [entry1] = Entries.NextEntry [entry2];
            
Entries.PreviousEntry [entry2] = Entries.PreviousEntry [entry1];
            if (
Entries.PreviousEntry [entry1] != INVALID_ENTRY)
                
Entries.NextEntry [Entries.PreviousEntry [entry1]] = entry2;
            if (
Entries.NextEntry [entry2] != INVALID_ENTRY)
                
Entries.PreviousEntry [Entries.NextEntry [entry2]] = entry1;
            
Entries.NextEntry [entry2] = entry1;
            
Entries.PreviousEntry [entry1] = entry2;
        }
        else if (
Entries.NextEntry [entry2] == entry1)
        {
            
Entries.NextEntry [entry2] = Entries.NextEntry [entry1];
            
Entries.PreviousEntry [entry1] = Entries.PreviousEntry [entry2];
            if (
Entries.PreviousEntry [entry2] != INVALID_ENTRY)
                
Entries.NextEntry [Entries.PreviousEntry [entry2]] = entry1;
            if (
Entries.NextEntry [entry1] != INVALID_ENTRY)
                
Entries.PreviousEntry [Entries.NextEntry [entry1]] = entry2;
            
Entries.NextEntry [entry1] = entry2;
            
Entries.PreviousEntry [entry2] = entry1;
        }
        else
        {
            new 
pointer;
            if (
Entries.PreviousEntry [entry1] != INVALID_ENTRY)
                
Entries.NextEntry [Entries.PreviousEntry [entry1]] = entry2;
            if (
Entries.NextEntry [entry1] != INVALID_ENTRY)
                
Entries.PreviousEntry [Entries.NextEntry [entry1]] = entry2;
            if (
Entries.PreviousEntry [entry2] != INVALID_ENTRY)
                
Entries.NextEntry [Entries.PreviousEntry [entry2]] = entry1;
            if (
Entries.NextEntry [entry2] != INVALID_ENTRY)
                
Entries.PreviousEntry [Entries.NextEntry [entry2]] = entry1;
            
pointer Entries.NextEntry [entry1];
            
Entries.NextEntry [entry1] = Entries.NextEntry [entry2];
            
Entries.NextEntry [entry2] = pointer;
            
pointer Entries.PreviousEntry [entry1];
            
Entries.PreviousEntry [entry1] = Entries.PreviousEntry [entry2];
            
Entries.PreviousEntry [entry2] = pointer;
        }
        return 
1;
    }
    return 
0;
}
private 
DOF2::HashKey (key [])
{
    new
        
= -1,
        
i,
        
j;
    if (
CaseSensitive)
    {
        while ((
key [i++]))
            
33 j;
    }
    else
    {
        while ((
tolower (key [i++])))
            
33 j;
    }
    return 
h;
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
stock DOF2::strcpy (dest [], const src [], size sizeof (dest))
{
    
dest [0] = '\0';
    
strcat (destsrcsize);
}
// Replace [oldstr] with [newstr] in [srcstr] and copy write the new string to 'deststr'.
stock DOF2::strreplace (const newstr [], const oldstr [], const srcstr [], deststr [], boolignorecase falsesize sizeof (deststr))
{
    new
        
newlen strlen (newstr),
        
oldlen strlen (oldstr),
        
srclen strlen (srcstr),
        
idx,
        
rep;
    for (new 
0srclen; ++i)
    {
        if (
idx < (size 1))
        {
            if ((
oldlen) <= srclen)
            {
                if (!
strcmp (srcstr [i], oldstrignorecaseoldlen))
                {
                    
deststr [idx] = '\0';
                    
strcat (deststrnewstrsize);
                    ++
rep;
                    
idx += newlen;
                    
+= oldlen 1;
                }
                else
                    
deststr [idx++] = srcstr [i];
            }
            else
                
deststr [idx++] = srcstr [i];
        }
        else
            return 
rep;
    }
    
deststr [idx] = '\0';
    return 
rep;
}
stock DOF2::udb_encode (nickname [])
{
    new
        
buf [256],
        
result [256];
    static const 
symbols [][2][] =
    {
        {
"_""_00"},
        {
";""_01"},
        {
"!""_02"},
        {
"/""_03"},
        {
"\\""_04"},
        {
"[""_05"},
        {
"]""_06"},
        {
"?""_07"},
        {
".""_08"},
        {
"*""_09"},
        {
"<""_10"},
        {
">""_11"},
        {
"{""_12"},
        {
"}""_13"},
        {
" ""_14"},
        {
"\"""_15"},
        {
":""_16"},
        {
"|""_17"},
        {
"=""_18"}
    };
    
strcat (bufnickname);
    for (new 
0sizeof (symbols); ++i)
    {
        
DOF2::strreplace (symbols [i][1], symbols [i][0], bufresult);
        
DOF2::strcpy (bufresult);
    }
    return 
result;
}
stock DOF2::udb_decode (nickname [])
{
    new
        
buf [256],
        
result [256];
    static const 
symbols [][2][] =
    {
        {
"_""_00"},
        {
";""_01"},
        {
"!""_02"},
        {
"/""_03"},
        {
"\\""_04"},
        {
"[""_05"},
        {
"]""_06"},
        {
"?""_07"},
        {
".""_08"},
        {
"*""_09"},
        {
"<""_10"},
        {
">""_11"},
        {
"{""_12"},
        {
"}""_13"},
        {
" ""_14"},
        {
"\"""_15"},
        {
":""_16"},
        {
"|""_17"},
        {
"=""_18"}
    };
    
strcat (bufnickname);
    for (new 
0sizeof (symbols); ++i)
    {
        
DOF2::strreplace (symbols [i][0], symbols [i][1], bufresult);
        
DOF2::strcpy (bufresult);
    }
    return 
result;
}
stock DOF2::num_hash (buf [])
{
    new
        
length strlen (buf),
        
s1 1,
        
s2 0,
        
n;
    for (
0lengthn++)
    {
       
s1 = (s1 buf [n]) % 65521;
       
s2 = (s2 s1) % 65521;
    }
    return (
s2 << 16) + s1;
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#if defined DUDB_CONVERT
    #tryinclude <dutils>
    #define dUser(%0).(             DOF2_GetString(DOF2_File(%0),
    #define dUserSet(%0).(             DOF2_SetString(DOF2_File(%0),
    #define dUserINT(%0).(             DOF2_GetInt(DOF2_File(%0),
    #define dUserSetINT(%0).(         DOF2_SetInt(DOF2_File(%0),
    #define dUserFLOAT(%0).(         DOF2_GetFloat(DOF2_File(%0),
    #define dUserSetFLOAT(%0).(     DOF2_SetFloat(DOF2_File(%0),
    #define udb_Create(%0,%1)        DOF2_CreateFile(DOF2_File(%0),%1)
    #define udb_RenameUser(%0,%1)   DOF2_RenameFile(DOF2_File(%0),DOF2_File(%1))
    #define udb_Exists(%0)          DOF2_FileExists(DOF2_File(%0))
    #define udb_Remove(%0)          DOF2_RemoveFile(DOF2_File(%0))
    #define udb_CheckLogin(%0,%1)   DOF2_CheckLogin(DOF2_File(%0),%1)
    #if !defined _dudb_included
        #define _dudb_included
    #endif
#endif
#if defined DINI_CONVERT
    #define dini_Exists                DOF2_FileExists
    #define dini_Remove             DOF2_RemoveFile
    #define dini_Create             DOF2_CreateFile
    #define dini_Set                DOF2_SetString
    #define dini_Get                 DOF2_GetString
    #define dini_IntSet               DOF2_SetInt
    #define dini_Int                 DOF2_GetInt
    #define dini_BoolSet            DOF2_SetBool
    #define dini_Bool               DOF2_GetBool
    #define dini_FloatSet             DOF2_SetFloat
    #define dini_Float              DOF2_GetFloat
    #define dini_Unset               DOF2_Unset
    #define dini_Isset               DOF2_IsSet
    #if !defined _dini_included
        #define _dini_included
    #endif
#endif
/*
#if defined DINI_CONVERT || defined DUDB_CONVERT
    #define udb_hash                DOF2_num_hash
    #define num_hash                DOF2_num_hash
    #define udb_encode              DOF2_udb_encode
    #define udb_decode              DOF2_udb_decode
#endif
*/ 
PPC_MissionsLixeiro

PHP код:
// This function gets called whenever a courier player enters "/work"
Lixeiro_StartJob(playerid)
{
    
// Setup local variables
    
new HouseCounterHousesInRange[200], DialogList[200];
    
// First clear the house-list
    
for (new i11i++)
        
APlayerData[playerid][CourierHouses][i] = 0;
    
// Count how many owned houses are in range of the player
    
for (new HouseID 1HouseID MAX_HOUSESHouseID++)
    {
        
// Check if the house is owned
        
if (AHouseData[HouseID][Owned] == true)
        {
            
// Check if the house is in range of the player
            
if (IsPlayerInRangeOfPoint(playeridLixeiroJobRangeAHouseData[HouseID][HouseX], AHouseData[HouseID][HouseY], AHouseData[HouseID][HouseZ]))
            {
                
// Check if there aren't 200 in-range houses have been found yet
                
if (HouseCounter 200)
                {
                    
HousesInRange[HouseCounter] = HouseID// Store the HouseID in the list of in-range houses
                    
HouseCounter++; // Increase the number of owned houses in range of the player (range = 1000 meters)
                
}
                else
                {
                    break; 
// Stop searching for more houses (200 is the maximum)
                
}
            }
        }
    }
    
// Abort the mission if there are less than 2 houses in range and inform the player
    
if (HouseCounter 2)
    {
        
SendClientMessage(playerid0xFFFFFFFF"{FF0000}Nгo а casa no local para recolher lixos, tente algum outro ponto");
        return 
0;
    }
    if (
HouseCounter >= 2)
    {
        
format(DialogListsizeof(DialogList), "Recolher 2 lixos\n"); // Add the line to the dialog
        
APlayerData[playerid][CourierMaxStep] = 2// Set the number of houses for the job to 2
    
}
    if (
HouseCounter >= 5)
    {
        
format(DialogListsizeof(DialogList), "%sRecolher 5 lixos\n"DialogList); // Add the line to the dialog
        
APlayerData[playerid][CourierMaxStep] = 5// Set the number of houses for the job to 5
    
}
    if (
HouseCounter >= 10)
    {
        
format(DialogListsizeof(DialogList), "%sRecolher 10 lixos\n"DialogList); // Add the line to the dialog
        
APlayerData[playerid][CourierMaxStep] = 10// Set the number of houses for the job to 10
    
}
    
APlayerData[playerid][CourierHouses][1] = HousesInRange[random(HouseCounter)];
    
// Now choose as many houses randomly as allowed, starting from the second
    
for (new 2<= APlayerData[playerid][CourierMaxStep]; i++)
    {
        
// Copy a random HouseID from the prepared list on in-range houses to the job-list
        
APlayerData[playerid][CourierHouses][i] = HousesInRange[random(HouseCounter)];
        
// If the HouseID is the same as the previous HouseID (the player would visit the same house twice in a row)
        
while (APlayerData[playerid][CourierHouses][1] == APlayerData[playerid][CourierHouses][i])
            
APlayerData[playerid][CourierHouses][i] = HousesInRange[random(HouseCounter)]; // Get a new random HouseID as long as the HouseID is the same as the previous one
    
}
    
// Let the player choose how many packages he wants to deliver
    
ShowPlayerDialog(playeridDialogCourierSelectQuantDIALOG_STYLE_LIST"Escolha quantos lixos vocк deseja recolher:"DialogListTXT_DialogButtonSelectTXT_DialogButtonCancel);
    return 
1;
}
// This function is called when the player has chosen how many packages he wants to deliver
Lixeiro_BeginJob(playerid)
{
    
// Setup local variables
    
new Lixeiro[128], StepHouseIDFloat:xFloat:yFloat:z,LoadMsgs[128];
    
// Job has started
    
APlayerData[playerid][JobStarted] = true;
    
// Store the vehicleID (required to be able to check if the player left his vehicle)
    
APlayerData[playerid][VehicleID] = GetPlayerVehicleID(playerid);
    
// Set jobstep to 1 (going to the first house)
    
Step 1;
    
APlayerData[playerid][JobStep] = Step;
    
// Get the HouseID of the house where the mission starts (the first house in the list of in-range owned house)
    
HouseID APlayerData[playerid][LixeiroHouses][Step];
    
// Set the TextDraw so the player can see it
    
format(Lixeiro255TXT_LixeiroTextDrawStepAPlayerData[playerid][CourierMaxStep], AHouseData[HouseID][HouseName]);
    
TextDrawSetString(APlayerData[playerid][MissionText], Lixeiro);
    
// Grab the x, y, z positions for the first location
    
AHouseData[HouseID][HouseX];
    
AHouseData[HouseID][HouseY];
    
AHouseData[HouseID][HouseZ];
    
// Create a checkpoint where the player should deliver his package
    
SetPlayerCheckpoint(playeridxyz3);
    
// Set the job-fail-time for the global vehicle-timer
    
APlayerData[playerid][VehicleTimerTime] = Job_TimeToFailMission;
    
// Send the player a message to inform him that the mission has started
    
return 1;
}
// This function is called when a courier enters a checkpoint
Lixeiro_OnPlayerEnterCheckpoint(playerid)
{
    
// Setup local variables
    
new Lixeiro[128], StepHouseIDFloat:xFloat:yFloat:zName[24], Msg[128], Payment;
    
// Check if the player is outside his vehicle while entering a checkpoint
    
if (GetPlayerVehicleSeat(playerid) == -1)
    {
        
// Check if all the packages haven't been delivered
        
if (APlayerData[playerid][CourierMaxStep] != APlayerData[playerid][JobStep])
        {
            
// First disable the current checkpoint
            
DisablePlayerCheckpoint(playerid);
            
// Let the player know he delivered a package
            
GameTextForPlayer(playeridTXT_LixosDeliveredGameText50004);
            
SendClientMessage(playerid0xFFFFFFFFTXT_LixosDeliveredMessage);
            
// Set next JobStep (next house)
            
APlayerData[playerid][JobStep]++;
            
Step APlayerData[playerid][JobStep];
            
// Get the HouseID of the house where the mission starts (the first house in the list of in-range owned house)
            
HouseID APlayerData[playerid][CourierHouses][Step];
            
// Set the TextDraw so the player can see it
            
format(Lixeiro255"~w~Recolher Lixos ~b~%i/%i~w~ para: ~r~%s"StepAPlayerData[playerid][CourierMaxStep], AHouseData[HouseID][HouseName]);
            
TextDrawSetString(APlayerData[playerid][MissionText], Lixeiro);
            
// Grab the x, y, z positions for the first location
            
AHouseData[HouseID][HouseX];
            
AHouseData[HouseID][HouseY];
            
AHouseData[HouseID][HouseZ];
            
// Create a checkpoint where the player should deliver his package
            
SetPlayerCheckpoint(playeridxyz3);
        }
        else 
// All packages have been delivered, the player has to get paid now
        
{
            
// Get the player name
            
GetPlayerName(playeridNamesizeof(Name));
            
// Send a message to all players to inform them that this player completed a courier-job
            
format(Msg128TXT_PlayerCompletedLixeiroJobNameAPlayerData[playerid][CourierMaxStep]);
            
SendClientMessageToAll(0xFFFFFFFFMsg);
            
// Set a payment based on the number of packages
            
Payment APlayerData[playerid][CourierMaxStep] * PaymentPerPackage;
            
// Pay the player money and give scorepoints, both based on the number of packages delivered
            
RewardPlayer(playeridPaymentAPlayerData[playerid][CourierMaxStep]);
            
// Send a message to let the player know he finished his mission and got paid
            
format(Msg128TXT_RewardJobPayment);
            
SendClientMessage(playerid0xFFFFFFFFMsg);
            
// Increase the stats for completing a courier job
            
APlayerData[playerid][StatsLixeiroJobs]++;
            
// End the current trucker job (clear mission-data)
            
Courier_EndJob(playerid);
            
// Also save the data (in case the server crashes, progress would be lost)
            
PlayerFile_Save(playerid);
        }
    }
    else
        
SendClientMessage(playerid0xFFFFFFFFTXT_NeedOnFootToProceed);
    return 
1;
}
// This function is used to stop any Courier-mission that has been started
Lixeiro_EndJob(playerid)
{
    if (
APlayerData[playerid][JobStarted] == true)
    {
        
// Clear all data about the job from the player, so he can start a new one
        
APlayerData[playerid][JobStarted] = false;
        
APlayerData[playerid][JobStep] = 0;
        
APlayerData[playerid][VehicleTimerTime] = 0;
        
APlayerData[playerid][VehicleID] = 0;
        
APlayerData[playerid][CourierMaxStep] = 0;
        
// Clear the list of houses-in-range
        
for (new i11i++)
            
APlayerData[playerid][CourierHouses][i] = 0;
        
// Delete the checkpoint
        
DisablePlayerCheckpoint(playerid);
        
// Reset the missiontext
        
TextDrawSetString(APlayerData[playerid][MissionText], Lixeiro_NoJobText);
    }
    return 
1;

PPC_MissionsPizza

PHP код:
// This function gets called whenever a courier player enters "/work"
Pizza_StartJob(playerid)
{
    
// Setup local variables
    
new HouseCounterHousesInRange[200], DialogList[200];
    
// First clear the house-list
    
for (new i11i++)
        
APlayerData[playerid][CourierHouses][i] = 0;
    
// Count how many owned houses are in range of the player
    
for (new HouseID 1HouseID MAX_HOUSESHouseID++)
    {
        
// Check if the house is owned
        
if (AHouseData[HouseID][Owned] == true)
        {
            
// Check if the house is in range of the player
            
if (IsPlayerInRangeOfPoint(playeridLixeiroJobRangeAHouseData[HouseID][HouseX], AHouseData[HouseID][HouseY], AHouseData[HouseID][HouseZ]))
            {
                
// Check if there aren't 200 in-range houses have been found yet
                
if (HouseCounter 200)
                {
                    
HousesInRange[HouseCounter] = HouseID// Store the HouseID in the list of in-range houses
                    
HouseCounter++; // Increase the number of owned houses in range of the player (range = 1000 meters)
                
}
                else
                {
                    break; 
// Stop searching for more houses (200 is the maximum)
                
}
            }
        }
    }
    
// Abort the mission if there are less than 2 houses in range and inform the player
    
if (HouseCounter 2)
    {
        
SendClientMessage(playerid0xFFFFFFFF"{FF0000}Nгo а casa no local para Entregar Pizzas, tente algum outro ponto");
        return 
0;
    }
    if (
HouseCounter >= 2)
    {
        
format(DialogListsizeof(DialogList), "Entregar 2 Pizzas\n"); // Add the line to the dialog
        
APlayerData[playerid][CourierMaxStep] = 2// Set the number of houses for the job to 2
    
}
    if (
HouseCounter >= 5)
    {
        
format(DialogListsizeof(DialogList), "%sEntregar 5 Pizzas\n"DialogList); // Add the line to the dialog
        
APlayerData[playerid][CourierMaxStep] = 5// Set the number of houses for the job to 5
    
}
    if (
HouseCounter >= 10)
    {
        
format(DialogListsizeof(DialogList), "%sEntregar 10 Pizzas\n"DialogList); // Add the line to the dialog
        
APlayerData[playerid][CourierMaxStep] = 10// Set the number of houses for the job to 10
    
}
    
APlayerData[playerid][CourierHouses][1] = HousesInRange[random(HouseCounter)];
    
// Now choose as many houses randomly as allowed, starting from the second
    
for (new 2<= APlayerData[playerid][CourierMaxStep]; i++)
    {
        
// Copy a random HouseID from the prepared list on in-range houses to the job-list
        
APlayerData[playerid][CourierHouses][i] = HousesInRange[random(HouseCounter)];
        
// If the HouseID is the same as the previous HouseID (the player would visit the same house twice in a row)
        
while (APlayerData[playerid][CourierHouses][1] == APlayerData[playerid][CourierHouses][i])
            
APlayerData[playerid][CourierHouses][i] = HousesInRange[random(HouseCounter)]; // Get a new random HouseID as long as the HouseID is the same as the previous one
    
}
    
// Let the player choose how many packages he wants to deliver
    
ShowPlayerDialog(playeridDialogCourierSelectQuantDIALOG_STYLE_LIST"Escolha quantas Pizzas vocк deseja Entregar:"DialogListTXT_DialogButtonSelectTXT_DialogButtonCancel);
    return 
1;
}
// This function is called when the player has chosen how many packages he wants to deliver
Pizza_BeginJob(playerid)
{
    
// Setup local variables
    
new Pizza[128], StepHouseIDFloat:xFloat:yFloat:z,LoadMsgs[128];
    
// Job has started
    
APlayerData[playerid][JobStarted] = true;
    
// Store the vehicleID (required to be able to check if the player left his vehicle)
    
APlayerData[playerid][VehicleID] = GetPlayerVehicleID(playerid);
    
// Set jobstep to 1 (going to the first house)
    
Step 1;
    
APlayerData[playerid][JobStep] = Step;
    
// Get the HouseID of the house where the mission starts (the first house in the list of in-range owned house)
    
HouseID APlayerData[playerid][LixeiroHouses][Step];
    
// Set the TextDraw so the player can see it
    
format(Pizza255TXT_PizzaTextDrawStepAPlayerData[playerid][CourierMaxStep], AHouseData[HouseID][HouseName]);
    
TextDrawSetString(APlayerData[playerid][MissionText], Pizza);
    
// Grab the x, y, z positions for the first location
    
AHouseData[HouseID][HouseX];
    
AHouseData[HouseID][HouseY];
    
AHouseData[HouseID][HouseZ];
    
// Create a checkpoint where the player should deliver his package
    
SetPlayerCheckpoint(playeridxyz3);
    
// Set the job-fail-time for the global vehicle-timer
    
APlayerData[playerid][VehicleTimerTime] = Job_TimeToFailMission;
    
// Send the player a message to inform him that the mission has started
    
return 1;
}
// This function is called when a courier enters a checkpoint
Pizza_OnPlayerEnterCheckpoint(playerid)
{
    
// Setup local variables
    
new Pizza[128], StepHouseIDFloat:xFloat:yFloat:zName[24], Msg[128], Payment;
    
// Check if the player is outside his vehicle while entering a checkpoint
    
if (GetPlayerVehicleSeat(playerid) == -1)
    {
        
// Check if all the packages haven't been delivered
        
if (APlayerData[playerid][CourierMaxStep] != APlayerData[playerid][JobStep])
        {
            
// First disable the current checkpoint
            
DisablePlayerCheckpoint(playerid);
            
// Let the player know he delivered a package
            
GameTextForPlayer(playeridTXT_PizzaDeliveredGameText50004);
            
SendClientMessage(playerid0xFFFFFFFFTXT_PizzaDeliveredMessage);
            
// Set next JobStep (next house)
            
APlayerData[playerid][JobStep]++;
            
Step APlayerData[playerid][JobStep];
            
// Get the HouseID of the house where the mission starts (the first house in the list of in-range owned house)
            
HouseID APlayerData[playerid][CourierHouses][Step];
            
// Set the TextDraw so the player can see it
            
format(Pizza255,"~w~Entregar pizzas ~b~%i/%i~w~ para: ~r~%s"StepAPlayerData[playerid][CourierMaxStep], AHouseData[HouseID][HouseName]);
            
TextDrawSetString(APlayerData[playerid][MissionText], Pizza);
            
// Grab the x, y, z positions for the first location
            
AHouseData[HouseID][HouseX];
            
AHouseData[HouseID][HouseY];
            
AHouseData[HouseID][HouseZ];
            
// Create a checkpoint where the player should deliver his package
            
SetPlayerCheckpoint(playeridxyz3);
        }
        else 
// All packages have been delivered, the player has to get paid now
        
{
            
// Get the player name
            
GetPlayerName(playeridNamesizeof(Name));
            
// Send a message to all players to inform them that this player completed a courier-job
            
format(Msg128TXT_PlayerCompletedPizzaJobNameAPlayerData[playerid][CourierMaxStep]);
            
SendClientMessageToAll(0xFFFFFFFFMsg);
            
// Set a payment based on the number of packages
            
Payment APlayerData[playerid][CourierMaxStep] * PaymentPerPackage;
            
// Pay the player money and give scorepoints, both based on the number of packages delivered
            
RewardPlayer(playeridPaymentAPlayerData[playerid][CourierMaxStep]);
            
// Send a message to let the player know he finished his mission and got paid
            
format(Msg128TXT_RewardJobPayment);
            
SendClientMessage(playerid0xFFFFFFFFMsg);
            
// Increase the stats for completing a courier job
            
APlayerData[playerid][StatsPizzaJobs]++;
            
// End the current trucker job (clear mission-data)
            
Courier_EndJob(playerid);
            
// Also save the data (in case the server crashes, progress would be lost)
            
PlayerFile_Save(playerid);
        }
    }
    else
        
SendClientMessage(playerid0xFFFFFFFFTXT_NeedOnFootToProceed);
    return 
1;
}
// This function is used to stop any Courier-mission that has been started
Pizza_EndJob(playerid)
{
    if (
APlayerData[playerid][JobStarted] == true)
    {
        
// Clear all data about the job from the player, so he can start a new one
        
APlayerData[playerid][JobStarted] = false;
        
APlayerData[playerid][JobStep] = 0;
        
APlayerData[playerid][VehicleTimerTime] = 0;
        
APlayerData[playerid][VehicleID] = 0;
        
APlayerData[playerid][CourierMaxStep] = 0;
        
// Clear the list of houses-in-range
        
for (new i11i++)
            
APlayerData[playerid][CourierHouses][i] = 0;
        
// Delete the checkpoint
        
DisablePlayerCheckpoint(playerid);
        
// Reset the missiontext
        
TextDrawSetString(APlayerData[playerid][MissionText], Pizza_NoJobText);
    }
    return 
1;

Reply
#2

tentar ai e sу substituir as includes DOF2 e a outra


include DOF2
Код:
#if defined _dof2_included
    #endinput
#endif
#define _dof2_included

#include <a_samp>

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

/*
 * This is a new version of the INI script Double-O-Files.
 * However, it's has completely been rewritten and has now a much better performance.
 * There is also the support for sections in the INI file. (But there is no support for comments.)
 * Double-O-Files 2 is compatible with DUDB, DINI, Double-O-Files and possibly y_ini since it
 * can handle sections and entry of the format "key = value", not only "key=value".
 * The number of spaces between the equal sign and key and value can actually be arbitrary.
 * I've added some comments below. You may see that I've mentioned the big-O-notation,
 * 'n' always Entries.Count.
 * Double-O-Files 2 should also be useful for Russian letter because I'm using
 * the functions fgetchar and fputchar to write and read the files.
 *
 * There is another new feature which has been inspired by ZCMD and y_ini:
 * The OnParseFile callbacks. To learn more about it, read the description in
 * the SA-MP forums if you haven't already.
 * THE END
 */

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

/*
native DOF2_SetFile(file[]);
native DOF2_LoadFile();
native DOF2_SaveFile();
native DOF2_ParseFile(file[],extraid,bool:callback=true);
native DOF2_ReparseFile(file[],extraid,bool:callback=true);
native DOF2_WriteFile();
native DOF2_PrintFile(comment[]="");
native DOF2_GetString(file[],key[],tag[]="");
native DOF2_GetStringEx(file[],key[],result[],size,tag[]="");
native Float:DOF2_GetFloat(file[],key[]);
native DOF2_GetInt(file[],key[],tag[]="");
native DOF2_GetHex(file[],key[],tag[]="");
native DOF2_GetBin(file[],key[],tag[]="");
native bool:DOF2_GetBool(file[],key[],tag[]="");
native DOF2_SetString(file[],key[],value[],tag[]="");
native DOF2_SetFloat(file[],key[],Float:value);
native DOF2_SetInt(file[],key[],value,tag[]="");
native DOF2_SetHex(file[],key[],value,tag[]="");
native DOF2_SetBin(file[],key[],value,tag[]="");
native DOF2_SetBool(file[],key[],bool:value,tag[]="");
native DOF2_IsSet(file[],key[],tag[]="");
native DOF2_Unset(file[],key[],tag[]="");
native DOF2_FileExists(file[]);
native DOF2_RemoveFile(file[]);
native DOF2_CreateFile(file[],password[]="");
native DOF2_RenameFile(oldfile[],newfile[]);
native DOF2_RenameKey(file[],oldkey[],newkey[],tag[]="");
native DOF2_CopyFile(filetocopy[],newfile[]);
native DOF2_CheckLogin(file[],password[]);
native DOF2_File(user[]);
native DOF2_ParseInt();
native DOF2_ParseFloat();
native DOF2_ParseBool();
native DOF2_ParseBin();
native DOF2_ParseHex();
native DOF2_SetUTF8(bool:set);
native bool:DOF2_GetUTF8();
native DOF2_GetFile();
native DOF2_MakeBackup(file[]);
native DOF2_RemoveSection (file [], tag []);
native DOF2_SectionExists (file [], tag []);
native DOF2_SortSection (file [], tag [], bool: ignorecase = true, bool: ascending = true);
native DOF2_SortAllSections (file [], bool: ignorecase = true, bool: ascending = true);
native DOF2_SetCaseSensitivity (bool: set);
native DOF2_GetCaseSensitivity ();
*/

#define DOF2_TagExists  DOF2_SectionExists
#define DOF2_RemoveTag  DOF2_RemoveSection

// OnParseFile <Tag><Key>(extraid, value [])
// OnParseFile <><Key>(extraid, value [])
// OnDefaultParseFile (extraid, value [], key [], tag [], file [])

// The arguments of your OnParseFile functions may have arbitrary names but must be an integer followed by a string.
// Function must return a value.
#define OnParseFile<%0><%1>(%2) \
    forward _OnParseFile_%0_%1 (extraid, value []); \
    public _OnParseFile_%0_%1 (extraid, value []) \
        return __OnParseFile_%0_%1 (extraid, (value [0] == '\1' && value [1] == '\0') ? ("") : value); \
    stock __OnParseFile_%0_%1 (%2)

// Also here: The argument names may be arbitrary but must be an integer followed by 4 strings.
// Function must return a value.
#define OnDefaultParseFile(%0) \
    forward _OnDefaultParseFile (extraid, value [], key [], tag [], file []); \
    public _OnDefaultParseFile (extraid, value [], key [], tag [], file []) \
        return __OnDefaultParseFile (extraid, (value [0] == '\1' && value [1] == '\0') ? ("") : value, key, (tag [0] == '\1' && tag [1] == '\0') ? ("") : tag, file); \
    stock __OnDefaultParseFile (%0)

#define DOF2_ParseBool() \
    (strval (value) || (value [0] && !strcmp (value, "true", true)))

#define DOF2_ParseInt() \
    (strval (value))

#define DOF2_ParseFloat() \
    (floatstr (value))

#define DOF2_ParseBin() \
    (DOF2_strbin (value))

#define DOF2_ParseHex() \
    (DOF2_strhex (value))

#define DOF2_LoadFile() \
    DOF2_ParseFile (CurrentFile, -1, false)

#define DOF2_SaveFile \
    DOF2_WriteFile

#define DOF2_FileExists \
    fexist

#define Sections. \
    Sections_

#define Entries. \
    Entries_

#define DOF2:: \
    DOF2_

#if !defined private
    #define private         static stock
#endif

#pragma dynamic 65536

/*
#define MAX_SECTION_TAG        (32)
#define MAX_LINE_SIZE       (128)
#define MAX_SECTIONS            (32)
#define MAX_ENTRIES         (256)
#define MAX_FILE_SIZE       (64)

#define USER_FILE_PATH         "Users/%s.ini"
*/

// The maximum length of the name of a tag.
#if !defined MAX_SECTION_TAG
    #define MAX_SECTION_TAG        (32)
#endif

// The maximum length of a line (including key and value).
#if !defined MAX_LINE_SIZE
    #define MAX_LINE_SIZE       (128)
#endif

// The maximum number of sections which can be handled. Be careful: MUST NOT be higher than 255.
#if !defined MAX_SECTIONS
    #define MAX_SECTIONS           (32)
#endif

// The maximum number of entries which can be loaded into the cache.
#if !defined MAX_ENTRIES
    #define MAX_ENTRIES         (256)
#endif

// The maximum length of the name of a file.
#if !defined MAX_FILE_SIZE
    #define MAX_FILE_SIZE       (64)
#endif

/*
If PACK_CONTENT == true tag names and lines (key + value) will get stored in cache as packed strings.
The result is less memory usage. However, you won't be able to use special characters like russian or chinese ones.
*/
#if !defined PACK_CONTENT
    #define PACK_CONTENT        (false)
#endif

#define INVALID_ENTRY           (-1)
#define INVALID_SECTION         (-1)

// Do you want to emulate DUDB?
#if !defined DUDB_CONVERT && 0 // Change to 1 to enable.
    #define DUDB_CONVERT
#endif

#if !defined USER_FILE_PATH
    #if defined DUDB_CONVERT
        #define USER_FILE_PATH     "%s.dudb.sav"
    #else
        #define USER_FILE_PATH     "%s.ini"
    #endif
#endif

#if !defined USER_PW_HASH_KEY
    #if defined DUDB_CONVERT
        #define USER_PW_HASH_KEY "password_hash"
    #else
        #define USER_PW_HASH_KEY "password"
    #endif
#endif


// Do you want to emulate DINI?
#if !defined DINI_CONVERT && 0 // Change to 1 to enable.
    #define DINI_CONVERT
#endif

/*
#if MAX_SECTIONS >= 256
    #error MAX_SECTIONS must not be greater than 255.
#endif
*/

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

private
    bool: UseUTF8 = PACK_CONTENT,
    bool: CaseSensitive = false,
    CurrentFile [MAX_FILE_SIZE],
    bool: FileChanged,
    Sections.FirstEntry [MAX_SECTIONS] = {INVALID_ENTRY, ...},
    Sections.LastEntry [MAX_SECTIONS] = {INVALID_ENTRY, ...},
    Sections.Count,
#if PACK_CONTENT == true
    Sections.Tag [MAX_SECTIONS][MAX_SECTION_TAG char],
    Entries.Line [MAX_ENTRIES][MAX_LINE_SIZE char],
    Entries.Tag [MAX_ENTRIES][MAX_SECTION_TAG char],
#else
    Sections.Tag [MAX_SECTIONS][MAX_SECTION_TAG],
    Entries.Line [MAX_ENTRIES][MAX_LINE_SIZE],
    Entries.Tag [MAX_ENTRIES][MAX_SECTION_TAG],
#endif
#if MAX_SECTIONS >= 256
    Entries.Section [MAX_ENTRIES],
#else
    Entries.Section [MAX_ENTRIES char],
#endif
    Entries.NextEntry [MAX_ENTRIES] = {INVALID_ENTRY, ...},
    Entries.PreviousEntry [MAX_ENTRIES] = {INVALID_ENTRY, ...},
    Entries.Count,
    SortedEntryList [MAX_ENTRIES][2]; // Index 0: Hashcode, Index 1: EntryID

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

stock DOF2::Exit ()
    DOF2::WriteFile ();

stock DOF2::SetUTF8 (bool: set)
    UseUTF8 = set;

stock bool: DOF2::GetUTF8 ()
    return UseUTF8;

stock bool: DOF2::SetCaseSensitivity (bool: set)
    CaseSensitive = set;

stock bool: DOF2::GetCaseSensitivity ()
    return CaseSensitive;

stock DOF2::SetFile (file [])
    DOF2::strcpy (CurrentFile, file);

stock DOF2::GetFile ()
    return CurrentFile;

stock DOF2::CreateFile (file [], password [] = "")
{
    if (!DOF2::FileExists (file))
    {
        new File: f = fopen (file, io_append);

        if (fclose (f))
        {
            if (password [0])
                return DOF2::SetInt (file, USER_PW_HASH_KEY, DOF2::num_hash (password));
            return 1;
        }
    }
    return 0;
}

stock DOF2::RenameFile (oldfile [], newfile [])
{
    if (!DOF2::FileExists (newfile))
    {
        // If 'CurrentFile' is 'oldfile', write it if it has been changed.
        if (CurrentFile [0] && !strcmp (CurrentFile, oldfile) && FileChanged)
            DOF2::WriteFile ();
        else if (!DOF2::ParseFile (oldfile, -1, false)) // Otherwise parse 'oldfile'.
            return 0;

        DOF2::SetFile (newfile);
        if (DOF2::WriteFile ())
            return fremove (oldfile);
    }
    return 0;
}

stock DOF2::CopyFile (filetocopy [], newfile [])
{
    if (!DOF2::FileExists (newfile))
    {
        if (CurrentFile [0] && !strcmp (CurrentFile, filetocopy) && FileChanged)
            DOF2::WriteFile ();
        else if(!DOF2::ParseFile (filetocopy, -1, false))
            return 0;

        DOF2::SetFile (newfile);
        return DOF2::WriteFile ();
    }
    return 0;
}

stock DOF2::RemoveFile (file [])
{
    if (file [0])
    {
        if (CurrentFile [0] && !strcmp (CurrentFile, file))
            CurrentFile [0] = '\0';
        return fremove (file);
    }
    return 0;
}

stock DOF2::MakeBackup (file [])
{
    new
        year,
        month,
        day,
        hour,
        minute,
        second,
        backupfile [MAX_FILE_SIZE];

    getdate (year, month, day);
    gettime (hour, minute, second);
    format (backupfile, sizeof (backupfile), "%s.%02d_%02d_%02d.%02d_%02d_%02d_%02d.bak", CurrentFile, month, day, year, hour, minute, second, GetTickCount ());
    return DOF2::CopyFile (CurrentFile, backupfile);
}

stock bool: DOF2::SectionExists (file [], tag [])
{
    if (file [0]) // You can't remove the empty Sections.
    {
        if (!tag [0])
            return true; // Emptry section always exists. In every file.

        if (!CurrentFile [0] || strcmp (CurrentFile, file)) // No file in buffer or the file you want to read from is not the file in the buffer.
            if (!DOF2::ParseFile (file, -1, false))
                return false;

    #if PACK_CONTENT == true
        new buf [MAX_SECTION_TAG];
    #endif

        for (new i = 1; i < Sections.Count; ++i)
        {
        #if PACK_CONTENT == true
            strunpack (buf, Sections.Tag [i]);
            if (!strcmp (buf, tag, !CaseSensitive))
                return true;
        #else
            if (!strcmp (Sections.Tag [i], tag, !CaseSensitive))
                return true;
        #endif
        }
    }
    return false;
}

stock DOF2::RemoveSection (file [], tag [])
{
    // Removes tag 'tag' with all it's entries.
    if (file [0] && tag [0]) // You can't remove the empty Sections.
    {
        if (!CurrentFile [0] || strcmp (CurrentFile, file)) // No file in buffer or the file you want to read from is not the file in the buffer.
            if (!DOF2::ParseFile (file, -1, false))
                return 0;

        new
        #if PACK_CONTENT == true
            line [MAX_LINE_SIZE],
        #endif
            buf [MAX_SECTION_TAG],
            section = INVALID_SECTION,
            entry,
            key [MAX_LINE_SIZE];

        for (new i = 1; i < Sections.Count; ++i)
        {
        #if PACK_CONTENT == true
            strunpack (buf, Sections.Tag [i]);
            if (!strcmp (buf, tag, !CaseSensitive))
            {
                section = i;
                break;
            }
        #else
            if (!strcmp (Sections.Tag [i], tag, !CaseSensitive))
            {
                section = i;
                break;
            }
        #endif
        }

        if (section != INVALID_SECTION)
        {
            entry = Sections.FirstEntry [section];
            while (entry != INVALID_ENTRY)
            {
                // Remove all entries under the current Sections.
            #if PACK_CONTENT == true
                strunpack (line, Entries.Line [entry]);
                DOF2::ParseLine (line, key, buf);
            #else
                DOF2::ParseLine (Entries.Line [entry], key, buf);
            #endif
                DOF2::Unset (file, key, tag);
                entry = Entries.NextEntry [entry];
            }

            // Move the last tag to the position of the current tag. Creates a little mess.
            --Sections.Count;
            Sections.Tag [section] = Sections.Tag [Sections.Count];
            Sections.FirstEntry [section] = Sections.FirstEntry [Sections.Count];
            Sections.LastEntry [section] = Sections.LastEntry [Sections.Count];

            // Adjust the tag IDs of the entries.
            entry = Sections.FirstEntry [section];
            while (entry != INVALID_ENTRY)
            {
            #if MAX_SECTIONS >= 256
                Entries.Section [entry] = section;
            #else
                Entries.Section {entry} = section;
            #endif
                entry = Entries.NextEntry [entry];
            }
            FileChanged = true;
            return 1;
        }
    }
    return 0;
}

private DOF2::SearchEntry (key [], tag [], keybuf [], valbuf [], &pos, keybufsize = sizeof (keybuf), valbufsize = sizeof (valbuf))
{
    if (key [0] && Entries.Count)
    {
        new
            entry = INVALID_ENTRY,
            l,
            m,
            r,
            h,
        #if PACK_CONTENT == true
            line [MAX_LINE_SIZE],
            buf [MAX_SECTION_TAG],
        #endif
            i;

        h = DOF2::HashKey (key);
        l = 0;
        r = Entries.Count - 1;

        /*
         * Binary search in a sorted list of entries in O(log n) time. This algorithm makes for example with 256 elements a maximum of ~8 steps until the entry is found if it exists.
         * A sequential search would take up to 256 steps. That was the case in the first Double-O-Files script.
         */
        while (l <= r)
        {
            if ((r - l) < 2)
            {
                if (h == SortedEntryList [l][0])
                {
                    m = l;
                    entry = SortedEntryList [l][1];
                }
                else if (r > l && h == SortedEntryList [r][0])
                {
                    m = r;
                    entry = SortedEntryList [r][1];
                }
                break;
            }
            else
            {
                m = l + (r - l) / 2;
                if (h == SortedEntryList [m][0])
                {
                    entry = SortedEntryList [m][1];
                    break;
                }
                else if (h > SortedEntryList [m][0])
                    l = m + 1;
                else
                    r = m - 1;
            }
        }

        // Candidate found?
        if (entry != INVALID_ENTRY)
        {
            // Check if it's the entry we want.
          #if PACK_CONTENT == true
            strunpack (line, Entries.Line [entry]);
            DOF2::ParseLine (line, keybuf, valbuf, keybufsize, valbufsize);
            strunpack (buf, Entries.Tag [entry]);
            if (!strcmp (keybuf, key, !CaseSensitive) && ((!tag [0] && !buf [0]) || (tag [0] && buf [0] && !strcmp (tag, buf, !CaseSensitive))))
        #else
            DOF2::ParseLine (Entries.Line [entry], keybuf, valbuf, keybufsize, valbufsize);
            if (!strcmp (keybuf, key, !CaseSensitive) && ((!tag [0] && !Entries.Tag [entry][0]) || (tag [0] && Entries.Tag [entry][0] && !strcmp (tag, Entries.Tag [entry], !CaseSensitive))))
        #endif
                return (pos = m, entry);
            else
            {
                // If not, look left and right in the list for entries with the same hash code. This can be collisions or entries with the same key from another section.
                for (i = m - 1; i >= 0 && h == SortedEntryList [i][0]; --i)
                {
                    entry = SortedEntryList [i][1];
                 #if PACK_CONTENT == true
                    strunpack (line, Entries.Line [entry]);
                    DOF2::ParseLine (line, keybuf, valbuf, keybufsize, valbufsize);
                    strunpack (buf, Entries.Tag [entry]);
                    if (!strcmp (keybuf, key, !CaseSensitive) && ((!tag [0] && !buf [0]) || (tag [0] && buf [0] && !strcmp (tag, buf, !CaseSensitive))))
                #else
                    DOF2::ParseLine (Entries.Line [entry], keybuf, valbuf, keybufsize, valbufsize);
                    if (!strcmp (keybuf, key, !CaseSensitive) && ((!tag [0] && !Entries.Tag [entry][0]) || (tag [0] && Entries.Tag [entry][0] && !strcmp (tag, Entries.Tag [entry], !CaseSensitive))))
                #endif
                        return (pos = i, entry);
                }

                for (i = m + 1; i < Entries.Count && h == SortedEntryList [i][0]; ++i)
                {
                    entry = SortedEntryList [i][1];
                 #if PACK_CONTENT == true
                    strunpack (line, Entries.Line [entry]);
                    DOF2::ParseLine (line, keybuf, valbuf, keybufsize, valbufsize);
                    strunpack (buf, Entries.Tag [entry]);
                    if (!strcmp (keybuf, key, !CaseSensitive) && ((!tag [0] && !buf [0]) || (tag [0] && buf [0] && !strcmp (tag, buf, !CaseSensitive))))
                #else
                    DOF2::ParseLine (Entries.Line [entry], keybuf, valbuf, keybufsize, valbufsize);
                    if (!strcmp (keybuf, key, !CaseSensitive) && ((!tag [0] && !Entries.Tag [entry][0]) || (tag [0] && Entries.Tag [entry][0] && !strcmp (tag, Entries.Tag [entry], !CaseSensitive))))
                #endif
                        return (pos = i, entry);
                }
            }
        }
    }

    keybuf [0] = valbuf [0] = '\0';
    return INVALID_ENTRY;
}

stock DOF2::SetString (file [], key [], value [], tag [] = "")
{
    if (file [0] && key [0])
    {
        new
            entry,
            pos,
            section = INVALID_SECTION,
            keybuf [MAX_LINE_SIZE],
            valbuf [MAX_LINE_SIZE],
        #if PACK_CONTENT == true
            buf [MAX_SECTION_TAG],
            line [MAX_LINE_SIZE],
        #endif
            i;

        if (!CurrentFile [0] || strcmp (CurrentFile, file)) // No file in buffer or the file you want to read from is not the file in the buffer.
            if (!DOF2::ParseFile (file, -1, false))
                return 0;

        entry = DOF2::SearchEntry (key, tag, keybuf, valbuf, pos);

        // If the entry has been found, just change it's content.
        if (entry != INVALID_ENTRY)
        {
            FileChanged = true;
        #if PACK_CONTENT == true
            format (line, sizeof (line), "%s = %s", key, value [0] ? value : ("(null)"));
            return strpack (Entries.Line [entry], line);
        #else
            format (Entries.Line [entry], sizeof (Entries.Line []), "%s = %s", key, value [0] ? value : ("(null)"));
            return 1;
        #endif
        }

        if (Entries.Count >= MAX_ENTRIES)
            return 0;

        // Search for the section where the entry belongs.
        if (!tag [0])
            section = 0;
        else
        {
            for (i = 1; i < Sections.Count; ++i)
            {
            #if PACK_CONTENT == true
                strunpack (buf, Sections.Tag [i]);
                if (buf [0] && !strcmp (tag, buf, !CaseSensitive))
                {
                    section = i;
                    break;
                }
            #else
                if (Sections.Tag [i][0] && !strcmp (tag, Sections.Tag [i], !CaseSensitive))
                {
                    section = i;
                    break;
                }
            #endif
            }
        }

        // Section we want does not exist, create new one if possible.
        if (section == INVALID_SECTION)
        {
            if (Sections.Count >= MAX_SECTIONS)
                return 0;

            section = Sections.Count++;
        #if PACK_CONTENT == true
            strpack (Sections.Tag [section], tag);
        #else
            DOF2::strcpy (Sections.Tag [section], tag);
        #endif
            Sections.FirstEntry [section] = Sections.LastEntry [section] = INVALID_ENTRY;
        }

        // Add the entry to the section. Section's content is defined by a linear two way list.
    #if PACK_CONTENT == true
        format (line, sizeof (line), "%s = %s", key, value [0] ? value : ("(null)"));
        strpack (Entries.Line [Entries.Count], line);
    #else
        format (Entries.Line [Entries.Count], sizeof (Entries.Line []), "%s = %s", key, value [0] ? value : ("(null)"));
    #endif
        Entries.Tag [Entries.Count] = Sections.Tag [section];
    #if MAX_SECTIONS >= 256
        Entries.Section [Entries.Count] = section;
    #else
        Entries.Section {Entries.Count} = section;
    #endif
        Entries.NextEntry [Entries.Count] = INVALID_ENTRY;

        // Add entry to sorted list of entries and move to right correct position in O(n) time.
        SortedEntryList [Entries.Count][0] = DOF2::HashKey (key);
        SortedEntryList [Entries.Count][1] = Entries.Count;
        i = Entries.Count - 1;
        while (i >= 0 && SortedEntryList [i][0] > SortedEntryList [i + 1][0])
        {
            DOF2::SwapSortedEntries (SortedEntryList [i], SortedEntryList [i + 1]);
            --i;
        }

        if (Sections.LastEntry [section] == INVALID_ENTRY) // No entry in this section.
        {
            Sections.FirstEntry [section] = Sections.LastEntry [section] = Entries.Count;
            Entries.PreviousEntry [Entries.Count] = INVALID_ENTRY;
        }
        else
        {
            Entries.NextEntry [Sections.LastEntry [section]] = Entries.Count;
            Entries.PreviousEntry [Entries.Count] = Sections.LastEntry [section];
            Sections.LastEntry [section] = Entries.Count;
        }
        ++Entries.Count;
        FileChanged = true;
    }
    return 1;
}

stock DOF2::GetString (file [], key [], tag [] = "")
{
    new buf [MAX_LINE_SIZE];
    DOF2::GetStringEx (file, key, buf, sizeof (buf), tag);
    return buf;
}

stock DOF2::GetStringEx (file [], key [], result [], size, tag [] = "")
{
    if (file [0] && key [0])
    {
        new
            pos,
            keybuf [MAX_LINE_SIZE];

        if (!CurrentFile [0] || strcmp (CurrentFile, file))
        {
            if (!DOF2::ParseFile (file, -1, false))
            {
                result [0] = '\0';
                return 0;
            }
        }

        // Find entry and assign the result with it's value.
        return (DOF2::SearchEntry (key, tag, keybuf, result, pos, sizeof (keybuf), size) != INVALID_ENTRY);
    }
    return 0;
}

stock DOF2::Unset (file [], key [], tag [] = "")
{
    if (file [0] && key [0])
    {
        new
            entry,
            pos,
            keybuf [MAX_LINE_SIZE],
            valbuf [MAX_LINE_SIZE];

        if (!CurrentFile [0] || strcmp (CurrentFile, file))
            if (!DOF2::ParseFile (file, -1, false))
                return 0;

        if ((entry = DOF2::SearchEntry (key, tag, keybuf, valbuf, pos)) != INVALID_ENTRY)
        {
            // Remove entry from it's section.
        #if MAX_SECTIONS >= 256
            if (Sections.FirstEntry [Entries.Section [entry]] == entry) // Is the entry the first entry in the section? Make it's next entry the first entry.
        #else
            if (Sections.FirstEntry [Entries.Section {entry}] == entry)
        #endif
            {
            #if MAX_SECTIONS >= 256
                Sections.FirstEntry [Entries.Section [entry]] = Entries.NextEntry [entry];
            #else
                Sections.FirstEntry [Entries.Section {entry}] = Entries.NextEntry [entry];
            #endif
                if (Entries.NextEntry [entry] != INVALID_ENTRY)
                    Entries.PreviousEntry [Entries.NextEntry [entry]] = INVALID_ENTRY;
            }
            else
            {
                Entries.NextEntry [Entries.PreviousEntry [entry]] = Entries.NextEntry [entry];
                if (Entries.NextEntry [entry] != INVALID_ENTRY)
                    Entries.PreviousEntry [Entries.NextEntry [entry]] = Entries.PreviousEntry [entry];
            }

        #if MAX_SECTIONS >= 256
            if (Sections.LastEntry [Entries.Section [entry]] == entry)
        #else
            if (Sections.LastEntry [Entries.Section {entry}] == entry)
        #endif
            {
            #if MAX_SECTIONS >= 256
                Sections.LastEntry [Entries.Section [entry]] = Entries.PreviousEntry [entry];
            #else
                Sections.LastEntry [Entries.Section {entry}] = Entries.PreviousEntry [entry];
            #endif
                if (Entries.PreviousEntry [entry] != INVALID_ENTRY)
                    Entries.NextEntry [Entries.PreviousEntry [entry]] = INVALID_ENTRY;
            }
            else
            {
                Entries.PreviousEntry [Entries.NextEntry [entry]] = Entries.PreviousEntry [entry];
                if (Entries.PreviousEntry [entry] != INVALID_ENTRY)
                    Entries.NextEntry [Entries.PreviousEntry [entry]] = Entries.NextEntry [entry];
            }

            // Move the entry to the end of the sorted list and decrement Entries.Count to forget about the unset Entries.
            while (pos < (Entries.Count - 1))
            {
                DOF2::SwapSortedEntries (SortedEntryList [pos], SortedEntryList [pos + 1]);
                ++pos;
            }
            --Entries.Count;
            FileChanged = true;
            return 1;
        }
    }
    return 0;
}

stock DOF2::RenameKey (file [], oldkey [], newkey [], tag [] = "")
{
    if (file [0] && oldkey [0])
    {
        new
            entry,
            pos,
        #if PACK_CONTENT == true
            line [MAX_LINE_SIZE],
        #endif
            keybuf [MAX_LINE_SIZE],
            valbuf [MAX_LINE_SIZE];

        if (!CurrentFile [0] || strcmp (CurrentFile, file))
            if (!DOF2::ParseFile (file, -1, false))
                return 0;

        if ((entry = DOF2::SearchEntry (oldkey, tag, keybuf, valbuf, pos)) != INVALID_ENTRY)
        {
            // Change content of Entries.
        #if PACK_CONTENT == true
            format (line, sizeof (line), "%s = %s", newkey, valbuf [0] ? valbuf : ("(null)"));
            strpack (Entries.Line [entry], line);
        #else
            format (Entries.Line [entry], sizeof (Entries.Line []), "%s = %s", newkey, valbuf [0] ? valbuf : ("(null)"));
        #endif

            // Because the hashcode has been changed, the entry has to move in the list.
            SortedEntryList [pos][0] = DOF2::HashKey (newkey);
            if (pos < (MAX_ENTRIES - 1) && SortedEntryList [pos][0] > SortedEntryList [pos + 1][0])
            {
                // Hash value of key is greater than the hash value of it's right neighbor, move to the right by swapping the 2 entries.
                while (pos < (MAX_ENTRIES - 1) && SortedEntryList [pos][0] > SortedEntryList [pos + 1][0])
                {
                    DOF2::SwapSortedEntries (SortedEntryList [pos], SortedEntryList [pos + 1]);
                    ++pos;
                }
            }
            else if (pos > 0 && SortedEntryList [pos][0] < SortedEntryList [pos + 1][0])
            {
                // Hash value of key is smaller than the hash value of it' left neighbor, move to the left by swapping the 2 entries.
                while (pos > 0 && SortedEntryList [pos][0] < SortedEntryList [pos - 1][0])
                {
                    DOF2::SwapSortedEntries (SortedEntryList [pos], SortedEntryList [pos - 1]);
                    --pos;
                }
            }

            FileChanged = true;
            return 1;
        }
    }
    return 0;
}

stock bool: DOF2::IsSet (file [], key [], tag [] = "")
{
    new
        pos,
        keybuf [MAX_LINE_SIZE],
        valbuf [MAX_LINE_SIZE];

    if (!CurrentFile [0] || strcmp (CurrentFile, file))
        if (!DOF2::ParseFile (file, -1, false))
            return false;

    // Try to find the Entries.
    return (DOF2::SearchEntry (key, tag, keybuf, valbuf, pos) != INVALID_ENTRY);
}

stock DOF2::SetInt (file [], key [], value, tag [] = "")
{
    new buf [16];
    format (buf, sizeof (buf), "%d", value);
    return DOF2::SetString (file, key, buf, tag);
}

stock DOF2::GetInt (file [], key [], tag [] = "")
{
    new buf [16];
    DOF2::GetStringEx (file, key, buf, sizeof (buf), tag);
    return strval (buf);
}

stock DOF2::SetHex (file [], key [], value, tag [] = "")
{
    new buf [16];
    DOF2::hexstr (value, buf);
    return DOF2::SetString (file, key, buf, tag);
}

stock DOF2::GetHex (file [], key [], tag [] = "")
{
    new buf [16];
    DOF2::GetStringEx (file, key, buf, sizeof (buf), tag);
    return DOF2::strhex (buf);
}

stock DOF2::SetBin (file [], key [], value, tag [] = "")
{
    new buf [35];
    DOF2::binstr (value, buf);
    return DOF2::SetString (file, key, buf, tag);
}

stock DOF2::GetBin (file [], key [], tag [] = "")
{
    new buf [35];
    DOF2::GetStringEx (file, key, buf, sizeof (buf), tag);
    return DOF2::strbin (buf);
}

stock DOF2::SetFloat (file [], key [], Float: value, tag [] = "")
{
    new buf [32];
    format (buf, sizeof (buf), "%.8f", value);
    return DOF2::SetString (file, key, buf, tag);
}

stock Float: DOF2::GetFloat (file [], key [], tag [] = "")
{
    new buf [32];
    DOF2::GetStringEx (file, key, buf, sizeof (buf), tag);
    return floatstr (buf);
}

stock bool: DOF2::GetBool (file [], key [], tag [] = "")
{
    new buf [16];
    DOF2::GetStringEx (file, key, buf, sizeof (buf), tag);
    return (strval (buf) || (buf [0] && !strcmp (buf, "true", true)));
}

stock DOF2::SetBool (file [], key [], bool: value, tag [] = "")
    return DOF2::SetString (file, key, value ? ("true") : ("false"), tag);

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

stock DOF2::PrintFile (comment [] = "")
{
    if (CurrentFile [0])
    {
        new
            bool: firstline = true,
            entry,
        #if PACK_CONTENT == true
            buf [MAX_LINE_SIZE],
        #endif
            entries,
            i;

        printf ("[DOF] Current file: %s", CurrentFile);
        for ( ; i < Sections.Count; ++i)
        {
            if (i)
            {
                if (!firstline)
                    print (" ");
                else
                    firstline = false;
            #if PACK_CONTENT == true
                strunpack (buf, Sections.Tag [i]);
                printf ("[%s]", buf);
            #else
                printf ("[%s]", Sections.Tag [i]);
            #endif
            }
            entry = Sections.FirstEntry [i];
            while (entry != INVALID_ENTRY)
            {
            #if PACK_CONTENT == true
                strunpack (buf, Entries.Line [entry]);
                print (buf);
            #else
                print (Entries.Line [entry]);
            #endif
                entry = Entries.NextEntry [entry];
                firstline = false;
                ++entries;
            }
        }
        printf ("* %d sections, %d entries", i, entries);
        if (comment [0])
            printf ("* Comment: %s", comment);
        return 1;
    }
    return 0;
}

stock DOF2::WriteFile ()
{
    if (CurrentFile [0])
    {
        new
            File: f = fopen (CurrentFile, io_write),
            bool: firstline = true,
            entry;

        if (f)
        {
            for (new i; i < Sections.Count; ++i)
            {
                if (Sections.FirstEntry [i] != INVALID_ENTRY) // Do not write when empty.
                {
                    if (i)
                    {
                        if (!firstline)
                        {
                            fputchar (f, '\r', UseUTF8);
                            fputchar (f, '\n', UseUTF8);
                        }
                        else
                            firstline = false;
                        fputchar (f, '[', UseUTF8);
                        fwritechars (f, Sections.Tag [i]);
                        fputchar (f, ']', UseUTF8);
                        fputchar (f, '\r', UseUTF8);
                        fputchar (f, '\n', UseUTF8);
                    }

                    entry = Sections.FirstEntry [i];
                    while (entry != INVALID_ENTRY)
                    {
                        fwritechars (f, Entries.Line [entry]);
                        fputchar (f, '\r', UseUTF8);
                        fputchar (f, '\n', UseUTF8);
                        entry = Entries.NextEntry [entry];
                        firstline = false;
                    }
                }
            }
            FileChanged = false;
            return fclose (f);
        }
    }
    return 0;
}

stock DOF2::ParseFile (file [], extraid = -1, bool: callback = false)
{
    if (file [0] && DOF2::FileExists (file))
    {
        /*
        Write the file in the buffer when:
        - There is actually a file in the buffer
        - The file in the buffer is not the file you want to parse and this file has been changed.
        - Or the current file is the file you want to and has been changed.
        */
        //if (CurrentFile [0] && ((strcmp (CurrentFile, file) && FileChanged) || FileChanged))
        if (CurrentFile [0] && FileChanged) // Equal to the query above but shorter.
            DOF2::WriteFile ();

        new
            File: f = fopen (file, io_readwrite),
            buf [MAX_LINE_SIZE],
        #if PACK_CONTENT == true
            line [MAX_LINE_SIZE char],
            tag [MAX_SECTION_TAG],
        #else
            line [MAX_LINE_SIZE],
        #endif
            key [MAX_LINE_SIZE],
            value [MAX_LINE_SIZE],
            c,
            pos;

        if (f)
        {
            FileChanged = false;
            DOF2::SetFile (file);

            Sections.Count = 1;
            Entries.Count = 0;
            Sections.FirstEntry [0] = Sections.LastEntry [0] = INVALID_ENTRY;

            for (new i, size = flength (f); i < size; ++i)
            {
                c = fgetchar (f, 0, UseUTF8);
                if (pos == MAX_LINE_SIZE - 1 || c == '\n' || c == '\r')
                    c = '\0';
            #if PACK_CONTENT == true
                line {pos++} = c;
            #else
                line [pos++] = c;
            #endif

                if (c == '\0')
                {
                    // A new section found. Add the section to the list of sections.
                #if PACK_CONTENT == true
                    if (line {0} == '[')
                #else
                    if (line [0] == '[')
                #endif
                    {
                        if (Sections.Count < MAX_SECTIONS)
                        {
                            pos = 1;
                        #if PACK_CONTENT == true
                            while (line {pos} && line {pos} != ']' && (pos - 1) < MAX_SECTION_TAG)
                            {
                                Sections.Tag [Sections.Count]{pos - 1} = line {pos};
                                ++pos;
                            }
                            Sections.Tag [Sections.Count]{pos - 1} = '\0';
                        #else
                            while (line [pos] && line [pos] != ']' && (pos - 1) < MAX_SECTION_TAG)
                            {
                                Sections.Tag [Sections.Count][pos - 1] = line [pos];
                                ++pos;
                            }
                            Sections.Tag [Sections.Count][pos - 1] = '\0';
                        #endif
                            Sections.FirstEntry [Sections.Count] = Sections.LastEntry [Sections.Count] = INVALID_ENTRY;
                            ++Sections.Count;
                        }
                    }
                    else
                    {
                    #if PACK_CONTENT == true
                        if (line {0})
                    #else
                        if (line [0])
                    #endif
                        {
                        #if PACK_CONTENT == true
                            strunpack (buf, line);
                            DOF2::ParseLine (buf, key, value);
                            strunpack (tag, Sections.Tag [Sections.Count - 1]);

                            // Call a specific function for a specific entry - ZCMD-style!
                            if (callback)
                            {
                                format (buf, sizeof (buf), "_OnParseFile_%s_%s", tag, key);
                                if (!CallRemoteFunction (buf, "is", extraid, value))
                                    CallRemoteFunction ("_OnDefaultParseFile", "issss", extraid, value [0] ? value : ("\1"), key, Sections.Tag [Sections.Count - 1][0] ? Sections.Tag [Sections.Count - 1] : ("\1"), file);
                            }
                        #else
                            DOF2::ParseLine (line, key, value);

                            // Call a specific function for a specific entry - ZCMD-style!
                            if (callback)
                            {
                                format (buf, sizeof (buf), "_OnParseFile_%s_%s", Sections.Tag [Sections.Count - 1], key);
                                if (!CallRemoteFunction (buf, "is", extraid, value))
                                    CallRemoteFunction ("_OnDefaultParseFile", "issss", extraid, value [0] ? value : ("\1"), key, Sections.Tag [Sections.Count - 1][0] ? Sections.Tag [Sections.Count - 1] : ("\1"), file);
                            }
                        #endif

                            // Add entry to it's section and to the list which will be sorted.
                            Entries.Line [Entries.Count] = line;
                            Entries.Tag [Entries.Count] = Sections.Tag [Sections.Count - 1];
                        #if MAX_SECTIONS >= 256
                            Entries.Section [Entries.Count] = Sections.Count - 1;
                        #else
                            Entries.Section {Entries.Count} = Sections.Count - 1;
                        #endif
                            Entries.NextEntry [Entries.Count] = INVALID_ENTRY;

                            SortedEntryList [Entries.Count][0] = DOF2::HashKey (key);
                            SortedEntryList [Entries.Count][1] = Entries.Count;

                            if (Sections.LastEntry [Sections.Count - 1] == INVALID_ENTRY)
                            {
                                Sections.FirstEntry [Sections.Count - 1] = Sections.LastEntry [Sections.Count - 1] = Entries.Count;
                                Entries.PreviousEntry [Entries.Count] = INVALID_ENTRY;
                            }
                            else
                            {
                                Entries.NextEntry [Sections.LastEntry [Sections.Count - 1]] = Entries.Count;
                                Entries.PreviousEntry [Entries.Count] = Sections.LastEntry [Sections.Count - 1];
                                Sections.LastEntry [Sections.Count - 1] = Entries.Count;
                            }
                            ++Entries.Count;
                        }
                    }
                    pos = 0;
                }
            }
            /*
             * Sort list of entries by it's hashcodes in O(n * log n) time.
             * (Worst case is actually O(n * n), however, this QuickSort implementation chooses a randomized pivot
             * to minimize the chance for the worst case.)
             */
            DOF2::SortEntries (SortedEntryList, 0, Entries.Count - 1, true);
            return fclose (f);
        }
    }
    return 0;
}

// Rather useless.
stock DOF2::ReparseFile (file [], extraid, bool: callback = true)
{
    if (file [0] && CurrentFile [0] && !strcmp (file, CurrentFile))
    {
        CurrentFile [0] = '\0';
        return DOF2::ParseFile (file, extraid, callback);
    }
    return 0;
}

private DOF2::ParseLine (line [], key [], value [], keysize = sizeof (key), valuesize = sizeof (value))
{
    new
        pos,
        readpos;

    if ((pos = charfind (line, '=')) != -1)
    {
        // Read key and value.
        readpos = pos - 1;
        while (readpos >= 0 && line [readpos] == ' ')
            --readpos;

        if (readpos >= 0 && keysize > (readpos + 1))
        {
            key [readpos + 1] = '\0';
            while (readpos >= 0)
            {
                key [readpos] = line [readpos];
                --readpos;
            }
        }
        else
            return 0;

        readpos = pos + 1;
        ++pos;
        while (line [readpos] == ' ')
        {
            ++pos;
            ++readpos;
        }

        if (line [readpos])
        {
            while (readpos >= 0 && line [readpos] && valuesize > (readpos - pos + 1))
            {
                value [readpos - pos] = line [readpos];
                ++readpos;
            }
            value [readpos - pos] = '\0';
        }
        else
        {
            key [0] = value [0] = '\0';
            return 0;
        }

        if (!strcmp (value, "(null)", true))
            value [0] = '\0';
        return 1;
    }
    key [0] = value [0] = '\0';
    return 0;
}

stock DOF2::File (user [])
{
    new newfile [MAX_FILE_SIZE];
    format (newfile, sizeof (newfile), USER_FILE_PATH, DOF2::udb_encode (user));
    return newfile;
}

stock bool: DOF2::CheckLogin (file [], password [])
    return (file [0] && password [0] && DOF2::num_hash (password) == DOF2::GetInt (file, USER_PW_HASH_KEY));

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

stock DOF2::binstr (value, dest [], size = sizeof (dest))
{
    new buf [32 + 3] = "0b";
    for (new i = 0; i < 32; ++i)
        buf [i + 2] = '0' + ((value >>> (31 - i)) & 1);

    DOF2::strcpy (dest, buf, size);
}
    //format (dest, size, "0b%b", value);

stock DOF2::hexstr (value, dest [], size = sizeof (dest))
{
    static const characters [] =
    {
        '0', '1', '2', '3',
        '4', '5', '6', '7',
        '8', '9', 'A', 'B',
        'C', 'D', 'E', 'F'
    };

    new buf [8 + 3] = "0x";

    for (new i = 0; i < 8; ++i)
        buf [2 + i] = characters [(value >>> ((7 - i) << 2)) & 0x0F];

    DOF2::strcpy (dest, buf, size);
}
    //format (dest, size, "0x%x", value);

stock DOF2::strhex (string [])
{
    new
        i,
        value;

    if (string [0] == '0' && (string [1] == 'x' || string [1] == 'X'))
        i = 2;

    while (string [i])
    {
        value <<= 4;
        switch (string [i])
        {
            case '0' .. '9':
                value |= string [i] - '0';

            case 'A' .. 'F':
                value |= string [i] - 'A' + 10;

            case 'a' .. 'f':
                value |= string [i] - 'a' + 10;

            default:
                return 0;
        }
        ++i;
    }
    return value;
}

stock DOF2::strbin (string [])
{
    new
        i,
        value;

    if (string [0] == '0' && (string [1] == 'b' || string [1] == 'B'))
        i = 2;

    while (string [i])
    {
        if (string [i] != '1' && string [i] != '0')
            return 0;

        value <<= 1;
        value |= (string [i] - '0');
        ++i;
    }
    return value;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

private charfind (string [], c)
{
    for (new i, len = strlen (string); i < len; ++i)
        if (string [i] == c)
            return i;
    return -1;
}

private fwritechars (File: handle, c [])
{
    new pos;
#if PACK_CONTENT == true
    while (c {pos})
        fputchar (handle, c {pos++}, UseUTF8);
#else
    while (c [pos])
        fputchar (handle, c [pos++], UseUTF8);
#endif
}

private DOF2::SortEntries (entries [][2], l, r, bool: randomize = true)
{
    if (r > l)
    {
        if (randomize)
        {
            new k = l + (random (65535) % (r - l + 1));
              DOF2::SwapSortedEntries (entries [k], entries [r]);
        }

        new
            i = l - 1,
            j = r,
            pivot = entries [r][0];

        while (i < j)
        {
            do
                ++i;
            while (entries [i][0] <= pivot && i < r);

            do
                --j;
            while (entries [j][0] >= pivot && j > l);

            if (i < j)
                DOF2::SwapSortedEntries (entries [i], entries [j]);
        }
        DOF2::SwapSortedEntries (entries [i], entries [r]);
        DOF2::SortEntries (entries, l, i - 1, randomize);
        DOF2::SortEntries (entries, i + 1, r, randomize);
    }
}

private DOF2::SwapSortedEntries (x [2], z [2])
{
     new c [2];
    c [0] = x [0];
    c [1] = x [1];
    x [0] = z [0];
    x [1] = z [1];
    z [0] = c [0];
    z [1] = c [1];
}

stock DOF2::SortAllSections (file [], bool: ignorecase = true, bool: ascending = true)
{
    if (file [0])
    {
        if (!CurrentFile [0] || strcmp (CurrentFile, file)) // No file in buffer or the file you want to read from is not the file in the buffer.
            if (!DOF2::ParseFile (file, -1, false))
                return 0;

        new
            entries [MAX_ENTRIES],
            keys [MAX_ENTRIES][MAX_LINE_SIZE],
            key [MAX_LINE_SIZE],
            value [MAX_LINE_SIZE],
        #if PACK_CONTENT == true
            line [MAX_LINE_SIZE],
        #endif
            entry,
            i;

        for (new section = 0; section < Sections.Count; ++section)
        {
            i = 0;
            entry = Sections.FirstEntry [section];
            while (entry != INVALID_ENTRY)
            {
            #if PACK_CONTENT == true
                strunpack (line, Entries.Line [entry]);
                DOF2::ParseLine (line, key, value);
            #else
                DOF2::ParseLine (Entries.Line [entry], key, value);
            #endif
                keys [i][0] = '\0';
                strcat (keys [i], key);
                entries [i] = entry;
                entry = Entries.NextEntry [entry];
                ++i;
            }

            if (i > 0)
                DOF2::SortSection_Internal (section, entries, keys, 0, i - 1, ignorecase, ascending);
        }
        return 1;
    }
    return 0;
}

stock DOF2::SortSection (file [], tag [], bool: ignorecase = true, bool: ascending = true)
{
    if (file [0])
    {
        if (!CurrentFile [0] || strcmp (CurrentFile, file)) // No file in buffer or the file you want to read from is not the file in the buffer.
            if (!DOF2::ParseFile (file, -1, false))
                return 0;

        new
            section = INVALID_SECTION,
            entries [MAX_ENTRIES],
            keys [MAX_ENTRIES][MAX_LINE_SIZE],
            key [MAX_LINE_SIZE],
            buf [MAX_LINE_SIZE],
        #if PACK_CONTENT == true
            line [MAX_LINE_SIZE],
        #endif
            entry,
            i;

        if (!tag [0])
            section = 0;
        else
        {
            for (i = 1; i < Sections.Count; ++i)
            {
            #if PACK_CONTENT == true
                strunpack (buf, Sections.Tag [i]);
                if (buf [0] && !strcmp (tag, buf, !CaseSensitive))
                {
                    section = i;
                    break;
                }
            #else
                if (Sections.Tag [i][0] && !strcmp (tag, Sections.Tag [i], !CaseSensitive))
                {
                    section = i;
                    break;
                }
            #endif
            }
        }

        if (section != INVALID_SECTION)
        {
            i = 0;
            entry = Sections.FirstEntry [section];
            while (entry != INVALID_ENTRY)
            {
            #if PACK_CONTENT == true
                strunpack (line, Entries.Line [entry]);
                DOF2::ParseLine (line, key, buf);
            #else
                DOF2::ParseLine (Entries.Line [entry], key, buf);
            #endif
                keys [i][0] = '\0';
                strcat (keys [i], key);
                entries [i] = entry;
                entry = Entries.NextEntry [entry];
                ++i;
            }

            if (i > 0)
            {
                DOF2::SortSection_Internal (section, entries, keys, 0, i - 1, ignorecase, ascending);
                return 1;
            }
        }
    }
    return 0;
}

private DOF2::SortSection_Internal (section, entries [], keys [][], l, r, bool: ignorecase = true, bool: ascending = true)
{
    // Entries must be stored into an array...
    if (0 <= section < Sections.Count && r > l)
    {
        new
            i = l - 1,
            j = r,
            buf [MAX_LINE_SIZE];

        static
            pivot [MAX_LINE_SIZE]; // Must be static, otherwise too much memory usage during recursion ==> Script will crash!

        pivot [0] = '\0';
        strcat (pivot, keys [r]);

        while (i < j)
        {
            if (ascending)
            {
                do
                    ++i;
                while (strcmp (keys [i], pivot,  ignorecase) <= 0 && i < r);

                do
                    --j;
                while (strcmp (keys [j], pivot, ignorecase) >= 0 && j > l);
            }
            else
            {
                do
                    ++i;
                while (strcmp (keys [i], pivot,  ignorecase) >= 0 && i < r);

                do
                    --j;
                while (strcmp (keys [j], pivot, ignorecase) <= 0 && j > l);
            }

            if (i < j)
            {
                DOF2::SwapEntries (section, entries [i], entries [j]);

                DOF2::strcpy (buf, keys [i]);
                DOF2::strcpy (keys [i], keys [j], MAX_LINE_SIZE);
                DOF2::strcpy (keys [j], buf, MAX_LINE_SIZE);

                entries [i] ^= entries [j];
                entries [j] ^= entries [i];
                entries [i] ^= entries [j];
            }
        }

        if (i != r)
        {
            DOF2::SwapEntries (section, entries [i], entries [r]);

            DOF2::strcpy (buf, keys [i]);
            DOF2::strcpy (keys [i], keys [r], MAX_LINE_SIZE);
            DOF2::strcpy (keys [r], buf, MAX_LINE_SIZE);

            entries [i] ^= entries [r];
            entries [r] ^= entries [i];
            entries [i] ^= entries [r];
        }

        DOF2::SortSection_Internal (section, entries, keys, l, i - 1, ignorecase, ascending);
        DOF2::SortSection_Internal (section, entries, keys, i + 1, r, ignorecase, ascending);
    }
}

private DOF2::SwapEntries (section, entry1, entry2)
{
    // This swaps two entries in the entry list of a section. (Pointers are swapped)
    if (0 <= section < Sections.Count && 0 <= entry1 <= Entries.Count && 0 <= entry2 <= Entries.Count)
    {
        if (entry1 == Sections.FirstEntry [section])
            Sections.FirstEntry [section] = entry2;
        else if (entry2 == Sections.FirstEntry [section])
            Sections.FirstEntry [section] = entry1;

        if (entry1 == Sections.LastEntry [section])
            Sections.LastEntry [section] = entry2;
        else if (entry2 == Sections.LastEntry [section])
            Sections.LastEntry [section] = entry1;

        if (Entries.NextEntry [entry1] == entry2)
        {
            Entries.NextEntry [entry1] = Entries.NextEntry [entry2];
            Entries.PreviousEntry [entry2] = Entries.PreviousEntry [entry1];

            if (Entries.PreviousEntry [entry1] != INVALID_ENTRY)
                Entries.NextEntry [Entries.PreviousEntry [entry1]] = entry2;

            if (Entries.NextEntry [entry2] != INVALID_ENTRY)
                Entries.PreviousEntry [Entries.NextEntry [entry2]] = entry1;

            Entries.NextEntry [entry2] = entry1;
            Entries.PreviousEntry [entry1] = entry2;
        }
        else if (Entries.NextEntry [entry2] == entry1)
        {
            Entries.NextEntry [entry2] = Entries.NextEntry [entry1];
            Entries.PreviousEntry [entry1] = Entries.PreviousEntry [entry2];

            if (Entries.PreviousEntry [entry2] != INVALID_ENTRY)
                Entries.NextEntry [Entries.PreviousEntry [entry2]] = entry1;

            if (Entries.NextEntry [entry1] != INVALID_ENTRY)
                Entries.PreviousEntry [Entries.NextEntry [entry1]] = entry2;

            Entries.NextEntry [entry1] = entry2;
            Entries.PreviousEntry [entry2] = entry1;
        }
        else
        {
            new pointer;

            if (Entries.PreviousEntry [entry1] != INVALID_ENTRY)
                Entries.NextEntry [Entries.PreviousEntry [entry1]] = entry2;

            if (Entries.NextEntry [entry1] != INVALID_ENTRY)
                Entries.PreviousEntry [Entries.NextEntry [entry1]] = entry2;

            if (Entries.PreviousEntry [entry2] != INVALID_ENTRY)
                Entries.NextEntry [Entries.PreviousEntry [entry2]] = entry1;

            if (Entries.NextEntry [entry2] != INVALID_ENTRY)
                Entries.PreviousEntry [Entries.NextEntry [entry2]] = entry1;

            pointer = Entries.NextEntry [entry1];
            Entries.NextEntry [entry1] = Entries.NextEntry [entry2];
            Entries.NextEntry [entry2] = pointer;

            pointer = Entries.PreviousEntry [entry1];
            Entries.PreviousEntry [entry1] = Entries.PreviousEntry [entry2];
            Entries.PreviousEntry [entry2] = pointer;
        }
        return 1;
    }
    return 0;
}

private DOF2::HashKey (key [])
{
    new
        h = -1,
        i,
        j;

    if (CaseSensitive)
    {
        while ((j = key [i++]))
            h = h * 33 + j;
    }
    else
    {
        while ((j = tolower (key [i++])))
            h = h * 33 + j;
    }
    return h;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

stock DOF2::strcpy (dest [], const src [], size = sizeof (dest))
{
    dest [0] = '\0';
    strcat (dest, src, size);
}

// Replace [oldstr] with [newstr] in [srcstr] and copy write the new string to 'deststr'.

stock DOF2::strreplace (const newstr [], const oldstr [], const srcstr [], deststr [], bool: ignorecase = false, size = sizeof (deststr))
{
    new
        newlen = strlen (newstr),
        oldlen = strlen (oldstr),
        srclen = strlen (srcstr),
        idx,
        rep;

    for (new i = 0; i < srclen; ++i)
    {
        if (idx < (size - 1))
        {
            if ((i + oldlen) <= srclen)
            {
                if (!strcmp (srcstr [i], oldstr, ignorecase, oldlen))
                {
                    deststr [idx] = '\0';
                    strcat (deststr, newstr, size);
                    ++rep;
                    idx += newlen;
                    i += oldlen - 1;
                }
                else
                    deststr [idx++] = srcstr [i];
            }
            else
                deststr [idx++] = srcstr [i];
        }
        else
            return rep;
    }
    deststr [idx] = '\0';
    return rep;
}

stock DOF2::udb_encode (nickname [])
{
    new
        buf [256],
        result [256];

    static const symbols [][2][] =
    {
        {"_", "_00"},
        {";", "_01"},
        {"!", "_02"},
        {"/", "_03"},
        {"\\", "_04"},
        {"[", "_05"},
        {"]", "_06"},
        {"?", "_07"},
        {".", "_08"},
        {"*", "_09"},
        {"<", "_10"},
        {">", "_11"},
        {"{", "_12"},
        {"}", "_13"},
        {" ", "_14"},
        {"\"", "_15"},
        {":", "_16"},
        {"|", "_17"},
        {"=", "_18"}
    };

    strcat (buf, nickname);
    for (new i = 0; i < sizeof (symbols); ++i)
    {
        DOF2::strreplace (symbols [i][1], symbols [i][0], buf, result);
        DOF2::strcpy (buf, result);
    }
    return result;
}

stock DOF2::udb_decode (nickname [])
{
    new
        buf [256],
        result [256];

    static const symbols [][2][] =
    {
        {"_", "_00"},
        {";", "_01"},
        {"!", "_02"},
        {"/", "_03"},
        {"\\", "_04"},
        {"[", "_05"},
        {"]", "_06"},
        {"?", "_07"},
        {".", "_08"},
        {"*", "_09"},
        {"<", "_10"},
        {">", "_11"},
        {"{", "_12"},
        {"}", "_13"},
        {" ", "_14"},
        {"\"", "_15"},
        {":", "_16"},
        {"|", "_17"},
        {"=", "_18"}
    };

    strcat (buf, nickname);
    for (new i = 0; i < sizeof (symbols); ++i)
    {
        DOF2::strreplace (symbols [i][0], symbols [i][1], buf, result);
        DOF2::strcpy (buf, result);
    }
    return result;
}

stock DOF2::num_hash (buf [])
{
    new
        length = strlen (buf),
        s1 = 1,
        s2 = 0,
        n;

    for (n = 0; n < length; n++)
    {
       s1 = (s1 + buf [n]) % 65521;
       s2 = (s2 + s1) % 65521;
    }
    return (s2 << 16) + s1;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

#if defined DUDB_CONVERT

    #tryinclude <dutils>

    #define dUser(%0).(             DOF2_GetString(DOF2_File(%0),
    #define dUserSet(%0).(             DOF2_SetString(DOF2_File(%0),
    #define dUserINT(%0).(             DOF2_GetInt(DOF2_File(%0),
    #define dUserSetINT(%0).(         DOF2_SetInt(DOF2_File(%0),
    #define dUserFLOAT(%0).(         DOF2_GetFloat(DOF2_File(%0),
    #define dUserSetFLOAT(%0).(     DOF2_SetFloat(DOF2_File(%0),
    #define udb_Create(%0,%1)        DOF2_CreateFile(DOF2_File(%0),%1)
    #define udb_RenameUser(%0,%1)   DOF2_RenameFile(DOF2_File(%0),DOF2_File(%1))
    #define udb_Exists(%0)          DOF2_FileExists(DOF2_File(%0))
    #define udb_Remove(%0)          DOF2_RemoveFile(DOF2_File(%0))
    #define udb_CheckLogin(%0,%1)   DOF2_CheckLogin(DOF2_File(%0),%1)

    #if !defined _dudb_included
        #define _dudb_included
    #endif

#endif

#if defined DINI_CONVERT

    #define dini_Exists                DOF2_FileExists
    #define dini_Remove             DOF2_RemoveFile
    #define dini_Create             DOF2_CreateFile
    #define dini_Set                DOF2_SetString
    #define dini_Get                 DOF2_GetString
    #define dini_IntSet               DOF2_SetInt
    #define dini_Int                 DOF2_GetInt
    #define dini_BoolSet            DOF2_SetBool
    #define dini_Bool               DOF2_GetBool
    #define dini_FloatSet             DOF2_SetFloat
    #define dini_Float              DOF2_GetFloat
    #define dini_Unset               DOF2_Unset
    #define dini_Isset               DOF2_IsSet

    #if !defined _dini_included
        #define _dini_included
    #endif

#endif

/*
#if defined DINI_CONVERT || defined DUDB_CONVERT

    #define udb_hash                DOF2_num_hash
    #define num_hash                DOF2_num_hash
    #define udb_encode              DOF2_udb_encode
    #define udb_decode              DOF2_udb_decode

#endif
*/





Include PPC_MissionsPizza

pawn Код:
// This function gets called whenever a courier player enters "/work"
Pizza_StartJob(playerid)
{
    // Setup local variables
    new HouseCounter, HousesInRange[200], DialogList[200];

    // First clear the house-list
    for (new i; i < 11; i++)
        APlayerData[playerid][CourierHouses][i] = 0;

    // Count how many owned houses are in range of the player
    for (new HouseID = 1; HouseID < MAX_HOUSES; HouseID++)
    {
        // Check if the house is owned
        if (AHouseData[HouseID][Owned] == true)
        {
            // Check if the house is in range of the player
            if (IsPlayerInRangeOfPoint(playerid, LixeiroJobRange, AHouseData[HouseID][HouseX], AHouseData[HouseID][HouseY], AHouseData[HouseID][HouseZ]))
            {
                // Check if there aren't 200 in-range houses have been found yet
                if (HouseCounter < 200)
                {
                    HousesInRange[HouseCounter] = HouseID; // Store the HouseID in the list of in-range houses
                    HouseCounter++; // Increase the number of owned houses in range of the player (range = 1000 meters)
                }
                else
                {
                    break; // Stop searching for more houses (200 is the maximum)
                }
            }
        }
    }

    // Abort the mission if there are less than 2 houses in range and inform the player
    if (HouseCounter < 2)
    {
        SendClientMessage(playerid, 0xFFFFFFFF, "{FF0000}Nгo а casa no local para Entregar Pizzas, tente algum outro ponto");
        return 0;
    }
    if (HouseCounter >= 2)
    {
        format(DialogList, sizeof(DialogList), "Entregar 2 Pizzas\n"); // Add the line to the dialog
        APlayerData[playerid][CourierMaxStep] = 2; // Set the number of houses for the job to 2
    }
    if (HouseCounter >= 5)
    {
        format(DialogList, sizeof(DialogList), "%sEntregar 5 Pizzas\n", DialogList); // Add the line to the dialog
        APlayerData[playerid][CourierMaxStep] = 5; // Set the number of houses for the job to 5
    }
    if (HouseCounter >= 10)
    {
        format(DialogList, sizeof(DialogList), "%sEntregar 10 Pizzas\n", DialogList); // Add the line to the dialog
        APlayerData[playerid][CourierMaxStep] = 10; // Set the number of houses for the job to 10
    }

    APlayerData[playerid][CourierHouses][1] = HousesInRange[random(HouseCounter)];
    // Now choose as many houses randomly as allowed, starting from the second
    for (new i = 2; i <= APlayerData[playerid][CourierMaxStep]; i++)
    {
        // Copy a random HouseID from the prepared list on in-range houses to the job-list
        APlayerData[playerid][CourierHouses][i] = HousesInRange[random(HouseCounter)];

        // If the HouseID is the same as the previous HouseID (the player would visit the same house twice in a row)
        while (APlayerData[playerid][CourierHouses][i - 1] == APlayerData[playerid][CourierHouses][i])
            APlayerData[playerid][CourierHouses][i] = HousesInRange[random(HouseCounter)]; // Get a new random HouseID as long as the HouseID is the same as the previous one
    }

    // Let the player choose how many packages he wants to deliver
    ShowPlayerDialog(playerid, DialogCourierSelectQuant, DIALOG_STYLE_LIST, "Escolha quantas Pizzas vocк deseja Entregar:", DialogList, TXT_DialogButtonSelect, TXT_DialogButtonCancel);

    return 1;
}

// This function is called when the player has chosen how many packages he wants to deliver
Pizza_BeginJob(playerid)
{
    // Setup local variables
    new Pizza[128], Step, HouseID, Float:x, Float:y, Float:z;

    // Job has started
    APlayerData[playerid][JobStarted] = true;
    // Store the vehicleID (required to be able to check if the player left his vehicle)
    APlayerData[playerid][VehicleID] = GetPlayerVehicleID(playerid);
    // Set jobstep to 1 (going to the first house)
    Step = 1;
    APlayerData[playerid][JobStep] = Step;
    // Get the HouseID of the house where the mission starts (the first house in the list of in-range owned house)
    HouseID = APlayerData[playerid][LixeiroHouses][Step];
    // Set the TextDraw so the player can see it
    format(Pizza, 255, TXT_PizzaTextDraw, Step, APlayerData[playerid][CourierMaxStep], AHouseData[HouseID][HouseName]);
    TextDrawSetString(APlayerData[playerid][MissionText], Pizza);
    // Grab the x, y, z positions for the first location
    x = AHouseData[HouseID][HouseX];
    y = AHouseData[HouseID][HouseY];
    z = AHouseData[HouseID][HouseZ];
    // Create a checkpoint where the player should deliver his package
    SetPlayerCheckpoint(playerid, x, y, z, 3);
    // Set the job-fail-time for the global vehicle-timer
    APlayerData[playerid][VehicleTimerTime] = Job_TimeToFailMission;
    // Send the player a message to inform him that the mission has started

    return 1;
}



// This function is called when a courier enters a checkpoint
Pizza_OnPlayerEnterCheckpoint(playerid)
{
    // Setup local variables
    new Pizza[128], Step, HouseID, Float:x, Float:y, Float:z, Name[24], Msg[128], Payment;

    // Check if the player is outside his vehicle while entering a checkpoint
    if (GetPlayerVehicleSeat(playerid) == -1)
    {
        // Check if all the packages haven't been delivered
        if (APlayerData[playerid][CourierMaxStep] != APlayerData[playerid][JobStep])
        {
            // First disable the current checkpoint
            DisablePlayerCheckpoint(playerid);
            // Let the player know he delivered a package
            GameTextForPlayer(playerid, TXT_PizzaDeliveredGameText, 5000, 4);
            SendClientMessage(playerid, 0xFFFFFFFF, TXT_PizzaDeliveredMessage);
            // Set next JobStep (next house)
            APlayerData[playerid][JobStep]++;
            Step = APlayerData[playerid][JobStep];
            // Get the HouseID of the house where the mission starts (the first house in the list of in-range owned house)
            HouseID = APlayerData[playerid][CourierHouses][Step];
            // Set the TextDraw so the player can see it
            format(Pizza, 255,"~w~Entregar pizzas ~b~%i/%i~w~ para: ~r~%s", Step, APlayerData[playerid][CourierMaxStep], AHouseData[HouseID][HouseName]);
            TextDrawSetString(APlayerData[playerid][MissionText], Pizza);
            // Grab the x, y, z positions for the first location
            x = AHouseData[HouseID][HouseX];
            y = AHouseData[HouseID][HouseY];
            z = AHouseData[HouseID][HouseZ];
            // Create a checkpoint where the player should deliver his package
            SetPlayerCheckpoint(playerid, x, y, z, 3);
        }
        else // All packages have been delivered, the player has to get paid now
        {
            // Get the player name
            GetPlayerName(playerid, Name, sizeof(Name));
            // Send a message to all players to inform them that this player completed a courier-job
            format(Msg, 128, TXT_PlayerCompletedPizzaJob, Name, APlayerData[playerid][CourierMaxStep]);
            SendClientMessageToAll(0xFFFFFFFF, Msg);
            // Set a payment based on the number of packages
            Payment = APlayerData[playerid][CourierMaxStep] * PaymentPerPackage;
            // Pay the player money and give scorepoints, both based on the number of packages delivered
            RewardPlayer(playerid, Payment, APlayerData[playerid][CourierMaxStep]);
            // Send a message to let the player know he finished his mission and got paid
            format(Msg, 128, TXT_RewardJob, Payment);
            SendClientMessage(playerid, 0xFFFFFFFF, Msg);

            // Increase the stats for completing a courier job
            APlayerData[playerid][StatsPizzaJobs]++;
            // End the current trucker job (clear mission-data)
            Courier_EndJob(playerid);
            // Also save the data (in case the server crashes, progress would be lost)
            PlayerFile_Save(playerid);
        }
    }
    else
        SendClientMessage(playerid, 0xFFFFFFFF, TXT_NeedOnFootToProceed);

    return 1;
}



// This function is used to stop any Courier-mission that has been started
Pizza_EndJob(playerid)
{
    if (APlayerData[playerid][JobStarted] == true)
    {
        // Clear all data about the job from the player, so he can start a new one
        APlayerData[playerid][JobStarted] = false;
        APlayerData[playerid][JobStep] = 0;
        APlayerData[playerid][VehicleTimerTime] = 0;
        APlayerData[playerid][VehicleID] = 0;
        APlayerData[playerid][CourierMaxStep] = 0;

        // Clear the list of houses-in-range
        for (new i; i < 11; i++)
            APlayerData[playerid][CourierHouses][i] = 0;

        // Delete the checkpoint
        DisablePlayerCheckpoint(playerid);
        // Reset the missiontext
        TextDrawSetString(APlayerData[playerid][MissionText], Pizza_NoJobText);
    }

    return 1;
}
Reply
#3

Obrigado quebrei muita a cabeзa para arrumar os 26... e a PPC_MissionsLixeiro?
Reply
#4

Quote:
Originally Posted by Nork
Посмотреть сообщение
Obrigado quebrei muita a cabeзa para arrumar os 26... e a PPC_MissionsLixeiro?
mesma coisa Crtl + h e cola LoadMsgs e deleta !
Reply
#5

Amigo, consegui sу tenho oque lhe agradeзer foi dias arrumando Dieguinho qualquer coisa fale comigo pelo Skype: caio_scripter.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)