summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt13
-rw-r--r--doc/script_commands.txt11
-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
13 files changed, 168 insertions, 24 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index e874a5203..eb91ffbee 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 611e38bbc..6f428b36e 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 "<map name>",<x>,<y>,"<name to show>",<mob id>,<amount>{,"<event label>"}{,<guardian index>};
+*guardian("<map name>",<x>,<y>,"<name to show>",<mob id>,<amount>{,"<event label>"}{,<guardian index>})
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("<map name>", <guardian number>, <type>)
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;
}