Follow up 95705d41bee8d15d50d34c484617790e4aae9b21
* Changed bonus script list to link list * Merged 'pc_bonus_script_clear_all' to 'pc_bonus_script_clear' * Now bonus script will be saved on auto-save timer or other save request, prevent losing the bonus when "something" happen. But, saving when player is quiting, will removes the bonus that won't be saved on logout. Signed-off-by: Cydh Ramdh <house.bad@gmail.com>
This commit is contained in:
parent
95705d41be
commit
148353eed9
@ -1328,6 +1328,9 @@ int chmapif_bonus_script_save(int fd) {
|
||||
uint32 cid = RFIFOL(fd,4);
|
||||
uint8 count = RFIFOB(fd,8);
|
||||
|
||||
if (SQL_ERROR == Sql_Query(sql_handle,"DELETE FROM `%s` WHERE `char_id` = '%d'", schema_config.bonus_script_db, cid))
|
||||
Sql_ShowDebug(sql_handle);
|
||||
|
||||
if (count > 0) {
|
||||
char esc_script[MAX_BONUS_SCRIPT_LENGTH*2];
|
||||
struct bonus_script_data bsdata;
|
||||
@ -1346,9 +1349,9 @@ int chmapif_bonus_script_save(int fd) {
|
||||
if (SQL_ERROR == Sql_QueryStr(sql_handle,StringBuf_Value(&buf)))
|
||||
Sql_ShowDebug(sql_handle);
|
||||
|
||||
ShowInfo("Bonus Script saved for CID=%d. Total: %d.\n", cid, count);
|
||||
StringBuf_Destroy(&buf);
|
||||
}
|
||||
ShowInfo("Bonus Script saved for CID=%d. Total: %d.\n", cid, count);
|
||||
RFIFOSKIP(fd,RFIFOW(fd,2));
|
||||
}
|
||||
return 1;
|
||||
|
@ -2717,18 +2717,29 @@ void linkdb_insert( struct linkdb_node** head, void *key, void* data)
|
||||
node->data = data;
|
||||
}
|
||||
|
||||
void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... )
|
||||
{
|
||||
int linkdb_vforeach( struct linkdb_node** head, LinkDBFunc func, va_list ap) {
|
||||
struct linkdb_node *node;
|
||||
if( head == NULL ) return;
|
||||
int retCount = 0;
|
||||
if( head == NULL )
|
||||
return 0;
|
||||
node = *head;
|
||||
while ( node ) {
|
||||
va_list args;
|
||||
va_start(args, func);
|
||||
func( node->key, node->data, args );
|
||||
va_end(args);
|
||||
va_list argscopy;
|
||||
va_copy(argscopy, ap);
|
||||
retCount += func(node->key, node->data, argscopy);
|
||||
va_end(argscopy);
|
||||
node = node->next;
|
||||
}
|
||||
return retCount;
|
||||
}
|
||||
|
||||
int linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... ) {
|
||||
va_list ap;
|
||||
int retCount = 0;
|
||||
va_start(ap, func);
|
||||
retCount = linkdb_vforeach(head, func, ap);
|
||||
va_end(ap);
|
||||
return retCount;
|
||||
}
|
||||
|
||||
void* linkdb_search( struct linkdb_node** head, void *key)
|
||||
|
@ -875,14 +875,15 @@ struct linkdb_node {
|
||||
void *data;
|
||||
};
|
||||
|
||||
typedef void (*LinkDBFunc)(void* key, void* data, va_list args);
|
||||
typedef int (*LinkDBFunc)(void* key, void* data, va_list args);
|
||||
|
||||
void linkdb_insert ( struct linkdb_node** head, void *key, void* data); // 重複を考慮しない
|
||||
void linkdb_replace( struct linkdb_node** head, void *key, void* data); // 重複を考慮する
|
||||
void* linkdb_search ( struct linkdb_node** head, void *key);
|
||||
void* linkdb_erase ( struct linkdb_node** head, void *key);
|
||||
void linkdb_final ( struct linkdb_node** head );
|
||||
void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
|
||||
int linkdb_vforeach(struct linkdb_node** head, LinkDBFunc func, va_list ap);
|
||||
int linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
|
||||
|
||||
|
||||
|
||||
|
112
src/map/chrif.c
112
src/map/chrif.c
@ -282,8 +282,6 @@ int chrif_save(struct map_session_data *sd, int flag) {
|
||||
if (chrif_isconnected()) {
|
||||
chrif_save_scdata(sd);
|
||||
chrif_skillcooldown_save(sd);
|
||||
if (flag != 3)
|
||||
chrif_bsdata_save(sd);
|
||||
chrif_req_login_operation(sd->status.account_id, sd->status.name, CHRIF_OP_LOGIN_BANK, 0, 2, sd->status.bank_vault); //save Bank data
|
||||
}
|
||||
if ( flag != 3 && !chrif_auth_logout(sd,flag == 1 ? ST_LOGOUT : ST_MAPCHANGE) )
|
||||
@ -292,6 +290,8 @@ int chrif_save(struct map_session_data *sd, int flag) {
|
||||
|
||||
chrif_check(-1); //Character is saved on reconnect.
|
||||
|
||||
chrif_bsdata_save(sd, (flag && (flag != 3)));
|
||||
|
||||
//For data sync
|
||||
if (sd->state.storage_flag == 2)
|
||||
gstorage_storagesave(sd->status.account_id, sd->status.guild_id, flag);
|
||||
@ -1619,63 +1619,63 @@ int chrif_bsdata_request(uint32 char_id) {
|
||||
/**
|
||||
* ZA 0x2b2e
|
||||
* <cmd>.W <len>.W <char_id>.L <count>.B { <bonus_script>.?B }
|
||||
* Stores bonus_script data(s) to the table when player log out
|
||||
* Stores bonus_script data(s) to the table
|
||||
* @param sd
|
||||
* @author [Cydh]
|
||||
**/
|
||||
int chrif_bsdata_save(struct map_session_data *sd) {
|
||||
uint16 i;
|
||||
uint8 count = 0;
|
||||
unsigned int tick;
|
||||
int chrif_bsdata_save(struct map_session_data *sd, bool quit) {
|
||||
uint8 i = 0;
|
||||
|
||||
chrif_check(-1);
|
||||
|
||||
if (!sd || !sd->bonus_script_num)
|
||||
if (!sd)
|
||||
return 0;
|
||||
|
||||
tick = gettick();
|
||||
// Removing...
|
||||
if (quit && sd->bonus_script.head) {
|
||||
uint16 flag = BSF_REM_ON_LOGOUT; //Remove bonus when logout
|
||||
if (battle_config.debuff_on_logout&1) //Remove negative buffs
|
||||
flag |= BSF_REM_DEBUFF;
|
||||
if (battle_config.debuff_on_logout&2) //Remove positive buffs
|
||||
flag |= BSF_REM_BUFF;
|
||||
pc_bonus_script_clear(sd, flag);
|
||||
}
|
||||
|
||||
WFIFOHEAD(char_fd, 9 + sd->bonus_script_num * sizeof(struct bonus_script_data));
|
||||
//ShowInfo("Saving %d bonus script for CID=%d\n", sd->bonus_script.count, sd->status.char_id);
|
||||
|
||||
WFIFOHEAD(char_fd, 9 + sd->bonus_script.count * sizeof(struct bonus_script_data));
|
||||
WFIFOW(char_fd, 0) = 0x2b2e;
|
||||
WFIFOL(char_fd, 4) = sd->status.char_id;
|
||||
|
||||
i = BSF_REM_ON_LOGOUT; //Remove bonus with this flag
|
||||
if (battle_config.debuff_on_logout&1) //Remove negative buffs
|
||||
i |= BSF_REM_DEBUFF;
|
||||
if (battle_config.debuff_on_logout&2) //Remove positive buffs
|
||||
i |= BSF_REM_BUFF;
|
||||
if (sd->bonus_script.count) {
|
||||
unsigned int tick = gettick();
|
||||
struct linkdb_node *node = NULL;
|
||||
|
||||
//Clear data that won't be stored
|
||||
pc_bonus_script_clear(sd, i);
|
||||
for (node = sd->bonus_script.head; node && i < MAX_PC_BONUS_SCRIPT; node = node->next) {
|
||||
const struct TimerData *timer = NULL;
|
||||
struct bonus_script_data bs;
|
||||
struct s_bonus_script_entry *entry = (struct s_bonus_script_entry *)node->data;
|
||||
|
||||
if (!sd->bonus_script_num)
|
||||
return 0;
|
||||
if (!entry || !(timer = get_timer(entry->tid)) || DIFF_TICK(timer->tick,tick) < 0)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < sd->bonus_script_num; i++) {
|
||||
const struct TimerData *timer = get_timer(sd->bonus_script[i]->tid);
|
||||
struct bonus_script_data bs;
|
||||
memset(&bs, 0, sizeof(bs));
|
||||
safestrncpy(bs.script_str, StringBuf_Value(entry->script_buf), StringBuf_Length(entry->script_buf)+1);
|
||||
bs.tick = DIFF_TICK(timer->tick, tick);
|
||||
bs.flag = entry->flag;
|
||||
bs.type = entry->type;
|
||||
bs.icon = entry->icon;
|
||||
memcpy(WFIFOP(char_fd, 9 + i * sizeof(struct bonus_script_data)), &bs, sizeof(struct bonus_script_data));
|
||||
i++;
|
||||
}
|
||||
|
||||
if (timer == NULL || DIFF_TICK(timer->tick,tick) < 0)
|
||||
continue;
|
||||
|
||||
memset(&bs, 0, sizeof(bs));
|
||||
safestrncpy(bs.script_str, StringBuf_Value(sd->bonus_script[i]->script_buf), StringBuf_Length(sd->bonus_script[i]->script_buf)+1);
|
||||
bs.tick = DIFF_TICK(timer->tick, tick);
|
||||
bs.flag = sd->bonus_script[i]->flag;
|
||||
bs.type = sd->bonus_script[i]->type;
|
||||
bs.icon = sd->bonus_script[i]->icon;
|
||||
memcpy(WFIFOP(char_fd, 9 + count * sizeof(struct bonus_script_data)), &bs, sizeof(struct bonus_script_data));
|
||||
count++;
|
||||
if (i != sd->bonus_script.count && sd->bonus_script.count > MAX_PC_BONUS_SCRIPT)
|
||||
ShowWarning("Only allowed to save %d (mmo.h::MAX_PC_BONUS_SCRIPT) bonus script each player.\n", MAX_PC_BONUS_SCRIPT);
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
WFIFOB(char_fd, 8) = count;
|
||||
WFIFOW(char_fd, 2) = 9 + sd->bonus_script_num * sizeof(struct bonus_script_data);
|
||||
WFIFOSET(char_fd, WFIFOW(char_fd, 2));
|
||||
}
|
||||
|
||||
// Clear All
|
||||
pc_bonus_script_clear_all(sd,3);
|
||||
WFIFOB(char_fd, 8) = i;
|
||||
WFIFOW(char_fd, 2) = 9 + sd->bonus_script.count * sizeof(struct bonus_script_data);
|
||||
WFIFOSET(char_fd, WFIFOW(char_fd, 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1690,8 +1690,7 @@ int chrif_bsdata_save(struct map_session_data *sd) {
|
||||
int chrif_bsdata_received(int fd) {
|
||||
struct map_session_data *sd;
|
||||
uint32 cid = RFIFOL(fd,4);
|
||||
uint8 i, count = 0;
|
||||
bool calc = false;
|
||||
uint8 count = 0;
|
||||
|
||||
sd = map_charid2sd(cid);
|
||||
|
||||
@ -1700,19 +1699,28 @@ int chrif_bsdata_received(int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
count = RFIFOB(fd,8);
|
||||
if ((count = RFIFOB(fd,8))) {
|
||||
struct s_bonus_script *list = NULL;
|
||||
uint8 i = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct bonus_script_data *bs = (struct bonus_script_data*)RFIFOP(fd,9 + i*sizeof(struct bonus_script_data));
|
||||
//ShowInfo("Loaded %d bonus script for CID=%d\n", count, sd->status.char_id);
|
||||
|
||||
if (bs->script_str[0] == '\0' || !bs->tick)
|
||||
continue;
|
||||
for (i = 0; i < count; i++) {
|
||||
struct bonus_script_data *bs = (struct bonus_script_data*)RFIFOP(fd,9 + i*sizeof(struct bonus_script_data));
|
||||
struct s_bonus_script_entry *entry = NULL;
|
||||
|
||||
if (pc_bonus_script_add(sd, bs->script_str, bs->tick, (enum si_type)bs->icon, bs->flag, bs->type))
|
||||
calc = true;
|
||||
if (bs->script_str[0] == '\0' || !bs->tick)
|
||||
continue;
|
||||
|
||||
if (!(entry = pc_bonus_script_add(sd, bs->script_str, bs->tick, (enum si_type)bs->icon, bs->flag, bs->type)))
|
||||
continue;
|
||||
|
||||
linkdb_insert(&sd->bonus_script.head, (void *)((intptr_t)entry), entry);
|
||||
}
|
||||
|
||||
if (sd->bonus_script.head)
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
}
|
||||
if (calc)
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ int chrif_req_charunban(int aid, const char* character_name);
|
||||
int chrif_load_bankdata(int fd);
|
||||
|
||||
int chrif_bsdata_request(uint32 char_id);
|
||||
int chrif_bsdata_save(struct map_session_data *sd);
|
||||
int chrif_bsdata_save(struct map_session_data *sd, bool quit);
|
||||
|
||||
void do_final_chrif(void);
|
||||
void do_init_chrif(void);
|
||||
|
@ -1945,11 +1945,12 @@ int guild_castledatasave(int castle_id, int index, int value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void guild_castle_reconnect_sub(void *key, void *data, va_list ap) {
|
||||
int guild_castle_reconnect_sub(void *key, void *data, va_list ap) {
|
||||
int castle_id = GetWord((int)__64BPRTSIZE(key), 0);
|
||||
int index = GetWord((int)__64BPRTSIZE(key), 1);
|
||||
intif_guild_castle_datasave(castle_id, index, *(int *)data);
|
||||
aFree(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
300
src/map/pc.c
300
src/map/pc.c
@ -1263,9 +1263,9 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
|
||||
sd->status.cashshop_sent = false;
|
||||
|
||||
sd->last_addeditem_index = -1;
|
||||
|
||||
sd->bonus_script = NULL;
|
||||
sd->bonus_script_num = 0;
|
||||
|
||||
sd->bonus_script.head = NULL;
|
||||
sd->bonus_script.count = 0;
|
||||
|
||||
// Request all registries (auth is considered completed whence they arrive)
|
||||
intif_request_registry(sd,7);
|
||||
@ -11039,6 +11039,16 @@ void pc_show_version(struct map_session_data *sd) {
|
||||
clif_displaymessage(sd->fd,buf);
|
||||
}
|
||||
|
||||
int pc_bonus_script_list(void *key, void *data, va_list ap) {
|
||||
struct s_bonus_script_entry *entry = (struct s_bonus_script_entry *)data;
|
||||
struct map_session_data *sd = va_arg(ap, struct map_session_data *);
|
||||
struct linkdb_node *node = (struct linkdb_node *)key;
|
||||
if (sd)
|
||||
ShowDebug(" cid=%d aid=%d\n",sd->status.char_id, sd->status.account_id);
|
||||
ShowDebug(" key:%d e:0x%08X n:0x%08X nn:0x%08X np:0x%08X\n",(intptr_t)key, entry, key, node->next, node->prev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run bonus_script on player
|
||||
* @param sd
|
||||
@ -11047,22 +11057,32 @@ void pc_show_version(struct map_session_data *sd) {
|
||||
void pc_bonus_script(struct map_session_data *sd) {
|
||||
uint8 i = 0;
|
||||
int now = gettick();
|
||||
struct linkdb_node *node = NULL, *next = NULL;
|
||||
|
||||
if (!sd || !sd->bonus_script_num)
|
||||
if (!sd || !(node = sd->bonus_script.head))
|
||||
return;
|
||||
|
||||
for (i = 0; i < sd->bonus_script_num; i++) {
|
||||
if (sd->bonus_script[i]->tid == INVALID_TIMER) { // Start new timer for new bonus_script
|
||||
sd->bonus_script[i]->tick += now;
|
||||
sd->bonus_script[i]->tid = add_timer(sd->bonus_script[i]->tick, pc_bonus_script_timer, sd->bl.id, 0);
|
||||
if (sd->bonus_script[i]->icon != SI_BLANK) //Gives status icon if exist
|
||||
clif_status_change(&sd->bl, sd->bonus_script[i]->icon, 1, sd->bonus_script[i]->tick, 1, 0, 0);
|
||||
while (node) {
|
||||
struct s_bonus_script_entry *entry = NULL;
|
||||
next = node->next;
|
||||
|
||||
if ((entry = (struct s_bonus_script_entry *)node->data)) {
|
||||
// Only start timer for new bonus_script
|
||||
if (entry->tid == INVALID_TIMER) {
|
||||
if (entry->icon != SI_BLANK) // Gives status icon if exist
|
||||
clif_status_change(&sd->bl, entry->icon, 1, entry->tick, 1, 0, 0);
|
||||
|
||||
entry->tick += now;
|
||||
entry->tid = add_timer(entry->tick, pc_bonus_script_timer, sd->bl.id, (intptr_t)entry);
|
||||
}
|
||||
|
||||
if (entry->script)
|
||||
run_script(entry->script, 0, sd->bl.id, 0);
|
||||
else
|
||||
ShowError("pc_bonus_script: The script has been removed somewhere. \"%s\"\n", StringBuf_Value(entry->script_buf));
|
||||
}
|
||||
if (!sd->bonus_script[i]->script) {
|
||||
ShowError("pc_bonus_script: The script has been removed somewhere. \"%s\"\n", StringBuf_Value(sd->bonus_script[i]->script_buf));
|
||||
continue;
|
||||
}
|
||||
run_script(sd->bonus_script[i]->script, 0, sd->bl.id, 0);
|
||||
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11074,126 +11094,93 @@ void pc_bonus_script(struct map_session_data *sd) {
|
||||
* @param icon SI
|
||||
* @param flag Flags @see enum e_bonus_script_flags
|
||||
* @param type 0 - None, 1 - Buff, 2 - Debuff
|
||||
* @return True if added, False if cannot
|
||||
* @return New created entry pointer or NULL if failed or NULL if duplicate fail
|
||||
* @author [Cydh]
|
||||
**/
|
||||
bool pc_bonus_script_add(struct map_session_data *sd, const char *script_str, uint32 dur, enum si_type icon, uint16 flag, uint8 type) {
|
||||
struct s_bonus_script_entry *pc_bonus_script_add(struct map_session_data *sd, const char *script_str, uint32 dur, enum si_type icon, uint16 flag, uint8 type) {
|
||||
struct script_code *script = NULL;
|
||||
struct linkdb_node *node = NULL;
|
||||
struct s_bonus_script_entry *entry = NULL;
|
||||
|
||||
if (!sd)
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
if (!(script = parse_script(script_str, "bonus_script", 0, SCRIPT_IGNORE_EXTERNAL_BRACKETS))) {
|
||||
ShowError("pc_bonus_script_add: Failed to parse script '%s' (CID:%d).\n", script_str, sd->status.char_id);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!sd->bonus_script_num)
|
||||
CREATE(sd->bonus_script, struct s_bonus_script *, 1);
|
||||
else {
|
||||
uint8 i = 0;
|
||||
for (i = 0; i < sd->bonus_script_num; i++) {
|
||||
if (strcmpi(script_str, StringBuf_Value(sd->bonus_script[i]->script_buf)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Duplication checks
|
||||
if (i < sd->bonus_script_num) {
|
||||
int newdur = gettick() + dur;
|
||||
if (flag&BSF_FORCE_REPLACE && sd->bonus_script[i]->tick < newdur) {
|
||||
settick_timer(sd->bonus_script[i]->tid, newdur);
|
||||
script_free_code(script);
|
||||
return true;
|
||||
}
|
||||
else if (flag&BSF_FORCE_DUPLICATE) {
|
||||
;
|
||||
}
|
||||
else {
|
||||
// No duplicate bonus
|
||||
script_free_code(script);
|
||||
return false;
|
||||
// Duplication checks
|
||||
if ((node = sd->bonus_script.head)) {
|
||||
while (node) {
|
||||
entry = (struct s_bonus_script_entry *)node->data;
|
||||
if (strcmpi(script_str, StringBuf_Value(entry->script_buf)) == 0) {
|
||||
int newdur = gettick() + dur;
|
||||
if (flag&BSF_FORCE_REPLACE && entry->tick < newdur) { // Change duration
|
||||
settick_timer(entry->tid, newdur);
|
||||
script_free_code(script);
|
||||
return NULL;
|
||||
}
|
||||
else if (flag&BSF_FORCE_DUPLICATE) // Allow duplicate
|
||||
break;
|
||||
else { // No duplicate bonus
|
||||
script_free_code(script);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
if (i >= UINT8_MAX) {
|
||||
ShowError("pc_bonus_script_add: Reached max (%d) possible bonuses for this player %d\n", UINT8_MAX);
|
||||
script_free_code(script);
|
||||
return false;
|
||||
}
|
||||
|
||||
RECREATE(sd->bonus_script, struct s_bonus_script *, sd->bonus_script_num+1);
|
||||
}
|
||||
|
||||
CREATE(sd->bonus_script[sd->bonus_script_num], struct s_bonus_script, 1);
|
||||
CREATE(entry, struct s_bonus_script_entry, 1);
|
||||
|
||||
sd->bonus_script[sd->bonus_script_num]->script_buf = StringBuf_Malloc();
|
||||
StringBuf_AppendStr(sd->bonus_script[sd->bonus_script_num]->script_buf, script_str);
|
||||
sd->bonus_script[sd->bonus_script_num]->tid = INVALID_TIMER;
|
||||
sd->bonus_script[sd->bonus_script_num]->flag = flag;
|
||||
sd->bonus_script[sd->bonus_script_num]->icon = icon;
|
||||
sd->bonus_script[sd->bonus_script_num]->tick = dur; // Use duration first, on run change to expire time
|
||||
sd->bonus_script[sd->bonus_script_num]->type = type;
|
||||
sd->bonus_script[sd->bonus_script_num]->script = script;
|
||||
|
||||
sd->bonus_script_num++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move bonus_script allocation to empty space
|
||||
* @param sd
|
||||
* @author [Cydh]
|
||||
**/
|
||||
static void pc_bonus_script_move(struct map_session_data *sd) {
|
||||
if (sd && sd->bonus_script_num) {
|
||||
uint8 i, cur;
|
||||
|
||||
for (i = 0, cur = 0; i < sd->bonus_script_num; i++) {
|
||||
if (sd->bonus_script[i] == NULL)
|
||||
continue;
|
||||
|
||||
if (i != cur)
|
||||
sd->bonus_script[cur] = sd->bonus_script[i];
|
||||
|
||||
cur++;
|
||||
}
|
||||
|
||||
if (!(sd->bonus_script_num = cur)) {
|
||||
aFree(sd->bonus_script);
|
||||
sd->bonus_script = NULL;
|
||||
sd->bonus_script_num = 0;
|
||||
}
|
||||
}
|
||||
entry->script_buf = StringBuf_Malloc();
|
||||
StringBuf_AppendStr(entry->script_buf, script_str);
|
||||
entry->tid = INVALID_TIMER;
|
||||
entry->flag = flag;
|
||||
entry->icon = icon;
|
||||
entry->tick = dur; // Use duration first, on run change to expire time
|
||||
entry->type = type;
|
||||
entry->script = script;
|
||||
sd->bonus_script.count++;
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove bonus_script data from player
|
||||
* @param sd: Target player
|
||||
* @param idx: Bonus script idx in player array
|
||||
* @param list: Bonus script entry from player
|
||||
* @author [Cydh]
|
||||
**/
|
||||
static void pc_bonus_script_remove(struct map_session_data *sd, uint8 idx) {
|
||||
uint8 i = 0, cursor = 0;
|
||||
void pc_bonus_script_free_entry(struct map_session_data *sd, struct s_bonus_script_entry *entry) {
|
||||
if (entry->tid != INVALID_TIMER)
|
||||
delete_timer(entry->tid, pc_bonus_script_timer);
|
||||
|
||||
if (!sd || !sd->bonus_script_num)
|
||||
return;
|
||||
if (entry->script)
|
||||
script_free_code(entry->script);
|
||||
|
||||
if (idx >= sd->bonus_script_num) {
|
||||
ShowError("pc_bonus_script_remove: Invalid index: %d\n", idx);
|
||||
return;
|
||||
if (entry->script_buf)
|
||||
StringBuf_Free(entry->script_buf);
|
||||
|
||||
if (sd) {
|
||||
if (entry->icon != SI_BLANK)
|
||||
clif_status_load(&sd->bl, entry->icon, 0);
|
||||
if (sd->bonus_script.count > 0)
|
||||
sd->bonus_script.count--;
|
||||
}
|
||||
aFree(entry);
|
||||
}
|
||||
|
||||
if (sd->bonus_script[idx]->tid != INVALID_TIMER)
|
||||
delete_timer(sd->bonus_script[idx]->tid, pc_bonus_script_timer);
|
||||
|
||||
if (sd->bonus_script[idx]->icon != SI_BLANK)
|
||||
clif_status_load(&sd->bl, sd->bonus_script[idx]->icon, 0);
|
||||
|
||||
script_free_code(sd->bonus_script[idx]->script);
|
||||
StringBuf_Free(sd->bonus_script[idx]->script_buf);
|
||||
|
||||
aFree(sd->bonus_script[idx]);
|
||||
sd->bonus_script[idx] = NULL;
|
||||
/**
|
||||
* Do final process if no entry left
|
||||
* @param sd
|
||||
**/
|
||||
static void inline pc_bonus_script_check_final(struct map_session_data *sd) {
|
||||
if (sd->bonus_script.count == 0) {
|
||||
if (sd->bonus_script.head && sd->bonus_script.head->data)
|
||||
pc_bonus_script_free_entry(sd, (struct s_bonus_script_entry *)sd->bonus_script.head->data);
|
||||
linkdb_final(&sd->bonus_script.head);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -11205,8 +11192,8 @@ static void pc_bonus_script_remove(struct map_session_data *sd, uint8 idx) {
|
||||
* @author [Cydh]
|
||||
**/
|
||||
int pc_bonus_script_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
uint8 i;
|
||||
struct map_session_data *sd;
|
||||
struct s_bonus_script_entry *entry = (struct s_bonus_script_entry *)data;
|
||||
|
||||
sd = map_id2sd(id);
|
||||
if (!sd) {
|
||||
@ -11214,21 +11201,17 @@ int pc_bonus_script_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tid == INVALID_TIMER || !sd->bonus_script_num)
|
||||
if (tid == INVALID_TIMER)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < sd->bonus_script_num; i++) {
|
||||
if (sd->bonus_script[i]->tid == tid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == sd->bonus_script_num) {
|
||||
ShowError("pc_bonus_script_timer: Timer %d is not found.\n", tid);
|
||||
if (!sd->bonus_script.head || entry == NULL) {
|
||||
ShowError("pc_bonus_script_timer: Invalid entry pointer 0x%08X!\n", entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pc_bonus_script_remove(sd, i);
|
||||
pc_bonus_script_move(sd);
|
||||
linkdb_erase(&sd->bonus_script.head, (void *)((intptr_t)entry));
|
||||
pc_bonus_script_free_entry(sd, entry);
|
||||
pc_bonus_script_check_final(sd);
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
return 0;
|
||||
}
|
||||
@ -11240,27 +11223,37 @@ int pc_bonus_script_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
* @author [Cydh]
|
||||
**/
|
||||
void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag) {
|
||||
uint8 i, count = 0;
|
||||
if (!sd || !sd->bonus_script_num)
|
||||
struct linkdb_node *node = NULL;
|
||||
uint16 count = 0;
|
||||
|
||||
if (!sd || !(node = sd->bonus_script.head))
|
||||
return;
|
||||
|
||||
for (i = 0; i < sd->bonus_script_num; i++) {
|
||||
if ((flag&sd->bonus_script[i]->flag) || // Matched flag
|
||||
(sd->bonus_script[i]->type && (
|
||||
(flag&BSF_REM_BUFF && sd->bonus_script[i]->type == 1) || // Buff type
|
||||
(flag&BSF_REM_DEBUFF && sd->bonus_script[i]->type == 2)) // Debuff type
|
||||
))
|
||||
while (node) {
|
||||
struct linkdb_node *next = node->next;
|
||||
struct s_bonus_script_entry *entry = (struct s_bonus_script_entry *)node->data;
|
||||
|
||||
if (entry && (
|
||||
(flag == BSF_PERMANENT) || // Remove all with permanent bonus
|
||||
(!flag && !(entry->flag&BSF_PERMANENT)) || // Remove all WITHOUT permanent bonus
|
||||
(flag&entry->flag) || // Matched flag
|
||||
(flag&BSF_REM_BUFF && entry->type == 1) || // Remove buff
|
||||
(flag&BSF_REM_DEBUFF && entry->type == 2) // Remove debuff
|
||||
)
|
||||
)
|
||||
{
|
||||
pc_bonus_script_remove(sd, i);
|
||||
linkdb_erase(&sd->bonus_script.head, (void *)((intptr_t)entry));
|
||||
pc_bonus_script_free_entry(sd, entry);
|
||||
count++;
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
if (count) {
|
||||
pc_bonus_script_move(sd);
|
||||
if (!(flag&BSF_REM_ON_LOGOUT)) { //Don't need to do this if log out
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
pc_bonus_script_check_final(sd);
|
||||
|
||||
if (count && !(flag&BSF_REM_ON_LOGOUT)) //Don't need to do this if log out
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -11270,21 +11263,34 @@ void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag) {
|
||||
* @author [Cydh]
|
||||
**/
|
||||
void pc_bonus_script_clear_all(struct map_session_data *sd, uint8 flag) {
|
||||
uint8 i, count = 0;
|
||||
if (!sd || !sd->bonus_script_num)
|
||||
struct linkdb_node *node = NULL;
|
||||
uint16 count = 0;
|
||||
|
||||
if (!sd || !(node = sd->bonus_script.head))
|
||||
return;
|
||||
|
||||
for (i = 0; i < sd->bonus_script_num; i++) {
|
||||
if (!(flag&1) && (sd->bonus_script[i]->flag&BSF_PERMANENT))
|
||||
continue;
|
||||
pc_bonus_script_remove(sd, i);
|
||||
count++;
|
||||
}
|
||||
if (count) {
|
||||
pc_bonus_script_move(sd);
|
||||
if (!(flag&2))
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
while (node) {
|
||||
struct linkdb_node *next = node->next;
|
||||
struct s_bonus_script_entry *entry = (struct s_bonus_script_entry *)node->data;
|
||||
|
||||
if (entry && (
|
||||
!(entry->flag&BSF_PERMANENT) ||
|
||||
((flag&1) && entry->flag&BSF_PERMANENT)
|
||||
)
|
||||
)
|
||||
{
|
||||
linkdb_erase(&sd->bonus_script.head, (void *)((intptr_t)entry));
|
||||
pc_bonus_script_free_entry(sd, entry);
|
||||
count++;
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
|
||||
pc_bonus_script_check_final(sd);
|
||||
|
||||
if (count && !(flag&2))
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
}
|
||||
|
||||
/** [Cydh]
|
||||
|
16
src/map/pc.h
16
src/map/pc.h
@ -158,7 +158,7 @@ struct s_pc_itemgrouphealrate {
|
||||
};
|
||||
|
||||
///Timed bonus 'bonus_script' struct [Cydh]
|
||||
struct s_bonus_script {
|
||||
struct s_bonus_script_entry {
|
||||
struct script_code *script;
|
||||
StringBuf *script_buf; //Used for comparing and storing on table
|
||||
uint32 tick;
|
||||
@ -604,9 +604,13 @@ struct map_session_data {
|
||||
struct vip_info vip;
|
||||
bool disableshowrate; //State to disable clif_display_pinfo(). [Cydh]
|
||||
#endif
|
||||
struct s_bonus_script **bonus_script; ///Bonus Script [Cydh]
|
||||
uint8 bonus_script_num;
|
||||
|
||||
|
||||
/// Bonus Script [Cydh]
|
||||
struct s_bonus_script_list {
|
||||
struct linkdb_node *head; ///< Bonus script head node. data: struct s_bonus_script_entry *entry, key: (intptr_t)entry
|
||||
uint16 count;
|
||||
} bonus_script;
|
||||
|
||||
struct s_pc_itemgrouphealrate **itemgrouphealrate; /// List of Item Group Heal rate bonus
|
||||
uint8 itemgrouphealrate_count; /// Number of rate bonuses
|
||||
|
||||
@ -1121,9 +1125,9 @@ void pc_show_version(struct map_session_data *sd);
|
||||
|
||||
int pc_bonus_script_timer(int tid, unsigned int tick, int id, intptr_t data);
|
||||
void pc_bonus_script(struct map_session_data *sd);
|
||||
bool pc_bonus_script_add(struct map_session_data *sd, const char *script_str, uint32 dur, enum si_type icon, uint16 flag, uint8 type);
|
||||
struct s_bonus_script_entry *pc_bonus_script_add(struct map_session_data *sd, const char *script_str, uint32 dur, enum si_type icon, uint16 flag, uint8 type);
|
||||
void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag);
|
||||
void pc_bonus_script_clear_all(struct map_session_data *sd, uint8 flag);
|
||||
int pc_bonus_script_list(void *key, void *data, va_list ap);
|
||||
|
||||
void pc_cell_basilica(struct map_session_data *sd);
|
||||
|
||||
|
@ -18909,6 +18909,7 @@ BUILDIN_FUNC(bonus_script) {
|
||||
uint8 type = 0;
|
||||
TBL_PC* sd;
|
||||
const char *script_str = NULL;
|
||||
struct s_bonus_script_entry *entry = NULL;
|
||||
|
||||
if (script_hasdata(st,7)) {
|
||||
if (!(sd = map_charid2sd(script_getnum(st,7)))) {
|
||||
@ -18942,8 +18943,10 @@ BUILDIN_FUNC(bonus_script) {
|
||||
if (icon <= SI_BLANK || icon >= SI_MAX)
|
||||
icon = SI_BLANK;
|
||||
|
||||
if (pc_bonus_script_add(sd, script_str, dur, (enum si_type)icon, flag, type))
|
||||
if ((entry = pc_bonus_script_add(sd, script_str, dur, (enum si_type)icon, flag, type))) {
|
||||
linkdb_insert(&sd->bonus_script.head, (void *)((intptr_t)entry), entry);
|
||||
status_calc_pc(sd,SCO_NONE);
|
||||
}
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -18969,7 +18972,7 @@ BUILDIN_FUNC(bonus_script_clear) {
|
||||
if (sd == NULL)
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
|
||||
pc_bonus_script_clear_all(sd,(flag ? 1 : 0));
|
||||
pc_bonus_script_clear(sd,(flag ? BSF_PERMANENT : BSF_REM_ALL));
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1762,7 +1762,7 @@ enum e_bonus_script_flags {
|
||||
BSF_FORCE_DUPLICATE = 0x800, ///< Force to add duplicated script
|
||||
|
||||
// These flags aren't part of 'bonus_script' scripting flags
|
||||
|
||||
BSF_REM_ALL = 0x0, ///< Remove all bonus script
|
||||
BSF_REM_BUFF = 0x4000, ///< Remove positive buff if battle_config.debuff_on_logout&1
|
||||
BSF_REM_DEBUFF = 0x8000, ///< Remove negative buff if battle_config.debuff_on_logout&2
|
||||
};
|
||||
|
@ -3169,6 +3169,10 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
sd->num_quests = sd->avail_quests = 0;
|
||||
}
|
||||
|
||||
// Clearing...
|
||||
if (sd->bonus_script.head)
|
||||
pc_bonus_script_clear(sd, BSF_REM_ALL);
|
||||
|
||||
pc_itemgrouphealrate_clear(sd);
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user