Merge pull request #889 from rathena/feature/random_start_point

Implemented Randomized Start Point
* Fixes #805.
* Character's will follow somewhat of the official method of a 'random' start point at their first login.
* Official servers use load balancing for setting the start point dynamically according to user count, whereas we at rAthena wanted to stay simple since we don't believe you guys will need this kind of load balancing for new characters.
This commit is contained in:
Aleos
2016-01-22 12:23:22 -05:00
7 changed files with 137 additions and 58 deletions

View File

@@ -108,9 +108,11 @@ autosave_time: 60
save_log: yes
// Starting point for new characters
// Format: <map_name>,<x>,<y>
start_point: iz_int,97,90
start_point_pre: new_1-1,53,111
// Format: <map_name>,<x>,<y>{:<map_name>,<x>,<y>...}
// Max number of start points is MAX_STARTPOINT in char.h (default 5)
// Location is randomly picked on character creation.
start_point: iz_int,97,90:iz_int01,97,90:iz_int02,97,90:iz_int03,97,90:iz_int04,97,90
start_point_pre: new_1-1,53,111:new_2-1,53,111:new_3-1,53,111:new_4-1,53,111:new_5-1,53,111
// Starting items for new characters
// Max number of items is MAX_STARTITEM in char.c (default 32)

View File

