summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/mmo.h2
-rw-r--r--src/map/clif.c16
-rw-r--r--src/map/clif.h1
-rw-r--r--src/map/guild.c54
-rw-r--r--src/map/map.h1
-rw-r--r--src/map/mob.c47
-rw-r--r--src/map/mob.h2
-rw-r--r--src/map/npc.c1
-rw-r--r--src/map/script.c27
-rw-r--r--src/map/trade.c1
-rw-r--r--src/map/unit.c16
11 files changed, 146 insertions, 22 deletions
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 18fda4bee..1c3d1e53a 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 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 <guild_id>;
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 "<map name>",<x>,<y>,"<name to show>",<mob id>,{,"<event label>"}{,<guardian index>};
+ * guardian("<map name>",<x>,<y>,"<name to show>",<mob id>{,"<event label>"}{,<guardian index>}) -> <id>
*------------------------------------------*/
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)
{// "<event label>",<guardian index>
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 index>
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;
}