Skip to content

Commit

Permalink
Merge pull request #263 from rathena/cleanup/bonus_script
Browse files Browse the repository at this point in the history
Bonus Script clean up
* Removed fixed array size (MAX_PC_BONUS_SCRIPT) of bonus_script on players, changed to link list.
* Changed fixed script string on player's bonus_script to StringBuf, reduce memory usage for each connected player.
* Added new flags to expand duplicated script and flag to allow duplicate script.
* Reduced buf length from 1024 to 512 on bonus_script_data (used for saving/loading bonus_script from char-server). Still, MAX_PC_BONUS_SCRIPT is used to gives limit data can be loaded.
* 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 quitting will removes the bonus that won't be saved on logout.
* Fixed Superstar_Snack (22843) and Sealed_Dracula_Card (22846) fields

NOTE:
Please import 'upgrade_20150131.sql' for `bonus_script` table changes

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>
  • Loading branch information
cydh committed Feb 13, 2015
2 parents 12a0b05 + 4726f4c commit bf6d2f0
Show file tree
Hide file tree
Showing 20 changed files with 537 additions and 345 deletions.
2 changes: 2 additions & 0 deletions db/const.txt
Expand Up @@ -4643,6 +4643,8 @@ BSF_REM_ON_LUXANIMA 0x040
BSF_REM_ON_MADOGEAR 0x080
BSF_REM_ON_DAMAGED 0x100
BSF_PERMANENT 0x200
BSF_FORCE_REPLACE 0x400
BSF_FORCE_DUPLICATE 0x800

false 0
true 1
4 changes: 2 additions & 2 deletions db/re/item_db.txt
Expand Up @@ -9878,10 +9878,10 @@
22837,Integer_Time,Integer Time,2,10,,100,,,,,,,,,,,,,{ getitem 673,5; },{},{}
22838,Something_Present_Candy_Holders,Something Present Candy Holders,2,10,,100,,,,,,,,,,,,,{},{},{}
22842,Sealed_Dracula_Scroll_II,Sealed Dracula Scroll II,2,10,,10,,,,,,,,,,,,,{ getitem callfunc("F_Rand",22846,6228,6232,24223,24227,17474/*, Enchant Letter*/),1; },{},{}
22843,Superstar_Snack,Superstar Snack,2,10,,10,,,,,,,,,,,,,{ bonus_script "{ bonus bAtk2,50; bonus bMatk,50; }",300; },{},{}
22843,Superstar_Snack,Superstar Snack,2,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ bonus_script "{ bonus bAtk2,50; bonus bMatk,50; }",300; },{},{}
22844,Sealed_Dracula_Card_Album,Sealed Dracula Card Album,2,10,,10,,,,,,,,,,,,,{/*No Info*/},{},{}
22845,Sealed_Fortune_Egg,Sealed Fortune Egg,2,10,,10,,,,,,,,,,,,,{ getitem callfunc("F_Rand",4488,4497,4486,4480,4485,4539,4487,4494,4538,4489,4490,4482,4503,22846),1; },{},{}
22846,Sealed_Dracula_Card,Sealed Dracula Card,2,10,,10,,,,,,,,,,,,,{ bonus_script "{ bonus3 bSPDrainRate,50,5,0; }",300; },{},{}
22846,Sealed_Dracula_Card,Sealed Dracula Card,2,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ bonus_script "{ bonus3 bSPDrainRate,50,5,0; }",300; },{},{}
// Shadow Equip
24000,T_STR1_Armor_Shadow,T STR1 Armor Shadow,12,10,,0,,,,0,0xFFFFFFFF,63,2,65536,,1,,,{ bonus bStr,1; },{},{}
24001,T_DEX1_Weapon_Shadow,T DEX1 Weapon Shadow,12,10,,0,,,,0,0xFFFFFFFF,63,2,131072,,1,,,{ bonus bDex,1; },{},{}
Expand Down
8 changes: 4 additions & 4 deletions doc/packet_interserv.txt
Expand Up @@ -2491,9 +2491,9 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.

