Browse Source

Made mercenary db dynamic (#2883)

Removed hard limit of the mercenary database
Cleaned up the hard coded duplicated logic
Turned hard coded mercenary ids into constants
Lemongrass3110 7 years ago
parent
commit
132feeb621
5 changed files with 118 additions and 109 deletions
  1. 0 1
      src/common/mmo.h
  2. 102 100
      src/map/mercenary.cpp
  3. 14 6
      src/map/mercenary.hpp
  4. 1 1
      src/map/script.cpp
  5. 1 1
      src/map/status.cpp

+ 0 - 1
src/common/mmo.h

@@ -139,7 +139,6 @@
 //Mercenary System
 #define MC_SKILLBASE 8201
 #define MAX_MERCSKILL 40
-#define MAX_MERCENARY_CLASS 61
 
 //Elemental System
 #define MAX_ELEMENTALSKILL 42

+ 102 - 100
src/map/mercenary.cpp

@@ -4,6 +4,7 @@
 #include "mercenary.hpp"
 
 #include <stdlib.h>
+#include <map>
 #include <math.h>
 
 #include "../common/cbasetypes.h"
@@ -25,27 +26,19 @@
 #include "trade.hpp"
 #include "npc.hpp"
 
-struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS]; // Mercenary Database
-static uint16 mercenary_count;
+std::map<uint16, struct s_mercenary_db> mercenary_db_data;
 
 /**
-* Search Mercenary by class
-* @param class_ Class ID of Mercenary
-* @return The index of mercenary on mercenary_db, or -1 if not found
-**/
-static int16 mercenary_search_index(int class_) {
-	int16 i;
-	ARR_FIND(0, mercenary_count, i, mercenary_db[i].class_ == class_);
-	return (i == mercenary_count)?-1:i;
-}
-
-/**
-* Check if the Class ID is a Mercenary
-* @param class_ The Class ID
-* @return true if Class ID is a Mercenary, false otherwise
-**/
-bool mercenary_class(int class_){
-	return (bool)(mercenary_search_index(class_) > -1);
+ * Search Mercenary by class
+ * @param class_ Class ID of Mercenary
+ * @return A pointer to the mercenary db entry or nullptr if not found
+ **/
+struct s_mercenary_db *mercenary_db( uint16 class_ ){
+	if( mercenary_db_data.find(class_) != mercenary_db_data.end() ){
+		return &mercenary_db_data.at(class_);
+	}else{
+		return nullptr;
+	}
 }
 
 /**
@@ -53,12 +46,14 @@ bool mercenary_class(int class_){
 * @param class_ The Class ID
 * @return View Data of Mercenary
 **/
-struct view_data * mercenary_get_viewdata(int class_){
-	int i = mercenary_search_index(class_);
-	if( i < 0 )
-		return 0;
+struct view_data *mercenary_get_viewdata( uint16 class_ ){
+	struct s_mercenary_db *db = mercenary_db(class_);
 
-	return &mercenary_db[i].vd;
+	if( db ){
+		return &db->vd;
+	}else{
+		return nullptr;
+	}
 }
 
 /**
@@ -82,16 +77,17 @@ short mercenary_skill_get_index(uint16 skill_id) {
 * @param lifetime Contract duration
 * @return false if failed, true otherwise
 **/
-bool mercenary_create(struct map_session_data *sd, int class_, unsigned int lifetime) {
+bool mercenary_create(struct map_session_data *sd, uint16 class_, unsigned int lifetime) {
 	struct s_mercenary merc;
 	struct s_mercenary_db *db;
-	int16 i;
 	nullpo_retr(false,sd);
 
-	if( (i = mercenary_search_index(class_)) < 0 )
+	db = mercenary_db(class_);
+
+	if( !db ){
 		return false;
+	}
 
-	db = &mercenary_db[i];
 	memset(&merc,0,sizeof(struct s_mercenary));
 
 	merc.char_id = sd->status.char_id;
@@ -123,24 +119,24 @@ int mercenary_get_lifetime(struct mercenary_data *md) {
 /**
 * Get Guild type of Mercenary
 * @param md Mercenary
-* @return -1 if not found, 0 - ARCH_MERC_GUILD, 1 - SPEAR_MERC_GUILD, or 2 - SWORD_MERC_GUILD
+* @return enum e_MercGuildType
 **/
-int mercenary_get_guild(struct mercenary_data *md){
+enum e_MercGuildType mercenary_get_guild(struct mercenary_data *md){
 	uint16 class_;
 
 	if( md == NULL || md->db == NULL )
-		return -1;
+		return NONE_MERC_GUILD;
 
 	class_ = md->db->class_;
 
-	if( class_ >= 6017 && class_ <= 6026 )
+	if( class_ >= MERID_MER_ARCHER01 && class_ <= MERID_MER_ARCHER10 )
 		return ARCH_MERC_GUILD;
-	if( class_ >= 6027 && class_ <= 6036 )
+	if( class_ >= MERID_MER_LANCER01 && class_ <= MERID_MER_LANCER10 )
 		return SPEAR_MERC_GUILD;
-	if( class_ >= 6037 && class_ <= 6046 )
+	if( class_ >= MERID_MER_SWORDMAN01 && class_ <= MERID_MER_SWORDMAN10 )
 		return SWORD_MERC_GUILD;
 
-	return -1;
+	return NONE_MERC_GUILD;
 }
 
 /**
@@ -150,21 +146,24 @@ int mercenary_get_guild(struct mercenary_data *md){
 **/
 int mercenary_get_faith(struct mercenary_data *md) {
 	struct map_session_data *sd;
-	uint16 class_;
+	enum e_MercGuildType guild;
 
 	if( md == NULL || md->db == NULL || (sd = md->master) == NULL )
 		return 0;
 
-	class_ = md->db->class_;
-
-	if( class_ >= 6017 && class_ <= 6026 )
-		return sd->status.arch_faith;
-	if( class_ >= 6027 && class_ <= 6036 )
-		return sd->status.spear_faith;
-	if( class_ >= 6037 && class_ <= 6046 )
-		return sd->status.sword_faith;
-
-	return 0;
+	guild = mercenary_get_guild(md);
+
+	switch( guild ){
+		case ARCH_MERC_GUILD:
+			return sd->status.arch_faith;
+		case SPEAR_MERC_GUILD:
+			return sd->status.spear_faith;
+		case SWORD_MERC_GUILD:
+			return sd->status.sword_faith;
+		case NONE_MERC_GUILD:
+		default:
+			return 0;
+	}
 }
 
 /**
@@ -174,22 +173,27 @@ int mercenary_get_faith(struct mercenary_data *md) {
 **/
 void mercenary_set_faith(struct mercenary_data *md, int value) {
 	struct map_session_data *sd;
-	uint16 class_;
+	enum e_MercGuildType guild;
 	int *faith;
 
 	if( md == NULL || md->db == NULL || (sd = md->master) == NULL )
 		return;
 
-	class_ = md->db->class_;
-
-	if( class_ >= 6017 && class_ <= 6026 )
-		faith = &sd->status.arch_faith;
-	else if( class_ >= 6027 && class_ <= 6036 )
-		faith = &sd->status.spear_faith;
-	else if( class_ >= 6037 && class_ <= 6046 )
-		faith = &sd->status.sword_faith;
-	else
-		return;
+	guild = mercenary_get_guild(md);
+
+	switch( guild ){
+		case ARCH_MERC_GUILD:
+			faith = &sd->status.arch_faith;
+			break;
+		case SPEAR_MERC_GUILD:
+			faith = &sd->status.spear_faith;
+			break;
+		case SWORD_MERC_GUILD:
+			faith = &sd->status.sword_faith;
+			break;
+		case NONE_MERC_GUILD:
+			return;
+	}
 
 	*faith += value;
 	*faith = cap_value(*faith, 0, SHRT_MAX);
@@ -203,21 +207,24 @@ void mercenary_set_faith(struct mercenary_data *md, int value) {
 **/
 int mercenary_get_calls(struct mercenary_data *md) {
 	struct map_session_data *sd;
-	uint16 class_;
+	enum e_MercGuildType guild;
 
 	if( md == NULL || md->db == NULL || (sd = md->master) == NULL )
 		return 0;
 
-	class_ = md->db->class_;
-
-	if( class_ >= 6017 && class_ <= 6026 )
-		return sd->status.arch_calls;
-	if( class_ >= 6027 && class_ <= 6036 )
-		return sd->status.spear_calls;
-	if( class_ >= 6037 && class_ <= 6046 )
-		return sd->status.sword_calls;
-
-	return 0;
+	guild = mercenary_get_guild(md);
+
+	switch( guild ){
+		case ARCH_MERC_GUILD:
+			return sd->status.arch_calls;
+		case SPEAR_MERC_GUILD:
+			return sd->status.spear_calls;
+		case SWORD_MERC_GUILD:
+			return sd->status.sword_calls;
+		case NONE_MERC_GUILD:
+		default:
+			return 0;
+	}
 }
 
 /**
@@ -227,22 +234,27 @@ int mercenary_get_calls(struct mercenary_data *md) {
 **/
 void mercenary_set_calls(struct mercenary_data *md, int value) {
 	struct map_session_data *sd;
-	uint16 class_;
+	enum e_MercGuildType guild;
 	int *calls;
 
 	if( md == NULL || md->db == NULL || (sd = md->master) == NULL )
 		return;
 
-	class_ = md->db->class_;
-
-	if( class_ >= 6017 && class_ <= 6026 )
-		calls = &sd->status.arch_calls;
-	else if( class_ >= 6027 && class_ <= 6036 )
-		calls = &sd->status.spear_calls;
-	else if( class_ >= 6037 && class_ <= 6046 )
-		calls = &sd->status.sword_calls;
-	else
-		return;
+	guild = mercenary_get_guild(md);
+
+	switch( guild ){
+		case ARCH_MERC_GUILD:
+			calls = &sd->status.arch_calls;
+			break;
+		case SPEAR_MERC_GUILD:
+			calls = &sd->status.spear_calls;
+			break;
+		case SWORD_MERC_GUILD:
+			calls = &sd->status.sword_calls;
+			break;
+		case NONE_MERC_GUILD:
+			return;
+	}
 
 	*calls += value;
 	*calls = cap_value(*calls, 0, INT_MAX);
@@ -347,16 +359,16 @@ bool mercenary_recv_data(struct s_mercenary *merc, bool flag)
 	struct map_session_data *sd;
 	struct mercenary_data *md;
 	struct s_mercenary_db *db;
-	int i = mercenary_search_index(merc->class_);
+
+	db = mercenary_db(merc->class_);
 
 	if( (sd = map_charid2sd(merc->char_id)) == NULL )
 		return false;
-	if( !flag || i < 0 ) { // Not created - loaded - DB info
+	if( !flag || !db ){ // Not created - loaded - DB info
 		sd->status.mer_id = 0;
 		return false;
 	}
 
-	db = &mercenary_db[i];
 	if( !sd->md ) {
 		sd->md = md = (struct mercenary_data*)aCalloc(1,sizeof(struct mercenary_data));
 		md->bl.type = BL_MER;
@@ -477,16 +489,11 @@ int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id) {
 static bool mercenary_readdb_sub(char* str[], int columns, int current)
 {
 	int ele;
-	uint16 i, class_ = atoi(str[0]);
+	uint16 class_ = atoi(str[0]);
 	struct s_mercenary_db *db;
 	struct status_data *status;
 
-	//Find the ID, already exist or not in mercenary_db
-	ARR_FIND(0,mercenary_count,i,mercenary_db[i].class_ == class_);
-	if (i >= mercenary_count)
-		db = &mercenary_db[mercenary_count];
-	else
-		db = &mercenary_db[i];
+	db = &mercenary_db_data[class_];
 
 	db->class_ = class_;
 	safestrncpy(db->sprite, str[1], NAME_LENGTH);
@@ -534,8 +541,6 @@ static bool mercenary_readdb_sub(char* str[], int columns, int current)
 	status->amotion = atoi(str[24]);
 	status->dmotion = atoi(str[25]);
 	
-	if (i >= mercenary_count)
-		mercenary_count++;
 	return true;
 }
 
@@ -546,10 +551,10 @@ void mercenary_readdb(void) {
 	const char *filename[]={ "mercenary_db.txt",DBIMPORT"/mercenary_db.txt"};
 	uint8 i;
 
-	mercenary_count = 0; //Reset the counter
-	memset(mercenary_db,0,sizeof(mercenary_db));
+	mercenary_db_data.clear();
+
 	for(i = 0; i<ARRAYLENGTH(filename); i++){
-		sv_readdb(db_path, filename[i], ',', 26, 26, MAX_MERCENARY_CLASS, &mercenary_readdb_sub, i > 0);
+		sv_readdb(db_path, filename[i], ',', 26, 26, -1, &mercenary_readdb_sub, i > 0);
 	}
 }
 
@@ -560,13 +565,11 @@ static bool mercenary_read_skilldb_sub(char* str[], int columns, int current)
 {// <merc id>,<skill id>,<skill level>
 	struct s_mercenary_db *db;
 	uint16 class_, skill_id, skill_lv;
-	uint8 i = 0;
 	short idx = -1;
 
 	class_ = atoi(str[0]);
-	ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary_db[i].class_);
-	if( i == MAX_MERCENARY_CLASS )
-	{
+	db = mercenary_db(class_);
+	if( !db ){
 		ShowError("read_mercenary_skilldb : Class %d not found in mercenary_db for skill entry.\n", class_);
 		return false;
 	}
@@ -577,7 +580,6 @@ static bool mercenary_read_skilldb_sub(char* str[], int columns, int current)
 		return false;
 	}
 
-	db = &mercenary_db[i];
 	skill_lv = atoi(str[2]);
 
 	db->skill[idx].id = skill_id;
@@ -612,5 +614,5 @@ void do_init_mercenary(void){
 * Do Final Mercenary datas
 **/
 void do_final_mercenary(void){
-	//Nothing to do yet
+	mercenary_db_data.clear();
 }

+ 14 - 6
src/map/mercenary.hpp

@@ -13,11 +13,21 @@
 #define MAX_MER_DISTANCE 15
 
 enum e_MercGuildType {
+	NONE_MERC_GUILD = -1,
 	ARCH_MERC_GUILD,
 	SPEAR_MERC_GUILD,
 	SWORD_MERC_GUILD,
 };
 
+enum MERID {
+	MERID_MER_ARCHER01 = 6017,
+	MERID_MER_ARCHER10 = 6026,
+	MERID_MER_LANCER01,
+	MERID_MER_LANCER10 = 6036,
+	MERID_MER_SWORDMAN01,
+	MERID_MER_SWORDMAN10 = 6046
+};
+
 struct s_mercenary_db {
 	int class_;
 	char sprite[NAME_LENGTH], name[NAME_LENGTH];
@@ -30,8 +40,6 @@ struct s_mercenary_db {
 	} skill[MAX_MERCSKILL];
 };
 
-extern struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS];
-
 struct mercenary_data {
 	struct block_list bl;
 	struct unit_data ud;
@@ -51,10 +59,10 @@ struct mercenary_data {
 	unsigned devotion_flag : 1;
 };
 
-bool mercenary_class(int class_);
-struct view_data * mercenary_get_viewdata(int class_);
+struct s_mercenary_db *mercenary_db(uint16 class_);
+struct view_data * mercenary_get_viewdata(uint16 class_);
 
-bool mercenary_create(struct map_session_data *sd, int class_, unsigned int lifetime);
+bool mercenary_create(struct map_session_data *sd, uint16 class_, unsigned int lifetime);
 bool mercenary_recv_data(struct s_mercenary *merc, bool flag);
 void mercenary_save(struct mercenary_data *md);
 
@@ -65,7 +73,7 @@ int mercenary_delete(struct mercenary_data *md, int reply);
 void mercenary_contract_stop(struct mercenary_data *md);
 
 int mercenary_get_lifetime(struct mercenary_data *md);
-int mercenary_get_guild(struct mercenary_data *md);
+enum e_MercGuildType mercenary_get_guild(struct mercenary_data *md);
 int mercenary_get_faith(struct mercenary_data *md);
 void mercenary_set_faith(struct mercenary_data *md, int value);
 int mercenary_get_calls(struct mercenary_data *md);

+ 1 - 1
src/map/script.cpp

@@ -18980,7 +18980,7 @@ BUILDIN_FUNC(mercenary_create)
 
 	class_ = script_getnum(st,2);
 
-	if( !mercenary_class(class_) )
+	if( !mercenary_db(class_) )
 		return SCRIPT_CMD_SUCCESS;
 
 	contract_time = script_getnum(st,3);

+ 1 - 1
src/map/status.cpp

@@ -7657,7 +7657,7 @@ void status_set_viewdata(struct block_list *bl, int class_)
 		vd = npc_get_viewdata(class_);
 	else if (homdb_checkid(class_))
 		vd = hom_get_viewdata(class_);
-	else if (mercenary_class(class_))
+	else if (mercenary_db(class_))
 		vd = mercenary_get_viewdata(class_);
 	else if (elemental_class(class_))
 		vd = elemental_get_viewdata(class_);