summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2014-12-27 06:35:34 +0100
committerHaru <haru@dotalux.com>2015-01-23 04:14:28 +0100
commite778f4f5f1b6a08adee5e7e908a44c38cd29bd12 (patch)
tree63cbc8e6eb78ffc374ffac374bf5e533b58bcafa
parentb1b1b1aa8edc866a83029081e93d3e7d0f138189 (diff)
downloadhercules-e778f4f5f1b6a08adee5e7e908a44c38cd29bd12.tar.gz
hercules-e778f4f5f1b6a08adee5e7e908a44c38cd29bd12.tar.bz2
hercules-e778f4f5f1b6a08adee5e7e908a44c38cd29bd12.tar.xz
hercules-e778f4f5f1b6a08adee5e7e908a44c38cd29bd12.zip
Cleaned up spirit charms implementation (optimized memory and CPU usage)
Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r--src/map/battle.c67
-rw-r--r--src/map/clif.c41
-rw-r--r--src/map/clif.h4
-rw-r--r--src/map/map.h21
-rw-r--r--src/map/pc.c141
-rw-r--r--src/map/pc.h9
-rw-r--r--src/map/skill.c46
-rw-r--r--src/map/status.c10
-rw-r--r--src/map/unit.c10
9 files changed, 170 insertions, 179 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index 0201e0e3a..d32a799ab 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -1251,8 +1251,8 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
def1 -= def1 * i / 100;
def2 -= def2 * i / 100;
}
- if ( sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] > 0 ) // hidden from status window
- def1 += 10 * def1 * sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] / 100;
+ if (sd->charm_type == CHARM_TYPE_LAND && sd->charm_count > 0 ) // hidden from status window
+ def1 += 10 * def1 * sd->charm_count / 100;
}
if( sc && sc->data[SC_EXPIATIO] ){
@@ -1491,39 +1491,39 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
case NJ_KOUENKA:
skillratio -= 10;
- if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE] > 0 )
- skillratio += 20 * sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE];
+ if (sd && sd->charm_type == CHARM_TYPE_FIRE && sd->charm_count > 0)
+ skillratio += 20 * sd->charm_count;
break;
case NJ_KAENSIN:
skillratio -= 50;
- if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE] > 0 )
- skillratio += 10 * sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE];
+ if (sd && sd->charm_type == CHARM_TYPE_FIRE && sd->charm_count > 0)
+ skillratio += 10 * sd->charm_count;
break;
case NJ_BAKUENRYU:
skillratio += 50 * (skill_lv - 1);
- if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE] > 0 )
- skillratio += 15 * sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE];
+ if (sd && sd->charm_type == CHARM_TYPE_FIRE && sd->charm_count > 0)
+ skillratio += 15 * sd->charm_count;
break;
#ifdef RENEWAL
case NJ_HYOUSENSOU:
skillratio -= 30;
- if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER] > 0 )
- skillratio += 5 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER];
+ if (sd && sd->charm_type == CHARM_TYPE_WATER && sd->charm_count > 0)
+ skillratio += 5 * sd->charm_count;
#endif
/* Fall through */
case NJ_HYOUSYOURAKU:
skillratio += 50 * skill_lv;
- if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER] > 0 )
- skillratio += 25 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER];
+ if (sd && sd->charm_type == CHARM_TYPE_WATER && sd->charm_count > 0)
+ skillratio += 25 * sd->charm_count;
break;
case NJ_RAIGEKISAI:
skillratio += 60 + 40 * skill_lv;
- if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND] > 0 )
- skillratio += 15 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND];
+ if (sd && sd->charm_type == CHARM_TYPE_WIND && sd->charm_count > 0)
+ skillratio += 15 * sd->charm_count;
break;
case NJ_KAMAITACHI:
- if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND] > 0 )
- skillratio += 10 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND];
+ if (sd && sd->charm_type == CHARM_TYPE_WIND && sd->charm_count > 0)
+ skillratio += 10 * sd->charm_count;
/* Fall through */
case NPC_ENERGYDRAIN:
skillratio += 100 * skill_lv;
@@ -1550,8 +1550,8 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
case NJ_HUUJIN:
skillratio += 50;
- if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND] > 0 )
- skillratio += 20 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND];
+ if (sd && sd->charm_type == CHARM_TYPE_WIND && sd->charm_count > 0)
+ skillratio += 20 * sd->charm_count;
break;
#else
case WZ_VERMILION:
@@ -1773,13 +1773,10 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 100 * skill_lv;
break;
case KO_KAIHOU:
- if ( sd ) {
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
- if ( i < SPIRITS_TYPE_SPHERE ) {
- skillratio += -100 + 200 * sd->spiritcharm[i];
- RE_LVL_DMOD(100);
- pc->del_charm(sd, sd->spiritcharm[i], i);
- }
+ if (sd && sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0) {
+ skillratio += -100 + 200 * sd->charm_count;
+ RE_LVL_DMOD(100);
+ pc->del_charm(sd, sd->charm_count, sd->charm_type);
}
break;
default:
@@ -3389,10 +3386,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element
s_ele = sstatus->rhw.ele;
- if( sd ){ //Summoning 10 spiritcharm will endow your weapon
- int i;
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] >= MAX_SPIRITCHARM);
- if( i < SPIRITS_TYPE_SPHERE ) s_ele = i;
+ if (sd && sd->charm_type != CHARM_TYPE_NONE && sd->charm_count >= MAX_SPIRITCHARM) {
+ //Summoning 10 spiritcharm will endow your weapon
+ s_ele = sd->charm_type;
}
}else if (s_ele == -2) //Use status element
s_ele = status_get_attack_sc_element(src,status->get_sc(src));
@@ -3434,11 +3430,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
s_ele = ELE_DARK;
break;
case KO_KAIHOU:
- if (sd) {
- int i;
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
- if( i < SPIRITS_TYPE_SPHERE )
- s_ele = i;
+ if (sd && sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0) {
+ s_ele = sd->charm_type;
}
break;
#ifdef RENEWAL
@@ -4296,9 +4289,9 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
{ //Take weapon's element
s_ele = sstatus->rhw.ele;
s_ele_ = sstatus->lhw.ele;
- if( sd ){ //Summoning 10 spiritcharm will endow your weapon.
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] >= MAX_SPIRITCHARM);
- if( i < SPIRITS_TYPE_SPHERE ) s_ele = s_ele_ = i;
+ if (sd && sd->charm_type != CHARM_TYPE_NONE && sd->charm_count >= MAX_SPIRITCHARM) {
+ //Summoning 10 spiritcharm will endow your weapon.
+ s_ele = s_ele_ = sd->charm_type;
}
if( flag.arrow && sd && sd->bonus.arrow_ele )
s_ele = sd->bonus.arrow_ele;
diff --git a/src/map/clif.c b/src/map/clif.c
index d39d87a8f..268066d1a 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -1280,16 +1280,13 @@ void clif_spiritball_single(int fd, struct map_session_data *sd) {
/*==========================================
* Kagerou/Oboro amulet spirit
*------------------------------------------*/
-void clif_charm_single(int fd, struct map_session_data *sd, short type) {
-
- if ( type <= SPIRITS_TYPE_NONE || type >= SPIRITS_TYPE_SPHERE )
- return;
-
+void clif_charm_single(int fd, struct map_session_data *sd)
+{
WFIFOHEAD(fd, packet_len(0x08cf));
- WFIFOW(fd,0)=0x08cf;
- WFIFOL(fd,2)=sd->bl.id;
- WFIFOW(fd,6)=type;
- WFIFOW(fd,8)=sd->spiritcharm[type];
+ WFIFOW(fd,0) = 0x08cf;
+ WFIFOL(fd,2) = sd->bl.id;
+ WFIFOW(fd,6) = sd->charm_type;
+ WFIFOW(fd,8) = sd->charm_count;
WFIFOSET(fd, packet_len(0x08cf));
}
@@ -1375,8 +1372,8 @@ bool clif_spawn(struct block_list *bl)
for( i = 0; i < sd->sc_display_count; i++ ) {
clif->sc_load(&sd->bl, sd->bl.id,AREA,status->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3);
}
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
- clif->spiritcharm(sd, i);
+ if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0)
+ clif->spiritcharm(sd);
if (sd->status.robe)
clif->refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA);
}
@@ -4275,8 +4272,8 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
if(dstsd->spiritball > 0)
clif->spiritball_single(sd->fd, dstsd);
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
- clif->charm_single(sd->fd, dstsd, i);
+ if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0)
+ clif->charm_single(sd->fd, dstsd);
for( i = 0; i < dstsd->sc_display_count; i++ ) {
clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3);
@@ -8473,7 +8470,6 @@ void clif_refresh_storagewindow( struct map_session_data *sd ) {
// refresh the client's screen, getting rid of any effects
void clif_refresh(struct map_session_data *sd)
{
- int i;
nullpo_retv(sd);
clif->changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y);
@@ -8492,8 +8488,8 @@ void clif_refresh(struct map_session_data *sd)
clif->updatestatus(sd,SP_LUK);
if (sd->spiritball)
clif->spiritball_single(sd->fd, sd);
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
- clif->charm_single(sd->fd, sd, i);
+ if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0)
+ clif->charm_single(sd->fd, sd);
if (sd->vd.cloth_color)
clif->refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF);
@@ -17471,19 +17467,16 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) {
/*==========================================
* Kagerou/Oboro amulet spirit
*------------------------------------------*/
-void clif_charm(struct map_session_data *sd,short type)
+void clif_charm(struct map_session_data *sd)
{
unsigned char buf[10];
nullpo_retv(sd);
- if ( type <= SPIRITS_TYPE_NONE || type >= SPIRITS_TYPE_SPHERE )
- return;
-
- WBUFW(buf,0)=0x08cf;
- WBUFL(buf,2)=sd->bl.id;
- WBUFW(buf,6)=type;
- WBUFW(buf,8)=sd->spiritcharm[type];
+ WBUFW(buf,0) = 0x08cf;
+ WBUFL(buf,2) = sd->bl.id;
+ WBUFW(buf,6) = sd->charm_type;
+ WBUFW(buf,8) = sd->charm_count;
clif->send(buf,packet_len(0x08cf),&sd->bl,AREA);
}
/// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE]
diff --git a/src/map/clif.h b/src/map/clif.h
index 3144f1586..6a99ba79a 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -820,8 +820,8 @@ struct clif_interface {
void (*specialeffect_single) (struct block_list* bl, int type, int fd);
void (*specialeffect_value) (struct block_list* bl, int effect_id, int num, send_target target);
void (*millenniumshield) (struct block_list *bl, short shields );
- void (*spiritcharm) (struct map_session_data *sd, short type);
- void (*charm_single) (int fd, struct map_session_data *sd, short type);
+ void (*spiritcharm) (struct map_session_data *sd);
+ void (*charm_single) (int fd, struct map_session_data *sd);
void (*snap) ( struct block_list *bl, short x, short y );
void (*weather_check) (struct map_session_data *sd);
/* sound effects client-side */
diff --git a/src/map/map.h b/src/map/map.h
index 3b24872fe..c28a65f52 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -283,7 +283,7 @@ enum {
RC2_MAX
};
-enum {
+enum elements {
ELE_NEUTRAL=0,
ELE_WATER,
ELE_EARTH,
@@ -297,14 +297,17 @@ enum {
ELE_MAX
};
-enum {
- SPIRITS_TYPE_NONE = 0,
- SPIRITS_TYPE_CHARM_WATER,
- SPIRITS_TYPE_CHARM_LAND,
- SPIRITS_TYPE_CHARM_FIRE,
- SPIRITS_TYPE_CHARM_WIND,
- SPIRITS_TYPE_SPHERE,
- SPIRITS_TYPE_END
+/**
+ * Types of spirit charms.
+ *
+ * Note: Code assumes that this matches the first entries in enum elements.
+ */
+enum spirit_charm_types {
+ CHARM_TYPE_NONE = 0,
+ CHARM_TYPE_WATER,
+ CHARM_TYPE_LAND,
+ CHARM_TYPE_FIRE,
+ CHARM_TYPE_WIND
};
enum auto_trigger_flag {
diff --git a/src/map/pc.c b/src/map/pc.c
index af630a5c6..806bfb42c 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -7017,8 +7017,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
if ( sd->spiritball )
pc->delspiritball(sd, sd->spiritball, 0);
- for ( i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++ )
- pc->del_charm(sd, sd->spiritcharm[i], i);
+ if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0)
+ pc->del_charm(sd, sd->charm_count, sd->charm_type);
if (src) {
switch (src->type) {
@@ -9794,103 +9794,124 @@ bool pc_can_use_command(struct map_session_data *sd, const char *command) {
return atcommand->can_use(sd,command);
}
-int pc_charm_timer(int tid, int64 tick, int id, intptr_t data) {
+/**
+ * Spirit Charm expiration timer.
+ *
+ * @see TimerFunc
+ */
+int pc_charm_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd;
- int i, type;
+ int i;
if( (sd=(struct map_session_data *)map->id2sd(id)) == NULL || sd->bl.type!=BL_PC )
return 1;
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, type, sd->spiritcharm[type] > 0);
-
- if( sd->spiritcharm[type] <= 0 )
- {
- ShowError("pc_charm_timer: %d spiritcharm's available. (aid=%d cid=%d tid=%d)\n", sd->spiritcharm[type], sd->status.account_id, sd->status.char_id, tid);
- sd->spiritcharm[type] = 0;
+ if (sd->charm_count <= 0) {
+ ShowError("pc_charm_timer: %d spiritcharm's available. (aid=%d cid=%d tid=%d)\n", sd->charm_count, sd->status.account_id, sd->status.char_id, tid);
+ sd->charm_count = 0;
return 0;
}
- ARR_FIND(0, sd->spiritcharm[type], i, sd->charm_timer[type][i] == tid);
- if( i == sd->spiritcharm[type] )
- {
+ ARR_FIND(0, sd->charm_count, i, sd->charm_timer[i] == tid);
+ if (i == sd->charm_count) {
ShowError("pc_charm_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid);
return 0;
}
- sd->spiritcharm[type]--;
- if( i != sd->spiritcharm[type] )
- memmove(sd->charm_timer[type]+i, sd->charm_timer[type]+i+1, (sd->spiritcharm[type]-i)*sizeof(int));
- sd->charm_timer[type][sd->spiritcharm[type]] = INVALID_TIMER;
+ sd->charm_count--;
+ if(i != sd->charm_count)
+ memmove(sd->charm_timer+i, sd->charm_timer+i+1, (sd->charm_count-i)*sizeof(int));
+ sd->charm_timer[sd->charm_count] = INVALID_TIMER;
- clif->spiritcharm(sd, type);
+ clif->spiritcharm(sd);
return 0;
}
-int pc_add_charm(struct map_session_data *sd,int interval,int max,int type)
+/**
+ * Adds a spirit charm.
+ *
+ * @param sd Target character.
+ * @param interval Duration.
+ * @param max Maximum amount of charms to add.
+ * @param type Charm type (@see spirit_charm_types)
+ */
+void pc_add_charm(struct map_session_data *sd, int interval, int max, int type)
{
int tid, i;
- nullpo_ret(sd);
+ nullpo_retv(sd);
- if(max > 10)
- max = 10;
- if(sd->spiritcharm[type] < 0)
- sd->spiritcharm[type] = 0;
+ if (sd->charm_type != CHARM_TYPE_NONE && type != sd->charm_type) {
+ pc->del_charm(sd, sd->charm_count, sd->charm_type);
+ }
- if( sd->spiritcharm[type] && sd->spiritcharm[type] >= max )
- {
- if(sd->charm_timer[type][0] != INVALID_TIMER)
- timer->delete(sd->charm_timer[type][0],pc->charm_timer);
- sd->spiritcharm[type]--;
- if( sd->spiritcharm[type] != 0 )
- memmove(sd->charm_timer[type]+0, sd->charm_timer[type]+1, (sd->spiritcharm[type])*sizeof(int));
- sd->charm_timer[type][sd->spiritcharm[type]] = INVALID_TIMER;
+ if (max > MAX_SPIRITCHARM)
+ max = MAX_SPIRITCHARM;
+ if (sd->charm_count < 0)
+ sd->charm_count = 0;
+
+ if (sd->charm_count && sd->charm_count >= max) {
+ if (sd->charm_timer[0] != INVALID_TIMER)
+ timer->delete(sd->charm_timer[0],pc->charm_timer);
+ sd->charm_count--;
+ if (sd->charm_count != 0)
+ memmove(sd->charm_timer+0, sd->charm_timer+1, sd->charm_count*sizeof(int));
+ sd->charm_timer[sd->charm_count] = INVALID_TIMER;
}
tid = timer->add(timer->gettick()+interval, pc->charm_timer, sd->bl.id, 0);
- ARR_FIND(0, sd->spiritcharm[type], i, sd->charm_timer[type][i] == INVALID_TIMER || DIFF_TICK(timer->get(tid)->tick, timer->get(sd->charm_timer[type][i])->tick) < 0);
- if( i != sd->spiritcharm[type] )
- memmove(sd->charm_timer[type]+i+1, sd->charm_timer[type]+i, (sd->spiritcharm[type]-i)*sizeof(int));
- sd->charm_timer[type][i] = tid;
- sd->spiritcharm[type]++;
+ ARR_FIND(0, sd->charm_count, i, sd->charm_timer[i] == INVALID_TIMER || DIFF_TICK(timer->get(tid)->tick, timer->get(sd->charm_timer[i])->tick) < 0);
+ if (i != sd->charm_count)
+ memmove(sd->charm_timer+i+1, sd->charm_timer+i, (sd->charm_count-i)*sizeof(int));
+ sd->charm_timer[i] = tid;
+ sd->charm_count++;
- clif->spiritcharm(sd, type);
- return 0;
+ clif->spiritcharm(sd);
}
-int pc_del_charm(struct map_session_data *sd,int count,int type)
+/**
+ * Removes one or more spirit charms.
+ *
+ * @param sd The target character.
+ * @param count Amount of charms to remove.
+ * @param type Type of charm to remove.
+ */
+void pc_del_charm(struct map_session_data *sd, int count, int type)
{
int i;
- nullpo_ret(sd);
+ nullpo_retv(sd);
- if( sd->spiritcharm[type] <= 0 ) {
- sd->spiritcharm[type] = 0;
- return 0;
+ if (sd->charm_type != type)
+ return;
+
+ if (sd->charm_count <= 0) {
+ sd->charm_count = 0;
+ return;
}
- if( count <= 0 )
- return 0;
- if( count > sd->spiritcharm[type] )
- count = sd->spiritcharm[type];
- sd->spiritcharm[type] -= count;
- if( count > 10 )
- count = 10;
+ if (count <= 0)
+ return;
+ if (count > sd->charm_count)
+ count = sd->charm_count;
+ sd->charm_count -= count;
+ if (count > MAX_SPIRITCHARM)
+ count = MAX_SPIRITCHARM;
- for(i = 0; i < count; i++) {
- if(sd->charm_timer[type][i] != INVALID_TIMER) {
- timer->delete(sd->charm_timer[type][i],pc->charm_timer);
- sd->charm_timer[type][i] = INVALID_TIMER;
+ for (i = 0; i < count; i++) {
+ if(sd->charm_timer[i] != INVALID_TIMER) {
+ timer->delete(sd->charm_timer[i],pc->charm_timer);
+ sd->charm_timer[i] = INVALID_TIMER;
}
}
- for(i = count; i < 10; i++) {
- sd->charm_timer[type][i-count] = sd->charm_timer[type][i];
- sd->charm_timer[type][i] = INVALID_TIMER;
+ for (i = count; i < MAX_SPIRITCHARM; i++) {
+ sd->charm_timer[i-count] = sd->charm_timer[i];
+ sd->charm_timer[i] = INVALID_TIMER;
}
- clif->spiritcharm(sd, type);
- return 0;
+ clif->spiritcharm(sd);
}
/*==========================================
* Renewal EXP/Itemdrop rate modifier base on level penalty
diff --git a/src/map/pc.h b/src/map/pc.h
index b7839147d..1785bd4c4 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -366,8 +366,9 @@ struct map_session_data {
short catch_target_class; // pet catching, stores a pet class to catch (short now) [zzo]
short spiritball, spiritball_old;
int spirit_timer[MAX_SPIRITBALL];
- short spiritcharm[SPIRITS_TYPE_END];
- int charm_timer[SPIRITS_TYPE_END][MAX_SPIRITCHARM];
+ short charm_count;
+ int charm_type;
+ int charm_timer[MAX_SPIRITCHARM];
unsigned char potion_success_counter; //Potion successes in row counter
unsigned char mission_count; //Stores the bounty kill count for TK_MISSION
short mission_mobid; //Stores the target mob_id for TK_MISSION
@@ -970,8 +971,8 @@ struct pc_interface {
int (*load_combo) (struct map_session_data *sd);
- int (*add_charm) (struct map_session_data *sd,int interval,int max,int type);
- int (*del_charm) (struct map_session_data *sd,int count,int type);
+ void (*add_charm) (struct map_session_data *sd, int interval, int max, int type);
+ void (*del_charm) (struct map_session_data *sd, int count, int type);
void (*baselevelchanged) (struct map_session_data *sd);
int (*level_penalty_mod) (int diff, unsigned char race, unsigned short mode, int type);
diff --git a/src/map/skill.c b/src/map/skill.c
index 81095b4ac..55b86310e 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -6168,10 +6168,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
sp = 2 * dstmd->level;
mob->target(dstmd,src,0);
}
- if ( dstsd ) {
- int i;
- for ( i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++ )
- pc->del_charm(dstsd, dstsd->spiritcharm[i], i);
+ if (dstsd && dstsd->charm_type != CHARM_TYPE_NONE && dstsd->charm_count > 0) {
+ pc->del_charm(dstsd, dstsd->charm_count, dstsd->charm_type);
}
if (sp) status->heal(src, 0, sp, 3);
clif->skill_nodamage(src,bl,skill_id,skill_lv,sp?1:0);
@@ -9039,10 +9037,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
pc->delspiritball(dstsd, dstsd->spiritball, 0);
status_percent_heal(src, 0, sp);
}
- if ( dstsd ) {
- int i;
- for (i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++)
- pc->del_charm(dstsd, dstsd->spiritcharm[i], i);
+ if (dstsd && dstsd->charm_type != CHARM_TYPE_NONE && dstsd->charm_count > 0) {
+ pc->del_charm(dstsd, dstsd->charm_count, dstsd->charm_type);
}
clif->skill_nodamage(src, bl, skill_id, skill_lv, sp ? 1:0);
} else {
@@ -9620,13 +9616,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case KO_KAZEHU_SEIRAN:
case KO_DOHU_KOUKAI:
if(sd) {
- int i;
int ttype = skill->get_ele(skill_id, skill_lv);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0 && ttype != i);
- if( i < SPIRITS_TYPE_SPHERE )
- pc->del_charm(sd, sd->spiritcharm[i], i); // replace with a new one.
- pc->add_charm(sd, skill->get_time(skill_id, skill_lv), MAX_SPIRITCHARM, ttype);
+ pc->add_charm(sd, skill->get_time(skill_id, skill_lv), MAX_SPIRITCHARM, ttype); // replace existing charms of other type
}
break;
@@ -11397,14 +11389,13 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
val3 = (x<<16)|y;
break;
case KO_ZENKAI:
- if( sd ){
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
- if( i < SPIRITS_TYPE_SPHERE ){
- val1 = sd->spiritcharm[i]; // no. of aura
- val2 = i; // aura type
+ if (sd) {
+ if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0) {
+ val1 = sd->charm_count; // no. of aura
+ val2 = sd->charm_type; // aura type
limit += val1 * 1000;
- subunt = i - 1;
- pc->del_charm(sd, sd->spiritcharm[i], i);
+ subunt = sd->charm_type - 1;
+ pc->del_charm(sd, sd->charm_count, sd->charm_type);
}
}
break;
@@ -13732,24 +13723,17 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case KO_HYOUHU_HUBUKI:
case KO_KAZEHU_SEIRAN:
case KO_DOHU_KOUKAI:
- {
- int ttype = skill->get_ele(skill_id, skill_lv);
- if( sd->spiritcharm[ttype] >= MAX_SPIRITCHARM ){
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0);
- return 0;
- }
+ if (sd->charm_type == skill->get_ele(skill_id, skill_lv) && sd->charm_count >= MAX_SPIRITCHARM) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0);
+ return 0;
}
break;
case KO_KAIHOU:
case KO_ZENKAI:
- {
- int i;
- ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
- if( i >= SPIRITS_TYPE_SPHERE ) {
+ if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0);
return 0;
}
- }
break;
default:
{
diff --git a/src/map/status.c b/src/map/status.c
index 9ad8d849f..3da0238c5 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -8648,11 +8648,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC__ENERVATION:
val2 = 20 + 10 * val1; // ATK Reduction
- if ( sd ) {
- int i;
+ if (sd) {
pc->delspiritball(sd, sd->spiritball, 0);
- for (i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++)
- pc->del_charm(sd, sd->spiritcharm[i], i);
+ pc->del_charm(sd, sd->charm_count, sd->charm_type);
}
break;
case SC__GROOMY:
@@ -11495,8 +11493,8 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl
max += (rnd() % 100) % r + 1;
}
- if ( sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] > 0 )
- max += 10 * max * sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] / 100;
+ if (sd->charm_type == CHARM_TYPE_LAND && sd->charm_count > 0)
+ max += 10 * max * sd->charm_count / 100;
}
max = status->calc_watk(bl, sc, max, false);
diff --git a/src/map/unit.c b/src/map/unit.c
index 27b96c55b..6e4efd533 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -2593,8 +2593,6 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
case BL_PC:
{
struct map_session_data *sd = (struct map_session_data*)bl;
- int i;
- unsigned int k;
sd->state.loggingout = 1;
@@ -2619,8 +2617,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
pc->cleareventtimer(sd);
pc->inventory_rental_clear(sd);
pc->delspiritball(sd,sd->spiritball,1);
- for(i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++)
- pc->del_charm(sd, sd->spiritcharm[i], i);
+ pc->del_charm(sd, sd->charm_count, sd->charm_type);
if( sd->st && sd->st->state != RUN ) {// free attached scripts that are waiting
script->free_state(sd->st);
@@ -2634,6 +2631,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
sd->combo_count = 0;
/* [Ind/Hercules] */
if( sd->sc_display_count ) {
+ int i;
for(i = 0; i < sd->sc_display_count; i++) {
ers_free(pc->sc_display_ers, sd->sc_display[i]);
}
@@ -2657,8 +2655,8 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
sd->num_quests = sd->avail_quests = 0;
}
- if( sd->hdata )
- {
+ if (sd->hdata) {
+ unsigned int k;
for( k = 0; k < sd->hdatac; k++ ) {
if( sd->hdata[k]->flag.free ) {
aFree(sd->hdata[k]->data);