0x2b2f
Type: AZ
Structure: <cmd>.W <len>.W <cid>.L <count>.W
Structure: <cmd>.W <len>.W <cid>.L <count>.B { <bonus_script_data>.?B }
index: 0,2,4,8
len: variable: 10+50*bonus_script_data
len: variable: 9+count*bonus_script_data
parameter:
- cmd : packet identification (0x2b2f)
desc:
Expand Down Expand Up @@ -2840,9 +2840,9 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.

0x2b2e
Type: ZA
Structure: <cmd>.W <len>.W <char_id>.L <count>.W
Structure: <cmd>.W <len>.W <char_id>.L <count>.B { <bonus_script_data>.?B }
index: 0,2,4,8
len: variable: 10+MAX_PC_BONUS_SCRIPT*bonus_script_data
len: variable: 9+count*bonus_script_data
parameter:
- cmd : packet identification (0x2b2e)
- len
Expand Down
14 changes: 7 additions & 7 deletions doc/script_commands.txt
Expand Up @@ -5350,20 +5350,20 @@ After that time, the script will automatically expire. The same bonus cannot be
stacked. By default, this bonus will be stored on `bonus_script` table when player
logs out.

Note that the maximum number of 'bonus_script' commands that can run simultaneously
for a player is 10 (MAX_PC_BONUS_SCRIPT in 'src/map/pc.h').

Flags (bitmask):
1 : Remove when dead.
2 : Removable by Dispell.
4 : Removable by Clearance.
8 : Remove when player logs out.
16 : Removeable by Banishing Buster.
32 : Removable by Refresh.
128 : Removable by Luxanima.
256 : Remove when Madogear is activated or deactivated.
512 : Remove when receive damage.
1024: Script is permanent, cannot be cleared by bonus_script_clear
64 : Removable by Luxanima.
128 : Remove when Madogear is activated or deactivated.
256 : Remove when receive damage.
512 : Script is permanent, cannot be cleared by bonus_script_clear.
1024: Force to replace duplicated script by expanding the duration.
2048: Force to add duplicated script. This flag cannot be stacked with 1024,
if both are defined, 1024 will be checked first and ignore this flag.

