From c97be60bbf5cddf05c98c06c6e9c2e15f05516b4 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Sat, 14 May 2016 11:57:54 -0400 Subject: [PATCH 01/10] Expanded the instance system to support new modes * New modes include: No player attached, single player, and guild. * Expanded script command instance_create to take in an owner ID and an optional mode. * Added a new script command instance_check_guild (works the same as instance_check_party). * Refactored all instance_id to unsigned short. --- doc/script_commands.txt | 75 +++++-- src/common/mmo.h | 1 + src/map/clif.c | 77 ++++--- src/map/clif.h | 8 +- src/map/guild.c | 24 +++ src/map/instance.c | 426 +++++++++++++++++++++++++++---------- src/map/instance.h | 40 ++-- src/map/map.c | 8 +- src/map/map.h | 6 +- src/map/party.c | 2 +- src/map/party.h | 2 +- src/map/pc.c | 17 +- src/map/pc.h | 2 + src/map/script.c | 209 +++++++++++++----- src/map/script_constants.h | 6 + 15 files changed, 662 insertions(+), 241 deletions(-) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 37493fdf62..1e3fdc9d8c 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -472,8 +472,8 @@ nothing - A permanent variable attached to the character, the default variable ends it. When a scope ends, its variables are converted to values ('return .@var;' returns a value, not a reference). "'" - An instance variable. - These are used with the instancing system, and are unique to each - party's instance. + These are used with the instancing system and are unique to each + instance type. "#" - A permanent local account variable. They are stored by char-server in the `acc_reg_num` table and `acc_reg_str`. @@ -503,6 +503,8 @@ $@name$ - temporary global string variable .name$ - NPC string variable .@name - scope integer variable .@name$ - scope string variable + 'name - instance integer variable + 'name$ - instance string variable #name - permanent local account integer variable #name$ - permanent local account string variable ##name - permanent global account integer variable @@ -8111,13 +8113,19 @@ This command will open a book item at the specified page. ======================== --------------------------------------- -*instance_create(""); +*instance_create("",{,}); -Creates an instance for the party of the attached player. The instance name, -along with all other instance data, is read from 'db/(pre-)re/instance_db.txt'. -Upon success, the command generates a unique instance ID, duplicates all listed -maps and NPCs, sets the alive time, and triggers the "OnInstanceInit" label in -all NPCs inside the instance. +Creates an instance for the of . The instance name, along with +all other instance data, is read from 'db/(pre-)re/instance_db.txt'. Upon success, +the command generates a unique instance ID, duplicates all listed maps and NPCs, +sets the alive time, and triggers the "OnInstanceInit" label in all NPCs inside +the instance. + +Instance Mode options: + IM_NONE: Attached to no one. + IM_CHAR: Attached to a single character. + IM_PARTY: Attached to a party (default instance mode). + IM_GUILD: Attached to a guild. The command returns the instance ID upon success, and these values upon failure: -1: Invalid type. @@ -8131,8 +8139,9 @@ The command returns the instance ID upon success, and these values upon failure: Destroys instance with the ID . If no ID is specified, the instance the script is attached to is used. If the script is not attached to an instance, -the instance of the currently attached player's party is used. If that fails, -the script will come to a halt. +the instance of the currently attached player is used (if it is a party or guild +mode). If it is not owned by anyone, no player needs to be attached. If that +fails, the script will come to a halt. --------------------------------------- @@ -8142,9 +8151,9 @@ Warps player to the specified instance after the script terminates. The map and coordinates are located in 'db/(pre-)re/instance_db.txt'. The command returns 0 upon success, and these values upon failure: - 1: Party not found. - 2: Party does not have an instance. - 3: Other errors (invalid instance name, instance doesn't match with party). + 1: Party/Guild not found (for party/guild modes). + 2: Character/Party/Guild does not have an instance. + 3: Other errors (invalid instance name, instance doesn't match with character/party/guild). Put -1 for x and y if want to warp player with default entrance coordinates. @@ -8163,16 +8172,18 @@ that fails, the script will come to a halt. Returns the unique name of the instanced map. If no instance ID is specified, the instance the script is attached to is used. If the script is not attached to -an instance, the instance of the currently attached player's party is used. If -that fails, the command returns an empty string instead. +an instance, the instance of the currently attached player is used (if it is a +party or guild mode). If it is not owned by anyone, no player needs to be +attached. If that fails, the command returns an empty string instead. --------------------------------------- *instance_id() Returns the unique instance id of the attached script. If the script is not -attached to an instance, the instance of the currently attached player's party is -used. If that fails, the function will return 0. +attached to an instance, the instance of the currently attached player is +used (if it is a party or guild mode). If it is not owned by anyone, no +player needs to be attached. If that fails, the function will return 0. --------------------------------------- @@ -8181,8 +8192,9 @@ used. If that fails, the function will return 0. Warps all players in the instance to at given coordinates. If no ID is specified, the instance the script is attached to is used. If the script is not attached to an instance, the instance of the -currently attached player's party is used. If that fails, the script will -come to a halt. +currently attached player is used (if it is a party or guild mode). If it +is not owned by anyone, no player needs to be attached. If that +fails, the script will come to a halt. --------------------------------------- @@ -8191,7 +8203,8 @@ come to a halt. Broadcasts a message to all players in the instance currently residing on an instance map. If -1 is specified for , the instance the script is attached to is used. If the script is not attached to an instance, -the instance of the currently attached player's party is used. +the instance of the currently attached player is used (if it is a party or guild +mode). If it is not owned by anyone, no player needs to be attached. For details on the other parameters, see 'announce'. @@ -8219,6 +8232,28 @@ if (instance_check_party(getcharid(1),2,2,149)) { --------------------------------------- +*instance_check_guild({,{,{,}}}) + +This function checks if a guild meets certain requirements, returning 1 if all +conditions are met and 0 otherwise. It will only check online characters. + +amount - number of online guild members (default is 1). +min - minimum level of all characters in the guild (default is 1). +max - maximum level of all characters in the guild (default is max level in conf). + +Example: + +if (instance_check_guild(getcharid(2),2,2,149)) { + mes "Your guild meets the Memorial Dungeon requirements.", + mes "All online members are between levels 1-150 and at least two are online."; + close; +} else { + mes "Sorry, your guild does not meet requirements."; + close; +} + +--------------------------------------- + ========================= |8.- Quest Log commands.| ========================= diff --git a/src/common/mmo.h b/src/common/mmo.h index f0dce7e232..c7a6fc8565 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -563,6 +563,7 @@ struct guild { struct guild_expulsion expulsion[MAX_GUILDEXPULSION]; struct guild_skill skill[MAX_GUILDSKILL]; struct Channel *channel; + unsigned short instance_id; /* Used by char-server to save events for guilds */ unsigned short save_flag; diff --git a/src/map/clif.c b/src/map/clif.c index 8b27345875..f592e914d8 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -16572,80 +16572,99 @@ void clif_font(struct map_session_data *sd) } -/*========================================== - * Notifies party members of instance change - *------------------------------------------*/ -void clif_instance_create(struct map_session_data *sd, const char *name, int num, int flag) +/// Required to start the instancing information window on Client +/// This window re-appears each "refresh" of client automatically until the keep_limit reaches 0. +/// S 0x2cb .61B .W +void clif_instance_create(unsigned short instance_id, int num) { #if PACKETVER >= 20071128 + struct map_session_data *sd = NULL; + enum send_target target = PARTY; unsigned char buf[65]; - if(!sd) return; + instance_getsd(instance_id, &sd, &target); + + if (!sd) + return; WBUFW(buf,0) = 0x2cb; - memcpy( WBUFP(buf,2), name, 62 ); + memcpy(WBUFP(buf,2), instance_data[instance_id].name, 62); WBUFW(buf,63) = num; - if(flag) // A timer has changed or been added - clif_send(buf,packet_len(0x2cb),&sd->bl,PARTY); - else // No notification - clif_send(buf,packet_len(0x2cb),&sd->bl,SELF); + clif_send(buf,packet_len(0x2cb),&sd->bl,target); #endif return; } -void clif_instance_changewait(struct map_session_data *sd, int num, int flag) +/// To announce Instancing queue creation if no maps available +/// S 0x2cc .W +void clif_instance_changewait(unsigned short instance_id, int num) { #if PACKETVER >= 20071128 + struct map_session_data *sd = NULL; + enum send_target target = PARTY; unsigned char buf[4]; - if(!sd) return; + instance_getsd(instance_id, &sd, &target); + + if (!sd) + return; WBUFW(buf,0) = 0x2cc; WBUFW(buf,2) = num; - if(flag) // A timer has changed or been added - clif_send(buf,packet_len(0x2cc),&sd->bl,PARTY); - else // No notification - clif_send(buf,packet_len(0x2cc),&sd->bl,SELF); + clif_send(buf,packet_len(0x2cc),&sd->bl,target); #endif return; } -void clif_instance_status(struct map_session_data *sd, const char *name, unsigned int limit1, unsigned int limit2, int flag) +/// Notify the current status to members +/// S 0x2cd .61B .L .L +void clif_instance_status(unsigned short instance_id, unsigned int limit1, unsigned int limit2) { #if PACKETVER >= 20071128 + struct map_session_data *sd = NULL; + enum send_target target = PARTY; unsigned char buf[71]; - if(!sd) return; //party_getavailablesd can return NULL + instance_getsd(instance_id, &sd, &target); + + if (!sd) + return; WBUFW(buf,0) = 0x2cd; - memcpy( WBUFP(buf,2), name, 62 ); + memcpy(WBUFP(buf,2), instance_data[instance_id].name, 62); WBUFL(buf,63) = limit1; WBUFL(buf,67) = limit2; - if(flag) // A timer has changed or been added - clif_send(buf,packet_len(0x2cd),&sd->bl,PARTY); - else // No notification - clif_send(buf,packet_len(0x2cd),&sd->bl,SELF); + clif_send(buf,packet_len(0x2cd),&sd->bl,target); #endif return; } -void clif_instance_changestatus(struct map_session_data *sd, int type, unsigned int limit, int flag) +/// Notify a status change to members +/// S 0x2ce .L +/// 0 = Notification (EnterLimitDate update?) +/// 1 = The Memorial Dungeon expired; it has been destroyed +/// 2 = The Memorial Dungeon's entry time limit expired; it has been destroyed +/// 3 = The Memorial Dungeon has been removed. +/// 4 = Create failure (removes the instance window) +void clif_instance_changestatus(unsigned int instance_id, int type, unsigned int limit) { #if PACKETVER >= 20071128 + struct map_session_data *sd = NULL; + enum send_target target = PARTY; unsigned char buf[10]; - if(!sd) return; + instance_getsd(instance_id, &sd, &target); + + if (!sd) + return; WBUFW(buf,0) = 0x2ce; WBUFL(buf,2) = type; WBUFL(buf,6) = limit; - if(flag) // A timer has changed or been added - clif_send(buf,packet_len(0x2ce),&sd->bl,PARTY); - else // No notification - clif_send(buf,packet_len(0x2ce),&sd->bl,SELF); + clif_send(buf,packet_len(0x2ce),&sd->bl,target); #endif return; diff --git a/src/map/clif.h b/src/map/clif.h index e94f4127a7..3325cf8908 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -745,10 +745,10 @@ void clif_sendbgemblem_area(struct map_session_data *sd); void clif_sendbgemblem_single(int fd, struct map_session_data *sd); // Instancing -void clif_instance_create(struct map_session_data *sd, const char *name, int num, int flag); -void clif_instance_changewait(struct map_session_data *sd, int num, int flag); -void clif_instance_status(struct map_session_data *sd, const char *name, unsigned int limit1, unsigned int limit2, int flag); -void clif_instance_changestatus(struct map_session_data *sd, int type, unsigned int limit, int flag); +void clif_instance_create(unsigned short instance_id, int num); +void clif_instance_changewait(unsigned short instance_id, int num); +void clif_instance_status(unsigned short instance_id, unsigned int limit1, unsigned int limit2); +void clif_instance_changestatus(unsigned int instance_id, int type, unsigned int limit); // Custom Fonts void clif_font(struct map_session_data *sd); diff --git a/src/map/guild.c b/src/map/guild.c index f13faacb16..243c1c69cf 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -17,6 +17,7 @@ #include "battle.h" #include "npc.h" #include "pc.h" +#include "instance.h" #include "intif.h" #include "channel.h" #include "log.h" @@ -551,6 +552,8 @@ int guild_recv_info(struct guild *sg) { clif_guild_notice(sd, g); sd->guild_emblem_id = g->emblem_id; } + if (g->instance_id != 0) + instance_reqinfo(sd, g->instance_id); } //Occurrence of an event @@ -694,6 +697,8 @@ void guild_member_joined(struct map_session_data *sd) { g->member[i].sd = sd; sd->guild = g; + if (g->instance_id != 0) + instance_reqinfo(sd, g->instance_id); if( channel_config.ally_enable && channel_config.ally_autojoin ) { channel_gjoin(sd,3); } @@ -744,6 +749,9 @@ int guild_member_added(int guild_id,uint32 account_id,uint32 char_id,int flag) { //Next line commented because it do nothing, look at guild_recv_info [LuzZza] //clif_charnameupdate(sd); //Update display name [Skotlex] + if (g->instance_id != 0) + instance_reqinfo(sd, g->instance_id); + return 0; } @@ -860,6 +868,17 @@ int guild_member_withdraw(int guild_id, uint32 account_id, uint32 char_id, int f sd->guild = NULL; sd->guild_emblem_id = 0; + if (g->instance_id) { + int16 m = sd->bl.m; + + if (map[m].instance_id) { // User was on the instance map + if (map[m].save.map) + pc_setpos(sd, map[m].save.map, map[m].save.x, map[m].save.y, CLR_TELEPORT); + else + pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); + } + } + clif_charnameupdate(sd); //Update display name [Skotlex] status_change_end(&sd->bl,SC_LEADERSHIP,INVALID_TIMER); status_change_end(&sd->bl,SC_GLORYWOUNDS,INVALID_TIMER); @@ -1833,6 +1852,11 @@ int guild_break(struct map_session_data *sd,char *name) { return 0; } + if (g->instance_id) { + instance_data[g->instance_id].owner_id = 0; + instance_destroy(g->instance_id); + } + /* Regardless of char server allowing it, we clear the guild master's auras */ if ((ud = unit_bl2ud(&sd->bl))) { int count = 0; diff --git a/src/map/instance.c b/src/map/instance.c index f3ad2577f6..1fa43f41dd 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -11,6 +11,7 @@ #include "../common/malloc.h" #include "clif.h" +#include "guild.h" #include "instance.h" #include "map.h" #include "npc.h" @@ -30,7 +31,8 @@ struct instance_data instance_data[MAX_INSTANCE_DATA]; struct instance_db { unsigned short id; ///< Instance ID StringBuf *name; ///< Instance name - unsigned int limit; ///< Duration limit + unsigned int limit, ///< Duration limit + timeout; ///< Timeout limit struct { StringBuf *mapname; ///< Mapname, the limit should be MAP_NAME_LENGTH_EXT unsigned short x, y; ///< Map coordinates @@ -59,6 +61,34 @@ static uint16 instance_name2id(const char *instance_name) { return (uint16)strdb_uiget(InstanceNameDB,instance_name); } +/** + * Search for a sd of an Instance + * @param instance_id: Instance ID + * @param sd: Player data to attach + * @param target: Target display type + */ +void instance_getsd(unsigned short instance_id, struct map_session_data **sd, enum send_target *target) { + switch(instance_data[instance_id].mode) { + case IM_NONE: + (*sd) = NULL; + (*target) = SELF; + break; + case IM_GUILD: + (*sd) = guild_getavailablesd(guild_search(instance_data[instance_id].owner_id)); + (*target) = GUILD; + break; + case IM_PARTY: + (*sd) = party_getavailablesd(party_search(instance_data[instance_id].owner_id)); + (*target) = PARTY; + break; + case IM_CHAR: + (*sd) = map_id2sd(instance_data[instance_id].owner_id); + (*target) = SELF; + break; + } + return; +} + /*========================================== * Searches for an instance name in the database *------------------------------------------*/ @@ -80,23 +110,42 @@ static int instance_delete_timer(int tid, unsigned int tick, int id, intptr_t da } /*========================================== - * Create subscription timer for party + * Create subscription timer *------------------------------------------*/ static int instance_subscription_timer(int tid, unsigned int tick, int id, intptr_t data) { int i, ret; - int instance_id = instance_wait.id[0]; - struct party_data *p; + unsigned short instance_id = instance_wait.id[0]; + struct map_session_data *sd = NULL; + struct party_data *p = NULL; + struct guild *g = NULL; + enum instance_mode mode; - if(instance_wait.count == 0 || instance_id <= 0) + if(instance_wait.count == 0 || instance_id == 0) return 0; // Check that maps have been added ret = instance_addmap(instance_id); + mode = instance_data[instance_id].mode; - // If no maps are created, tell party to wait - if(ret == 0 && ( p = party_search( instance_data[instance_id].party_id ) ) != NULL) - clif_instance_changewait( party_getavailablesd( p ), 0xffff, 1 ); + switch(mode) { + case IM_NONE: + break; + case IM_CHAR: + if (ret == 0 && (sd = map_id2sd(instance_data[instance_id].owner_id)) != NULL) // If no maps are created, tell player to wait + clif_instance_changewait(instance_id, 0xffff); + break; + case IM_PARTY: + if (ret == 0 && (p = party_search(instance_data[instance_id].owner_id)) != NULL) // If no maps are created, tell party to wait + clif_instance_changewait(instance_id, 0xffff); + break; + case IM_GUILD: + if (ret == 0 && (g = guild_search(instance_data[instance_id].owner_id)) != NULL) // If no maps are created, tell guild to wait + clif_instance_changewait(instance_id, 0xffff); + break; + default: + return 0; + } instance_wait.count--; memmove(&instance_wait.id[0],&instance_wait.id[1],sizeof(instance_wait.id[0])*instance_wait.count); @@ -104,9 +153,9 @@ static int instance_subscription_timer(int tid, unsigned int tick, int id, intpt for(i = 0; i < instance_wait.count; i++) { if( instance_data[instance_wait.id[i]].state == INSTANCE_IDLE && - ( p = party_search( instance_data[instance_wait.id[i]].party_id ) ) != NULL + ((mode == IM_CHAR && sd != NULL) || (mode == IM_GUILD && g != NULL) || (mode == IM_PARTY && p != NULL)) ){ - clif_instance_changewait( party_getavailablesd( p ), i + 1, 1 ); + clif_instance_changewait(instance_id, i + 1); } } @@ -119,12 +168,11 @@ static int instance_subscription_timer(int tid, unsigned int tick, int id, intpt } /*========================================== - * Adds timer back to party entering instance + * Adds timer back to members entering instance *------------------------------------------*/ -static int instance_startkeeptimer(struct instance_data *im, short instance_id) +static int instance_startkeeptimer(struct instance_data *im, unsigned short instance_id) { struct instance_db *db; - struct party_data *p; nullpo_retr(0, im); @@ -139,9 +187,24 @@ static int instance_startkeeptimer(struct instance_data *im, short instance_id) im->keep_limit = (unsigned int)time(NULL) + db->limit; im->keep_timer = add_timer(gettick()+db->limit*1000, instance_delete_timer, instance_id, 0); - // Notify party of the added instance timer - if( ( p = party_search( im->party_id ) ) != NULL ) - clif_instance_status( party_getavailablesd( p ), StringBuf_Value(db->name), im->keep_limit, im->idle_limit, 1 ); + switch(im->mode) { + case IM_NONE: + break; + case IM_CHAR: + if (map_id2sd(im->owner_id) != NULL) // Notify player of the added instance timer + clif_instance_status(instance_id, im->keep_limit, im->idle_limit); + break; + case IM_PARTY: + if (party_search(im->owner_id) != NULL) // Notify party of the added instance timer + clif_instance_status(instance_id, im->keep_limit, im->idle_limit); + break; + case IM_GUILD: + if (guild_search(im->owner_id) != NULL) // Notify guild of the added instance timer + clif_instance_status(instance_id, im->keep_limit, im->idle_limit); + break; + default: + return 1; + } return 0; } @@ -150,10 +213,9 @@ static int instance_startkeeptimer(struct instance_data *im, short instance_id) * Creates idle timer * Default before instance destroy is 5 minutes *------------------------------------------*/ -static int instance_startidletimer(struct instance_data *im, short instance_id) +static int instance_startidletimer(struct instance_data *im, unsigned short instance_id) { struct instance_db *db; - struct party_data *p; nullpo_retr(1, im); @@ -161,16 +223,30 @@ static int instance_startidletimer(struct instance_data *im, short instance_id) if(im->idle_timer != INVALID_TIMER) return 1; + if ((db = instance_searchtype_db(im->type)) == NULL) + return 1; + // Add the timer im->idle_limit = (unsigned int)time(NULL) + INSTANCE_LIMIT/1000; im->idle_timer = add_timer(gettick()+INSTANCE_LIMIT, instance_delete_timer, instance_id, 0); - // Notify party of added instance timer - if( ( p = party_search( im->party_id ) ) != NULL && - ( db = instance_searchtype_db( im->type ) ) != NULL - ) - { - clif_instance_status( party_getavailablesd( p ), StringBuf_Value(db->name), im->keep_limit, im->idle_limit, 1 ); + switch(im->mode) { + case IM_NONE: + break; + case IM_CHAR: + if (map_id2sd(im->owner_id) != NULL && instance_searchtype_db(im->type) != NULL) // Notify player of added instance timer + clif_instance_status(instance_id, im->keep_limit, im->idle_limit); + break; + case IM_PARTY: + if (party_search(im->owner_id) != NULL && instance_searchtype_db(im->type) != NULL) // Notify party of added instance timer + clif_instance_status(instance_id, im->keep_limit, im->idle_limit); + break; + case IM_GUILD: + if (guild_search(im->owner_id) != NULL && instance_searchtype_db(im->type) != NULL) // Notify guild of added instance timer + clif_instance_status(instance_id, im->keep_limit, im->idle_limit); + break; + default: + return 1; } return 0; @@ -179,10 +255,8 @@ static int instance_startidletimer(struct instance_data *im, short instance_id) /*========================================== * Delete the idle timer *------------------------------------------*/ -static int instance_stopidletimer(struct instance_data *im) +static int instance_stopidletimer(struct instance_data *im, unsigned short instance_id) { - struct party_data *p; - nullpo_retr(0, im); // No timer @@ -194,9 +268,24 @@ static int instance_stopidletimer(struct instance_data *im) delete_timer(im->idle_timer, instance_delete_timer); im->idle_timer = INVALID_TIMER; - // Notify the party - if( ( p = party_search( im->party_id ) ) != NULL ) - clif_instance_changestatus( party_getavailablesd( p ), 0, im->idle_limit, 1 ); + switch(im->mode) { + case IM_NONE: + break; + case IM_CHAR: + if (map_id2sd(im->owner_id) != NULL) // Notify the player + clif_instance_changestatus(instance_id, 0, im->idle_limit); + break; + case IM_PARTY: + if (party_search(im->owner_id) != NULL) // Notify the party + clif_instance_changestatus(instance_id, 0, im->idle_limit); + break; + case IM_GUILD: + if (guild_search(im->owner_id) != NULL) // Notify the guild + clif_instance_changestatus(instance_id, 0, im->idle_limit); + break; + default: + return 1; + } return 0; } @@ -247,46 +336,84 @@ void instance_addnpc(struct instance_data *im) /*-------------------------------------- * name : instance name * Return value could be - * -4 = no free instances | -3 = already exists | -2 = party not found | -1 = invalid type + * -4 = no free instances | -3 = already exists | -2 = character/party/guild not found | -1 = invalid type * On success return instance_id *--------------------------------------*/ -int instance_create(int party_id, const char *name) -{ - short i; +int instance_create(int owner_id, const char *name, enum instance_mode mode) { struct instance_db *db = instance_searchname_db(name); - struct party_data *p = party_search(party_id); + struct map_session_data *sd = NULL; + struct party_data *p = NULL; + struct guild *g = NULL; + unsigned short i; - if(db == NULL) - return -1; + nullpo_retr(-1, db); - if( p == NULL ) - return -2; - - if( p->instance_id ) - return -3; // Party already instancing + switch(mode) { + case IM_NONE: + break; + case IM_CHAR: + if ((sd = map_id2sd(owner_id)) == NULL) { + ShowError("instance_create: character %d not found for instance '%s'.\n", owner_id, name); + return -2; + } + if (sd->instance_id) + return -3; // Player already instancing + break; + case IM_PARTY: + if ((p = party_search(owner_id)) == NULL) { + ShowError("instance_create: party %d not found for instance '%s'.\n", owner_id, name); + return -2; + } + if (p->instance_id) + return -3; // Party already instancing + break; + case IM_GUILD: + if ((g = guild_search(owner_id)) == NULL) { + ShowError("instance_create: guild %d not found for instance '%s'.\n", owner_id, name); + return -2; + } + if (g->instance_id) + return -3; // Guild already instancing + break; + default: + ShowError("instance_create: unknown mode %u for owner_id %d and name %s.\n", mode, owner_id, name); + return -2; + } // Searching a Free Instance - // 0 is ignored as this mean "no instance" on maps + // 0 is ignored as this means "no instance" on maps ARR_FIND(1, MAX_INSTANCE_DATA, i, instance_data[i].state == INSTANCE_FREE); if( i >= MAX_INSTANCE_DATA ) return -4; instance_data[i].type = db->id; instance_data[i].state = INSTANCE_IDLE; - instance_data[i].party_id = p->party.party_id; + instance_data[i].owner_id = owner_id; + instance_data[i].mode = mode; instance_data[i].keep_limit = 0; instance_data[i].keep_timer = INVALID_TIMER; instance_data[i].idle_limit = 0; instance_data[i].idle_timer = INVALID_TIMER; instance_data[i].regs.vars = i64db_alloc(DB_OPT_RELEASE_DATA); instance_data[i].regs.arrays = NULL; + safestrncpy(instance_data[i].name, name, sizeof(instance_data[i].name)); memset(instance_data[i].map, 0, sizeof(instance_data[i].map)); - p->instance_id = i; + switch(mode) { + case IM_CHAR: + sd->instance_id = i; + break; + case IM_PARTY: + p->instance_id = i; + break; + case IM_GUILD: + g->instance_id = i; + break; + } - instance_wait.id[instance_wait.count++] = p->instance_id; + instance_wait.id[instance_wait.count++] = i; - clif_instance_create( party_getavailablesd( p ), name, instance_wait.count, 1); + clif_instance_create(i, instance_wait.count); instance_subscription_timer(0,0,0,0); @@ -298,24 +425,23 @@ int instance_create(int party_id, const char *name) /*-------------------------------------- * Adds maps to the instance *--------------------------------------*/ -int instance_addmap(short instance_id) +int instance_addmap(unsigned short instance_id) { int i, m; int cnt_map = 0; struct instance_data *im; struct instance_db *db; - struct party_data *p; - if(instance_id <= 0) + if (instance_id == 0) return 0; im = &instance_data[instance_id]; // If the instance isn't idle, we can't do anything - if(im->state != INSTANCE_IDLE) + if (im->state != INSTANCE_IDLE) return 0; - if((db = instance_searchtype_db(im->type)) == NULL) + if ((db = instance_searchtype_db(im->type)) == NULL) return 0; // Set to busy, update timers @@ -343,9 +469,24 @@ int instance_addmap(short instance_id) // Create NPCs on all maps instance_addnpc(im); - // Inform party members of the created instance - if( (p = party_search( im->party_id ) ) != NULL ) - clif_instance_status( party_getavailablesd( p ), StringBuf_Value(db->name), im->keep_limit, im->idle_limit, 1); + switch(im->mode) { + case IM_NONE: + break; + case IM_CHAR: + if (map_id2sd(im->owner_id) != NULL) // Inform player of the created instance + clif_instance_status(instance_id, im->keep_limit, im->idle_limit); + break; + case IM_PARTY: + if (party_search(im->owner_id) != NULL) // Inform party members of the created instance + clif_instance_status(instance_id, im->keep_limit, im->idle_limit); + break; + case IM_GUILD: + if (guild_search(im->owner_id) != NULL) // Inform guild members of the created instance + clif_instance_status(instance_id, im->keep_limit, im->idle_limit); + break; + default: + return 0; + } return cnt_map; } @@ -357,7 +498,7 @@ int instance_addmap(short instance_id) * instance_id : where to search * result : mapid of map "name" in this instance *------------------------------------------*/ -int instance_mapname2mapid(const char *name, short instance_id) +int instance_mapname2mapid(const char *name, unsigned short instance_id) { struct instance_data *im; int m = map_mapname2mapid(name); @@ -371,7 +512,7 @@ int instance_mapname2mapid(const char *name, short instance_id) strcpy(iname,name); - if(instance_id <= 0 || instance_id > MAX_INSTANCE_DATA) + if(instance_id == 0 || instance_id > MAX_INSTANCE_DATA) return m; im = &instance_data[instance_id]; @@ -395,14 +536,17 @@ int instance_mapname2mapid(const char *name, short instance_id) /*========================================== * Removes a instance, all its maps and npcs. *------------------------------------------*/ -int instance_destroy(short instance_id) +int instance_destroy(unsigned short instance_id) { struct instance_data *im; - struct party_data *p; + struct map_session_data *sd = NULL; + struct party_data *p = NULL; + struct guild *g = NULL; int i, type = 0; unsigned int now = (unsigned int)time(NULL); + enum instance_mode mode; - if(instance_id <= 0 || instance_id > MAX_INSTANCE_DATA) + if(instance_id == 0 || instance_id > MAX_INSTANCE_DATA) return 1; im = &instance_data[instance_id]; @@ -410,6 +554,33 @@ int instance_destroy(short instance_id) if(im->state == INSTANCE_FREE) return 1; + mode = im->mode; + switch(mode) { + case IM_NONE: + break; + case IM_CHAR: + if ((sd = map_id2sd(im->owner_id)) == NULL) { + ShowError("instance_destroy: character %d not found for instance '%s'.\n", im->owner_id, im->name); + return 1; + } + break; + case IM_PARTY: + if ((p = party_search(im->owner_id)) == NULL) { + ShowError("instance_destroy: party %d not found for instance '%s'.\n", im->owner_id, im->name); + return 1; + } + break; + case IM_GUILD: + if ((g = guild_search(im->owner_id)) == NULL) { + ShowError("instance_destroy: guild %d not found for instance '%s'.\n", im->owner_id, im->name); + return 1; + } + break; + default: + ShowError("instance_destroy: unknown owner type %u for owner_id %d and name %s.\n", mode, im->owner_id, im->name); + return 1; + } + if(im->state == INSTANCE_IDLE) { for(i = 0; i < instance_wait.count; i++) { if(instance_wait.id[i] == instance_id) { @@ -419,8 +590,8 @@ int instance_destroy(short instance_id) for(i = 0; i < instance_wait.count; i++) if(instance_data[instance_wait.id[i]].state == INSTANCE_IDLE) - if((p = party_search(instance_data[instance_wait.id[i]].party_id)) != NULL) - clif_instance_changewait( party_getavailablesd( p ), i+1, 1); + if ((mode == IM_CHAR && sd != NULL) || (mode == IM_PARTY && p != NULL) || (mode == IM_GUILD && g != NULL)) + clif_instance_changewait(instance_id, i + 1); if(instance_wait.count) instance_wait.timer = add_timer(gettick()+INSTANCE_INTERVAL, instance_subscription_timer, 0, 0); @@ -451,13 +622,18 @@ int instance_destroy(short instance_id) im->idle_timer = INVALID_TIMER; } - if((p = party_search(im->party_id))) { + if (mode == IM_CHAR) + sd->instance_id = 0; + else if (mode == IM_PARTY) p->instance_id = 0; + else if (mode == IM_GUILD) + g->instance_id = 0; + if (mode != IM_NONE) { if(type) - clif_instance_changestatus( party_getavailablesd( p ), type, 0, 1 ); + clif_instance_changestatus(instance_id, type, 0); else - clif_instance_changewait( party_getavailablesd( p ), 0xffff, 1 ); + clif_instance_changewait(instance_id, 0xffff); } if( im->regs.vars ) { @@ -478,61 +654,78 @@ int instance_destroy(short instance_id) /*========================================== * Allows a user to enter an instance *------------------------------------------*/ -int instance_enter(struct map_session_data *sd, const char *name) +int instance_enter(struct map_session_data *sd, unsigned short instance_id, const char *name) { struct instance_db *db = instance_searchname_db(name); - if(db == NULL) - return 3; + nullpo_retr(-1, sd); + nullpo_retr(3, db); - return instance_enter_position(sd, name, db->enter.x, db->enter.y); + return instance_enter_position(sd, instance_id, name, db->enter.x, db->enter.y); } /*========================================== * Warp a user into instance *------------------------------------------*/ -int instance_enter_position(struct map_session_data *sd, const char *name, short x, short y) +int instance_enter_position(struct map_session_data *sd, unsigned short instance_id, const char *name, short x, short y) { - struct instance_data *im; + struct instance_data *im = &instance_data[instance_id]; struct instance_db *db = instance_searchname_db(name); - struct party_data *p; - int m; + struct party_data *p = NULL; + struct guild *g = NULL; + int16 m; nullpo_retr(-1, sd); + nullpo_retr(3, db); - // Character must be in instance party - if(sd->status.party_id == 0) - return 1; - if((p = party_search(sd->status.party_id)) == NULL) - return 1; + switch(instance_data[instance_id].mode) { + case IM_NONE: + break; + case IM_CHAR: + if (sd->instance_id == 0) // Player must have an instance + return 2; + if (im->owner_id != sd->status.account_id) + return 3; + break; + case IM_PARTY: + if (sd->status.party_id == 0) // Character must be in instance party + return 1; + if ((p = party_search(sd->status.party_id)) == NULL) + return 1; + if (p->instance_id == 0) // Party must have an instance + return 2; + if (im->owner_id != p->party.party_id) + return 3; + break; + case IM_GUILD: + if (sd->status.guild_id == 0) // Character must be in instance guild + return 1; + if ((g = guild_search(sd->status.guild_id)) == NULL) + return 1; + if (g->instance_id == 0) // Guild must have an instance + return 2; + if (im->owner_id != g->guild_id) + return 3; + break; + } - // Party must have an instance - if(p->instance_id == 0) - return 2; - - if(db == NULL) + if (im->state != INSTANCE_BUSY) return 3; - - im = &instance_data[p->instance_id]; - if(im->party_id != p->party.party_id) - return 3; - if(im->state != INSTANCE_BUSY) - return 3; - if(im->type != db->id) + if (im->type != db->id) return 3; // Does the instance match? - if((m = instance_mapname2mapid(StringBuf_Value(db->enter.mapname), p->instance_id)) < 0) + if ((m = instance_mapname2mapid(StringBuf_Value(db->enter.mapname), instance_id)) < 0) return 3; - if(pc_setpos(sd, map_id2index(m), x, y, CLR_OUTSIGHT)) + if (pc_setpos(sd, map_id2index(m), x, y, CLR_OUTSIGHT)) return 3; // If there was an idle timer, let's stop it - instance_stopidletimer(im); + instance_stopidletimer(im, instance_id); // Now we start the instance timer - instance_startkeeptimer(im, p->instance_id); + instance_startkeeptimer(im, instance_id); return 0; } @@ -540,14 +733,14 @@ int instance_enter_position(struct map_session_data *sd, const char *name, short /*========================================== * Request some info about the instance *------------------------------------------*/ -int instance_reqinfo(struct map_session_data *sd, short instance_id) +int instance_reqinfo(struct map_session_data *sd, unsigned short instance_id) { struct instance_data *im; struct instance_db *db; nullpo_retr(1, sd); - if(instance_id <= 0 || instance_id > MAX_INSTANCE_DATA) + if(instance_id == 0 || instance_id > MAX_INSTANCE_DATA) return 1; im = &instance_data[instance_id]; @@ -561,12 +754,12 @@ int instance_reqinfo(struct map_session_data *sd, short instance_id) for(i = 0; i < instance_wait.count; i++) { if(instance_wait.id[i] == instance_id) { - clif_instance_create(sd, StringBuf_Value(db->name), i+1, 0); + clif_instance_create(instance_id, i + 1); break; } } } else if(im->state == INSTANCE_BUSY) // Give info on the instance if busy - clif_instance_status(sd, StringBuf_Value(db->name), im->keep_limit, im->idle_limit, 0); + clif_instance_status(instance_id, im->keep_limit, im->idle_limit); return 0; } @@ -574,11 +767,11 @@ int instance_reqinfo(struct map_session_data *sd, short instance_id) /*========================================== * Add players to the instance (for timers) *------------------------------------------*/ -int instance_addusers(short instance_id) +int instance_addusers(unsigned short instance_id) { struct instance_data *im; - if(instance_id <= 0 || instance_id > MAX_INSTANCE_DATA) + if(instance_id == 0 || instance_id > MAX_INSTANCE_DATA) return 1; im = &instance_data[instance_id]; @@ -586,7 +779,7 @@ int instance_addusers(short instance_id) return 1; // Stop the idle timer if we had one - instance_stopidletimer(im); + instance_stopidletimer(im, instance_id); // Start the instance keep timer instance_startkeeptimer(im, instance_id); @@ -597,12 +790,12 @@ int instance_addusers(short instance_id) /*========================================== * Delete players from the instance (for timers) *------------------------------------------*/ -int instance_delusers(short instance_id) +int instance_delusers(unsigned short instance_id) { struct instance_data *im; int i, idle = 0; - if(instance_id <= 0 || instance_id > MAX_INSTANCE_DATA) + if(instance_id == 0 || instance_id > MAX_INSTANCE_DATA) return 1; im = &instance_data[instance_id]; @@ -637,8 +830,8 @@ static bool instance_readdb_sub(char* str[], int columns, int current) return false; } - if (mapindex_name2id(str[3]) == 0) { - ShowError("instance_readdb_sub: Invalid map '%s' as entrance map.\n", str[3]); + if (mapindex_name2id(str[4]) == 0) { + ShowError("instance_readdb_sub: Invalid map '%s' as entrance map.\n", str[4]); return false; } @@ -662,12 +855,13 @@ static bool instance_readdb_sub(char* str[], int columns, int current) StringBuf_AppendStr(db->name, str[1]); db->limit = atoi(str[2]); - StringBuf_AppendStr(db->enter.mapname, str[3]); - db->enter.x = atoi(str[4]); - db->enter.y = atoi(str[5]); + db->timeout = atoi(str[3]); + StringBuf_AppendStr(db->enter.mapname, str[4]); + db->enter.x = atoi(str[5]); + db->enter.y = atoi(str[6]); //Instance maps - for (i = 6; i < columns; i++) { + for (i = 7; i < columns; i++) { if (strlen(str[i])) { if (mapindex_name2id(str[i]) == 0) { ShowWarning("instance_readdb_sub: Invalid map '%s' in maplist, skipping...\n", str[i]); @@ -675,7 +869,7 @@ static bool instance_readdb_sub(char* str[], int columns, int current) } RECREATE(db->maplist, StringBuf *, db->maplist_count+1); db->maplist[db->maplist_count] = StringBuf_Malloc(); - if (strcmpi(str[i], str[3]) == 0) + if (strcmpi(str[i], str[4]) == 0) defined = true; StringBuf_AppendStr(db->maplist[db->maplist_count], str[i]); db->maplist_count++; @@ -732,7 +926,7 @@ void instance_readdb(void) { int f; for (f = 0; fbl.m].instance_id) { struct party_data *p; - if(!(p = party_search(sd->status.party_id)) || p->instance_id != map[sd->bl.m].instance_id) // Someone not in party is on instance map + struct guild *g; + + if (instance_data[map[sd->bl.m].instance_id].mode == IM_PARTY && (!(p = party_search(sd->status.party_id)) || p->instance_id != map[sd->bl.m].instance_id)) // Someone not in party is on instance map + continue; + if (instance_data[map[sd->bl.m].instance_id].mode == IM_GUILD && (!(g = guild_search(sd->status.guild_id)) || g->instance_id != map[sd->bl.m].instance_id)) // Someone not in guild is on instance map continue; im = &instance_data[p->instance_id]; - if((db = instance_searchtype_db(im->type)) != NULL && !instance_enter(sd,StringBuf_Value(db->name))) { // All good + if((db = instance_searchtype_db(im->type)) != NULL && !instance_enter(sd, i, StringBuf_Value(db->name))) { // All good clif_displaymessage(sd->fd, msg_txt(sd,515)); // Instance has been reloaded instance_reqinfo(sd,p->instance_id); } else // Something went wrong diff --git a/src/map/instance.h b/src/map/instance.h index e10a12152e..7d59a0ad24 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -14,13 +14,27 @@ struct block_list; #define INSTANCE_NAME_LENGTH (60+1) -typedef enum instance_state { INSTANCE_FREE, INSTANCE_IDLE, INSTANCE_BUSY } instance_state; +typedef enum instance_state { + INSTANCE_FREE, + INSTANCE_IDLE, + INSTANCE_BUSY +} instance_state; + +enum instance_mode { + IM_NONE, + IM_CHAR, + IM_PARTY, + IM_GUILD, + IM_MAX, +}; struct instance_data { unsigned short type, ///< Instance DB ID cnt_map; - int state; - int party_id; + char name[INSTANCE_NAME_LENGTH]; + enum instance_state state; + enum instance_mode mode; + int owner_id; unsigned int keep_limit; int keep_timer; unsigned int idle_limit; @@ -37,15 +51,17 @@ struct instance_data { extern int instance_start; extern struct instance_data instance_data[MAX_INSTANCE_DATA]; -int instance_create(int party_id, const char *name); -int instance_destroy(short instance_id); -int instance_enter(struct map_session_data *sd, const char *name); -int instance_enter_position(struct map_session_data *sd, const char *name, short x, short y); -int instance_reqinfo(struct map_session_data *sd, short instance_id); -int instance_addusers(short instance_id); -int instance_delusers(short instance_id); -int instance_mapname2mapid(const char *name, short instance_id); -int instance_addmap(short instance_id); +void instance_getsd(unsigned short instance_id, struct map_session_data **sd, enum send_target *target); + +int instance_create(int owner_id, const char *name, enum instance_mode mode); +int instance_destroy(unsigned short instance_id); +int instance_enter(struct map_session_data *sd, unsigned short instance_id, const char *name); +int instance_enter_position(struct map_session_data *sd, unsigned short instance_id, const char *name, short x, short y); +int instance_reqinfo(struct map_session_data *sd, unsigned short instance_id); +int instance_addusers(unsigned short instance_id); +int instance_delusers(unsigned short instance_id); +int instance_mapname2mapid(const char *name, unsigned short instance_id); +int instance_addmap(unsigned short instance_id); void instance_addnpc(struct instance_data *im); void instance_readdb(void); diff --git a/src/map/map.c b/src/map/map.c index f725629990..c6a630f4c0 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -2554,7 +2554,7 @@ bool map_addnpc(int16 m,struct npc_data *nd) /*========================================== * Add an instance map *------------------------------------------*/ -int map_addinstancemap(const char *name, int id) +int map_addinstancemap(const char *name, unsigned short instance_id) { int src_m = map_mapname2mapid(name); int dst_m = -1, i; @@ -2594,9 +2594,9 @@ int map_addinstancemap(const char *name, int id) // This also allows us to maintain complete independence with main map functions if((strchr(iname,'@') == NULL) && strlen(iname) > 8) { memmove(iname, iname+(strlen(iname)-9), strlen(iname)); - snprintf(map[dst_m].name, sizeof(map[dst_m].name),"%d#%s", id, iname); + snprintf(map[dst_m].name, sizeof(map[dst_m].name),"%hu#%s", instance_id, iname); } else - snprintf(map[dst_m].name, sizeof(map[dst_m].name),"%.3d%s", id, iname); + snprintf(map[dst_m].name, sizeof(map[dst_m].name),"%.3hu%s", instance_id, iname); map[dst_m].name[MAP_NAME_LENGTH-1] = '\0'; // Mimic questinfo @@ -2607,7 +2607,7 @@ int map_addinstancemap(const char *name, int id) } map[dst_m].m = dst_m; - map[dst_m].instance_id = id; + map[dst_m].instance_id = instance_id; map[dst_m].instance_src_map = src_m; map[dst_m].users = 0; diff --git a/src/map/map.h b/src/map/map.h index b60a67cd14..8f9cc830a0 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -689,7 +689,7 @@ struct map_data { } skill_damage; #endif // Instance Variables - int instance_id; + unsigned short instance_id; int instance_src_map; /* rAthena Local Chat */ @@ -800,8 +800,8 @@ void map_clearflooritem(struct block_list* bl); int map_addflooritem(struct item *item, int amount, int16 m, int16 x, int16 y, int first_charid, int second_charid, int third_charid, int flags, unsigned short mob_id); // instances -int map_addinstancemap(const char*,int); -int map_delinstancemap(int); +int map_addinstancemap(const char *name, unsigned short instance_id); +int map_delinstancemap(int m); // player to map session void map_addnickdb(int charid, const char* nick); diff --git a/src/map/party.c b/src/map/party.c index 1f3faeb35b..65e68a9baa 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -660,7 +660,7 @@ int party_broken(int party_id) return 0; if( p->instance_id ) { - instance_data[p->instance_id].party_id = 0; + instance_data[p->instance_id].owner_id = 0; instance_destroy( p->instance_id ); } diff --git a/src/map/party.h b/src/map/party.h index d727b61c1e..5ada7dca74 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -25,7 +25,7 @@ struct party_data { struct party party; struct party_member_data data[MAX_PARTY]; uint8 itemc; //For item distribution, position of last picker in party - unsigned int instance_id; + unsigned short instance_id; struct { unsigned monk : 1; //There's at least one monk in party? unsigned sg : 1; //There's at least one Star Gladiator in party? diff --git a/src/map/pc.c b/src/map/pc.c index 6d36949e32..f03d0c58b6 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -5285,10 +5285,21 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in sd->state.changemap = (sd->mapindex != mapindex); sd->state.warping = 1; - if(sd->status.party_id && map[sd->bl.m].instance_id && sd->state.changemap && !map[m].instance_id) { - struct party_data *p; - if((p = party_search(sd->status.party_id)) != NULL && p->instance_id ) + if(map[sd->bl.m].instance_id && sd->state.changemap && !map[m].instance_id) { + bool instance_found = false; + struct party_data *p = NULL; + struct guild *g = NULL; + + if (sd->instance_id) { + instance_delusers(sd->instance_id); + instance_found = true; + } + if (!instance_found && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id) { instance_delusers(p->instance_id); + instance_found = true; + } + if (!instance_found && sd->status.guild_id && (g = guild_search(sd->status.guild_id)) != NULL && g->instance_id) + instance_delusers(g->instance_id); } if( sd->state.changemap ) { // Misc map-changing settings int i; diff --git a/src/map/pc.h b/src/map/pc.h index 611cd7bf98..e155b466cf 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -679,6 +679,8 @@ struct map_session_data { short prizeStage; bool claimPrize; } roulette; + + unsigned short instance_id; }; struct eri *pc_sc_display_ers; /// Player's SC display table diff --git a/src/map/script.c b/src/map/script.c index 22d252bc41..cc103d25f5 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -295,7 +295,7 @@ struct { *------------------------------------------*/ const char* parse_subexpr(const char* p,int limit); int run_func(struct script_state *st); -int script_instancegetid(struct script_state *st); +unsigned short script_instancegetid(struct script_state *st); enum { MF_NOMEMO, //0 @@ -2593,7 +2593,7 @@ void get_val_(struct script_state* st, struct script_data* data, struct map_sess break; case '\'': { - int instance_id = script_instancegetid(st); + unsigned short instance_id = script_instancegetid(st); if( instance_id ) data->u.str = (char*)i64db_get(instance_data[instance_id].regs.vars,reference_getuid(data)); else { @@ -2651,7 +2651,7 @@ void get_val_(struct script_state* st, struct script_data* data, struct map_sess break; case '\'': { - int instance_id = script_instancegetid(st); + unsigned short instance_id = script_instancegetid(st); if( instance_id ) data->u.num = (int)i64db_iget(instance_data[instance_id].regs.vars,reference_getuid(data)); else { @@ -2867,7 +2867,7 @@ struct reg_db *script_array_src(struct script_state *st, struct map_session_data break; case '\'': // instance { - int instance_id = script_instancegetid(st); + unsigned short instance_id = script_instancegetid(st); if( instance_id ) { src = &instance_data[instance_id].regs; @@ -2981,7 +2981,7 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co return 1; case '\'': { - int instance_id = script_instancegetid(st); + unsigned short instance_id = script_instancegetid(st); if( instance_id ) { if( str[0] ) { i64db_put(instance_data[instance_id].regs.vars, num, aStrdup(str)); @@ -3044,7 +3044,7 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co return 1; case '\'': { - int instance_id = script_instancegetid(st); + unsigned short instance_id = script_instancegetid(st); if( instance_id ) { if( val != 0 ) { i64db_iput(instance_data[instance_id].regs.vars, num, val); @@ -18827,19 +18827,27 @@ BUILDIN_FUNC(bg_get_data) * Instancing System *------------------------------------------*/ //Returns an Instance ID -//Checks NPC first, then if player is attached we check party -int script_instancegetid(struct script_state* st) +//Checks NPC first, then if player is attached we check +unsigned short script_instancegetid(struct script_state* st) { - short instance_id = 0; - + unsigned short instance_id = 0; struct npc_data *nd; + if( (nd = map_id2nd(st->oid)) && nd->instance_id > 0 ) instance_id = nd->instance_id; else { - struct map_session_data *sd; - struct party_data *p; - if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) - instance_id = p->instance_id; + struct map_session_data *sd = NULL; + struct party_data *p = NULL; + struct guild *g = NULL; + + if ((sd = script_rid2sd(st)) != NULL) { + if (sd->instance_id) + instance_id = sd->instance_id; + if (instance_id == 0 && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id) + instance_id = p->instance_id; + if (instance_id == 0 && sd->status.guild_id && (g = guild_search(sd->status.guild_id)) != NULL && g->instance_id) + instance_id = g->instance_id; + } } return instance_id; @@ -18851,12 +18859,20 @@ int script_instancegetid(struct script_state* st) *------------------------------------------*/ BUILDIN_FUNC(instance_create) { - struct map_session_data *sd; + enum instance_mode mode = IM_PARTY; + int owner_id; - if((sd = script_rid2sd(st)) == NULL) - return -1; + owner_id = script_getnum(st, 3); + if (script_hasdata(st, 4)) { + mode = script_getnum(st, 4); - script_pushint(st,instance_create(sd->status.party_id, script_getstr(st, 2))); + if (mode < IM_NONE || mode >= IM_MAX) { + ShowError("buildin_instance_create: Unknown instance owner type %d for '%s'\n", mode, script_getstr(st, 2)); + return SCRIPT_CMD_FAILURE; + } + } + + script_pushint(st, instance_create(owner_id, script_getstr(st, 2), mode)); return SCRIPT_CMD_SUCCESS; } @@ -18868,7 +18884,7 @@ BUILDIN_FUNC(instance_create) *------------------------------------------*/ BUILDIN_FUNC(instance_destroy) { - short instance_id; + unsigned short instance_id; if( script_hasdata(st,2) ) instance_id = script_getnum(st,2); @@ -18876,7 +18892,7 @@ BUILDIN_FUNC(instance_destroy) instance_id = script_instancegetid(st); if( instance_id <= 0 || instance_id >= MAX_MAP_PER_SERVER ) { - ShowError("script:instance_destroy: Trying to destroy invalid instance %d.\n", instance_id); + ShowError("buildin_instance_destroy: Trying to destroy invalid instance %d.\n", instance_id); return SCRIPT_CMD_SUCCESS; } @@ -18888,9 +18904,9 @@ BUILDIN_FUNC(instance_destroy) * Warps player to instance * Results: * 0: Success - * 1: Character not in party - * 2: Party doesn't have instance - * 3: Other errors (instance not in DB, instance doesn't match with party, etc.) + * 1: Character not in party/guild (for party/guild type instances) + * 2: Character/Party/Guild doesn't have instance + * 3: Other errors (instance not in DB, instance doesn't match with character/party/guild, etc.) *------------------------------------------*/ BUILDIN_FUNC(instance_enter) { @@ -18902,9 +18918,9 @@ BUILDIN_FUNC(instance_enter) return SCRIPT_CMD_FAILURE; if (x != -1 && y != -1) - script_pushint(st,instance_enter_position(sd,script_getstr(st, 2),x,y)); + script_pushint(st, instance_enter_position(sd, script_instancegetid(st), script_getstr(st, 2), x, y)); else - script_pushint(st,instance_enter(sd,script_getstr(st, 2))); + script_pushint(st, instance_enter(sd, script_instancegetid(st), script_getstr(st, 2))); return SCRIPT_CMD_SUCCESS; } @@ -18918,8 +18934,7 @@ BUILDIN_FUNC(instance_enter) BUILDIN_FUNC(instance_npcname) { const char *str; - short instance_id = 0; - + unsigned short instance_id = 0; struct npc_data *nd; str = script_getstr(st,2); @@ -18933,7 +18948,7 @@ BUILDIN_FUNC(instance_npcname) snprintf(npcname, sizeof(npcname), "dup_%d_%d", instance_id, nd->bl.id); script_pushconststr(st,npcname); } else { - ShowError("script:instance_npcname: invalid instance NPC (instance_id: %d, NPC name: \"%s\".)\n", instance_id, str); + ShowError("buildin_instance_npcname: Invalid instance NPC (instance_id: %d, NPC name: \"%s\".)\n", instance_id, str); st->state = END; return SCRIPT_CMD_FAILURE; } @@ -18950,7 +18965,7 @@ BUILDIN_FUNC(instance_mapname) { const char *str; int16 m; - short instance_id = 0; + unsigned short instance_id = 0; str = script_getstr(st,2); @@ -18973,12 +18988,12 @@ BUILDIN_FUNC(instance_mapname) *------------------------------------------*/ BUILDIN_FUNC(instance_id) { - short instance_id; + unsigned short instance_id; instance_id = script_instancegetid(st); if(!instance_id) { - //ShowError("script:instance_id: No instance attached to NPC or player"); + //ShowError("buildin_instance_id: No instance attached to NPC or player"); script_pushint(st, 0); return SCRIPT_CMD_SUCCESS; } @@ -18991,11 +19006,29 @@ BUILDIN_FUNC(instance_id) * * instance_warpall ,,{,}; *------------------------------------------*/ +static int buildin_instance_warpall_sub(struct block_list *bl, va_list ap) +{ + unsigned int m = va_arg(ap,unsigned int); + int x = va_arg(ap,int); + int y = va_arg(ap,int); + + nullpo_retr(0, bl); + + if (bl->type != BL_PC) + return 0; + + pc_setpos((TBL_PC *)bl, m, x, y, CLR_TELEPORT); + + return 0; +} + BUILDIN_FUNC(instance_warpall) { - struct party_data *p; + struct map_session_data *sd = NULL; + struct party_data *p = NULL; + struct guild *g = NULL; int16 m, i; - short instance_id; + unsigned short instance_id; const char *mapn; int x, y; @@ -19008,16 +19041,30 @@ BUILDIN_FUNC(instance_warpall) instance_id = script_instancegetid(st); if( !instance_id || (m = map_mapname2mapid(mapn)) < 0 || (m = instance_mapname2mapid(map[m].name,instance_id)) < 0) - return SCRIPT_CMD_SUCCESS; + return SCRIPT_CMD_FAILURE; - if( !(p = party_search(instance_data[instance_id].party_id)) ) - return SCRIPT_CMD_SUCCESS; - - for( i = 0; i < MAX_PARTY; i++ ) { - struct map_session_data *pl_sd; - if( (pl_sd = p->data[i].sd) && map[pl_sd->bl.m].instance_id == instance_id ) pc_setpos(pl_sd,map_id2index(m),x,y,CLR_TELEPORT); + switch(instance_data[instance_id].mode) { + case IM_NONE: + break; + case IM_CHAR: + if (!(sd = map_id2sd(instance_data[instance_id].owner_id))) + return SCRIPT_CMD_FAILURE; + break; + case IM_PARTY: + if (!(p = party_search(instance_data[instance_id].owner_id))) + return SCRIPT_CMD_FAILURE; + break; + case IM_GUILD: + if (!(g = guild_search(instance_data[instance_id].owner_id))) + return SCRIPT_CMD_FAILURE; + default: + ShowError("buildin_instance_warpall: Invalid instance owner type (instance_id: %d)\n", instance_id); + break; } + for(i = 0; i < instance_data[instance_id].cnt_map; i++) + map_foreachinmap(buildin_instance_warpall_sub, instance_data[instance_id].map[i].m, BL_PC, map_id2index(m), x, y); + return SCRIPT_CMD_SUCCESS; } @@ -19028,15 +19075,14 @@ BUILDIN_FUNC(instance_warpall) * Using -1 for will auto-detect the id. *------------------------------------------*/ BUILDIN_FUNC(instance_announce) { - int instance_id = script_getnum(st,2); - const char *mes = script_getstr(st,3); - int flag = script_getnum(st,4); - const char *fontColor = script_hasdata(st,5) ? script_getstr(st,5) : NULL; - int fontType = script_hasdata(st,6) ? script_getnum(st,6) : FW_NORMAL; // default fontType - int fontSize = script_hasdata(st,7) ? script_getnum(st,7) : 12; // default fontSize - int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign - int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY - + unsigned short instance_id = script_getnum(st,2); + const char *mes = script_getstr(st,3); + int flag = script_getnum(st,4); + const char *fontColor = script_hasdata(st,5) ? script_getstr(st,5) : NULL; + int fontType = script_hasdata(st,6) ? script_getnum(st,6) : FW_NORMAL; // default fontType + int fontSize = script_hasdata(st,7) ? script_getnum(st,7) : 12; // default fontSize + int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign + int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY int i; if( instance_id == -1 ) { @@ -19114,6 +19160,68 @@ BUILDIN_FUNC(instance_check_party) return SCRIPT_CMD_SUCCESS; } +/*========================================== + * instance_check_guild + * Values: + * guild_id : Guild ID of the invoking character. [Required Parameter] + * amount : Amount of needed Guild members for the Instance. [Optional Parameter] + * min : Minimum Level needed to join the Instance. [Optional Parameter] + * max : Maxium Level allowed to join the Instance. [Optional Parameter] + * Example: instance_check_guild (getcharid(2){,amount}{,min}{,max}); + * Example 2: instance_check_guild (getcharid(2),1,1,99); + *------------------------------------------*/ +BUILDIN_FUNC(instance_check_guild) +{ + int amount, min, max, i, guild_id, c = 0; + struct guild *g = NULL; + + amount = script_hasdata(st,3) ? script_getnum(st,3) : 1; // Amount of needed Guild members for the Instance. + min = script_hasdata(st,4) ? script_getnum(st,4) : 1; // Minimum Level needed to join the Instance. + max = script_hasdata(st,5) ? script_getnum(st,5) : MAX_LEVEL; // Maxium Level allowed to join the Instance. + + if (min < 1 || min > MAX_LEVEL) { + ShowError("buildin_instance_check_guild: Invalid min level, %d\n", min); + return SCRIPT_CMD_FAILURE; + } else if (max < 1 || max > MAX_LEVEL) { + ShowError("buildin_instance_check_guild: Invalid max level, %d\n", max); + return SCRIPT_CMD_FAILURE; + } + + if (script_hasdata(st,2)) + guild_id = script_getnum(st,2); + else + return SCRIPT_CMD_SUCCESS; + + if (!(g = guild_search(guild_id))) { + script_pushint(st, 0); // Returns false if guild does not exist. + return SCRIPT_CMD_SUCCESS; + } + + for(i = 0; i < MAX_GUILD; i++) { + struct map_session_data *pl_sd; + + if ((pl_sd = g->member[i].sd)) { + if (map_id2bl(pl_sd->bl.id)) { + if (pl_sd->status.base_level < min) { + script_pushint(st, 0); + return SCRIPT_CMD_SUCCESS; + } else if (pl_sd->status.base_level > max) { + script_pushint(st, 0); + return SCRIPT_CMD_SUCCESS; + } + c++; + } + } + } + + if (c < amount) + script_pushint(st, 0); // Not enough Members in the Guild to join Instance. + else + script_pushint(st, 1); + + return SCRIPT_CMD_SUCCESS; +} + /*========================================== * Custom Fonts *------------------------------------------*/ @@ -21783,7 +21891,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(bg_updatescore,"sii"), // Instancing - BUILDIN_DEF(instance_create,"s"), + BUILDIN_DEF(instance_create,"si?"), BUILDIN_DEF(instance_destroy,"?"), BUILDIN_DEF(instance_id,""), BUILDIN_DEF(instance_enter,"s???"), @@ -21792,6 +21900,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(instance_warpall,"sii?"), BUILDIN_DEF(instance_announce,"isi?????"), BUILDIN_DEF(instance_check_party,"i???"), + BUILDIN_DEF(instance_check_guild,"i???"), /** * 3rd-related **/ diff --git a/src/map/script_constants.h b/src/map/script_constants.h index 63592d03cc..12b01cfc0c 100644 --- a/src/map/script_constants.h +++ b/src/map/script_constants.h @@ -3062,6 +3062,12 @@ export_constant(DIR_EAST); export_constant(DIR_NORTHEAST); + /* instance modes */ + export_constant(IM_NONE); + export_constant(IM_CHAR); + export_constant(IM_PARTY); + export_constant(IM_GUILD); + #undef export_constant #endif /* _SCRIPT_CONSTANTS_H_ */ From 8f7d2208a972d2bee603364a6069bf1e8127e59d Mon Sep 17 00:00:00 2001 From: aleos89 Date: Sat, 14 May 2016 12:01:22 -0400 Subject: [PATCH 02/10] Adjusted instance scripts to new format * Follow up to c97be60. * Adjusted script command instance_create to include owner ID. --- npc/instances/EndlessTower.txt | 2 +- npc/instances/NydhoggsNest.txt | 2 +- npc/instances/OrcsMemory.txt | 2 +- npc/instances/SealedShrine.txt | 2 +- npc/re/instances/BakonawaLake.txt | 2 +- npc/re/instances/BangungotHospital.txt | 2 +- npc/re/instances/BuwayaCave.txt | 2 +- npc/re/instances/EclageInterior.txt | 2 +- npc/re/instances/HazyForest.txt | 2 +- npc/re/instances/MalangdoCulvert.txt | 2 +- npc/re/instances/OctopusCave.txt | 2 +- npc/re/instances/OldGlastHeim.txt | 2 +- npc/re/instances/WolfchevLaboratory.txt | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/npc/instances/EndlessTower.txt b/npc/instances/EndlessTower.txt index 756690c9dc..9c91cd4f6d 100644 --- a/npc/instances/EndlessTower.txt +++ b/npc/instances/EndlessTower.txt @@ -220,7 +220,7 @@ e_tower,81,105,0 script Tower Protection Stone 406,{ next; switch(select("Generate dungeon "+.@md_name$+":Enter the dungeon:Return to Alberta:Cancel")) { case 1: - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "Party Name: "+ getpartyname(.@party_id); mes "Party Leader: "+strcharinfo(0); mes "^0000ff"+.@md_name$+" ^000000- Reservation Failed!"; diff --git a/npc/instances/NydhoggsNest.txt b/npc/instances/NydhoggsNest.txt index ced58fceb1..21924057c1 100644 --- a/npc/instances/NydhoggsNest.txt +++ b/npc/instances/NydhoggsNest.txt @@ -114,7 +114,7 @@ nyd_dun02,100,201,3 script Yggdrasil Gatekeeper 111,8,8,{ next; switch(select("Please allow me to enter.:I want to go in.:I want to leave.")) { case 1: - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "[Yggdrasil Gatekeeper]"; mes "The Guardian seems to wish to be alone. I will go in and check, please wait out here."; close; diff --git a/npc/instances/OrcsMemory.txt b/npc/instances/OrcsMemory.txt index 6965be8b1c..976d32ee76 100644 --- a/npc/instances/OrcsMemory.txt +++ b/npc/instances/OrcsMemory.txt @@ -52,7 +52,7 @@ gef_fild10,242,202,0 script Dimensional Gorge Piece 406,{ next; switch(select("Reserve the "+.@md_name$+":Enter the Dungeon:Cancel")) { case 1: - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "Party Name: "+ getpartyname(.@party_id); mes "Party Leader: "+strcharinfo(0); mes "^0000ff"+.@md_name$+" ^000000 - Reservation Failed."; diff --git a/npc/instances/SealedShrine.txt b/npc/instances/SealedShrine.txt index 2734a5f228..785095cb00 100644 --- a/npc/instances/SealedShrine.txt +++ b/npc/instances/SealedShrine.txt @@ -113,7 +113,7 @@ monk_test,309,146,3 script Friar Patrick#edq 412,{ mes "[Friar Patrick]"; mes "Party name is "+getpartyname(.@party_id)+"..."; mes "Name of the leader is "+strcharinfo(0)+"..."; - if (instance_create("Sealed Catacomb") < 0) { + if (instance_create("Sealed Catacomb", .@party_id) < 0) { mes "Umm... But it seems that there is a problem here... I'll check quickly. Please wait."; } else { diff --git a/npc/re/instances/BakonawaLake.txt b/npc/re/instances/BakonawaLake.txt index 39ec9f5dfb..64cd02bafd 100644 --- a/npc/re/instances/BakonawaLake.txt +++ b/npc/re/instances/BakonawaLake.txt @@ -65,7 +65,7 @@ ma_scene01,174,179,4 script Taho 541,{ } switch(.@i) { case 1: - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "[Taho]"; mes "Oh, the rope got dropped. I have to make a new one."; close; diff --git a/npc/re/instances/BangungotHospital.txt b/npc/re/instances/BangungotHospital.txt index a9127bd417..3546149414 100644 --- a/npc/re/instances/BangungotHospital.txt +++ b/npc/re/instances/BangungotHospital.txt @@ -258,7 +258,7 @@ L_Enter: next; switch(select(((getarg(0))?"Prepare to enter the second floor.":"")+":Enter the second floor.:Do not enter.")) { case 1: - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "[Nurse Maenne]"; mes "A critical situation has happened."; mes "You can't go up to the 2nd floor."; diff --git a/npc/re/instances/BuwayaCave.txt b/npc/re/instances/BuwayaCave.txt index f6c3618ce4..d348bbb217 100644 --- a/npc/re/instances/BuwayaCave.txt +++ b/npc/re/instances/BuwayaCave.txt @@ -75,7 +75,7 @@ ma_fild02,312,317,5 script Guard#buwaya_cave 570,{ erasequest 4229; // fall through } - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "[Guard]"; mes "Party name is... "+getpartyname(.@party_id)+".";; mes "Party leader is... "+strcharinfo(0); diff --git a/npc/re/instances/EclageInterior.txt b/npc/re/instances/EclageInterior.txt index 61dbc7debd..aaaca316be 100644 --- a/npc/re/instances/EclageInterior.txt +++ b/npc/re/instances/EclageInterior.txt @@ -31,7 +31,7 @@ ecl_hub01,132,12,3 script Chief of Staff#tl02 435,{ next; switch (select("Enter it.:Forget it.")) { case 1: - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "[Shenime]"; mes "There are some soldiers dispatched by Mayor not too long ago."; mes "I should sure hope that you aren't the disturbance they're looking for, right?"; diff --git a/npc/re/instances/HazyForest.txt b/npc/re/instances/HazyForest.txt index cdf6670e57..437b25fdb4 100644 --- a/npc/re/instances/HazyForest.txt +++ b/npc/re/instances/HazyForest.txt @@ -83,7 +83,7 @@ bif_fild01,158,340,5 script Laphine Soldier#mist 447,{ mes "[Laphine Soldier]"; mes "Party Name "+getpartyname(.@party_id)+"..."; mes "Party Leader "+strcharinfo(0)+"..."; - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "Hmm..."; next; mes "[Laphine Soldier]"; diff --git a/npc/re/instances/MalangdoCulvert.txt b/npc/re/instances/MalangdoCulvert.txt index 264467a951..12c1cbf9fa 100644 --- a/npc/re/instances/MalangdoCulvert.txt +++ b/npc/re/instances/MalangdoCulvert.txt @@ -402,7 +402,7 @@ mal_in01,160,34,4 script Missing, the Cleaner 545,{ mes "What a rookie."; close; case 2: - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "Party name: "+getpartyname(.@party_id); mes "Party leader: "+strcharinfo(0); mes "^0000ff"+.@md_name$+"^000000 - Reservation Failed!"; diff --git a/npc/re/instances/OctopusCave.txt b/npc/re/instances/OctopusCave.txt index affbcf639c..50ef1b5e18 100644 --- a/npc/re/instances/OctopusCave.txt +++ b/npc/re/instances/OctopusCave.txt @@ -84,7 +84,7 @@ mal_dun01,151,235,5 script Starfish 551,{ } if (.@playtime == 2) erasequest 4197; if (countitem(6442)) { - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "[Starfish]"; mes "Party name is... "+getpartyname(.@party_id)+"."; mes "Party leader is... "+strcharinfo(0)+"."; diff --git a/npc/re/instances/OldGlastHeim.txt b/npc/re/instances/OldGlastHeim.txt index 73def91209..ae8aedbdfe 100644 --- a/npc/re/instances/OldGlastHeim.txt +++ b/npc/re/instances/OldGlastHeim.txt @@ -41,7 +41,7 @@ glast_01,204,273,6 script Hugin#ghinstance 755,{ set .@menu$, ":Enter the Old Glast Heim.:Cancel."; switch(select(.@menu$)) { case 1: - if (instance_create(.@md_name$) < 0) { + if (instance_create(.@md_name$, .@party_id) < 0) { mes "Party Name: "+.@p_name$; mes "Party Leader: "+strcharinfo(0); mes "^0000ff"+.@md_name$+" ^000000- Reservation Failed!"; diff --git a/npc/re/instances/WolfchevLaboratory.txt b/npc/re/instances/WolfchevLaboratory.txt index a814f6146e..50c453c15b 100644 --- a/npc/re/instances/WolfchevLaboratory.txt +++ b/npc/re/instances/WolfchevLaboratory.txt @@ -819,7 +819,7 @@ lhz_dun04,151,276,3 script Researcher#memo 4_LGTSCIENCE,{ } } if (getpartyleader(getcharid(1),2) == getcharid(0)) { - if (instance_create("Wolfchev's Laboratory") < 0) { + if (instance_create("Wolfchev's Laboratory", getcharid(1)) < 0) { mes "[Wolfchev]"; mes "Hmm.. Lab entering system is a bit weird. Would wait for me to check the system?"; close; From cb703c5bfafa8c1ef2a2dbeb5428c2df03e389f4 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Sat, 14 May 2016 12:06:04 -0400 Subject: [PATCH 03/10] Expanded instance_db to include idle time * Follow up to c97be60. * Adjusted the instance_db to allow instance idle time to be adjustable. --- db/import-tmpl/instance_db.txt | 2 +- db/pre-re/instance_db.txt | 10 +++++----- db/re/instance_db.txt | 28 ++++++++++++++-------------- src/map/instance.c | 9 ++++----- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/db/import-tmpl/instance_db.txt b/db/import-tmpl/instance_db.txt index cd085a2c4c..929f270f3b 100644 --- a/db/import-tmpl/instance_db.txt +++ b/db/import-tmpl/instance_db.txt @@ -1,5 +1,5 @@ // Instance Database // // Structure of Database: -// ID,Name,LimitTime,EnterMap,EnterX,EnterY,Map1,Map2,Map3,Map4,Map5,Map6,Map7,Map8 +// ID,Name,LimitTime,IdleTimeout,EnterMap,EnterX,EnterY,Map1,Map2,Map3,Map4,Map5,Map6,Map7,Map8 diff --git a/db/pre-re/instance_db.txt b/db/pre-re/instance_db.txt index 91937eb1de..912ce9a14b 100644 --- a/db/pre-re/instance_db.txt +++ b/db/pre-re/instance_db.txt @@ -1,9 +1,9 @@ // Instance Database // // Structure of Database: -// ID,Name,LimitTime,EnterMap,EnterX,EnterY,Map1,Map2,Map3,Map4,Map5,Map6,Map7,Map8 +// ID,Name,LimitTime,IdleTimeout,EnterMap,EnterX,EnterY,Map1,Map2,Map3,Map4,Map5,Map6,Map7,Map8 -1,Endless Tower,14400,1@tower,50,355,1@tower,2@tower,3@tower,4@tower,5@tower,6@tower -2,Sealed Catacomb,7200,1@cata,100,224,1@cata,2@cata -3,Orc's Memory,3600,1@orcs,179,15,1@orcs,2@orcs -4,Nidhoggur's Nest,14400,1@nyd,32,36,1@nyd,2@nyd +1,Endless Tower,14400,300,1@tower,50,355,1@tower,2@tower,3@tower,4@tower,5@tower,6@tower +2,Sealed Catacomb,7200,300,1@cata,100,224,1@cata,2@cata +3,Orc's Memory,3600,300,1@orcs,179,15,1@orcs,2@orcs +4,Nidhoggur's Nest,14400,300,1@nyd,32,36,1@nyd,2@nyd diff --git a/db/re/instance_db.txt b/db/re/instance_db.txt index 1c3df13f10..417ae9071c 100644 --- a/db/re/instance_db.txt +++ b/db/re/instance_db.txt @@ -1,18 +1,18 @@ // Instance Database // // Structure of Database: -// ID,Name,LimitTime,EnterMap,EnterX,EnterY,Map1,Map2,Map3,Map4,Map5,Map6,Map7,Map8 +// ID,Name,LimitTime,IdleTime,EnterMap,EnterX,EnterY,Map1,Map2,Map3,Map4,Map5,Map6,Map7,Map8 -1,Endless Tower,14400,1@tower,50,355,1@tower,2@tower,3@tower,4@tower,5@tower,6@tower -2,Sealed Catacomb,7200,1@cata,100,224,1@cata,2@cata -3,Orc's Memory,3600,1@orcs,179,15,1@orcs,2@orcs -4,Nidhoggur's Nest,14400,1@nyd,32,36,1@nyd,2@nyd -5,Mistwood Maze,7200,1@mist,89,29,1@mist -6,Culvert,3600,1@pump,63,98,1@pump,2@pump -7,Octopus Cave,3600,1@cash,199,99,1@cash -8,Bangungot Hospital 2F,3600,1@ma_h,40,157,1@ma_h -9,Buwaya Cave,3600,1@ma_c,35,57,1@ma_c -10,Bakonawa Lake,7200,1@ma_b,64,51,1@ma_b -11,Wolfchev's Laboratory,14400,1@lhz,45,148,1@lhz -12,Old Glast Heim,3600,1@gl_k,150,20,1@gl_k,2@gl_k -13,Eclage Interior,1200,1@ecl,60,50,1@ecl +1,Endless Tower,14400,300,1@tower,50,355,1@tower,2@tower,3@tower,4@tower,5@tower,6@tower +2,Sealed Catacomb,7200,300,1@cata,100,224,1@cata,2@cata +3,Orc's Memory,3600,300,1@orcs,179,15,1@orcs,2@orcs +4,Nidhoggur's Nest,14400,300,1@nyd,32,36,1@nyd,2@nyd +5,Mistwood Maze,7200,300,1@mist,89,29,1@mist +6,Culvert,3600,300,1@pump,63,98,1@pump,2@pump +7,Octopus Cave,3600,300,1@cash,199,99,1@cash +8,Bangungot Hospital 2F,3600,300,1@ma_h,40,157,1@ma_h +9,Buwaya Cave,3600,300,1@ma_c,35,57,1@ma_c +10,Bakonawa Lake,7200,300,1@ma_b,64,51,1@ma_b +11,Wolfchev's Laboratory,14400,300,1@lhz,45,148,1@lhz +12,Old Glast Heim,3600,300,1@gl_k,150,20,1@gl_k,2@gl_k +13,Eclage Interior,1200,300,1@ecl,60,50,1@ecl diff --git a/src/map/instance.c b/src/map/instance.c index 1fa43f41dd..13d375af3d 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -21,7 +21,6 @@ #include #define INSTANCE_INTERVAL 60000 // Interval used to check when an instance is to be destroyed (ms) -#define INSTANCE_LIMIT 300000 // Idle timer before instance is destroyed (ms) : 5 Minute Default int instance_start = 0; // To keep the last index + 1 of normal map inserted in the map[ARRAY] @@ -227,8 +226,8 @@ static int instance_startidletimer(struct instance_data *im, unsigned short inst return 1; // Add the timer - im->idle_limit = (unsigned int)time(NULL) + INSTANCE_LIMIT/1000; - im->idle_timer = add_timer(gettick()+INSTANCE_LIMIT, instance_delete_timer, instance_id, 0); + im->idle_limit = (unsigned int)time(NULL) + db->timeout; + im->idle_timer = add_timer(gettick() + db->timeout * 1000, instance_delete_timer, instance_id, 0); switch(im->mode) { case IM_NONE: @@ -446,8 +445,8 @@ int instance_addmap(unsigned short instance_id) // Set to busy, update timers im->state = INSTANCE_BUSY; - im->idle_limit = (unsigned int)time(NULL) + INSTANCE_LIMIT/1000; - im->idle_timer = add_timer(gettick()+INSTANCE_LIMIT, instance_delete_timer, instance_id, 0); + im->idle_limit = (unsigned int)time(NULL) + db->timeout; + im->idle_timer = add_timer(gettick() + db->timeout * 1000, instance_delete_timer, instance_id, 0); // Add the maps for(i = 0; i < db->maplist_count; i++) { From 9c89b0e06ec06273b5cae730a15e2dc0d4b1bb16 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Mon, 23 May 2016 12:56:11 -0400 Subject: [PATCH 04/10] Revert "Adjusted instance scripts to new format" This reverts commit 8f7d2208a972d2bee603364a6069bf1e8127e59d. --- npc/instances/EndlessTower.txt | 2 +- npc/instances/NydhoggsNest.txt | 2 +- npc/instances/OrcsMemory.txt | 2 +- npc/instances/SealedShrine.txt | 2 +- npc/re/instances/BakonawaLake.txt | 2 +- npc/re/instances/BangungotHospital.txt | 2 +- npc/re/instances/BuwayaCave.txt | 2 +- npc/re/instances/EclageInterior.txt | 2 +- npc/re/instances/HazyForest.txt | 2 +- npc/re/instances/MalangdoCulvert.txt | 2 +- npc/re/instances/OctopusCave.txt | 2 +- npc/re/instances/OldGlastHeim.txt | 2 +- npc/re/instances/WolfchevLaboratory.txt | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/npc/instances/EndlessTower.txt b/npc/instances/EndlessTower.txt index 9c91cd4f6d..756690c9dc 100644 --- a/npc/instances/EndlessTower.txt +++ b/npc/instances/EndlessTower.txt @@ -220,7 +220,7 @@ e_tower,81,105,0 script Tower Protection Stone 406,{ next; switch(select("Generate dungeon "+.@md_name$+":Enter the dungeon:Return to Alberta:Cancel")) { case 1: - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "Party Name: "+ getpartyname(.@party_id); mes "Party Leader: "+strcharinfo(0); mes "^0000ff"+.@md_name$+" ^000000- Reservation Failed!"; diff --git a/npc/instances/NydhoggsNest.txt b/npc/instances/NydhoggsNest.txt index 21924057c1..ced58fceb1 100644 --- a/npc/instances/NydhoggsNest.txt +++ b/npc/instances/NydhoggsNest.txt @@ -114,7 +114,7 @@ nyd_dun02,100,201,3 script Yggdrasil Gatekeeper 111,8,8,{ next; switch(select("Please allow me to enter.:I want to go in.:I want to leave.")) { case 1: - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "[Yggdrasil Gatekeeper]"; mes "The Guardian seems to wish to be alone. I will go in and check, please wait out here."; close; diff --git a/npc/instances/OrcsMemory.txt b/npc/instances/OrcsMemory.txt index 976d32ee76..6965be8b1c 100644 --- a/npc/instances/OrcsMemory.txt +++ b/npc/instances/OrcsMemory.txt @@ -52,7 +52,7 @@ gef_fild10,242,202,0 script Dimensional Gorge Piece 406,{ next; switch(select("Reserve the "+.@md_name$+":Enter the Dungeon:Cancel")) { case 1: - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "Party Name: "+ getpartyname(.@party_id); mes "Party Leader: "+strcharinfo(0); mes "^0000ff"+.@md_name$+" ^000000 - Reservation Failed."; diff --git a/npc/instances/SealedShrine.txt b/npc/instances/SealedShrine.txt index 785095cb00..2734a5f228 100644 --- a/npc/instances/SealedShrine.txt +++ b/npc/instances/SealedShrine.txt @@ -113,7 +113,7 @@ monk_test,309,146,3 script Friar Patrick#edq 412,{ mes "[Friar Patrick]"; mes "Party name is "+getpartyname(.@party_id)+"..."; mes "Name of the leader is "+strcharinfo(0)+"..."; - if (instance_create("Sealed Catacomb", .@party_id) < 0) { + if (instance_create("Sealed Catacomb") < 0) { mes "Umm... But it seems that there is a problem here... I'll check quickly. Please wait."; } else { diff --git a/npc/re/instances/BakonawaLake.txt b/npc/re/instances/BakonawaLake.txt index 64cd02bafd..39ec9f5dfb 100644 --- a/npc/re/instances/BakonawaLake.txt +++ b/npc/re/instances/BakonawaLake.txt @@ -65,7 +65,7 @@ ma_scene01,174,179,4 script Taho 541,{ } switch(.@i) { case 1: - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "[Taho]"; mes "Oh, the rope got dropped. I have to make a new one."; close; diff --git a/npc/re/instances/BangungotHospital.txt b/npc/re/instances/BangungotHospital.txt index 3546149414..a9127bd417 100644 --- a/npc/re/instances/BangungotHospital.txt +++ b/npc/re/instances/BangungotHospital.txt @@ -258,7 +258,7 @@ L_Enter: next; switch(select(((getarg(0))?"Prepare to enter the second floor.":"")+":Enter the second floor.:Do not enter.")) { case 1: - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "[Nurse Maenne]"; mes "A critical situation has happened."; mes "You can't go up to the 2nd floor."; diff --git a/npc/re/instances/BuwayaCave.txt b/npc/re/instances/BuwayaCave.txt index d348bbb217..f6c3618ce4 100644 --- a/npc/re/instances/BuwayaCave.txt +++ b/npc/re/instances/BuwayaCave.txt @@ -75,7 +75,7 @@ ma_fild02,312,317,5 script Guard#buwaya_cave 570,{ erasequest 4229; // fall through } - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "[Guard]"; mes "Party name is... "+getpartyname(.@party_id)+".";; mes "Party leader is... "+strcharinfo(0); diff --git a/npc/re/instances/EclageInterior.txt b/npc/re/instances/EclageInterior.txt index aaaca316be..61dbc7debd 100644 --- a/npc/re/instances/EclageInterior.txt +++ b/npc/re/instances/EclageInterior.txt @@ -31,7 +31,7 @@ ecl_hub01,132,12,3 script Chief of Staff#tl02 435,{ next; switch (select("Enter it.:Forget it.")) { case 1: - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "[Shenime]"; mes "There are some soldiers dispatched by Mayor not too long ago."; mes "I should sure hope that you aren't the disturbance they're looking for, right?"; diff --git a/npc/re/instances/HazyForest.txt b/npc/re/instances/HazyForest.txt index 437b25fdb4..cdf6670e57 100644 --- a/npc/re/instances/HazyForest.txt +++ b/npc/re/instances/HazyForest.txt @@ -83,7 +83,7 @@ bif_fild01,158,340,5 script Laphine Soldier#mist 447,{ mes "[Laphine Soldier]"; mes "Party Name "+getpartyname(.@party_id)+"..."; mes "Party Leader "+strcharinfo(0)+"..."; - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "Hmm..."; next; mes "[Laphine Soldier]"; diff --git a/npc/re/instances/MalangdoCulvert.txt b/npc/re/instances/MalangdoCulvert.txt index 12c1cbf9fa..264467a951 100644 --- a/npc/re/instances/MalangdoCulvert.txt +++ b/npc/re/instances/MalangdoCulvert.txt @@ -402,7 +402,7 @@ mal_in01,160,34,4 script Missing, the Cleaner 545,{ mes "What a rookie."; close; case 2: - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "Party name: "+getpartyname(.@party_id); mes "Party leader: "+strcharinfo(0); mes "^0000ff"+.@md_name$+"^000000 - Reservation Failed!"; diff --git a/npc/re/instances/OctopusCave.txt b/npc/re/instances/OctopusCave.txt index 50ef1b5e18..affbcf639c 100644 --- a/npc/re/instances/OctopusCave.txt +++ b/npc/re/instances/OctopusCave.txt @@ -84,7 +84,7 @@ mal_dun01,151,235,5 script Starfish 551,{ } if (.@playtime == 2) erasequest 4197; if (countitem(6442)) { - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "[Starfish]"; mes "Party name is... "+getpartyname(.@party_id)+"."; mes "Party leader is... "+strcharinfo(0)+"."; diff --git a/npc/re/instances/OldGlastHeim.txt b/npc/re/instances/OldGlastHeim.txt index ae8aedbdfe..73def91209 100644 --- a/npc/re/instances/OldGlastHeim.txt +++ b/npc/re/instances/OldGlastHeim.txt @@ -41,7 +41,7 @@ glast_01,204,273,6 script Hugin#ghinstance 755,{ set .@menu$, ":Enter the Old Glast Heim.:Cancel."; switch(select(.@menu$)) { case 1: - if (instance_create(.@md_name$, .@party_id) < 0) { + if (instance_create(.@md_name$) < 0) { mes "Party Name: "+.@p_name$; mes "Party Leader: "+strcharinfo(0); mes "^0000ff"+.@md_name$+" ^000000- Reservation Failed!"; diff --git a/npc/re/instances/WolfchevLaboratory.txt b/npc/re/instances/WolfchevLaboratory.txt index 50c453c15b..a814f6146e 100644 --- a/npc/re/instances/WolfchevLaboratory.txt +++ b/npc/re/instances/WolfchevLaboratory.txt @@ -819,7 +819,7 @@ lhz_dun04,151,276,3 script Researcher#memo 4_LGTSCIENCE,{ } } if (getpartyleader(getcharid(1),2) == getcharid(0)) { - if (instance_create("Wolfchev's Laboratory", getcharid(1)) < 0) { + if (instance_create("Wolfchev's Laboratory") < 0) { mes "[Wolfchev]"; mes "Hmm.. Lab entering system is a bit weird. Would wait for me to check the system?"; close; From 2cfb84442902661dd3b48a44023f5a70499025af Mon Sep 17 00:00:00 2001 From: aleos89 Date: Mon, 23 May 2016 14:12:34 -0400 Subject: [PATCH 05/10] Refactored a bit of the instance modes * Follow up to c97be60. * Added some safety measures when sending the instance name to the client. * Adjusted the stored maps of instances to dynamic arrays to conserve memory. - Max amount of possible maps increased to 255. * Removed Map1 from the instance_db as the EnterMap is always the same value. * Instances will now be destroyed even if the owner cannot be found. * Corrected the return value when entering an instance when a character, party, or guild does not have an instance. * Corrected a few script commands to properly stop the script engine on failures for instance script commands. * Removed the instance name lookup for when entering an instance as instance_id is now passed. - Adjusted script command instance_enter to no longer require the instance name. * Adjusted script command instance_create to keep backwards compatibility. * Cleaned up script command instance_warpall. * Updated script documentation to reflect changes. * Updated instance_db to reflect changes. --- db/import-tmpl/instance_db.txt | 5 +- db/pre-re/instance_db.txt | 12 ++- db/re/instance_db.txt | 30 +++--- doc/script_commands.txt | 34 +++---- src/map/clif.c | 8 +- src/map/instance.c | 169 ++++++++++++++------------------- src/map/instance.h | 49 ++++++---- src/map/map.c | 8 +- src/map/npc.c | 4 +- src/map/script.c | 121 ++++++++++++----------- 10 files changed, 223 insertions(+), 217 deletions(-) diff --git a/db/import-tmpl/instance_db.txt b/db/import-tmpl/instance_db.txt index 929f270f3b..eb33400dad 100644 --- a/db/import-tmpl/instance_db.txt +++ b/db/import-tmpl/instance_db.txt @@ -1,5 +1,6 @@ // Instance Database // // Structure of Database: -// ID,Name,LimitTime,IdleTimeout,EnterMap,EnterX,EnterY,Map1,Map2,Map3,Map4,Map5,Map6,Map7,Map8 - +// ID,Name,LimitTime,IdleTimeOut,EnterMap,EnterX,EnterY,Map2,Map3,Map4,Map5,Map6,Map7,Map8,Map9,Map10 +// +// EnterMap is considered as Map1 diff --git a/db/pre-re/instance_db.txt b/db/pre-re/instance_db.txt index 912ce9a14b..7501545263 100644 --- a/db/pre-re/instance_db.txt +++ b/db/pre-re/instance_db.txt @@ -1,9 +1,11 @@ // Instance Database // // Structure of Database: -// ID,Name,LimitTime,IdleTimeout,EnterMap,EnterX,EnterY,Map1,Map2,Map3,Map4,Map5,Map6,Map7,Map8 +// ID,Name,LimitTime,IdleTimeOut,EnterMap,EnterX,EnterY,Map2,Map3,Map4,Map5,Map6,Map7,Map8,Map9,Map10 +// +// EnterMap is considered as Map1 -1,Endless Tower,14400,300,1@tower,50,355,1@tower,2@tower,3@tower,4@tower,5@tower,6@tower -2,Sealed Catacomb,7200,300,1@cata,100,224,1@cata,2@cata -3,Orc's Memory,3600,300,1@orcs,179,15,1@orcs,2@orcs -4,Nidhoggur's Nest,14400,300,1@nyd,32,36,1@nyd,2@nyd +1,Endless Tower,14400,300,1@tower,50,355,2@tower,3@tower,4@tower,5@tower,6@tower +2,Sealed Catacomb,7200,300,1@cata,100,224,2@cata +3,Orc's Memory,3600,300,1@orcs,179,15,2@orcs +4,Nidhoggur's Nest,14400,300,1@nyd,32,36,2@nyd diff --git a/db/re/instance_db.txt b/db/re/instance_db.txt index 417ae9071c..8a1d10e712 100644 --- a/db/re/instance_db.txt +++ b/db/re/instance_db.txt @@ -1,18 +1,20 @@ // Instance Database // // Structure of Database: -// ID,Name,LimitTime,IdleTime,EnterMap,EnterX,EnterY,Map1,Map2,Map3,Map4,Map5,Map6,Map7,Map8 +// ID,Name,LimitTime,IdleTimeOut,EnterMap,EnterX,EnterY,Map2,Map3,Map4,Map5,Map6,Map7,Map8,Map9,Map10 +// +// EnterMap is considered as Map1 -1,Endless Tower,14400,300,1@tower,50,355,1@tower,2@tower,3@tower,4@tower,5@tower,6@tower -2,Sealed Catacomb,7200,300,1@cata,100,224,1@cata,2@cata -3,Orc's Memory,3600,300,1@orcs,179,15,1@orcs,2@orcs -4,Nidhoggur's Nest,14400,300,1@nyd,32,36,1@nyd,2@nyd -5,Mistwood Maze,7200,300,1@mist,89,29,1@mist -6,Culvert,3600,300,1@pump,63,98,1@pump,2@pump -7,Octopus Cave,3600,300,1@cash,199,99,1@cash -8,Bangungot Hospital 2F,3600,300,1@ma_h,40,157,1@ma_h -9,Buwaya Cave,3600,300,1@ma_c,35,57,1@ma_c -10,Bakonawa Lake,7200,300,1@ma_b,64,51,1@ma_b -11,Wolfchev's Laboratory,14400,300,1@lhz,45,148,1@lhz -12,Old Glast Heim,3600,300,1@gl_k,150,20,1@gl_k,2@gl_k -13,Eclage Interior,1200,300,1@ecl,60,50,1@ecl +1,Endless Tower,14400,300,1@tower,50,355,2@tower,3@tower,4@tower,5@tower,6@tower +2,Sealed Catacomb,7200,300,1@cata,100,224,2@cata +3,Orc's Memory,3600,300,1@orcs,179,15,2@orcs +4,Nidhoggur's Nest,14400,300,1@nyd,32,36,2@nyd +5,Mistwood Maze,7200,300,1@mist,89,29 +6,Culvert,3600,300,1@pump,63,98,2@pump +7,Octopus Cave,3600,300,1@cash,199,99 +8,Bangungot Hospital 2F,3600,300,1@ma_h,40,157 +9,Buwaya Cave,3600,300,1@ma_c,35,57 +10,Bakonawa Lake,7200,300,1@ma_b,64,51 +11,Wolfchev's Laboratory,14400,300,1@lhz,45,148 +12,Old Glast Heim,3600,300,1@gl_k,150,20,2@gl_k +13,Eclage Interior,1200,300,1@ecl,60,50 diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 1e3fdc9d8c..d8404c22cb 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3,7 +3,7 @@ //===== By: ================================================== //= rAthena Dev Team //===== Last Updated: ======================================== -//= 20150610 +//= 20160523 //===== Description: ========================================= //= A reference manual for the rAthena scripting language. //= Commands are sorted depending on their functionality. @@ -8113,9 +8113,9 @@ This command will open a book item at the specified page. ======================== --------------------------------------- -*instance_create("",{,}); +*instance_create(""{,{,}}); -Creates an instance for the of . The instance name, along with +Creates an instance for the of . The instance name, along with all other instance data, is read from 'db/(pre-)re/instance_db.txt'. Upon success, the command generates a unique instance ID, duplicates all listed maps and NPCs, sets the alive time, and triggers the "OnInstanceInit" label in all NPCs inside @@ -8129,7 +8129,7 @@ Instance Mode options: The command returns the instance ID upon success, and these values upon failure: -1: Invalid type. - -2: Party not found. + -2: Character/Party/Guild not found. -3: Instance already exists. -4: No free instances (MAX_INSTANCE exceeded). @@ -8139,13 +8139,13 @@ The command returns the instance ID upon success, and these values upon failure: Destroys instance with the ID . If no ID is specified, the instance the script is attached to is used. If the script is not attached to an instance, -the instance of the currently attached player is used (if it is a party or guild -mode). If it is not owned by anyone, no player needs to be attached. If that -fails, the script will come to a halt. +the instance of the currently attached player is used (if it is a character, party, +or guild mode). If it is not owned by anyone, no player needs to be attached. If +that fails, the script will come to a halt. --------------------------------------- -*instance_enter(""{,,,}); +*instance_enter({,,}); Warps player to the specified instance after the script terminates. The map and coordinates are located in 'db/(pre-)re/instance_db.txt'. @@ -8163,8 +8163,8 @@ Put -1 for x and y if want to warp player with default entrance coordinates. Returns the unique name of the instanced script. If no ID is specified, the instance the script is attached to is used. If the script is not attached to -an instance, the instance of the currently attached player's party is used. If -that fails, the script will come to a halt. +an instance, the instance of the currently attached NPC, player, party, or guild +is used. If that fails, the script will come to a halt. --------------------------------------- @@ -8173,8 +8173,8 @@ that fails, the script will come to a halt. Returns the unique name of the instanced map. If no instance ID is specified, the instance the script is attached to is used. If the script is not attached to an instance, the instance of the currently attached player is used (if it is a -party or guild mode). If it is not owned by anyone, no player needs to be -attached. If that fails, the command returns an empty string instead. +character, party, or guild mode). If it is not owned by anyone, no player needs +to be attached. If that fails, the command returns an empty string instead. --------------------------------------- @@ -8182,7 +8182,7 @@ attached. If that fails, the command returns an empty string instead. Returns the unique instance id of the attached script. If the script is not attached to an instance, the instance of the currently attached player is -used (if it is a party or guild mode). If it is not owned by anyone, no +used (if it is a character, party, or guild mode). If it is not owned by anyone, no player needs to be attached. If that fails, the function will return 0. --------------------------------------- @@ -8192,8 +8192,8 @@ player needs to be attached. If that fails, the function will return 0. Warps all players in the instance to at given coordinates. If no ID is specified, the instance the script is attached to is used. If the script is not attached to an instance, the instance of the -currently attached player is used (if it is a party or guild mode). If it -is not owned by anyone, no player needs to be attached. If that +currently attached player is used (if it is a character, party, or guild +mode). If it is not owned by anyone, no player needs to be attached. If that fails, the script will come to a halt. --------------------------------------- @@ -8203,8 +8203,8 @@ fails, the script will come to a halt. Broadcasts a message to all players in the instance currently residing on an instance map. If -1 is specified for , the instance the script is attached to is used. If the script is not attached to an instance, -the instance of the currently attached player is used (if it is a party or guild -mode). If it is not owned by anyone, no player needs to be attached. +the instance of the currently attached player is used (if it is a character, +party, or guild mode). If it is not owned by anyone, no player needs to be attached. For details on the other parameters, see 'announce'. diff --git a/src/map/clif.c b/src/map/clif.c index f592e914d8..17b6b00da5 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -16578,6 +16578,7 @@ void clif_font(struct map_session_data *sd) void clif_instance_create(unsigned short instance_id, int num) { #if PACKETVER >= 20071128 + struct instance_db *db = NULL; struct map_session_data *sd = NULL; enum send_target target = PARTY; unsigned char buf[65]; @@ -16587,8 +16588,9 @@ void clif_instance_create(unsigned short instance_id, int num) if (!sd) return; + db = instance_searchtype_db(instance_data[instance_id].type); WBUFW(buf,0) = 0x2cb; - memcpy(WBUFP(buf,2), instance_data[instance_id].name, 62); + safestrncpy(WBUFP(buf,2), StringBuf_Value(db->name), INSTANCE_NAME_LENGTH); WBUFW(buf,63) = num; clif_send(buf,packet_len(0x2cb),&sd->bl,target); #endif @@ -16623,6 +16625,7 @@ void clif_instance_changewait(unsigned short instance_id, int num) void clif_instance_status(unsigned short instance_id, unsigned int limit1, unsigned int limit2) { #if PACKETVER >= 20071128 + struct instance_db *db = NULL; struct map_session_data *sd = NULL; enum send_target target = PARTY; unsigned char buf[71]; @@ -16632,8 +16635,9 @@ void clif_instance_status(unsigned short instance_id, unsigned int limit1, unsig if (!sd) return; + db = instance_searchtype_db(instance_data[instance_id].type); WBUFW(buf,0) = 0x2cd; - memcpy(WBUFP(buf,2), instance_data[instance_id].name, 62); + safestrncpy(WBUFP(buf,2), StringBuf_Value(db->name), INSTANCE_NAME_LENGTH); WBUFL(buf,63) = limit1; WBUFL(buf,67) = limit2; clif_send(buf,packet_len(0x2cd),&sd->bl,target); diff --git a/src/map/instance.c b/src/map/instance.c index 13d375af3d..e7f78d9e5f 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -25,20 +25,7 @@ int instance_start = 0; // To keep the last index + 1 of normal map inserted in the map[ARRAY] struct instance_data instance_data[MAX_INSTANCE_DATA]; - -/// Instance DB entry struct -struct instance_db { - unsigned short id; ///< Instance ID - StringBuf *name; ///< Instance name - unsigned int limit, ///< Duration limit - timeout; ///< Timeout limit - struct { - StringBuf *mapname; ///< Mapname, the limit should be MAP_NAME_LENGTH_EXT - unsigned short x, y; ///< Map coordinates - } enter; - StringBuf **maplist; ///< Used maps in instance, the limit should be MAP_NAME_LENGTH_EXT - uint8 maplist_count; ///< Number of used maps -}; +struct eri *instance_maps_ers = NULL; ///< Array of maps per instance static DBMap *InstanceDB; /// Instance DB: struct instance_db, key: id static DBMap *InstanceNameDB; /// instance id, key: name @@ -52,7 +39,7 @@ static struct { /*========================================== * Searches for an instance ID in the database *------------------------------------------*/ -static struct instance_db *instance_searchtype_db(unsigned short instance_id) { +struct instance_db *instance_searchtype_db(unsigned short instance_id) { return (struct instance_db *)uidb_get(InstanceDB,instance_id); } @@ -60,6 +47,16 @@ static uint16 instance_name2id(const char *instance_name) { return (uint16)strdb_uiget(InstanceNameDB,instance_name); } +/*========================================== + * Searches for an instance name in the database + *------------------------------------------*/ +static struct instance_db *instance_searchname_db(const char *instance_name) { + uint16 id = instance_name2id(instance_name); + if (id == 0) + return NULL; + return (struct instance_db *)uidb_get(InstanceDB,id); +} + /** * Search for a sd of an Instance * @param instance_id: Instance ID @@ -88,16 +85,6 @@ void instance_getsd(unsigned short instance_id, struct map_session_data **sd, en return; } -/*========================================== - * Searches for an instance name in the database - *------------------------------------------*/ -static struct instance_db *instance_searchname_db(const char *instance_name) { - uint16 id = instance_name2id(instance_name); - if (id == 0) - return NULL; - return (struct instance_db *)uidb_get(InstanceDB,id); -} - /*========================================== * Deletes an instance timer (Destroys instance) *------------------------------------------*/ @@ -324,11 +311,11 @@ void instance_addnpc(struct instance_data *im) // First add the NPCs for(i = 0; i < im->cnt_map; i++) - map_foreachinarea(instance_addnpc_sub, im->map[i].src_m, 0, 0, map[im->map[i].src_m].xs, map[im->map[i].src_m].ys, BL_NPC, im->map[i].m); + map_foreachinarea(instance_addnpc_sub, im->map[i]->src_m, 0, 0, map[im->map[i]->src_m].xs, map[im->map[i]->src_m].ys, BL_NPC, im->map[i]->m); // Now run their OnInstanceInit for(i = 0; i < im->cnt_map; i++) - map_foreachinarea(instance_npcinit, im->map[i].m, 0, 0, map[im->map[i].m].xs, map[im->map[i].m].ys, BL_NPC, im->map[i].m); + map_foreachinarea(instance_npcinit, im->map[i]->m, 0, 0, map[im->map[i]->m].xs, map[im->map[i]->m].ys, BL_NPC, im->map[i]->m); } @@ -395,8 +382,7 @@ int instance_create(int owner_id, const char *name, enum instance_mode mode) { instance_data[i].idle_timer = INVALID_TIMER; instance_data[i].regs.vars = i64db_alloc(DB_OPT_RELEASE_DATA); instance_data[i].regs.arrays = NULL; - safestrncpy(instance_data[i].name, name, sizeof(instance_data[i].name)); - memset(instance_data[i].map, 0, sizeof(instance_data[i].map)); + instance_data[i].cnt_map = 0; switch(mode) { case IM_CHAR: @@ -416,7 +402,7 @@ int instance_create(int owner_id, const char *name, enum instance_mode mode) { instance_subscription_timer(0,0,0,0); - ShowInfo("[Instance] Created: %s.\n", name); + ShowInfo("[Instance] Created: %s (%hu).\n", name, i); return i; } @@ -424,12 +410,11 @@ int instance_create(int owner_id, const char *name, enum instance_mode mode) { /*-------------------------------------- * Adds maps to the instance *--------------------------------------*/ -int instance_addmap(unsigned short instance_id) -{ +int instance_addmap(unsigned short instance_id) { int i, m; - int cnt_map = 0; struct instance_data *im; struct instance_db *db; + struct s_instance_map *entry; if (instance_id == 0) return 0; @@ -449,22 +434,39 @@ int instance_addmap(unsigned short instance_id) im->idle_timer = add_timer(gettick() + db->timeout * 1000, instance_delete_timer, instance_id, 0); // Add the maps + if (db->maplist_count > MAX_MAP_PER_INSTANCE) { + ShowError("instance_addmap: Too many maps (%d) created for a single instance '%s' (%hu).\n", db->maplist_count, StringBuf_Value(db->name), instance_id); + return 0; + } + + // Add initial map + if ((m = map_addinstancemap(StringBuf_Value(db->enter.mapname), instance_id)) < 0) { + ShowError("instance_addmap: Failed to create initial map for instance '%s' (%hu).\n", StringBuf_Value(db->name), instance_id); + return 0; + } + entry = ers_alloc(instance_maps_ers, struct s_instance_map); + entry->m = m; + entry->src_m = map_mapname2mapid(StringBuf_Value(db->enter.mapname)); + RECREATE(im->map, struct s_instance_map *, im->cnt_map + 1); + im->map[im->cnt_map++] = entry; + + // Add extra maps (if any) for(i = 0; i < db->maplist_count; i++) { if(strlen(StringBuf_Value(db->maplist[i])) < 1) continue; else if( (m = map_addinstancemap(StringBuf_Value(db->maplist[i]), instance_id)) < 0) { // An error occured adding a map - ShowError("instance_addmap: No maps added to instance %d.\n",instance_id); + ShowError("instance_addmap: No maps added to instance '%s' (%hu).\n", StringBuf_Value(db->name), instance_id); return 0; } else { - im->map[cnt_map].m = m; - im->map[cnt_map].src_m = map_mapname2mapid(StringBuf_Value(db->maplist[i])); - cnt_map++; + entry = ers_alloc(instance_maps_ers, struct s_instance_map); + entry->m = m; + entry->src_m = map_mapname2mapid(StringBuf_Value(db->maplist[i])); + RECREATE(im->map, struct s_instance_map *, im->cnt_map + 1); + im->map[im->cnt_map++] = entry; } } - im->cnt_map = cnt_map; - // Create NPCs on all maps instance_addnpc(im); @@ -487,7 +489,7 @@ int instance_addmap(unsigned short instance_id) return 0; } - return cnt_map; + return im->cnt_map; } @@ -518,14 +520,14 @@ int instance_mapname2mapid(const char *name, unsigned short instance_id) if(im->state != INSTANCE_BUSY) return m; - for(i = 0; i < MAX_MAP_PER_INSTANCE; i++) - if(im->map[i].src_m == m) { + for(i = 0; i < im->cnt_map; i++) + if(im->map[i]->src_m == m) { char alt_name[MAP_NAME_LENGTH]; if((strchr(iname,'@') == NULL) && strlen(iname) > 8) { memmove(iname, iname+(strlen(iname)-9), strlen(iname)); - snprintf(alt_name, sizeof(alt_name),"%d#%s", instance_id, iname); + snprintf(alt_name, sizeof(alt_name),"%hu#%s", instance_id, iname); } else - snprintf(alt_name, sizeof(alt_name),"%.3d%s", instance_id, iname); + snprintf(alt_name, sizeof(alt_name),"%.3hu%s", instance_id, iname); return map_mapname2mapid(alt_name); } @@ -554,31 +556,6 @@ int instance_destroy(unsigned short instance_id) return 1; mode = im->mode; - switch(mode) { - case IM_NONE: - break; - case IM_CHAR: - if ((sd = map_id2sd(im->owner_id)) == NULL) { - ShowError("instance_destroy: character %d not found for instance '%s'.\n", im->owner_id, im->name); - return 1; - } - break; - case IM_PARTY: - if ((p = party_search(im->owner_id)) == NULL) { - ShowError("instance_destroy: party %d not found for instance '%s'.\n", im->owner_id, im->name); - return 1; - } - break; - case IM_GUILD: - if ((g = guild_search(im->owner_id)) == NULL) { - ShowError("instance_destroy: guild %d not found for instance '%s'.\n", im->owner_id, im->name); - return 1; - } - break; - default: - ShowError("instance_destroy: unknown owner type %u for owner_id %d and name %s.\n", mode, im->owner_id, im->name); - return 1; - } if(im->state == INSTANCE_IDLE) { for(i = 0; i < instance_wait.count; i++) { @@ -608,8 +585,10 @@ int instance_destroy(unsigned short instance_id) else type = 3; - for(i = 0; i < im->cnt_map; i++) - map_delinstancemap(im->map[i].m); + for(i = 0; i < im->cnt_map; i++) { + map_delinstancemap(im->map[i]->m); + ers_free(instance_maps_ers, im->map[i]); + } } if(im->keep_timer != INVALID_TIMER) { @@ -643,7 +622,7 @@ int instance_destroy(unsigned short instance_id) if( im->regs.arrays ) instance_data[instance_id].regs.arrays->destroy(instance_data[instance_id].regs.arrays, script_free_array_db); - ShowInfo("[Instance] Destroyed %d.\n", instance_id); + ShowInfo("[Instance] Destroyed %hu.\n", instance_id); memset(&instance_data[instance_id], 0, sizeof(instance_data[instance_id])); @@ -653,29 +632,29 @@ int instance_destroy(unsigned short instance_id) /*========================================== * Allows a user to enter an instance *------------------------------------------*/ -int instance_enter(struct map_session_data *sd, unsigned short instance_id, const char *name) +int instance_enter(struct map_session_data *sd, unsigned short instance_id) { - struct instance_db *db = instance_searchname_db(name); + struct instance_db *db = instance_searchtype_db(instance_data[instance_id].type); nullpo_retr(-1, sd); - nullpo_retr(3, db); - return instance_enter_position(sd, instance_id, name, db->enter.x, db->enter.y); + if (db == NULL) + return 2; + + return instance_enter_position(sd, instance_id, db->enter.x, db->enter.y); } /*========================================== * Warp a user into instance *------------------------------------------*/ -int instance_enter_position(struct map_session_data *sd, unsigned short instance_id, const char *name, short x, short y) +int instance_enter_position(struct map_session_data *sd, unsigned short instance_id, short x, short y) { struct instance_data *im = &instance_data[instance_id]; - struct instance_db *db = instance_searchname_db(name); struct party_data *p = NULL; struct guild *g = NULL; int16 m; nullpo_retr(-1, sd); - nullpo_retr(3, db); switch(instance_data[instance_id].mode) { case IM_NONE: @@ -710,11 +689,9 @@ int instance_enter_position(struct map_session_data *sd, unsigned short instance if (im->state != INSTANCE_BUSY) return 3; - if (im->type != db->id) - return 3; // Does the instance match? - if ((m = instance_mapname2mapid(StringBuf_Value(db->enter.mapname), instance_id)) < 0) + if ((m = instance_mapname2mapid(map_mapid2mapname(im->map[0]->m), instance_id)) < 0) return 3; if (pc_setpos(sd, map_id2index(m), x, y, CLR_OUTSIGHT)) @@ -735,7 +712,6 @@ int instance_enter_position(struct map_session_data *sd, unsigned short instance int instance_reqinfo(struct map_session_data *sd, unsigned short instance_id) { struct instance_data *im; - struct instance_db *db; nullpo_retr(1, sd); @@ -744,7 +720,7 @@ int instance_reqinfo(struct map_session_data *sd, unsigned short instance_id) im = &instance_data[instance_id]; - if((db = instance_searchtype_db(im->type)) == NULL) + if(instance_searchtype_db(im->type) == NULL) return 1; // Say it's created if instance is not busy @@ -802,8 +778,8 @@ int instance_delusers(unsigned short instance_id) return 1; // If no one is in the instance, start the idle timer - for(i = 0; im->map[i].m && i < MAX_MAP_PER_INSTANCE; i++) - if(map[im->map[i].m].users > 1) // We check this before the actual map.users are updated, hence the 1 + for(i = 0; im->map[i]->m && i > im->cnt_map; i++) + if(map[im->map[i]->m].users > 1) // We check this before the actual map.users are updated, hence the 1 idle++; if(!idle) // If idle wasn't added to, we know no one was in the instance @@ -822,7 +798,7 @@ static bool instance_readdb_sub(char* str[], int columns, int current) uint8 i; int id = atoi(str[0]); struct instance_db *db; - bool isNew = false, defined = false; + bool isNew = false; if (!id || id > USHRT_MAX) { ShowError("instance_readdb_sub: Cannot add instance with ID '%d'. Valid ID is 1 ~ %d.\n", id, USHRT_MAX); @@ -868,21 +844,11 @@ static bool instance_readdb_sub(char* str[], int columns, int current) } RECREATE(db->maplist, StringBuf *, db->maplist_count+1); db->maplist[db->maplist_count] = StringBuf_Malloc(); - if (strcmpi(str[i], str[4]) == 0) - defined = true; StringBuf_AppendStr(db->maplist[db->maplist_count], str[i]); db->maplist_count++; } } - if (!defined) { - ShowError("instance_readdb_sub: The entrance map is not defined in instance map list.\n"); - instance_db_free_sub(db); - if (!isNew) - uidb_remove(InstanceDB,id); - return false; - } - if (isNew) { uidb_put(InstanceDB, id, db); strdb_uiput(InstanceNameDB, StringBuf_Value(db->name), id); @@ -925,7 +891,7 @@ void instance_readdb(void) { int f; for (f = 0; fbl.m].instance_id].mode == IM_GUILD && (!(g = guild_search(sd->status.guild_id)) || g->instance_id != map[sd->bl.m].instance_id)) // Someone not in guild is on instance map continue; im = &instance_data[p->instance_id]; - if((db = instance_searchtype_db(im->type)) != NULL && !instance_enter(sd, i, StringBuf_Value(db->name))) { // All good + if((db = instance_searchtype_db(im->type)) != NULL && !instance_enter(sd, i)) { // All good clif_displaymessage(sd->fd, msg_txt(sd,515)); // Instance has been reloaded instance_reqinfo(sd,p->instance_id); } else // Something went wrong - ShowError("do_reload_instance: Error setting character at instance start: character_id=%d instance=%s.\n",sd->status.char_id,db->name); + ShowError("do_reload_instance: Error setting character at instance start: character_id=%d instance=%s.\n",sd->status.char_id,StringBuf_Value(db->name)); } mapit_free(iter); } @@ -993,6 +959,8 @@ void do_init_instance(void) { memset(&instance_wait, 0, sizeof(instance_wait)); instance_wait.timer = -1; + instance_maps_ers = ers_new(sizeof(struct s_instance_map),"instance.c::instance_maps_ers", ERS_OPT_NONE); + add_timer_func_list(instance_delete_timer,"instance_delete_timer"); add_timer_func_list(instance_subscription_timer,"instance_subscription_timer"); } @@ -1000,6 +968,7 @@ void do_init_instance(void) { void do_final_instance(void) { int i; + ers_destroy(instance_maps_ers); for( i = 1; i < MAX_INSTANCE_DATA; i++ ) instance_destroy(i); diff --git a/src/map/instance.h b/src/map/instance.h index 7d59a0ad24..98c4a8fb27 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -9,8 +9,8 @@ struct block_list; -#define MAX_INSTANCE_DATA 300 // Essentially how many instances we can create, but instance creation is primarily decided by MAX_MAP_PER_SERVER -#define MAX_MAP_PER_INSTANCE 10 // Max number of maps per instance +#define MAX_INSTANCE_DATA 300 // Essentially how many instances we can create, but instance creation is primarily decided by MAX_MAP_PER_SERVER +#define MAX_MAP_PER_INSTANCE 9 // Max number of maps per instance (Enter map is counted as one) - Supports up to 255 maps #define INSTANCE_NAME_LENGTH (60+1) @@ -28,35 +28,48 @@ enum instance_mode { IM_MAX, }; +struct s_instance_map { + int16 m, src_m; +}; + struct instance_data { - unsigned short type, ///< Instance DB ID - cnt_map; - char name[INSTANCE_NAME_LENGTH]; - enum instance_state state; - enum instance_mode mode; - int owner_id; - unsigned int keep_limit; - int keep_timer; - unsigned int idle_limit; - int idle_timer; - + unsigned short type; ///< Instance DB ID + enum instance_state state; ///< State of instance + enum instance_mode mode; ///< Mode of instance + int owner_id; ///< Owner ID of instance + unsigned int keep_limit; ///< Life time of instance + int keep_timer; ///< Remaining life time of instance + unsigned int idle_limit; ///< Idle time of instance + int idle_timer; ///< Remaining idle time of instance struct reg_db regs; ///< Instance variables for scripts + struct s_instance_map **map; ///< Dynamic array of maps in instance + uint8 cnt_map; ///< Number of maps in an instance +}; +/// Instance DB entry struct +struct instance_db { + unsigned short id; ///< Instance ID + StringBuf *name; ///< Instance name + unsigned int limit, ///< Duration limit + timeout; ///< Timeout limit struct { - int m; - int src_m; - } map[MAX_MAP_PER_INSTANCE]; + StringBuf *mapname; ///< Mapname, the limit should be MAP_NAME_LENGTH_EXT + short x, y; ///< Map coordinates + } enter; + StringBuf **maplist; ///< Used maps in instance, the limit should be MAP_NAME_LENGTH_EXT + uint8 maplist_count; ///< Number of used maps }; extern int instance_start; extern struct instance_data instance_data[MAX_INSTANCE_DATA]; +struct instance_db *instance_searchtype_db(unsigned short instance_id); void instance_getsd(unsigned short instance_id, struct map_session_data **sd, enum send_target *target); int instance_create(int owner_id, const char *name, enum instance_mode mode); int instance_destroy(unsigned short instance_id); -int instance_enter(struct map_session_data *sd, unsigned short instance_id, const char *name); -int instance_enter_position(struct map_session_data *sd, unsigned short instance_id, const char *name, short x, short y); +int instance_enter(struct map_session_data *sd, unsigned short instance_id); +int instance_enter_position(struct map_session_data *sd, unsigned short instance_id, short x, short y); int instance_reqinfo(struct map_session_data *sd, unsigned short instance_id); int instance_addusers(unsigned short instance_id); int instance_delusers(unsigned short instance_id); diff --git a/src/map/map.c b/src/map/map.c index c6a630f4c0..e4288bbd3a 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -2823,11 +2823,11 @@ const char* map_mapid2mapname(int m) if (!im) // This shouldn't happen but if it does give them the map we intended to give return map[m].name; else { - int i; + uint8 i; - for (i = 0; i < MAX_MAP_PER_INSTANCE; i++) { // Loop to find the src map we want - if (im->map[i].m == m) - return map[im->map[i].src_m].name; + for (i = 0; i < im->cnt_map; i++) { // Loop to find the src map we want + if (im->map[i]->m == m) + return map[im->map[i]->src_m].name; } } } diff --git a/src/map/npc.c b/src/map/npc.c index 7f9f224799..e320f6a8d7 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -3167,8 +3167,8 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) { int dm = map_mapindex2mapid(snd->u.warp.mapindex), imap = 0, i; if( dm < 0 ) return 1; - for(i = 0; i < MAX_MAP_PER_INSTANCE; i++) - if(im->map[i].m && map_mapname2mapid(map[im->map[i].src_m].name) == dm) { + for(i = 0; i < im->cnt_map; i++) + if(im->map[i]->m && map_mapname2mapid(map[im->map[i]->src_m].name) == dm) { imap = map_mapname2mapid(map[m].name); break; // Instance map matches destination, update to instance map } diff --git a/src/map/script.c b/src/map/script.c index cc103d25f5..60f89c2892 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -18860,17 +18860,42 @@ unsigned short script_instancegetid(struct script_state* st) BUILDIN_FUNC(instance_create) { enum instance_mode mode = IM_PARTY; - int owner_id; + int owner_id = 0; - owner_id = script_getnum(st, 3); - if (script_hasdata(st, 4)) { - mode = script_getnum(st, 4); + if (script_hasdata(st, 3)) { + mode = script_getnum(st, 3); if (mode < IM_NONE || mode >= IM_MAX) { ShowError("buildin_instance_create: Unknown instance owner type %d for '%s'\n", mode, script_getstr(st, 2)); return SCRIPT_CMD_FAILURE; } } + if (script_hasdata(st, 4)) + owner_id = script_getnum(st, 4); + else { + struct map_session_data *sd = NULL; + + sd = script_rid2sd(st); // If sd is NULL, instance_create will return -2. + switch(mode) { + case IM_NONE: + owner_id = st->oid; + break; + case IM_CHAR: + if (sd) + owner_id = sd->status.char_id; + break; + case IM_PARTY: + if (sd) + owner_id = sd->status.party_id; + break; + case IM_GUILD: + if (sd) + owner_id = sd->status.guild_id; + default: + ShowError("buildin_instance_create: Invalid instance mode (instance name: %s)\n", script_getstr(st, 2)); + return SCRIPT_CMD_FAILURE; + } + } script_pushint(st, instance_create(owner_id, script_getstr(st, 2), mode)); return SCRIPT_CMD_SUCCESS; @@ -18893,7 +18918,7 @@ BUILDIN_FUNC(instance_destroy) if( instance_id <= 0 || instance_id >= MAX_MAP_PER_SERVER ) { ShowError("buildin_instance_destroy: Trying to destroy invalid instance %d.\n", instance_id); - return SCRIPT_CMD_SUCCESS; + return SCRIPT_CMD_FAILURE; } instance_destroy(instance_id); @@ -18911,16 +18936,16 @@ BUILDIN_FUNC(instance_destroy) BUILDIN_FUNC(instance_enter) { struct map_session_data *sd = NULL; - int x = script_hasdata(st,3) ? script_getnum(st, 3) : -1; - int y = script_hasdata(st,4) ? script_getnum(st, 4) : -1; + int x = script_hasdata(st,2) ? script_getnum(st, 2) : -1; + int y = script_hasdata(st,3) ? script_getnum(st, 3) : -1; - if (!script_charid2sd(5,sd)) + if (!script_charid2sd(4,sd)) return SCRIPT_CMD_FAILURE; if (x != -1 && y != -1) - script_pushint(st, instance_enter_position(sd, script_instancegetid(st), script_getstr(st, 2), x, y)); + script_pushint(st, instance_enter_position(sd, script_instancegetid(st), x, y)); else - script_pushint(st, instance_enter(sd, script_instancegetid(st), script_getstr(st, 2))); + script_pushint(st, instance_enter(sd, script_instancegetid(st))); return SCRIPT_CMD_SUCCESS; } @@ -18988,16 +19013,7 @@ BUILDIN_FUNC(instance_mapname) *------------------------------------------*/ BUILDIN_FUNC(instance_id) { - unsigned short instance_id; - - instance_id = script_instancegetid(st); - - if(!instance_id) { - //ShowError("buildin_instance_id: No instance attached to NPC or player"); - script_pushint(st, 0); - return SCRIPT_CMD_SUCCESS; - } - script_pushint(st, instance_id); + script_pushint(st, script_instancegetid(st)); return SCRIPT_CMD_SUCCESS; } @@ -19011,22 +19027,40 @@ static int buildin_instance_warpall_sub(struct block_list *bl, va_list ap) unsigned int m = va_arg(ap,unsigned int); int x = va_arg(ap,int); int y = va_arg(ap,int); + unsigned short instance_id = va_arg(ap,unsigned int); + struct map_session_data *sd = NULL; + int owner_id = 0; nullpo_retr(0, bl); if (bl->type != BL_PC) return 0; - pc_setpos((TBL_PC *)bl, m, x, y, CLR_TELEPORT); + sd = (TBL_PC *)bl; + owner_id = instance_data[instance_id].owner_id; + switch(instance_data[instance_id].mode) { + case IM_NONE: + break; + case IM_CHAR: + if (sd->status.char_id != owner_id) + return 0; + break; + case IM_PARTY: + if (sd->status.party_id != owner_id) + return 0; + break; + case IM_GUILD: + if (sd->status.guild_id != owner_id) + return 0; + } - return 0; + pc_setpos(sd, m, x, y, CLR_TELEPORT); + + return 1; } BUILDIN_FUNC(instance_warpall) { - struct map_session_data *sd = NULL; - struct party_data *p = NULL; - struct guild *g = NULL; int16 m, i; unsigned short instance_id; const char *mapn; @@ -19043,27 +19077,8 @@ BUILDIN_FUNC(instance_warpall) if( !instance_id || (m = map_mapname2mapid(mapn)) < 0 || (m = instance_mapname2mapid(map[m].name,instance_id)) < 0) return SCRIPT_CMD_FAILURE; - switch(instance_data[instance_id].mode) { - case IM_NONE: - break; - case IM_CHAR: - if (!(sd = map_id2sd(instance_data[instance_id].owner_id))) - return SCRIPT_CMD_FAILURE; - break; - case IM_PARTY: - if (!(p = party_search(instance_data[instance_id].owner_id))) - return SCRIPT_CMD_FAILURE; - break; - case IM_GUILD: - if (!(g = guild_search(instance_data[instance_id].owner_id))) - return SCRIPT_CMD_FAILURE; - default: - ShowError("buildin_instance_warpall: Invalid instance owner type (instance_id: %d)\n", instance_id); - break; - } - for(i = 0; i < instance_data[instance_id].cnt_map; i++) - map_foreachinmap(buildin_instance_warpall_sub, instance_data[instance_id].map[i].m, BL_PC, map_id2index(m), x, y); + map_foreachinmap(buildin_instance_warpall_sub, instance_data[instance_id].map[i]->m, BL_PC, map_id2index(m), x, y, instance_id); return SCRIPT_CMD_SUCCESS; } @@ -19095,7 +19110,7 @@ BUILDIN_FUNC(instance_announce) { } for( i = 0; i < instance_data[instance_id].cnt_map; i++ ) - map_foreachinmap(buildin_announce_sub, instance_data[instance_id].map[i].m, BL_PC, + map_foreachinmap(buildin_announce_sub, instance_data[instance_id].map[i]->m, BL_PC, mes, strlen(mes)+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY); return SCRIPT_CMD_SUCCESS; @@ -19130,11 +19145,11 @@ BUILDIN_FUNC(instance_check_party) if( script_hasdata(st,2) ) party_id = script_getnum(st,2); - else return SCRIPT_CMD_SUCCESS; + else return SCRIPT_CMD_FAILURE; if( !(p = party_search(party_id)) ) { script_pushint(st, 0); // Returns false if party does not exist. - return SCRIPT_CMD_SUCCESS; + return SCRIPT_CMD_FAILURE; } for( i = 0; i < MAX_PARTY; i++ ) { @@ -19172,7 +19187,7 @@ BUILDIN_FUNC(instance_check_party) *------------------------------------------*/ BUILDIN_FUNC(instance_check_guild) { - int amount, min, max, i, guild_id, c = 0; + int amount, min, max, i, guild_id = 0, c = 0; struct guild *g = NULL; amount = script_hasdata(st,3) ? script_getnum(st,3) : 1; // Amount of needed Guild members for the Instance. @@ -19190,11 +19205,11 @@ BUILDIN_FUNC(instance_check_guild) if (script_hasdata(st,2)) guild_id = script_getnum(st,2); else - return SCRIPT_CMD_SUCCESS; + return SCRIPT_CMD_FAILURE; if (!(g = guild_search(guild_id))) { script_pushint(st, 0); // Returns false if guild does not exist. - return SCRIPT_CMD_SUCCESS; + return SCRIPT_CMD_FAILURE; } for(i = 0; i < MAX_GUILD; i++) { @@ -21891,10 +21906,10 @@ struct script_function buildin_func[] = { BUILDIN_DEF(bg_updatescore,"sii"), // Instancing - BUILDIN_DEF(instance_create,"si?"), + BUILDIN_DEF(instance_create,"s??"), BUILDIN_DEF(instance_destroy,"?"), BUILDIN_DEF(instance_id,""), - BUILDIN_DEF(instance_enter,"s???"), + BUILDIN_DEF(instance_enter,"???"), BUILDIN_DEF(instance_npcname,"s?"), BUILDIN_DEF(instance_mapname,"s?"), BUILDIN_DEF(instance_warpall,"sii?"), From c591586f2b21ca813ece1e8085aee589404ce5ea Mon Sep 17 00:00:00 2001 From: aleos89 Date: Mon, 23 May 2016 14:20:55 -0400 Subject: [PATCH 06/10] Adjusted instance script's instance_enter to new format * Follow up to c97be60. * No longer requires instance name. --- npc/instances/EndlessTower.txt | 2 +- npc/instances/NydhoggsNest.txt | 2 +- npc/instances/OrcsMemory.txt | 2 +- npc/instances/SealedShrine.txt | 2 +- npc/re/instances/BakonawaLake.txt | 2 +- npc/re/instances/BangungotHospital.txt | 2 +- npc/re/instances/BuwayaCave.txt | 2 +- npc/re/instances/EclageInterior.txt | 2 +- npc/re/instances/HazyForest.txt | 2 +- npc/re/instances/MalangdoCulvert.txt | 2 +- npc/re/instances/OctopusCave.txt | 2 +- npc/re/instances/OldGlastHeim.txt | 2 +- npc/re/instances/WolfchevLaboratory.txt | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/npc/instances/EndlessTower.txt b/npc/instances/EndlessTower.txt index 756690c9dc..e44bf3a0cf 100644 --- a/npc/instances/EndlessTower.txt +++ b/npc/instances/EndlessTower.txt @@ -291,7 +291,7 @@ e_tower,81,105,0 script Tower Protection Stone 406,{ } L_Enter: - switch(instance_enter("Endless Tower")) { + switch(instance_enter()) { case 3: mes "An unknown error has occurred."; close; diff --git a/npc/instances/NydhoggsNest.txt b/npc/instances/NydhoggsNest.txt index ced58fceb1..f5a08096ab 100644 --- a/npc/instances/NydhoggsNest.txt +++ b/npc/instances/NydhoggsNest.txt @@ -192,7 +192,7 @@ nyd_dun02,100,201,3 script Yggdrasil Gatekeeper 111,8,8,{ close; L_Enter: - switch(instance_enter("Nidhoggur's Nest")) { + switch(instance_enter()) { case 3: mes "[Yggdrasil Gatekeeper]"; mes "An unknown error has occurred."; diff --git a/npc/instances/OrcsMemory.txt b/npc/instances/OrcsMemory.txt index 6965be8b1c..3d94be13a4 100644 --- a/npc/instances/OrcsMemory.txt +++ b/npc/instances/OrcsMemory.txt @@ -84,7 +84,7 @@ gef_fild10,242,202,0 script Dimensional Gorge Piece 406,{ mes "In order to generate a dungeon you must be the Party Leader and have at least 2 members in the party."; close; L_Enter: - switch(instance_enter("Orc's Memory")) { + switch(instance_enter()) { case 3: mes "An unknown error has occurred."; close; diff --git a/npc/instances/SealedShrine.txt b/npc/instances/SealedShrine.txt index 2734a5f228..ee68eec968 100644 --- a/npc/instances/SealedShrine.txt +++ b/npc/instances/SealedShrine.txt @@ -214,7 +214,7 @@ monk_test,306,151,3 script Grave of Baphomet#edq 111,{ //set .@ins_bapho_check2,checkquest(3045,PLAYTIME); if (.@ins_bapho_check == -1) { - switch(instance_enter("Sealed Catacomb")) { + switch(instance_enter()) { case 3: case 2: mes "It's cold to the touch. It doesn't respond."; diff --git a/npc/re/instances/BakonawaLake.txt b/npc/re/instances/BakonawaLake.txt index 39ec9f5dfb..893a5d5f5f 100644 --- a/npc/re/instances/BakonawaLake.txt +++ b/npc/re/instances/BakonawaLake.txt @@ -74,7 +74,7 @@ ma_scene01,174,179,4 script Taho 541,{ mes "Now I'm weaving, so you can go down when I'm done."; close; case 2: - switch(instance_enter(.@md_name$)) { + switch(instance_enter()) { case 3: mes "[Taho]"; mes "An unknown error occurred."; diff --git a/npc/re/instances/BangungotHospital.txt b/npc/re/instances/BangungotHospital.txt index a9127bd417..b671860f63 100644 --- a/npc/re/instances/BangungotHospital.txt +++ b/npc/re/instances/BangungotHospital.txt @@ -282,7 +282,7 @@ L_Enter: cutin "",255; end; case 2: - switch(instance_enter(.@md_name$)) { + switch(instance_enter()) { case 3: mes "[Nurse Maenne]"; mes "A critical situation has happened."; diff --git a/npc/re/instances/BuwayaCave.txt b/npc/re/instances/BuwayaCave.txt index f6c3618ce4..f30aa1743f 100644 --- a/npc/re/instances/BuwayaCave.txt +++ b/npc/re/instances/BuwayaCave.txt @@ -126,7 +126,7 @@ OnTouch: } switch(select("Enter.:Turn back.")) { case 1: - switch(instance_enter("Buwaya Cave")) { + switch(instance_enter()) { case 3: mes "[Guard]"; mes "Oh, now is not a good time."; diff --git a/npc/re/instances/EclageInterior.txt b/npc/re/instances/EclageInterior.txt index 61dbc7debd..b2e68f70ba 100644 --- a/npc/re/instances/EclageInterior.txt +++ b/npc/re/instances/EclageInterior.txt @@ -74,7 +74,7 @@ ecl_hub01,130,15,0 script It is closed shut. 844,{ mes "It is pretty difficult to guide an outsider like you."; close; } - switch (instance_enter(.@md_name$)) { + switch (instance_enter()) { case 3: mes "An unknown error has occurred."; close; diff --git a/npc/re/instances/HazyForest.txt b/npc/re/instances/HazyForest.txt index cdf6670e57..80e86d9962 100644 --- a/npc/re/instances/HazyForest.txt +++ b/npc/re/instances/HazyForest.txt @@ -139,7 +139,7 @@ bif_fild01,161,355,0 script Log Tunnel 844,{ next; if(select("Enter the tunnel.:Give up.") == 2) close; - switch(instance_enter("Mistwood Maze")) { + switch(instance_enter()) { case 3: mes "[Laphine Soldier]"; mes "Something doesn't feel right. Looks like something dangerous is going on, so you'd better turn back today."; diff --git a/npc/re/instances/MalangdoCulvert.txt b/npc/re/instances/MalangdoCulvert.txt index 264467a951..150d9b019e 100644 --- a/npc/re/instances/MalangdoCulvert.txt +++ b/npc/re/instances/MalangdoCulvert.txt @@ -432,7 +432,7 @@ mal_in01,160,34,4 script Missing, the Cleaner 545,{ } end; L_Enter: - switch(instance_enter("Culvert")) { + switch(instance_enter()) { case 3: mes "An unknown error has occurred."; close; diff --git a/npc/re/instances/OctopusCave.txt b/npc/re/instances/OctopusCave.txt index affbcf639c..1c5c216c20 100644 --- a/npc/re/instances/OctopusCave.txt +++ b/npc/re/instances/OctopusCave.txt @@ -119,7 +119,7 @@ mal_dun01,153,237,5 script Weird Entrance 844,{ switch(select("Go in.:Stop.")) { case 1: if (countitem(6442)) { - switch(instance_enter("Octopus Cave")) { + switch(instance_enter()) { case 3: mes "[Starfish]"; mes "Ah, now is not the time..."; diff --git a/npc/re/instances/OldGlastHeim.txt b/npc/re/instances/OldGlastHeim.txt index 73def91209..b51a050a97 100644 --- a/npc/re/instances/OldGlastHeim.txt +++ b/npc/re/instances/OldGlastHeim.txt @@ -51,7 +51,7 @@ glast_01,204,273,6 script Hugin#ghinstance 755,{ mes "The time gap was created. When you're ready, talk to me again."; close; case 2: - switch(instance_enter(.@md_name$)) { + switch(instance_enter()) { case 3: mes "An unknown error has occurred."; close; diff --git a/npc/re/instances/WolfchevLaboratory.txt b/npc/re/instances/WolfchevLaboratory.txt index a814f6146e..3a7096b945 100644 --- a/npc/re/instances/WolfchevLaboratory.txt +++ b/npc/re/instances/WolfchevLaboratory.txt @@ -877,7 +877,7 @@ lhz_dun04,147,279,0 script Laboratory Entrance#memo CLEAR_NPC,{ mes "You have stopped entering to Wolfchev's laboratory."; close; } - if (instance_enter("Wolfchev's Laboratory") != 0) { // probably missing failure cases + if (instance_enter() != 0) { // probably missing failure cases mes "^FF0000Warning^000000"; mes ""+ strcharinfo(0) +". . ."; mes "^FF0000Unregistered personnel^000000"; From 6babca36897e4e3ebbf2301e8c53acd9e68273e4 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 24 May 2016 09:22:03 -0400 Subject: [PATCH 07/10] Corrected a few minor issues * Follow up to 2cfb844. * Adjusted the instance_db documentation. * Adjusted script command instance_announce to check when instance ID is 0 rather than -1 since instance IDs are stored as unsigned now. * Added a couple of checks when sending instance information to the client. * Fixed a compile warning. --- db/import-tmpl/instance_db.txt | 2 +- db/pre-re/instance_db.txt | 2 +- db/re/instance_db.txt | 2 +- doc/script_commands.txt | 2 +- src/map/clif.c | 12 ++++++++++-- src/map/script.c | 14 +++++++------- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/db/import-tmpl/instance_db.txt b/db/import-tmpl/instance_db.txt index eb33400dad..5672eec9e4 100644 --- a/db/import-tmpl/instance_db.txt +++ b/db/import-tmpl/instance_db.txt @@ -1,6 +1,6 @@ // Instance Database // // Structure of Database: -// ID,Name,LimitTime,IdleTimeOut,EnterMap,EnterX,EnterY,Map2,Map3,Map4,Map5,Map6,Map7,Map8,Map9,Map10 +// ID,Name,LimitTime,IdleTimeOut,EnterMap,EnterX,EnterY,Map2,Map3,...,Map255 // // EnterMap is considered as Map1 diff --git a/db/pre-re/instance_db.txt b/db/pre-re/instance_db.txt index 7501545263..e9cf668f15 100644 --- a/db/pre-re/instance_db.txt +++ b/db/pre-re/instance_db.txt @@ -1,7 +1,7 @@ // Instance Database // // Structure of Database: -// ID,Name,LimitTime,IdleTimeOut,EnterMap,EnterX,EnterY,Map2,Map3,Map4,Map5,Map6,Map7,Map8,Map9,Map10 +// ID,Name,LimitTime,IdleTimeOut,EnterMap,EnterX,EnterY,Map2,Map3,...,Map255 // // EnterMap is considered as Map1 diff --git a/db/re/instance_db.txt b/db/re/instance_db.txt index 8a1d10e712..255371e80f 100644 --- a/db/re/instance_db.txt +++ b/db/re/instance_db.txt @@ -1,7 +1,7 @@ // Instance Database // // Structure of Database: -// ID,Name,LimitTime,IdleTimeOut,EnterMap,EnterX,EnterY,Map2,Map3,Map4,Map5,Map6,Map7,Map8,Map9,Map10 +// ID,Name,LimitTime,IdleTimeOut,EnterMap,EnterX,EnterY,Map2,...,Map255 // // EnterMap is considered as Map1 diff --git a/doc/script_commands.txt b/doc/script_commands.txt index d8404c22cb..d1ae5ad030 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -8201,7 +8201,7 @@ fails, the script will come to a halt. *instance_announce ,"",{,{,{,{,{,}}}}}; Broadcasts a message to all players in the instance currently -residing on an instance map. If -1 is specified for , the instance +residing on an instance map. If 0 is specified for , the instance the script is attached to is used. If the script is not attached to an instance, the instance of the currently attached player is used (if it is a character, party, or guild mode). If it is not owned by anyone, no player needs to be attached. diff --git a/src/map/clif.c b/src/map/clif.c index 17b6b00da5..da523fa2ec 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -16589,8 +16589,12 @@ void clif_instance_create(unsigned short instance_id, int num) return; db = instance_searchtype_db(instance_data[instance_id].type); + + if (!db) + return; + WBUFW(buf,0) = 0x2cb; - safestrncpy(WBUFP(buf,2), StringBuf_Value(db->name), INSTANCE_NAME_LENGTH); + safestrncpy((char *)WBUFP(buf,2), StringBuf_Value(db->name), INSTANCE_NAME_LENGTH); WBUFW(buf,63) = num; clif_send(buf,packet_len(0x2cb),&sd->bl,target); #endif @@ -16636,8 +16640,12 @@ void clif_instance_status(unsigned short instance_id, unsigned int limit1, unsig return; db = instance_searchtype_db(instance_data[instance_id].type); + + if (!db) + return; + WBUFW(buf,0) = 0x2cd; - safestrncpy(WBUFP(buf,2), StringBuf_Value(db->name), INSTANCE_NAME_LENGTH); + safestrncpy((char *)WBUFP(buf,2), StringBuf_Value(db->name), INSTANCE_NAME_LENGTH); WBUFL(buf,63) = limit1; WBUFL(buf,67) = limit2; clif_send(buf,packet_len(0x2cd),&sd->bl,target); diff --git a/src/map/script.c b/src/map/script.c index 60f89c2892..fd1a903dee 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -18866,7 +18866,7 @@ BUILDIN_FUNC(instance_create) mode = script_getnum(st, 3); if (mode < IM_NONE || mode >= IM_MAX) { - ShowError("buildin_instance_create: Unknown instance owner type %d for '%s'\n", mode, script_getstr(st, 2)); + ShowError("buildin_instance_create: Unknown instance mode %d for '%s'\n", mode, script_getstr(st, 2)); return SCRIPT_CMD_FAILURE; } } @@ -18916,8 +18916,8 @@ BUILDIN_FUNC(instance_destroy) else instance_id = script_instancegetid(st); - if( instance_id <= 0 || instance_id >= MAX_MAP_PER_SERVER ) { - ShowError("buildin_instance_destroy: Trying to destroy invalid instance %d.\n", instance_id); + if( instance_id == 0 || instance_id >= MAX_MAP_PER_SERVER ) { + ShowError("buildin_instance_destroy: Trying to destroy invalid instance %hu.\n", instance_id); return SCRIPT_CMD_FAILURE; } @@ -18970,10 +18970,10 @@ BUILDIN_FUNC(instance_npcname) if( instance_id && (nd = npc_name2id(str)) != NULL ) { static char npcname[NAME_LENGTH]; - snprintf(npcname, sizeof(npcname), "dup_%d_%d", instance_id, nd->bl.id); + snprintf(npcname, sizeof(npcname), "dup_%hu_%d", instance_id, nd->bl.id); script_pushconststr(st,npcname); } else { - ShowError("buildin_instance_npcname: Invalid instance NPC (instance_id: %d, NPC name: \"%s\".)\n", instance_id, str); + ShowError("buildin_instance_npcname: Invalid instance NPC (instance_id: %hu, NPC name: \"%s\".)\n", instance_id, str); st->state = END; return SCRIPT_CMD_FAILURE; } @@ -19087,7 +19087,7 @@ BUILDIN_FUNC(instance_warpall) * Broadcasts to all maps inside an instance * * instance_announce ,"",{,{,{,{,{,}}}}}; - * Using -1 for will auto-detect the id. + * Using 0 for will auto-detect the id. *------------------------------------------*/ BUILDIN_FUNC(instance_announce) { unsigned short instance_id = script_getnum(st,2); @@ -19100,7 +19100,7 @@ BUILDIN_FUNC(instance_announce) { int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY int i; - if( instance_id == -1 ) { + if( instance_id == 0 ) { instance_id = script_instancegetid(st); } From 1408eefd80db25ea869b20f5893869d3c59ec964 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 24 May 2016 09:57:42 -0400 Subject: [PATCH 08/10] Expanded max maps per instance define * Follow up to c97be60. * Increased the max amount of maps per instance to the limit. --- src/map/instance.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/map/instance.h b/src/map/instance.h index 98c4a8fb27..7bb45c63ca 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -10,7 +10,7 @@ struct block_list; #define MAX_INSTANCE_DATA 300 // Essentially how many instances we can create, but instance creation is primarily decided by MAX_MAP_PER_SERVER -#define MAX_MAP_PER_INSTANCE 9 // Max number of maps per instance (Enter map is counted as one) - Supports up to 255 maps +#define MAX_MAP_PER_INSTANCE UINT8_MAX // Max number of maps per instance (Enter map is counted as one) - Supports up to 255 maps #define INSTANCE_NAME_LENGTH (60+1) @@ -83,4 +83,8 @@ void do_reload_instance(void); void do_init_instance(void); void do_final_instance(void); +#if MAX_MAP_PER_INSTANCE > UINT8_MAX + #error Too many maps per instance defined! Please adjust MAX_MAP_PER_INSTANCE to a lower value. +#endif + #endif From 1cd648b1af84a01b2cb237343563a92e1e1311c2 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 24 May 2016 10:30:42 -0400 Subject: [PATCH 09/10] Resolved compile errors * Follow up to 1408eef. --- src/map/instance.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/map/instance.h b/src/map/instance.h index 7bb45c63ca..5879f4f883 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -10,7 +10,7 @@ struct block_list; #define MAX_INSTANCE_DATA 300 // Essentially how many instances we can create, but instance creation is primarily decided by MAX_MAP_PER_SERVER -#define MAX_MAP_PER_INSTANCE UINT8_MAX // Max number of maps per instance (Enter map is counted as one) - Supports up to 255 maps +#define MAX_MAP_PER_INSTANCE 255 // Max number of maps per instance (Enter map is counted as one) - Supports up to 255 maps #define INSTANCE_NAME_LENGTH (60+1) @@ -83,7 +83,7 @@ void do_reload_instance(void); void do_init_instance(void); void do_final_instance(void); -#if MAX_MAP_PER_INSTANCE > UINT8_MAX +#if MAX_MAP_PER_INSTANCE > 255 #error Too many maps per instance defined! Please adjust MAX_MAP_PER_INSTANCE to a lower value. #endif From 28ad9ac22d64bc28f8b0730666cfce763641c9c9 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Wed, 25 May 2016 14:22:27 -0400 Subject: [PATCH 10/10] Resolved compile warnings * Follow up to 2cfb844. * Initialized some variables. --- src/map/instance.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/map/instance.c b/src/map/instance.c index e7f78d9e5f..480d3a9b7e 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -933,8 +933,8 @@ void do_reload_instance(void) iter = mapit_getallusers(); for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) if(sd && map[sd->bl.m].instance_id) { - struct party_data *p; - struct guild *g; + struct party_data *p = NULL; + struct guild *g = NULL; if (instance_data[map[sd->bl.m].instance_id].mode == IM_PARTY && (!(p = party_search(sd->status.party_id)) || p->instance_id != map[sd->bl.m].instance_id)) // Someone not in party is on instance map continue;