1392 lines
42 KiB
C++
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_;
|
|
}
|