diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/battle.c | 2 | ||||
-rw-r--r-- | src/map/map.c | 4 | ||||
-rw-r--r-- | src/map/skill.c | 51 | ||||
-rw-r--r-- | src/map/skill.h | 1 | ||||
-rw-r--r-- | src/map/status.c | 8 |
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); } |