- Added status_calc_life to properly calculate hp/max_hp as a ratio taking into accounts overflows (and for now also avoids divisions by 0). Applied this function around clif.c, mob.c and pet.c
- Implemented the correct walk-speed bonus from the Bard/Dancer spirit. - Added a few error messages in case something goes wrong in the new auth db system. - Fixed logarithmic drops turning 0% drop rates into 100%. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12225 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
6da0007d11
commit
9c638fa6b2
@ -4,6 +4,11 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
|
||||
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
|
||||
|
||||
2007/02/21
|
||||
* Added status_calc_life to properly calculate hp/max_hp as a ratio taking
|
||||
into accounts overflows (and for now also avoids divisions by 0). Applied
|
||||
this function around clif.c, mob.c and pet.c
|
||||
* Implemented the correct walk-speed bonus from the Bard/Dancer spirit.
|
||||
* Fixed logarithmic drops turning 0% drop rates into 100%.
|
||||
* Restructured the login mechanism of the map-server. The goal was to make
|
||||
sure players are not found in the different dbs of the map while the
|
||||
player has not yet been fully authed or while it is quitting, to avoid the
|
||||
|
@ -169,8 +169,7 @@ bool chrif_auth_finished(TBL_PC* sd)
|
||||
struct auth_node *node= chrif_search(sd->status.account_id);
|
||||
if (node && node->sd == sd && node->state == ST_LOGIN) {
|
||||
node->sd = NULL;
|
||||
chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN);
|
||||
return true;
|
||||
return chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -242,7 +241,8 @@ int chrif_save(struct map_session_data *sd, int flag)
|
||||
{
|
||||
//FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex]
|
||||
if (chrif_isconnected()) chrif_save_scdata(sd);
|
||||
chrif_auth_logout(sd, flag==1?ST_LOGOUT:ST_MAPCHANGE);
|
||||
if (!chrif_auth_logout(sd, flag==1?ST_LOGOUT:ST_MAPCHANGE))
|
||||
ShowError("chrif_save: Failed to set up player %d:%d for proper quitting!\n", sd->status.account_id, sd->status.char_id);
|
||||
}
|
||||
|
||||
if(!chrif_isconnected())
|
||||
@ -515,11 +515,12 @@ void chrif_authreq(struct map_session_data *sd)
|
||||
|
||||
if(node->state == ST_LOGIN &&
|
||||
node->char_dat &&
|
||||
node->account_id== sd->status.account_id &&
|
||||
node->account_id == sd->status.account_id &&
|
||||
node->char_id == sd->status.char_id &&
|
||||
node->login_id1 == sd->login_id1)
|
||||
{ //auth ok
|
||||
if (!pc_authok(sd, node->login_id2, node->connect_until_time, node->char_dat))
|
||||
chrif_auth_delete(sd->status.account_id, sd->status.char_id, ST_LOGIN);
|
||||
chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN);
|
||||
else {
|
||||
//char_dat no longer needed, but player auth is not completed yet.
|
||||
aFree(node->char_dat);
|
||||
@ -587,16 +588,18 @@ void chrif_authok(int fd)
|
||||
int auth_db_cleanup_sub(DBKey key,void *data,va_list ap)
|
||||
{
|
||||
struct auth_node *node=(struct auth_node*)data;
|
||||
|
||||
const char* states[] = { "Login", "Logout", "Map change" };
|
||||
if(DIFF_TICK(gettick(),node->node_created)>60000) {
|
||||
switch (node->state)
|
||||
{
|
||||
case ST_LOGOUT:
|
||||
//Re-save attempt (->sd should never be null here).
|
||||
node->node_created = gettick(); //Refresh tick (avoid char-server load if connection is really bad)
|
||||
chrif_save(node->sd, 1);
|
||||
break;
|
||||
default:
|
||||
//Clear data. any connected players should have timed out by now.
|
||||
ShowInfo("auth_db: Node (state %s) timed out for %d:%d\n", states[node->state], node->account_id, node->char_id);
|
||||
chrif_auth_delete(node->account_id, node->char_id, node->state);
|
||||
break;
|
||||
}
|
||||
|
@ -7188,9 +7188,7 @@ int clif_charnameack (int fd, struct block_list *bl)
|
||||
str_p += sprintf(str_p, "HP: %u/%u | ", md->status.hp, md->status.max_hp);
|
||||
if (battle_config.show_mob_info&2)
|
||||
str_p += sprintf(str_p, "HP: %d%% | ",
|
||||
md->status.max_hp > 10000?
|
||||
md->status.hp/(md->status.max_hp/100):
|
||||
100*md->status.hp/md->status.max_hp);
|
||||
status_calc_life(md->status.hp, md->status.max_hp));
|
||||
//Even thought mobhp ain't a name, we send it as one so the client
|
||||
//can parse it. [Skotlex]
|
||||
if (str_p != mobhp) {
|
||||
|
@ -300,6 +300,7 @@ int clif_guild_allianceinfo(struct map_session_data *sd);
|
||||
int clif_guild_memberlist(struct map_session_data *sd);
|
||||
int clif_guild_skillinfo(struct map_session_data *sd);
|
||||
int clif_guild_send_onlineinfo(struct map_session_data *sd); //[LuzZza]
|
||||
int clif_guild_masterormember(struct map_session_data *sd);
|
||||
int clif_guild_memberlogin_notice(struct guild *g,int idx,int flag);
|
||||
int clif_guild_invite(struct map_session_data *sd,struct guild *g);
|
||||
int clif_guild_inviteack(struct map_session_data *sd,int flag);
|
||||
|
@ -95,7 +95,7 @@ int merc_hom_vaporize(struct map_session_data *sd, int flag)
|
||||
if (status_isdead(&hd->bl))
|
||||
return 0; //Can't vaporize a dead homun.
|
||||
|
||||
if (flag && hd->battle_status.hp < (hd->battle_status.max_hp*80/100))
|
||||
if (flag && status_calc_life(hd->battle_status.hp, hd->battle_status.max_hp)< 80)
|
||||
return 0;
|
||||
|
||||
hd->regen.state.block = 3; //Block regen while vaporized.
|
||||
|
@ -2451,7 +2451,7 @@ int mob_class_change (struct mob_data *md, int class_)
|
||||
if (md->class_ == class_)
|
||||
return 0; //Nothing to change.
|
||||
|
||||
hp_rate = md->status.hp*100/md->status.max_hp;
|
||||
hp_rate = status_calc_life(md->status.hp, md->status.max_hp);
|
||||
md->class_ = class_;
|
||||
md->db = mob_db(class_);
|
||||
if (battle_config.override_mob_names==1)
|
||||
@ -2586,7 +2586,7 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int skill_id)
|
||||
|
||||
if (!battle_config.monster_class_change_recover &&
|
||||
(skill_id == NPC_TRANSFORMATION || skill_id == NPC_METAMORPHOSIS))
|
||||
hp_rate = 100*md2->status.hp/md2->status.max_hp;
|
||||
hp_rate = status_calc_life(md2->status.hp, md2->status.max_hp);
|
||||
|
||||
for(;k<amount;k++) {
|
||||
short x,y;
|
||||
@ -2691,7 +2691,7 @@ int mob_getfriendhprate_sub(struct block_list *bl,va_list ap)
|
||||
if (battle_check_target(&md->bl,bl,BCT_ENEMY)>0)
|
||||
return 0;
|
||||
|
||||
rate = 100*status_get_hp(bl)/status_get_max_hp(bl);
|
||||
rate = status_calc_life(status_get_hp(bl), status_get_max_hp(bl));
|
||||
|
||||
if (rate >= min_rate && rate <= max_rate)
|
||||
(*fr) = bl;
|
||||
@ -2717,7 +2717,7 @@ struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md,int rate)
|
||||
{
|
||||
if (md && md->master_id > 0) {
|
||||
struct block_list *bl = map_id2bl(md->master_id);
|
||||
if (status_get_hp(bl) < status_get_max_hp(bl) * rate / 100)
|
||||
if (bl && status_calc_life(status_get_hp(bl), status_get_max_hp(bl)) < rate);
|
||||
return bl;
|
||||
}
|
||||
|
||||
@ -2823,11 +2823,11 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
|
||||
case MSC_ALWAYS:
|
||||
flag = 1; break;
|
||||
case MSC_MYHPLTMAXRATE: // HP< maxhp%
|
||||
flag = 100*md->status.hp/md->status.max_hp;
|
||||
flag = status_calc_life(md->status.hp, md->status.max_hp);
|
||||
flag = (flag <= c2);
|
||||
break;
|
||||
case MSC_MYHPINRATE:
|
||||
flag = 100*md->status.hp/md->status.max_hp;
|
||||
flag = status_calc_life(md->status.hp, md->status.max_hp);
|
||||
flag = (flag >= c2 && flag <= ms[i].val[0]);
|
||||
break;
|
||||
case MSC_MYSTATUSON: // status[num] on
|
||||
@ -3282,7 +3282,7 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor
|
||||
{
|
||||
double rate = baserate;
|
||||
|
||||
if (battle_config.logarithmic_drops && rate_adjust > 0) //Logarithmic drops equation by Ishizu-Chan
|
||||
if (battle_config.logarithmic_drops && rate_adjust > 0 && baserate > 0) //Logarithmic drops equation by Ishizu-Chan
|
||||
//Equation: Droprate(x,y) = x * (5 - log(x)) ^ (ln(y) / ln(5))
|
||||
//x is the normal Droprate, y is the Modificator.
|
||||
rate = rate * pow((5.0 - log10(rate)), (log(rate_adjust/100.) / log(5.0))) + 0.5;
|
||||
|
@ -842,7 +842,8 @@ int pc_reg_received(struct map_session_data *sd)
|
||||
|
||||
map_addiddb(&sd->bl);
|
||||
map_delnickdb(sd->status.char_id, sd->status.name);
|
||||
chrif_auth_finished(sd);
|
||||
if (!chrif_auth_finished(sd))
|
||||
ShowError("pc_reg_received: Failed to properly remove player %d:%d from logging db!\n", sd->status.account_id, sd->status.char_id);
|
||||
|
||||
status_calc_pc(sd,1);
|
||||
chrif_scdata_request(sd->status.account_id, sd->status.char_id);
|
||||
|
@ -554,7 +554,8 @@ int pet_catch_process2(struct map_session_data* sd, int target_id)
|
||||
return 1;
|
||||
}
|
||||
|
||||
pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - md->level)*30 + sd->battle_status.luk*20)*(200 - md->status.hp*100/md->status.max_hp)/100;
|
||||
pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - md->level)*30 + sd->battle_status.luk*20)*(200 - status_calc_life(md->status.hp, md->status.max_hp))/100;
|
||||
|
||||
if(pet_catch_rate < 1) pet_catch_rate = 1;
|
||||
if(battle_config.pet_catch_rate != 100)
|
||||
pet_catch_rate = (pet_catch_rate*battle_config.pet_catch_rate)/100;
|
||||
@ -1161,8 +1162,8 @@ int pet_heal_timer(int tid,unsigned int tick,int id,int data)
|
||||
status = status_get_status_data(&sd->bl);
|
||||
|
||||
if(pc_isdead(sd) ||
|
||||
(rate = status->sp*100/status->max_sp) > pd->s_skill->sp ||
|
||||
(rate = status->hp*100/status->max_hp) > pd->s_skill->hp ||
|
||||
(rate = status_calc_life(status->sp, status->max_sp)) > pd->s_skill->sp ||
|
||||
(rate = status_calc_life(status->hp, status->max_hp)) > pd->s_skill->hp ||
|
||||
(rate = (pd->ud.skilltimer != -1)) //Another skill is in effect
|
||||
) { //Wait (how long? 1 sec for every 10% of remaining)
|
||||
pd->s_skill->timer=add_timer(gettick()+(rate>10?rate:10)*100,pet_heal_timer,sd->bl.id,0);
|
||||
@ -1204,8 +1205,8 @@ int pet_skill_support_timer(int tid,unsigned int tick,int id,int data)
|
||||
}
|
||||
|
||||
if(pc_isdead(sd) ||
|
||||
(rate = status->sp*100/status->max_sp) > pd->s_skill->sp ||
|
||||
(rate = status->hp*100/status->max_hp) > pd->s_skill->hp ||
|
||||
(rate = status_calc_life(status->sp, status->max_sp)) > pd->s_skill->sp ||
|
||||
(rate = status_calc_life(status->hp, status->max_hp)) > pd->s_skill->hp ||
|
||||
(rate = (pd->ud.skilltimer != -1)) //Another skill is in effect
|
||||
) { //Wait (how long? 1 sec for every 10% of remaining)
|
||||
pd->s_skill->timer=add_timer(tick+(rate>10?rate:10)*100,pet_skill_support_timer,sd->bl.id,0);
|
||||
|
@ -951,6 +951,17 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//calculates the base/max ratio as a value between 0->100 (percent), using
|
||||
//different approaches to avoid overflows.
|
||||
//NOTE: The -1 case (0 max hp) should never trigger!
|
||||
char status_calc_life(unsigned int base, unsigned int max)
|
||||
{
|
||||
if (!max) return -1;
|
||||
if (max < 10000) return 100*base/max;
|
||||
return base/(max/100);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Checks whether the src can use the skill on the target,
|
||||
* taking into account status/option of both source/target. [Skotlex]
|
||||
@ -5173,11 +5184,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
clif_status_change(bl,SI_MOONLIT,1);
|
||||
val1|= (val3<<16);
|
||||
val3 = 0; //Tick duration/Speed penalty.
|
||||
if (sd) { //Store walk speed change in lower part of val3
|
||||
//Store walk speed change in lower part of val3
|
||||
if (sd && !(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER))
|
||||
val3 = 500-40*pc_checkskill(sd,(sd->status.sex?BA_MUSICALLESSON:DC_DANCINGLESSON));
|
||||
if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)
|
||||
val3 -= 40; //TODO: Figure out real bonus rate.
|
||||
}
|
||||
val3|= ((tick/1000)<<16)&0xFFFF0000; //Store tick in upper part of val3
|
||||
tick = 1000;
|
||||
break;
|
||||
|
@ -599,6 +599,8 @@ int status_set_sp(struct block_list *bl, unsigned int sp, int flag);
|
||||
int status_heal(struct block_list *bl,int hp,int sp, int flag);
|
||||
int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp);
|
||||
|
||||
char status_calc_life(unsigned int base, unsigned int max);
|
||||
|
||||
//Define for copying a status_data structure from b to a, without overwriting current Hp and Sp
|
||||
#define status_cpy(a, b) \
|
||||
memcpy(&((a)->max_hp), &((b)->max_hp), sizeof(struct status_data)-(sizeof((a)->hp)+sizeof((a)->sp)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user