aozhiwei baa31b74d5 1
2023-03-30 16:30:04 +08:00

2005 lines
68 KiB
C++

#include "precompile.h"
#include <math.h>
#include <float.h>
#include <a8/mutable_xobject.h>
#include <f8/udplog.h>
#include <f8/utils.h>
#include "cs_proto.pb.h"
#include "cs_msgid.pb.h"
#include "ss_proto.pb.h"
#include "ss_msgid.pb.h"
#include "pbutils.h"
#include "ability.h"
#include "killmgr.h"
#include "room.h"
#include "player.h"
#include "human.h"
#include "weapon.h"
#include "buff.h"
#include "effect.h"
#include "car.h"
#include "hero.h"
#include "loot.h"
#include "obstacle.h"
#include "roomobstacle.h"
#include "skill.h"
#include "skin.h"
#include "typeconvert.h"
#include "team.h"
#include "roommgr.h"
#include "httpproxy.h"
#include "jsondatamgr.h"
#include "gamelog.h"
#include "GGListener.h"
#include "playermgr.h"
#include "matchmgr.h"
#include "frag_mitask.h"
#include "smoke_mitask.h"
#include "stats.h"
#include "mt/Param.h"
#include "mt/Buff.h"
#include "mt/Item.h"
#include "mt/Equip.h"
#include "mt/Hero.h"
#include "mt/MapThing.h"
#include "mt/Skill.h"
#include "mt/SafeArea.h"
#include "mt/Map.h"
#include "mt/PveGemini.h"
#include "mt/PveGeminiMode.h"
#include "mt/PveGeminiContent.h"
static void Creature_FillBuffList(Creature* self, Human* hum, ::google::protobuf::RepeatedPtrField<::cs::MFBuff>* pb_buff_list)
{
self->TraverseBuff
(
[hum, pb_buff_list] (Buff* buff, bool& stop)
{
if (buff->NeedSync(hum) && buff->IsValid()) {
auto p = pb_buff_list->Add();
buff->FillMFBuff(p);
}
});
}
static void Creature_FillEffectList(Creature* self, Human* hum, ::google::protobuf::RepeatedPtrField<::cs::MFEffect>* pb_effect_list)
{
self->TraverseEffect
(
[hum, pb_effect_list] (Effect* effect, bool& stop)
{
auto p = pb_effect_list->Add();
effect->FillMFEffect(p);
});
}
static void Creature_FillSkillList(Creature* self, ::google::protobuf::RepeatedPtrField< cs::MFSkill >*
pb_skill_list)
{
self->TraverseSkill
(
[self, pb_skill_list] (Skill* skill, bool& stop)
{
auto p = pb_skill_list->Add();
skill->FillMFSkill(p);
});
}
static void Human_FillItemList(Human* self,
std::map<int, int>& items,
::google::protobuf::RepeatedPtrField<::cs::MFPair>* pb_item_list)
{
for (auto& pair : items) {
auto p = pb_item_list->Add();
p->set_key(pair.first);
p->set_value(pair.second);
}
}
static void Human_FillBodyState(Human* self, ::google::protobuf::RepeatedPtrField<::cs::MFBodyState>* states)
{
if (!self->pain_killer_timer.expired()) {
int passed_time = (self->room->GetFrameNo() - self->pain_killer_frameno) * FRAME_RATE_MS;
int left_time = std::max(0, self->pain_killer_lastingtime * 1000 - passed_time);
int anodyne_max_time = mt::Param::GetIntParam("anodyne_max_time");
left_time = std::min(left_time, anodyne_max_time * 1000);
cs::MFBodyState* state = states->Add();
state->set_state_type(1);
state->set_left_time(left_time);
state->set_lasting_time(anodyne_max_time * 1000);
}
}
void PBUtils::Ability_FillMFAttrAdditionList(Ability* self, Human* hum, cs::MFActivePlayerData* player_data)
{
_Ability_FillMFAttrAdditionList
(self,
hum,
[player_data] ()
{
return player_data->add_attr_addition();
});
}
void PBUtils::Ability_FillMFAttrAdditionList(Ability* self, Human* hum, cs::MFPlayerFull* full_data)
{
_Ability_FillMFAttrAdditionList
(self,
hum,
[full_data] ()
{
return full_data->add_attr_addition();
});
}
void PBUtils::_Ability_FillMFAttrAdditionList(Ability* self,
Human* hum,
std::function<cs::MFAttrAddition* ()> add_func
)
{
#if 0
for (int attr_id = 0; attr_id < kHAT_End; ++attr_id) {
if (!(attr_id == 12 || attr_id == 33)) {
continue;
}
if (self->buff_attr_flag_[attr_id]) {
auto pb_attr = add_func();
pb_attr->set_attr_id(attr_id);
pb_attr->set_abs_val(self->buff_attr_abs_[attr_id]);
#if 1
pb_attr->set_rate_val(self->buff_attr_rate_[attr_id]);
#else
pb_attr->set_rate_val(self->buff_attr_rate_[attr_id] * 100);
#endif
}
}
#endif
}
/*
master.name
killer.name
dead.name
weapon.name
weapon.text_icon
image.id:
*/
void KillMgr::OnHumanDead(Human* dead_hum, KillInfo* info)
{
RollMsgHintInfo hint_info;
std::shared_ptr<cs::SMRollMsg> pb_msg = std::make_shared<cs::SMRollMsg>();
FillHintInfo(dead_hum, info, hint_info);
PreprocessRollMsg(pb_msg, hint_info);
BoradcastRollMsg(dead_hum, info, 0, pb_msg);
}
void KillMgr::PreprocessRollMsg(std::shared_ptr<cs::SMRollMsg> pb_msg,
RollMsgHintInfo& hint_info)
{
if (hint_info.hint_template) {
for (auto& tuple : *hint_info.hint_template) {
int el_type = std::get<0>(tuple);
std::string el_val = std::get<1>(tuple);
switch (el_type) {
case kTextElement:
{
auto e = pb_msg->add_elements();
e->set_element_type(el_type);
e->mutable_union_obj_1()->set_text(el_val);
}
break;
case kImageElement:
{
auto e = pb_msg->add_elements();
e->set_element_type(el_type);
e->mutable_union_obj_2()->set_id(a8::XValue(el_val));
}
break;
default:
{
std::string text;
if (hint_info.Replace(el_type, text)) {
if (el_type == kFieldIdxWeaponTextIcon) {
auto e = pb_msg->add_elements();
e->set_element_type(kImageElement);
e->mutable_union_obj_2()->set_id(a8::XValue(text));
} else {
auto e = pb_msg->add_elements();
e->set_element_type(kTextElement);
e->mutable_union_obj_1()->set_text(text);
}
}
}
break;
}
}
}
}
void KillMgr::BoradcastRollMsg(Human* dead_hum,
KillInfo* info,
int killer_team_id,
std::shared_ptr<cs::SMRollMsg> pb_msg)
{
std::shared_ptr<KillInfo> info_copy = std::make_shared<KillInfo>();
*info_copy = *info;
std::shared_ptr<cs::SMRollMsg> pb_msg_copy = std::make_shared<cs::SMRollMsg>();
pb_msg_copy = pb_msg;
dead_hum->room->xtimer.SetTimeoutEx
(
0,
[dead_hum, info_copy, pb_msg_copy, killer_team_id]
(int event, const a8::Args* args) mutable
{
if (a8::TIMER_EXEC_EVENT == event) {
KillMgr::Instance()->BoradcastRollMsgCb
(dead_hum,
info_copy.get(),
killer_team_id,
pb_msg_copy);
}
},
&dead_hum->xtimer_attacher);
}
void KillMgr::BoradcastRollMsgCb(Human* dead_hum,
KillInfo* info,
int killer_team_id,
std::shared_ptr<cs::SMRollMsg> pb_msg)
{
dead_hum->room->TraversePlayerList
(
[dead_hum, info, &pb_msg, killer_team_id]
(Player* hum) -> bool
{
for (int i = 0; i < pb_msg->elements_size(); ++i) {
auto element = pb_msg->mutable_elements(i);
if (element->element_type() == kTextElement) {
int color = element->mutable_union_obj_1()->color();
if (info->killer_id == hum->GetUniId()){
color = mt::Param::s().self_kill_color;
} else if (killer_team_id == hum->team_id) {
color = mt::Param::s().teammate_kill_color;
} else if (dead_hum == hum) {
color = mt::Param::s().self_bekill_color;
} else if (dead_hum->team_id == hum->team_id) {
color = mt::Param::s().teammate_bekill_color;
}
if (element->mutable_union_obj_1()->color() != color) {
element->mutable_union_obj_1()->set_color(color);
}
}
}
hum->SendNotifyMsg(*pb_msg);
return true;
});
}
void Weapon::ToPB(Creature* c, cs::MFWeapon* pb_obj)
{
pb_obj->set_weapon_uniid(a8::XValue(weapon_uniid).GetString());
pb_obj->set_weapon_id(weapon_id);
if (weapon_uniid && weapon_lv == 0) {
int p_weapon_lv = 1;
int p_quality = 1;
c->GetBattleContext()->GetWeaponLvQuality(weapon_uniid, p_weapon_lv, p_quality);
weapon_lv = p_weapon_lv;
}
pb_obj->set_weapon_lv(std::max(1, weapon_lv));
pb_obj->set_ammo(ammo);
pb_obj->set_volume(GetClipVolume(c));
}
void Buff::FillMFBuff(cs::MFBuff* buff_pb)
{
buff_pb->set_buff_id(meta->buff_id());
buff_pb->set_left_time(GetLeftTime());
buff_pb->set_lasting_time(GetLastingTime());
buff_pb->set_buff_uniid(buff_uniid);
if (res_scale_frameno > 0) {
buff_pb->set_res_scale(res_scale);
}
if (owner->IsHuman() &&
(meta->buff_effect() == kBET_Driver ||
meta->buff_effect() == kBET_Passenger)) {
}
}
void Effect::FillMFEffect(cs::MFEffect* effect_pb)
{
effect_pb->set_effect_id(effect_id);
effect_pb->set_effect_uniid(effect_uniid);
}
void Car::FillMFObjectPart(Room* room, Human* hum, cs::MFObjectPart* part_data)
{
part_data->set_object_type(ET_Car);
cs::MFCarPart* p = part_data->mutable_union_obj_11();
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
TypeConvert::ToPb(GetAttackDir(), p->mutable_dir());
}
void Car::FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data)
{
full_data->set_object_type(ET_Car);
cs::MFCarFull* p = full_data->mutable_union_obj_11();
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
TypeConvert::ToPb(GetAttackDir(), p->mutable_dir());
p->set_car_id(meta->id());
p->set_heroid(meta->heroid());
p->set_driver(driver_ ? driver_->GetUniId() : 0);
for (auto hum : passengers_) {
auto less_data = p->add_passengers();
hum->FillMFObjectLess(room, hum, less_data);
}
p->set_born_frameno(ceil(born_frameno_ / 2.0));
p->set_dead(dead);
p->set_health(GetHP());
p->set_max_health(GetMaxHP());
p->set_oil(cur_oil_);
p->set_max_oil(meta->max_oil());
if (GetCurrWeapon()) {
p->set_bullet_num(GetCurrWeapon()->ammo);
} else {
p->set_bullet_num(0);
}
p->set_seat_num(meta->_int_param2);
Creature_FillBuffList(this, hum, p->mutable_buff_list());
Creature_FillEffectList(this, hum, p->mutable_effect_list());
p->set_team_id(team_id);
}
void Hero::FillMFObjectPart(Room* room, Human* hum, cs::MFObjectPart* part_data)
{
part_data->set_object_type(ET_Hero);
cs::MFHeroPart* p = part_data->mutable_union_obj_10();
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
TypeConvert::ToPb(GetAttackDir(), p->mutable_dir());
}
void Hero::FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data)
{
full_data->set_object_type(ET_Hero);
cs::MFHeroFull* p = full_data->mutable_union_obj_10();
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
TypeConvert::ToPb(GetAttackDir(), p->mutable_dir());
p->set_heroid(meta->id());
p->set_master_uniid(master.Get() ? master.Get()->GetUniId() : 0);
p->set_dead(dead);
p->set_health(GetHP());
p->set_max_health(GetMaxHP());
Creature_FillBuffList(this, hum, p->mutable_buff_list());
Creature_FillEffectList(this, hum, p->mutable_effect_list());
p->set_team_id(team_id);
}
void Loot::FillMFObjectPart( Room* room, Human* hum, cs::MFObjectPart* part_data)
{
part_data->set_object_type(ET_Loot);
cs::MFLootPart* p = part_data->mutable_union_obj_5();
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
}
void Loot::FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data)
{
full_data->set_object_type(ET_Loot);
cs::MFLootFull* p = full_data->mutable_union_obj_5();
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
TypeConvert::ToPb(born_pos, p->mutable_born_pos());
p->set_item_id(item_id);
p->set_count(count);
p->set_item_level(item_level);
if (show_anim && room->GetFrameNo() <= create_frame_no + 1) {
p->set_show_anim(true);
}
}
void Obstacle::FillMFObjectPart(Room* room, Human* hum, cs::MFObjectPart* part_data)
{
part_data->set_object_type(ET_Obstacle);
cs::MFObstaclePart* p = part_data->mutable_union_obj_2();
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
if (std::abs(scale - 1.0f) > 0.00001f) {
p->set_scale(scale);
}
}
void Obstacle::FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data)
{
full_data->set_object_type(ET_Obstacle);
if (IsClientCached(hum)) {
int object_flags = 0;
a8::SetBitFlag(object_flags, kOfReadCache);
full_data->set_obj_uniid(GetUniId());
full_data->set_object_flags(object_flags);
return;
}
cs::MFObstacleFull* p = full_data->mutable_union_obj_2();
if (CanClientCache(hum)) {
int object_flags = 0;
a8::SetBitFlag(object_flags, kOfWriteCache);
#if 0
full_data->set_obj_uniid(GetUniId());
#endif
full_data->set_object_flags(object_flags);
AddClientCache(hum);
}
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
if (std::abs(scale - 1.0f) > 0.00001f) {
p->set_scale(scale);
}
p->set_obstacle_id(meta->thing_id());
p->set_health(GetHealth(room));
p->set_dead(IsDead(room));
p->set_dead_at_thisframe(IsDead(room) ? GetDeadFrameNo(room) <= room->GetFrameNo() : false);
if (!IsPermanent()) {
RoomObstacle* ob = (RoomObstacle*)this;
p->set_born_frameno(ceil(ob->born_frameno / 2.0));
}
if (meta->thing_type() == kObstacleHideHouse) {
#if 0
if (GetInteractionData(hum)) {
#if 1
p->set_button_name("3");
#else
p->set_button_name("脱离");
#endif
} else {
#if 1
p->set_button_name("2");
#else
p->set_button_name("躲藏");
#endif
}
#endif
} else {
if (IsOpenInteraction()) {
if (IsDead(hum->room)) {
p->set_button_name("");
} else {
#if 1
p->set_button_name("1");
#else
p->set_button_name("开启");
#endif
}
}
}
if (meta->thing_type() == kObstacleStrengthenWall) {
p->set_rotate(rotate_ * 180);
}
p->set_team_id(GetTeamId(room));
}
void Skill::FillMFSkill(cs::MFSkill* skill_pb)
{
skill_pb->set_skill_id(meta->skill_id());
skill_pb->set_left_time(GetLeftTime());
skill_pb->set_cd_time(GetCd());
skill_pb->set_curr_times(GetCurrTimes());
skill_pb->set_max_times(GetMaxTimes());
if (minor_type_) {
int minor_left_time = std::max
(0,
minor_cd_time_ - (int)((owner->room->GetFrameNo() - minor_frameno_) * FRAME_RATE_MS));
skill_pb->set_minor_type(minor_type_);
skill_pb->set_minor_left_time(minor_left_time);
skill_pb->set_minor_cd_time(minor_cd_time_);
skill_pb->set_left_time(GetCd());
#ifdef DEBUG
a8::XPrintf("type: %d, lefttime:%d cd_time:%d\n", {
minor_type_,
minor_left_time,
minor_cd_time_
});
#endif
}
}
void Skin::ToPB(cs::MFSkin* pb_obj)
{
pb_obj->set_skin_id(skin_id);
pb_obj->set_skin_lv(skin_lv);
}
void PBUtils::Human_SendSMPvePassWave(Human* self, int new_wave, int pve_max_wave, int wait_time)
{
cs::SMPvePassWave notify_msg;
notify_msg.set_new_wave(new_wave);
notify_msg.set_pve_max_wave(pve_max_wave);
notify_msg.set_pve_max_wave(wait_time);
self->SendNotifyMsg(notify_msg);
}
void Human::FillMFObjectPart(Room* room, Human* hum, cs::MFObjectPart* part_data)
{
part_data->set_object_type(ET_Player);
cs::MFPlayerPart* p = part_data->mutable_union_obj_1();
p->set_obj_uniid(GetUniId());
p->set_speed(GetSpeed() * SERVER_FRAME_RATE);
TypeConvert::ToPb(GetPos(), p->mutable_pos());
TypeConvert::ToPb(GetAttackDir(), p->mutable_dir());
}
void Human::FillMFObjectLess(Room* room, Human* hum, cs::MFPlayerFull* full_data)
{
cs::MFPlayerFull* p = full_data;
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
TypeConvert::ToPb(GetAttackDir(), p->mutable_dir());
p->set_health(GetHP());
p->set_max_health(GetMaxHP());
p->set_dead(dead);
p->set_downed(downed);
p->set_disconnected(disconnected);
for (auto itr : skins) {
auto skin = p->add_skin();
itr.ToPB(skin);
}
p->set_backpack(backpack);
p->set_helmet(helmet);
p->set_chest(chest);
p->set_shoot_offset_x(shoot_offset.x);
p->set_shoot_offset_y(shoot_offset.y);
p->set_level(GetBattleContext()->GetLevel());
p->set_hero_level(GetBattleContext()->GetHeroLevel());
p->set_hero_level(GetBattleContext()->GetHeroLevel());
GetCurrWeapon()->ToPB(this, p->mutable_weapon());
PBUtils::Ability_FillMFAttrAdditionList(GetAbility().get(), this, p);
if (GetCar()) {
p->set_car_uniid(GetCar()->car_uniid);
p->set_car_seat(GetSeat());
} else {
p->set_car_uniid(0);
p->set_car_seat(0);
}
}
void Human::FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data)
{
full_data->set_object_type(ET_Player);
cs::MFPlayerFull* p = full_data->mutable_union_obj_1();
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
TypeConvert::ToPb(GetAttackDir(), p->mutable_dir());
p->set_health(GetHP());
p->set_level(GetBattleContext()->GetLevel());
p->set_Hero_level(GetBattleContext()->GetHeroLevel());
p->set_max_health(GetMaxHP());
p->set_dead(dead);
p->set_downed(downed);
p->set_disconnected(disconnected);
p->set_speed(GetSpeed() * SERVER_FRAME_RATE);
for (auto itr : skins) {
auto skin = p->add_skin();
itr.ToPB(skin);
}
p->set_backpack(backpack);
p->set_helmet(helmet);
p->set_chest(chest);
p->set_team_member_num(GetTeam()->GetMemberNum());
GetCurrWeapon()->ToPB(this, p->mutable_weapon());
p->set_energy_shield(energy_shield);
p->set_gemstone(gemstone);
p->set_shoot_offset_x(shoot_offset.x);
p->set_shoot_offset_y(shoot_offset.y);
#if 1
{
p->set_max_energy_shield(max_energy_shield);
}
#endif
if (guild_id != 0) {
p->set_guild_id(guild_id);
}
if (vip_lv != 0) {
p->set_vip_lv(vip_lv);
}
if (head_frame != 0) {
p->set_head_frame(head_frame);
}
if (sex != 0) {
p->set_sex(sex);
}
if (!user_data.empty()) {
p->set_user_data(user_data);
}
p->set_vip(vip);
p->set_kill_count(stats->kills);
if (emoji1 != 0) {
p->set_emoji1(emoji1);
}
if (emoji2 != 0) {
p->set_emoji2(emoji2);
}
if (parachute != 0) {
p->set_parachute(parachute);
}
if (IsPlayer()) {
int i = 0;
}
if (follow_target.Get()) {
p->set_follow_target(follow_target.Get()->GetUniId());
#ifdef DEBUG1
a8::XPrintf("DoFollow1 %d->%d\n", {GetUniId(), follow_target.Get()->GetUniId()});
#endif
}
Human_FillBodyState(this, p->mutable_states());
Creature_FillBuffList(this, hum, p->mutable_buff_list());
Creature_FillEffectList(this, hum, p->mutable_effect_list());
Creature_FillSkillList(this, p->mutable_skill_list());
if (dead) {
p->set_killer_name(stats->killer_name);
p->set_killer_id(stats->killer_id);
if (real_dead){
p->set_can_revive(false);
} else {
p->set_can_revive(true);
int countdown = 0;
if (!revive_timer.expired()) {
countdown = std::ceil(room->xtimer.GetRemainTime(revive_timer) / SERVER_FRAME_RATE);
} else {
f8::UdpLog::Instance()->Warning
("Human::FillMFObjectfull revive_timer == nullptr "
"dead_frameno:%d dead_times:%d alive_count:%d "
"room.frameno:%d",
{
dead_frameno,
stats->dead_times,
room->AliveCount(),
room->GetFrameNo()
});
}
countdown = std::max(0, countdown - kReviveTimeAdd);
p->set_revive_countdown(countdown);
}
}
p->set_charid(meta->id());
if (GetCar()) {
p->set_car_uniid(GetCar()->car_uniid);
p->set_car_seat(GetSeat());
} else {
p->set_car_uniid(0);
p->set_car_seat(0);
}
if (GetBuffByEffectId(kBET_HoldShield)) {
p->set_shield_hp(shield_hp_);
p->set_shield_max_hp(shield_max_hp_);
}
p->set_team_id(team_id);
}
void Human::FillMFObjectImage(Room* room, Human* hum, cs::MFCharacterImage* image_data)
{
image_data->set_obj_uniid(GetUniId());
image_data->set_cur_weapon_idx(GetCurrWeapon()->weapon_idx);
GetCurrWeapon()->ToPB(this, image_data->mutable_weapon());
}
void Human::FillMFPlayerStats(cs::MFPlayerStats* stats_pb)
{
stats_pb->set_player_id(GetUniId());
stats_pb->set_player_avatar_url(avatar_url);
stats_pb->set_charid(meta->id());
stats_pb->set_team_id(team_id);
stats_pb->set_nickname(name);
int alive_time = room->GetFrameNo() * FRAME_RATE_MS;
if (!dead) {
stats_pb->set_time_alive(alive_time);
} else {
alive_time = (dead_frameno - room->GetBattleStartFrameNo()) * FRAME_RATE_MS;
if (room->GetBattleStartFrameNo() <= 0) {
alive_time = 0;
}
alive_time = std::max(alive_time, 0);
stats_pb->set_time_alive(alive_time);
}
stats_pb->set_kills(stats->kills);
stats_pb->set_damage_amount(stats->damage_amount_out);
stats_pb->set_heal_amount(stats->heal_amount);
stats_pb->set_assist(stats->assist);
stats_pb->set_rescue(stats->rescue_member);
stats_pb->set_pve_wave(stats->pve_wave);
stats_pb->set_revive(stats->revive);
stats_pb->set_rank_chg(stats->rank_chg);
stats_pb->set_history_time_alive(stats->history_time_alive);
stats_pb->set_history_kills(stats->history_kills);
stats_pb->set_history_damage_amount(stats->history_damage_amount);
stats_pb->set_history_heal_amount(stats->history_heal_amount);
stats_pb->set_gold(stats->gold);
#if 1
stats_pb->set_score(stats->pve_rank_score);
#else
stats_pb->set_score(stats->score);
#endif
stats_pb->set_pass_score(stats->pass_score);
stats_pb->set_rank_score(stats->rank_score);
stats_pb->set_has_pass(has_pass);
stats_pb->set_dead(dead);
stats_pb->set_killer_id(stats->killer_id);
stats_pb->set_killer_name(stats->killer_name);
{
Player* killer = room->GetPlayerByUniId(stats->killer_id);
if (killer) {
stats_pb->set_killer_avatar_url(killer->avatar_url);
stats_pb->set_killer_account_id(killer->account_id);
} else {
stats_pb->set_killer_avatar_url("");
stats_pb->set_killer_account_id("");
}
}
stats_pb->set_account_id(account_id);
if (guild_id != 0) {
stats_pb->set_guild_id(guild_id);
}
stats_pb->set_rescue_guild_member(stats->rescue_guild_member);
for (auto& pair : stats->items) {
auto p = stats_pb->add_items();
p->set_key(pair.first);
p->set_value(pair.second);
}
for (auto& pair : stats->extra_drop) {
auto p = stats_pb->add_extra_drop();
p->set_key(pair.first);
p->set_value(pair.second);
}
if (vip_lv != 0) {
stats_pb->set_vip_lv(vip_lv);
}
if (head_frame != 0) {
stats_pb->set_head_frame(head_frame);
}
if (sex != 0) {
stats_pb->set_sex(sex);
}
{
for (auto& skin : skins) {
auto pb_skin = stats_pb->add_skin();
skin.ToPB(pb_skin);
}
}
TypeConvert::ToPb(stats->pb_hero_stats, stats_pb->mutable_hero_stats());
for (auto& itr : stats->pb_weapons_stats) {
TypeConvert::ToPb(itr, stats_pb->add_weapons_stats());
}
}
void Human::FillMFTeamData(Human* hum, cs::MFTeamData* team_data, bool is_game_over)
{
{
last_sync_teamdata_frameno_ = room->GetFrameNo();
team_data->set_team_id(team_id);
team_data->set_player_id(GetUniId());
team_data->set_hero_id(meta->id());
team_data->set_level(hum->GetBattleContext()->GetLevel());
team_data->set_hero_level(hum->GetBattleContext()->GetHeroLevel());
team_data->set_score(stats->pve_rank_score);
if (is_game_over || !real_dead || room->GetFrameNo() - GetRealDeadFrameNo(room) < 4) {
TypeConvert::ToPb(GetPos(), team_data->mutable_pos());
TypeConvert::ToPb(GetAttackDir(), team_data->mutable_dir());
team_data->set_health(GetHP());
team_data->set_max_health(GetMaxHP());
team_data->set_dead(dead);
team_data->set_downed(downed);
}
#if 1
team_data->set_dead(dead);
#endif
if (is_game_over || room->GetGasData().GetGasMode() == GasInactive) {
team_data->set_name(name);
}
if (room->GetGasData().GetGasMode() != GasInactive &&
room->GetFrameNo() - room->GetBattleStartFrameNo() < 4) {
team_data->set_name(name);
team_data->set_disconnected(socket_handle == 0);
}
if (is_game_over) {
team_data->set_account_id(account_id);
team_data->set_avatar_url(avatar_url);
team_data->set_user_value1(user_value1);
team_data->set_user_value2(user_value2);
team_data->set_user_value3(user_value3);
if (guild_id != 0) {
team_data->set_guild_id(guild_id);
}
}
if (vip_lv != 0) {
team_data->set_vip_lv(vip_lv);
}
if (head_frame != 0) {
team_data->set_head_frame(head_frame);
}
if (sex != 0) {
team_data->set_sex(sex);
}
if (room->GetGasData().GetGasMode() == GasInactive ||
room->GetFrameNo() - room->GetBattleStartFrameNo() < 4) {
team_data->set_user_data(user_data);
}
#if 0
if (HasBuffEffect(kBET_Jump) && GetTeam()) {
bool can_follow = hum->CanFollow(this);
if (can_follow) {
team_data->set_can_follow(can_follow);
}
}
#endif
{
for (auto itr : skins) {
auto skin = team_data->add_skin();
itr.ToPB(skin);
}
}
}
}
void Human::FillSMGameOver(cs::SMGameOver& msg)
{
if (GetTeam()->already_report_battle) {
msg.mutable_settlement_new()->set_settlement_status(1);
auto p = msg.mutable_settlement_new();
p->set_version(20230321);
p->set_team_id(GetTeam()->GetTeamId());
p->set_room_uuid(a8::XValue(room->GetRoomUuid()).GetString());
p->set_room_mode(room->IsPveRoom() ? 1 : 0);
p->set_team_mode(1);
p->set_game_over(room->IsGameOver() ? 1 : 0);
p->set_victory(stats->victory ? 1 : 0);
p->set_watchable(false);
p->set_map_id(room->GetMapMeta()->map_id());
p->set_battle_uuid(a8::XValue(battle_uuid).GetString());
if (room->IsPveRoom()) {
p->set_pve_settlement_color(stats->settlement_color);
p->set_pve_wave(room->pve_data.GetPassedWave());
p->set_pve_max_wave(room->pve_data.max_wave);
p->set_pve_instance_id(room->pve_instance->gemini_id());
} else {
p->set_pvp_settlement_type(stats->pvp_settlement_type);
p->set_pvp_settlement_color(stats->settlement_color);
p->set_pvp_team_rank(GetTeam()->team_rank);
p->set_pvp_total_human_num(room->GetHumanNum());
p->set_pvp_alive_human_num(room->AliveCount());
p->set_pvp_total_team_num(room->GetTeamNum());
p->set_pvp_match_mode(0);
}
GetTeam()->FillSMGameOver(msg);
return;
} else {
msg.mutable_settlement_new()->set_settlement_status(0);
auto p = msg.mutable_settlement_new();
p->set_version(20230321);
p->set_team_id(GetTeam()->GetTeamId());
p->set_room_uuid(a8::XValue(room->GetRoomUuid()).GetString());
p->set_room_mode(room->IsPveRoom() ? 1 : 0);
p->set_team_mode(1);
p->set_game_over(room->IsGameOver() ? 1 : 0);
p->set_victory(stats->victory ? 1 : 0);
{
int alive_team_num = room->GetAliveTeamNum();
if (stats->victory) {
p->set_watchable(false);
} else {
if (room->GetAliveTeamNum() > 1) {
p->set_watchable(true);
} else {
if (room->IsPveRoom()) {
p->set_watchable(!room->IsGameOver());
} else {
p->set_watchable(false);
}
}
}
}
p->set_map_id(room->GetMapMeta()->map_id());
p->set_battle_uuid(a8::XValue(battle_uuid).GetString());
if (room->IsPveRoom()) {
p->set_pve_settlement_color(stats->settlement_color);
p->set_pve_wave(room->pve_data.GetPassedWave());
p->set_pve_max_wave(room->pve_data.max_wave);
p->set_pve_instance_id(room->pve_instance->gemini_id());
} else {
p->set_pvp_settlement_type(stats->pvp_settlement_type);
p->set_pvp_settlement_color(stats->settlement_color);
p->set_pvp_team_rank(GetTeam()->team_rank);
p->set_pvp_total_human_num(room->GetHumanNum());
p->set_pvp_alive_human_num(room->AliveCount());
p->set_pvp_total_team_num(room->GetTeamNum());
p->set_pvp_match_mode(0);
}
GetTeam()->FillSMGameOver(msg);
return;
}
int alive_team_num = room->GetAliveTeamNum();
if (stats->victory) {
msg.set_watchable(false);
} else {
if (room->GetAliveTeamNum() > 1) {
msg.set_watchable(true);
} else {
if (room->IsPveRoom()) {
msg.set_watchable(!room->IsGameOver());
} else {
msg.set_watchable(false);
}
}
}
msg.set_map_id(room->GetMapMeta()->map_id());
msg.set_team_id(team_id);
msg.set_team_rank(GetTeam()->team_rank);
msg.set_personal_rank(stats->rank);
if (room->IsPveRoom()) {
stats->pve_wave = room->pve_data.GetPassedWave();
msg.set_game_over(room->IsGameOver());
} else {
msg.set_game_over(room->IsGameOver() || (alive_team_num == 1));
}
msg.set_victory(stats->victory);
msg.set_room_uuid(a8::XValue(room->GetRoomUuid()));
msg.set_total_human_num(room->GetHumanNum());
msg.set_alive_human_num(room->AliveCount());
if (GetTeam()) {
GetTeam()->TraverseMembers
(
[this, &msg] (Human* member) -> bool
{
{
member->FillMFTeamData(this, msg.add_team_data(), true);
cs::MFPlayerStats* p = msg.add_player_stats();
member->FillMFPlayerStats(p);
}
return true;
});
}
{
msg.set_total_team_num(room->GetTeamNum());
if (room->IsPveRoom()) {
msg.set_pve_wave(room->pve_data.GetPassedWave());
msg.set_pve_max_wave(room->pve_data.max_wave);
msg.set_pve_instance_id(room->pve_instance->gemini_id());
msg.set_pve_boss_killed(room->pve_data.boss_state == 2 ? 1 : 0);
}
}
TypeConvert::ToPb(stats->over_reward, msg.mutable_reward());
{
if (!stats->over_reward.total_ceg.empty()) {
auto p = msg.add_spoils_items();
p->add_values("10001");
p->add_values(stats->over_reward.total_ceg);
}
for (auto& tuple : stats->over_reward.items) {
auto p = msg.add_spoils_items();
p->add_values(a8::XValue(std::get<0>(tuple)).GetString());
p->add_values(std::get<1>(tuple));
}
}
{
if (room->IsPveRoom()) {
msg.set_mode(GetTeam()->GetMemberNum() <= 1 ? 1 : 2);
msg.set_my_rank(room->pve_data.GetPassedWave());
msg.set_max_rank(room->pve_data.max_wave);
} else {
if (GetTeam()->GetMemberNum() <= 1) {
msg.set_mode(1);
msg.set_my_rank(stats->rank);
msg.set_max_rank(room->GetHumanNum());
} else {
if (GetTeam()->team_rank <= 0) {
msg.set_mode(1);
msg.set_my_rank(stats->rank);
msg.set_max_rank(room->GetHumanNum());
} else {
msg.set_mode(2);
msg.set_my_rank(GetTeam()->team_rank);
msg.set_max_rank(room->GetTeamNum());
}
}
}
}
#if 1
if (room->GetBattleStartFrameNo() <= 0 &&
dead_frameno) {
msg.set_team_rank(0);
msg.set_personal_rank(0);
msg.set_my_rank(0);
}
#endif
if (IsPlayer()) {
Player* p = (Player*)this;
if (!p->settlement) {
p->settlement = std::make_shared<cs::MFSettlement>();
FillMFSettlement(&msg, p->settlement.get());
}
*msg.mutable_settlement() = *p->settlement;
}
}
void Human::FillMFActivePlayerData(cs::MFActivePlayerData* player_data)
{
#ifdef DEBUG1
a8::XPrintf("FillMFActivePlayerData isPlayer:%d id:%d name:%s need_sync_active_player:%d send_msg_times:%d\n",
{
IsPlayer() ? 1 : 0,
GetUniId(),
name,
need_sync_active_player ? 1 : 0,
send_msg_times
});
#endif
{
player_data->set_action_type(action_type);
if (action_type != AT_None) {
int duration = std::max(0,
action_duration -
(int)((room->GetFrameNo() - action_frameno) * 1.0f / SERVER_FRAME_RATE) * 1000
);
player_data->set_action_item_id(action_item_id);
player_data->set_action_duration(duration);
player_data->set_action_target_id(action_target_id);
player_data->set_action_frameno(action_frameno);
#if 1
if (action_type == AT_UseItem) {
const mt::Equip* item_meta = mt::Equip::GetByIdBySlotId(action_item_id);
if (item_meta) {
player_data->set_action_item_id(item_meta->id());
int action_param = 0;
switch (action_item_id) {
case IS_HEALTHKIT:
case IS_SHEN_BAO:
{
switch (std::get<0>(item_meta->_heal)) {
case 1:
{
action_param = std::get<1>(item_meta->_heal);
}
break;
case 2:
{
action_param = std::get<1>(item_meta->_heal) * GetMaxHP();
}
break;
default:
{
}
break;
}
}
break;
case IS_PAIN_KILLER:
{
switch (std::get<0>(item_meta->_heal)) {
case 1:
{
action_param = std::get<1>(item_meta->_heal) * item_meta->time();
}
break;
case 2:
{
action_param = std::get<1>(item_meta->_heal) * GetMaxHP()
* item_meta->time();
}
break;
default:
{
}
break;
}
}
break;
default:
{
}
break;
}
player_data->set_action_param(action_param);
}
}
#endif
}
}
#if 1
for (auto itr : skins) {
auto skin = player_data->add_skin();
itr.ToPB(skin);
}
#else
skin.ToPB(player_data->mutable_skin());
#endif
player_data->set_backpack(backpack);
player_data->set_helmet(helmet);
player_data->set_chest(chest);
player_data->set_health(GetHP());
player_data->set_max_health(GetMaxHP());
player_data->set_cur_weapon_idx(GetCurrWeapon()->weapon_idx);
player_data->set_cur_scope(curr_scope_idx);
if (HasBuffEffect(kBET_InWater)) {
player_data->set_dive_oxygen_max(mt::Param::s().dive_oxygen_total);
player_data->set_dive_oxygen_curr(oxygen_);
}
for (auto& weapon : weapons) {
auto p = player_data->add_weapons();
weapon.ToPB(this, p);
}
for (auto& inv : GetInventoryData()) {
player_data->add_inventory(inv.num);
}
player_data->set_energy_shield(energy_shield);
#if 1
{
player_data->set_max_energy_shield(max_energy_shield);
}
#endif
Human_FillBodyState(this, player_data->mutable_states());
Human_FillItemList(this, this->items_, player_data->mutable_items());
Creature_FillSkillList(this, player_data->mutable_skill_list());
player_data->set_shoot_offset_x(shoot_offset.x);
player_data->set_shoot_offset_y(shoot_offset.y);
PBUtils::Ability_FillMFAttrAdditionList(GetAbility().get(), this, player_data);
if (GetBuffByEffectId(kBET_HoldShield)) {
player_data->set_shield_hp(shield_hp_);
player_data->set_shield_max_hp(shield_max_hp_);
}
player_data->set_gemstone(gemstone);
}
void Human::ProcThrowDmg(int throw_uniid)
{
auto itr = pending_throw_bomb.find(throw_uniid);
if (itr == pending_throw_bomb.end()) {
return;
}
auto context = itr->second;
glm::vec3 bomb_pos;
glm::vec3 bomb_dir;
TypeConvert::FromPb(bomb_pos, &context->pos());
TypeConvert::FromPb(bomb_dir, &context->dir());
if (!(std::abs(bomb_dir.x) > FLT_EPSILON ||
std::abs(bomb_dir.y) > FLT_EPSILON ||
std::abs(bomb_dir.z) > FLT_EPSILON
)) {
pending_throw_bomb.erase(throw_uniid);
return;
}
GlmHelper::Normalize(bomb_dir);
glm::vec3 target_pos = bomb_pos + bomb_dir * context->fly_distance();
const mt::Equip* equip_meta = mt::Equip::GetById(context->weapon_id());
if (equip_meta && equip_meta->_inventory_slot() > 0) {
auto proc_frag_func =
[this, equip_meta, context, bomb_pos, bomb_dir, target_pos] ()
{
std::shared_ptr<FragMiTask> task = std::make_shared<FragMiTask>();
task->room = room;
task->sender.Attach(this);
task->bomb_pos.FromGlmVec3(target_pos);
task->gun_meta = equip_meta;
task->meta = equip_meta;
task->atk = equip_meta->_atk;
task->explosion_range = equip_meta->explosion_range();
task->Initialize();
int delay_time = equip_meta->missiles_time();;
room->xtimer.SetTimeoutEx
(std::max(1, (int)(delay_time / FRAME_RATE_MS)),
[task] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
task->Done();
}
},
&task->xtimer_attacher);
};
auto proc_smoke_func =
[this, equip_meta, context, bomb_pos, bomb_dir, target_pos] ()
{
const mt::Buff* buff_meta = mt::Buff::GetById(HUNLUAN_BUFFID);
if (!buff_meta) {
return;
}
std::shared_ptr<SmokeMiTask> task = std::make_shared<SmokeMiTask>();
task->room = room;
task->bomb_pos.FromGlmVec3(target_pos);
task->buff_meta = buff_meta;
task->gun_meta = equip_meta;
task->Initialize();
auto task_wp = std::weak_ptr<SmokeMiTask>(task);
room->xtimer.SetIntervalEx
(SERVER_FRAME_RATE / 2,
[task_wp] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
if (!task_wp.expired()) {
task_wp.lock()->Check();
}
}
},
&task->xtimer_attacher);
room->xtimer.SetTimeoutEx
(SERVER_FRAME_RATE * mt::Param::GetIntParam("smoke_duration", 10),
[task] (int event, const a8::Args* args)
{
if (a8::TIMER_DELETE_EVENT == event) {
task->Done();
}
},
&room->xtimer_attacher_);
{
std::shared_ptr<Ability> old_context_ability = context_ability;
glm::vec3 old_context_dir = context_dir;
Position old_context_pos = context_pos;
context_dir = bomb_dir;
context_pos.FromGlmVec3(target_pos);
context_ability = nullptr;
const mt::Buff * buff_meta = mt::Buff::GetById(equip_meta->buffid());
if (buff_meta) {
AddBuff(this,
buff_meta
);
}
context_dir = old_context_dir;
context_pos = old_context_pos;
context_ability = old_context_ability;
}
};
auto proc_molotor_cocktail_func =
[this, equip_meta, context, bomb_pos, bomb_dir, target_pos] ()
{
std::shared_ptr<Ability> old_context_ability = context_ability;
glm::vec3 old_context_dir = context_dir;
Position old_context_pos = context_pos;
context_dir = bomb_dir;
context_pos.FromGlmVec3(target_pos);
context_ability = nullptr;
const mt::Buff * buff_meta = mt::Buff::GetById(equip_meta->buffid());
if (buff_meta) {
AddBuff(this,
buff_meta
);
}
context_dir = old_context_dir;
context_pos = old_context_pos;
context_ability = old_context_ability;
};
switch (equip_meta->_inventory_slot()) {
case IS_FRAG:
{
proc_frag_func();
}
break;
case IS_SMOKE:
{
proc_smoke_func();
}
break;
case IS_MOLOTOR_COCKTAIL:
{
proc_molotor_cocktail_func();
}
break;
default:
{
}
break;
}//end switch
}
pending_throw_bomb.erase(throw_uniid);
}
void Human::FillMFGasData(cs::MFGasData* gas_data)
{
gas_data->set_mode(room->GetGasData().GetGasMode());
if (room->GetGasData().GetGasMode() == GasInactive) {
long long duration = room->GetGasInactiveTime() * SERVER_FRAME_RATE -
(room->GetFrameNo() - room->GetGasData().gas_start_frameno);
gas_data->set_duration(std::max(duration * 50, (long long)1000) / 1000);
} else if (room->GetGasData().GetGasMode() == GasJump) {
gas_data->set_duration(0);
} else if (room->GetGasData().GetGasMode() == GasMoving) {
if (room->GetGasData().new_area_meta->shrink_speed() > 0.01f) {
long long duration = (room->GetGasData().old_area_meta->rad() - room->GetGasData().new_area_meta->rad()) /
room->GetGasData().new_area_meta->shrink_speed();
++duration;
gas_data->set_duration(++duration);
} else {
gas_data->set_duration(0);
}
} else {
if (room->GetGasData().old_area_meta->wait_time() <= 0) {
gas_data->set_duration(0);
} else {
long long duration = room->GetGasData().old_area_meta->wait_time() * 20 -
(room->GetFrameNo() - room->GetGasData().gas_start_frameno);
gas_data->set_duration(std::max(duration * 50, (long long)1000) / 1000);
}
if (room->IsPveRoom()) {
gas_data->set_duration(0);
}
}
// 333
{
glm::vec3 v3(room->GetGasData().pos_old.x, 0.0f, room->GetGasData().pos_old.y);
TypeConvert::ToPb(v3, gas_data->mutable_pos_old());
}
{
glm::vec3 v3(room->GetGasData().pos_new.x, 0.0f, room->GetGasData().pos_new.y);
TypeConvert::ToPb(v3, gas_data->mutable_pos_new());
}
gas_data->set_rad_old(room->GetGasData().rad_old);
gas_data->set_rad_new(room->GetGasData().rad_new);
}
void Human::SendUpdateMsg()
{
#ifdef DEBUG
long long begin_tick1 = a8::XGetTickCount();
long long end_tick1 = a8::XGetTickCount();
#endif
if (!follow_target_ && !a8::HasBitFlag(status, CS_Disable)) {
#ifdef DEBUG
long long begin_tick = a8::XGetTickCount();
long long end_tick = a8::XGetTickCount();
#endif
cs::MFActivePlayerData* active_player_data_pb = nullptr;
if (send_msg_times == 0 || need_sync_active_player_) {
active_player_data_pb = new cs::MFActivePlayerData();
FillMFActivePlayerData(active_player_data_pb);
need_sync_active_player_ = false;
}
#ifdef DEBUG
end_tick = a8::XGetTickCount();
if (a8::XGetTickCount() - begin_tick > 1000) {
A8_ABORT();
}
begin_tick = a8::XGetTickCount();
#endif
cs::SMUpdate* msg = room->frame_maker.MakeUpdateMsg(this);
if (send_msg_times == 0 || last_sync_gas_frameno < room->GetGasData().gas_start_frameno) {
last_sync_gas_frameno = room->GetGasData().gas_start_frameno;
FillMFGasData(msg->mutable_gas_data());
}
#ifdef DEBUG
end_tick = a8::XGetTickCount();
if (a8::XGetTickCount() - begin_tick > 200) {
A8_ABORT();
}
begin_tick = a8::XGetTickCount();
#endif
NotifyObservers(msg, active_player_data_pb);
delete msg;
if (active_player_data_pb) {
delete active_player_data_pb;
}
++send_msg_times;
} else {
need_sync_active_player_ = false;
}
#ifdef DEBUG
end_tick1 = a8::XGetTickCount();
if (end_tick1 - begin_tick1 > 100) {
A8_ABORT();
}
#endif
framedata_.ClearFrameData(this);
}
void Human::SendGameOver()
{
#if 1
if (GetTeam()->HasPlayer()) {
if (GetTeam()->already_report_battle) {
cs::SMGameOver msg;
FillSMGameOver(msg);
SendNotifyMsg(msg);
} else {
CalcStats();
if (GetTeam()->team_rank) {
if (!GetTeam()->sending_battlereport) {
GetTeam()->sending_battlereport = true;
GetTeam()->SendTeamBattleReport(this);
}
} else {
cs::SMGameOver msg;
FillSMGameOver(msg);
SendNotifyMsg(msg);
}
}
}
if (IsEntitySubType(EST_Player)) {
if (!is_game_end_) {
GameLog::Instance()->GameEnd((Player*)this);
is_game_end_ = true;
}
}
#else
if (IsEntitySubType(EST_Player)) {
if (already_report_battle_) {
cs::SMGameOver msg;
FillSMGameOver(msg);
SendNotifyMsg(msg);
#ifdef DEBUG
if (!f8::IsTestEnv()) {
a8::XPrintf("gameOver %s\n", {f8::PbToJson(&msg)});
}
#endif
} else {
if (!sending_battlereport_) {
sending_battlereport_ = true;
SendBattleReport();
}
if (!is_game_end_) {
GameLog::Instance()->GameEnd((Player*)this);
is_game_end_ = true;
}
}
}
#endif
}
void Human::SendDebugMsg(const std::string& debug_msg)
{
#ifdef DEBUG
cs::SMDebugMsg notify_msg;
#if 1
notify_msg.set_debug_msg(debug_msg);
#else
notify_msg.set_debug_msg(a8::TimestampToDateTime(time(nullptr)) + " " + debug_msg);
#endif
SendNotifyMsg(notify_msg);
#endif
}
void Human::SendUIUpdate()
{
cs::SMUiUpdate notifymsg;
notifymsg.set_alive_count(room->AliveCount());
notifymsg.set_kill_count(stats->kills);
room->FillSMUiUpdate(notifymsg);
if (room->IsPveRoom()) {
notifymsg.set_score(stats->pve_rank_score);
notifymsg.set_wave(room->pve_data.GetWave() + 1);
notifymsg.set_max_wave(room->pve_data.max_wave);
notifymsg.set_mon_num(room->pve_data.mon_num);
notifymsg.set_boss_state(room->pve_data.boss_state);
}
SendNotifyMsg(notifymsg);
}
void Human::SendSysPiaoMsg(const std::string& msg, int color, int duration)
{
cs::SMSysPiaoMsg notifymsg;
notifymsg.set_msg(msg);
notifymsg.set_color(color);
notifymsg.set_duration(duration);
SendNotifyMsg(notifymsg);
}
void Human::SendShowCountdown(const std::string& msg, int countdown)
{
cs::SMShowCountdown notifymsg;
notifymsg.set_msg(msg);
notifymsg.set_countdown(countdown);
SendNotifyMsg(notifymsg);
}
void Human::SendBattleSettlement()
{
if (!IsPlayer()) {
return;
}
Player* p = (Player*)this;
std::shared_ptr<a8::MutableXObject> params = a8::MutableXObject::CreateObject();
{
params->SetVal("account_id", account_id);
params->SetVal("session_id", session_id);
params->SetVal("battle_uuid", battle_uuid);
params->SetVal("__POST", f8::PbToJson(p->settlement.get()));
}
std::string url;
JsonDataMgr::Instance()->GetApiUrl(url);
if (url.find('?') != std::string::npos) {
url += "c=Battle&a=reportSettlement";
} else {
url += "?c=Battle&a=reportSettlement";
}
std::string data;
params->ToUrlEncodeStr(data);
#ifdef DEBUG
{
if (!f8::IsTestEnv()) {
a8::XPrintf("reportSettlement %s\n", {data});
}
}
#endif
long long room_uuid = room->GetRoomUuid();
std::string tmp_account_id = account_id;
HttpProxy::Instance()->HttpGet
(
[room_uuid, tmp_account_id, data]
(bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx)
{
Room* room = RoomMgr::Instance()->GetRoomByUuid(room_uuid);
if (!room) {
return;
}
Player* hum = room->GetPlayerByAccountId(tmp_account_id);
if (!hum) {
return;
}
if (!ok) {
f8::UdpLog::Instance()->Error("reportSettlement error params: %s response: %s",
{
data,
""
});
}
},
url.c_str(),
*params.get()
);
}
void Human::AddItem(int item_id, int item_num)
{
auto itr = items_.find(item_id);
if (itr != items_.end()) {
itr->second += item_num;
} else {
items_[item_id] = item_num;
}
if (room && room->GetFrameNo() > join_frameno) {
#if 0
room->frame_event.AddItemChg(GetWeakPtrRef(), item_id, items_[item_id]);
#endif
if (IsPlayer()) {
cs::SMGetItemNotify notify_msg;
auto pair = notify_msg.add_items();
pair->set_key(item_id);
pair->set_value(item_num);
SendNotifyMsg(notify_msg);
}
} else {
if (item_num <= 0) {
battling_items_.insert(item_id);
}
}
}
void Human::NotifyObservers(cs::SMUpdate* msg, cs::MFActivePlayerData* active_player_data_pb)
{
bool refreshed_view = false;
std::set<int> synced_objects;
for (Human* observer : observers_) {
msg->clear_team_data();
if (observer->GetTeam()) {
observer->GetTeam()->TraverseMembers
(
[observer, msg] (Human* member) -> bool
{
#if 1
{
#else
if (member != observer || observer->room->IsPveRoom()) {
#endif
member->FillMFTeamData(observer, msg->add_team_data(), false);
}
return true;
});
}
if (observer != this && !observer->follow_synced_active_player) {
msg->set_active_player_id(GetUniId());
FillMFActivePlayerData(msg->mutable_active_player_data());
if (!refreshed_view) {
{
for (auto& pair : framedata_.new_objects) {
synced_objects.insert(pair.first);
}
}
std::set<Entity*> view_objects;
GetViewObjects(view_objects);
for (Entity* entity : view_objects) {
if (synced_objects.find(entity->GetUniId()) == synced_objects.end()) {
entity->FillMFObjectFull(room, this, msg->add_full_objects());
synced_objects.insert(entity->GetUniId());
}
}
refreshed_view = true;
for (auto& pair : framedata_.part_objects) {
if (synced_objects.find(pair.second.entity_uniid) == synced_objects.end()) {
Entity* entity = room->GetEntityByUniId(pair.second.entity_uniid);
if (entity) {
entity->FillMFObjectFull(room, this, msg->add_full_objects());
synced_objects.insert(entity->GetUniId());
} else {
#ifdef DEBUG
A8_ABORT();
#endif
}
}
#ifdef DEBUG
observer->SendDebugMsg(a8::Format("观战 notify %d->%d frameno:%d part_obj:%d",
{
GetUniId(),
observer->GetUniId(),
room->GetFrameNo(),
pair.second.entity_uniid
}));
#endif
}
#ifdef DEBUG
observer->SendDebugMsg(a8::Format("观战 notify %d->%d frameno:%d",
{
GetUniId(),
observer->GetUniId(),
room->GetFrameNo()
}));
#endif
}
observer->follow_synced_active_player = true;
} else {
if (active_player_data_pb) {
msg->set_active_player_id(GetUniId());
*msg->mutable_active_player_data() = *active_player_data_pb;
} else {
msg->clear_active_player_id();
msg->clear_active_player_data();
}
}
if (observer != this) {
for (int i = 0; i < msg->full_objects_size(); ++i) {
cs::MFObjectFull* full_obj = msg->mutable_full_objects(i);
if (a8::HasBitFlag(full_obj->object_flags(), kOfReadCache)) {
Entity* e = room->GetEntityByUniId(full_obj->obj_uniid());
if (e) {
if (!e->IsClientCached(observer)) {
}
}
}
}
}
observer->SendNotifyMsg(*msg);
}
}
void Human::FillMFSettlement(cs::SMGameOver* msg, cs::MFSettlement* s)
{
s->set_version(2022111801);
s->set_room_uuid(a8::XValue(room->GetRoomUuid()).GetString());
s->set_room_mode(room->GetRoomMode());
s->set_match_mode(GetBattleContext()->GetMatchMode());
s->set_team_mode(GetTeamMode());
s->set_game_over(msg->game_over() ? 1 : 0);
s->set_victory(stats->victory);
if (stats->victory) {
s->set_watchable(false);
} else {
if (room->GetAliveTeamNum() > 1) {
s->set_watchable(true);
} else {
if (room->IsPveRoom()) {
s->set_watchable(!room->IsGameOver());
} else {
s->set_watchable(false);
}
}
}
s->set_team_id(team_id);
s->set_account_id(account_id);
s->set_temmate_all_dead(1);
s->set_old_rank(stats->old_rank);
s->set_new_rank(stats->new_rank);
s->set_old_score(stats->old_score);
s->set_new_score(stats->new_score);
s->set_map_id(room->GetMapMeta()->map_id());
s->set_map_name(room->GetMapMeta()->map_name());
s->set_rank_score_chg(stats->new_score - stats->old_score);
for (auto item : msg->spoils_items()) {
if (!(a8::XValue(item.values(1)).GetString().empty())) {
auto p = s->add_spoils_items();
p->set_item_id(a8::XValue(item.values(0)));
p->set_item_num(item.values(1));
}
}
if (room->IsPveRoom()) {
s->set_pve_settlement_color(stats->settlement_color);
s->set_pve_wave(room->pve_data.GetPassedWave());
s->set_pve_max_wave(room->pve_data.max_wave);
s->set_pve_instance_id(room->pve_instance->gemini_id());
s->set_pve_boss_killed(room->pve_data.boss_state == 2 ? 1 : 0);
} else {
s->set_pvp_settlement_type(stats->pvp_settlement_type);
s->set_pvp_settlement_color(stats->settlement_color);
s->set_pvp_team_rank(GetTeam()->team_rank);
s->set_pvp_personal_rank(stats->rank);
s->set_pvp_my_rank(msg->my_rank());
s->set_pvp_max_rank(msg->max_rank());
s->set_pvp_total_human_num(msg->total_human_num());
s->set_pvp_alive_human_num(msg->alive_human_num());
s->set_pvp_total_team_num(msg->total_team_num());
}
*s->mutable_reward() = msg->reward();
std::vector<const cs::MFPlayerStats*> stats;
{
for (auto& item : msg->player_stats()) {
stats.push_back(&item);
}
if (room->IsPveRoom()) {
std::sort(stats.begin(), stats.end(),
[] (const cs::MFPlayerStats* a, const cs::MFPlayerStats *b) -> bool
{
if (a->score() > b->score()) {
return true;
}
if (a->score() < b->score()) {
return false;
}
return a->player_id() < b->player_id();
});
}
}
int i = 0;
for (auto item : stats) {
++i;
auto p = s->add_members_stats();
p->set_id(item->player_id());
p->set_account_id(item->account_id());
p->set_name(item->nickname());
p->set_head(a8::XValue(avatar_url));
p->set_head_frame(item->head_frame());
p->set_sex(item->sex());
p->set_hero_id(item->charid());
p->set_dead(item->dead() ? 1 : 0);
p->set_is_myself(item->account_id() == account_id ? 1 : 0);
//
p->set_is_mvp(0);
if (room->IsPveRoom()) {
p->set_pve_order(i);
p->set_pve_score(item->score());
p->set_pve_star(room->pve_mode_meta->CalcStar(item->score()));
p->set_pve_damage(item->damage_amount());
p->set_pve_survia_time(item->time_alive());
p->set_pve_wave(item->pve_wave());
p->set_pve_max_wave(room->pve_data.max_wave);
p->set_pve_revive(item->revive());
} else {
p->set_pvp_kill(item->kills());
p->set_pvp_damage(item->damage_amount());
p->set_pvp_assist(item->assist());
p->set_pvp_survia_time(item->time_alive());
p->set_pvp_recover(item->heal_amount());
p->set_pvp_rescue(item->rescue());
}
if (!item->dead() && p->account_id() != account_id) {
s->set_temmate_all_dead(0);
}
}
}
void Human::NotifyTeamMarkTargetPos()
{
if (GetTeam()) {
cs::SMTeamMarkTargetPosList notify_msg;
for (auto& pair : GetTeam()->target_pos) {
auto p = notify_msg.add_pos_list();
p->set_obj_uniid(pair.first);
TypeConvert::ToPb(pair.second, p->mutable_pos());
}
GetTeam()->TraverseMembers
(
[&notify_msg] (Human* hum)
{
hum->SendNotifyMsg(notify_msg);
return true;
});
}
}
void GGListener::SendError(int sockhandle, unsigned int seqid,
int error_code, const std::string& error_msg,
const char* file, int lineno, int error_param)
{
cs::SMRpcError msg;
msg.set_error_code(error_code);
msg.set_error_msg(error_msg);
msg.set_debug_msg("");
if (file) {
msg.set_file(file);
} else {
msg.set_file("");
}
msg.set_lineno(lineno);
msg.set_error_param(error_param);
f8::Net_SendProxyMsg(tcp_listener_.get(), sockhandle, seqid, error_code, cs::_SMRpcError, msg);
}
void GGListener::ForceCloseChildSocket(int sockhandle)
{
ss::SS_ForceCloseSocket msg;
SendProxyMsg(sockhandle, msg);
}
Player* PlayerMgr::CreatePlayerByCMJoin(Player* hum,
long ip_saddr,
int socket,
const cs::CMJoin& msg)
{
hum->socket_handle = socket;
hum->ip_saddr = ip_saddr;
hum->account_id = msg.account_id();
hum->session_id = msg.session_id();
hum->name = msg.name();
hum->team_uuid = msg.team_uuid();
hum->team_mode = msg.team_mode();
hum->auto_fill = msg.auto_fill();
hum->avatar_url = msg.avatar_url();
hum->create_tick = a8::XGetTickCount();
hum->account_registertime = f8::ExtractRegisterTimeFromSessionId(msg.session_id());
hum->channel = f8::ExtractChannelIdFromAccountId(msg.account_id());
hum->head_frame = msg.head_frame();
hum->sex = msg.sex();
hum->user_data = msg.user_data();
#if 0
for (auto& weapon : msg.weapons()) {
if (weapon.weapon_id() != 0) {
const mt::Item* item_meta = mt::Item::GetById(weapon.weapon_id());
if (item_meta && item_meta->type() == 7) {
const mt::Equip* equip_meta = mt::Equip::GetById(item_meta->relationship());
if (equip_meta && equip_meta->equip_type() == EQUIP_TYPE_WEAPON) {
Weapon& spec_weapon = a8::FastAppend(hum->spec_weapons);
spec_weapon.weapon_uniid = a8::XValue(weapon.weapon_uniid());
spec_weapon.weapon_id = item_meta->relationship();
spec_weapon.ammo = weapon.ammo();
spec_weapon.meta = equip_meta;
spec_weapon.Recalc();
}
}
}
}
#endif
#if 0
for (auto& pair : msg.talent_list()) {
hum->talent_list.push_back(
std::make_tuple(pair.key(), pair.value())
);
}
#endif
socket_hash_[socket] = hum;
return hum;
}
void PlayerMgr::_SS_WSP_SocketDisconnect(f8::MsgHdr& hdr, const ss::SS_WSP_SocketDisconnect& msg)
{
Player* hum = GetPlayerBySocket(hdr.socket_handle);
if (hum) {
RemovePlayerBySocket(hdr.socket_handle);
hum->room->OnPlayerOffline(hum);
}
#if DEBUG
a8::XPrintf("remove socket1 %d\n", {hdr.socket_handle});
#endif
if (MatchMgr::Instance()->GetMatchInfo(hdr.socket_handle)) {
#if DEBUG
a8::XPrintf("remove socket2 %d\n", {hdr.socket_handle});
#endif
MatchMgr::Instance()->RemoveSocket(hdr.socket_handle);
}
}
void PlayerMgr::_SS_Ping(f8::MsgHdr& hdr, const ss::SS_Ping& msg)
{
ss::SS_Pong respmsg;
GGListener::Instance()->SendToClient(hdr.socket_handle, 0, respmsg);
}
void Team::FillSMGameOver(cs::SMGameOver& msg)
{
auto p = msg.mutable_settlement_new();
std::vector<Human*> sorted_members;
for (Human* hum : members_) {
sorted_members.push_back(hum);
}
if (room->IsPveRoom()) {
std::sort(sorted_members.begin(), sorted_members.end(),
[] (Human* a, Human* b) -> bool
{
if (a->stats->pve_rank_score > b->stats->pve_rank_score) {
return true;
}
if (a->stats->pve_rank_score < b->stats->pve_rank_score) {
return false;
}
return a->GetUniId() < b->GetUniId();
});
}
int i = 0;
for (Human* hum : sorted_members) {
++i;
auto member = p->add_members();
member->set_obj_uniid(hum->GetUniId());
member->set_account_id(hum->account_id);
member->set_name(hum->name);
member->set_head(a8::XValue(hum->avatar_url));
member->set_head_frame(hum->head_frame);
member->set_sex(hum->sex);
member->set_hero_id(hum->meta->id());
member->set_dead(hum->dead);
member->set_is_mvp(0);
member->set_old_rank(0);
member->set_new_rank(0);
member->set_old_score(0);
member->set_new_score(0);
if (room->IsPveRoom()) {
member->set_pve_order(i);
member->set_pve_score(hum->stats->pve_rank_score);
member->set_pve_star(room->pve_mode_meta->CalcStar(hum->stats->pve_rank_score));
member->set_pve_damage(hum->stats->damage_amount_out);
member->set_pve_revive(hum->stats->revive);
member->set_pve_survia_time(room->GetFrameNo() * FRAME_RATE_MS);
member->set_pve_wave(hum->stats->pve_wave);
member->set_pve_max_wave(room->pve_data.max_wave);
member->set_pve_boss_killed(hum->stats->pve_kill_boss);
} else {
member->set_pvp_kill(hum->stats->kills);
member->set_pvp_damage(hum->stats->damage_amount_out);
member->set_pvp_assist(hum->stats->assist);
member->set_pvp_survia_time(room->GetFrameNo() * FRAME_RATE_MS);
member->set_pvp_recover(hum->stats->heal_amount);
member->set_pvp_rescue(hum->stats->rescue_member);
member->set_pvp_personal_rank(hum->stats->rank);
}
}
}