#include forward OnCharacterSaved(playerid); forward OnCharacterLoaded(playerid); forward Character_Select(playerid, dialogid, response, listitem, string:inputtext[]); forward Character_Delete(playerid, dialogid, response, listitem, string:inputtext[]); #define MAX_PLAYER_CHARACTERS 3 static CharacterSQLID[MAX_PLAYERS]; static CharacterName[MAX_PLAYERS][MAX_PLAYER_NAME]; static Gender[MAX_PLAYERS]; static Age[MAX_PLAYERS]; static Race[MAX_PLAYERS]; static Float:Health[MAX_PLAYERS]; static Float:Armour[MAX_PLAYERS]; static Float:LastX[MAX_PLAYERS]; static Float:LastY[MAX_PLAYERS]; static Float:LastZ[MAX_PLAYERS]; static Float:LastA[MAX_PLAYERS]; static LastVW[MAX_PLAYERS]; static LastInt[MAX_PLAYERS]; static CharacterListSQLIDS[MAX_PLAYERS][MAX_PLAYER_CHARACTERS]; static CharacterListNames[MAX_PLAYERS][MAX_PLAYER_CHARACTERS][MAX_PLAYER_NAME]; static CharacterCount[MAX_PLAYERS]; hook OnMySQLPreClose() { foreach(new i : Player) { if(IsPlayerSpawned(i)) { CallRemoteFunction("OnCharacterSaved", "i", i); } } } hook OnPlayerConnect(playerid) { CharacterSQLID[playerid] = 0; CharacterName[playerid][0] = EOS; Gender[playerid] = 0; Age[playerid] = 0; Race[playerid] = 0; Health[playerid] = 100.0; Armour[playerid] = 0.0; LastX[playerid] = 0.0; LastY[playerid] = 0.0; LastZ[playerid] = 4.0; LastA[playerid] = 0.0; LastVW[playerid] = 0; LastInt[playerid] = 0; for(new i; i < MAX_PLAYER_CHARACTERS; i++) { CharacterListSQLIDS[playerid][i] = 0; CharacterListNames[playerid][i][0] = EOS; } CharacterCount[playerid] = 0; } hook OnPlayerDisconnect(playerid, reason) { if(IsPlayerSpawned(playerid)) { new string[64]; new DisconnectReason[3][] = {"Timeout/Crash", "Quit", "Kick/Ban"}; format(string, sizeof(string), "* %s has left the server. (%s)", ReturnPlayerRPName(playerid), DisconnectReason[reason]); ProxDetector(20.0, playerid, string, 0xb3b3b3ff, 0xb3b3b3ff, 0xb3b3b3ff, 0xb3b3b3ff, 0xb3b3b3ff); CallRemoteFunction("OnCharacterSaved", "i", playerid); } } hook OnPlayerLogin(playerid) { //Character_Menu(playerid); } hook OnPlayerRegister(playerid) { Character_Menu(playerid); } hook OnPlayerFirstSpawn(playerid) { SetPlayerHealth(playerid, Health[playerid]); SetPlayerArmour(playerid, Armour[playerid]); SetPlayerPos(playerid, LastX[playerid], LastY[playerid], LastZ[playerid]); SetPlayerFacingAngle(playerid, LastA[playerid]); SetPlayerInterior(playerid, LastInt[playerid]); SetPlayerVirtualWorld(playerid, LastVW[playerid]); } public OnCharacterSaved(playerid) { GetPlayerHealth(playerid, Health[playerid]); GetPlayerArmour(playerid, Armour[playerid]); if(!(0.0 <= Health[playerid] <= 100)) Health[playerid] = 100.0; if(!(0.0 <= Armour[playerid] <= 100)) Armour[playerid] = 0.0; GetPlayerPos(playerid, LastX[playerid], LastY[playerid], LastZ[playerid]); GetPlayerFacingAngle(playerid, LastA[playerid]); new query[256]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE characters SET minutes_played = %d, health = %f, armour = %f, last_x = %f, last_y = %f, last_z = %f, last_a = %f, world = %d, interior = %d WHERE id = %d", Player_GetMinutesPlayed(playerid), Health[playerid], Armour[playerid], LastX[playerid], LastY[playerid], LastZ[playerid], LastA[playerid], GetPlayerVirtualWorld(playerid), GetPlayerInterior(playerid), CharacterSQLID[playerid]); mysql_tquery(MySQL_GetHandle(), query); } public OnCharacterLoaded(playerid) { SetPlayerName(playerid, CharacterName[playerid]); } public Character_Select(playerid, dialogid, response, listitem, string:inputtext[]) { #pragma unused dialogid, inputtext if(!response) return Kick(playerid); switch(listitem) { case 0: { if(CharacterCount[playerid] >= MAX_PLAYER_CHARACTERS) { SendErrorMessageF(playerid, "You are not allowed to have more than %d characters.", MAX_PLAYER_CHARACTERS); Character_Menu(playerid); } else Character_Create(playerid); } default: { CharacterSQLID[playerid] = CharacterListSQLIDS[playerid][listitem - 1]; CharacterName[playerid] = CharacterListNames[playerid][listitem - 1]; Character_Connect(playerid); } } return 1; } public Character_Delete(playerid, dialogid, response, listitem, string:inputtext[]) { #pragma unused dialogid, inputtext if(!response) return Character_Connect(playerid); va_SendClientMessage(playerid, 0xff6666ff, "> You deleted %s from the database.", CharacterName[playerid]); new query[78]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "DELETE FROM characters WHERE Name = '%e'", CharacterName[playerid]); mysql_tquery(MySQL_GetHandle(), query); Character_Menu(playerid); return 1; } Character_Menu(playerid) { inline const OnMenuLoaded() { CharacterCount[playerid] = 0; new string[124]; strcat(string, "Select or create a character\n{b3b3b3}Create a character{eeeeee}\n"); for(new i = 0, j = cache_num_rows(); i < j; i++) { CharacterCount[playerid]++; cache_get_value_name_int(i, "id", CharacterListSQLIDS[playerid][i]); cache_get_value_name(i, "name", CharacterListNames[playerid][i]); strcat(string, va_return("%s\n", CharacterListNames[playerid][i])); } Dialog_ShowCallback(playerid, using public Character_Select, DIALOG_STYLE_TABLIST_HEADERS, "Character Selection", string, "Next", "Quit"); } MySQL_TQueryInline(MySQL_GetHandle(), using inline OnMenuLoaded, "SELECT id, name FROM characters WHERE master_id = %d LIMIT %d", Account_GetSQLID(playerid), MAX_PLAYER_CHARACTERS); return 1; } Character_Connect(playerid) { inline _response(response, listitem, string:inputtext[]) { #pragma unused inputtext if(!response) return Character_Menu(playerid); switch(listitem) { case 0: Character_Load(playerid); case 1: { new string[168]; format(string, sizeof(string), "{eeeeee}Are you sure you want to delete {99ccff}%s? {ff6666}This action is irreversible.", CharacterName[playerid]); Dialog_ShowCallback(playerid, using public Character_Delete, DIALOG_STYLE_MSGBOX, "Delete Character", string, "Yes", "No"); } } } Dialog_ShowCallback(playerid, using inline _response, DIALOG_STYLE_TABLIST_HEADERS, va_return("Character %s", CharacterName[playerid]), "Please choose an action\n{eeeeee}Spawn this character\n{ff6666}Delete this character", "Next", "Back"); return 1; } Character_Load(playerid) { inline const OnStatsLoaded() { if(cache_num_rows()) { cache_get_value_name_int(0, "gender", Gender[playerid]); cache_get_value_name_int(0, "age", Age[playerid]); cache_get_value_name_int(0, "race", Race[playerid]); cache_get_value_name_float(0, "health", Health[playerid]); cache_get_value_name_float(0, "armour", Armour[playerid]); cache_get_value_name_float(0, "last_x", LastX[playerid]); cache_get_value_name_float(0, "last_y", LastY[playerid]); cache_get_value_name_float(0, "last_z", LastZ[playerid]); cache_get_value_name_float(0, "last_a", LastA[playerid]); cache_get_value_name_int(0, "world", LastVW[playerid]); cache_get_value_name_int(0, "interior", LastInt[playerid]); new cash; new skin; new job; cache_get_value_name_int(0, "cash", cash); cache_get_value_name_int(0, "skin", skin); cache_get_value_name_int(0, "job", job); Player_GiveCash(playerid, cash, false); Player_SetJob(playerid, job, false); Player_SetSkin(playerid, skin, false); new talkstyle; cache_get_value_name_int(0, "talk_style", talkstyle); Player_SetTalkStyle(playerid, talkstyle, false); new level; new experience; new hoursPlayed; new minutesPlayed; cache_get_value_name_int(0, "level", level); cache_get_value_name_int(0, "experience", experience); cache_get_value_name_int(0, "hours_played", hoursPlayed); cache_get_value_name_int(0, "minutes_played", minutesPlayed); Player_SetLevel(playerid, level); Player_SetExperience(playerid, experience); Player_SetHoursPlayed(playerid, hoursPlayed); Player_SetMinutesPlayed(playerid, minutesPlayed); CallRemoteFunction("OnCharacterLoaded", "i", playerid); } else { SendErrorMessage(playerid, "Your character doesn't exist in the database."); Kick(playerid); } } MySQL_TQueryInline(MySQL_GetHandle(), using inline OnStatsLoaded, "SELECT * FROM characters WHERE id = %d", CharacterSQLID[playerid]); } Character_Create(playerid) { inline _response(response, listitem, string:inputtext[]) { #pragma unused listitem if(!response) return Character_Menu(playerid); if(strlen(inputtext) < 6 || strlen(inputtext) > 20) { SendErrorMessage(playerid, "The character name must be between 6 and 20 letters."); return Character_Create(playerid); } new charName[MAX_PLAYER_NAME]; StrCpy(charName, inputtext, sizeof(charName)); inline const OnNameVerified() { if(cache_num_rows()) { SendErrorMessage(playerid, "That name is already in use."); return Character_Create(playerid); } format(CharacterName[playerid], 24, "%s", inputtext); Character_RegisterStep(playerid, 1); } MySQL_TQueryInline(MySQL_GetHandle(), using inline OnNameVerified, "SELECT id FROM characters WHERE name = '%e'", charName); } Dialog_ShowCallback(playerid, using inline _response, DIALOG_STYLE_INPUT, "Create character", "{eeeeee}Choose a name for your character.\nUse {cc80ff}fantasynamegenerators.com {eeeeee}if you have no name ideas.\n\n{ff6666}!! {c3c3c3}The correct format is Firstname_Lastname.\n{ff6666}!! {c3c3c3}Famous names are forbidden.", "Next", "Back"); return 1; } Character_RegisterStep(playerid, step) { switch(step) { case 1: // Gender { inline _response(response, listitem, string:inputtext[]) { #pragma unused inputtext if(!response) return Kick(playerid); Gender[playerid] = listitem + 1; Character_RegisterStep(playerid, 2); } Dialog_ShowCallback(playerid, using inline _response, DIALOG_STYLE_TABLIST_HEADERS, "Sex", "What's your character's sex?\nMale\nFemale", "Next", "Back"); } case 2: // Age { inline _response(response, listitem, string:inputtext[]) { #pragma unused inputtext if(!response) return Character_RegisterStep(playerid, 1); Age[playerid] = listitem + 16; Character_RegisterStep(playerid, 3); } new string[188]; strcat(string, "How old is your character?\n"); for(new i = 16; i <= 100; i++) { strcat(string, va_return("%d\n", i)); } Dialog_ShowCallback(playerid, using inline _response, DIALOG_STYLE_TABLIST_HEADERS, "Age", string, "Next", "Back"); } case 3: // Race { inline _response(response, listitem, string:inputtext[]) { #pragma unused inputtext if(!response) return Character_RegisterStep(playerid, 2); Race[playerid] = listitem + 1; Character_InsertToDB(playerid); } Dialog_ShowCallback(playerid, using inline _response, DIALOG_STYLE_TABLIST_HEADERS, "Race", "Indicate your character's race\nCaucasian (white)\nAfrican American\nHispanic\nAsian", "Next", "Back"); } } return 1; } Character_InsertToDB(playerid) { inline const OnInserted() { CharacterSQLID[playerid] = cache_insert_id(); LastX[playerid] = DEFAULT_POSX; LastY[playerid] = DEFAULT_POSY; LastZ[playerid] = DEFAULT_POSZ; LastA[playerid] = DEFAULT_POSA; LastVW[playerid] = DEFAULT_VW; LastInt[playerid] = DEFAULT_INT; Player_SetLevel(playerid, 1); Player_SetExperience(playerid, 0); Player_SetHoursPlayed(playerid, 0); Player_SetMinutesPlayed(playerid, 0); CallRemoteFunction("OnCharacterLoaded", "i", playerid); } MySQL_TQueryInline(MySQL_GetHandle(), using inline OnInserted, "INSERT INTO characters (master_id, name, gender, age, race) VALUES (%d, '%e', %d, %d, %d)", Account_GetSQLID(playerid), CharacterName[playerid], Gender[playerid], Age[playerid], Race[playerid]); } stock Character_SetSQLID(playerid, id) { CharacterSQLID[playerid] = id; } stock Character_GetSQLID(playerid) { return CharacterSQLID[playerid]; } stock Character_SetName(playerid, const name[]) { format(CharacterName[playerid], MAX_PLAYER_NAME, name); } stock Character_GetName(playerid) { return CharacterName[playerid]; } stock Character_SetGender(playerid, gender, bool:save) { Gender[playerid] = gender; if(save) { new query[78]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE characters SET gender = %d WHERE id = %d", CharacterSQLID[playerid]); mysql_tquery(MySQL_GetHandle(), query); } } stock Character_GetGender(playerid) { return Gender[playerid]; } stock Character_SetAge(playerid, age, bool:save) { Age[playerid] = age; if(save) { new query[78]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE characters SET age = %d WHERE id = %d", CharacterSQLID[playerid]); mysql_tquery(MySQL_GetHandle(), query); } } stock Character_GetAge(playerid) { return Age[playerid]; } stock Character_SetRace(playerid, race, bool:save) { Race[playerid] = race; if(save) { new query[78]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE characters SET race = %d WHERE id = %d", CharacterSQLID[playerid]); mysql_tquery(MySQL_GetHandle(), query); } } stock Character_GetRace(playerid) { return Race[playerid]; } stock Character_SetLastPos(playerid, Float:x, Float:y, Float:z, Float:a = 0.0) { LastX[playerid] = x; LastY[playerid] = y; LastZ[playerid] = z; LastA[playerid] = a; } stock Character_GetLastPos(playerid, &Float:x, &Float:y, &Float:z, &Float:a = 0.0) { x = LastX[playerid]; y = LastY[playerid]; z = LastZ[playerid]; a = LastA[playerid]; } stock Character_SetLastWorld(playerid, world) { LastVW[playerid] = world; } stock Character_GetLastWorld(playerid) { return LastVW[playerid]; } stock Character_SetLastInterior(playerid, interior) { LastInt[playerid] = interior; } stock Character_GetLastInterior(playerid) { return LastInt[playerid]; }