|
@@ -67,7 +67,6 @@ using namespace rathena;
|
|
|
static uint16 skilldb_id2idx[(UINT16_MAX + 1)]; /// Skill ID to Index lookup: skill_index = skill_get_index(skill_id) - [FWI] 20160423 the whole index thing should be removed.
|
|
|
static uint16 skill_num = 1; /// Skill count, also as last index
|
|
|
|
|
|
-static struct eri *skill_unit_ers = NULL; //For handling skill_unit's [Skotlex]
|
|
|
static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Skotlex]
|
|
|
static DBMap* bowling_db = NULL; // int mob_id -> struct mob_data*
|
|
|
|
|
@@ -326,12 +325,12 @@ int skill_tree_get_max(uint16 skill_id, int b_class)
|
|
|
|
|
|
int skill_frostjoke_scream(struct block_list *bl,va_list ap);
|
|
|
int skill_attack_area(struct block_list *bl,va_list ap);
|
|
|
-struct skill_unit_group *skill_locate_element_field(struct block_list *bl); // [Skotlex]
|
|
|
+std::shared_ptr<s_skill_unit_group> skill_locate_element_field(struct block_list *bl); // [Skotlex]
|
|
|
int skill_graffitiremover(struct block_list *bl, va_list ap); // [Valaris]
|
|
|
int skill_greed(struct block_list *bl, va_list ap);
|
|
|
static int skill_cell_overlap(struct block_list *bl, va_list ap);
|
|
|
static int skill_trap_splash(struct block_list *bl, va_list ap);
|
|
|
-struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg,t_tick tick);
|
|
|
+struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,std::shared_ptr<s_skill_unit_group> sg,t_tick tick);
|
|
|
static int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,t_tick tick);
|
|
|
int skill_unit_onleft(uint16 skill_id, struct block_list *bl,t_tick tick);
|
|
|
static int skill_unit_effect(struct block_list *bl,va_list ap);
|
|
@@ -488,10 +487,8 @@ bool skill_pos_maxcount_check(struct block_list *src, int16 x, int16 y, uint16 s
|
|
|
return false;
|
|
|
}
|
|
|
if (type&battle_config.land_skill_limit && (maxcount = skill_get_maxcount(skill_id, skill_lv)) > 0) {
|
|
|
- for (int i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i] && maxcount; i++) {
|
|
|
- if (ud->skillunit[i]->skill_id == skill_id)
|
|
|
- maxcount--;
|
|
|
- }
|
|
|
+ unit_skillunit_maxcount(*ud, skill_id, maxcount);
|
|
|
+
|
|
|
if (maxcount == 0) {
|
|
|
if (sd && display_failure)
|
|
|
clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
|
|
@@ -4445,14 +4442,16 @@ int skill_cleartimerskill (struct block_list *src)
|
|
|
return 1;
|
|
|
}
|
|
|
static int skill_active_reverberation(struct block_list *bl, va_list ap) {
|
|
|
- struct skill_unit *su = (TBL_SKILL*)bl;
|
|
|
- struct skill_unit_group *sg = NULL;
|
|
|
+ skill_unit *su = (skill_unit*)bl;
|
|
|
|
|
|
nullpo_ret(su);
|
|
|
|
|
|
if (bl->type != BL_SKILL)
|
|
|
return 0;
|
|
|
- if (su->alive && (sg = su->group) && sg->skill_id == NPC_REVERBERATION) {
|
|
|
+
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg = su->group;
|
|
|
+
|
|
|
+ if (su->alive && sg && sg->skill_id == NPC_REVERBERATION) {
|
|
|
map_foreachinallrange(skill_trap_splash, bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, gettick());
|
|
|
su->limit = DIFF_TICK(gettick(), sg->tick);
|
|
|
sg->unit_id = UNT_USED_TRAPS;
|
|
@@ -5876,8 +5875,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
|
if (tsc && tsc->data[SC__SHADOWFORM] && rnd() % 100 < 100 - tsc->data[SC__SHADOWFORM]->val1 * 10) // [100 - (Skill Level x 10)] %
|
|
|
status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); // Should only end, no damage dealt.
|
|
|
} else {
|
|
|
- struct skill_unit *su = NULL;
|
|
|
- struct skill_unit_group* sg;
|
|
|
+ skill_unit *su = BL_CAST(BL_SKILL, bl);
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg;
|
|
|
|
|
|
if (su && (sg = su->group) && skill_get_inf2(sg->skill_id, INF2_ISTRAP)) {
|
|
|
if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) )
|
|
@@ -8965,12 +8964,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
case MA_REMOVETRAP:
|
|
|
case HT_REMOVETRAP:
|
|
|
{
|
|
|
- struct skill_unit* su;
|
|
|
- struct skill_unit_group* sg = NULL;
|
|
|
+ skill_unit* su = BL_CAST(BL_SKILL, bl);
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg;
|
|
|
std::shared_ptr<s_skill_db> skill_group;
|
|
|
|
|
|
- su = BL_CAST(BL_SKILL, bl);
|
|
|
-
|
|
|
// Mercenaries can remove any trap
|
|
|
// Players can only remove their own traps or traps on Vs maps.
|
|
|
if( su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && ( skill_group = skill_db.find(sg->skill_id) ) && skill_group->inf2[INF2_ISTRAP] )
|
|
@@ -12104,7 +12101,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
|
struct map_session_data* sd;
|
|
|
struct status_change* sc;
|
|
|
struct status_change_entry *sce;
|
|
|
- struct skill_unit_group* sg;
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg;
|
|
|
enum sc_type type;
|
|
|
int i;
|
|
|
|
|
@@ -12186,7 +12183,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
|
case SA_DELUGE:
|
|
|
case SA_VIOLENTGALE:
|
|
|
{ //Does not consumes if the skill is already active. [Skotlex]
|
|
|
- struct skill_unit_group *sg2;
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg2;
|
|
|
if ((sg2= skill_locate_element_field(src)) != NULL && ( sg2->skill_id == SA_VOLCANO || sg2->skill_id == SA_DELUGE || sg2->skill_id == SA_VIOLENTGALE ))
|
|
|
{
|
|
|
if (sg2->limit - DIFF_TICK(gettick(), sg2->tick) > 0)
|
|
@@ -12715,9 +12712,9 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
|
break;
|
|
|
|
|
|
case SC_FEINTBOMB: {
|
|
|
- struct skill_unit_group *group = skill_unitsetting(src,skill_id,skill_lv,x,y,0); // Set bomb on current Position
|
|
|
+ std::shared_ptr<s_skill_unit_group> group = skill_unitsetting(src,skill_id,skill_lv,x,y,0); // Set bomb on current Position
|
|
|
|
|
|
- if( group == NULL || group->unit == NULL ) {
|
|
|
+ if( group == nullptr || group->unit == nullptr ) {
|
|
|
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
|
|
return 1;
|
|
|
}
|
|
@@ -12770,16 +12767,15 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
|
}
|
|
|
break;
|
|
|
case GN_FIRE_EXPANSION: {
|
|
|
- int i_su;
|
|
|
struct unit_data *ud = unit_bl2ud(src);
|
|
|
|
|
|
if( !ud ) break;
|
|
|
|
|
|
- for(i_su = 0; i_su < MAX_SKILLUNITGROUP && ud->skillunit[i_su]; i_su++) {
|
|
|
- struct skill_unit *su = ud->skillunit[i_su]->unit;
|
|
|
- struct skill_unit_group *sg = ud->skillunit[i_su]->unit->group;
|
|
|
+ for (const auto itsu : ud->skillunits) {
|
|
|
+ skill_unit *su = itsu->unit;
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg = itsu->unit->group;
|
|
|
|
|
|
- if (ud->skillunit[i_su]->skill_id == GN_DEMONIC_FIRE && distance_xy(x, y, su->bl.x, su->bl.y) < 4) {
|
|
|
+ if (itsu->skill_id == GN_DEMONIC_FIRE && distance_xy(x, y, su->bl.x, su->bl.y) < 4) {
|
|
|
switch (skill_lv) {
|
|
|
case 1: {
|
|
|
// TODO:
|
|
@@ -12987,7 +12983,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
|
|
|
case AL_WARP:
|
|
|
{
|
|
|
const struct point *p[4];
|
|
|
- struct skill_unit_group *group;
|
|
|
+ std::shared_ptr<s_skill_unit_group> group;
|
|
|
int i, lv, wx, wy;
|
|
|
int maxcount=0;
|
|
|
int x,y;
|
|
@@ -13005,11 +13001,9 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
|
|
|
p[3] = &sd->status.memo_point[2];
|
|
|
|
|
|
if((maxcount = skill_get_maxcount(skill_id, sd->menuskill_val)) > 0) {
|
|
|
- for(i=0;i<MAX_SKILLUNITGROUP && sd->ud.skillunit[i] && maxcount;i++) {
|
|
|
- if(sd->ud.skillunit[i]->skill_id == skill_id)
|
|
|
- maxcount--;
|
|
|
- }
|
|
|
- if(!maxcount) {
|
|
|
+ unit_skillunit_maxcount(sd->ud, skill_id, maxcount);
|
|
|
+
|
|
|
+ if (maxcount == 0) {
|
|
|
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
|
|
skill_failed(sd);
|
|
|
return 0;
|
|
@@ -13042,7 +13036,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
|
|
|
skill_consume_requirement(sd,sd->menuskill_id,lv,2);
|
|
|
sd->skillitem = sd->skillitemlv = sd->skillitem_keep_requirement = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish]
|
|
|
|
|
|
- if((group=skill_unitsetting(&sd->bl,skill_id,lv,wx,wy,0))==NULL) {
|
|
|
+ if((group=skill_unitsetting(&sd->bl,skill_id,lv,wx,wy,0))==nullptr) {
|
|
|
skill_failed(sd);
|
|
|
return 0;
|
|
|
}
|
|
@@ -13116,10 +13110,10 @@ int skill_dance_overlap(struct skill_unit* unit, int flag)
|
|
|
static bool skill_dance_switch(struct skill_unit* unit, int flag)
|
|
|
{
|
|
|
static int prevflag = 1; // by default the backup is empty
|
|
|
- static struct skill_unit_group backup;
|
|
|
- struct skill_unit_group* group;
|
|
|
+ static s_skill_unit_group backup;
|
|
|
+ std::shared_ptr<s_skill_unit_group> group;
|
|
|
|
|
|
- if( unit == NULL || (group = unit->group) == NULL )
|
|
|
+ if( unit == nullptr || (group = unit->group) == nullptr )
|
|
|
return false;
|
|
|
|
|
|
//val2&(1 << UF_ENSEMBLE) is a hack to indicate dissonance
|
|
@@ -13174,11 +13168,11 @@ static bool skill_dance_switch(struct skill_unit* unit, int flag)
|
|
|
* @param y Position y
|
|
|
* @param flag &1: Used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active)
|
|
|
* xx_METEOR: flag &1 contains if the unit can cause curse, flag is also the duration of the unit in milliseconds
|
|
|
- * @return skill_unit_group
|
|
|
+ * @return s_skill_unit_group
|
|
|
*/
|
|
|
-struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_id, uint16 skill_lv, int16 x, int16 y, int flag)
|
|
|
+std::shared_ptr<s_skill_unit_group> skill_unitsetting(struct block_list *src, uint16 skill_id, uint16 skill_lv, int16 x, int16 y, int flag)
|
|
|
{
|
|
|
- struct skill_unit_group *group;
|
|
|
+ std::shared_ptr<s_skill_unit_group> group;
|
|
|
int i, val1 = 0, val2 = 0, val3 = 0;
|
|
|
t_tick limit;
|
|
|
int link_group_id = 0;
|
|
@@ -13193,7 +13187,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
bool hidden = false;
|
|
|
struct map_data *mapdata;
|
|
|
|
|
|
- nullpo_retr(NULL, src);
|
|
|
+ nullpo_retr(nullptr, src);
|
|
|
|
|
|
std::shared_ptr<s_skill_db> skill = skill_db.find(skill_id);
|
|
|
|
|
@@ -13232,10 +13226,10 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
limit=2000;
|
|
|
else // previous implementation (not used anymore)
|
|
|
{ //Warp Portal morphing to active mode, extract relevant data from src. [Skotlex]
|
|
|
- if( src->type != BL_SKILL ) return NULL;
|
|
|
+ if( src->type != BL_SKILL ) return nullptr;
|
|
|
group = ((TBL_SKILL*)src)->group;
|
|
|
src = map_id2bl(group->src_id);
|
|
|
- if( !src ) return NULL;
|
|
|
+ if( !src ) return nullptr;
|
|
|
val2 = group->val2; //Copy the (x,y) position you warp to
|
|
|
val3 = group->val3; //as well as the mapindex to warp to.
|
|
|
}
|
|
@@ -13258,7 +13252,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
break;
|
|
|
case WZ_FIREPILLAR:
|
|
|
if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
|
|
|
- return NULL;
|
|
|
+ return nullptr;
|
|
|
if((flag&1)!=0)
|
|
|
limit=1000;
|
|
|
val1=skill_lv+2;
|
|
@@ -13311,8 +13305,9 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
case SA_VIOLENTGALE:
|
|
|
case SC_CHAOSPANIC:
|
|
|
{
|
|
|
- struct skill_unit_group *old_sg;
|
|
|
- if ((old_sg = skill_locate_element_field(src)) != NULL)
|
|
|
+ std::shared_ptr<s_skill_unit_group> old_sg = skill_locate_element_field(src);
|
|
|
+
|
|
|
+ if (old_sg != nullptr)
|
|
|
{ //HelloKitty confirmed that these are interchangeable,
|
|
|
//so you can change element and not consume gemstones.
|
|
|
if ((
|
|
@@ -13460,7 +13455,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
}
|
|
|
case GC_POISONSMOKE:
|
|
|
if( !(sc && sc->data[SC_POISONINGWEAPON]) )
|
|
|
- return NULL;
|
|
|
+ return nullptr;
|
|
|
val2 = sc->data[SC_POISONINGWEAPON]->val2; // Type of Poison
|
|
|
val3 = sc->data[SC_POISONINGWEAPON]->val1;
|
|
|
limit = skill_get_time(skill_id, skill_lv);
|
|
@@ -13490,7 +13485,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
case SO_WIND_INSIGNIA:
|
|
|
case SO_EARTH_INSIGNIA:
|
|
|
if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
|
|
|
- return NULL;
|
|
|
+ return nullptr;
|
|
|
break;
|
|
|
case SO_CLOUD_KILL:
|
|
|
case NPC_CLOUD_KILL:
|
|
@@ -13551,7 +13546,11 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
}
|
|
|
|
|
|
// Init skill unit group
|
|
|
- nullpo_retr(NULL, (group = skill_initunitgroup(src,layout->count,skill_id,skill_lv,(flag & 1 ? skill->unit_id2 : skill->unit_id)+subunt, limit, interval)));
|
|
|
+ group = skill_initunitgroup(src, layout->count, skill_id, skill_lv, (flag & 1 ? skill->unit_id2 : skill->unit_id) + subunt, limit, interval);
|
|
|
+
|
|
|
+ if (group == nullptr)
|
|
|
+ return nullptr;
|
|
|
+
|
|
|
group->val1 = val1;
|
|
|
group->val2 = val2;
|
|
|
group->val3 = val3;
|
|
@@ -13687,7 +13686,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
if( !alive )
|
|
|
continue;
|
|
|
|
|
|
- nullpo_retr(NULL, (unit = skill_initunit(group,i,ux,uy,unit_val1,unit_val2,hidden)));
|
|
|
+ nullpo_retr(nullptr, (unit = skill_initunit(group,i,ux,uy,unit_val1,unit_val2,hidden)));
|
|
|
unit->limit = limit;
|
|
|
unit->range = range;
|
|
|
|
|
@@ -13705,7 +13704,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
if (!group->alive_count)
|
|
|
{ //No cells? Something that was blocked completely by Land Protector?
|
|
|
skill_delunitgroup(group);
|
|
|
- return NULL;
|
|
|
+ return nullptr;
|
|
|
}
|
|
|
|
|
|
//success, unit created.
|
|
@@ -13736,7 +13735,7 @@ void ext_skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, t_ti
|
|
|
*/
|
|
|
static int skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, t_tick tick)
|
|
|
{
|
|
|
- struct skill_unit_group *sg;
|
|
|
+
|
|
|
struct block_list *ss; // Actual source that cast the skill unit
|
|
|
struct status_change *sc;
|
|
|
struct status_change_entry *sce;
|
|
@@ -13750,7 +13749,11 @@ static int skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, t_
|
|
|
if(bl->prev == NULL || !unit->alive || status_isdead(bl))
|
|
|
return 0;
|
|
|
|
|
|
- nullpo_ret(sg = unit->group);
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg = unit->group;
|
|
|
+
|
|
|
+ if (sg == nullptr)
|
|
|
+ return 0;
|
|
|
+
|
|
|
nullpo_ret(ss = map_id2bl(sg->src_id));
|
|
|
|
|
|
tstatus = status_get_status_data(bl);
|
|
@@ -14078,7 +14081,6 @@ static int skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, t_
|
|
|
*/
|
|
|
int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_tick tick)
|
|
|
{
|
|
|
- struct skill_unit_group *sg;
|
|
|
struct block_list *ss;
|
|
|
TBL_PC* tsd;
|
|
|
struct status_data *tstatus;
|
|
@@ -14094,7 +14096,11 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
|
|
|
if (bl->prev == NULL || !unit->alive || status_isdead(bl))
|
|
|
return 0;
|
|
|
|
|
|
- nullpo_ret(sg = unit->group);
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg = unit->group;
|
|
|
+
|
|
|
+ if (sg == nullptr)
|
|
|
+ return 0;
|
|
|
+
|
|
|
nullpo_ret(ss = map_id2bl(sg->src_id));
|
|
|
|
|
|
tsd = BL_CAST(BL_PC, bl);
|
|
@@ -14800,14 +14806,18 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
|
|
|
*/
|
|
|
int skill_unit_onout(struct skill_unit *src, struct block_list *bl, t_tick tick)
|
|
|
{
|
|
|
- struct skill_unit_group *sg;
|
|
|
struct status_change *sc;
|
|
|
struct status_change_entry *sce;
|
|
|
enum sc_type type;
|
|
|
|
|
|
nullpo_ret(src);
|
|
|
nullpo_ret(bl);
|
|
|
- nullpo_ret(sg=src->group);
|
|
|
+
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg = src->group;
|
|
|
+
|
|
|
+ if (sg == nullptr)
|
|
|
+ return 0;
|
|
|
+
|
|
|
sc = status_get_sc(bl);
|
|
|
type = status_skill2sc(sg->skill_id);
|
|
|
sce = (sc && type != -1)?sc->data[type]:NULL;
|
|
@@ -15008,7 +15018,6 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, t_tick tick)
|
|
|
static int skill_unit_effect(struct block_list* bl, va_list ap)
|
|
|
{
|
|
|
struct skill_unit* unit = va_arg(ap,struct skill_unit*);
|
|
|
- struct skill_unit_group* group = unit->group;
|
|
|
t_tick tick = va_arg(ap,t_tick);
|
|
|
unsigned int flag = va_arg(ap,unsigned int);
|
|
|
uint16 skill_id;
|
|
@@ -15018,7 +15027,10 @@ static int skill_unit_effect(struct block_list* bl, va_list ap)
|
|
|
if( (!unit->alive && !(flag&4)) || bl->prev == NULL )
|
|
|
return 0;
|
|
|
|
|
|
- nullpo_ret(group);
|
|
|
+ std::shared_ptr<s_skill_unit_group> group = unit->group;
|
|
|
+
|
|
|
+ if (group == nullptr)
|
|
|
+ return 0;
|
|
|
|
|
|
if( !(flag&8) ) {
|
|
|
dissonance = skill_dance_switch(unit, 0);
|
|
@@ -15058,10 +15070,12 @@ static int skill_unit_effect(struct block_list* bl, va_list ap)
|
|
|
*/
|
|
|
int64 skill_unit_ondamaged(struct skill_unit *unit, int64 damage)
|
|
|
{
|
|
|
- struct skill_unit_group *sg;
|
|
|
-
|
|
|
nullpo_ret(unit);
|
|
|
- nullpo_ret(sg = unit->group);
|
|
|
+
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg = unit->group;
|
|
|
+
|
|
|
+ if (sg == nullptr)
|
|
|
+ return 0;
|
|
|
|
|
|
switch( sg->unit_id ) {
|
|
|
case UNT_BLASTMINE:
|
|
@@ -17848,18 +17862,17 @@ int skill_attack_area(struct block_list *bl, va_list ap)
|
|
|
*/
|
|
|
int skill_clear_group(struct block_list *bl, int flag)
|
|
|
{
|
|
|
- struct unit_data *ud = NULL;
|
|
|
- struct skill_unit_group *group[MAX_SKILLUNITGROUP];
|
|
|
- int i, count = 0;
|
|
|
-
|
|
|
nullpo_ret(bl);
|
|
|
|
|
|
- if (!(ud = unit_bl2ud(bl)))
|
|
|
+ unit_data *ud = unit_bl2ud(bl);
|
|
|
+
|
|
|
+ if (ud == nullptr)
|
|
|
return 0;
|
|
|
|
|
|
- // All groups to be deleted are first stored on an array since the array elements shift around when you delete them. [Skotlex]
|
|
|
- for (i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i]; i++) {
|
|
|
- switch (ud->skillunit[i]->skill_id) {
|
|
|
+ size_t count = 0;
|
|
|
+
|
|
|
+ for (auto it = ud->skillunits.begin(); it != ud->skillunits.end(); it++) {
|
|
|
+ switch ((*it)->skill_id) {
|
|
|
case SA_DELUGE:
|
|
|
case SA_VOLCANO:
|
|
|
case SA_VIOLENTGALE:
|
|
@@ -17869,47 +17882,52 @@ int skill_clear_group(struct block_list *bl, int flag)
|
|
|
case SC_CHAOSPANIC:
|
|
|
case MH_POISON_MIST:
|
|
|
case MH_LAVA_SLIDE:
|
|
|
- if (flag&1)
|
|
|
- group[count++] = ud->skillunit[i];
|
|
|
+ if (flag & 1) {
|
|
|
+ skill_delunitgroup(*it);
|
|
|
+ count++;
|
|
|
+ }
|
|
|
break;
|
|
|
case SO_CLOUD_KILL:
|
|
|
case NPC_CLOUD_KILL:
|
|
|
- if( flag&4 )
|
|
|
- group[count++] = ud->skillunit[i];
|
|
|
+ if (flag & 4) {
|
|
|
+ skill_delunitgroup(*it);
|
|
|
+ count++;
|
|
|
+ }
|
|
|
break;
|
|
|
case SO_WARMER:
|
|
|
- if( flag&8 )
|
|
|
- group[count++] = ud->skillunit[i];
|
|
|
+ if (flag & 8) {
|
|
|
+ skill_delunitgroup(*it);
|
|
|
+ count++;
|
|
|
+ }
|
|
|
break;
|
|
|
default:
|
|
|
- if (flag&2 && skill_get_inf2(ud->skillunit[i]->skill_id, INF2_ISTRAP))
|
|
|
- group[count++] = ud->skillunit[i];
|
|
|
+ if (flag & 2 && skill_get_inf2((*it)->skill_id, INF2_ISTRAP)) {
|
|
|
+ skill_delunitgroup(*it);
|
|
|
+ count++;
|
|
|
+ }
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
- for (i = 0; i < count; i++)
|
|
|
- skill_delunitgroup(group[i]);
|
|
|
- return count;
|
|
|
+
|
|
|
+ return static_cast<int>(count);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Returns the first element field found [Skotlex]
|
|
|
* @param bl
|
|
|
- * @return skill_unit_group
|
|
|
+ * @return s_skill_unit_group
|
|
|
*/
|
|
|
-struct skill_unit_group *skill_locate_element_field(struct block_list *bl)
|
|
|
+std::shared_ptr<s_skill_unit_group> skill_locate_element_field(struct block_list *bl)
|
|
|
{
|
|
|
- struct unit_data *ud = NULL;
|
|
|
- int i;
|
|
|
-
|
|
|
nullpo_ret(bl);
|
|
|
|
|
|
- if (!(ud = unit_bl2ud(bl)))
|
|
|
- return NULL;
|
|
|
+ unit_data *ud = unit_bl2ud(bl);
|
|
|
+
|
|
|
+ if (ud == nullptr)
|
|
|
+ return nullptr;
|
|
|
|
|
|
- for (i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i]; i++) {
|
|
|
- switch (ud->skillunit[i]->skill_id) {
|
|
|
+ for (const auto su : ud->skillunits) {
|
|
|
+ switch (su->skill_id) {
|
|
|
case SA_DELUGE:
|
|
|
case SA_VOLCANO:
|
|
|
case SA_VIOLENTGALE:
|
|
@@ -17921,10 +17939,10 @@ struct skill_unit_group *skill_locate_element_field(struct block_list *bl)
|
|
|
case SC_CHAOSPANIC:
|
|
|
case MH_POISON_MIST:
|
|
|
case MH_LAVA_SLIDE:
|
|
|
- return ud->skillunit[i];
|
|
|
+ return su;
|
|
|
}
|
|
|
}
|
|
|
- return NULL;
|
|
|
+ return nullptr;
|
|
|
}
|
|
|
|
|
|
/// Graffiti cleaner [Valaris]
|
|
@@ -17977,7 +17995,7 @@ int skill_detonator(struct block_list *bl, va_list ap)
|
|
|
if (unit == nullptr)
|
|
|
return 0;
|
|
|
|
|
|
- skill_unit_group *group = unit->group;
|
|
|
+ std::shared_ptr<s_skill_unit_group> group = unit->group;
|
|
|
|
|
|
if (group == nullptr || group->src_id != src->id)
|
|
|
return 0;
|
|
@@ -18198,7 +18216,6 @@ static int skill_trap_splash(struct block_list *bl, va_list ap)
|
|
|
struct block_list *src = va_arg(ap,struct block_list *);
|
|
|
struct skill_unit *unit = NULL;
|
|
|
t_tick tick = va_arg(ap,t_tick);
|
|
|
- struct skill_unit_group *sg;
|
|
|
struct block_list *ss; //Skill src bl
|
|
|
|
|
|
nullpo_ret(src);
|
|
@@ -18208,7 +18225,11 @@ static int skill_trap_splash(struct block_list *bl, va_list ap)
|
|
|
if (!unit || !unit->alive || bl->prev == NULL)
|
|
|
return 0;
|
|
|
|
|
|
- nullpo_ret(sg = unit->group);
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg = unit->group;
|
|
|
+
|
|
|
+ if (sg == nullptr)
|
|
|
+ return 0;
|
|
|
+
|
|
|
nullpo_ret(ss = map_id2bl(sg->src_id));
|
|
|
|
|
|
if (battle_check_target(src,bl,sg->target_flag) <= 0)
|
|
@@ -18574,13 +18595,15 @@ void skill_getareachar_skillunit_visibilty_single(struct skill_unit *su, struct
|
|
|
* @param val1
|
|
|
* @param val2
|
|
|
*/
|
|
|
-struct skill_unit *skill_initunit(struct skill_unit_group *group, int idx, int x, int y, int val1, int val2, bool hidden)
|
|
|
+struct skill_unit *skill_initunit(std::shared_ptr<s_skill_unit_group> group, int idx, int x, int y, int val1, int val2, bool hidden)
|
|
|
{
|
|
|
- struct skill_unit *unit;
|
|
|
+ if (group == nullptr || group->unit == nullptr)
|
|
|
+ return nullptr;
|
|
|
+
|
|
|
+ skill_unit *unit = &group->unit[idx];
|
|
|
|
|
|
- nullpo_retr(NULL, group);
|
|
|
- nullpo_retr(NULL, group->unit); // crash-protection against poor coding
|
|
|
- nullpo_retr(NULL, (unit = &group->unit[idx]));
|
|
|
+ if (unit == nullptr)
|
|
|
+ return nullptr;
|
|
|
|
|
|
if( map_getcell(map_id2bl(group->src_id)->m, x, y, CELL_CHKMAELSTROM) )
|
|
|
return unit;
|
|
@@ -18639,8 +18662,6 @@ struct skill_unit *skill_initunit(struct skill_unit_group *group, int idx, int x
|
|
|
*/
|
|
|
int skill_delunit(struct skill_unit* unit)
|
|
|
{
|
|
|
- struct skill_unit_group *group;
|
|
|
-
|
|
|
nullpo_ret(unit);
|
|
|
|
|
|
if( !unit->alive )
|
|
@@ -18648,7 +18669,10 @@ int skill_delunit(struct skill_unit* unit)
|
|
|
|
|
|
unit->alive = 0;
|
|
|
|
|
|
- nullpo_ret(group = unit->group);
|
|
|
+ std::shared_ptr<s_skill_unit_group> group = unit->group;
|
|
|
+
|
|
|
+ if (group == nullptr)
|
|
|
+ return 0;
|
|
|
|
|
|
if( group->state.song_dance&0x1 ) //Cancel dissonance effect.
|
|
|
skill_dance_overlap(unit, 0);
|
|
@@ -18714,11 +18738,11 @@ int skill_delunit(struct skill_unit* unit)
|
|
|
}
|
|
|
|
|
|
|
|
|
-static DBMap* skillunit_group_db = NULL; /// Skill unit group DB. Key int group_id -> struct skill_unit_group*
|
|
|
+static std::unordered_map<int, std::shared_ptr<s_skill_unit_group>> skillunit_group_db; /// Skill unit group DB. Key int group_id -> struct s_skill_unit_group*
|
|
|
|
|
|
-/// Returns the target skill_unit_group or NULL if not found.
|
|
|
-struct skill_unit_group* skill_id2group(int group_id) {
|
|
|
- return (struct skill_unit_group*)idb_get(skillunit_group_db, group_id);
|
|
|
+/// Returns the target s_skill_unit_group or nullptr if not found.
|
|
|
+std::shared_ptr<s_skill_unit_group> skill_id2group(int group_id) {
|
|
|
+ return util::umap_find(skillunit_group_db, group_id);
|
|
|
}
|
|
|
|
|
|
static int skill_unit_group_newid = MAX_SKILL; /// Skill Unit Group ID
|
|
@@ -18755,46 +18779,28 @@ static int skill_get_new_group_id(void)
|
|
|
* @param unit_id Unit ID (see skill.hpp::e_skill_unit_id)
|
|
|
* @param limit Lifetime for skill unit, uses skill_get_time(skill_id, skill_lv)
|
|
|
* @param interval Time interval
|
|
|
- * @return skill_unit_group
|
|
|
+ * @return s_skill_unit_group
|
|
|
*/
|
|
|
-struct skill_unit_group* skill_initunitgroup(struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, t_tick limit, int interval)
|
|
|
+std::shared_ptr<s_skill_unit_group> skill_initunitgroup(struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, t_tick limit, int interval)
|
|
|
{
|
|
|
- struct unit_data* ud = unit_bl2ud( src );
|
|
|
- struct skill_unit_group* group;
|
|
|
- int i;
|
|
|
+ nullpo_retr(nullptr, src);
|
|
|
|
|
|
- if(!(skill_id && skill_lv)) return 0;
|
|
|
+ unit_data *ud = unit_bl2ud(src);
|
|
|
|
|
|
- nullpo_retr(NULL, src);
|
|
|
- nullpo_retr(NULL, ud);
|
|
|
+ nullpo_retr(nullptr, ud);
|
|
|
|
|
|
- // Find a free spot to store the new unit group
|
|
|
- // TODO: Make this flexible maybe by changing this fixed array?
|
|
|
- ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == NULL );
|
|
|
- if(i == MAX_SKILLUNITGROUP) {
|
|
|
- // Array is full, make room by discarding oldest group
|
|
|
- int j = 0;
|
|
|
- t_tick maxdiff = 0, tick = gettick();
|
|
|
- for(i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i];i++){
|
|
|
- t_tick x = DIFF_TICK(tick,ud->skillunit[i]->tick);
|
|
|
- if(x > maxdiff){
|
|
|
- maxdiff = x;
|
|
|
- j = i;
|
|
|
- }
|
|
|
- }
|
|
|
- skill_delunitgroup(ud->skillunit[j]);
|
|
|
- // Since elements must have shifted, we use the last slot.
|
|
|
- i = MAX_SKILLUNITGROUP-1;
|
|
|
- }
|
|
|
+ if (skill_id == 0 || skill_lv == 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ auto group = std::make_shared<s_skill_unit_group>();
|
|
|
|
|
|
- group = ers_alloc(skill_unit_ers, struct skill_unit_group);
|
|
|
group->src_id = src->id;
|
|
|
group->party_id = status_get_party_id(src);
|
|
|
group->guild_id = status_get_guild_id(src);
|
|
|
group->bg_id = bg_team_get_id(src);
|
|
|
group->group_id = skill_get_new_group_id();
|
|
|
group->link_group_id = 0;
|
|
|
- group->unit = (struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
|
|
|
+ group->unit = (skill_unit *)aCalloc(count, sizeof(skill_unit));
|
|
|
group->unit_count = count;
|
|
|
group->alive_count = 0;
|
|
|
group->val1 = 0;
|
|
@@ -18807,12 +18813,13 @@ struct skill_unit_group* skill_initunitgroup(struct block_list* src, int count,
|
|
|
group->limit = limit;
|
|
|
group->interval = interval;
|
|
|
group->tick = gettick();
|
|
|
- group->valstr = NULL;
|
|
|
+ group->valstr = nullptr;
|
|
|
+
|
|
|
+ ud->skillunits.push_back(group);
|
|
|
|
|
|
- ud->skillunit[i] = group;
|
|
|
+ // Stores this new group
|
|
|
+ skillunit_group_db.insert({ group->group_id, group });
|
|
|
|
|
|
- // Stores this new group to DBMap
|
|
|
- idb_put(skillunit_group_db, group->group_id, group);
|
|
|
return group;
|
|
|
}
|
|
|
|
|
@@ -18823,14 +18830,14 @@ struct skill_unit_group* skill_initunitgroup(struct block_list* src, int count,
|
|
|
* @param line
|
|
|
* @param *func
|
|
|
*/
|
|
|
-int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int line, const char* func)
|
|
|
+int skill_delunitgroup_(std::shared_ptr<s_skill_unit_group> group, const char* file, int line, const char* func)
|
|
|
{
|
|
|
struct block_list* src;
|
|
|
struct unit_data *ud;
|
|
|
- short i, j;
|
|
|
+ short i;
|
|
|
int link_group_id;
|
|
|
|
|
|
- if( group == NULL ) {
|
|
|
+ if( group == nullptr ) {
|
|
|
ShowDebug("skill_delunitgroup: group is NULL (source=%s:%d, %s)! Please report this! (#3504)\n", file, line, func);
|
|
|
return 0;
|
|
|
}
|
|
@@ -18962,28 +18969,14 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
|
|
|
group->valstr = NULL;
|
|
|
}
|
|
|
|
|
|
- idb_remove(skillunit_group_db, group->group_id);
|
|
|
- map_freeblock(&group->unit->bl); // schedules deallocation of whole array (HACK)
|
|
|
- group->unit = NULL;
|
|
|
- group->group_id = 0;
|
|
|
- group->unit_count = 0;
|
|
|
-
|
|
|
link_group_id = group->link_group_id;
|
|
|
- group->link_group_id = 0;
|
|
|
|
|
|
- // locate this group, swap with the last entry and delete it
|
|
|
- ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == group );
|
|
|
- ARR_FIND( i, MAX_SKILLUNITGROUP, j, ud->skillunit[j] == NULL );
|
|
|
- j--;
|
|
|
- if( i < MAX_SKILLUNITGROUP ) {
|
|
|
- ud->skillunit[i] = ud->skillunit[j];
|
|
|
- ud->skillunit[j] = NULL;
|
|
|
- ers_free(skill_unit_ers, group);
|
|
|
- } else
|
|
|
+ if (skillunit_group_db.erase(group->group_id) != 1)
|
|
|
ShowError("skill_delunitgroup: Group not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id);
|
|
|
|
|
|
if(link_group_id) {
|
|
|
- struct skill_unit_group* group_cur = skill_id2group(link_group_id);
|
|
|
+ std::shared_ptr<s_skill_unit_group> group_cur = skill_id2group(link_group_id);
|
|
|
+
|
|
|
if(group_cur)
|
|
|
skill_delunitgroup(group_cur);
|
|
|
}
|
|
@@ -18997,13 +18990,15 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
|
|
|
*/
|
|
|
void skill_clear_unitgroup(struct block_list *src)
|
|
|
{
|
|
|
- struct unit_data *ud;
|
|
|
-
|
|
|
nullpo_retv(src);
|
|
|
- nullpo_retv((ud = unit_bl2ud(src)));
|
|
|
|
|
|
- while (ud->skillunit[0])
|
|
|
- skill_delunitgroup(ud->skillunit[0]);
|
|
|
+ unit_data *ud = unit_bl2ud(src);
|
|
|
+
|
|
|
+ nullpo_retv(ud);
|
|
|
+
|
|
|
+ for (auto it = ud->skillunits.begin(); it != ud->skillunits.end(); it++) {
|
|
|
+ skill_delunitgroup(*it);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -19013,7 +19008,7 @@ void skill_clear_unitgroup(struct block_list *src)
|
|
|
* @param tick
|
|
|
* @return skill_unit_group_tickset if found
|
|
|
*/
|
|
|
-struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl, struct skill_unit_group *group, t_tick tick)
|
|
|
+struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl, std::shared_ptr<s_skill_unit_group> group, t_tick tick)
|
|
|
{
|
|
|
int i, j = -1, s, id;
|
|
|
struct unit_data *ud;
|
|
@@ -19059,7 +19054,6 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list
|
|
|
int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap)
|
|
|
{
|
|
|
struct skill_unit* unit = va_arg(ap,struct skill_unit *);
|
|
|
- struct skill_unit_group* group = NULL;
|
|
|
t_tick tick = va_arg(ap,t_tick);
|
|
|
|
|
|
nullpo_ret(unit);
|
|
@@ -19067,7 +19061,10 @@ int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap)
|
|
|
if( !unit->alive || bl->prev == NULL )
|
|
|
return 0;
|
|
|
|
|
|
- nullpo_ret(group = unit->group);
|
|
|
+ std::shared_ptr<s_skill_unit_group> group = unit->group;
|
|
|
+
|
|
|
+ if (group == nullptr)
|
|
|
+ return 0;
|
|
|
|
|
|
std::shared_ptr<s_skill_db> skill = skill_db.find(group->skill_id);
|
|
|
|
|
@@ -19088,7 +19085,6 @@ int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap)
|
|
|
static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
|
|
{
|
|
|
struct skill_unit* unit = (struct skill_unit*)db_data2ptr(data);
|
|
|
- struct skill_unit_group* group = NULL;
|
|
|
t_tick tick = va_arg(ap,t_tick);
|
|
|
bool dissonance;
|
|
|
struct block_list* bl = &unit->bl;
|
|
@@ -19098,7 +19094,10 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
|
|
if( !unit->alive )
|
|
|
return 0;
|
|
|
|
|
|
- nullpo_ret(group = unit->group);
|
|
|
+ std::shared_ptr<s_skill_unit_group> group = unit->group;
|
|
|
+
|
|
|
+ if (group == nullptr)
|
|
|
+ return 0;
|
|
|
|
|
|
// Check for expiration
|
|
|
if( !group->state.guildaura && (DIFF_TICK(tick,group->tick) >= group->limit || DIFF_TICK(tick,group->tick) >= unit->limit) )
|
|
@@ -19370,7 +19369,6 @@ static int skill_unit_temp[20]; // temporary storage for tracking skill unit sk
|
|
|
int skill_unit_move_sub(struct block_list* bl, va_list ap)
|
|
|
{
|
|
|
struct skill_unit* unit = (struct skill_unit *)bl;
|
|
|
- struct skill_unit_group* group = NULL;
|
|
|
|
|
|
struct block_list* target = va_arg(ap,struct block_list*);
|
|
|
t_tick tick = va_arg(ap,t_tick);
|
|
@@ -19385,7 +19383,10 @@ int skill_unit_move_sub(struct block_list* bl, va_list ap)
|
|
|
if( !unit->alive || target->prev == NULL )
|
|
|
return 0;
|
|
|
|
|
|
- nullpo_ret(group = unit->group);
|
|
|
+ std::shared_ptr<s_skill_unit_group> group = unit->group;
|
|
|
+
|
|
|
+ if (group == nullptr)
|
|
|
+ return 0;
|
|
|
|
|
|
if( flag&1 && ( group->skill_id == PF_SPIDERWEB || group->skill_id == GN_THORNS_TRAP ) )
|
|
|
return 0; // Fiberlock is never supposed to trigger on skill_unit_move. [Inkfish]
|
|
@@ -19536,7 +19537,7 @@ void skill_unit_move_unit(struct block_list *bl, int dx, int dy) {
|
|
|
* @param dx
|
|
|
* @param dy
|
|
|
*/
|
|
|
-void skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx, int16 dy)
|
|
|
+void skill_unit_move_unit_group(std::shared_ptr<s_skill_unit_group> group, int16 m, int16 dx, int16 dy)
|
|
|
{
|
|
|
int i, j;
|
|
|
t_tick tick = gettick();
|
|
@@ -20727,13 +20728,12 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite
|
|
|
*/
|
|
|
static int skill_destroy_trap(struct block_list *bl, va_list ap)
|
|
|
{
|
|
|
- struct skill_unit *su = (struct skill_unit *)bl;
|
|
|
- struct skill_unit_group *sg = NULL;
|
|
|
- t_tick tick;
|
|
|
+ skill_unit *su = (struct skill_unit *)bl;
|
|
|
|
|
|
nullpo_ret(su);
|
|
|
|
|
|
- tick = va_arg(ap, t_tick);
|
|
|
+ std::shared_ptr<s_skill_unit_group> sg;
|
|
|
+ t_tick tick = va_arg(ap, t_tick);
|
|
|
|
|
|
if (su->alive && (sg = su->group) && skill_get_inf2(sg->skill_id, INF2_ISTRAP)) {
|
|
|
switch( sg->unit_id ) {
|
|
@@ -20934,8 +20934,8 @@ void skill_usave_add(struct map_session_data *sd, uint16 skill_id, uint16 skill_
|
|
|
*/
|
|
|
void skill_usave_trigger(struct map_session_data *sd)
|
|
|
{
|
|
|
- struct skill_usave *sus = NULL;
|
|
|
- struct skill_unit_group *group = NULL;
|
|
|
+ skill_usave *sus;
|
|
|
+ std::shared_ptr<s_skill_unit_group> group;
|
|
|
|
|
|
if (!(sus = static_cast<skill_usave *>(idb_get(skillusave_db,sd->status.char_id))))
|
|
|
return;
|
|
@@ -23074,14 +23074,11 @@ void do_init_skill(void)
|
|
|
{
|
|
|
skill_readdb();
|
|
|
|
|
|
- skillunit_group_db = idb_alloc(DB_OPT_BASE);
|
|
|
skillunit_db = idb_alloc(DB_OPT_BASE);
|
|
|
skillusave_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
|
|
bowling_db = idb_alloc(DB_OPT_BASE);
|
|
|
- skill_unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.cpp::skill_unit_ers",ERS_CACHE_OPTIONS);
|
|
|
skill_timer_ers = ers_new(sizeof(struct skill_timerskill),"skill.cpp::skill_timer_ers",ERS_CACHE_OPTIONS);
|
|
|
|
|
|
- ers_chunk_size(skill_unit_ers, 150);
|
|
|
ers_chunk_size(skill_timer_ers, 150);
|
|
|
|
|
|
add_timer_func_list(skill_unit_timer,"skill_unit_timer");
|
|
@@ -23102,10 +23099,8 @@ void do_final_skill(void)
|
|
|
reading_spellbook_db.clear();
|
|
|
skill_arrow_db.clear();
|
|
|
|
|
|
- db_destroy(skillunit_group_db);
|
|
|
db_destroy(skillunit_db);
|
|
|
db_destroy(skillusave_db);
|
|
|
db_destroy(bowling_db);
|
|
|
- ers_destroy(skill_unit_ers);
|
|
|
ers_destroy(skill_timer_ers);
|
|
|
}
|