Bläddra i källkod

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.
Aleos 9 år sedan
förälder
incheckning
994b406575
7 ändrade filer med 137 tillägg och 58 borttagningar
  1. 5 3
      conf/char_athena.conf
  2. 109 52
      src/char/char.c
  3. 6 1
      src/char/char.h
  4. 7 1
      src/common/mapindex.h
  5. 5 0
      src/common/mmo.h
  6. 1 1
      src/config/const.h
  7. 4 0
      src/map/atcommand.c

+ 5 - 3
conf/char_athena.conf

@@ -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)

+ 109 - 52
src/char/char.c

@@ -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
  */

+ 6 - 1
src/char/char.h

@@ -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;

+ 7 - 1
src/common/mapindex.h

@@ -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"

+ 5 - 0
src/common/mmo.h

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

+ 1 - 1
src/config/const.h

@@ -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

+ 4 - 0
src/map/atcommand.c

@@ -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