summaryrefslogtreecommitdiff
path: root/src/map/map.c
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-03-22 23:58:16 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-03-22 23:58:16 +0000
commit021b26b8409a84b4c83eb0cc1eedbd65eedfd4e0 (patch)
tree63b8507c38f428421d56c9d816c1d2b2b5c4cd7a /src/map/map.c
parent2e2f6aff261555ae5eaee6b7777d5844b7d20544 (diff)
downloadhercules-021b26b8409a84b4c83eb0cc1eedbd65eedfd4e0.tar.gz
hercules-021b26b8409a84b4c83eb0cc1eedbd65eedfd4e0.tar.bz2
hercules-021b26b8409a84b4c83eb0cc1eedbd65eedfd4e0.tar.xz
hercules-021b26b8409a84b4c83eb0cc1eedbd65eedfd4e0.zip
- Merged the unit_data structure from jA for handling unit-related data (attack times, walking, auto-attack timers, skill related data)
- Modified unit_skillcastcancel to receive flag&2, which stands for "cancel casting only if current skill is cancellable" - Battle config options changed from yes/no to BL_TYPE settings: skillrange_by_distance, skill_noreiteration, skill_nofootset, gvg_traps_target_all, skill_log, attack_direction_change, auto_counter_type - Clif.c will disconnect sessions that send an unknown command packet above 0x30000 instead of just ignoring it. - Cleaned up/rewrite of the pet ai, same for pet_calc_pos - Implemented use of mob variable attacked_players as it is used on jA - Cleaned up error reporting during mob-skill loading to be less spamy with non-loaded mobs. - Corrected water_height reading. I forgot to give credits to LittleWolf for providing the water-reading function :X git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5707 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map/map.c')
-rw-r--r--src/map/map.c312
1 files changed, 92 insertions, 220 deletions
diff --git a/src/map/map.c b/src/map/map.c
index c06f7ef1b..f218572b3 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -36,6 +36,7 @@
#include "skill.h"
#include "trade.h"
#include "party.h"
+#include "unit.h"
#include "battle.h"
#include "script.h"
#include "guild.h"
@@ -1501,191 +1502,70 @@ void map_deliddb(struct block_list *bl) {
* quit?理の主?が違うような?もしてきた
*------------------------------------------
*/
-int map_quit(struct map_session_data *sd) {
-
- //nullpo_retr(0, sd); //Utterly innecessary, all invokations to this function already have an SD non-null check.
- //Learn to use proper coding and stop relying on nullpo_'s for safety :P [Skotlex]
-
-
- if(!sd->state.waitingdisconnect) {
- if (sd->npc_timer_id != -1) //Cancel the event timer.
- npc_timerevent_quit(sd);
- if (sd->state.event_disconnect) {
- if (script_config.event_script_type == 0) {
- struct npc_data *npc;
- if ((npc = npc_name2id(script_config.logout_event_name))) {
- run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLogoutNPC
- ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.logout_event_name);
- }
- } else {
- ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
- npc_event_doall_id(script_config.logout_event_name, sd->bl.id), script_config.logout_event_name);
- }
- }
-
- if(sd->chatID) // チャットから出る
- chat_leavechat(sd);
-
- if(sd->trade_partner) // 取引を中?する
- trade_tradecancel(sd);
-
- if(sd->party_invite>0) // パ?ティ?誘を拒否する
- party_reply_invite(sd,sd->party_invite_account,0);
-
- if(sd->guild_invite>0) // ギルド?誘を拒否する
- guild_reply_invite(sd,sd->guild_invite,0);
- if(sd->guild_alliance>0) // ギルド同盟?誘を拒否する
- guild_reply_reqalliance(sd,sd->guild_alliance_account,0);
-
- // Force exiting from duel and rejecting
- // all duel invitations when player quit [LuzZza]
- if(sd->duel_group > 0)
- duel_leave(sd->duel_group, sd);
-
- if(sd->duel_invite > 0)
- duel_reject(sd->duel_invite, sd);
-
- party_send_logout(sd); // パ?ティのログアウトメッセ?ジ送信
-
- party_send_dot_remove(sd);//minimap dot fix [Kevin]
-
- guild_send_memberinfoshort(sd,0); // ギルドのログアウトメッセ?ジ送信
-
- guild_send_dot_remove(sd);
-
- pc_cleareventtimer(sd); // イベントタイマを破棄する
-
- // check if we've been authenticated [celest]
- if (sd->state.auth)
- skill_castcancel(&sd->bl,0); // 詠唱を中?する
-
- skill_stop_dancing(&sd->bl);// ダンス/演奏中?
-
- //Status that are not saved...
- if(sd->sc.count) {
- if(sd->sc.data[SC_HIDING].timer!=-1)
- status_change_end(&sd->bl,SC_HIDING,-1);
- if(sd->sc.data[SC_CLOAKING].timer!=-1)
- status_change_end(&sd->bl,SC_CLOAKING,-1);
- if(sd->sc.data[SC_RUN].timer!=-1)
- status_change_end(&sd->bl,SC_RUN,-1);
- if(sd->sc.data[SC_SPURT].timer!=-1)
- status_change_end(&sd->bl,SC_SPURT,-1);
- if(sd->sc.data[SC_BERSERK].timer!=-1)
- status_change_end(&sd->bl,SC_BERSERK,-1);
- if(sd->sc.data[SC_TRICKDEAD].timer!=-1)
- status_change_end(&sd->bl,SC_TRICKDEAD,-1);
- if (battle_config.debuff_on_logout) {
- if(sd->sc.data[SC_STRIPWEAPON].timer!=-1)
- status_change_end(&sd->bl,SC_STRIPWEAPON,-1);
- if(sd->sc.data[SC_STRIPARMOR].timer!=-1)
- status_change_end(&sd->bl,SC_STRIPARMOR,-1);
- if(sd->sc.data[SC_STRIPSHIELD].timer!=-1)
- status_change_end(&sd->bl,SC_STRIPSHIELD,-1);
- if(sd->sc.data[SC_STRIPHELM].timer!=-1)
- status_change_end(&sd->bl,SC_STRIPHELM,-1);
- if(sd->sc.data[SC_EXTREMITYFIST].timer!=-1)
- status_change_end(&sd->bl,SC_EXTREMITYFIST,-1);
- if(sd->sc.data[SC_EXPLOSIONSPIRITS].timer!=-1)
- status_change_end(&sd->bl,SC_EXPLOSIONSPIRITS,-1);
- }
- }
- skill_clear_unitgroup(&sd->bl); // スキルユニットグル?プの削除
-
- // check if we've been authenticated [celest]
- if (sd->state.auth) {
- skill_cleartimerskill(&sd->bl);
- pc_stop_walking(sd,0);
- pc_stopattack(sd);
- pc_stop_following(sd);
- pc_delinvincibletimer(sd);
- }
- pc_delspiritball(sd,sd->spiritball,1);
- skill_gangsterparadise(sd,0);
- skill_unit_move(&sd->bl,gettick(),4);
-
- if (sd->state.auth)
- status_calc_pc(sd,4);
- // skill_clear_unitgroup(&sd->bl); // [Sara-chan]
-
- if (!(sd->sc.option & OPTION_INVISIBLE))
- clif_clearchar_area(&sd->bl,2);
-
- chrif_save_scdata(sd); //Save status changes, then clear'em out from memory. [Skotlex]
- status_change_clear(&sd->bl,1);
-
- if(sd->status.pet_id && sd->pd) {
- pet_lootitem_drop(sd->pd,sd);
- pet_remove_map(sd);
- if(sd->pet.intimate <= 0) {
- intif_delete_petdata(sd->status.pet_id);
- sd->status.pet_id = 0;
- sd->pd = NULL;
- sd->petDB = NULL;
- }
- else
- intif_save_petdata(sd->status.account_id,&sd->pet);
- }
-
- if(pc_isdead(sd))
- pc_setrestartvalue(sd,2);
-
- pc_clean_skilltree(sd);
-
- //The storage closing routines will save the char if needed. [Skotlex]
- if (!sd->state.storage_flag)
- chrif_save(sd,1);
- else if (sd->state.storage_flag == 1)
- storage_storage_quit(sd,1);
- else if (sd->state.storage_flag == 2)
- storage_guild_storage_quit(sd,1);
-
- map_delblock(&sd->bl);
- } else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex]
- if (sd->bl.prev != NULL)
- { //Remove from map...
- if (!(sd->sc.option & OPTION_INVISIBLE))
- clif_clearchar_area(&sd->bl,2);
- map_delblock(&sd->bl);
- }
- if (sd->pd)
- pet_remove_map(sd);
- }
-
- if (sd->stack) {
- script_free_stack(sd->stack);
- sd->stack= NULL;
- }
-
-// chrif_char_offline(sd); //chrif_save handles this now.
-
- //Do we really need to remove the name?
- idb_remove(charid_db,sd->status.char_id);
- idb_remove(id_db,sd->bl.id);
- idb_remove(pc_db,sd->bl.id);
-
- // Notify friends that this char logged out. [Skotlex]
- clif_foreachclient(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0);
-
- if(sd->reg)
- { //Double logout already freed pointer fix... [Skotlex]
- aFree(sd->reg);
- sd->reg = NULL;
- sd->reg_num = 0;
- }
-
- if(sd->regstr)
- {
- aFree(sd->regstr);
- sd->regstr = NULL;
- sd->regstr_num = 0;
- }
-
- if(!sd->fd) //There is no session connected, and as such socket.c won't free the data, we must do it. [Skotlex]
- aFree(sd);
- return 0;
-}
-
+int map_quit(struct map_session_data *sd) {
+
+ //nullpo_retr(0, sd); //Utterly innecessary, all invokations to this function already have an SD non-null check.
+ //Learn to use proper coding and stop relying on nullpo_'s for safety :P [Skotlex]
+
+ if(!sd->state.waitingdisconnect) {
+ if (sd->npc_timer_id != -1) //Cancel the event timer.
+ npc_timerevent_quit(sd);
+ if (sd->state.event_disconnect) {
+ if (script_config.event_script_type == 0) {
+ struct npc_data *npc;
+ if ((npc = npc_name2id(script_config.logout_event_name))) {
+ run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLogoutNPC
+ ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.logout_event_name);
+ }
+ } else {
+ ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
+ npc_event_doall_id(script_config.logout_event_name, sd->bl.id), script_config.logout_event_name);
+ }
+ }
+ if (sd->pd) unit_free(&sd->pd->bl);
+ unit_free(&sd->bl);
+ pc_clean_skilltree(sd);
+ status_calc_pc(sd,4);
+ if(sd->pet.intimate > 0)
+ intif_save_petdata(sd->status.account_id,&sd->pet);
+ chrif_save(sd,1);
+ } else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex]
+ if (sd->bl.prev != NULL)
+ { //Remove from map...
+ unit_remove_map(&sd->bl, 0);
+ if (sd->pd && sd->pd->bl.prev != NULL)
+ unit_remove_map(&sd->pd->bl, 0);
+ }
+ }
+ if (sd->stack) {
+ script_free_stack(sd->stack);
+ sd->stack= NULL;
+ }
+
+ //Do we really need to remove the name?
+ idb_remove(charid_db,sd->status.char_id);
+ idb_remove(id_db,sd->bl.id);
+ idb_remove(pc_db,sd->bl.id);
+
+ if(sd->reg)
+ { //Double logout already freed pointer fix... [Skotlex]
+ aFree(sd->reg);
+ sd->reg = NULL;
+ sd->reg_num = 0;
+ }
+ if(sd->regstr)
+ {
+ aFree(sd->regstr);
+ sd->regstr = NULL;
+ sd->regstr_num = 0;
+ }
+
+ if(!sd->fd) //There is no session connected, and as such socket.c won't free the data, we must do it. [Skotlex]
+ aFree(sd);
+ return 0;
+}
+
+
/*==========================================
* id番?のPCを探す。居なければNULL
*------------------------------------------
@@ -1894,16 +1774,16 @@ void map_removenpc(void) {
// allocates a struct when it there is place free in the cache,
// and returns NULL otherwise
// -- i'll just leave the old code in case it's needed ^^;
-struct mob_list* map_addmobtolist(unsigned short m)
+int map_addmobtolist(unsigned short m, struct spawn_data *spawn)
{
size_t i;
for (i = 0; i < MAX_MOB_LIST_PER_MAP; i++) {
if (map[m].moblist[i] == NULL) {
- map[m].moblist[i] = (struct mob_list *) aMalloc (sizeof(struct mob_list));
- return map[m].moblist[i];
+ map[m].moblist[i] = spawn;
+ return i;
}
}
- return NULL;
+ return -1;
}
void map_spawnmobs(int m)
@@ -1919,7 +1799,7 @@ void map_spawnmobs(int m)
if(map[m].moblist[i]!=NULL)
{
k+=map[m].moblist[i]->num;
- npc_parse_mob2(map[m].moblist[i],1);
+ npc_parse_mob2(map[m].moblist[i],i);
}
if (battle_config.etc_log && k > 0)
@@ -1940,10 +1820,7 @@ int mob_cache_cleanup_sub(struct block_list *bl, va_list ap) {
md->hp < md->db->max_hp) //don't use status_get_maxhp for speed (by the time you have to remove a mob, their status changes should have expired anyway)
return 0; //Do not remove damaged mobs.
- mob_remove_map(md, 0);
- map_deliddb(&md->bl);
- aFree(md);
- md = NULL;
+ unit_free(&md->bl);
return 1;
}
@@ -2408,15 +2285,20 @@ int map_waterheight(char *mapname) {
char *rsw;
float whtemp;
int wh;
-#ifdef _WIN32
+
+ //Look up for clone map.
+ if(waterlist){
+ int i;
+ for(i=0;waterlist[i].mapname[0] && i < MAX_MAP_PER_SERVER;i++)
+ if(strcmp(waterlist[i].mapname,mapname)==0)
+ return map_waterheight(waterlist[i].clonemapname);
+ }
+ //Look up for the rsw
sprintf(fn,"data\\%s",mapname);
-#else
- sprintf(fn,"data/%s",mapname);
-#endif
+
rsw = strstr(fn, ".");
- if (rsw && strstr(fn, ".rsw") == NULL)
- strcat (rsw, "rsw");
-
+ if (rsw && strstr(fn, ".rsw") == NULL)
+ sprintf(rsw,".rsw");
// read & convert fn
// again, might not need to be unsigned char
rsw = (char *) grfio_read (fn);
@@ -2427,13 +2309,7 @@ int map_waterheight(char *mapname) {
aFree(rsw);
return wh;
}
- //Look up for clone map.
- if(waterlist){
- int i;
- for(i=0;waterlist[i].mapname[0] && i < MAX_MAP_PER_SERVER;i++)
- if(strcmp(waterlist[i].mapname,mapname)==0)
- return map_waterheight(waterlist[i].clonemapname);
- }
+ ShowWarning("Failed to find water level for (%s)\n", mapname, fn);
return NO_WATER;
}
@@ -2930,19 +2806,11 @@ int map_readgat (struct map_data *m)
if ((pt = strstr(m->name,"<")) != NULL) { // [MouseJstr]
char buf[64];
*pt++ = '\0';
-#ifdef _WIN32
sprintf(buf,"data\\%s", pt);
-#else
- sprintf(buf,"data/%s", pt);
-#endif
m->alias = aStrdup(buf);
}
-#ifdef _WIN32
sprintf(fn,"data\\%s",m->name);
-#else
- sprintf(fn,"data/%s",m->name);
-#endif
// read & convert fn
// again, might not need to be unsigned char
@@ -3675,11 +3543,10 @@ int cleanup_sub(struct block_list *bl, va_list ap) {
npc_unload((struct npc_data *)bl);
break;
case BL_MOB:
- mob_unload((struct mob_data *)bl);
+ unit_free(bl);
break;
case BL_PET:
- //There is no need for this, the pet is removed together with the player. [Skotlex]
-// pet_remove_map(((struct pet_data *)bl)->msd);
+ //There is no need for this, the pet is removed together with the player. [Skotlex]
break;
case BL_ITEM:
map_clearflooritem(bl->id);
@@ -3689,9 +3556,13 @@ int cleanup_sub(struct block_list *bl, va_list ap) {
break;
}
- return 0;
+ return 1;
}
+static int cleanup_db_sub(DBKey key,void *data,va_list va) {
+ return cleanup_sub((struct block_list*)data, NULL);
+}
+
/*==========================================
* map鯖終了・理
*------------------------------------------
@@ -3715,6 +3586,7 @@ void do_final(void) {
for (i = 0; i < j; i++)
map_quit(pl_allsd[i]);
+ i = id_db->foreach(id_db,cleanup_db_sub);
chrif_char_reset_offline();
chrif_flush_fifo();