summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2009-11-19 18:19:09 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2009-11-19 18:19:09 +0000
commit30c8d7704026aa450b64997c2996ee8d9d4f2cec (patch)
treedae267b2e016111da192de4dbf67679878e73409
parent620ea0643c3bcbfed5dd7c84e8d65fc8941997a7 (diff)
downloadhercules-30c8d7704026aa450b64997c2996ee8d9d4f2cec.tar.gz
hercules-30c8d7704026aa450b64997c2996ee8d9d4f2cec.tar.bz2
hercules-30c8d7704026aa450b64997c2996ee8d9d4f2cec.tar.xz
hercules-30c8d7704026aa450b64997c2996ee8d9d4f2cec.zip
- Applied the renewal client support patch from Diablo (eA forum topic 222623)
- Added support for strcharinfo(3) to retrieve the player's map - Added script command "searchitem" for name item searches. - Moved PACKETVER to src/common/mmo.h as it's needed by the char-server now - Changed the status valX from int to long so that it won't break for pointer-storage in other architectures. - Moved the change party leader code to party.c - A few bugfixes or packet field completions based on my past experience messing around with my server. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@14155 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r--Changelog-Trunk.txt11
-rw-r--r--conf/battle/client.conf38
-rw-r--r--db/packet_db.txt219
-rw-r--r--doc/script_commands.txt39
-rw-r--r--src/char/char.c53
-rw-r--r--src/char/int_status.c4
-rw-r--r--src/char_sql/char.c50
-rw-r--r--src/common/mmo.h50
-rw-r--r--src/map/atcommand.c54
-rw-r--r--src/map/battle.c4
-rw-r--r--src/map/clif.c164
-rw-r--r--src/map/clif.h32
-rw-r--r--src/map/npc.c1
-rw-r--r--src/map/party.c51
-rw-r--r--src/map/party.h1
-rw-r--r--src/map/script.c105
-rw-r--r--src/map/skill.c3
17 files changed, 662 insertions, 217 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index 25c4784b2..999c68be1 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -3,6 +3,17 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
+2009/11/19
+ * Applied the renewal client support patch from Diablo (eA forum topic 222623).
+ By default eA still supports sakexe/ragexe clients. In order to support the
+ renewal clients you must:
+ - 1: Change the default packet version to "default" in db/packet_db.txt
+ - 2: Change the supported PACKETVER in src/common/mmo.h to the most recent one
+ - 3: recompile. [Skotlex]
+ * Added support for strcharinfo(3) to retrieve the player's map, as getmapxy
+ can be a bit unwieldy when you just want this information. [Skotlex]
+ * Added script command "searchitem" which enables scripts to do item searches
+ based on name (can be useful for creating query NPCs). [Skotlex]
09/11/09
* Fixed mob is removed from map right after his rebirth. [Inkfish]
* Fixed dead event does not trigger when a mob has rebirth skill and dies for the second time. [Inkfish]
diff --git a/conf/battle/client.conf b/conf/battle/client.conf
index a0a5b6bdf..a2db1a6c3 100644
--- a/conf/battle/client.conf
+++ b/conf/battle/client.conf
@@ -22,23 +22,25 @@
// Set here which client version do you accept. Add all values of clients:
// Clients older than accepted versions, and versions not set to 'accepted'
// here will be rejected when logging in
-// 0x0001: Clients older than 2004-09-06aSakray (packet versions 5-9)
-// 0x0002: 2004-09-06aSakexe (version 10)
-// 0x0004: 2004-09-20aSakexe (version 11)
-// 0x0008: 2004-10-05aSakexe (version 12)
-// 0x0010: 2004-10-25aSakexe (version 13)
-// 0x0020: 2004-11-29aSakexe (version 14)
-// 0x0040: 2005-01-10bSakexe (version 15)
-// 0x0080: 2005-05-09aSakexe (version 16)
-// 0x0100: 2005-06-28aSakexe (version 17)
-// 0x0200: 2005-07-18aSakexe (version 18)
-// 0x0400: 2005-07-19bSakexe (version 19)
-// 0x0800: 2006-03-27aSakexe (version 20)
-// 0x1000: 2007-01-08aSakexe (version 21)
-// 0x2000: 2007-02-12aSakexe (version 22)
-// 0x4000: 2008-09-10aSakexe (version 23)
-// default value: 0xFFFF (all clients)
-packet_ver_flag: 0xFFFF
+// 0x00001: Clients older than 2004-09-06aSakray (packet versions 5-9)
+// 0x00002: 2004-09-06aSakexe (version 10)
+// 0x00004: 2004-09-20aSakexe (version 11)
+// 0x00008: 2004-10-05aSakexe (version 12)
+// 0x00010: 2004-10-25aSakexe (version 13)
+// 0x00020: 2004-11-29aSakexe (version 14)
+// 0x00040: 2005-01-10bSakexe (version 15)
+// 0x00080: 2005-05-09aSakexe (version 16)
+// 0x00100: 2005-06-28aSakexe (version 17)
+// 0x00200: 2005-07-18aSakexe (version 18)
+// 0x00400: 2005-07-19bSakexe (version 19)
+// 0x00800: 2006-03-27aSakexe (version 20)
+// 0x01000: 2007-01-08aSakexe (version 21)
+// 0x02000: 2007-02-12aSakexe (version 22)
+// 0x04000: 2008-09-10aSakexe (version 23)
+// 0x08000: 2008-08-27aRagexeRE (version 24)
+// 0x10000: 2008-09-10aRagexeRE (version 25)
+// default value: 0xFFFFF (all clients)
+packet_ver_flag: 0xFFFFF
// Minimum delay between whisper/global/party/guild messages (in ms)
// Messages that break this threshold are silently omitted.
@@ -116,4 +118,4 @@ display_hallucination: yes
// Set this to 1 if your client supports status change timers and you want to use them
// Clients from 2009 onward support this
-display_status_timers: no
+display_status_timers: yes
diff --git a/db/packet_db.txt b/db/packet_db.txt
index 94d55b164..250627fbe 100644
--- a/db/packet_db.txt
+++ b/db/packet_db.txt
@@ -7,7 +7,9 @@
// Main packet version of the DB to use (default = max available version)
// Client detection is faster when all clients use this version.
-packet_db_ver: default
+// Version 23 is the latest Sakexe (above versions are for Renewal clients)
+packet_db_ver: 23
+//packet_db_ver: default
packet_ver: 5
@@ -1202,50 +1204,6 @@ packet_ver: 22
0x035f,-1
0x0389,-1
-//2008-08-20aSakexe
-0x040c,-1
-0x040d,-1
-0x040e,-1
-0x040f,-1
-0x0410,-1
-0x0411,-1
-0x0412,-1
-0x0413,-1
-0x0414,-1
-0x0415,-1
-0x0416,-1
-0x0417,-1
-0x0418,-1
-0x0419,-1
-0x041a,-1
-0x041b,-1
-0x041c,-1
-0x041d,-1
-0x041e,-1
-0x041f,-1
-0x0420,-1
-0x0421,-1
-0x0422,-1
-0x0423,-1
-0x0424,-1
-0x0425,-1
-0x0426,-1
-0x0427,-1
-0x0428,-1
-0x0429,-1
-0x042a,-1
-0x042b,-1
-0x042c,-1
-0x042d,-1
-0x042e,-1
-0x042f,-1
-0x0430,-1
-0x0431,-1
-0x0432,-1
-0x0433,-1
-0x0434,-1
-0x0435,-1
-
//2008-09-10aSakexe
packet_ver: 23
0x0436,19,wanttoconnection,2:6:10:14:18
@@ -1253,38 +1211,157 @@ packet_ver: 23
0x0438,10,useskilltoid,2:4:6
0x0439,8,useitem,2:4
-//2008-11-13aSakexe
+//2009-04-08aSakexe
+//0x02a6,-1
+//0x02a7,-1
+0x044a,6
+
+//Renewal Clients
+//2008-08-27aRagexeRE
+packet_ver: 24
+0x0072,22,useskilltoid,9:15:18
+0x007c,44
+0x007e,105,useskilltoposinfo,10:14:18:23:25
+0x0085,10,changedir,4:9
+0x0089,11,ticksend,7
+0x008c,14,getcharnamerequest,10
+0x0094,19,movetokafra,3:15
+0x009b,34,wanttoconnection,7:15:25:29:33
+0x009f,20,useitem,7:20
+0x00a2,14,solvecharname,10
+0x00a7,9,walktoxy,6
+0x00f5,11,takeitem,7
+0x00f7,17,movefromkafra,3:13
+0x0113,25,useskilltopos,10:14:18:23
+0x0116,17,dropitem,6:15
+0x0190,23,actionrequest,9:22
+0x02e2,20
+0x02e3,22
+0x02e4,11
+0x02e5,9
+
+//2008-09-10aRagexeRE
+packet_ver: 25
+0x0436,19,wanttoconnection,2:6:10:14:18
+0x0437,7,actionrequest,2:6
+0x0438,10,useskilltoid,2:4:6
+0x0439,8,useitem,2:4
+
+//2008-11-12aRagexeRE
0x043d,8
-0x043e,-1
+//0x043e,-1
0x043f,8
-//2008-11-26aSakexe
+//2008-12-17aRagexeRE
0x01a2,37
-0x0440,10
-0x0441,4
+//0x0440,10
+//0x0441,4
+//0x0442,8
+//0x0443,8
-//2008-12-10aSakexe
-0x0442,-1
-0x0443,8
+//2008-12-17bRagexeRE
+0x006d,114
-//2009-01-14aSakexe
+//2009-01-21aRagexeRE
0x043f,25
-0x0444,-1
-0x0445,10
-
-//2009-02-18aSakexe
-0x0446,14
-
-//2009-02-25aSakexe
-0x0448,-1
-
-//2009-03-30aSakexe
-0x0449,4
-
-//2009-04-08aSakexe
-0x02a6,-1
-0x02a7,-1
-0x044a,6
+//0x0444,-1
+//0x0445,10
+
+//2009-02-18aRagexeRE
+//0x0446,14
+
+//2009-02-26cRagexeRE
+//0x0448,-1
+
+//2009-04-01aRagexeRE
+//0x0449,4
+
+//2009-05-14aRagexeRE
+//0x044b,2
+
+//2009-05-20aRagexeRE
+//0x07d0,6
+//0x07d1,2
+//0x07d2,-1
+//0x07d3,4
+//0x07d4,4
+//0x07d5,4
+//0x07d6,4
+//0x0447,2
+
+//2009-06-03aRagexeRE
+0x07d7,8,partychangeoption,2:6
+0x07d8,8
+0x07d9,254
+0x07da,6,partychangeleader,2
+
+//2009-06-10aRagexeRE
+//0x07db,8
+
+//2009-06-17aRagexeRE
+0x07d9,268
+//0x07dc,6
+//0x07dd,54
+//0x07de,30
+//0x07df,54
+
+//2009-07-01aRagexeRE
+//0x0275,37
+//0x0276,-1
+
+//2009-07-08aRagexeRE
+//0x07e0,58
+
+//2009-07-15aRagexeRE
+//0x07e1,15
+
+//2009-08-05aRagexeRE
+//0x07e2,8
+
+//2009-08-18aRagexeRE
+//0x07e3,6
+//0x07e4,-1
+//0x07e6,8
+
+//2009-08-25aRagexeRE
+//0x07e6,28
+0x07e7,5
+
+//2009-09-22aRagexeRE
+0x07e5,8
+//0x07e6,8
+0x07e7,32
+0x07e8,-1
+0x07e9,5
+
+//2009-09-29aRagexeRE
+//0x07ea,2
+//0x07eb,0
+//0x07ec,6
+//0x07ed,8
+//0x07ee,6
+//0x07ef,8
+//0x07f0,4
+//0x07f2,4
+//0x07f3,3
+
+//2009-10-06aRagexeRE
+//0x07ec,8
+//0x07ed,10
+//0x07f0,8
+//0x07f1,15
+//0x07f2,6
+//0x07f3,4
+//0x07f4,3
+
+//2009-10-27aRagexeRE
+//0x07f5,6
+//0x07f6,14
+
+//2009-11-03aRagexeRE
+//0x07f7,0
+//0x07f8,0
+//0x07f9,0
//Add new packets here
-//packet_ver: 24
+//packet_ver: 26
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index bb4097063..c6b892311 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -4,7 +4,7 @@
//= A reference manual for the eAthena scripting language.
//= Commands are sorted depending on their functionality.
//===== Version ===========================================
-//= 3.25.20081220
+//= 3.28.20091119
//=========================================================
//= 1.0 - First release, filled will as much info as I could
//= remember or figure out, most likely there are errors,
@@ -132,6 +132,9 @@
//= Replaced 'bonusautoscript' by 'autobonus'. [Inkfish]
//= 3.27.20090725
//= Added Quest Log related commands. [Inkfish]
+//= 3.28.20091119
+//= Added showevent and itemsearch commands [Skotlex]
+//= Added info on strcharinfo(3) [Skotlex]
//=========================================================
This document is a reference manual for all the scripting commands and functions
@@ -2013,6 +2016,7 @@ invoking character. Whatever it returns is determined by type.
0 - Character's name.
1 - The name of the party they're in if any.
2 - The name of the guild they're in if any.
+ 3 - The name of the map the character is in.
If a character is not a member of any party or guild, an empty string will be
returned when requesting that information.
@@ -4065,6 +4069,20 @@ If the map name is given as "this", the map the invoking character is on will be
---------------------------------------
+*searchitem <array name>,"<item name>";
+
+This command will fill the given array with the ID of items whose name matches the given one. It returns the number of items found. For performance reasons, the results array is limited to 10 items.
+
+ mes "What item are you looking for?";
+ input @name$;
+ set @qty, searchitem(@matches[0],@name$);
+ mes "I found "+@qty+" items:";
+ for (set @i, 0; @i < @qty; set @i, @i+1)
+ //Display name (eg: "Apple[0]")
+ mes getitemname(@matches[@i])+"["+getitemslots(@matches[@i])+"]";
+
+---------------------------------------
+
*delitem <item id>,<amount>{,<account ID>};
*delitem "<item name>",<amount>{,<account ID>};
@@ -6639,6 +6657,25 @@ If parameter "HUNTING" is supplied:
2 = you've killed all of the target monsters
---------------------------------------
+*showevent <state>, <color>;
+
+Show a colored mark in the mini-map like "viewpoint" and an emoticon on top of a NPC.
+This is used to indicate that a NPC has a quest or an event to certain player/s.
+
+state can be:
+ 0 = disable ( Used to disable and remove the mark and the emoticon from the NPC. )
+ 1 = exclamation emoticon ( Used to show an important quest event to certain player. )
+ 2 = interrogation emoticon ( Used to show an non-important quest event to certain player. )
+ Other value may cause client crashes.
+
+color can be:
+ 0 = yellow
+ 1 = orange
+ 2 = green
+ 3 = blue
+ other values show a transparent mark in the mini-map.
+
+----------------------------------------
Whew.
That's about all of them.
diff --git a/src/char/char.c b/src/char/char.c
index 200257584..f2910751f 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -1675,16 +1675,19 @@ int count_users(void)
return users;
}
-/// Writes char data to the buffer in the format used by the client.
-/// Used in packets 0x6b (chars info) and 0x6d (new char info)
-/// Returns the size (106 or 108)
-int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p)
+// Writes char data to the buffer in the format used by the client.
+// Used in packets 0x6b (chars info) and 0x6d (new char info)
+// Returns the size
+#define MAX_CHAR_BUF 110 //Max size (for WFIFOHEAD calls)
+int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
{
- int size = 106;
+ unsigned short offset = 0;
+ uint8* buf;
- if( buf == NULL || p == NULL )
+ if( buffer == NULL || p == NULL )
return 0;
+ buf = WBUFP(buffer,0);
WBUFL(buf,0) = p->char_id;
WBUFL(buf,4) = min(p->base_exp, LONG_MAX);
WBUFL(buf,8) = p->zeny;
@@ -1696,8 +1699,15 @@ int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p)
WBUFL(buf,32) = p->karma;
WBUFL(buf,36) = p->manner;
WBUFW(buf,40) = min(p->status_point, SHRT_MAX);
+#if PACKETVER > 20081217
+ WBUFL(buf,42) = p->hp;
+ WBUFL(buf,46) = p->max_hp;
+ offset+=4;
+ buf = WBUFP(buffer,offset);
+#else
WBUFW(buf,42) = min(p->hp, SHRT_MAX);
WBUFW(buf,44) = min(p->max_hp, SHRT_MAX);
+#endif
WBUFW(buf,46) = min(p->sp, SHRT_MAX);
WBUFW(buf,48) = min(p->max_sp, SHRT_MAX);
WBUFW(buf,50) = DEFAULT_WALK_SPEED; // p->speed;
@@ -1722,10 +1732,9 @@ int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p)
WBUFW(buf,104) = p->slot;
#if PACKETVER >= 20061023
WBUFW(buf,106) = ( p->rename > 0 ) ? 0 : 1;
- size += 2;
+ offset += 2;
#endif
-
- return size;
+ return 106+offset;
}
//----------------------------------------
@@ -1747,7 +1756,7 @@ int mmo_char_send006b(int fd, struct char_session_data* sd)
sd->found_char[i] = -1;
j = 24; // offset
- WFIFOHEAD(fd,j + found_num*108); // or 106(!)
+ WFIFOHEAD(fd,j + found_num*MAX_CHAR_BUF);
WFIFOW(fd,0) = 0x6b;
memset(WFIFOP(fd,4), 0, 20); // unknown bytes
for(i = 0; i < found_num; i++)
@@ -3473,7 +3482,7 @@ int parse_char(int fd)
{
int len;
// send to player
- WFIFOHEAD(fd,110);
+ WFIFOHEAD(fd,MAX_CHAR_BUF+2);
WFIFOW(fd,0) = 0x6d;
len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat[i].status);
WFIFOSET(fd,len);
@@ -3613,6 +3622,28 @@ int parse_char(int fd)
RFIFOSKIP(fd,34);
break;
+ // captcha code request (not implemented)
+ // R 07e5 <?>.w <aid>.l
+ case 0x7e5:
+ WFIFOHEAD(fd,5);
+ WFIFOW(fd,0) = 0x7e9;
+ WFIFOW(fd,2) = 5;
+ WFIFOB(fd,4) = 1;
+ WFIFOSET(fd,5);
+ RFIFOSKIP(fd,8);
+ break;
+
+ // captcha code check (not implemented)
+ // R 07e7 <len>.w <aid>.l <code>.b10 <?>.b14
+ case 0x7e7:
+ WFIFOHEAD(fd,5);
+ WFIFOW(fd,0) = 0x7e9;
+ WFIFOW(fd,2) = 5;
+ WFIFOB(fd,4) = 1;
+ WFIFOSET(fd,5);
+ RFIFOSKIP(fd,32);
+ break;
+
// login as map-server
case 0x2af8:
if (RFIFOREST(fd) < 60)
diff --git a/src/char/int_status.c b/src/char/int_status.c
index bf5d94155..52b14ebbe 100644
--- a/src/char/int_status.c
+++ b/src/char/int_status.c
@@ -54,7 +54,7 @@ static void inter_status_tostr(char* line, struct scdata *sc_data)
len = sprintf(line, "%d,%d,%d\t", sc_data->account_id, sc_data->char_id, sc_data->count);
for(i = 0; i < sc_data->count; i++) {
- len += sprintf(line + len, "%d,%d,%d,%d,%d,%d\t", sc_data->data[i].type, sc_data->data[i].tick,
+ len += sprintf(line + len, "%d,%ld,%ld,%ld,%ld,%ld\t", sc_data->data[i].type, sc_data->data[i].tick,
sc_data->data[i].val1, sc_data->data[i].val2, sc_data->data[i].val3, sc_data->data[i].val4);
}
return;
@@ -74,7 +74,7 @@ static int inter_scdata_fromstr(char *line, struct scdata *sc_data)
for (i = 0; i < sc_data->count; i++)
{
- if (sscanf(line + next, "%hu,%d,%d,%d,%d,%d\t%n", &sc_data->data[i].type, &sc_data->data[i].tick,
+ if (sscanf(line + next, "%hu,%ld,%ld,%ld,%ld,%ld\t%n", &sc_data->data[i].type, &sc_data->data[i].tick,
&sc_data->data[i].val1, &sc_data->data[i].val2, &sc_data->data[i].val3, &sc_data->data[i].val4, &len) < 6)
{
aFree(sc_data->data);
diff --git a/src/char_sql/char.c b/src/char_sql/char.c
index 85e7d83c0..ee1e08bdb 100644
--- a/src/char_sql/char.c
+++ b/src/char_sql/char.c
@@ -132,7 +132,6 @@ struct char_session_data {
char new_name[NAME_LENGTH];
};
-int char_num, char_max;
int max_connect_user = 0;
int gm_allow_level = 99;
int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
@@ -811,6 +810,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit
return 0;
}
+#define MAX_CHAR_BUF 110 //Max size (for WFIFOHEAD calls)
int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p);
#ifndef TXT_SQL_CONVERT
@@ -1538,14 +1538,16 @@ int count_users(void)
/// Writes char data to the buffer in the format used by the client.
/// Used in packets 0x6b (chars info) and 0x6d (new char info)
-/// Returns the size (106 or 108)
-int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p)
+// Returns the size
+int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
{
- int size = 106;
+ unsigned short offset = 0;
+ uint8* buf;
- if( buf == NULL || p == NULL )
+ if( buffer == NULL || p == NULL )
return 0;
+ buf = WBUFP(buffer,0);
WBUFL(buf,0) = p->char_id;
WBUFL(buf,4) = min(p->base_exp, LONG_MAX);
WBUFL(buf,8) = p->zeny;
@@ -1557,8 +1559,15 @@ int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p)
WBUFL(buf,32) = p->karma;
WBUFL(buf,36) = p->manner;
WBUFW(buf,40) = min(p->status_point, SHRT_MAX);
+#if PACKETVER > 20081217
+ WBUFL(buf,42) = p->hp;
+ WBUFL(buf,46) = p->max_hp;
+ offset+=4;
+ buf = WBUFP(buffer,offset);
+#else
WBUFW(buf,42) = min(p->hp, SHRT_MAX);
WBUFW(buf,44) = min(p->max_hp, SHRT_MAX);
+#endif
WBUFW(buf,46) = min(p->sp, SHRT_MAX);
WBUFW(buf,48) = min(p->max_sp, SHRT_MAX);
WBUFW(buf,50) = DEFAULT_WALK_SPEED; // p->speed;
@@ -1583,10 +1592,9 @@ int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p)
WBUFW(buf,104) = p->slot;
#if PACKETVER >= 20061023
WBUFW(buf,106) = ( p->rename > 0 ) ? 0 : 1;
- size += 2;
+ offset+=2;
#endif
-
- return size;
+ return 106+offset;
}
int mmo_char_send006b(int fd, struct char_session_data* sd)
@@ -1597,7 +1605,7 @@ int mmo_char_send006b(int fd, struct char_session_data* sd)
ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
j = 24; // offset
- WFIFOHEAD(fd,j + MAX_CHARS*108); // or 106(!)
+ WFIFOHEAD(fd,j + MAX_CHARS*MAX_CHAR_BUF);
WFIFOW(fd,0) = 0x6b;
memset(WFIFOP(fd,4), 0, 20); // unknown bytes
j+=mmo_chars_fromsql(sd, WFIFOP(fd,j));
@@ -3204,7 +3212,7 @@ int parse_char(int fd)
mmo_char_fromsql(i, &char_dat, false); //Only the short data is needed.
// send to player
- WFIFOHEAD(fd,110);
+ WFIFOHEAD(fd,2+MAX_CHAR_BUF);
WFIFOW(fd,0) = 0x6d;
len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat);
WFIFOSET(fd,len);
@@ -3345,6 +3353,28 @@ int parse_char(int fd)
}
break;
+ // captcha code request (not implemented)
+ // R 07e5 <?>.w <aid>.l
+ case 0x7e5:
+ WFIFOHEAD(fd,5);
+ WFIFOW(fd,0) = 0x7e9;
+ WFIFOW(fd,2) = 5;
+ WFIFOB(fd,4) = 1;
+ WFIFOSET(fd,5);
+ RFIFOSKIP(fd,8);
+ break;
+
+ // captcha code check (not implemented)
+ // R 07e7 <len>.w <aid>.l <code>.b10 <?>.b14
+ case 0x7e7:
+ WFIFOHEAD(fd,5);
+ WFIFOW(fd,0) = 0x7e9;
+ WFIFOW(fd,2) = 5;
+ WFIFOB(fd,4) = 1;
+ WFIFOSET(fd,5);
+ RFIFOSKIP(fd,32);
+ break;
+
// log in as map-server
case 0x2af8:
if (RFIFOREST(fd) < 60)
diff --git a/src/common/mmo.h b/src/common/mmo.h
index d772f6fea..69a316dc4 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -7,6 +7,41 @@
#include "cbasetypes.h"
#include <time.h>
+// server->client protocol version
+// 0 - pre-?
+// 1 - ? - 0x196
+// 2 - ? - 0x78, 0x79
+// 3 - ? - 0x1c8, 0x1c9, 0x1de
+// 4 - ? - 0x1d7, 0x1d8, 0x1d9, 0x1da
+// 5 - 2003-12-18aSakexe+ - 0x1ee, 0x1ef, 0x1f0, ?0x1c4, 0x1c5?
+// 6 - 2004-03-02aSakexe+ - 0x1f4, 0x1f5
+// 7 - 2005-04-11aSakexe+ - 0x229, 0x22a, 0x22b, 0x22c
+// 20070521 - 2007-05-21aSakexe+ - 0x283
+// 20070821 - 2007-08-21aSakexe+ - 0x2c5
+// 20070918 - 2007-09-18aSakexe+ - 0x2d7, 0x2d9, 0x2da
+// 20071106 - 2007-11-06aSakexe+ - 0x78, 0x7c, 0x22c
+// 20081126 - 2008-11-26aSakexe+ - 0x1a2
+// 20090408 - 2009-04-08aSakexe+ - 0x44a (dont use as it overlaps with RE client packets)
+// 20080827 - 2008-08-27aRagexeRE+ - First RE Client
+// 20081217 - 2008-12-17aRagexeRE+ - 0x6d (Note: This one still use old Char Info Packet Structure)
+// 20081218 - 2008-12-17bRagexeRE+ - 0x6d (Note: From this one client use new Char Info Packet Structure)
+// 20090603 - 2009-06-03aRagexeRE+ - 0x7d7, 0x7d8, 0x7d9, 0x7da
+// 20090617 - 2009-06-17aRagexeRE+ - 0x7d9
+// 20090922 - 2009-09-22aRagexeRE+ - 0x7e5, 0x7e7, 0x7e8, 0x7e9
+#ifndef PACKETVER
+ #define PACKETVER 20081126
+ //#define PACKETVER 20090922
+#endif
+// backward compatible PACKETVER 8 and 9
+#if PACKETVER == 8
+#undef PACKETVER
+#define PACKETVER 20070521
+#endif
+#if PACKETVER == 9
+#undef PACKETVER
+#define PACKETVER 20071106
+#endif
+
#define FIFOSIZE_SERVERLINK 256*1024
//Remove/Comment this line to disable sc_data saving. [Skotlex]
@@ -15,8 +50,17 @@
//Note that newer clients no longer save hotkeys in the registry!
#define HOTKEY_SAVING
-//The number is the max number of hotkeys to save (27 = 9 skills x 3 bars)
-#define MAX_HOTKEYS 27
+//The number is the max number of hotkeys to save
+#if PACKETVER < 20090603
+ // (27 = 9 skills x 3 bars) (0x02b9,191)
+ #define MAX_HOTKEYS 27
+#elif PACKETVER < 20090617
+ // (36 = 9 skills x 4 bars) (0x07d9,254)
+ #define MAX_HOTKEYS 36
+#else
+ // (38 = 9 skills x 4 bars & 2 Quickslots)(0x07d9,268)
+ #define MAX_HOTKEYS 38
+#endif
#define MAX_MAP_PER_SERVER 1500 // Increased to allow creation of Instance Maps
#define MAX_INVENTORY 100
@@ -172,7 +216,7 @@ struct accreg {
//For saving status changes across sessions. [Skotlex]
struct status_change_data {
unsigned short type; //SC_type
- int val1, val2, val3, val4, tick; //Remaining duration.
+ long val1, val2, val3, val4, tick; //Remaining duration.
};
struct storage_data {
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index fe86cced7..bb8c1d683 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -2725,8 +2725,7 @@ int atcommand_produce(const int fd, struct map_session_data* sd, const char* com
if ((item_data = itemdb_searchname(item_name)) == NULL &&
(item_data = itemdb_exists(atoi(item_name))) == NULL)
{
- strcpy(atcmd_output, msg_txt(170)); // The item is not equipable.
- clif_displaymessage(fd, atcmd_output);
+ clif_displaymessage(fd, msg_txt(170)); //This item is not an equipment.
return -1;
}
item_id = item_data->nameid;
@@ -5950,62 +5949,17 @@ int atcommand_changegm(const int fd, struct map_session_data* sd, const char* co
*------------------------------------------*/
int atcommand_changeleader(const int fd, struct map_session_data* sd, const char* command, const char* message)
{
- struct party_data *p;
- struct map_session_data *pl_sd;
- int mi, pl_mi;
nullpo_retr(-1, sd);
-
- if (sd->status.party_id == 0 || (p = party_search(sd->status.party_id)) == NULL)
- { //Need to be a party leader.
- clif_displaymessage(fd, msg_txt(282));
- return -1;
- }
-
- if( map[sd->bl.m].flag.partylock )
- {
- clif_displaymessage(fd, "You cannot change party leaders on this map.");
- return -1;
- }
-
- ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd );
- if (mi == MAX_PARTY)
- return -1; //Shouldn't happen
-
- if (!p->party.member[mi].leader)
- { //Need to be a party leader.
- clif_displaymessage(fd, msg_txt(282));
- return -1;
- }
if (strlen(message)==0)
{
clif_displaymessage(fd, "Command usage: @changeleader <party member name>");
return -1;
}
-
- if((pl_sd=map_nick2sd((char *) message)) == NULL || pl_sd->status.party_id != sd->status.party_id) {
- clif_displaymessage(fd, msg_txt(283));
- return -1;
- }
- for (pl_mi = 0; pl_mi < MAX_PARTY && p->data[pl_mi].sd != pl_sd; pl_mi++);
-
- if (pl_mi == MAX_PARTY)
- return -1; //Shouldn't happen
-
- //Change leadership.
- p->party.member[mi].leader = 0;
- if (p->data[mi].sd->fd)
- clif_displaymessage(p->data[mi].sd->fd, msg_txt(284));
- p->party.member[pl_mi].leader = 1;
- if (p->data[pl_mi].sd->fd)
- clif_displaymessage(p->data[pl_mi].sd->fd, msg_txt(285));
-
- intif_party_leaderchange(p->party.party_id,p->party.member[pl_mi].account_id,p->party.member[pl_mi].char_id);
- //Update info.
- clif_party_info(p,NULL);
-
- return 0;
+ if (party_changeleader(sd, map_nick2sd((char *) message)))
+ return 0;
+ return -1;
}
/*==========================================
diff --git a/src/map/battle.c b/src/map/battle.c
index adf87c367..dd70de892 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -3345,7 +3345,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
else
return -1;
}
- else if( flag == BCT_NOONE ) //Why would someone use this? no clue.
+ if( flag == BCT_NOONE ) //Why would someone use this? no clue.
return -1;
if( t_bl == s_bl )
@@ -3730,7 +3730,7 @@ static const struct _battle_data {
{ "hack_info_GM_level", &battle_config.hack_info_GM_level, 60, 0, 100, },
{ "any_warp_GM_min_level", &battle_config.any_warp_GM_min_level, 20, 0, 100, },
{ "who_display_aid", &battle_config.who_display_aid, 40, 0, 100, },
- { "packet_ver_flag", &battle_config.packet_ver_flag, 0xFFFF, 0x0000, 0xFFFF, },
+ { "packet_ver_flag", &battle_config.packet_ver_flag, 0xFFFFFF,0x0000,INT_MAX, },
{ "min_hair_style", &battle_config.min_hair_style, 0, 0, INT_MAX, },
{ "max_hair_style", &battle_config.max_hair_style, 23, 0, INT_MAX, },
{ "min_hair_color", &battle_config.min_hair_color, 0, 0, INT_MAX, },
diff --git a/src/map/clif.c b/src/map/clif.c
index 2eb614780..fe04ada31 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -821,11 +821,17 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
WBUFW(buf,30) = vd->cloth_color;
WBUFW(buf,32) = (sd)? sd->head_dir : 0;
if (type&&spawn) { //End of packet 0x7c
- WBUFB(buf,34) = 0; // karma
+ WBUFB(buf,34) = (sd)?sd->status.karma:0; // karma
WBUFB(buf,35) = vd->sex;
WBUFPOS(buf,36,bl->x,bl->y,unit_getdir(bl));
WBUFB(buf,39) = 0;
+#if PACKETVER >= 20071106
WBUFB(buf,40) = 0;
+#endif
+#if PACKETVER > 20081217
+ WBUFB(buf,41) = 0;
+ WBUFB(buf,42) = 0;
+#endif
return packet_len(0x7c);
}
WBUFL(buf,34) = status_get_guild_id(bl);
@@ -4061,7 +4067,7 @@ int clif_skillinfo(struct map_session_data *sd,int skillid,int type,int range)
int clif_skillinfoblock(struct map_session_data *sd)
{
int fd;
- int i,c,len,id;
+ int i,len,id;
nullpo_retr(0, sd);
@@ -4070,7 +4076,7 @@ int clif_skillinfoblock(struct map_session_data *sd)
WFIFOHEAD(fd, MAX_SKILL * 37 + 4);
WFIFOW(fd,0) = 0x10f;
- for ( i = 0, c = 0, len = 4; i < MAX_SKILL; i++)
+ for ( i = 0, len = 4; i < MAX_SKILL; i++)
{
if( (id = sd->status.skill[i].id) != 0 )
{
@@ -4089,7 +4095,6 @@ int clif_skillinfoblock(struct map_session_data *sd)
else
WFIFOB(fd,len+36) = 0;
len += 37;
- c++;
}
}
WFIFOW(fd,2)=len;
@@ -4229,6 +4234,27 @@ int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype)
}
/*==========================================
+ * skill cooldown display icon
+ * R 043d <skill ID>.w <tick>.l
+ *------------------------------------------*/
+int clif_skill_cooldown(struct map_session_data *sd, int skillid, unsigned int tick)
+{
+#if PACKETVER>=20081112
+ int fd;
+
+ nullpo_retr(0, sd);
+
+ fd=sd->fd;
+ WFIFOHEAD(fd,packet_len(0x043d));
+ WFIFOW(fd,0) = 0x043d;
+ WFIFOW(fd,2) = skillid;
+ WFIFOL(fd,4) = tick;
+ WFIFOSET(fd,packet_len(0x043d));
+#endif
+ return 0;
+}
+
+/*==========================================
* skill attack effect and damage
* R 01de <skill ID>.w <src ID>.l <dst ID>.l <tick>.l <src delay>.l <dst delay>.l <damage>.l <skillv>.w <div>.w <type>.B
*------------------------------------------*/
@@ -5681,6 +5707,11 @@ void clif_party_inviteack(struct map_session_data* sd, const char* nick, int fla
int clif_party_option(struct party_data *p,struct map_session_data *sd,int flag)
{
unsigned char buf[16];
+#if PACKETVER<20090603
+ const int cmd = 0x101;
+#else
+ const int cmd = 0x7d8;
+#endif
nullpo_retr(0, p);
@@ -5691,14 +5722,18 @@ int clif_party_option(struct party_data *p,struct map_session_data *sd,int flag)
sd = p->data[i].sd;
}
if(!sd) return 0;
- WBUFW(buf,0)=0x101;
+ WBUFW(buf,0)=cmd;
// WBUFL(buf,2) // that's how the client reads it, still need to check it's uses [FlavioJS]
WBUFW(buf,2)=((flag&0x01)?2:p->party.exp);
WBUFW(buf,4)=0;
+#if PACKETVER>=20090603
+ WBUFB(buf,6)=(p->party.item&1)?1:0;
+ WBUFB(buf,7)=(p->party.item&2)?1:0;
+#endif
if(flag==0)
- clif_send(buf,packet_len(0x101),&sd->bl,PARTY);
+ clif_send(buf,packet_len(cmd),&sd->bl,PARTY);
else
- clif_send(buf,packet_len(0x101),&sd->bl,SELF);
+ clif_send(buf,packet_len(cmd),&sd->bl,SELF);
return 0;
}
/*==========================================
@@ -8328,15 +8363,20 @@ void clif_hotkeys_send(struct map_session_data *sd) {
#ifdef HOTKEY_SAVING
const int fd = sd->fd;
int i;
+#if PACKETVER<20090603
+ const int cmd = 0x02b9;
+#else
+ const int cmd = 0x07d9;
+#endif
if (!fd) return;
WFIFOHEAD(fd, 2+MAX_HOTKEYS*7);
- WFIFOW(fd, 0) = 0x02b9;
+ WFIFOW(fd, 0) = cmd;
for(i = 0; i < MAX_HOTKEYS; i++) {
WFIFOB(fd, 2 + 0 + i * 7) = sd->status.hotkeys[i].type; // type: 0: item, 1: skill
WFIFOL(fd, 2 + 1 + i * 7) = sd->status.hotkeys[i].id; // item or skill ID
WFIFOW(fd, 2 + 5 + i * 7) = sd->status.hotkeys[i].lv; // skill level
}
- WFIFOSET(fd, packet_len(0x02b9));
+ WFIFOSET(fd, packet_len(cmd));
#endif
}
@@ -10345,6 +10385,15 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd)
party_send_message(sd, text, textlen);
}
+/*
+ * Changes Party Leader
+ * S 07da <account ID>.L
+ *------------------------------------------*/
+void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd)
+{
+ party_changeleader(sd, map_id2sd(RFIFOL(fd,2)));
+}
+
/*==========================================
* 露店閉鎖
*------------------------------------------*/
@@ -12800,6 +12849,22 @@ void clif_quest_update_status(struct map_session_data * sd, int quest_id, bool a
WFIFOSET(fd, packet_len(0x02B7));
}
+void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, short state, short color)
+{
+#if PACKETVER >= 20090218
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd, packet_len(0x446));
+ WFIFOW(fd, 0) = 0x446;
+ WFIFOL(fd, 2) = bl->id;
+ WFIFOW(fd, 6) = bl->x;
+ WFIFOW(fd, 8) = bl->y;
+ WFIFOW(fd, 10) = state;
+ WFIFOW(fd, 12) = color;
+ WFIFOSET(fd, packet_len(0x446));
+#endif
+}
+
/*==========================================
* Mercenary System
*==========================================*/
@@ -13513,13 +13578,19 @@ static int packetdb_readdb(void)
//#0x0040
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,108, 3, 2,
+#if PACKETVER <= 20081217
+ 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,110, 3, 2,
+#else
+ 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,114, 3, 2,
+#endif
#if PACKETVER < 2
3, 28, 19, 11, 3, -1, 9, 5, 52, 51, 56, 58, 41, 2, 6, 6,
#elif PACKETVER < 20071106 // 78-7b 亀島以降 lv99エフェクト用
3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6,
-#else // change in 0x78 and 0x7c
+#elif PACKETVER <= 20081217 // change in 0x78 and 0x7c
3, 28, 19, 11, 3, -1, 9, 5, 55, 53, 58, 60, 42, 2, 6, 6,
+#else
+ 3, 28, 19, 11, 3, -1, 9, 5, 55, 53, 58, 60, 44, 2, 6, 6,
#endif
//#0x0080
7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 2, -1, -1, -1, 0, // 0x8b changed to 2 (was 23)
@@ -13577,7 +13648,7 @@ static int packetdb_readdb(void)
0, 0, 0, 6, 0, 0, 0, 0, 0, 8, 18, 0, 0, 0, 0, 0,
0, 4, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,107, 6, 0, 7, 7, 22,191, 0, 0, 0, 0, 0, 0,
+ 85, -1, -1,107, 6, -1, 7, 7, 22,191, 0, 0, 0, 0, 0, 0,
//#0x02C0
0, 0, 0, 0, 0, 30, 0, 0, 0, 3, 0, 65, 4, 71, 10, 0,
0, 0, 0, 0, 29, 0, 6, -1, 10, 10, 3, 0, -1, 32, 6, 0,
@@ -13607,9 +13678,9 @@ static int packetdb_readdb(void)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 25,
//#0x0440
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -13623,6 +13694,70 @@ static int packetdb_readdb(void)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ //#0x0500
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
+ //#0x0540
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ //#0x0580
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ //#0x05C0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ //#0x0600
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
+ //#0x0640
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ //#0x0680
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ //#0x06C0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ //#0x0700
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
+ //#0x0740
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ //#0x0780
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ //#0x07C0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#if PACKETVER < 20090617
+ 6, 2, -1, 4, 4, 4, 4, 8, 8,254, 6, 8, 6, 54, 30, 54,
+#else // 0x7d9 changed
+ 6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54,
+#endif
+ 0, 0, 0, 0, 0, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
struct {
void (*func)(int, struct map_session_data *);
@@ -13708,6 +13843,7 @@ static int packetdb_readdb(void)
{clif_parse_RemovePartyMember,"removepartymember"},
{clif_parse_PartyChangeOption,"partychangeoption"},
{clif_parse_PartyMessage,"partymessage"},
+ {clif_parse_PartyChangeLeader,"partychangeleader"},
{clif_parse_CloseVending,"closevending"},
{clif_parse_VendingListReq,"vendinglistreq"},
{clif_parse_PurchaseReq,"purchasereq"},
diff --git a/src/map/clif.h b/src/map/clif.h
index 43fd8b1f7..fd9bea645 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -26,36 +26,8 @@ struct guild;
struct battleground_data;
struct quest;
#include <stdarg.h>
-
-// server->client protocol version
-// 0 - pre-?
-// 1 - ? - 0x196
-// 2 - ? - 0x78, 0x79
-// 3 - ? - 0x1c8, 0x1c9, 0x1de
-// 4 - ? - 0x1d7, 0x1d8, 0x1d9, 0x1da
-// 5 - 2003-12-18aSakexe+ - 0x1ee, 0x1ef, 0x1f0, ?0x1c4, 0x1c5?
-// 6 - 2004-03-02aSakexe+ - 0x1f4, 0x1f5
-// 7 - 2005-04-11aSakexe+ - 0x229, 0x22a, 0x22b, 0x22c
-// 20070521 - 2007-05-21aSakexe+ - 0x283
-// 20070821 - 2007-08-21aSakexe+ - 0x2c5
-// 20070918 - 2007-09-18aSakexe+ - 0x2d7, 0x2d9, 0x2da
-// 20071106 - 2007-11-06aSakexe+ - 0x78, 0x7c, 0x22c
-// 20081126 - 2008-11-26aSakexe+ - 0x1a2
-#ifndef PACKETVER
- #define PACKETVER 20081126
-#endif
-// backward compatible PACKETVER 8 and 9
-#if PACKETVER == 8
-#undef PACKETVER
-#define PACKETVER 20070521
-#endif
-#if PACKETVER == 9
-#undef PACKETVER
-#define PACKETVER 20071106
-#endif
-
// packet DB
-#define MAX_PACKET_DB 0x500
+#define MAX_PACKET_DB 0x800
#define MAX_PACKET_VER 25
struct s_packet_db {
@@ -224,6 +196,7 @@ int clif_skillup(struct map_session_data *sd,int skill_num);
int clif_skillcasting(struct block_list* bl,int src_id,int dst_id,int dst_x,int dst_y,int skill_num,int pl,int casttime);
int clif_skillcastcancel(struct block_list* bl);
int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype);
+int clif_skill_cooldown(struct map_session_data *sd, int skillid, unsigned int tick);
int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,int skill_id,int skill_lv,int type);
//int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,int skill_id,int skill_lv,int type);
int clif_skill_nodamage(struct block_list *src,struct block_list *dst,int skill_id,int heal,int fail);
@@ -437,6 +410,7 @@ void clif_quest_add(struct map_session_data * sd, struct quest * qd, int index);
void clif_quest_delete(struct map_session_data * sd, int quest_id);
void clif_quest_update_status(struct map_session_data * sd, int quest_id, bool active);
void clif_quest_update_objective(struct map_session_data * sd, struct quest * qd, int index);
+void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, short state, short color);
int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type);
int do_final_clif(void);
diff --git a/src/map/npc.c b/src/map/npc.c
index 0a412de41..2a92a0e1b 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2395,7 +2395,6 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
int npc_duplicate4instance(struct npc_data *snd, int m)
{
char newname[NAME_LENGTH];
- int i = 0;
if( map[m].instance_id == 0 )
return 1;
diff --git a/src/map/party.c b/src/map/party.c
index 4a10036d3..be54455d7 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -606,6 +606,57 @@ int party_optionchanged(int party_id,int account_id,int exp,int item,int flag)
return 0;
}
+bool party_changeleader(struct map_session_data *sd, struct map_session_data *tsd)
+{
+ struct party_data *p;
+ int mi, tmi;
+
+ if (!sd || !sd->status.party_id)
+ return false;
+
+ if (!tsd || tsd->status.party_id != sd->status.party_id) {
+ clif_displaymessage(sd->fd, msg_txt(283));
+ return false;
+ }
+
+ if( map[sd->bl.m].flag.partylock )
+ {
+ clif_displaymessage(sd->fd, "You cannot change party leaders on this map.");
+ return false;
+ }
+
+ if ((p = party_search(sd->status.party_id)) == NULL)
+ return false;
+
+ ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd );
+ if (mi == MAX_PARTY)
+ return false; //Shouldn't happen
+
+ if (!p->party.member[mi].leader)
+ { //Need to be a party leader.
+ clif_displaymessage(sd->fd, msg_txt(282));
+ return false;
+ }
+
+ ARR_FIND( 0, MAX_PARTY, tmi, p->data[tmi].sd == tsd);
+ if (tmi == MAX_PARTY)
+ return false; //Shouldn't happen
+
+ //Change leadership.
+ p->party.member[mi].leader = 0;
+ if (p->data[mi].sd->fd)
+ clif_displaymessage(p->data[mi].sd->fd, msg_txt(284));
+
+ p->party.member[tmi].leader = 1;
+ if (p->data[tmi].sd->fd)
+ clif_displaymessage(p->data[tmi].sd->fd, msg_txt(285));
+
+ //Update info.
+ intif_party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id);
+ clif_party_info(p,NULL);
+ return true;
+}
+
/// Invoked (from char-server) when a party member
/// - changes maps
/// - logs in or out
diff --git a/src/map/party.h b/src/map/party.h
index bdaccc7e1..55142fa7e 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -54,6 +54,7 @@ int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short m
int party_broken(int party_id);
int party_optionchanged(int party_id,int account_id,int exp,int item,int flag);
int party_changeoption(struct map_session_data *sd,int exp,int item);
+bool party_changeleader(struct map_session_data *sd, struct map_session_data *t_sd);
void party_send_movemap(struct map_session_data *sd);
void party_send_levelup(struct map_session_data *sd);
int party_send_logout(struct map_session_data *sd);
diff --git a/src/map/script.c b/src/map/script.c
index 8883f3783..57b11f305 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -6086,6 +6086,9 @@ BUILDIN_FUNC(strcharinfo)
else
script_pushconststr(st,"");
break;
+ case 3:
+ script_pushconststr(st,map[sd->bl.m].name);
+ break;
default:
ShowWarning("buildin_strcharinfo: unknown parameter.\n");
script_pushconststr(st,"");
@@ -6231,7 +6234,7 @@ BUILDIN_FUNC(getbrokenid)
num=script_getnum(st,2);
for(i=0; i<MAX_INVENTORY; i++) {
- if(sd->status.inventory[i].attribute==1){
+ if(sd->status.inventory[i].attribute){
brokencounter++;
if(num==brokencounter){
id=sd->status.inventory[i].nameid;
@@ -6260,7 +6263,7 @@ BUILDIN_FUNC(repair)
num=script_getnum(st,2);
for(i=0; i<MAX_INVENTORY; i++) {
- if(sd->status.inventory[i].attribute==1){
+ if(sd->status.inventory[i].attribute){
repaircounter++;
if(num==repaircounter){
sd->status.inventory[i].attribute=0;
@@ -12608,6 +12611,75 @@ BUILDIN_FUNC(checkchatting) // check chatting [Marka]
return 0;
}
+BUILDIN_FUNC(searchitem)
+{
+ struct script_data* data = script_getdata(st, 2);
+ const char *itemname = script_getstr(st,3);
+ struct item_data *items[MAX_SEARCH];
+ int count;
+
+ char* name;
+ int32 start;
+ int32 id;
+ int32 i;
+ TBL_PC* sd = NULL;
+
+ if ((items[0] = itemdb_exists(atoi(itemname))))
+ count = 1;
+ else {
+ count = itemdb_searchname_array(items, ARRAYLENGTH(items), itemname);
+ if (count > MAX_SEARCH) count = MAX_SEARCH;
+ }
+
+ if (!count) {
+ script_pushint(st, 0);
+ return 0;
+ }
+
+ if( !data_isreference(data) )
+ {
+ ShowError("script:searchitem: not a variable\n");
+ script_reportdata(data);
+ st->state = END;
+ return 1;// not a variable
+ }
+
+ id = reference_getid(data);
+ start = reference_getindex(data);
+ name = reference_getname(data);
+ if( not_array_variable(*name) )
+ {
+ ShowError("script:searchitem: illegal scope\n");
+ script_reportdata(data);
+ st->state = END;
+ return 1;// not supported
+ }
+
+ if( not_server_variable(*name) )
+ {
+ sd = script_rid2sd(st);
+ if( sd == NULL )
+ return 0;// no player attached
+ }
+
+ if( is_string_variable(name) )
+ {// string array
+ ShowError("script:searchitem: not an integer array reference\n");
+ script_reportdata(data);
+ st->state = END;
+ return 1;// not supported
+ }
+
+ for( i = 0; i < count; ++start, ++i )
+ {// Set array
+ void* v = (void*)items[i]->nameid;
+ set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data));
+ }
+
+ script_pushint(st, count);
+ return 0;
+}
+
int axtoi(const char *hexStg)
{
int n = 0; // position in string
@@ -13057,8 +13129,10 @@ BUILDIN_FUNC(awake)
struct linkdb_node *node = (struct linkdb_node *)sleep_db;
nd = npc_name2id(script_getstr(st, 2));
- if( nd == NULL )
- return 0;
+ if( nd == NULL ) {
+ ShowError("awake: NPC \"%s\" not found\n", script_getstr(st, 2));
+ return 1;
+ }
while( node )
{
@@ -13081,7 +13155,8 @@ BUILDIN_FUNC(awake)
delete_timer(tst->sleep.timer, run_script_timer);
node = script_erase_sleepdb(node);
tst->sleep.timer = INVALID_TIMER;
- //tst->sleep.tick = 0;
+ if(tst->state != RERUNLINE)
+ tst->sleep.tick = 0;
run_script_main(tst);
}
else
@@ -13490,6 +13565,24 @@ BUILDIN_FUNC(checkquest)
return 0;
}
+BUILDIN_FUNC(showevent)
+{
+ TBL_PC *sd = script_rid2sd(st);
+ struct npc_data *nd = map_id2nd(st->oid);
+ int state, color;
+
+ if( sd == NULL || nd == NULL )
+ return 0;
+ state = script_getnum(st, 2);
+ color = script_getnum(st, 3);
+
+ if( color < 0 || color > 4 )
+ color = 0; // set default color
+
+ clif_quest_show_event(sd, &nd->bl, state, color);
+ return 0;
+}
+
/*==========================================
* BattleGround System
*------------------------------------------*/
@@ -14498,6 +14591,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(setcell,"siiiiii"),
BUILDIN_DEF(setwall,"siiiiis"),
BUILDIN_DEF(delwall,"s"),
+ BUILDIN_DEF(searchitem,"rs"),
BUILDIN_DEF(mercenary_create,"ii"),
BUILDIN_DEF(mercenary_heal,"ii"),
BUILDIN_DEF(mercenary_sc_start,"iii"),
@@ -14547,5 +14641,6 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(completequest, "i"),
BUILDIN_DEF(checkquest, "i*"),
BUILDIN_DEF(changequest, "ii"),
+ BUILDIN_DEF(showevent, "ii"),
{NULL,NULL,NULL},
};
diff --git a/src/map/skill.c b/src/map/skill.c
index c16eecdda..8d0b1cda9 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -11195,6 +11195,9 @@ int skill_blockpc_start(struct map_session_data *sd, int skillid, int tick)
return -1;
}
+ if( battle_config.display_status_timers )
+ clif_skill_cooldown(sd, skillid, tick);
+
sd->blockskill[skillid] = 0x1|(0xFE&add_timer(gettick()+tick,skill_blockpc_end,sd->bl.id,skillid));
return 0;
}