summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt9
-rw-r--r--conf-tmpl/script_athena.conf1
-rw-r--r--db/const.txt1
-rw-r--r--src/char/int_pet.c192
-rw-r--r--src/map/chrif.c6
-rw-r--r--src/map/clif.c16
-rw-r--r--src/map/map.h1
-rw-r--r--src/map/npc.c4
-rw-r--r--src/map/script.c8
-rw-r--r--src/map/skill.c4
-rw-r--r--src/map/status.c9
-rw-r--r--src/map/storage.c35
-rw-r--r--src/map/storage.h2
13 files changed, 168 insertions, 120 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index ea413e0a0..7dd377acb 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -4,6 +4,15 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2006/05/27
+ * Added mapflag "loadevent", now load-map script events will ONLY trigger
+ on maps with this mapflag on, rather than every map. [Skotlex]
+ * High Jump can now be used in all versus maps. [Skotlex]
+ * Added Kaite's opt3 value, taken from jA [Skotlex]
+ * Added state dirty == 2 to storages. Signals when a storage was sent for
+ final saving. Said storage is removed from memory after the ack from the
+ char-server, and they are sent to save if the map/char servers reconnect
+ before the ack arrives. In short: they are guaranteed to be saved after a
+ char logs out. [Skotlex]
* Put pay_arche.gat in the "no experience lost" mapflag file. [MasterOfMuppets]
2006/06/26
* Corrected the element of hunter traps. [Skotlex]
diff --git a/conf-tmpl/script_athena.conf b/conf-tmpl/script_athena.conf
index bb06371ee..e4bb846e5 100644
--- a/conf-tmpl/script_athena.conf
+++ b/conf-tmpl/script_athena.conf
@@ -62,6 +62,7 @@ logout_event_name: PCLogoutEvent
login_event_name: PCLoginEvent
// Name of event when a player changes map
+// NOTE: This event will only trigger on maps with the "loadmap" flag active.
loadmap_event_name: PCLoadMapEvent
// Name of event when a player levels up (base lv)
diff --git a/db/const.txt b/db/const.txt
index 9987e4836..7d5458156 100644
--- a/db/const.txt
+++ b/db/const.txt
@@ -131,6 +131,7 @@ mf_nodrop 38
mf_jexp 39
mf_bexp 40
mf_novending 41
+mf_loadevent 42
cell_wall 1
cell_water 3
diff --git a/src/char/int_pet.c b/src/char/int_pet.c
index d787b9821..67f3fb697 100644
--- a/src/char/int_pet.c
+++ b/src/char/int_pet.c
@@ -217,8 +217,8 @@ int mapif_delete_pet_ack(int fd,int flag)
WFIFOB(fd,2)=flag;
WFIFOSET(fd,3);
- return 0;
- }
+ return 0;
+}
int mapif_rename_pet_ack(int fd, int account_id, int char_id, int flag, char *name){
WFIFOW(fd, 0) =0x3884;
@@ -231,112 +231,112 @@ int mapif_rename_pet_ack(int fd, int account_id, int char_id, int flag, char *na
return 0;
}
- int mapif_create_pet(int fd,int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id,
- short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name)
- {
- struct s_pet *p;
- p= (struct s_pet *) aCalloc(sizeof(struct s_pet), 1);
- if(p==NULL){
- ShowFatalError("int_pet: out of memory !\n");
- mapif_pet_created(fd,account_id,NULL);
- return 0;
- }
- // memset(p,0,sizeof(struct s_pet)); unnecessary after aCalloc [Skotlex]
- p->pet_id = pet_newid++;
- memcpy(p->name,pet_name,NAME_LENGTH-1);
- if(incuvate == 1)
- p->account_id = p->char_id = 0;
- else {
- p->account_id = account_id;
- p->char_id = char_id;
- }
- p->class_ = pet_class;
- p->level = pet_lv;
- p->egg_id = pet_egg_id;
- p->equip = pet_equip;
- p->intimate = intimate;
- p->hungry = hungry;
- p->rename_flag = rename_flag;
- p->incuvate = incuvate;
-
- if(p->hungry < 0)
- p->hungry = 0;
- else if(p->hungry > 100)
- p->hungry = 100;
- if(p->intimate < 0)
- p->intimate = 0;
- else if(p->intimate > 1000)
- p->intimate = 1000;
-
- idb_put(pet_db,p->pet_id,p);
-
- mapif_pet_created(fd,account_id,p);
-
+int mapif_create_pet(int fd,int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id,
+ short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name)
+{
+ struct s_pet *p;
+ p= (struct s_pet *) aCalloc(sizeof(struct s_pet), 1);
+ if(p==NULL){
+ ShowFatalError("int_pet: out of memory !\n");
+ mapif_pet_created(fd,account_id,NULL);
return 0;
}
+// memset(p,0,sizeof(struct s_pet)); unnecessary after aCalloc [Skotlex]
+ p->pet_id = pet_newid++;
+ memcpy(p->name,pet_name,NAME_LENGTH-1);
+ if(incuvate == 1)
+ p->account_id = p->char_id = 0;
+ else {
+ p->account_id = account_id;
+ p->char_id = char_id;
+ }
+ p->class_ = pet_class;
+ p->level = pet_lv;
+ p->egg_id = pet_egg_id;
+ p->equip = pet_equip;
+ p->intimate = intimate;
+ p->hungry = hungry;
+ p->rename_flag = rename_flag;
+ p->incuvate = incuvate;
+
+ if(p->hungry < 0)
+ p->hungry = 0;
+ else if(p->hungry > 100)
+ p->hungry = 100;
+ if(p->intimate < 0)
+ p->intimate = 0;
+ else if(p->intimate > 1000)
+ p->intimate = 1000;
+
+ idb_put(pet_db,p->pet_id,p);
+
+ mapif_pet_created(fd,account_id,p);
- int mapif_load_pet(int fd,int account_id,int char_id,int pet_id)
- {
- struct s_pet *p;
- p= idb_get(pet_db,pet_id);
- if(p!=NULL) {
- if(p->incuvate == 1) {
- p->account_id = p->char_id = 0;
- mapif_pet_info(fd,account_id,p);
- }
- else if(account_id == p->account_id && char_id == p->char_id)
- mapif_pet_info(fd,account_id,p);
- else
- mapif_pet_noinfo(fd,account_id);
+ return 0;
+}
+
+int mapif_load_pet(int fd,int account_id,int char_id,int pet_id)
+{
+ struct s_pet *p;
+ p= idb_get(pet_db,pet_id);
+ if(p!=NULL) {
+ if(p->incuvate == 1) {
+ p->account_id = p->char_id = 0;
+ mapif_pet_info(fd,account_id,p);
}
+ else if(account_id == p->account_id && char_id == p->char_id)
+ mapif_pet_info(fd,account_id,p);
else
mapif_pet_noinfo(fd,account_id);
-
- return 0;
}
+ else
+ mapif_pet_noinfo(fd,account_id);
+
+ return 0;
+}
- static void* create_pet(DBKey key, va_list args) {
- struct s_pet *p;
- p=(struct s_pet *)aCalloc(sizeof(struct s_pet),1);
- p->pet_id = key.i;
- return p;
+static void* create_pet(DBKey key, va_list args) {
+ struct s_pet *p;
+ p=(struct s_pet *)aCalloc(sizeof(struct s_pet),1);
+ p->pet_id = key.i;
+ return p;
+}
+int mapif_save_pet(int fd,int account_id,struct s_pet *data)
+{
+ struct s_pet *p;
+ int pet_id, len;
+ RFIFOHEAD(fd);
+ len=RFIFOW(fd,2);
+
+ if(sizeof(struct s_pet)!=len-8) {
+ ShowError("inter pet: data size error %d %d\n",sizeof(struct s_pet),len-8);
}
- int mapif_save_pet(int fd,int account_id,struct s_pet *data)
- {
- struct s_pet *p;
- int pet_id, len;
- RFIFOHEAD(fd);
- len=RFIFOW(fd,2);
-
- if(sizeof(struct s_pet)!=len-8) {
- ShowError("inter pet: data size error %d %d\n",sizeof(struct s_pet),len-8);
- }
- else{
- pet_id = data->pet_id;
- if (pet_id == 0)
- pet_id = data->pet_id = pet_newid++;
- p= idb_ensure(pet_db,pet_id,create_pet);
- if(data->hungry < 0)
- data->hungry = 0;
- else if(data->hungry > 100)
- data->hungry = 100;
- if(data->intimate < 0)
- data->intimate = 0;
- else if(data->intimate > 1000)
- data->intimate = 1000;
- memcpy(p,data,sizeof(struct s_pet));
- if(p->incuvate == 1)
- p->account_id = p->char_id = 0;
-
- mapif_save_pet_ack(fd,account_id,0);
- }
+ else{
+ pet_id = data->pet_id;
+ if (pet_id == 0)
+ pet_id = data->pet_id = pet_newid++;
+ p= idb_ensure(pet_db,pet_id,create_pet);
+ if(data->hungry < 0)
+ data->hungry = 0;
+ else if(data->hungry > 100)
+ data->hungry = 100;
+ if(data->intimate < 0)
+ data->intimate = 0;
+ else if(data->intimate > 1000)
+ data->intimate = 1000;
+ memcpy(p,data,sizeof(struct s_pet));
+ if(p->incuvate == 1)
+ p->account_id = p->char_id = 0;
- return 0;
+ mapif_save_pet_ack(fd,account_id,0);
}
- int mapif_delete_pet(int fd,int pet_id)
- {
- mapif_delete_pet_ack(fd,inter_pet_delete(pet_id));
+ return 0;
+}
+
+int mapif_delete_pet(int fd,int pet_id)
+{
+ mapif_delete_pet_ack(fd,inter_pet_delete(pet_id));
return 0;
}
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 5b7dee2de..be0b2a25f 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -189,7 +189,7 @@ int chrif_save(struct map_session_data *sd, int flag)
return -1; //Refuse to save a char already tagged for final saving. [Skotlex]
//For data sync
if (sd->state.storage_flag == 1)
- storage_storage_save(sd->status.account_id);
+ storage_storage_save(sd->status.account_id, flag);
else if (sd->state.storage_flag == 2)
storage_guild_storagesave(sd->status.account_id, sd->status.guild_id);
@@ -218,10 +218,8 @@ int chrif_save(struct map_session_data *sd, int flag)
#ifndef TXT_ONLY
}
#endif
- if (flag) {//Remove the storage from memory.
- storage_delete(sd->status.account_id);
+ if (flag)
sd->state.finalsave = 1; //Mark the last save as done.
- }
return 0;
}
diff --git a/src/map/clif.c b/src/map/clif.c
index e25b89a8f..1698045e2 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -8207,7 +8207,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
sc_start(&sd->bl,SC_NOCHAT,100,0,0);
// Lance
- if(sd->state.event_loadmap){
+ if(sd->state.event_loadmap && map[sd->bl.m].flag.loadevent){
pc_setregstr(sd, add_str("@maploaded$"), map[sd->bl.m].name);
npc_script_event(sd, NPCE_LOADMAP);
}
@@ -9848,8 +9848,6 @@ void clif_parse_NpcStringInput(int fd,struct map_session_data *sd)
if(message_len >= sizeof(sd->npc_str)){
ShowWarning("clif: input string too long !\n");
message_len = sizeof(sd->npc_str);
- } else {
- message_len += 1; // Null character
}
// Exploit prevention if crafted packets (without null) is being sent. [Lance]
@@ -9972,12 +9970,18 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) {
*/
void clif_parse_LGMmessage(int fd, struct map_session_data *sd) {
unsigned char buf[512];
- int len = RFIFOREST(fd);
+// int len = RFIFOREST(fd);
int plen = RFIFOW(fd,2);
RFIFOHEAD(fd);
- if(plen <= 0 || plen > len) // Possible hack! [Lance]
- plen = len;
+ //This shouldn't be needed.... because the parsing code makes sure
+ //this function is not invoked until enough bytes have been received.
+ //So if the client "hacks" the packet, all that will happen is that
+ //it will not be parsed until enough data is received, on which point
+ //the following packets will be offset, causing them to fail to parse,
+ //which leads to disconnecting them :3 [Skotlex]
+// if(plen <= 0 || plen > len) // Possible hack! [Lance]
+// plen = len;
if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) &&
(pc_isGM(sd) >= get_atcommand_level(AtCommand_LocalBroadcast))) {
diff --git a/src/map/map.h b/src/map/map.h
index 94415fcf5..116ff25fd 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -1045,6 +1045,7 @@ struct map_data {
unsigned nocommand : 1; //Blocks @/# commands for non-gms. [Skotlex]
unsigned nodrop : 1;
unsigned novending : 1;
+ unsigned loadevent : 1;
} flag;
struct point save;
struct npc_data *npc[MAX_NPC_PER_MAP];
diff --git a/src/map/npc.c b/src/map/npc.c
index 26ab060a7..6f3fe5f00 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2514,6 +2514,10 @@ static int npc_parse_mapflag (char *w1, char *w2, char *w3, char *w4)
if( map[m].bexp < 0 ) map[m].bexp = 100;
map[m].flag.nobaseexp = (map[m].bexp==0)?1:0;
}
+ else if (strcmpi(w3,"loadevent")==0) { // Skotlex
+ map[m].flag.loadevent=state;
+ }
+
return 0;
}
diff --git a/src/map/script.c b/src/map/script.c
index 02acd4ee5..692b985b4 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -6869,7 +6869,7 @@ enum { MF_NOMEMO,MF_NOTELEPORT,MF_NOSAVE,MF_NOBRANCH,MF_NOPENALTY,MF_NOZENYPENA
MF_NOWARP,MF_FREE,MF_NOICEWALL,MF_SNOW,MF_FOG,MF_SAKURA,MF_LEAVES,MF_RAIN,
MF_INDOORS,MF_NOGO,MF_CLOUDS,MF_CLOUDS2,MF_FIREWORKS,MF_GVG_CASTLE,MF_GVG_DUNGEON,MF_NIGHTENABLED,
MF_NOBASEEXP, MF_NOJOBEXP, MF_NOMOBLOOT, MF_NOMVPLOOT, MF_NORETURN, MF_NOWARPTO, MF_NIGHTMAREDROP,
- MF_RESTRICTED, MF_NOCOMMAND, MF_NODROP, MF_JEXP, MF_BEXP, MF_NOVENDING };
+ MF_RESTRICTED, MF_NOCOMMAND, MF_NODROP, MF_JEXP, MF_BEXP, MF_NOVENDING, MF_LOADEVENT };
int buildin_setmapflagnosave(struct script_state *st)
{
@@ -7028,6 +7028,9 @@ int buildin_setmapflag(struct script_state *st)
case MF_NOVENDING:
map[m].flag.novending=1;
break;
+ case MF_LOADEVENT:
+ map[m].flag.loadevent=1;
+ break;
}
}
@@ -7167,6 +7170,9 @@ int buildin_removemapflag(struct script_state *st)
case MF_NOVENDING:
map[m].flag.novending=0;
break;
+ case MF_LOADEVENT:
+ map[m].flag.loadevent=0;
+ break;
}
}
diff --git a/src/map/skill.c b/src/map/skill.c
index aa55ea971..a07db8ba0 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -883,8 +883,8 @@ int skillnotok (int skillid, struct map_session_data *sd)
}
return 0;
case TK_HIGHJUMP:
- if(map[sd->bl.m].flag.noteleport && !map_flag_gvg(sd->bl.m))
- { //Can't be used on noteleport maps, except for gvg maps [Skotlex]
+ if(map[sd->bl.m].flag.noteleport && !map_flag_vs(sd->bl.m))
+ { //Can't be used on noteleport maps, except for vs maps [Skotlex]
clif_skill_fail(sd,skillid,0,0);
return 1;
}
diff --git a/src/map/status.c b/src/map/status.c
index 08aeb291a..1654d5dc6 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -5278,7 +5278,10 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
sc->opt3 |= 4096;
opt_flag = 0;
break;
-
+ case SC_KAITE:
+ sc->opt3 |= 8192;
+ opt_flag = 0;
+ break;
//OPTION
case SC_HIDING:
sc->option |= OPTION_HIDE;
@@ -5764,6 +5767,10 @@ int status_change_end( struct block_list* bl , int type,int tid )
sc->opt3 &= ~4096;
opt_flag = 0;
break;
+ case SC_KAITE:
+ sc->opt3 &= ~8192;
+ opt_flag = 0;
+ break;
default:
opt_flag = 0;
}
diff --git a/src/map/storage.c b/src/map/storage.c
index c420795a1..211bdb9ec 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -82,7 +82,7 @@ static int storage_reconnect_sub(DBKey key,void *data,va_list ap)
{ //Account Storage
struct storage* stor = (struct storage*) data;
if (stor->dirty && stor->storage_status == 0) //Save closed storages.
- storage_storage_save(stor->account_id);
+ storage_storage_save(stor->account_id, stor->dirty==2?1:0);
}
return 0;
}
@@ -390,16 +390,27 @@ void storage_storage_dirty(struct map_session_data *sd)
stor->dirty = 1;
}
-int storage_storage_save(int account_id)
+int storage_storage_save(int account_id, int final)
{
struct storage *stor;
stor=account2storage2(account_id);
- if(stor && stor->dirty)
+ if(!stor) return 0;
+
+ if(stor->dirty)
{
+ if (final) {
+ stor->dirty = 2;
+ stor->storage_status = 0; //To prevent further manipulation of it.
+ }
intif_send_storage(stor);
return 1;
}
+ if (final)
+ { //Clear storage from memory. Nothing to save.
+ storage_delete(account_id);
+ return 1;
+ }
return 0;
}
@@ -409,13 +420,19 @@ int storage_storage_saved(int account_id)
{
struct storage *stor;
- if((stor=account2storage2(account_id)) != NULL)
+ if((stor=account2storage2(account_id)) == NULL)
+ return 0;
+
+ if (stor->dirty == 2)
+ { //Final save of storage. Remove from memory.
+ storage_delete(account_id);
+ return 1;
+ }
+
+ if (stor->dirty && stor->storage_status == 0)
{ //Only mark it clean if it's not in use. [Skotlex]
- if (stor->dirty && stor->storage_status == 0)
- {
- stor->dirty = 0;
- sortage_sortitem(stor);
- }
+ stor->dirty = 0;
+ sortage_sortitem(stor);
return 1;
}
return 0;
diff --git a/src/map/storage.h b/src/map/storage.h
index 40e11331b..e33505062 100644
--- a/src/map/storage.h
+++ b/src/map/storage.h
@@ -19,7 +19,7 @@ struct storage *account2storage(int account_id);
struct storage *account2storage2(int account_id);
int storage_delete(int account_id);
int storage_storage_quit(struct map_session_data *sd, int flag);
-int storage_storage_save(int account_id);
+int storage_storage_save(int account_id, int final);
int storage_storage_saved(int account_id); //Ack from char server that guild store was saved.
void storage_storage_dirty(struct map_session_data *sd);