@@ -53,13 +53,6 @@ static char* msg_table[CHAR_MAX_MSG]; // Login Server messages_conf
// other is char_id
unsigned int save_flag = 0;
#define MAX_STARTITEM 32
struct startitem {
int nameid; //Item ID
int amount; //Number of items
int pos; //Position (for auto-equip)
} start_items[MAX_STARTITEM+1];
// Advanced subnet check [LuzZza]
struct s_subnet {
uint32 mask;
@@ -1423,7 +1416,7 @@ int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, i
char name[NAME_LENGTH];
char esc_name[NAME_LENGTH*2+1];
uint32 char_id;
int flag, k;
int flag, k, start_point_idx = rand() % charserv_config.start_point_count;
safestrncpy(name, name_, NAME_LENGTH);
normalize_name(name,TRIM_CHARS);
@@ -1475,7 +1468,7 @@ int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, i
"'%d', '%d', '%s', '%d', '%d','%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')",
schema_config.char_db, sd->account_id , slot, esc_name, charserv_config.start_zeny, 48, str, agi, vit, int_, dex, luk,
(40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
mapindex_id2name(charserv_config.start_point.map), charserv_config.start_point.x, charserv_config.start_point.y, mapindex_id2name(charserv_config.start_point.map), charserv_config.start_point.x, charserv_config.start_point.y) )
mapindex_id2name(charserv_config.start_point[start_point_idx].map), charserv_config.start_point[start_point_idx].x, charserv_config.start_point[start_point_idx].y, mapindex_id2name(charserv_config.start_point[start_point_idx].map), charserv_config.start_point[start_point_idx].x, charserv_config.start_point[start_point_idx].y) )
{
Sql_ShowDebug(sql_handle);
return -2; //No, stop the procedure!
@@ -1487,7 +1480,7 @@ int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, i
"'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')",
schema_config.char_db, sd->account_id , slot, esc_name, charserv_config.start_zeny, str, agi, vit, int_, dex, luk,
(40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
mapindex_id2name(charserv_config.start_point.map), charserv_config.start_point.x, charserv_config.start_point.y, mapindex_id2name(charserv_config.start_point.map), charserv_config.start_point.x, charserv_config.start_point.y) )
mapindex_id2name(charserv_config.start_point[start_point_idx].map), charserv_config.start_point[start_point_idx].x, charserv_config.start_point[start_point_idx].y, mapindex_id2name(charserv_config.start_point[start_point_idx].map), charserv_config.start_point[start_point_idx].x, charserv_config.start_point[start_point_idx].y) )
{
Sql_ShowDebug(sql_handle);
return -2; //No, stop the procedure!
@@ -1496,8 +1489,8 @@ int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, i
//Retrieve the newly auto-generated char id
char_id = (int)Sql_LastInsertId(sql_handle);
//Give the char the default items
for (k = 0; k <= MAX_STARTITEM && start_items[k].nameid != 0; k ++) {
if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%hu', '%d', '%d', '%d')", schema_config.inventory_db, char_id, start_items[k].nameid, start_items[k].amount, start_items[k].pos, 1) )
for (k = 0; k <= MAX_STARTITEM && charserv_config.start_items[k].nameid != 0; k ++) {
if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%hu', '%hu', '%hu', '%d')", schema_config.inventory_db, char_id, charserv_config.start_items[k].nameid, charserv_config.start_items[k].amount, charserv_config.start_items[k].pos, 1) )
Sql_ShowDebug(sql_handle);
}
@@ -2636,10 +2629,18 @@ void char_set_defaults(){
charserv_config.log_inter = 1; // loggin inter or not [devil]
charserv_config.char_check_db =1;
//see const.h to change those default
charserv_config.start_point.map = mapindex_name2id(MAP_DEFAULT_NAME);
charserv_config.start_point.x = MAP_DEFAULT_X;
charserv_config.start_point.y = MAP_DEFAULT_Y;
// See const.h to change the default values
charserv_config.start_point[0].map = mapindex_name2id(MAP_DEFAULT_NAME);
charserv_config.start_point[0].x = MAP_DEFAULT_X;
charserv_config.start_point[0].y = MAP_DEFAULT_Y;
charserv_config.start_point_count = 0;
charserv_config.start_items[0].nameid = 1201;
charserv_config.start_items[0].amount = 1;
charserv_config.start_items[0].pos = 2;
charserv_config.start_items[1].nameid = 2301;
charserv_config.start_items[1].amount = 1;
charserv_config.start_items[1].pos = 16;
charserv_config.console = 0;
charserv_config.max_connect_user = -1;
@@ -2653,6 +2654,96 @@ void char_set_defaults(){
charserv_config.default_map_y = 191;
}
/**
* Split start_point configuration values.
* @param w2_value: Value from w2
*/
static void char_config_split_startpoint(char *w2_value)
{
char *lineitem, **fields, config_name[20];
int i = 0, fields_length = 3 + 1;
memset(config_name, 0, sizeof(config_name));
#ifdef RENEWAL
strcat(config_name, "start_point");
#else
strcat(config_name, "start_point_pre");
#endif
fields = (char **)aMalloc(fields_length * sizeof(char *));
if (fields == NULL)
return; // Failed to allocate memory.
lineitem = strtok(w2_value, ":");
while (lineitem != NULL) {
int n = sv_split(lineitem, strlen(lineitem), 0, ',', fields, fields_length, SV_NOESCAPE_NOTERMINATE);
if (n + 1 < fields_length) {
ShowDebug("%s: not enough arguments for %s! Skipping...\n", config_name, lineitem);
lineitem = strtok(NULL, ":"); //next lineitem
continue;
}
if (i > MAX_STARTPOINT)
ShowDebug("%s: too many start points, only %d are allowed! Ignoring parameter %s...\n", config_name, MAX_STARTPOINT, lineitem);
else {
charserv_config.start_point[i].map = mapindex_name2id(fields[1]);
if (!charserv_config.start_point[i].map) {
ShowError("Start point %s not found in map-index cache. Setting to default location.\n", charserv_config.start_point[i].map);
charserv_config.start_point[i].map = mapindex_name2id(MAP_DEFAULT_NAME);
charserv_config.start_point[i].x = MAP_DEFAULT_X;
charserv_config.start_point[i].y = MAP_DEFAULT_Y;
} else {
charserv_config.start_point[i].x = max(0, atoi(fields[2]));
charserv_config.start_point[i].y = max(0, atoi(fields[3]));
}
charserv_config.start_point_count++;
}
lineitem = strtok(NULL, ":"); //next lineitem
i++;
}
aFree(fields);
}
/**
* Split start_items configuration values.
* @param w2_value: Value from w2
*/
static void char_config_split_startitem(char *w2_value)
{
char *lineitem, **fields, config_name[20];
int i = 0, fields_length = 3 + 1;
memset(config_name, 0, sizeof(config_name));
strcat(config_name, "start_items");
fields = (char **)aMalloc(fields_length * sizeof(char *));
if (fields == NULL)
return; // Failed to allocate memory.
lineitem = strtok(w2_value, ":");
while (lineitem != NULL) {
int n = sv_split(lineitem, strlen(lineitem), 0, ',', fields, fields_length, SV_NOESCAPE_NOTERMINATE);
if (n + 1 < fields_length) {
ShowDebug("%s: not enough arguments for %s! Skipping...\n", config_name, lineitem);
lineitem = strtok(NULL, ":"); //next lineitem
continue;
}
if (i > MAX_STARTITEM)
ShowDebug("%s: too many start items, only %d are allowed! Ignoring parameter %s...\n", config_name, MAX_STARTITEM, lineitem);
else {
charserv_config.start_items[i].nameid = max(0, atoi(fields[1]));
charserv_config.start_items[i].amount = max(0, atoi(fields[2]));
charserv_config.start_items[i].pos = max(0, atoi(fields[3]));
}
lineitem = strtok(NULL, ":"); //next lineitem
i++;
}
aFree(fields);
}
bool char_config_read(const char* cfgName, bool normal){
char line[1024], w1[1024], w2[1024];
FILE* fp = fopen(cfgName, "r");
@@ -2749,46 +2840,13 @@ bool char_config_read(const char* cfgName, bool normal){
#else
} else if (strcmpi(w1, "start_point_pre") == 0) {
#endif
char map[MAP_NAME_LENGTH_EXT];
short x, y;
if (sscanf(w2, "%15[^,],%6hd,%6hd", map, &x, &y) < 3){
ShowWarning( "Specified start_point has an invalid format.\n" );
continue;
}
charserv_config.start_point.map = mapindex_name2id(map);
if (!charserv_config.start_point.map)
ShowError("Specified start_point %s not found in map-index cache.\n", map);
charserv_config.start_point.x = x;
charserv_config.start_point.y = y;
char_config_split_startpoint(w2);
} else if (strcmpi(w1, "start_zeny") == 0) {
charserv_config.start_zeny = atoi(w2);
if (charserv_config.start_zeny < 0)
charserv_config.start_zeny = 0;
} else if (strcmpi(w1, "start_items") == 0) {
int i=0;
char *lineitem, **fields;
int fields_length = 3+1;
fields = (char**)aMalloc(fields_length*sizeof(char*));
lineitem = strtok(w2, ":");
while (lineitem != NULL) {
int n = sv_split(lineitem, strlen(lineitem), 0, ',', fields, fields_length, SV_NOESCAPE_NOTERMINATE);
if(n+1 < fields_length){
ShowDebug("start_items: not enough arguments for %s! Skipping...\n",lineitem);
lineitem = strtok(NULL, ":"); //next itemline
continue;
}
if(i > MAX_STARTITEM){
ShowDebug("start_items: too many items, only %d are allowed! Ignoring parameter %s...\n",MAX_STARTITEM,lineitem);
} else {
start_items[i].nameid = max(0,atoi(fields[1]));
start_items[i].amount = max(0,atoi(fields[2]));
start_items[i].pos = max(0,atoi(fields[3]));
}
lineitem = strtok(NULL, ":"); //next itemline
i++;
}
aFree(fields);
char_config_split_startitem(w2);
} else if(strcmpi(w1,"log_char")==0) { //log char or not [devil]
charserv_config.log_char = atoi(w2);
} else if (strcmpi(w1, "unknown_char_name") == 0) {
@@ -2870,7 +2928,6 @@ bool char_config_read(const char* cfgName, bool normal){
return true;
}
/*
* Message conf function
*/

View File

@@ -15,6 +15,9 @@
extern int login_fd; //login file descriptor
extern int char_fd; //char file descriptor
#define MAX_STARTPOINT 5
#define MAX_STARTITEM 32
enum E_CHARSERVER_ST {
CHARSERVER_ST_RUNNING = CORE_ST_LAST,
CHARSERVER_ST_STARTING,
@@ -142,7 +145,9 @@ struct CharServ_Config {
int log_inter; // loggin inter or not [devil]
int char_check_db; ///cheking sql-table at begining ?
struct point start_point; // Initial position the player will spawn on server
struct point start_point[MAX_STARTPOINT]; // Initial position the player will spawn on the server
short start_point_count; // Number of positions read
struct startitem start_items[MAX_STARTITEM]; // Initial items the player with spawn with on the server
int console;
int max_connect_user;
int gm_allow_group;

View File

@@ -4,6 +4,8 @@
#ifndef _MAPINDEX_H_
#define _MAPINDEX_H_
#include "../config/renewal.h"
#define MAX_MAPINDEX 2000
//Some definitions for the mayor city maps.
@@ -31,7 +33,11 @@
#define MAP_RACHEL "rachel"
#define MAP_VEINS "veins"
#define MAP_JAIL "sec_pri"
#define MAP_NOVICE "new_1-1"
#ifdef RENEWAL
#define MAP_NOVICE "iz_int"
#else
#define MAP_NOVICE "new_1-1"
#endif
#define MAP_MOSCOVIA "moscovia"
#define MAP_MIDCAMP "mid_camp"
#define MAP_MANUK "manuk"

View File

@@ -219,6 +219,11 @@ struct point {
short x,y;
};
struct startitem {
unsigned short nameid, amount;
short pos;
};
enum e_skill_flag
{
SKILL_FLAG_PERMANENT,

View File

@@ -103,7 +103,7 @@
#define MAP_DEFAULT_X 97
#define MAP_DEFAULT_Y 90
#else
#define MAP_DEFAULT_NAME "new_zone01"
#define MAP_DEFAULT_NAME "new_1-1"
#define MAP_DEFAULT_X 53
#define MAP_DEFAULT_Y 111
#endif

View File

@@ -1874,7 +1874,11 @@ ACMD_FUNC(go)
{ MAP_UMBALA, 89, 157 }, // 12=Umbala
{ MAP_NIFLHEIM, 21, 153 }, // 13=Niflheim
{ MAP_LOUYANG, 217, 40 }, // 14=Louyang
#ifdef RENEWAL
{ MAP_NOVICE, 97, 90 }, // 15=Training Grounds (Renewal)
#else
{ MAP_NOVICE, 53, 111 }, // 15=Training Grounds
#endif
{ MAP_JAIL, 23, 61 }, // 16=Prison
{ MAP_JAWAII, 249, 127 }, // 17=Jawaii
{ MAP_AYOTHAYA, 151, 117 }, // 18=Ayothaya