From 094c6b58a0a6aea3d35adaea0f48d5c869e92407 Mon Sep 17 00:00:00 2001 From: yangduo Date: Sun, 20 Apr 2025 22:41:36 +0800 Subject: [PATCH] talent & fashion --- .gitignore | 3 +- server/gameserver/human.cc | 86 +++++++++++++++++++++++++++------- server/gameserver/human.h | 6 ++- server/gameserver/metadata.cc | 77 ++++++++++++++++++++++++++++++ server/gameserver/metadata.h | 28 +++++++++++ server/gameserver/metamgr.cc | 52 ++++++++++++++++++++ server/gameserver/metamgr.h | 4 ++ server/gameserver/player.cc | 3 ++ server/gameserver/playermgr.cc | 4 +- 9 files changed, 241 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 13f7d83..3c7921a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ __pycache__ .user game.py *.cxx -compile_commands.json \ No newline at end of file +compile_commands.json +.vscode/settings.json diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index 52a0e94..eac21e0 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -136,12 +136,8 @@ void Human::Initialize() RecalcSelfCollider(); volume_ = meta->volume; observers_.insert(this); - ability.hp = meta->i->health(); - for (auto& weapon : spec_weapons) { - if (weapon.meta) { - ability.hp += weapon.meta ? weapon.GetAttrValue(kHAT_MaxHp) : 0; - } - } + RecalcMaxHp(); + ability.hp = ability.max_hp; } float Human::GetSpeed() @@ -1570,7 +1566,9 @@ void Human::RecalcBaseAttr() if (helmet_meta) { ability.def += helmet_meta->i->def(); } - ability.max_hp = std::max(ability.hp, ability.max_hp); + RecalcSkinAttr(); + RecalcTalentAttr(); + RecalcMaxHp(); } int Human::GetInventory(int slot_id) @@ -1611,7 +1609,7 @@ void Human::RecoverHp(int inc_hp) { if (!dead) { ability.hp += inc_hp; - ability.hp = std::max(GetHP(), GetMaxHP()); + ability.hp = std::min(GetHP(), GetMaxHP()); } } @@ -2090,15 +2088,69 @@ bool Human::IsEnemy(Human* hum) } } - void Human::RecalTalentAttr() + void Human::RecalcTalentAttr() { + talent_attr_abs_ = {}; + if (curr_weapon == nullptr) + { + return; + } + + for(int i = 1;i <= maxtalent; i++) + { + auto talent = MetaMgr::Instance()->GetTalent(i); + std::string label(curr_weapon->meta->i.equip_label()); + if (talent->GetEquipLabel() == a8::XValue(label).GetInt()) { + talent_attr_abs_[kHAT_Atk] += talent->GetAtkPlus(); + talent_attr_abs_[kHAT_MaxHp] += talent->GetHpPlus(); + } + } } - void Human::RecalSkinAttr() + void Human::RecalcSkinAttr() { + std::map skinmap = {}; + int fashionid = 0; + for(int i = 0;i < 6;i++) + { + skinmap[skins[i].skin_id] = skins[i].skin_id; + if (i == 1) { + fashionid = skins[i].skin_id; + } + } - } + skin_attr_abs_ = {}; + auto fashion = MetaMgr::Instance()->GetFashion(fashionid); + if (fashion != nullptr && fashion->CheckFashion(skinmap)){ + fashion->GetAttr(skin_attr_abs_); + } + + for(auto& item:skinmap) + { + auto skinattr = MetaMgr::Instance()->GetSkinAttr(item.first); + if (skinattr == nullptr) { + continue; + } + + for(int i = kHAT_Begin; i < kHAT_End; i++) + { + skin_attr_abs_[i] += (*skinattr)[i]; + } + } +} + +void Human::RecalcMaxHp() +{ + ability.max_hp = meta->i->health(); + for (auto& weapon : spec_weapons) { + if (weapon.meta) { + ability.max_hp += weapon.meta ? weapon.GetAttrValue(kHAT_MaxHp) : 0; + } + } + ability.max_hp += talent_attr_abs_[kHAT_MaxHp]; + ability.max_hp += skin_attr_abs_[kHAT_MaxHp]; +} void Human::_InternalUpdateMove(float speed) { @@ -3320,6 +3372,10 @@ float Human::GetAttrAbs(int attr_id) } } } + if (IsValidHumanAttr(attr_id)) { + attr_abs_val += talent_attr_abs_[attr_id]; + attr_abs_val += skin_attr_abs_[attr_id]; + } return attr_abs_val; } @@ -4024,14 +4080,10 @@ void Human::OnMetaChange() curr_weapon = &weapons[0]; } } - ability.hp = meta->i->health(); - for (auto& weapon : spec_weapons) { - if (weapon.meta) { - ability.hp += weapon.meta ? weapon.GetAttrValue(kHAT_MaxHp) : 0; - } - } + room->frame_event.AddHpChg(this); RecalcBaseAttr(); + ability.hp = ability.max_hp; skill_meta_ = MetaMgr::Instance()->GetSkill(meta->i->active_skill()); ResetSkill(); MetaData::Skill* passive_skill_meta = MetaMgr::Instance()->GetSkill(meta->i->passive_skill()); diff --git a/server/gameserver/human.h b/server/gameserver/human.h index 573bd16..87fbb8d 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -297,8 +297,8 @@ class Human : public MoveableEntity void DeadDrop(); bool IsEnemy(Human* hum); - void RecalTalentAttr(); - void RecalSkinAttr(); + void RecalcTalentAttr(); + void RecalcSkinAttr(); protected: void _InternalUpdateMove(float speed); @@ -312,6 +312,8 @@ protected: void AutoChgWeapon(); void CancelRevive(); + void RecalcMaxHp(); + private: void ClearFrameData(); void GenBattleReportData(a8::MutableXObject* params); diff --git a/server/gameserver/metadata.cc b/server/gameserver/metadata.cc index 6ad08cd..87d6ee9 100644 --- a/server/gameserver/metadata.cc +++ b/server/gameserver/metadata.cc @@ -580,4 +580,81 @@ namespace MetaData ); } + void Talent::Init() + { + talentid = a8::XValue(i->talent_id()).GetInt(); + if (!i->equip_label().empty()) { + equiplabel = a8::XValue(i->equip_label()).GetInt(); + hpplus = a8::XValue(i->hp_upgrade()).GetInt(); + } else { + equiplabel = a8::XValue(i->equip_label2()).GetInt(); + atkplus = a8::XValue(i->atk_upgrade()).GetInt(); + } + } + + int Talent::GetId() + { + return talentid; + } + + int Talent::GetEquipLabel() + { + return equiplabel; + } + + int Talent::GetHpPlus() + { + return hpplus; + } + + int Talent::GetAtkPlus() + { + return atkplus; + } + + void Fashion::Init() + { + fashionid = i->id(); + std::vector strings; + a8::Split(i->spera_attr(), strings, ';'); + for(auto& item: strings) + { + std::vector itemstrs; + a8::Split(item, itemstrs, ':'); + if (itemstrs.size() < 2) { + continue; + } + + int key = a8::XValue(itemstrs[0]).GetInt(); + int value = a8::XValue(itemstrs[1]).GetInt(); + attr_abs[key] = value; + } + + strings.clear(); + a8::Split(i->item_id(), strings, '|'); + for(auto& item: strings) + { + fashion_details.push_back(a8::XValue(item).GetInt()); + } + } + + bool Fashion::CheckFashion(const std::map &skins) + { + for(auto& item: fashion_details) + { + if (skins.find(item) == skins.end()) { + return false; + } + } + + return true; + } + + void Fashion::GetAttr(std::array &attarr) + { + for(int i = kHAT_Begin; i < kHAT_End; i++) + { + attarr[i] = attr_abs[i]; + } + } } diff --git a/server/gameserver/metadata.h b/server/gameserver/metadata.h index a7739f4..35d0785 100755 --- a/server/gameserver/metadata.h +++ b/server/gameserver/metadata.h @@ -234,4 +234,32 @@ namespace MetaData }; + struct Talent + { + const metatable::Talent* i = nullptr; + void Init(); + int GetId(); + int GetEquipLabel(); + int GetHpPlus(); + int GetAtkPlus(); + + private: + int talentid = 0; + int equiplabel = 0; + int hpplus = 0; + int atkplus = 0; + }; + + struct Fashion + { + const metatable::Fashion* i = nullptr; + void Init(); + bool CheckFashion(const std::map &skins); + void GetAttr(std::array &attarr); + + private: + int fashionid = 0; + std::array attr_abs = {}; + std::vector fashion_details = {}; + }; } diff --git a/server/gameserver/metamgr.cc b/server/gameserver/metamgr.cc index 2adab43..ee6ddde 100755 --- a/server/gameserver/metamgr.cc +++ b/server/gameserver/metamgr.cc @@ -63,6 +63,11 @@ public: std::list ai_meta_list; std::list ai_list; + std::list talent_meta_list; + std::list talent_list; + std::list fashion_meta_list; + std::list fashion_list; + std::map parameter_hash; std::map gamemap_hash; std::map airdrop_hash; @@ -90,6 +95,9 @@ public: std::map robot_hash; std::map> airline_hash; std::map ai_hash; + std::map talent_hash; + std::map fashion_hash; + std::map> skinatt_hash; void Load() { @@ -138,6 +146,8 @@ public: f8::ReadCsvMetaFile(res_path + "equipUpgrade@equipUpgrade.csv", equipupgrade_meta_list); f8::ReadCsvMetaFile(res_path + "robot@robot.csv", robot_meta_list); f8::ReadCsvMetaFile(res_path + "ai@ai.csv", ai_meta_list); + f8::ReadCsvMetaFile(res_path + "talent@talent.csv", talent_meta_list); + f8::ReadCsvMetaFile(res_path + "fashion@fashion.csv", fashion_meta_list); BindToMetaData(); #if 1 { @@ -489,6 +499,16 @@ private: if (meta._inventory_slot() > -1) { equip_slot_hash[meta._inventory_slot()] = &item; } + + if (meta->equip_type() == 10) { + if (!meta->atk().empty()) { + skinatt_hash[item.i->id()][kHAT_Atk] = a8::XValue(meta->atk()).GetInt(); + } + + if (!meta->max_hp().empty()) { + skinatt_hash[item.i->id()][kHAT_MaxHp] = a8::XValue(meta->max_hp()).GetInt(); + } + } } for (auto& meta : player_meta_list) { @@ -616,6 +636,20 @@ private: item.Init(); ai_hash[a8::MakeInt64(meta.ai_level(), meta.ai_mode())] = &item; } + + for (auto& meta : talent_meta_list) { + MetaData::Talent& item = a8::FastAppend(talent_list); + item.i = &meta; + item.Init(); + talent_hash[meta.talent_id()] = &item; + } + + for (auto& meta : fashion_meta_list) { + MetaData::Fashion& item = a8::FastAppend(fashion_list); + item.i = &meta; + item.Init(); + fashion_hash[meta.id()] = &item; + } } private: @@ -848,3 +882,21 @@ MetaData::AI* MetaMgr::GetAI(int ai_level, int ai_mode) auto itr = loader_->ai_hash.find(a8::MakeInt64(ai_level, ai_mode)); return itr != loader_->ai_hash.end() ? itr->second : nullptr; } + +MetaData::Talent* MetaMgr::GetTalent(int talentid) +{ + auto itr = loader_->talent_hash.find(talentid); + return itr != loader_->talent_hash.end() ? itr->second : nullptr; +} + +MetaData::Fashion* MetaMgr::GetFashion(int fashionid) +{ + auto itr = loader_->fashion_hash.find(fashionid); + return itr != loader_->fashion_hash.end() ? itr->second : nullptr; +} + +std::array* MetaMgr::GetSkinAttr(int skinid) +{ + auto itr = loader_->skinatt_hash.find(skinid); + return itr != loader_->skinatt_hash.end() ? &(itr->second) : nullptr; +} diff --git a/server/gameserver/metamgr.h b/server/gameserver/metamgr.h index 76a9aae..8b0bfa3 100755 --- a/server/gameserver/metamgr.h +++ b/server/gameserver/metamgr.h @@ -49,6 +49,10 @@ class MetaMgr : public a8::Singleton MetaData::Robot* RandRobot(std::set& refreshed_robot_set); MetaData::AI* GetAI(int ai_level, int ai_mode); + MetaData::Talent* GetTalent(int talentid); + MetaData::Fashion* GetFashion(int fashionid); + std::array* GetSkinAttr(int skinid); + int gas_inactive_time = 10; int newbie_gas_inactive_time = 5; int midbrid_gas_inactive_time = 15; diff --git a/server/gameserver/player.cc b/server/gameserver/player.cc index 7f7763c..9825760 100644 --- a/server/gameserver/player.cc +++ b/server/gameserver/player.cc @@ -582,6 +582,7 @@ void Player::LootInteraction(Loot* entity) a8::SetBitFlag(status, HS_AlreadyEquip); ProcNewBieLogic(); } + RecalcBaseAttr(); } break; case EQUIP_TYPE_OLDSKIN: @@ -592,6 +593,7 @@ void Player::LootInteraction(Loot* entity) case EQUIP_TYPE_SKIN: { ProcLootSkin(entity, item_meta); + RecalcBaseAttr(); } break; case EQUIP_TYPE_CAR: @@ -885,6 +887,7 @@ void Player::ProcPrepareItems(const ::google::protobuf::RepeatedField< ::google: add_num = curr_weapon->GetClipVolume(); curr_weapon->ammo = add_num; } + RecalcBaseAttr(); } for (auto& spec_weapon : spec_weapons) { MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquip(spec_weapon.weapon_id); diff --git a/server/gameserver/playermgr.cc b/server/gameserver/playermgr.cc index bdd2646..9d77a42 100644 --- a/server/gameserver/playermgr.cc +++ b/server/gameserver/playermgr.cc @@ -117,8 +117,8 @@ Player* PlayerMgr::CreatePlayerByCMJoin(Player* hum, hum->SetSkinInfo(msg.baseskin()); #endif hum->maxtalent = msg.talent(); - hum->RecalTalentAttr(); - hum->RecalSkinAttr(); + hum->RecalcTalentAttr(); + hum->RecalcSkinAttr(); socket_hash_[socket] = hum; return hum;