summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
authorpanikon <panikon@zoho.com>2014-05-06 21:14:46 -0300
committerpanikon <panikon@zoho.com>2014-05-06 21:14:46 -0300
commit9a425c11b61fb6f4e299013c7d8d9841129b8f45 (patch)
treeb8e8bc56c6e51679c23fe2de0e268f49b29f7288 /src/map
parent9cf6b362a0d5e2f52c017d747c0fa8f69a1a273f (diff)
downloadhercules-9a425c11b61fb6f4e299013c7d8d9841129b8f45.tar.gz
hercules-9a425c11b61fb6f4e299013c7d8d9841129b8f45.tar.bz2
hercules-9a425c11b61fb6f4e299013c7d8d9841129b8f45.tar.xz
hercules-9a425c11b61fb6f4e299013c7d8d9841129b8f45.zip
Bug fixes and other changes
#Fixed issue where a corrupted map cache would lead to a crash *Moved Big-endian compatibility functions to common/utils.h #Fixed issue 8162 *http://hercules.ws/board/tracker/issue-8162-loadnpc-doesnt-trigger-oninit-of-duplicate-npcs/ *Added options to npc_parse_duplicate #Fixed issue 8169 *http://hercules.ws/board/tracker/issue-8169-script-command-guildskill-skill-idlevel-not-working-as-intended/ *Changed *guildskill behavior, now it behaves exactly as depicted in the documentation *Updated *guildskill documentation #Added missing GBI types to mapif_parse_GuildBasicInfoChange now it's possible to change guild exp, lv, skill point and skill information #GeoIP revamp *GeoIP module was partially rewritten *Added several data checks to prevent corruption and crashes *Updated GeoIP database *See https://github.com/maxmind/geoip-api-c/blob/master/libGeoIP/GeoIP.c for more information #Added packetver checks regarding NST_MARKET *Now *tradertype warns if user is trying to use this feature with older clients
Diffstat (limited to 'src/map')
-rw-r--r--src/map/clif.c6
-rw-r--r--src/map/intif.c20
-rw-r--r--src/map/map.c14
-rw-r--r--src/map/npc.c21
-rw-r--r--src/map/npc.h2
-rw-r--r--src/map/script.c35
6 files changed, 87 insertions, 11 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index 2fbf64e09..24dcfebf4 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -18179,6 +18179,7 @@ void clif_parse_NPCShopClosed(int fd, struct map_session_data *sd) {
}
/* NPC Market (by Ind after an extensive debugging of the packet, only possible thanks to Yommy <3) */
void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) {
+#if PACKETVER >= 20131223
struct npc_item_list *shop = nd->u.scr.shop->item;
unsigned short shop_size = nd->u.scr.shop->items, i, c;
struct item_data *id = NULL;
@@ -18199,12 +18200,14 @@ void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) {
npcmarket_open.PacketLength = 4 + ( sizeof(npcmarket_open.list[0]) * c );
clif->send(&npcmarket_open,npcmarket_open.PacketLength,&sd->bl,SELF);
+#endif
}
void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) {
/* TODO track the state <3~ */
sd->npc_shopid = 0;
}
void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc_market_purchase *req, unsigned char response) {
+#if PACKETVER >= 20131223
unsigned short c = 0;
npcmarket_result.PacketType = npcmarketresultackType;
@@ -18237,11 +18240,14 @@ void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc
npcmarket_result.PacketLength = 5 + ( sizeof(npcmarket_result.list[0]) * c );;
clif->send(&npcmarket_result,npcmarket_result.PacketLength,&sd->bl,SELF);
+#endif
}
void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) {
+#if PACKETVER >= 20131223
struct packet_npc_market_purchase *p = P2PTR(fd);
clif->npc_market_purchase_ack(sd,p,npc->market_buylist(sd,(p->PacketLength - 4) / sizeof(p->list[0]),p));
+#endif
}
/* */
unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
diff --git a/src/map/intif.c b/src/map/intif.c
index 1aa5a46d4..6bd24368a 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -692,7 +692,10 @@ int intif_guild_message(int guild_id,int account_id,const char *mes,int len)
return 0;
}
-// Request a change of Guild basic information
+/**
+ * Requests to change a basic guild information, it is parsed via mapif_parse_GuildBasicInfoChange
+ * To see the information types that can be changed see mmo.h::guild_basic_info
+ **/
int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len)
{
if (intif->CheckForCharServer())
@@ -1237,6 +1240,21 @@ void intif_parse_GuildBasicInfoChanged(int fd) {
case GBI_EXP: g->exp = RFIFOQ(fd,10); break;
case GBI_GUILDLV: g->guild_lv = RFIFOW(fd,10); break;
case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break;
+ case GBI_SKILLLV: {
+ int idx, max;
+ struct guild_skill *gs = (struct guild_skill *)RFIFOP(fd,10);
+
+ if( gs == NULL )
+ return;
+
+ idx = gs->id - GD_SKILLBASE;
+ max = guild->skill_get_max(gs->id);
+ if( gs->lv > max )
+ gs->lv = max;
+
+ memcpy(&(g->skill[idx]), gs, sizeof(g->skill[idx]));
+ break;
+ }
}
}
diff --git a/src/map/map.c b/src/map/map.c
index 04ac8a239..11ef56cb3 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -2846,6 +2846,7 @@ int map_eraseipport(unsigned short map_index, uint32 ip, uint16 port) {
* [Shinryo]: Init the mapcache
*------------------------------------------*/
char *map_init_mapcache(FILE *fp) {
+ struct map_cache_main_header header;
size_t size = 0;
char *buffer;
@@ -2869,6 +2870,19 @@ char *map_init_mapcache(FILE *fp) {
return NULL;
}
+ rewind(fp);
+
+ // Get main header to verify if data is corrupted
+ if( fread(&header, sizeof(header), 1, fp) != 1 ) {
+ ShowError("map_init_mapcache: Error obtaining main header!\n");
+ return NULL;
+ }
+ ShowError("Map cache is corrupted!\r"); // If the file is totally corrupted this will allow us to warn the user
+ if( GetULong((unsigned char *)&(header.file_size)) != size ) {
+ ShowError("map_init_mapcache: Map cache is corrupted!\n");
+ return NULL;
+ }
+
return buffer;
}
diff --git a/src/map/npc.c b/src/map/npc.c
index ae374e961..43e4bcc88 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2935,7 +2935,8 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char*
/// shop/cashshop/npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>
/// npc: -%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>
/// npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>
-const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
+/// !!Only NPO_ONINIT is available trough options!!
+const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options)
{
int x, y, dir, m, xs = -1, ys = -1;
char mapname[32];
@@ -3074,6 +3075,20 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
nd->u.scr.timerid = INVALID_TIMER;
+ if( type == SCRIPT && options&NPO_ONINIT ) {
+ // From npc_parse_script
+ char evname[EVENT_NAME_LENGTH];
+ struct event_data *ev;
+
+ snprintf(evname, ARRAYLENGTH(evname), "%s::OnInit", nd->exname);
+
+ if( ( ev = (struct event_data*)strdb_get(npc->ev_db, evname) ) ) {
+
+ //Execute OnInit
+ script->run(nd->u.scr.script,ev->pos,0,nd->bl.id);
+
+ }
+ }
return end;
}
@@ -3137,7 +3152,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
else
snprintf(w4, sizeof(w4), "%d", snd->class_);
- npc->parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING");
+ npc->parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING", NPO_NONE);
}
return 0;
@@ -4094,7 +4109,7 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
}
else if( (i=0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) && count > 3 )
{
- p = npc->parse_duplicate(w1,w2,w3,w4, p, buffer, filepath);
+ p = npc->parse_duplicate(w1,w2,w3,w4, p, buffer, filepath, (runOnInit?NPO_ONINIT:NPO_NONE));
}
else if( (strcmp(w2,"monster") == 0 || strcmp(w2,"boss_monster") == 0) && count > 3 )
{
diff --git a/src/map/npc.h b/src/map/npc.h
index 346a9f8c0..d1e060a39 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -237,7 +237,7 @@ struct npc_interface {
void (*convertlabel_db) (struct npc_label_list *label_list, const char *filepath);
const char* (*skip_script) (const char *start, const char *buffer, const char *filepath);
const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options);
- const char* (*parse_duplicate) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath);
+ const char* (*parse_duplicate) (char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options);
int (*duplicate4instance) (struct npc_data *snd, int16 m);
void (*setcells) (struct npc_data *nd);
int (*unsetcells_sub) (struct block_list *bl, va_list ap);
diff --git a/src/map/script.c b/src/map/script.c
index 3e11a510e..c57b086f4 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -8268,20 +8268,36 @@ BUILDIN(addtoskill) {
/// guildskill <skill id>,<amount>;
/// guildskill "<skill name>",<amount>;
BUILDIN(guildskill) {
- int id;
+ int skill_id, id, max_points;
int level;
+
TBL_PC* sd;
- int i;
+ struct guild *gd;
+ struct guild_skill gd_skill;
sd = script->rid2sd(st);
if( sd == NULL )
- return true;// no player attached, report source
+ return false; // no player attached, report source
- id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+ if( (gd = sd->guild) == NULL )
+ return true;
+
+ skill_id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
level = script_getnum(st,3);
- for( i=0; i < level; i++ )
- guild->skillup(sd, id);
+ id = skill_id - GD_SKILLBASE;
+ max_points = guild->skill_get_max(skill_id);
+
+ if( (gd->skill[id].lv + level) > max_points )
+ level = max_points - gd->skill[id].lv;
+
+ if( level == 0 )
+ return true;
+
+ memcpy(&gd_skill, &(gd->skill[id]), sizeof(gd->skill[id]));
+ gd_skill.lv += level;
+
+ intif->guild_change_basicinfo( gd->guild_id, GBI_SKILLLV, &(gd_skill), sizeof(gd_skill) );
return true;
}
@@ -18538,6 +18554,13 @@ BUILDIN(tradertype) {
npc->market_delfromsql(nd,USHRT_MAX);
}
+#if PACKETVER < 20131223
+ if( type == NST_MARKET ) {
+ ShowWarning("buildin_tradertype: NST_MARKET is only available with PACKETVER 20131223 or newer!\n");
+ script->reportsrc(st);
+ }
+#endif
+
nd->u.scr.shop->type = type;
return true;