From cd1f48cc9e81e2538e1c056ab440de4968680bf0 Mon Sep 17 00:00:00 2001 From: FlavioJS Date: Mon, 7 Apr 2008 21:04:28 +0000 Subject: [PATCH] * Made script command 'flagemblem' and guild_emblem_change send an update of the emblem_id to the players in the area. - known bug: ui components that are displaying the emblem at the time (emblem in flag npc and emblem over head in gvg maps) are not updated, but putting the mouse over the target shows the new emblem * Modified script command 'guardian': - returns the id of the guardian - if guardian index isn't supplied, it generates a temporary guardian * Implemented support for temporary guardians (not saved with castle). * Added missing includes from r12520. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12525 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 13 ++++++++++ doc/script_commands.txt | 11 +++++++-- src/common/mmo.h | 2 ++ src/map/clif.c | 16 ++++++++++++ src/map/clif.h | 1 + src/map/guild.c | 54 +++++++++++++++++++++++++++++++++++++++-- src/map/map.h | 1 + src/map/mob.c | 47 ++++++++++++++++++++++++++--------- src/map/mob.h | 2 +- src/map/npc.c | 1 + src/map/script.c | 27 ++++++++++++++++++--- src/map/trade.c | 1 + src/map/unit.c | 16 +++++++++--- 13 files changed, 168 insertions(+), 24 deletions(-) diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index e874a5203c..eb91ffbee9 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,7 +4,20 @@ 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. 2008/04/07 + * Made script command 'flagemblem' and guild_emblem_change send an update + of the emblem_id to the players in the area. + - known bug: ui components that are displaying the emblem at the time + (emblem in flag npc and emblem over head in gvg maps) are not updated, + but putting the mouse over the target shows the new emblem + * Modified script command 'guardian': + - returns the id of the guardian + - if guardian index isn't supplied, it generates a temporary guardian + * Implemented support for temporary guardians (not saved with castle). + * Added missing includes from r12520. [FlavioJS] * Party/guild names can no longer be less then 2 characters long. (r12521) [Kevin] + * Removed the 'wait close' timer that closed a session's socket after 5 seconds. + This was causing random disconnects when logging in. (bugreport:1330) + * Improved the Mental Sensing fix from r12507 to not start the status at all, instead of starting it and ignoring it later on. [ultramage] 2008/04/06 * Fixed a case where a dangling pointer was formed when a person was - invited to a party immediately after creating their own. (r12518) [Kevin] diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 611e38bbc5..6f428b36ec 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.18.20080327 +//= 3.19.20080407 //========================================================= //= 1.0 - First release, filled will as much info as I could //= remember or figure out, most likely there are errors, @@ -108,6 +108,8 @@ //= Corrected cashshop description. (#FREEPOINTS->#KAFRAPOINTS) [L0ne_W0lf] //= 3.18.20080327 //= Added documentation for the 'checkcell' command [ultramage] +//= 3.19.20080407 +//= Extended the behaviour of 'guardian'. [FlavioJS] //========================================================= This document is a reference manual for all the scripting commands and functions @@ -5514,13 +5516,18 @@ returns a guild id: --------------------------------------- -*guardian "",,,"",,{,""}{,}; +*guardian("",,,"",,{,""}{,}) This command is roughly equivalent to 'monster', but is meant to be used with castle guardian monsters and will only work with them. It will set the guardian characteristics up according to the castle's investment values and otherwise set the things up that only castle guardians need. +Since trunk r12524: +Returns the id of the mob or 0 if an error occurred. +When 'guardian index' isn't supplied it produces a temporary guardian. +Temporary guardians are not saved with the castle and can't be accessed by guardianinfo. + --------------------------------------- *guardianinfo("", , ) diff --git a/src/common/mmo.h b/src/common/mmo.h index 18fda4bee4..1c3d1e53a7 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -425,6 +425,8 @@ struct guild_castle { unsigned visible : 1; int id; // object id } guardian[MAX_GUARDIANS]; + int* temp_guardians; // ids of temporary guardians (mobs) + int temp_guardians_max; }; // for Brandish Spear calculations diff --git a/src/map/clif.c b/src/map/clif.c index 56a46a015a..12c43972f9 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -6327,6 +6327,22 @@ int clif_guild_emblem(struct map_session_data *sd,struct guild *g) return 0; } +/// Sends update of the guild id/emblem id to everyone in the area. +void clif_guild_emblem_area(struct block_list* bl) +{ + char buf[12]; + + nullpo_retv(bl); + + // TODO this packet doesn't force the update of ui components that have the emblem visible + // (emblem in the flag npcs and emblem over the head in agit maps) [FlavioJS] + WBUFW(buf,0) = 0x1B4; + WBUFL(buf,2) = bl->id; + WBUFL(buf,6) = status_get_guild_id(bl); + WBUFW(buf,10) = status_get_emblem_id(bl); + clif_send(buf, 12, bl, AREA_WOS); +} + /*========================================== * Send guild skills *------------------------------------------*/ diff --git a/src/map/clif.h b/src/map/clif.h index 0c0e9b04dd..382e399bb6 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -307,6 +307,7 @@ int clif_guild_expulsion(struct map_session_data *sd,const char *name,const char int clif_guild_positionchanged(struct guild *g,int idx); int clif_guild_memberpositionchanged(struct guild *g,int idx); int clif_guild_emblem(struct map_session_data *sd,struct guild *g); +void clif_guild_emblem_area(struct block_list* bl); int clif_guild_notice(struct map_session_data *sd,struct guild *g); int clif_guild_message(struct guild *g,int account_id,const char *mes,int len); int clif_guild_skillup(struct map_session_data *sd,int skill_num,int lv); diff --git a/src/map/guild.c b/src/map/guild.c index f02deb16c1..473599cc71 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -1103,8 +1103,49 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) sd->guild_emblem_id=emblem_id; clif_guild_belonginfo(sd,g); clif_guild_emblem(sd,g); + clif_guild_emblem_area(&sd->bl); } } + {// update guardians (mobs) + DBIterator* iter = db_iterator(castle_db); + struct guild_castle* gc; + for( gc = (struct guild_castle*)dbi_first(iter) ; dbi_exists(iter); gc = (struct guild_castle*)dbi_next(iter) ) + { + if( gc->guild_id != guild_id ) + continue; + // update permanent guardians + for( i = 0; i < ARRAYLENGTH(gc->guardian); ++i ) + { + TBL_MOB* md = (gc->guardian[i].id ? map_id2md(gc->guardian[i].id) : NULL); + if( md == NULL || md->guardian_data == NULL ) + continue; + md->guardian_data->emblem_id = emblem_id; + clif_guild_emblem_area(&md->bl); + } + // update temporary guardians + for( i = 0; i < gc->temp_guardians_max; ++i ) + { + TBL_MOB* md = (gc->temp_guardians[i] ? map_id2md(gc->temp_guardians[i]) : NULL); + if( md == NULL || md->guardian_data == NULL ) + continue; + md->guardian_data->emblem_id = emblem_id; + clif_guild_emblem_area(&md->bl); + } + } + dbi_destroy(iter); + } + {// update npcs (flags or other npcs that used flagemblem to attach to this guild) + // TODO this is not efficient [FlavioJS] + struct s_mapiterator* iter = mapit_geteachnpc(); + TBL_NPC* nd; + for( nd = (TBL_NPC*)mapit_first(iter) ; mapit_exists(iter); nd = (TBL_NPC*)mapit_next(iter) ) + { + if( nd->subtype != SCRIPT || nd->u.scr.guild_id != guild_id ) + continue; + clif_guild_emblem_area(&nd->bl); + } + mapit_free(iter); + } return 0; } @@ -1909,10 +1950,19 @@ static int guild_expcache_db_final(DBKey key,void *data,va_list ap) return 0; } +static int guild_castle_db_final(DBKey key, void* data,va_list ap) +{ + struct guild_castle* gc = (struct guild_castle*)data; + if( gc->temp_guardians ) + aFree(gc->temp_guardians); + aFree(data); + return 0; +} + void do_init_guild(void) { guild_db=idb_alloc(DB_OPT_RELEASE_DATA); - castle_db=idb_alloc(DB_OPT_RELEASE_DATA); + castle_db=idb_alloc(DB_OPT_BASE); guild_expcache_db=idb_alloc(DB_OPT_BASE); guild_infoevent_db=idb_alloc(DB_OPT_BASE); expcache_ers = ers_new(sizeof(struct guild_expcache)); @@ -1932,7 +1982,7 @@ void do_init_guild(void) void do_final_guild(void) { guild_db->destroy(guild_db,NULL); - castle_db->destroy(castle_db,NULL); + castle_db->destroy(castle_db,guild_castle_db_final); guild_expcache_db->destroy(guild_expcache_db,guild_expcache_db_final); guild_infoevent_db->destroy(guild_infoevent_db,guild_infoevent_db_final); guild_castleinfoevent_db->destroy(guild_castleinfoevent_db,guild_infoevent_db_final); diff --git a/src/map/map.h b/src/map/map.h index 1dbc4581a2..2bf12e3668 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -584,6 +584,7 @@ bool mapit_exists(struct s_mapiterator* mapit); #define mapit_getallusers() mapit_alloc(MAPIT_NORMAL,BL_PC) #define mapit_geteachpc() mapit_alloc(MAPIT_NORMAL,BL_PC) #define mapit_geteachmob() mapit_alloc(MAPIT_NORMAL,BL_MOB) +#define mapit_geteachnpc() mapit_alloc(MAPIT_NORMAL,BL_NPC) #define mapit_geteachiddb() mapit_alloc(MAPIT_NORMAL,BL_ALL) // ‚»‚Ì‘¼ diff --git a/src/map/mob.c b/src/map/mob.c index 6463c2103d..b62006d0b5 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -677,6 +677,7 @@ static int mob_spawn_guardian_sub(int tid,unsigned int tick,int id,int data) struct block_list* bl = map_id2bl(id); struct mob_data* md; struct guild* g; + int guardup_lv; if (bl == NULL) //It is possible mob was already removed from map when the castle has no owner. [Skotlex] return 0; @@ -703,7 +704,7 @@ static int mob_spawn_guardian_sub(int tid,unsigned int tick,int id,int data) guild_castledatasave(md->guardian_data->castle->castle_id, 1, 0); } } else { - if (md->guardian_data->castle->guardian[md->guardian_data->number].visible) + if( md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible ) { //Safe removal of guardian. md->guardian_data->castle->guardian[md->guardian_data->number].visible = 0; guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); @@ -712,10 +713,11 @@ static int mob_spawn_guardian_sub(int tid,unsigned int tick,int id,int data) } return 0; } + guardup_lv = guild_checkskill(g,GD_GUARDUP); md->guardian_data->emblem_id = g->emblem_id; - memcpy (md->guardian_data->guild_name, g->name, NAME_LENGTH); - md->guardian_data->guardup_lv = guild_checkskill(g,GD_GUARDUP); - if(md->guardian_data->guardup_lv) + memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); + md->guardian_data->guardup_lv = guardup_lv; + if( guardup_lv ) status_calc_mob(md, 0); //Give bonuses. return 0; } @@ -723,7 +725,7 @@ static int mob_spawn_guardian_sub(int tid,unsigned int tick,int id,int data) /*========================================== * Summoning Guardians [Valaris] *------------------------------------------*/ -int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian) +int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian, bool has_index) { struct mob_data *md=NULL; struct spawn_data data; @@ -749,7 +751,11 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam data.class_ = class_; - if(guardian < 0 || guardian >= MAX_GUARDIANS) + if( !has_index ) + { + guardian = -1; + } + else if( guardian < 0 || guardian >= MAX_GUARDIANS ) { ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, class_, map[m].name); return 0; @@ -778,7 +784,7 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam else g = guild_search(gc->guild_id); - if (gc->guardian[guardian].id) + if( has_index && gc->guardian[guardian].id ) { //Check if guardian already exists, refuse to spawn if so. struct mob_data *md2 = (TBL_MOB*)map_id2bl(gc->guardian[guardian].id); if (md2 && md2->bl.type == BL_MOB && @@ -794,7 +800,21 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam md->guardian_data->number = guardian; md->guardian_data->guild_id = gc->guild_id; md->guardian_data->castle = gc; - gc->guardian[guardian].id = md->bl.id; + if( has_index ) + {// permanent guardian + gc->guardian[guardian].id = md->bl.id; + } + else + {// temporary guardian + int i; + ARR_FIND(0, gc->temp_guardians_max, i, gc->temp_guardians[i] == 0); + if( i == gc->temp_guardians_max ) + { + ++(gc->temp_guardians_max); + RECREATE(gc->temp_guardians, int, gc->temp_guardians_max); + } + gc->temp_guardians[i] = md->bl.id; + } if (g) { md->guardian_data->emblem_id = g->emblem_id; @@ -2077,7 +2097,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) status = &md->status; - if(md->guardian_data && md->guardian_data->number < MAX_GUARDIANS) + if( md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS ) guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); md->state.skillstate = MSS_DEAD; @@ -2588,7 +2608,7 @@ int mob_guardian_guildchange(struct block_list *bl,va_list ap) md->guardian_data->emblem_id = 0; md->guardian_data->guild_name[0] = '\0'; } else { - if (md->guardian_data->castle->guardian[md->guardian_data->number].visible) + if( md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible ) { //Safe removal of guardian. md->guardian_data->castle->guardian[md->guardian_data->number].visible = 0; guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); @@ -2602,8 +2622,11 @@ int mob_guardian_guildchange(struct block_list *bl,va_list ap) if (g == NULL) { //Properly remove guardian info from Castle data. ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->guild_id); - md->guardian_data->castle->guardian[md->guardian_data->number].visible = 0; - guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); + if( md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS ) + { + md->guardian_data->castle->guardian[md->guardian_data->number].visible = 0; + guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); + } unit_free(&md->bl,0); return 0; } diff --git a/src/map/mob.h b/src/map/mob.h index b8a8a23942..bad4b6088c 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -227,7 +227,7 @@ void mob_barricade_destroy(short m, const char *event); void mob_barricade_get(struct map_session_data *sd); void mod_barricade_clearall(void); -int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian); // Spawning Guardians [Valaris] +int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian, bool has_index); // Spawning Guardians [Valaris] int mob_guardian_guildchange(struct block_list *bl,va_list ap); //Change Guardian's ownership. [Skotlex] int mob_randomwalk(struct mob_data *md,unsigned int tick); diff --git a/src/map/npc.c b/src/map/npc.c index 78a7390cd5..703e4faf64 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -10,6 +10,7 @@ #include "../common/utils.h" #include "../common/ers.h" #include "../common/db.h" +#include "../common/socket.h" #include "map.h" #include "log.h" #include "clif.h" diff --git a/src/map/script.c b/src/map/script.c index 15e83aeecd..4cfde66f94 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -9165,14 +9165,30 @@ BUILDIN_FUNC(agitcheck) return 0; } +/// Sets the guild_id of this npc. +/// +/// flagemblem ; BUILDIN_FUNC(flagemblem) { + TBL_NPC* nd; int g_id=script_getnum(st,2); if(g_id < 0) return 0; -// ShowMessage("Script.c: [FlagEmblem] GuildID=%d, Emblem=%d.\n", g->guild_id, g->emblem_id); - ((struct npc_data *)map_id2bl(st->oid))->u.scr.guild_id = g_id; + nd = (TBL_NPC*)map_id2nd(st->oid); + if( nd == NULL ) + { + ShowError("script:flagemblem: npc %d not found\n", st->oid); + } + else if( nd->subtype != SCRIPT ) + { + ShowError("script:flagemblem: unexpected subtype %d for npc %d '%s'\n", nd->subtype, st->oid, nd->exname); + } + else + { + nd->u.scr.guild_id = g_id; + clif_guild_emblem_area(&nd->bl); + } return 0; } @@ -9743,13 +9759,14 @@ BUILDIN_FUNC(strmobinfo) /*========================================== * Summon guardians [Valaris] - * guardian "",,,"",,{,""}{,}; + * guardian("",,,"",{,""}{,}) -> *------------------------------------------*/ BUILDIN_FUNC(guardian) { int class_=0,x=0,y=0,guardian=0; const char *str,*map,*evt=""; struct script_data *data; + bool has_index = false; map =script_getstr(st,2); x =script_getnum(st,3); @@ -9761,6 +9778,7 @@ BUILDIN_FUNC(guardian) {// "", evt=script_getstr(st,7); guardian=script_getnum(st,8); + has_index = true; } else if( script_hasdata(st,7) ){ data=script_getdata(st,7); get_val(st,data); @@ -9770,6 +9788,7 @@ BUILDIN_FUNC(guardian) } else if( data_isint(data) ) {// guardian=script_getnum(st,7); + has_index = true; } else { ShowError("script:guardian: invalid data type for argument #6 (from 1)\n"); script_reportdata(data); @@ -9778,7 +9797,7 @@ BUILDIN_FUNC(guardian) } check_event(st, evt); - mob_spawn_guardian(map,x,y,str,class_,evt,guardian); + script_pushint(st, mob_spawn_guardian(map,x,y,str,class_,evt,guardian,has_index)); return 0; } diff --git a/src/map/trade.c b/src/map/trade.c index e94bb5a0d7..880657ff01 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -2,6 +2,7 @@ // For more information, see LICENCE in the main folder #include "../common/nullpo.h" +#include "../common/socket.h" #include "clif.h" #include "itemdb.h" #include "map.h" diff --git a/src/map/unit.c b/src/map/unit.c index b8a5d327a7..88bfaab477 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1950,10 +1950,20 @@ int unit_free(struct block_list *bl, int clrtype) aFree(md->lootitem); md->lootitem=NULL; } - if(md->guardian_data) + if( md->guardian_data ) { - if (md->guardian_data->number < MAX_GUARDIANS) - md->guardian_data->castle->guardian[md->guardian_data->number].id = 0; + struct guild_castle* gc = md->guardian_data->castle; + if( md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS ) + { + gc->guardian[md->guardian_data->number].id = 0; + } + else + { + int i; + ARR_FIND(0, gc->temp_guardians_max, i, gc->temp_guardians[i] == md->bl.id); + if( i < gc->temp_guardians_max ) + gc->temp_guardians[i] = 0; + } aFree(md->guardian_data); md->guardian_data = NULL; }