aozhiwei 0a039944b2 1
2024-08-28 19:29:12 +08:00

1392 lines
42 KiB
C++

#include "precompile.h"
#include <math.h>
#include "netdata.h"
#include "human.h"
#include "creature.h"
#include "types.h"
#include "bullet.h"
#include "app.h"
#include "room.h"
#include "explosion.h"
#include "roommgr.h"
#include "ability.h"
#include "stats.h"
#include "android.h"
#include "skill.h"
#include "trigger.h"
#include "buff/distance_dmg_addition.h"
#include "mt/Param.h"
#include "mt/Item.h"
#include "mt/Hero.h"
#include "mt/HeroQuality.h"
#include "mt/GunQuality.h"
#include "mt/NpcStandard.h"
#include "mt/PveGemini.h"
#include "mt/PveGeminiContent.h"
#include "mt/Equip.h"
#include "mt/Skill.h"
#include "mt/SkillNumber.h"
#include "mt/FormulaPvp.h"
#include "mt/Robot.h"
#include "mt/BattleBasicAttribute.h"
#include "attrhelper.h"
struct CalcDmgContext
{
int is_crit = 0;
int is_block = 0;
float crit_dmg = 0.0f;
int dmg_bp = 0;
};
static CalcDmgContext g_calc_dmg_context = {0};
class HeroAbility
{
public:
long long hero_uniid_ = 0;
const mt::Hero* hero_meta = nullptr;
std::shared_ptr<a8::XObject> hero_dto;
int spec_skill_id = 0;
int main_skill_id = 0;
const mt::NpcStandard* standard_meta = nullptr;
void Init(CreatureWeakPtr owner)
{
owner_ = owner;
}
float GetHP()
{
return hp_;
}
float GetAtk()
{
return atk_;
}
float GetDef()
{
return def_;
}
float GetCrit()
{
return crit_;
}
float GetBlock()
{
return block_;
}
float GetBrainLifePct()
{
return brain_life_pct_;
}
float GetSkillCdPct()
{
return skill_cd_pct_;
}
float GetRescueTimePct()
{
return rescue_time_pct_;
}
float GetDrugTimePct()
{
return durg_time_pct_;
}
float GetDrugEfficacyPct()
{
return durg_eff_pct_;
}
float GetTenacityPct()
{
return tenacity_pct_;
}
float GetRecoverHpAdd()
{
return recover_hp_add_pct_;
}
void Init(Creature* c)
{
DefaultInit(c);
if (hero_dto) {
DtoInit(c);
}
}
void RecalcHp()
{
auto ability = owner_.Get()->GetAbility();
float pHealRateAm = 0.0f; //加基础点数属性绝对值
float pHealthAm_Add = ability->GetAttr(kHAT_pHealthAm); //buff或者养成的属性
pHealRateAm += pHealthAm_Add;
float pHealthRateSe = 0.0f;
float pHealthRateSe_Add = ability->GetAttr(kHAT_pHealthRateSe); //buff或者养成的属性
pHealthRateSe += pHealthRateSe_Add;
float pHealthRateIn = 0.0f;
float pHealthRateIn_Add = ability->GetAttr(kHAT_pHealthRateIn); //buff或者养成的属性
pHealthRateIn = (1 + pHealthRateIn) * (1 + pHealthRateIn_Add) - 1;
float pHealth = (hero_meta->GetBasicMeta()->pOrigHealth() + pHealRateAm) * (1 + pHealthRateSe) * (1 + pHealthRateIn);
float vHealthAm = 0.0f;
float vHealthAm_Add = ability->GetAttr(kHAT_vHealthAm); //buff或者养成的属性
vHealthAm += vHealthAm_Add;
float vHealthRateSe = 0.0f;
float vHealthRateSe_Add = ability->GetAttr(kHAT_vHealthRateSe); //buff或者养成的属性
vHealthRateSe += vHealthRateSe_Add;
float vHealthRateIn = 0.0f;
float vHealthRateIn_Add = ability->GetAttr(kHAT_vHealthRateIn); //buff或者养成的属性
vHealthRateIn = (1 + vHealthRateIn) * (1 + vHealthRateIn_Add) - 1;
hp_ = (hero_meta->GetBasicMeta()->vOrigHealth() * (1 + pHealth / hero_meta->GetBasicMeta()->pBaseHealth()) + vHealthAm) *
(1 + vHealthRateSe) * (1 + vHealthRateIn);
}
void RecalcAttack()
{
auto ability = owner_.Get()->GetAbility();
float pAttackAm = 0.0f;
float pAttackAm_Add = ability->GetAttr(kHAT_pAttackAm);
pAttackAm += pAttackAm_Add;
float pAttackRateSe = 0.0f;
float pAttackRateSe_Add = ability->GetAttr(kHAT_pAttackRateSe);
pAttackRateSe += pAttackRateSe_Add;
float pAttackRateIn = 0.0f;
float pAttackRateIn_Add = ability->GetAttr(kHAT_pAttackRateIn);
pAttackRateIn = (1 + pAttackRateIn) * ( 1 + pAttackRateIn_Add) - 1;
float vAttackAm = 0.0f;
float vAttackAm_Add = ability->GetAttr(kHAT_vAttackAm);
vAttackAm += vAttackAm_Add;
float vAttackRateSe = 0.0f;
float vAttackRateSe_Add = ability->GetAttr(kHAT_vAttackRateSe);
vAttackRateSe += vAttackRateSe_Add;
float vAttackRateIn = 0.0f;
float vAttackRateIn_Add = ability->GetAttr(kHAT_vAttackRateIn);
vAttackRateIn = (1 + vAttackRateIn) * (1 + vAttackRateIn_Add) - 1;
float pAttack = 0.0f;
pAttack = (hero_meta->GetBasicMeta()->pOrigAttack() + pAttackAm) * (1 + pAttackRateSe) * (1 + pAttackRateIn);
atk_ = (hero_meta->GetBasicMeta()->vOrigAttack() * (1 + pAttack / hero_meta->GetBasicMeta()->pBaseAttack()) + vAttackAm) *
(1 + vAttackRateSe) * (1 + vAttackRateIn);
if (owner_.Get()->IsPlayer()) {
int i = 0;
}
}
void RecalcDef()
{
auto ability = owner_.Get()->GetAbility();
float pDefendAm = 0.0f;
float pDefendAm_Add = ability->GetAttr(kHAT_pDefendAm);
pDefendAm += pDefendAm_Add;
float pDefendRateSe = 0.0f;
float pDefendRateSe_Add = ability->GetAttr(kHAT_pDefendRateSe);
pDefendRateSe += pDefendRateSe_Add;
float pDefendRateIn = 0.0f;
float pDefendRateIn_Add = ability->GetAttr(kHAT_pDefendRateIn);
pDefendRateIn = (1 + pDefendRateIn) * (1 + pDefendRateIn_Add) - 1;
float pDefend = (hero_meta->GetBasicMeta()->pOrigDefend() + pDefendAm) *
(1 + pDefendRateSe) * (1 + pDefendRateIn);
def_ = 1 - (1 - hero_meta->GetBasicMeta()->vOrigDefend()) / (1 + pDefend / hero_meta->GetBasicMeta()->pBaseDefend());
}
void RecalcBlock()
{
auto ability = owner_.Get()->GetAbility();
float pBlockAm = 0.0f;
float pBlockAm_Add = ability->GetAttr(kHAT_pBlockAm);
pBlockAm += pBlockAm_Add;
float pBlockRateSe = 0.0f;
float pBlockRateSe_Add = ability->GetAttr(kHAT_pBlockRateSe);
pBlockRateSe += pBlockRateSe_Add;
float pBlockRateIn = 0.0f;
float pBlockRateIn_Add = ability->GetAttr(kHAT_pBlockRateIn);
pBlockRateIn = (1 + pBlockRateIn) * (1 + pBlockRateIn_Add) - 1;
float pBlock = (hero_meta->GetBasicMeta()->pOrigBlock() + pBlockAm) * (1 + pBlockRateSe) * (1 + pBlockRateIn);
float vBlock = 1 - (1 - hero_meta->GetBasicMeta()->vOrigBlock()) / (1 + pBlock / hero_meta->GetBasicMeta()->pBaseBlock());
block_ = vBlock;
}
void RecalcCrit()
{
auto ability = owner_.Get()->GetAbility();
float pCritAm = 0.0f;
float pCritAm_Add = ability->GetAttr(kHAT_pCritAm);
pCritAm += pCritAm_Add;
float pCritRateSe = 0.0f;
float pCritRateSe_Add = ability->GetAttr(kHAT_pCritRateSe);
pCritRateSe += pCritRateSe_Add;
float pCritRateIn = 0.0f;
float pCritRateIn_Add = ability->GetAttr(kHAT_pCritRateIn);
pCritRateIn = (1 + pCritRateIn) * (1 + pCritRateIn_Add) - 1;
float pCrit = 0.0f;
pCrit = (hero_meta->GetBasicMeta()->pOrigCrit() + pCritAm) * (1 + pCritRateSe) * (1 + pCritRateIn);
float vCrit = 0.0f;
vCrit = (1 + hero_meta->GetBasicMeta()->vOrigCrit()) * (1 + pCrit / hero_meta->GetBasicMeta()->pBaseCrit()) - 1;
crit_ = vCrit;
}
private:
void DefaultInit(Creature* c)
{
RecalcHp();
RecalcAttack();
RecalcDef();
RecalcBlock();
RecalcCrit();
}
void DtoInit(Creature* c)
{
{
auto rand_attr = hero_dto->At("rand_attr");
if (rand_attr && rand_attr->IsArray()) {
for (int i = 0; i < rand_attr->Size(); ++i) {
auto attr = rand_attr->At(i);
if (attr && attr->IsObject()) {
int attr_id = a8::XValue(attr->Get("attr_id", "0"));
float val = a8::XValue(attr->Get("val", "0")).GetDouble();
if (IsValidHumanAttr(attr_id)) {
auto attr_handle = owner_.Get()->GetAbility()->AddAttr(attr_id, val);
if (!attr_handle.expired()) {
#ifdef MYDEBUG
std::string source_name = a8::Format
("<-hero_rand_attr",
{
});
auto cb = std::make_shared<std::function<std::string()>>
(
[source_name] () -> std::string
{
return source_name;
});
owner_.Get()->GetAbility()->SetSource(attr_handle, cb);
#endif
}
}
}
}
}
}
{
auto chip_page = hero_dto->At("chip_page");
if (chip_page && chip_page->IsObject()) {
std::vector<std::string> keys;
chip_page->GetKeys(keys);
for (auto& key : keys) {
auto attr = chip_page->At(key);
if (attr && attr->IsObject()) {
int attr_id = a8::XValue(attr->Get("attr_id", "0"));
float val = a8::XValue(attr->Get("val", "0")).GetDouble();
if (IsValidHumanAttr(attr_id)) {
auto attr_handle = owner_.Get()->GetAbility()->AddAttr(attr_id, val);
if (!attr_handle.expired()) {
#ifdef MYDEBUG
std::string source_name = a8::Format
("<-chip_page",
{
});
auto cb = std::make_shared<std::function<std::string()>>
(
[source_name] () -> std::string
{
return source_name;
});
owner_.Get()->GetAbility()->SetSource(attr_handle, cb);
#endif
}
}
}
}
}
}
}
private:
CreatureWeakPtr owner_;
float hp_ = 0.0f;
float atk_ = 0.0f;
float def_ = 0.0f;
float brain_life_pct_ = 0.0f;
float skill_cd_pct_ = 0.0f;
float rescue_time_pct_ = 0.0f;
float durg_time_pct_ = 0.0f;
float durg_eff_pct_ = 0.0f;
float tenacity_pct_ = 0.0f;
float recover_hp_add_pct_ = 0.0f;
float crit_ = 0.0f;
float block_ = 0.0f;
};
class WeaponAbility
{
public:
long long weapon_uniid = 0;
int weapon_lv = 1;
int quality = 1;
const mt::Equip* weapon_meta = nullptr;
std::shared_ptr<a8::XObject> weapon_dto;
float GetAtk()
{
return atk_;
}
float GetCritAtk()
{
return crit_atk_;
}
float GetCritAtkRatio()
{
return crit_atk_ratio_;
}
int GetClipVolume()
{
return clip_volume_;
}
int GetFireRate()
{
return fire_rate_;
}
int GetReloadTime()
{
return reload_time_;
}
void Init(Creature* c)
{
#ifdef NEW_NUM
DefaultInit(c);
#else
if (weapon_dto) {
DtoInit(c);
} else {
DefaultInit(c);
}
#endif
}
private:
void DefaultInit(Creature* c)
{
atk_ = weapon_meta->_atk;
crit_atk_ = weapon_meta->critical();
crit_atk_ratio_ = weapon_meta->cri_damage();
clip_volume_ = weapon_meta->clip_volume();
fire_rate_ = weapon_meta->fire_rate();
reload_time_ = weapon_meta->reload_time();
}
void DtoInit(Creature* c)
{
std::array<float, kHAT_End> base_attr_abs = {0};
std::array<float, kHAT_End> base_attr_rate = {0};
std::array<float, kHAT_End> pro_attr_abs = {0};
std::array<float, kHAT_End> pro_attr_rate = {0};
std::array<float, kHAT_End> chip_attr_abs = {0};
std::array<float, kHAT_End> chip_attr_rate = {0};
std::array<float, kHAT_End> core_attr_abs = {0};
std::array<float, kHAT_End> core_attr_rate = {0};
{
std::shared_ptr<a8::XObject> attr_base_xobj = weapon_dto->At("attr_base");
if (attr_base_xobj && attr_base_xobj->IsArray()) {
AttrHelper::ParseAttr(attr_base_xobj, base_attr_abs, base_attr_rate);
}
}
{
std::shared_ptr<a8::XObject> attr_base_xobj = weapon_dto->At("rand_attr");
if (attr_base_xobj && attr_base_xobj->IsArray()) {
AttrHelper::ParseAttr(attr_base_xobj, base_attr_abs, base_attr_rate);
}
}
{
std::shared_ptr<a8::XObject> attr_pro_xobj = weapon_dto->At("attr_pro");
if (attr_pro_xobj && attr_pro_xobj->IsArray()) {
AttrHelper::ParseAttr(attr_pro_xobj, pro_attr_abs, pro_attr_rate);
}
}
{
std::shared_ptr<a8::XObject> attr_chip_xobj = weapon_dto->At("attr_chip");
if (attr_chip_xobj && attr_chip_xobj->IsArray()) {
AttrHelper::ParseAttr(attr_chip_xobj, chip_attr_abs, chip_attr_rate);
}
}
{
std::shared_ptr<a8::XObject> attr_core_xobj = weapon_dto->At("attr_core");
if (attr_core_xobj && attr_core_xobj->IsArray()) {
AttrHelper::ParseAttr(attr_core_xobj, core_attr_abs, core_attr_rate);
}
}
std::array<float, kHAT_End> finaly_attr_abs = base_attr_abs;
std::array<float, kHAT_End> finaly_attr_rate = base_attr_rate;
for (int i = 0; i < kHAT_End; ++i) {
if (pro_attr_abs[i] > 0.000f) {
finaly_attr_abs[i] = pro_attr_abs[i];
}
if (pro_attr_rate[i] > 0.000f) {
finaly_attr_rate[i] = pro_attr_rate[i];
}
finaly_attr_abs[i] += chip_attr_abs[i];
finaly_attr_rate[i] += chip_attr_rate[i];
finaly_attr_abs[i] += core_attr_abs[i];
finaly_attr_rate[i] += core_attr_rate[i];
}
}
private:
float atk_ = 0.0f;
float crit_atk_ = 0.0f;
float crit_atk_ratio_ = 0.0f;
int clip_volume_ = 0;
int fire_rate_ = 0;
int reload_time_ = 0;
};
BattleDataContext::BattleDataContext()
{
hero_ability_ = std::make_shared<HeroAbility>();
hero_ability_->hero_meta = mt::Param::s().human_meta;
}
void BattleDataContext::Clear()
{
}
void BattleDataContext::ParseResult(a8::XObject& obj)
{
is_valid_battle = obj.Get("is_valid_battle");
payload = obj.Get("payload").GetString();
errcode = obj.Get("errcode");
errmsg = obj.Get("errmsg").GetString();
if (errcode == 0) {
revive_coin_ = obj.Get("revive_coin");
match_mode_ = obj.Get("match_mode");
rank_ = obj.Get("rank");
elo_ = obj.Get("elo");
battle_times_ = obj.Get("battle_times");
current_get_star_ = obj.Get("current_get_star");
}
level_ = obj.HasKey("level") ? obj.Get("level").GetInt() : 1;
skin_id_ = obj.HasKey("hero_skin") ? obj.Get("hero_skin").GetInt() : 0;
total_lucky_ = obj.HasKey("total_lucky") ? obj.Get("total_lucky").GetDouble() : 0;
if (obj.HasKey("hero_dto") && obj.At("hero_dto")->IsObject()) {
hero_dto = obj.At("hero_dto");
hero_ability_->hero_uniid_ = hero_dto->Get("hero_uniid", "");
hero_ability_->spec_skill_id = obj.Get("skill_id", "");
hero_ability_->main_skill_id = obj.Get("skill_id", "");
hero_ability_->hero_dto = hero_dto;
hero_lv_ = hero_dto->HasKey("hero_lv") ? hero_dto->Get("hero_lv").GetInt() : 1;
const mt::Hero* meta = mt::Hero::GetById(hero_dto->Get("hero_id", ""));
if (meta) {
hero_ability_->hero_meta = meta;
}
if (hero_dto->HasKey("avatar_info") && hero_dto->At("avatar_info")->IsArray()) {
if (hero_dto->At("avatar_info")->Size() > 0) {
avatars_.push_back(290001);
}
}
}
if (obj.HasKey("honor_info") && obj.At("honor_info")->IsArray()) {
auto honor_info = obj.At("honor_info");
for (int i = 0; i < honor_info->Size(); ++i) {
auto info = honor_info->At(i);
if (info->IsObject()) {
if (info->HasKey("token_type") &&
info->HasKey("state") &&
info->At("token_type")->IsSimple() &&
info->At("state")->IsSimple()
) {
int token_type = info->Get("token_type").GetInt();
int state = info->Get("state").GetInt();
if (token_type == 6 && state) {
honor_ = 1;
}
}
}
}
}
#if 1
if (hero_ability_->hero_meta) {
const mt::Item* item_meta = mt::Item::GetById(hero_ability_->hero_meta->default_weapon());
if (item_meta) {
const mt::Equip* meta = mt::Equip::GetById(item_meta->relationship());
if (meta) {
weapon1_ability_ = std::make_shared<WeaponAbility>();
weapon1_ability_->weapon_uniid = 0;
weapon1_ability_->weapon_lv = 1;
weapon1_ability_->quality = 1;
weapon1_ability_->weapon_meta = meta;
}
}
}
#else
if (obj.HasKey("weapon_dto1") && obj.At("weapon_dto1")->IsObject()) {
weapon_dto1 = obj.At("weapon_dto1");
const mt::Item* item_meta = mt::Item::GetById(weapon_dto1->Get("gun_id", 0));
if (item_meta) {
const mt::Equip* meta = mt::Equip::GetById(item_meta->relationship());
if (meta) {
weapon1_ability_ = std::make_shared<WeaponAbility>();
weapon1_ability_->weapon_uniid = weapon_dto1->Get("gun_uniid", 0);
weapon1_ability_->weapon_lv = weapon_dto1->Get("gun_lv", 1);
weapon1_ability_->quality = weapon_dto1->Get("quality", 1);
weapon1_ability_->weapon_meta = meta;
weapon1_ability_->weapon_dto = weapon_dto1;
}
}
}
if (obj.HasKey("weapon_dto2") && obj.At("weapon_dto2")->IsObject()) {
weapon_dto2 = obj.At("weapon_dto2");
const mt::Item* item_meta = mt::Item::GetById(weapon_dto2->Get("gun_id", 0));
if (item_meta) {
const mt::Equip* meta = mt::Equip::GetById(item_meta->relationship());
if (meta) {
weapon2_ability_ = std::make_shared<WeaponAbility>();
weapon2_ability_->weapon_uniid = weapon_dto2->Get("gun_uniid", 0);
weapon2_ability_->weapon_lv = weapon_dto2->Get("gun_lv", 1);
weapon2_ability_->quality = weapon_dto2->Get("quality", 1);
weapon2_ability_->weapon_meta = meta;
weapon2_ability_->weapon_dto = weapon_dto2;
}
}
}
#endif
parse_ok = hero_ability_->hero_meta != nullptr;
}
void BattleDataContext::GetHeroLvQuality(long long& hero_uniid, int& hero_lv, int& quality)
{
hero_uniid = 0;
hero_lv = 1;
quality = 1;
#if 1
{
#else
if (owner_.Get()->IsPlayer()) {
#endif
if (hero_ability_ && hero_dto && hero_dto->IsObject()) {
hero_uniid = hero_dto->Get("hero_uniid", 0).GetInt64();
hero_lv = hero_dto->Get("hero_lv", 0).GetInt();
quality = hero_dto->Get("quality", 0).GetInt();
}
}
if (owner_.Get()) {
hero_lv = owner_.Get()->GetHeroLevel();
}
}
void BattleDataContext::GetWeaponLvQuality(long long weapon_uniid, int& weapon_lv, int& quality)
{
weapon_lv = 1;
quality = 1;
if (owner_.Get()->IsPlayer() && weapon_uniid) {
if (weapon1_ability_ && weapon_uniid == weapon1_ability_->weapon_uniid) {
weapon_lv = weapon1_ability_->weapon_lv;
quality = weapon1_ability_->quality;
}
if (weapon2_ability_ && weapon_uniid == weapon2_ability_->weapon_uniid) {
weapon_lv = weapon2_ability_->weapon_lv;
quality = weapon2_ability_->quality;
}
}
}
int BattleDataContext::GetWeaponMaxLv()
{
int max_weapon_lv = 1;
if (weapon1_ability_) {
max_weapon_lv = std::max(max_weapon_lv, weapon_dto1->Get("gun_lv", 0).GetInt());
}
if (weapon2_ability_) {
max_weapon_lv = std::max(max_weapon_lv, weapon_dto2->Get("gun_lv", 0).GetInt());
}
return std::max(1, max_weapon_lv);
}
void BattleDataContext::CalcBattleStat(struct PlayerStats* stats)
{
if (!owner_.Get()->IsPlayer()) {
return;
}
auto CalcHeroPvpCeg =
[] (long long ceg_uplimit, struct PlayerStats* stats) -> long long
{
const mt::FormulaPvp* meta = mt::FormulaPvp::GetByTopx(stats->ranked_topx);
if (!meta) {
return 0;
}
long long ceg = round
(
ceg_uplimit *
(
(0.5 * stats->ranked_topx * meta->ranked_topx()) +
(0.25 * stats->kills_topx * meta->kills_topx()) +
(0.15 * stats->hero_topx * meta->hero_topx()) +
(0.5 * stats->weapon_topx * meta->weapon_topx()) +
(0.5 * stats->survival_topx * meta->survival_topx())
)
);
return ceg;
};
auto CalcWeaponPvpCeg =
[] (long long ceg_uplimit, struct PlayerStats* stats) -> long long
{
const mt::FormulaPvp* meta = mt::FormulaPvp::GetByTopx(stats->ranked_topx);
if (!meta) {
return 0;
}
long long ceg = round
(
ceg_uplimit *
(
(0.5 * stats->ranked_topx * meta->ranked_topx()) +
(0.25 * stats->kills_topx * meta->kills_topx()) +
(0.15 * stats->hero_topx * meta->hero_topx()) +
(0.5 * stats->weapon_topx * meta->weapon_topx()) +
(0.5 * stats->survival_topx * meta->survival_topx())
)
);
return ceg;
};
if (hero_ability_ && hero_dto && hero_dto->IsObject()) {
int hero_id = hero_dto->Get("hero_id", 0).GetInt();
int quality = hero_dto->Get("quality", 0).GetInt();
int today_get_gold = hero_dto->Get("today_get_gold", 0).GetInt();
const mt::Hero* hero_meta = mt::Hero::GetById(hero_id);
const mt::HeroQuality* quality_meta = mt::HeroQuality::GetById(quality);
stats->pb_hero_stats.hero_uniid = a8::XValue(hero_ability_->hero_uniid_).GetString();
stats->pb_hero_stats.hero_id = hero_id;
stats->pb_hero_stats.hero_name = hero_meta ? hero_meta->name() : "";
if (quality_meta) {
int up_limit = quality_meta->GetPvpCegUpLimit();
int ceg = CalcHeroPvpCeg(up_limit, stats);
int new_ceg = std::min(up_limit, today_get_gold + ceg);
int finaly_ceg = std::max(0, new_ceg - today_get_gold);
stats->pb_hero_stats.ceg_uplimit = up_limit;
stats->pb_hero_stats.today_get_ceg =
std::min(up_limit, today_get_gold + finaly_ceg);
stats->pb_hero_stats.reward_ceg = finaly_ceg;
}
}
std::vector<std::shared_ptr<a8::XObject>> weapons;
if (weapon_dto1) {
weapons.push_back(weapon_dto1);
}
if (weapon_dto2) {
weapons.push_back(weapon_dto2);
}
for (auto& weapon_dto : weapons) {
std::string gun_uniid = weapon_dto->Get("gun_uniid", 0).GetString();
int gun_id = weapon_dto->Get("gun_id", 0).GetInt();
int quality = weapon_dto->Get("quality", 0).GetInt();
int today_get_gold = weapon_dto->Get("today_get_gold", 0).GetInt();
const mt::Item* item_meta = mt::Item::GetById(gun_id);
const mt::GunQuality* quality_meta = mt::GunQuality::GetById(quality);
auto& p = a8::FastAppend(stats->pb_weapons_stats);
p.weapon_uniid = gun_uniid;
p.weapon_id = gun_id;
p.weapon_name = item_meta ? item_meta->name() : "";
if (quality_meta) {
int up_limit = quality_meta->GetPvpCegUpLimit();
int ceg = CalcWeaponPvpCeg(up_limit, stats);
int new_ceg = std::min(up_limit, today_get_gold + ceg);
int finaly_ceg = std::max(0, new_ceg - today_get_gold);
p.ceg_uplimit = up_limit;
p.today_get_ceg =
std::min(up_limit, today_get_gold + finaly_ceg);
p.reward_ceg = finaly_ceg;
}
}
}
static float ProEffect(Creature* c, float p, float b){
if (p * b > -1 && std::fabs(b) > 0.00001f) {
float x = std::floor(p) * b;
float y = std::max(x + b, -1.0f);
float q = (p * b - y) / (x - y);
float rnd = (float)rand() / (float)RAND_MAX;
c->SendDebugMsg(a8::Format("数值: p:%f b:%f x:%f y:%f q:%f rnd:%f",
{
p,
b,
x,
y,
q,
rnd
}));
return rnd < q ? x : y;
} else {
return 0.0f;
}
}
float BattleDataContext::CalcDmg(Creature* target, IBullet* bullet)
{
g_calc_dmg_context = {0};
#ifdef MYDEBUG
std::vector<std::string> dbg_strings;
if (owner_.Get()->IsPlayer()) {
{
std::vector<std::string> tmp_strings;
tmp_strings = owner_.Get()->GetAbility()->GMShowAttrs();
owner_.Get()->SendDebugMsg("数值: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
for (auto& str : tmp_strings) {
owner_.Get()->SendDebugMsg("数值: self " + str);
}
owner_.Get()->SendDebugMsg("数值: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
}
{
std::vector<std::string> tmp_strings;
tmp_strings = target->GetAbility()->GMShowAttrs();
owner_.Get()->SendDebugMsg("数值: <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
for (auto& str : tmp_strings) {
owner_.Get()->SendDebugMsg("数值: target " + str);
}
owner_.Get()->SendDebugMsg("数值: <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
if (owner_.Get()->GetHeroMeta()->id() == 9011) {
int i = 0;
}
#endif
owner_.Get()->GetTrigger()->BulletDmgStart(target);
float vEbc = 1.0f;
float vEd = 1 - target->GetNetData()->GetDef();
float X = (1 + hero_ability_->GetCrit()) * (1 - target->GetNetData()->GetBlock()) - 1;
float vCritBon = 0.0f;
float E = 0.0f;
float vBlock = 0.0f;
if (X > 0.00001f) {
//触发暴击
vCritBon = hero_ability_->hero_meta->GetBasicMeta()->vOrigCriBon();
E = ProEffect(owner_.Get(), X / vCritBon, vCritBon); //E >= 0
if (E > 0.00001f) {
vEbc = 1 + E;
g_calc_dmg_context.dmg_bp = mt::Param::GetCritEffect(E);
}
} else if (X < -0.00001f) {
//触发格挡 0,-1
vBlock = target->GetNetData()->GetHeroAbility()->hero_meta->GetBasicMeta()->vOrigBloDef();
E = ProEffect(owner_.Get(), X / (-vBlock) , -vBlock); //E >= 0
if (E < 0.00001f) {
vEbc = 1 + E;
g_calc_dmg_context.dmg_bp = mt::Param::GetBlockEffect(E);
}
} else {
vEbc = 1.0f;
}
float vAttack = GetHeroTotalAtk();
float vBullet = GetWeaponAtk(bullet);
const float BDM = 100;
float vNormalDamageDealtRateIn = owner_.Get()->GetAbility()->GetAttr(kHAT_vNormalDamageDealtRateIn);
float vNormalDamageTakenRateIn = target->GetAbility()->GetAttr(kHAT_vNormalDamageTakenRateIn);
float vDmg = vAttack * vBullet / BDM * (1 + vNormalDamageDealtRateIn) * ( 1 + vNormalDamageTakenRateIn);
if (owner_.Get()->GetAbility()->HasAttr(kHVAT_DirectAtk)) {
vDmg = owner_.Get()->GetAbility()->GetAttr(kHVAT_DirectAtk) * vBullet / BDM * (1 + vNormalDamageDealtRateIn) * ( 1 + vNormalDamageTakenRateIn);
}
float DDR = owner_.Get()->GetAbility()->GetAttr(kHAT_vDamageDealtRateIn);
float DTR = target->GetAbility()->GetAttr(kHAT_vDamageTakenRateIn);
float finaly_dmg = vDmg * vEbc * vEd * (1 + DDR) * (1 + DTR);
#ifdef MYDEBUG
if (owner_.Get()->IsPlayer()) {
dbg_strings.push_back(a8::Format
("finaly_dmg:%f vEcb:%f vEd:%f X:%f vCritBon:%f E:%f vBlock:%f vAttack:%f vBullet:%f BDM:%f "
"vNormalDamageDealtRateIn:%f vNormalDamageTakenRateIn:%f vDmg:%f DDR:%f DTR:%f self.id:%d target.id:%f dmg_type:%d",
{
finaly_dmg,
vEbc,
vEd,
X,
vCritBon,
E,
vBlock,
vAttack,
vBullet,
BDM,
vNormalDamageDealtRateIn,
vNormalDamageTakenRateIn,
vDmg,
DDR,
DTR,
owner_.Get()->GetUniId(),
target->GetUniId(),
g_calc_dmg_context.dmg_bp
}
)
);
for (auto& str : dbg_strings) {
owner_.Get()->SendDebugMsg("数值: " + str);
}
}
#endif
owner_.Get()->GetTrigger()->BulletDmgEnd(target);
return std::max(1.0f, std::round(finaly_dmg));
}
float BattleDataContext::CalcDmg(Obstacle* target, IBullet* bullet)
{
g_calc_dmg_context = {0};
g_calc_dmg_context.is_crit = 0;
#ifdef NEW_NUM
/// 888 return GetTotalAtk(bullet);
return 100;
#else
g_calc_dmg_context.is_crit = IsCrit(bullet) ? 1 : 0;
float total_atk = GetTotalAtk(bullet);
float normal_dmg = total_atk * (1 - 0 / 1000);
float crit = g_calc_dmg_context.is_crit ? GetCritRate(bullet) : 0;
float finaly_dmg = normal_dmg * (1.0f + crit);
#ifdef MYDEBUG
if (owner_.Get()->IsPlayer()) {
std::string data = a8::Format
("数值: 子弹攻击物件 total_atk:%f normal_dmg:%f crit:%f finaly_dmg:%f target_def:%f",
{
total_atk,
normal_dmg,
crit,
finaly_dmg,
0
});
owner_.Get()->SendDebugMsg(data);
}
#endif
if (g_calc_dmg_context.is_crit) {
g_calc_dmg_context.crit_dmg = finaly_dmg;
}
return finaly_dmg;
#endif
}
float BattleDataContext::CalcReceiveDmg(Creature* sender, float normal_dmg)
{
float finaly_dmg = normal_dmg *
(1 - owner_.Get()->GetNetData()->GetDef() / (sender->GetNetData()->GetDef() + 200));
finaly_dmg *= (1 + sender->GetAbility()->GetAttrAddition(kHVAT_Dmg)); //连加
#if 1
if (owner_.Get()->GetAbility()->GetAttrRuduce(kHVAT_Dmg) > 0.0001) {
finaly_dmg *= owner_.Get()->GetAbility()->GetAttrRuduce(kHVAT_Dmg); //(1-减免) 连乘
}
#else
finaly_dmg *= (1 - owner_.Get()->GetAbility()->GetAttrRuduce(kHVAT_Dmg)); //(1-减免) 连乘
#endif
finaly_dmg = std::max(1.0f, finaly_dmg);
return std::round(finaly_dmg);
}
float BattleDataContext::CalcSkillReceiveDmg(Creature* sender, float normal_dmg)
{
g_calc_dmg_context = {0};
g_calc_dmg_context.is_crit = 0;
float vEbc = 1.0f;
float vEd = 1 - GetDef();
float X = (1 + sender->GetNetData()->GetHeroAbility()->GetCrit()) * (1 - GetBlock()) - 1;
if (X > 0.00001f) {
//触发暴击
float vCritBon = sender->GetNetData()->GetHeroAbility()->hero_meta->GetBasicMeta()->vOrigCriBon();
float E = ProEffect(owner_.Get(), X, vCritBon); //E >= 0
if (E > 0.00001f) {
vEbc = 1 + E;
}
} else {
//触发格挡 0,-1
float vBlock = GetHeroAbility()->hero_meta->GetBasicMeta()->vOrigBloDef();
float E = ProEffect(owner_.Get(), X, -vBlock); //E >= 0
if (E < 0.00001f) {
vEbc = 1 + E;
}
}
float BDM = 100;
float vSkillDamageDealtRateIn = 0.0f;
float vSkillDamageTakenRateIn = 0.0f;
float vDmg = normal_dmg * (1 + vSkillDamageDealtRateIn) * (1 + vSkillDamageTakenRateIn);
float DDR = 0.0f;
float DTR = 0.0f;
float finaly_dmg = vDmg * vEbc * vEd * (1 + DDR) * (1 + DTR);
return std::max(1.0f, std::round(finaly_dmg));
}
float BattleDataContext::CalcDmg(Explosion* e)
{
g_calc_dmg_context = {0};
float finaly_dmg = e->GetDmg();
#ifdef MYDEBUG
if (owner_.Get()->IsPlayer()) {
std::string data = a8::Format
("数值: 爆炸伤害 finaly_dmg:%f def:%f",
{
finaly_dmg,
GetDef()
});
owner_.Get()->SendDebugMsg(data);
}
#endif
return finaly_dmg;
}
float BattleDataContext::GetMaxHP()
{
float hp = hero_ability_->GetHP();
return hp;
}
float BattleDataContext::GetAttack()
{
return hero_ability_->GetAtk();
}
float BattleDataContext::GetDef()
{
float def = hero_ability_->GetDef();
return def;
}
float BattleDataContext::GetHeroTotalAtk()
{
float atk = hero_ability_->GetAtk();
return atk;
}
float BattleDataContext::GetWeaponAtk(IBullet* bullet)
{
float atk = 0.0f;
auto weapon = GetWeaponByUniId(bullet->GetWeaponUniId());
if (weapon) {
atk = weapon->GetAtk();
} else {
atk = bullet->GetGunMeta()->_atk;
}
atk *= (1 + owner_.Get()->GetAbility()->GetAttrAddition(kHVAT_WeaponAtk));
return atk;
}
std::shared_ptr<WeaponAbility> BattleDataContext::GetWeaponByUniId(long long weapon_uuid)
{
if (weapon1_ability_ && weapon1_ability_->weapon_uniid == weapon_uuid) {
return weapon1_ability_;
}
if (weapon2_ability_ && weapon2_ability_->weapon_uniid == weapon_uuid) {
return weapon2_ability_;
}
return nullptr;
}
void BattleDataContext::ForceInit(long long hero_uniid,
const mt::Hero* hum_meta,
long long weapon1_uniid,
const mt::Equip* weapon1_meta,
long long weapon2_uniid,
const mt::Equip* weapon2_meta)
{
hero_ability_->hero_uniid_ = hero_uniid;
hero_ability_->hero_meta = hum_meta;
if (weapon1_uniid && weapon1_meta) {
weapon1_ability_ = std::make_shared<WeaponAbility>();
weapon1_ability_->weapon_uniid = weapon1_uniid;
weapon1_ability_->weapon_meta = weapon1_meta;
}
if (weapon2_uniid && weapon2_meta) {
weapon2_ability_ = std::make_shared<WeaponAbility>();
weapon2_ability_->weapon_uniid = weapon2_uniid;
weapon2_ability_->weapon_meta = weapon2_meta;
}
}
void BattleDataContext::Init(Creature* c)
{
owner_ = c->GetWeakPtrRef();
hero_ability_->Init(owner_);
if (!hero_ability_->hero_uniid_) {
hero_ability_->hero_uniid_ = App::Instance()->AllocTempHeroUniId();
}
hero_ability_->Init(c);
if (weapon1_ability_) {
weapon1_ability_->Init(c);
}
if (weapon2_ability_) {
weapon2_ability_->Init(c);
}
#if 1
{
if (c->IsAndroid() && a8::RandEx(0, 1000) < 100) {
skin_id_ = a8::RandEx(0, 1) + c->GetHeroMeta()->skinlist();
}
}
#endif
if (skin_id_ && c->IsHuman()) {
const mt::Item* item_meta = mt::Item::GetById(skin_id_);
if (item_meta) {
Skin* skin = c->AsHuman()->GetSkinByIdx(0);
#if 1
skin->skin_id = skin_id_;
#else
skin->skin_id = item_meta->skinid();
#endif
}
}
if (c->IsPlayer()) {
std::array<std::shared_ptr<WeaponAbility>, 2> weapons = {weapon1_ability_, weapon2_ability_};
for (auto weapon : weapons) {
if (weapon) {
Weapon& spec_weapon = a8::FastAppend(c->AsHuman()->spec_weapons);
spec_weapon.weapon_uniid = a8::XValue(weapon->weapon_uniid);
spec_weapon.weapon_id = weapon->weapon_meta->id();
spec_weapon.meta = weapon->weapon_meta;
spec_weapon.Recalc();
spec_weapon.ammo = spec_weapon.GetClipVolume(c);
}
}
}
auto match_conf = owner_.Get()->room->GetRankMatchConf();
if (owner_.Get()->IsAndroid() && match_conf) {
}
c->NetInitOk();
}
void BattleDataContext::GetSkillList(std::vector<int>& skill_list)
{
const mt::Skill* spec_skill = mt::Skill::GetById(hero_ability_->spec_skill_id);
const mt::Skill* skill1 = mt::Skill::GetById(hero_ability_->hero_meta->skill1list());
const mt::Skill* skill2 = mt::Skill::GetById(hero_ability_->hero_meta->skill2list());
const mt::Skill* skill3 = mt::Skill::GetById(hero_ability_->hero_meta->skill3list());
if (owner_.Get()->IsHuman()) {
if (skill1 && skill2 && skill3 && skill1_lv > 0 && skill2_lv > 0 && skill3_lv > 0) {
if (mt::Skill::GetById(skill1->skill_id() + skill1_lv - 1)) {
skill_list.push_back(skill1->skill_id() + skill1_lv - 1);
} else {
skill_list.push_back(skill1->skill_id());
}
//替换翻滚
if (spec_skill) {
skill_list.push_back(spec_skill->skill_id());
} else {
if (mt::Skill::GetById(skill2->skill_id() + skill2_lv - 2)) {
skill_list.push_back(skill2->skill_id() + skill2_lv - 2);
} else {
skill_list.push_back(skill2->skill_id());
}
}
if (mt::Skill::GetById(skill3->skill_id() + skill3_lv - 3)) {
skill_list.push_back(skill3->skill_id() + skill3_lv - 3);
} else {
skill_list.push_back(skill3->skill_id());
}
}
} else {
std::vector<const mt::Skill*> skills = {skill1, skill2, skill3};
for (auto skill_meta : skills) {
if (skill_meta) {
skill_list.push_back(skill_meta->skill_id());
}
}
}
}
int BattleDataContext::GetClipVolume(Creature* c, Weapon* weapon)
{
if (!weapon->meta) {
return 0;
}
auto p = GetWeaponByUniId(weapon->weapon_uniid);
return p ? p->GetClipVolume() : weapon->meta->clip_volume();
}
int BattleDataContext::GetFireRate(Creature* c, Weapon* weapon)
{
if (!weapon->meta) {
return 0;
}
auto p = GetWeaponByUniId(weapon->weapon_uniid);
return p ? p->GetFireRate() : weapon->meta->fire_rate();
}
int BattleDataContext::GetReloadTime(Creature* c, Weapon* weapon)
{
if (!weapon->meta) {
return 0;
}
auto p = GetWeaponByUniId(weapon->weapon_uniid);
return p ? p->GetReloadTime() : weapon->meta->reload_time();
}
float BattleDataContext::GetExtRecoverHp()
{
return 0;
}
void BattleDataContext::SetReviveCoin(int num)
{
revive_coin_ = num;
}
int BattleDataContext::GetReviveCoin()
{
return revive_coin_;
}
void BattleDataContext::SetMatchMode(int match_mode)
{
match_mode_ = match_mode;
}
int BattleDataContext::GetMatchMode()
{
return match_mode_;
}
bool BattleDataContext::IsCrit()
{
return g_calc_dmg_context.is_crit ? 1 : 0;
}
bool BattleDataContext::IsBlock()
{
return g_calc_dmg_context.is_block ? 1 : 0;
}
float BattleDataContext::GetCritDmg()
{
return g_calc_dmg_context.crit_dmg;
}
int BattleDataContext::GetCritBp()
{
return g_calc_dmg_context.dmg_bp;
}
int BattleDataContext::GetBlockBp()
{
return g_calc_dmg_context.dmg_bp;
}
int BattleDataContext::GetDmgBp()
{
return g_calc_dmg_context.dmg_bp;
}
int BattleDataContext::GetSkinId()
{
return skin_id_;
}
int BattleDataContext::GetLevel()
{
return std::max(level_, 1);
}
float BattleDataContext::GetBrainLifePct()
{
return hero_ability_->GetBrainLifePct();
}
float BattleDataContext::GetSkillCdPct()
{
return hero_ability_->GetSkillCdPct() + owner_.Get()->GetAbility()->GetAttr(kHVAT_SkillTime);
}
float BattleDataContext::GetRescueTimePct()
{
return hero_ability_->GetRescueTimePct();
}
float BattleDataContext::GetDrugTimePct()
{
return hero_ability_->GetDrugTimePct();
}
float BattleDataContext::GetDrugEfficacyPct()
{
return owner_.Get()->GetAbility()->GetAttr(kHAT_vHealthGainRateIn);
}
float BattleDataContext::GetTenacityPct()
{
return hero_ability_->GetTenacityPct();
}
float BattleDataContext::GetRecoverHpAdd()
{
return hero_ability_->GetRecoverHpAdd();
}
int BattleDataContext::GetHeroLevel()
{
if (!owner_.Get()->IsPlayer() && hero_ability_ && hero_ability_->standard_meta) {
return hero_ability_->standard_meta->level();
}
return std::max(hero_lv_, 1);
}
int BattleDataContext::GetHeroId()
{
if (hero_ability_) {
return hero_ability_->hero_meta->id();
}
A8_ABORT();
}
bool BattleDataContext::IsMainSkill(Skill* skill)
{
if (skill->GetBaseSkillMeta()->_base_skill_meta) {
return hero_ability_->hero_meta->skill1list() == skill->GetBaseSkillMeta()->_base_skill_meta->skill_id();
} else {
return hero_ability_->hero_meta->skill1list() == skill->GetBaseSkillMeta()->skill_id();
}
}
int BattleDataContext::GetRank()
{
return rank_;
}
int BattleDataContext::GetCurrentGetStar()
{
return current_get_star_;
}
int BattleDataContext::GetBattleTimes()
{
return battle_times_;
}
int BattleDataContext::GetHonor()
{
return honor_;
}
float BattleDataContext::GetBlock()
{
return hero_ability_->GetBlock();
}
float BattleDataContext::GetCrit()
{
return hero_ability_->GetCrit();
}
void BattleDataContext::RecalcMaxHP()
{
hero_ability_->RecalcHp();
}
void BattleDataContext::RecalcAttack()
{
hero_ability_->RecalcAttack();
}
void BattleDataContext::RecalcDef()
{
hero_ability_->RecalcDef();
}
void BattleDataContext::RecalcBlock()
{
hero_ability_->RecalcBlock();
}
void BattleDataContext::RecalcCrit()
{
hero_ability_->RecalcCrit();
}
bool BattleDataContext::HasWing()
{
return true;
if (hero_dto) {
long long token_id = hero_dto->Get("token_id", "");
if (token_id > 6240603010001668 && token_id <= 6240603010002168) {
return true;
}
if (token_id == 6240603010001523) {
return true;
}
}
return false;
}
bool BattleDataContext::HideBigEventBox()
{
return GetTotalLucky() < 0.01f;
}
float BattleDataContext::GetTotalLucky()
{
return total_lucky_;
}