summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-SVN.txt4
-rw-r--r--conf-tmpl/packet_athena.conf45
-rw-r--r--db/const.txt4
-rw-r--r--doc/item_bonus.txt10
-rw-r--r--src/common/socket.c48
-rw-r--r--src/map/battle.c12
-rw-r--r--src/map/map.h10
-rw-r--r--src/map/mob.c33
-rw-r--r--src/map/pc.c47
-rw-r--r--src/map/status.c6
10 files changed, 157 insertions, 62 deletions
diff --git a/Changelog-SVN.txt b/Changelog-SVN.txt
index bbbf13d6a..c05c01b98 100644
--- a/Changelog-SVN.txt
+++ b/Changelog-SVN.txt
@@ -2,8 +2,12 @@ Date Added
03/20
* Fixed @storage / @gstorage ATcommands thanks2 Yor/Freya [Lupus]
+ * Added 4 new card effects from 3/15's patch -- check item_bonus.txt [celest]
+ * Added 'enable_ip_rules' to packet_athena.conf [celest]
+ * Updated socket debug messages to be more readable [celest]
* Added a sql upgrader to handle the mob_db changes to assist
in migrating to the newer SVN servers [MouseJstr]
+
03/19
* Added getrefine() for 3/15's card patch -- returns the refined number
of the current item [celest]
diff --git a/conf-tmpl/packet_athena.conf b/conf-tmpl/packet_athena.conf
index b8e1f31f7..b11baa429 100644
--- a/conf-tmpl/packet_athena.conf
+++ b/conf-tmpl/packet_athena.conf
@@ -1,27 +1,18 @@
-// ソケット関連の設定です。 (Untranslated yet)
+// Athena sockets Configuration file
+// (Untranslated yet)
-// How long can a socket stall before closing the connection (in seconds)
-stall_time: 60
-
-//---- Ddos Protection Settings ----
-
// デバッグ情報の表示(バグ報告の際にコピペして頂けると助かります)
-// debug: 1
+debug: no
-// ddos攻撃と判断する為のルール設定
-// ddos_interval msec以内の接続要求がddos_count回続いた場合に、
-// ddos攻撃されたと判定します。
+// How long can a socket stall before closing the connection (in seconds)
+stall_time: 60
-// 接続間隔(msec)
-ddos_interval: 3000
-// 接続回数
-ddos_count: 5
+//----- IP Rules Settings -----
-// ddos制限を解除する間隔(msec)
-// この時間経過すると、接続制限が解除されます。
-ddos_autoreset: 600000
+// Do we check IP's before allowing incoming connections?
+enable_ip_rules: yes
// アクセス制限の判定順序(Apacheと同じ)
// deny,allow が標準になっています。
@@ -43,4 +34,22 @@ allow: all
// deny: 127.0.0.1
-import: conf/import/packet_conf.txt \ No newline at end of file
+
+//---- Ddos Protection Settings ----
+
+// ddos攻撃と判断する為のルール設定
+// ddos_interval msec以内の接続要求がddos_count回続いた場合に、
+// ddos攻撃されたと判定します。
+
+// 接続間隔(msec)
+ddos_interval: 3000
+
+// 接続回数
+ddos_count: 5
+
+// ddos制限を解除する間隔(msec)
+// この時間経過すると、接続制限が解除されます。
+ddos_autoreset: 600000
+
+
+//import: conf/import/packet_conf.txt \ No newline at end of file
diff --git a/db/const.txt b/db/const.txt
index 6c3ec6b8b..329c3530f 100644
--- a/db/const.txt
+++ b/db/const.txt
@@ -250,6 +250,10 @@ bHPGainValue 2025
bSubSize 2026
bDamageWhenUnequip 2027
bAddItemHealRate 2028
+bLoseSPWhenUnequip 2029
+bExpAddRace 2030
+bSPGainRace 2031
+bSPSubRace2 2032
Eff_Stone 0
diff --git a/doc/item_bonus.txt b/doc/item_bonus.txt
index 039a84bd7..fbc613893 100644
--- a/doc/item_bonus.txt
+++ b/doc/item_bonus.txt
@@ -192,3 +192,13 @@ bonus4 bAutoSpellWhenHit,x,y,n,i; n% chance to cast skill x of level y when
bonus2 bAddItemHealRate,n,x; Increases HP recovered by n type items by x%
n:1=potions 2=herbs 3=fruits 4=meat 5=candy
6=juice 7=sashimi
+
+//---- 3/15 new card effects ----
+
+bonus bLoseSPWhenUnequip.n; Lose n SP when the item is unequipped
+
+bonus2 bExpAddRace,n,x; Increase exp gained by n% vs. enemies of type x
+bonus2 bSPGainRace,n,x; When killing a monster of type x by physical
+ attack gain n amount of sp
+bonus2 bSPSubRace2,n,x; Damage x% reduction from enemies of race n
+ (Check db/mob_race2_db.txt)
diff --git a/src/common/socket.c b/src/common/socket.c
index 19e4275a8..f49d4c0ca 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -42,6 +42,7 @@ fd_set readfds;
int fd_max;
time_t tick_;
time_t stall_time_ = 60;
+int ip_rules = 1;
int rfifo_size = 65536;
int wfifo_size = 65536;
@@ -50,6 +51,8 @@ int wfifo_size = 65536;
#define TCP_FRAME_LEN 1053
#endif
+#define CONVIP(ip) ip&0xFF,(ip>>8)&0xFF,(ip>>16)&0xFF,ip>>24
+
struct socket_data *session[FD_SETSIZE];
static int null_parse(int fd);
@@ -197,7 +200,7 @@ static int connect_client(int listen_fd)
if(fd==-1) {
perror("accept");
return -1;
- } else if (!connect_check(*(unsigned int*)(&client_address.sin_addr))) {
+ } else if (ip_rules && !connect_check(*(unsigned int*)(&client_address.sin_addr))) {
close(fd);
return -1;
} else
@@ -554,7 +557,7 @@ static struct _access_control *access_deny;
static int access_order=ACO_DENY_ALLOW;
static int access_allownum=0;
static int access_denynum=0;
-static int access_debug;
+static int access_debug=0;
static int ddos_count = 10;
static int ddos_interval = 3000;
static int ddos_autoreset = 600*1000;
@@ -576,8 +579,8 @@ static int connect_check_(unsigned int ip);
static int connect_check(unsigned int ip) {
int result = connect_check_(ip);
if(access_debug) {
- printf("connect_check: connection from %08x %s\n",
- ip,result ? "allowed" : "denied");
+ printf("connect_check: Connection from %d.%d.%d.%d %s\n",
+ CONVIP(ip),result ? "allowed." : "denied!");
}
return result;
}
@@ -591,8 +594,10 @@ static int connect_check_(unsigned int ip) {
for(i = 0;i < access_allownum; i++) {
if((ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask)) {
if(access_debug) {
- printf("connect_check: match allow list from:%08x ip:%08x mask:%08x\n",
- ip,access_allow[i].ip,access_allow[i].mask);
+ printf("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
+ CONVIP(ip),
+ CONVIP(access_allow[i].ip),
+ CONVIP(access_allow[i].mask));
}
is_allowip = 1;
break;
@@ -601,8 +606,10 @@ static int connect_check_(unsigned int ip) {
for(i = 0;i < access_denynum; i++) {
if((ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask)) {
if(access_debug) {
- printf("connect_check: match deny list from:%08x ip:%08x mask:%08x\n",
- ip,access_deny[i].ip,access_deny[i].mask);
+ printf("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
+ CONVIP(ip),
+ CONVIP(access_deny[i].ip),
+ CONVIP(access_deny[i].mask));
}
is_denyip = 1;
break;
@@ -655,8 +662,8 @@ static int connect_check_(unsigned int ip) {
if(hist->count++ >= ddos_count) {
// ddos 攻撃を検出
hist->status = 1;
- printf("connect_check: ddos attack detected (%d.%d.%d.%d)\n",
- ip & 0xFF,(ip >> 8) & 0xFF,(ip >> 16) & 0xFF,ip >> 24);
+ printf("connect_check: DDOS Attack detected from %d.%d.%d.%d!\n",
+ CONVIP(ip));
return (connect_ok == 2 ? 1 : 0);
} else {
return connect_ok;
@@ -715,7 +722,7 @@ static int connect_check_clear(int tid,unsigned int tick,int id,int data) {
}
}
if(access_debug) {
- printf("connect_check_clear: clear = %d list = %d\n",clear,list);
+ printf("connect_check_clear: Cleared %d of %d from IP list.\n", clear, clear+list);
}
return list;
}
@@ -729,7 +736,7 @@ int access_ipmask(const char *str,struct _access_control* acc)
mask = 0;
} else {
if( sscanf(str,"%d.%d.%d.%d%n",&a0,&a1,&a2,&a3,&i)!=4 || i==0) {
- printf("access_ipmask: unknown format %s\n",str);
+ printf("access_ipmask: Unknown format %s!\n",str);
return 0;
}
ip = (a3 << 24) | (a2 << 16) | (a1 << 8) | a0;
@@ -746,7 +753,8 @@ int access_ipmask(const char *str,struct _access_control* acc)
}
}
if(access_debug) {
- printf("access_ipmask: ip:%08x mask:%08x %s\n",ip,mask,str);
+ printf("access_ipmask: Loaded IP:%d.%d.%d.%d mask:%d.%d.%d.%d\n",
+ CONVIP(ip), CONVIP(mask));
}
acc->ip = ip;
acc->mask = mask;
@@ -771,11 +779,17 @@ int socket_config_read(const char *cfgName) {
continue;
if(strcmpi(w1,"stall_time")==0){
stall_time_ = atoi(w2);
+ } else if(strcmpi(w1,"enable_ip_rules")==0){
+ if(strcmpi(w2,"yes")==0)
+ ip_rules = 1;
+ else if(strcmpi(w2,"no")==0)
+ ip_rules = 0;
+ else ip_rules = atoi(w2);
} else if(strcmpi(w1,"order")==0){
access_order=atoi(w2);
if(strcmpi(w2,"deny,allow")==0) access_order=ACO_DENY_ALLOW;
if(strcmpi(w2,"allow,deny")==0) access_order=ACO_ALLOW_DENY;
- if(strcmpi(w2,"mutual-failture")==0) access_order=ACO_MUTUAL_FAILTURE;
+ if(strcmpi(w2,"mutual-failure")==0) access_order=ACO_MUTUAL_FAILTURE;
} else if(strcmpi(w1,"allow")==0){
access_allow = aRealloc(access_allow,(access_allownum+1)*sizeof(struct _access_control));
if(access_ipmask(w2,&access_allow[access_allownum])) {
@@ -793,7 +807,11 @@ int socket_config_read(const char *cfgName) {
} else if(!strcmpi(w1,"ddos_autoreset")){
ddos_autoreset = atoi(w2);
} else if(!strcmpi(w1,"debug")){
- access_debug = atoi(w2);
+ if(strcmpi(w2,"yes")==0)
+ access_debug = 1;
+ else if(strcmpi(w2,"no")==0)
+ access_debug = 0;
+ else access_debug = atoi(w2);
} else if (strcmpi(w1, "import") == 0)
socket_config_read(w2);
}
diff --git a/src/map/battle.c b/src/map/battle.c
index 483ddffb7..81b2c3189 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -1063,7 +1063,7 @@ static struct Damage battle_calc_mob_weapon_attack(
struct Damage wd;
int damage,damage2=0,type,div_,blewcount=skill_get_blewcount(skill_num,skill_lv);
int flag,skill,ac_flag = 0,dmg_lv = 0;
- int t_mode=0,t_race=0,t_size=1,s_race=0,s_ele=0,s_size=0;
+ int t_mode=0,t_race=0,t_size=1,s_race=0,s_ele=0,s_size=0,s_race2=0;
struct status_change *sc_data,*t_sc_data;
short *sc_count;
short *option, *opt1, *opt2;
@@ -1085,6 +1085,7 @@ static struct Damage battle_calc_mob_weapon_attack(
option = status_get_option(src);
opt1 = status_get_opt1(src);
opt2 = status_get_opt2(src);
+ s_race2 = status_get_race2(src);
// ターゲット
if(target->type == BL_PC)
@@ -1504,6 +1505,7 @@ static struct Damage battle_calc_mob_weapon_attack(
cardfix=cardfix*(100-tsd->subele[s_ele])/100; // 属 性によるダメージ耐性
cardfix=cardfix*(100-tsd->subrace[s_race])/100; // 種族によるダメージ耐性
cardfix=cardfix*(100-tsd->subsize[s_size])/100;
+ cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; // 種族によるダメージ耐性
if(mob_db[md->class_].mode & 0x20)
cardfix=cardfix*(100-tsd->subrace[10])/100;
else
@@ -2857,7 +2859,7 @@ struct Damage battle_calc_magic_attack(
int aflag;
int normalmagic_flag=1;
int matk_flag = 1;
- int ele=0,race=7,size=1,t_ele=0,t_race=7,t_mode = 0,cardfix,t_class,i;
+ int ele=0,race=7,size=1,race2=7,t_ele=0,t_race=7,t_mode = 0,cardfix,t_class,i;
struct map_session_data *sd=NULL,*tsd=NULL;
struct mob_data *tmd = NULL;
@@ -2879,6 +2881,7 @@ struct Damage battle_calc_magic_attack(
ele = skill_get_pl(skill_num);
race = status_get_race(bl);
size = status_get_size(bl);
+ race2 = status_get_race2(bl);
t_ele = status_get_elem_type(target);
t_race = status_get_race(target);
t_mode = status_get_mode(target);
@@ -3091,6 +3094,7 @@ struct Damage battle_calc_magic_attack(
cardfix=cardfix*(100-tsd->subrace[race])/100; // 種族によるダメージ耐性
cardfix=cardfix*(100-tsd->subsize[size])/100;
cardfix=cardfix*(100-tsd->magic_subrace[race])/100;
+ cardfix=cardfix*(100-tsd->subrace2[race2])/100; // 種族によるダメージ耐性
if(status_get_mode(bl) & 0x20)
cardfix=cardfix*(100-tsd->magic_subrace[10])/100;
else
@@ -3166,7 +3170,7 @@ struct Damage battle_calc_misc_attack(
int int_=status_get_int(bl);
// int luk=status_get_luk(bl);
int dex=status_get_dex(bl);
- int skill,ele,race,size,cardfix;
+ int skill,ele,race,size,cardfix,race2;
struct map_session_data *sd=NULL,*tsd=NULL;
int damage=0,div_=1,blewcount=skill_get_blewcount(skill_num,skill_lv);
struct Damage md;
@@ -3270,6 +3274,7 @@ struct Damage battle_calc_misc_attack(
ele = skill_get_pl(skill_num);
race = status_get_race(bl);
size = status_get_size(bl);
+ race2 = status_get_race(bl);
if(damagefix){
if(damage<1 && skill_num != NPC_DARKBREATH)
@@ -3281,6 +3286,7 @@ struct Damage battle_calc_misc_attack(
cardfix=cardfix*(100-tsd->subrace[race])/100; // 種族によるダメージ耐性
cardfix=cardfix*(100-tsd->subsize[size])/100;
cardfix=cardfix*(100-tsd->misc_def_rate)/100;
+ cardfix=cardfix*(100-tsd->subrace2[race2])/100;
damage=damage*cardfix/100;
}
if (sd && skill_num > 0 && sd->skillatk[0] == skill_num)
diff --git a/src/map/map.h b/src/map/map.h
index a83f810b9..8039615f7 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -297,9 +297,14 @@ struct map_session_data {
short hp_loss_value, hp_loss_type;
int addrace2[6],addrace2_[6];
int subsize[3];
- short unequip_damage[11];
+ short unequip_losehp[11];
+ short unequip_losesp[11];
int itemid;
int itemhealrate[6];
+ //--- 03/15's new card effects
+ int expaddrace[6];
+ int subrace2[6];
+ short sp_gain_race[6];
short spiritball, spiritball_old;
int spirit_timer[MAX_SKILL_LEVEL];
@@ -647,7 +652,8 @@ enum {
SP_CRIT_ATK_RATE, SP_CRITICAL_ADDRACE, SP_NO_REGEN, SP_ADDEFF_WHENHIT, SP_AUTOSPELL_WHENHIT, // 2013-2017
SP_SKILL_ATK, SP_UNSTRIPABLE, SP_ADD_DAMAGE_BY_CLASS, // 2018-2020
SP_SP_GAIN_VALUE, SP_IGNORE_DEF_MOB, SP_HP_LOSS_RATE, SP_ADDRACE2, SP_HP_GAIN_VALUE, // 2021-2025
- SP_SUBSIZE, SP_DAMAGE_WHEN_UNEQUIP, SP_ADD_ITEM_HEAL_RATE // 2026-2028
+ SP_SUBSIZE, SP_DAMAGE_WHEN_UNEQUIP, SP_ADD_ITEM_HEAL_RATE, SP_LOSESP_WHEN_UNEQUIP, SP_EXP_ADDRACE, // 2026-2030
+ SP_SP_GAIN_RACE, SP_SUBRACE2,
};
enum {
diff --git a/src/map/mob.c b/src/map/mob.c
index 584d9de2e..3cfb4e6d5 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -2198,10 +2198,12 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
struct item item;
int ret;
int drop_rate;
+ int race;
nullpo_retr(0, md); //srcはNULLで呼ばれる場合もあるので、他でチェック
max_hp = status_get_max_hp(&md->bl);
+ race = status_get_race(&md->bl);
if(src && src->type == BL_PC) {
sd = (struct map_session_data *)src;
@@ -2425,6 +2427,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
sp += (status_get_lv(&md->bl))*(65+15*i)/100;
}
sp += sd->sp_gain_value;
+ sp += sd->sp_gain_race[race];
hp += sd->hp_gain_value;
if (sp > 0) {
if(sd->status.sp + sp > sd->status.max_sp)
@@ -2512,21 +2515,24 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(job_exp < 1) job_exp = 1;
}
- if(sd && battle_config.pk_mode && (mob_db[md->class_].lv - sd->status.base_level >= 20)) {
- base_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris]
- }
- if(sd && battle_config.pk_mode && (mob_db[md->class_].lv - sd->status.base_level >= 20)) {
- job_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris]
+ if(sd) {
+ int rate;
+ if ((rate = sd->expaddrace[race]) > 0) {
+ base_exp = (100+rate)*base_exp/100;
+ job_exp = (100+rate)*job_exp/100;
+ }
+ if (battle_config.pk_mode && (mob_db[md->class_].lv - sd->status.base_level >= 20)) {
+ base_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris]
+ job_exp*=1.15;
+ }
}
if(md->master_id) {
- master = map_id2bl(md->master_id);
- }
- if((master && status_get_mode(master)&0x20) || // check if its master is a boss (MVP's and minibosses)
- (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)) { // for summoned creatures [Valaris]
- base_exp = 0;
- job_exp = 0;
- }
- else {
+ if(((master = map_id2bl(md->master_id)) && status_get_mode(master)&0x20) || // check if its master is a boss (MVP's and minibosses)
+ (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)) { // for summoned creatures [Valaris]
+ base_exp = 0;
+ job_exp = 0;
+ }
+ } else {
if(battle_config.zeny_from_mobs) {
if(md->level > 0) zeny=(md->level+rand()%md->level)*per/256; // zeny calculation moblv + random moblv [Valaris]
if(mob_db[md->class_].mexp > 0)
@@ -2639,7 +2645,6 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(sd && sd->state.attack_type == BF_WEAPON) {
for(i=0;i<sd->monster_drop_item_count;i++) {
struct delay_item_drop *ditem;
- int race = status_get_race(&md->bl);
if(sd->monster_drop_itemid[i] <= 0)
continue;
if(sd->monster_drop_race[i] & (1<<race) ||
diff --git a/src/map/pc.c b/src/map/pc.c
index 920784da3..c681f8ec5 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1588,7 +1588,18 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
int i;
for (i=0; i<11; i++) {
if (sd->inventory_data[current_equip_item_index]->equip & equip_pos[i]) {
- sd->unequip_damage[i] += val;
+ sd->unequip_losehp[i] += val;
+ break;
+ }
+ }
+ }
+ break;
+ case SP_LOSESP_WHEN_UNEQUIP:
+ if(!sd->state.lr_flag) {
+ int i;
+ for (i=0; i<11; i++) {
+ if (sd->inventory_data[current_equip_item_index]->equip & equip_pos[i]) {
+ sd->unequip_losesp[i] += val;
break;
}
}
@@ -1861,10 +1872,22 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
if(sd->state.lr_flag != 2)
sd->subsize[type2]+=val;
break;
+ case SP_SUBRACE2:
+ if(sd->state.lr_flag != 2)
+ sd->subrace2[type2]+=val;
+ break;
case SP_ADD_ITEM_HEAL_RATE:
if(sd->state.lr_flag != 2)
sd->itemhealrate[type2 - 1] += val;
break;
+ case SP_EXP_ADDRACE:
+ if(sd->state.lr_flag != 2)
+ sd->expaddrace[type2]+=val;
+ break;
+ case SP_SP_GAIN_RACE:
+ if(sd->state.lr_flag != 2)
+ sd->sp_gain_race[type2]+=val;
+ break;
default:
if(battle_config.error_log)
@@ -6076,7 +6099,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos)
*/
int pc_unequipitem(struct map_session_data *sd,int n,int flag)
{
- short dmg = 0;
+ short hp = 0, sp = 0;
nullpo_retr(0, sd);
// -- moonsoul (if player is berserk then cannot unequip)
@@ -6093,9 +6116,13 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
for(i=0;i<11;i++) {
if(sd->status.inventory[n].equip & equip_pos[i]) {
sd->equip_index[i] = -1;
- if(sd->unequip_damage[i] > 0) {
- dmg += sd->unequip_damage[i];
- sd->unequip_damage[i] = 0;
+ if(sd->unequip_losehp[i] > 0) {
+ hp += sd->unequip_losehp[i];
+ sd->unequip_losehp[i] = 0;
+ }
+ if(sd->unequip_losesp[i] > 0) {
+ sp += sd->unequip_losesp[i];
+ sd->unequip_losesp[i] = 0;
}
}
}
@@ -6150,10 +6177,12 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
}
- if (dmg > 0) {
- if (dmg > sd->status.hp)
- dmg = sd->status.hp;
- pc_heal(sd,-dmg,0);
+ if (hp > 0 || sp > 0) {
+ if (hp > sd->status.hp)
+ hp = sd->status.hp;
+ if (sp > sd->status.sp)
+ sp = sd->status.sp;
+ pc_heal(sd,-hp,-sp);
}
return 0;
diff --git a/src/map/status.c b/src/map/status.c
index b0c90d520..e05d33909 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -521,7 +521,11 @@ int status_calc_pc(struct map_session_data* sd,int first)
memset(sd->addrace2_,0,sizeof(sd->addrace2_));
sd->hp_gain_value = sd->sp_drain_type = 0;
memset(sd->subsize,0,sizeof(sd->subsize));
- memset(sd->unequip_damage,0,sizeof(sd->unequip_damage));
+ memset(sd->unequip_losehp,0,sizeof(sd->unequip_losehp));
+ memset(sd->unequip_losesp,0,sizeof(sd->unequip_losesp));
+ memset(sd->subrace2,0,sizeof(sd->subrace2));
+ memset(sd->expaddrace,0,sizeof(sd->expaddrace));
+ memset(sd->sp_gain_race,0,sizeof(sd->sp_gain_race));
if(!sd->disguiseflag && sd->disguise) {
sd->disguise=0;