Types:
This will be used to decide negative or positive buff for 'debuff_on_logout'.
Expand Down
4 changes: 2 additions & 2 deletions sql-files/item_db_re.sql
Expand Up @@ -9909,10 +9909,10 @@ REPLACE INTO `item_db_re` VALUES (22829,'Sealed_Card_Album','Sealed Card Album',
REPLACE INTO `item_db_re` VALUES (22837,'Integer_Time','Integer Time',2,10,NULL,100,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'getitem 673,5;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22838,'Something_Present_Candy_Holders','Something Present Candy Holders',2,10,NULL,100,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22842,'Sealed_Dracula_Scroll_II','Sealed Dracula Scroll II',2,10,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'getitem callfunc("F_Rand",22846,6228,6232,24223,24227,17474/*, Enchant Letter*/),1;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22843,'Superstar_Snack','Superstar Snack',2,10,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'bonus_script "{ bonus bAtk2,50; bonus bMatk,50; }",300;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22843,'Superstar_Snack','Superstar Snack',2,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'bonus_script "{ bonus bAtk2,50; bonus bMatk,50; }",300;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22844,'Sealed_Dracula_Card_Album','Sealed Dracula Card Album',2,10,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'/*No Info*/',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22845,'Sealed_Fortune_Egg','Sealed Fortune Egg',2,10,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'getitem callfunc("F_Rand",4488,4497,4486,4480,4485,4539,4487,4494,4538,4489,4490,4482,4503,22846),1;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22846,'Sealed_Dracula_Card','Sealed Dracula Card',2,10,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'bonus_script "{ bonus3 bSPDrainRate,50,5,0; }",300;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22846,'Sealed_Dracula_Card','Sealed Dracula Card',2,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'bonus_script "{ bonus3 bSPDrainRate,50,5,0; }",300;',NULL,NULL);
# Shadow Equip
REPLACE INTO `item_db_re` VALUES (24000,'T_STR1_Armor_Shadow','T STR1 Armor Shadow',12,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,65536,NULL,'1',NULL,NULL,'bonus bStr,1;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (24001,'T_DEX1_Weapon_Shadow','T DEX1 Weapon Shadow',12,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,131072,NULL,'1',NULL,NULL,'bonus bDex,1;',NULL,NULL);
Expand Down
12 changes: 6 additions & 6 deletions sql-files/main.sql
Expand Up @@ -706,12 +706,12 @@ CREATE TABLE IF NOT EXISTS `interreg` (
--

CREATE TABLE IF NOT EXISTS `bonus_script` (
`char_id` varchar(11) NOT NULL,
`script` varchar(1024) NOT NULL,
`tick` varchar(11) NOT NULL DEFAULT '0',
`flag` varchar(3) NOT NULL DEFAULT '0',
`type` char(1) NOT NULL DEFAULT '0',
`icon` varchar(3) NOT NULL DEFAULT '-1'
`char_id` INT(11) UNSIGNED NOT NULL,
`script` TEXT NOT NULL,
`tick` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`flag` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0',
`type` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
`icon` SMALLINT(3) NOT NULL DEFAULT '-1'
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `vending_items` (
Expand Down
6 changes: 6 additions & 0 deletions sql-files/upgrades/upgrade_20150131.sql
@@ -0,0 +1,6 @@
ALTER TABLE `bonus_script` MODIFY COLUMN `char_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `bonus_script` MODIFY COLUMN `script` TEXT NOT NULL;
ALTER TABLE `bonus_script` MODIFY COLUMN `tick` INT(11) UNSIGNED NOT NULL DEFAULT '0';
ALTER TABLE `bonus_script` MODIFY COLUMN `flag` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0';
ALTER TABLE `bonus_script` MODIFY COLUMN `type` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0';
ALTER TABLE `bonus_script` MODIFY COLUMN `icon` SMALLINT(3) NOT NULL DEFAULT '-1';
127 changes: 76 additions & 51 deletions src/char/char_mapif.c
Expand Up @@ -1242,91 +1242,116 @@ int chmapif_parse_reqcharunban(int fd){
return 1;
}

/** [Cydh]
* Get bonus_script data(s) from table to load
* @param fd
*/
/**
* ZA 0x2b2d
* <cmd>.W <char_id>.L
* AZ 0x2b2f
* <cmd>.W <len>.W <cid>.L <count>.B { <bonus_script_data>.?B }
* Get bonus_script data(s) from table to load then send to player
* @param fd
* @author [Cydh]
**/
int chmapif_bonus_script_get(int fd) {
if (RFIFOREST(fd) < 6)
return 0;
else {
int cid;
cid = RFIFOL(fd,2);
uint8 num_rows = 0;
uint32 cid = RFIFOL(fd,2);
struct bonus_script_data tmp_bsdata;
SqlStmt* stmt = SqlStmt_Malloc(sql_handle);

RFIFOSKIP(fd,6);

if (SQL_ERROR == Sql_Query(sql_handle,"SELECT `script`, `tick`, `flag`, `type`, `icon` FROM `%s` WHERE `char_id`='%d'",
schema_config.bonus_script_db,cid))
if (SQL_ERROR == SqlStmt_Prepare(stmt,
"SELECT `script`, `tick`, `flag`, `type`, `icon` FROM `%s` WHERE `char_id` = '%d' LIMIT %d",
schema_config.bonus_script_db, cid, MAX_PC_BONUS_SCRIPT) ||
SQL_ERROR == SqlStmt_Execute(stmt) ||
SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &tmp_bsdata.script_str, sizeof(tmp_bsdata.script_str), NULL, NULL) ||
SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_UINT32, &tmp_bsdata.tick, 0, NULL, NULL) ||
SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_UINT16, &tmp_bsdata.flag, 0, NULL, NULL) ||
SQL_ERROR == SqlStmt_BindColumn(stmt, 3, SQLDT_UINT8, &tmp_bsdata.type, 0, NULL, NULL) ||
SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_INT16, &tmp_bsdata.icon, 0, NULL, NULL)
)
{
Sql_ShowDebug(sql_handle);
SqlStmt_ShowDebug(stmt);
SqlStmt_Free(stmt);
return 1;
}
if (Sql_NumRows(sql_handle) > 0) {
struct bonus_script_data bsdata;
int count;
char *data;

WFIFOHEAD(fd,10+50*sizeof(struct bonus_script_data));
WFIFOW(fd,0) = 0x2b2f;
WFIFOL(fd,4) = cid;
for (count = 0; count < MAX_PC_BONUS_SCRIPT && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count) {
Sql_GetData(sql_handle,0,&data,NULL); memcpy(bsdata.script,data,strlen(data)+1);
Sql_GetData(sql_handle,1,&data,NULL); bsdata.tick = atoi(data);
Sql_GetData(sql_handle,2,&data,NULL); bsdata.flag = atoi(data);
Sql_GetData(sql_handle,3,&data,NULL); bsdata.type = atoi(data);
Sql_GetData(sql_handle,4,&data,NULL); bsdata.icon = atoi(data);
memcpy(WFIFOP(fd,10+count*sizeof(struct bonus_script_data)),&bsdata,sizeof(struct bonus_script_data));
}
if (count >= MAX_PC_BONUS_SCRIPT)
ShowWarning("Too many bonus_script for %d, some of them were not loaded.\n",cid);
if (count > 0) {
WFIFOW(fd,2) = 10 + count*sizeof(struct bonus_script_data);
WFIFOW(fd,8) = count;
WFIFOSET(fd,WFIFOW(fd,2));

//Clear the data once loaded.
if (SQL_ERROR == Sql_Query(sql_handle,"DELETE FROM `%s` WHERE `char_id`='%d'",schema_config.bonus_script_db,cid))
Sql_ShowDebug(sql_handle);
ShowInfo("Loaded %d bonus_script for char_id: %d\n",count,cid);
if ((num_rows = (uint8)SqlStmt_NumRows(stmt)) > 0) {
uint8 i;
uint32 size = 9 + num_rows * sizeof(struct bonus_script_data);

WFIFOHEAD(fd, size);
WFIFOW(fd, 0) = 0x2b2f;
WFIFOW(fd, 2) = size;
WFIFOL(fd, 4) = cid;
WFIFOB(fd, 8) = num_rows;

for (i = 0; i < num_rows && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++) {
struct bonus_script_data bsdata;
memset(&bsdata, 0, sizeof(bsdata));
memset(bsdata.script_str, '\0', sizeof(bsdata.script_str));

safestrncpy(bsdata.script_str, tmp_bsdata.script_str, strlen(tmp_bsdata.script_str)+1);
bsdata.tick = tmp_bsdata.tick;
bsdata.flag = tmp_bsdata.flag;
bsdata.type = tmp_bsdata.type;
bsdata.icon = tmp_bsdata.icon;
memcpy(WFIFOP(fd, 9 + i * sizeof(struct bonus_script_data)), &bsdata, sizeof(struct bonus_script_data));
}

WFIFOSET(fd, size);

ShowInfo("Bonus Script loaded for CID=%d. Total: %d.\n", cid, i);

if (SQL_ERROR == SqlStmt_Prepare(stmt,"DELETE FROM `%s` WHERE `char_id`='%d'",schema_config.bonus_script_db,cid) ||
SQL_ERROR == SqlStmt_Execute(stmt))
SqlStmt_ShowDebug(stmt);
}
Sql_FreeResult(sql_handle);
SqlStmt_Free(stmt);
}
return 1;
}

/** [Cydh]
* Save bonus_script data(s) to the table
* @param fd
*/
/**
* ZA 0x2b2e
* <cmd>.W <len>.W <char_id>.L <count>.B { <bonus_script>.?B }
* Save bonus_script data(s) to the table
* @param fd
* @author [Cydh]
**/
int chmapif_bonus_script_save(int fd) {
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
else {
int count, cid;
uint32 cid = RFIFOL(fd,4);
uint8 count = RFIFOB(fd,8);

cid = RFIFOL(fd,4);
count = RFIFOW(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) {
struct bonus_script_data bs;
char esc_script[MAX_BONUS_SCRIPT_LENGTH*2];
struct bonus_script_data bsdata;
StringBuf buf;
int i;
char esc_script[MAX_BONUS_SCRIPT_LENGTH] = "";
uint8 i;

StringBuf_Init(&buf);
StringBuf_Printf(&buf,"INSERT INTO `%s` (`char_id`, `script`, `tick`, `flag`, `type`, `icon`) VALUES ",schema_config.bonus_script_db);
StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `script`, `tick`, `flag`, `type`, `icon`) VALUES ", schema_config.bonus_script_db);
for (i = 0; i < count; ++i) {
memcpy(&bs,RFIFOP(fd,10+i*sizeof(struct bonus_script_data)),sizeof(struct bonus_script_data));
Sql_EscapeString(sql_handle,esc_script,bs.script);
memcpy(&bsdata, RFIFOP(fd, 9 + i*sizeof(struct bonus_script_data)), sizeof(struct bonus_script_data));
Sql_EscapeString(sql_handle, esc_script, bsdata.script_str);
if (i > 0)
StringBuf_AppendStr(&buf,", ");
StringBuf_Printf(&buf,"('%d','%s','%d','%d','%d','%d')",cid,esc_script,bs.tick,bs.flag,bs.type,bs.icon);
StringBuf_Printf(&buf, "('%d','%s','%d','%d','%d','%d')", cid, esc_script, bsdata.tick, bsdata.flag, bsdata.type, bsdata.icon);
}
if (SQL_ERROR == Sql_QueryStr(sql_handle,StringBuf_Value(&buf)))
Sql_ShowDebug(sql_handle);

StringBuf_Destroy(&buf);
ShowInfo("Saved %d bonus_script for char_id: %d\n",count,cid);
}
ShowInfo("Bonus Script saved for CID=%d. Total: %d.\n", cid, count);
RFIFOSKIP(fd,RFIFOW(fd,2));
}
return 1;
Expand Down
25 changes: 18 additions & 7 deletions src/common/db.c
Expand Up @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions src/common/db.h
Expand Up @@ -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, ... );



Expand Down
14 changes: 8 additions & 6 deletions src/common/mmo.h
Expand Up @@ -7,6 +7,7 @@
#include "cbasetypes.h"
#include "../common/db.h"
#include <time.h>
#include "../common/strlib.h"// StringBuf

// server->client protocol version
// 0 - pre-?
Expand Down Expand Up @@ -73,7 +74,7 @@
#define MAX_GUILDLEVEL 50 ///Max Guild level
#define MAX_GUARDIANS 8 ///Local max per castle. If this value is increased, need to add more fields on MySQL `guild_castle` table [Skotlex]
#define MAX_QUEST_OBJECTIVES 3 ///Max quest objectives for a quest
#define MAX_PC_BONUS_SCRIPT 20 ///Max bonus script
#define MAX_PC_BONUS_SCRIPT 50 ///Max bonus script can be fetched from `bonus_script` table on player load [Cydh]

// for produce
#define MIN_ATTRIBUTE 0
Expand Down Expand Up @@ -259,12 +260,13 @@ struct status_change_data {
long val1, val2, val3, val4, tick; //Remaining duration.
};

#define MAX_BONUS_SCRIPT_LENGTH 1024
#define MAX_BONUS_SCRIPT_LENGTH 512
struct bonus_script_data {
char script[MAX_BONUS_SCRIPT_LENGTH];
long tick;
char type;
short flag, icon;
char script_str[MAX_BONUS_SCRIPT_LENGTH]; //< Script string
uint32 tick; ///< Tick
uint16 flag; ///< Flags @see enum e_bonus_script_flags
int16 icon; ///< Icon SI
uint8 type; ///< 0 - None, 1 - Buff, 2 - Debuff
};

struct skill_cooldown_data {
Expand Down

0 comments on commit bf6d2f0

Please sign in to comment.