summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map/battle.c2
-rw-r--r--src/map/map.c4
-rw-r--r--src/map/skill.c51
-rw-r--r--src/map/skill.h1
-rw-r--r--src/map/status.c8
5 files changed, 49 insertions, 17 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index 4450c3258..01f4c9b67 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -311,7 +311,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT )
{
- struct skill_unit_group *group = (struct skill_unit_group *)sc->data[SC_SAFETYWALL]->val3;
+ struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3);
if (group) {
if (--group->val2<=0)
skill_delunitgroup(NULL,group);
diff --git a/src/map/map.c b/src/map/map.c
index 14a93c669..03b095295 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -437,9 +437,9 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
if (sc->data[SC_CLOAKING])
skill_check_cloaking(bl, sc->data[SC_CLOAKING]);
if (sc->data[SC_DANCING])
- skill_unit_move_unit_group((struct skill_unit_group *)sc->data[SC_DANCING]->val2, bl->m, x1-x0, y1-y0);
+ skill_unit_move_unit_group(skill_id2group(sc->data[SC_DANCING]->val2), bl->m, x1-x0, y1-y0);
if (sc->data[SC_WARM])
- skill_unit_move_unit_group((struct skill_unit_group *)sc->data[SC_WARM]->val4, bl->m, x1-x0, y1-y0);
+ skill_unit_move_unit_group(skill_id2group(sc->data[SC_WARM]->val4), bl->m, x1-x0, y1-y0);
}
}
} else
diff --git a/src/map/skill.c b/src/map/skill.c
index bd4bd618f..32f05a51a 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -6042,7 +6042,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
case HW_GRAVITATION:
if ((sg = skill_unitsetting(src,skillid,skilllv,x,y,0)))
- sc_start4(src,type,100,skilllv,0,BCT_SELF,(int)sg,skill_get_time(skillid,skilllv));
+ sc_start4(src,type,100,skilllv,0,BCT_SELF,sg->group_id,skill_get_time(skillid,skilllv));
flag|=1;
break;
@@ -6078,7 +6078,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
case SG_STAR_WARM:
skill_clear_unitgroup(src);
if ((sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0)))
- sc_start4(src,type,100,skilllv,0,0,(int)sg,skill_get_time(skillid,skilllv));
+ sc_start4(src,type,100,skilllv,0,0,sg->group_id,skill_get_time(skillid,skilllv));
flag|=1;
break;
@@ -6091,7 +6091,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
if (!sg) break;
if (sce)
status_change_end(src,type,-1); //Was under someone else's Gospel. [Skotlex]
- sc_start4(src,type,100,skilllv,0,(int)sg,BCT_SELF,skill_get_time(skillid,skilllv));
+ sc_start4(src,type,100,skilllv,0,sg->group_id,BCT_SELF,skill_get_time(skillid,skilllv));
clif_skill_poseffect(src, skillid, skilllv, 0, 0, tick); // PA_GOSPEL music packet
}
break;
@@ -6620,7 +6620,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
sd->skilllv_dance = skilllv;
}
if (
- sc_start4(src, SC_DANCING, 100, skillid, (int)group, skilllv,
+ sc_start4(src, SC_DANCING, 100, skillid, group->group_id, skilllv,
(group->state.song_dance&2?BCT_SELF:0), limit+1000) &&
sd && group->state.song_dance&2 && skillid != CG_HERMODE //Hermod is a encore with a warp!
)
@@ -6753,7 +6753,7 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
case UNT_SAFETYWALL:
//TODO: Find a more reliable way to handle the link to sg, this could cause dangling pointers. [Skotlex]
if (!sce)
- sc_start4(bl,type,100,sg->skill_lv,sg->group_id,(int)sg,0,sg->limit);
+ sc_start4(bl,type,100,sg->skill_lv,sg->group_id,sg->group_id,0,sg->limit);
break;
case UNT_PNEUMA:
@@ -9423,7 +9423,7 @@ void skill_stop_dancing (struct block_list *src)
if(!sc->count || !(sce=sc->data[SC_DANCING]))
return;
- group = (struct skill_unit_group *)sce->val2;
+ group = skill_id2group(sce->val2);
sce->val2 = 0;
if (sce->val4)
@@ -9547,8 +9547,38 @@ int skill_delunit (struct skill_unit* unit)
/*==========================================
*
*------------------------------------------*/
+static DBMap* group_db = NULL;// int group_id -> struct 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(group_db, group_id);
+}
+
+
static int skill_unit_group_newid = MAX_SKILL_DB;
+/// Returns a new group_id that isn't being used in group_db.
+/// Fatal error if nothing is available.
+static int skill_get_new_group_id(void)
+{
+ if( skill_unit_group_newid >= MAX_SKILL_DB && skill_id2group(skill_unit_group_newid) == NULL )
+ return skill_unit_group_newid++;// available
+ {// find next id
+ int base_id = skill_unit_group_newid;
+ while( base_id != ++skill_unit_group_newid )
+ {
+ if( skill_unit_group_newid < MAX_SKILL_DB )
+ skill_unit_group_newid = MAX_SKILL_DB;
+ if( skill_id2group(skill_unit_group_newid) == NULL )
+ return skill_unit_group_newid++;// available
+ }
+ // full loop, nothing available
+ ShowFatalError("skill_get_new_group_id: All ids are taken. Exiting...");
+ exit(1);
+ }
+}
+
struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, short skillid, short skilllv, int unit_id, int limit, int interval)
{
struct unit_data* ud = unit_bl2ud( src );
@@ -9581,7 +9611,7 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count,
group->src_id = src->id;
group->party_id = status_get_party_id(src);
group->guild_id = status_get_guild_id(src);
- group->group_id = skill_unit_group_newid++;
+ group->group_id = skill_get_new_group_id();
group->unit = (struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
group->unit_count = count;
group->alive_count = 0;
@@ -9599,12 +9629,10 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count,
ud->skillunit[i] = group;
- if(skill_unit_group_newid<=0)
- skill_unit_group_newid = MAX_SKILL_DB;
-
if (skillid == PR_SANCTUARY) //Sanctuary starts healing +1500ms after casted. [Skotlex]
group->tick += 1500;
+ idb_put(group_db, group->group_id, group);
return group;
}
@@ -9672,6 +9700,7 @@ int skill_delunitgroup (struct block_list *src, struct skill_unit_group *group)
}
map_freeblock(&group->unit->bl);
+ idb_remove(group_db, group->group_id);
group->unit=NULL;
group->group_id=0;
group->unit_count=0;
@@ -11304,6 +11333,7 @@ int do_init_skill (void)
skilldb_name2id = strdb_alloc(DB_OPT_DUP_KEY, 0);
skill_readdb();
+ group_db = idb_alloc(DB_OPT_BASE);
skill_unit_ers = ers_new(sizeof(struct skill_unit_group));
skill_timer_ers = ers_new(sizeof(struct skill_timerskill));
@@ -11321,6 +11351,7 @@ int do_init_skill (void)
int do_final_skill(void)
{
db_destroy(skilldb_name2id);
+ db_destroy(group_db);
ers_destroy(skill_unit_ers);
ers_destroy(skill_timer_ers);
return 0;
diff --git a/src/map/skill.h b/src/map/skill.h
index 75cb63e9c..a9156edde 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -266,6 +266,7 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
int skill_break_equip(struct block_list *bl, unsigned short where, int rate, int flag);
int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time);
// ユニットスキル
+struct skill_unit_group* skill_id2group(int group_id);
struct skill_unit_group *skill_unitsetting(struct block_list* src, short skillid, short skilllv, short x, short y, int flag);
struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2);
int skill_delunit(struct skill_unit *unit);
diff --git a/src/map/status.c b/src/map/status.c
index e8da71bcc..fcfc0fb7f 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -692,7 +692,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
}
if ((sce=sc->data[SC_GRAVITATION]) && sce->val3 == BCT_SELF)
{
- struct skill_unit_group *sg = (struct skill_unit_group *)sce->val4;
+ struct skill_unit_group* sg = skill_id2group(sce->val4);
if (sg) {
skill_delunitgroup(target,sg);
sce->val4 = 0;
@@ -6602,7 +6602,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
struct skill_unit_group *group;
if(sce->val2)
{
- group = (struct skill_unit_group *)sce->val2;
+ group = skill_id2group(sce->val2);
sce->val2 = 0;
skill_delunitgroup(bl, group);
}
@@ -6691,7 +6691,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
break;
case SC_GOSPEL:
if (sce->val3) { //Clear the group.
- struct skill_unit_group *group = (struct skill_unit_group *)sce->val3;
+ struct skill_unit_group* group = skill_id2group(sce->val3);
sce->val3 = 0;
skill_delunitgroup(bl, group);
}
@@ -6708,7 +6708,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
break;
case SC_WARM:
if (sce->val4) { //Clear the group.
- struct skill_unit_group *group = (struct skill_unit_group *)sce->val4;
+ struct skill_unit_group* group = skill_id2group(sce->val4);
sce->val4 = 0;
skill_delunitgroup(bl, group);
}