From 1792fa7dcbae6d0678d9672ccb38eba88e87c757 Mon Sep 17 00:00:00 2001 From: FlavioJS Date: Mon, 7 Apr 2008 21:04:28 +0000 Subject: * 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://rathena.svn.sourceforge.net/svnroot/rathena/trunk@12525 54d463be-8e91-2dee-dedb-b68131a5f0ec --- 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 +++++++++++++--- 10 files changed, 144 insertions(+), 22 deletions(-) (limited to 'src/map') diff --git a/src/map/clif.c b/src/map/clif.c index 56a46a015..12c43972f 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 0c0e9b04d..382e399bb 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 f02deb16c..473599cc7 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 1dbc4581a..2bf12e366 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 6463c2103..b62006d0b 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 b8a8a2394..bad4b6088 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 78a7390cd..703e4faf6 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 15e83aeec..4cfde66f9 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 e94bb5a0d..880657ff0 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 b8a5d327a..88bfaab47 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; } -- cgit v1.2.3-70-g09d2