#include "precompile.h" #include #include #include #include #include #include #include "playermgr.h" #include "player.h" #include "cs_proto.pb.h" #include "room.h" #include "bullet.h" #include "obstacle.h" #include "loot.h" #include "car.h" #include "app.h" #include "typeconvert.h" #include "playermgr.h" #include "perfmonitor.h" #include "jsondatamgr.h" #include "skill.h" #include "team.h" #include "httpproxy.h" #include "roommgr.h" #include "movement.h" #include "trigger.h" #include "ability.h" #include "buff.h" #include "stats.h" #include "mapinstance.h" #include "debugcmd.h" #include "mt/Param.h" #include "mt/Equip.h" #include "mt/Hero.h" #include "mt/Buff.h" #include "mt/Text.h" #include "mt/Map.h" #include "mt/PveGemini.h" #include "mt/BattleBasicAttribute.h" const int kREVIVE_BUFF_ID = 1005; Player::Player():Human() { ++PerfMonitor::Instance()->entity_num[ET_Player]; } Player::~Player() { SetDestorying(); --PerfMonitor::Instance()->entity_num[ET_Player]; PlayerMgr::Instance()->DecAccountNum(account_id); } void Player::Initialize() { Human::Initialize(); max_energy_shield = energy_shield; RecalcBaseAttr(); if (room->IsInfiniteBulletMode()) { SetInfiniteBulletMode(); } { if (GetCurrWeapon()) { const mt::Equip* bullet_meta = mt::Equip::GetById(GetCurrWeapon()->meta->use_bullet()); if (bullet_meta) { int add_num = GetInventory(bullet_meta->_inventory_slot()); add_num = GetCurrWeapon()->GetClipVolume(this); GetCurrWeapon()->ammo = add_num; } } for (auto& spec_weapon : spec_weapons) { const mt::Equip* item_meta = mt::Equip::GetById(spec_weapon.weapon_id); if (item_meta) { if (item_meta->equip_subtype() != 1) { int weapon_idx = GUN_SLOT1; if (weapons[weapon_idx].weapon_id != 0) { weapon_idx = GUN_SLOT2; } if (weapons[weapon_idx].weapon_id == 0) { Weapon* weapon = &weapons[weapon_idx]; weapon->weapon_uniid = spec_weapon.weapon_uniid; weapon->weapon_idx = weapon_idx; weapon->weapon_id = spec_weapon.weapon_id; weapon->meta = item_meta; weapon->Recalc(); weapon->ammo = weapon->GetClipVolume(this); SetCurrWeapon(&weapons[GUN_SLOT1]); } } } } #ifdef MYDEBUG1 { std::vector present_items{30202, 30201, 30301, 30203, 30207, 30208, 30209, 30210, 30204, 30205, 30206, 30302, 30303}; for (int item_id : present_items) { GMAddItem(item_id, 10); } } #endif MarkSyncActivePlayer(__FILE__, __LINE__, __func__); } { room->xtimer.SetTimeoutEx (SERVER_FRAME_RATE * 2, [this] (int event, const a8::Args* args) { if (a8::TIMER_EXEC_EVENT == event) { room->frame_event.AddPropChg (GetWeakPtrRef(), kPropReviveCion, 0, GetNetData()->GetReviveCoin(), true); } }, &xtimer_attacher); } { room->xtimer.SetTimeoutEx (SERVER_FRAME_RATE * 1, [this] (int event, const a8::Args* args) { if (a8::TIMER_EXEC_EVENT == event) { SyncVolume(-1); } }, &xtimer_attacher); } if (GetHeroMeta()->GetBasicMeta()) { SetHeroLevel(1, 0, GetHeroMeta()->GetBasicMeta()->GetGrowMeta(room->GetMapMeta()->map_id())); } else { SetHeroLevel(1, 0, nullptr); } } void Player::Update(int delta_time) { if (UpdatedTimes() <= 0) { if (room->GetFrameNo() % 2 != 0) { return; } } InternalUpdate(delta_time); CheckShotHold(); ++updated_times_; } void Player::InternalUpdate(int delta_time) { if (poisoning) { poisoning_time += delta_time; } if (HasBuffEffect(kBET_Fly)) { App::Instance()->verify_set_pos = 1; GetMutablePos().FromGlmVec3(room->plane.curr_pos); App::Instance()->verify_set_pos = 0; room->grid_service->MoveCreature(this); } if (HasSpecMove()) { _UpdateSpecMove(); } else { if (HasBuffEffect(kBET_Sprint)) { moving = true; moved_frames = 0; } if (HasBuffEffect(kBET_Jump) && follow_target.Get() && GetPos().ManhattanDistance2D(follow_target.Get()->GetPos()) > 70) { moving = true; moved_frames = 0; } if (room->GetGasData().GetGasMode() == GasInactive && room->IsSandTableRoom() ) { if (sand_table_target_pos) { if (!GlmHelper::IsEqual2D(*sand_table_target_pos, GetPos().ToGlmVec3())) { moving = true; moved_frames = 0; } else { moving = false; GetMovement()->ClearPath(); } } else { moving = false; } } if (GetMovement()->IsFindPath()) { moving = true; } #if 1 if (moving) { UpdateMoving(); } #endif } if (room->GetFrameNo() % 2 == 0) { if (drop_weapon) { UpdateDropWeapon(); } if (!interaction_objids.empty()) { ProcInteraction(); } if (poisoning) { UpdatePoisoning(); } if (select_weapon) { UpdateSelectWeapon(); } if (use_scope) { UpdateUseScope(); } if (reload) { UpdateReload(); } if (cancel_action) { UpdateCancelAction(); } if (use_item) { UpdateUseItemIdx(); } if (action_type != AT_None) { UpdateAction(); } if (spectate) { UpdateSpectate(); } if (emote) { UpdateEmote(); } if (jump) { UpdateJump(); } if (follow != -1) { UpdateFollow(); } if (dive) { UpdateDive(); } if (shot_start || shot_hold) { UpdateShot(); } UpdateAiming(); if (use_skill) { UpdateUseSkill(); } if (has_use_item_id) { UpdateUseItemId(); } if (playing_skill) { UpdateSkill(); } if (get_down) { UpdateGetDown(); } if (get_on) { UpdateGetOn(); } if (switch_seat) { UpdateSwitchSeat(); } if (throw_bomb) { UpdateThrowBomb(); } if (skill_hold) { if (skill_hold_skill_id != skill_hold) { int old_skill_hold = skill_hold; ClearSkillHoldState(); AddSkillHoldState(old_skill_hold); skill_hold = old_skill_hold; } } else { ClearSkillHoldState(); } #if 0 if (moving) { UpdateMoving(); } #endif } } void Player::UpdateMoving() { #ifdef MYDEBUG1 a8::XPrintf("UpdateMoving\n", {}); #endif if (action_type == AT_Relive) { CancelAction(); } if (dead) { moving = false; moved_frames = 0; return; } if (HasBuffEffect(kBET_Vertigo)) { return; } if (GetCar()) { if (GetCar()->HasBuffEffect(kBET_Vertigo)) { return; } if (!GetCar()->HasOil()) { return; } } if (HasBuffEffect(kBET_Passenger)) { return; } if (HasBuffEffect(kBET_Camouflage) && camouflage_move_addition_ <= 0) { RemoveBuffByEffectId(kBET_Camouflage); } ++moved_frames; if (moved_frames > 4) { moving = false; moved_frames = 0; return; } Position old_pos = GetPos(); App::Instance()->verify_set_pos = 1; UpdateMove(); App::Instance()->verify_set_pos = 0; if (GetCar() && GetCar()->IsDriver(this)) { if (!GetCar()->HasBuffEffect(kBET_Sprint)) { GetCar()->SyncPos(); float dec_oil = old_pos.Distance2D2(GetPos()) * GetCar()->meta->average_oil() / 100; GetCar()->DecOil(dec_oil); room->frame_event.AddPropChg(GetCar()->GetWeakPtrRef(), kPropCarOil, GetCar()->GetCurOil(), GetCar()->GetMaxOil()); } } #ifdef MYDEBUG room->CheckPartObjects(); #endif } void Player::UpdateShot() { if (dead || downed || HasBuffEffect(kBET_Jump) || HasBuffEffect(kBET_Fly) || HasBuffEffect(kBET_InWater)) { shot_start = false; SetShotHold(false); series_shot_frames = 0; return; } if (HasBuffEffect(kBET_Vertigo) && !( HasBuffEffect(kBET_AutoShot) || HasBuffEffect(kBET_MachineGun) )) { shot_start = false; SetShotHold(false); series_shot_frames = 0; return; } if (HasBuffEffect(kBET_HoldShield)) { shot_start = false; SetShotHold(false); series_shot_frames = 0; return; } if (HasBuffEffect(kBET_Sprint)) { shot_start = false; SetShotHold(false); series_shot_frames = 0; return; } Weapon* p_weapon = GetCurrWeapon(); if (second_weapon.meta) { p_weapon = &second_weapon; } if (!p_weapon->meta->_power_charge.empty() && power_idx < 1 && !p_weapon->meta->IsMultistageGun()) { shot_start = false; SetShotHold(false); series_shot_frames = 0; return; } if (GetCar()) { if (GetCar()->CanShot(this)) { bool shot_ok = false; glm::vec target_dir = GetAttackDir(); glm::vec3 old_car_shoot_offset = GetCar()->shoot_offset; glm::vec3 old_car_attack_dir = GetCar()->GetAttackDir(); Creature* old_car_shot_passenger = GetCar()->shot_passenger; int old_car_shot_hole = GetCar()->shot_hole; GetCar()->shoot_offset = shoot_offset; GetCar()->shot_hole = GetSeat(); GetCar()->shot_passenger = this; GetCar()->SetShotDir(GetAttackDir()); GetCar()->Shot(target_dir, shot_ok, fly_distance, 0); if (!moving && GetCar()->IsDriver(this)) { GetCar()->SetMoveDir(GetAttackDir()); } GetCar()->shot_hole = old_car_shot_hole; GetCar()->shoot_offset = old_car_shoot_offset; GetCar()->shot_passenger = old_car_shot_passenger; } shot_start = false; if (shot_hold) { ++series_shot_frames; if (room->GetFrameNo() - last_cmmove_frameno >= 4) { SetShotHold(false); series_shot_frames = 0; } } return; } else { if (shot_start) { shot_start = false; Shot(); return; } if (shot_hold) { ++series_shot_frames; CheckShotHoldState(p_weapon); if (last_shot_frameno_ == 0 || ( (room->GetFrameNo() - last_shot_frameno_) * (1000 / SERVER_FRAME_RATE)) >= p_weapon->GetFireRate(this) ) { Shot(); } if (room->GetFrameNo() - last_cmmove_frameno >= 4) { SetShotHold(false); series_shot_frames = 0; } } } if (HasBuffEffect(kBET_Camouflage)) { RemoveBuffByEffectId(kBET_Camouflage); } } void Player::UpdateSelectWeapon() { if (!FreezeOperate()) { #ifdef NEW_WEAPON_SYS if (selected_weapon_idx >= GUN_SLOT0 && selected_weapon_idx <= GUN_SLOT2) { #else if (selected_weapon_idx >= 0 && selected_weapon_idx < weapons.size()) { #endif Weapon* old_weapon = GetCurrWeapon(); Weapon* weapon = &weapons[selected_weapon_idx]; if (weapon->weapon_id != 0) { SetCurrWeapon(weapon); ResetAction(); MarkSyncActivePlayer(__FILE__, __LINE__, __func__); SyncAroundPlayers(__FILE__, __LINE__, __func__); if (old_weapon != weapon) { AutoLoadingBullet(); } } } } select_weapon = false; selected_weapon_idx = 0; if (HasBuffEffect(kBET_Camouflage)) { RemoveBuffByEffectId(kBET_Camouflage); } } void Player::UpdateReload() { AutoLoadingBullet(true); reload = false; } void Player::UpdateCancelAction() { CancelAction(); cancel_action = false; } void Player::UpdateUseItemIdx() { if (room->HasRoomSwitch(kRoomSwitchDisableUseItem)) { return; } if (HasBuffEffect(kBET_Vertigo)) { return; } #if 0 if (use_item_idx == 24) { use_item_idx = IS_SHEN_BAO; } #endif if (downed && use_item_idx != IS_SHEN_BAO) { return; } if (use_item_idx >= 0 && use_item_idx < IS_END) { const mt::Equip* item_meta = mt::Equip::GetByIdBySlotId(use_item_idx); if (item_meta) { if (GetInventory(item_meta->_inventory_slot()) <= 0) { return; } int use_time = item_meta->use_time(); switch (use_item_idx) { case IS_HEALTHKIT: case IS_PAIN_KILLER: case IS_SHEN_BAO: { if (IsHpFull()) { SendSysPiaoMsg(TEXT("battle_server_hp_is_full", "HP is full"), a8::MkRgb(255, 255, 255), 1.5); break; } #if 0 GetTrigger()->UseItemAction(use_item_idx); #endif use_time *= 1.0f + GetNetData()->GetDrugTimePct(); use_time = std::max(1, use_time); StartAction( AT_UseItem, use_time, //use_item_idx, item_meta->id(), 0 ); } break; default: { } break; } } } use_item_idx = 0; use_item = false; } void Player::UpdateUseItemId() { ProcUseItem(use_item_id); use_item_id = 0; has_use_item_id = false; MarkSyncActivePlayer(__FILE__, __LINE__, __func__); } void Player::UpdateSpectate() { if (room->GetGasData().GetGasMode() == GasInactive || room->GetGasData().GetGasMode() == GasJump || HasBuffEffect(kBET_Fly)) { spectate = false; return; } BeKill(GetUniId(), name, 0, GetUniId(), name); spectate = false; } void Player::UpdateEmote() { room->frame_event.AddEmote(GetWeakPtrRef(), emote_id); emote = false; emote_id = 0; } void Player::UpdateJump() { if (HasBuffEffect(kBET_Fly)) { DoJump(); if (GetPos().DistanceGlmVec3(room->last_player_jump_pos) > 64 * 4) { size_t num = 2 + rand() % 2; for (size_t i = 0; i < num; ++i){ room->xtimer.SetTimeoutEx (SERVER_FRAME_RATE / 10, [this] (int event, const a8::Args* args) { if (a8::TIMER_EXEC_EVENT == event) { room->TraverseHumanList ( [] (Human* hum) -> bool { if (hum->HasBuffEffect(kBET_Fly) && hum->IsAndroid()) { hum->DoJump(); return false; } return true; }); } }, &xtimer_attacher); } } room->last_player_jump_pos = GetPos().ToGlmVec3(); if (follow_target.Get()) { follow_target.Detach(); if (!follow_target_timer_.expired()) { room->xtimer.Delete(follow_target_timer_); } } } jump = false; } void Player::UpdateGetDown() { DoGetDown(); get_down = false; } void Player::UpdateGetOn() { DoGetOn(get_on); get_on = 0; } void Player::UpdateSwitchSeat() { if (GetCar()) { GetCar()->SwitchSeat(this, switch_seat - 1); } switch_seat = 0; } void Player::UpdateUseSkill() { if (GetCar() && GetCar()->IsDriver(this)) { GetCar()->DoSkill(use_skill_id, skill_target_id, skill_dir, skill_distance); } else { DoSkill(use_skill_id, skill_target_id, skill_dir, skill_distance); } use_skill = false; } void Player::Shot() { if (second_weapon.meta) { CarShot(GetAttackDir()); return; } bool shot_ok = false; glm::vec3 target_dir = GetAttackDir(); int target_uniid = 0; if (trace_target_uniid && GetCurrWeapon()->meta->auto_trace()) { Entity* target = room->GetEntityByUniId(trace_target_uniid); if (target && target->IsCreature(room) && ((Creature*)target)->team_id != team_id && GetPos().Distance2D2(target->GetPos()) < GetCurrWeapon()->meta->trace_range() ) { target_uniid = trace_target_uniid; glm::vec3 attack_dir = GetPos().CalcDir(target->GetPos()); GlmHelper::Normalize(attack_dir); SetAttackDir(attack_dir); target_dir = attack_dir; } } if (shot_target_pos && shot_client_pos) { glm::vec3 old_attack_dir = GetAttackDir(); if (std::fabs(shot_client_pos->x - GetPos().GetX()) < 60.0f && std::fabs(shot_client_pos->y - GetPos().GetY()) < 5.0f && std::fabs(shot_client_pos->z - GetPos().GetZ()) < 60.0f) { glm::vec3 new_attack_dir = *shot_target_pos - GetPos().ToGlmVec3(); GlmHelper::Normalize(new_attack_dir); SetAttackDir(new_attack_dir); } Creature::Shot(target_dir, shot_ok, fly_distance, target_uniid); SetAttackDir(old_attack_dir); } else { Creature::Shot(target_dir, shot_ok, fly_distance, target_uniid); } } void Player::ProcInteraction() { if (room->GetGasData().GetGasMode() == GasInactive) { return; } if (HasBuffEffect(kBET_Fly)) { return; } if (HasBuffEffect(kBET_Jump)) { return; } if (dead) { return; } if (downed) { return; } cs::SMGetItemNotify notify_msg; for (auto obj_id : interaction_objids) { Entity* entity = room->GetEntityByUniId(obj_id); #ifdef MYDEBUG1 a8::XPrintf("LootInteraction %d\n", {obj_id}); #endif if (entity) { if (entity->GetPos().Distance2D2(GetPos()) > 600) { #ifdef MYDEBUG1 a8::XPrintf("LootInteraction error3 %d\n", {entity->GetUniId()}); #endif continue; } switch (entity->GetEntityType()) { case ET_Obstacle: { ObstacleInteraction((Obstacle*)entity); } break; case ET_Loot: { if (entity->GetPos().Distance2D2(GetPos()) > 150) { break; } Loot* loot = (Loot*)entity; int old_count = loot->count; LootInteraction(loot); if (loot->pickuped || loot->count < old_count) { bool real_get_count = loot->count < old_count ? old_count - loot->count : loot->count; bool found = false; for (int i = 0; i < notify_msg.old_items().size(); ++i) { auto pair = notify_msg.mutable_old_items(i); { if (pair->key() == loot->item_id) { pair->set_value(pair->value() + real_get_count); found = true; break; } } { auto tuple = notify_msg.add_items(); tuple->add_values(loot->item_id); tuple->add_values(pair->value() + real_get_count); int curr_num = 0; if (loot->meta->equip_type() == EQUIP_TYPE_WEAPON) { if (GetCurrWeapon()->weapon_id == loot->meta->id()) { #if 1 //888 #else curr_num = GetCompose()->GetNum() + 1; #endif } } else if (loot->meta->equip_type() == EQUIP_TYPE_GEMSTONE) { switch (loot->meta->equip_subtype()) { case GEMSTONE_SUB_EQUIP_ENERGY: { curr_num = gemstone; } break; case GEMSTONE_SUB_EQUIP_SKILL: { curr_num = GetInventory(IS_BLUE_STONE); } break; case GEMSTONE_SUB_EQUIP_SHIELD: { } break; default: { break; } } } tuple->add_values(curr_num); } } if (!found) { auto pair = notify_msg.add_old_items(); pair->set_key(loot->item_id); pair->set_value(real_get_count); { auto tuple = notify_msg.add_items(); tuple->add_values(loot->item_id); tuple->add_values(pair->value()); int curr_num = 0; if (loot->meta->equip_type() == EQUIP_TYPE_WEAPON) { if (GetCurrWeapon()->weapon_id == loot->meta->id()) { #if 1 //888 #else curr_num = GetCompose()->GetNum() + 1; #endif } } else if (loot->meta->equip_type() == EQUIP_TYPE_GEMSTONE) { switch (loot->meta->equip_subtype()) { case GEMSTONE_SUB_EQUIP_ENERGY: { curr_num = gemstone; } break; case GEMSTONE_SUB_EQUIP_SKILL: { curr_num = GetInventory(IS_BLUE_STONE); } break; case GEMSTONE_SUB_EQUIP_SHIELD: { } break; default: { break; } } } tuple->add_values(curr_num); } } } } break; case ET_Player: { HumanInteraction((Human*)entity); } break; default: { } break; } } else { #ifdef MYDEBUG a8::XPrintf("LootInteraction error4 %d\n", {obj_id}); #endif } } interaction_objids.clear(); if (notify_msg.items().size() > 0) { SendNotifyMsg(notify_msg); } } void Player::HumanInteraction(Human* hum) { if (downed) { return; } if (HasBuffEffect(kBET_Floating)) { return; } if (hum == this) { return; } if (!hum->downed) { return; } if (hum->GetActionType() == AT_Rescue) { return; } int downed_relive_time = mt::Param::GetIntParam("downed_relive_time") * 1000; downed_relive_time *= 1 + GetNetData()->GetRescueTimePct(); downed_relive_time = std::max(0, downed_relive_time); StartAction( AT_Rescue, downed_relive_time, room->GetFrameNo(), hum->GetUniId() ); hum->StartAction( AT_Relive, downed_relive_time, room->GetFrameNo(), GetUniId() ); TryAddBuff(this, kRescuerBuffId); hum->TryAddBuff(this, kInRescueBuffId); } void Player::ProcSkillList() { std::vector skill_list; GetNetData()->GetSkillList(skill_list); for (auto& skill_id : skill_list) { AddSkill(skill_id); } } void Player::_CMReconnect(f8::MsgHdr* hdr, const cs::CMReconnect& msg) { int old_socket_handle = socket_handle; if (socket_handle != 0) { GGListener::Instance()->ForceCloseChildSocket(socket_handle); PlayerMgr::Instance()->RemovePlayerBySocket(socket_handle); } socket_handle = hdr->socket_handle; TraverseAllLayerHumanList ( [this] (Human* hum, bool& stop) { AddToNewObjects(hum); } ); last_sync_gas_frameno = 0; MarkSyncActivePlayer(__FILE__, __LINE__, __func__); cs::SMReconnect respmsg; respmsg.set_errcode(0); respmsg.set_errmsg(TEXT("battle_server_reconnect_ok", "战斗重连成功")); SendNotifyMsg(respmsg); PlayerMgr::Instance()->ReBindSocket(this); f8::UdpLog::Instance()->Debug ("战斗服重连成功 %s %d %d", { account_id, hdr->socket_handle, old_socket_handle }); { room->xtimer.SetTimeoutEx (SERVER_FRAME_RATE, [this] (int event, const a8::Args* args) { if (a8::TIMER_EXEC_EVENT == event) { SendUIUpdate(); if (real_dead) { SendGameOver(); } } }, &xtimer_attacher); } if (!room->game_over_timer.expired()) { room->xtimer.Delete(room->game_over_timer); } SendViewerUiNotify(); } void Player::_CMMove(f8::MsgHdr* hdr, const cs::CMMove& msg) { #ifdef MYDEBUG1 if (msg.shot_start() || msg.shot_hold()) { a8::XPrintf("CMMove.Shot\n", { }); } #endif #ifdef MYDEBUG1 a8::XPrintf("CMMove.Shot shot_sart:%d shot_hold:%d skill_hold:%d\n", { msg.shot_start(), msg.shot_hold(), msg.skill_hold() }); #endif long long pre_frameno = last_cmmove_frameno_; last_cmmove_frameno_ = room->GetFrameNo(); moving = false; if (msg.has_move_dir()) { #ifdef MYDEBUG1 a8::XPrintf("move_dir %f,%f,%f\n", { msg.move_dir().x(), msg.move_dir().y(), msg.move_dir().z() }); #endif if (std::abs(msg.move_dir().x()) > FLT_EPSILON || std::abs(msg.move_dir().y()) > FLT_EPSILON || std::abs(msg.move_dir().z()) > FLT_EPSILON ) { glm::vec3 old_move_dir; glm::vec3 new_move_dir; TypeConvert::FromPb(new_move_dir, &msg.move_dir()); #ifdef MYDEBUG1 a8::XPrintf("has_move_dir0\n", {}); #endif if (!HasBuffEffect(kBET_Vertigo)) { #ifdef MYDEBUG1 a8::XPrintf("has_move_dir1\n", {}); #endif if (!(HasBuffEffect(kBET_Jump) && follow_target.Get())) { if (GetDisableMoveDirTimes() <= 0 && GlmHelper::IsValidVec3(new_move_dir)) { GlmHelper::Normalize(new_move_dir); if (std::fabs(new_move_dir.x - GetMoveDir().x) > 0.00001f || std::fabs(new_move_dir.y - GetMoveDir().y) > 0.00001f || std::fabs(new_move_dir.z - GetMoveDir().z) > 0.00001f) { SetMoveDir(new_move_dir); GetMovement()->CalcTargetPos(mt::Param::s().move_step_len); } moving = true; } #ifdef MYDEBUG1 a8::XPrintf("has_move_dir2\n", {}); #endif } } } } assert(!isnan(GetMoveDir().x) && !isnan(GetMoveDir().y) && !isnan(GetMoveDir().z)); if (msg.has_attack_dir()) { if (std::isfinite(msg.attack_dir().x()) && std::isfinite(msg.attack_dir().y()) && std::isfinite(msg.attack_dir().z()) && ( std::abs(msg.attack_dir().x()) > 0.00001f || std::abs(msg.attack_dir().y()) > 0.00001f || std::abs(msg.attack_dir().z()) > 0.00001f ) ){ bool can_set = true; if (HasBuffEffect(kBET_Vertigo)) { can_set = HasBuffEffect(kBET_AutoShot); if (!can_set) { can_set = HasBuffEffect(kBET_MachineGun); } } else if (GetCar()) { if (GetCar()->HasOil()) { if (GetCar()->HasBuffEffect(kBET_Vertigo)) { can_set = GetCar()->HasBuffEffect(kBET_AutoShot); } } else { #if 0 can_set = false; #endif } } if (can_set) { if (GetDisableMoveDirTimes() <= 0 && GetDisableAttackDirTimes() <= 0) { glm::vec3 attack_dir(msg.attack_dir().x(), msg.attack_dir().y(), msg.attack_dir().z()); GlmHelper::Normalize(attack_dir); SetAttackDir(attack_dir); if (GetCar() && GetCar()->IsDriver(this)) { if (!GetCar()->HasBuffEffect(kBET_Sprint)) { GetCar()->SetAttackDir(GetAttackDir()); } } } } #ifdef MYDEBUG a8::XPrintf("attack_dir:%f,%f,%f cli_dir:%f,%f,%f\n", { GetAttackDir().x, GetAttackDir().y, GetAttackDir().z, msg.attack_dir().x(), msg.attack_dir().y(), msg.attack_dir().z(), }); #endif } else { #ifdef MYDEBUG1 a8::XPrintf("attack_dir 0,0\n", {}); #endif } } else { #ifdef MYDEBUG1 a8::XPrintf("moving:%d times:%d\n", {moving ? 1 : 0, GetDisableAttackDirTimes()}); #endif if (moving && GetDisableAttackDirTimes() <= 0) { #if 1 SetAttackDir(GetMoveDir()); #else if (!HasBuffEffect(kBET_HoldShield)) { SetAttackDir(GetMoveDir()); } #endif if (GetCar() && GetCar()->IsDriver(this)) { if (!GetCar()->HasBuffEffect(kBET_Sprint)) { GetCar()->SetAttackDir(GetAttackDir()); } } } } #if 1 moved_frames = 0; #else if (moving) { moved_frames = 0; } #endif //前一个状态是纯点射 if (shot_start && !shot_hold) { } else { if (!HasBuffEffect(kBET_AutoShot)) { shot_start = msg.shot_start(); SetShotHold(msg.shot_hold()); } } fly_distance = std::min(500.0f, msg.fly_distance()); if (!shot_hold) { series_shot_frames = 0; } if (msg.has_interaction()) { for (auto objid : msg.interaction_objids()) { interaction_objids.push_back(objid); } } last_seq_id = msg.seq(); if (msg.has_select_weapon()) { select_weapon = true; selected_weapon_idx = msg.select_weapon(); } if (msg.has_drop_weapon()) { drop_weapon = true; drop_weapon_idx = msg.drop_weapon(); drop_num = msg.drop_num(); } if (msg.has_use_scope()) { use_scope = true; use_scope_idx = msg.use_scope(); } if (msg.has_reload()) { reload = msg.reload(); } if (msg.has_cancel_action()) { cancel_action = msg.cancel_action(); } if (msg.has_use_item_idx()) { use_item = true; use_item_idx = msg.use_item_idx(); } if (msg.has_use_item_id()) { has_use_item_id = true; use_item_id = msg.use_item_id(); } if (msg.has_spectate()) { spectate = true; } if (msg.has_emote()) { emote = true; emote_id = msg.emote(); } if (msg.has_aiming()) { aiming = msg.aiming(); } else { aiming = false; } if (msg.has_get_down()) { get_down = msg.get_down(); } if (msg.has_get_on()) { get_on = msg.get_on(); } if (msg.has_switch_seat()) { switch_seat = msg.switch_seat() + 1; } if (msg.has_jump()) { jump = true; } if (msg.has_follow()) { follow = msg.follow(); } if (msg.has_dive()) { dive = msg.dive(); } if (msg.has_use_skill()) { use_skill = msg.use_skill(); use_skill_id = msg.skill_id(); skill_target_id = msg.skill_target_id(); if (std::abs(msg.skill_dir().x()) > FLT_EPSILON || std::abs(msg.skill_dir().y()) > FLT_EPSILON || std::abs(msg.skill_dir().z()) > FLT_EPSILON ) { TypeConvert::FromPb(skill_dir, &msg.skill_dir()); GlmHelper::Normalize(skill_dir); } else { skill_dir = GlmHelper::ZERO; } skill_distance = msg.skill_distance(); } else { use_skill = false; } if (msg.has_throw_bomb()) { throw_bomb = std::make_shared(); *(throw_bomb.get()) = msg.throw_bomb(); } else { throw_bomb.reset(); } if (msg.has_sand_table_target_pos()) { if (!sand_table_target_pos) { sand_table_target_pos = std::make_shared(); } TypeConvert::FromPb(*sand_table_target_pos, &msg.sand_table_target_pos()); if (GlmHelper::IsEqual2D(*sand_table_target_pos, GetPos().ToGlmVec3()) || !room->map_instance->IsValidPos(*sand_table_target_pos)) { sand_table_target_pos = nullptr; } else { glm::vec3 target_dir = *sand_table_target_pos - GetPos().ToGlmVec3(); target_dir = glm::vec3(target_dir.x, 0.0f, target_dir.z); float distance = GlmHelper::Norm(target_dir); GlmHelper::Normalize(target_dir); SetMoveDir(target_dir); SetAttackDir(target_dir); GetMovement()->CalcTargetPos(distance); } } if (msg.has_shot_target_pos() && msg.has_shot_client_pos()) { if (!shot_target_pos) { shot_target_pos = std::make_shared(0.0f, 0.0f, 0.0f); } if (!shot_client_pos) { shot_client_pos = std::make_shared(0.0f, 0.0f, 0.0f); } TypeConvert::FromPb(*shot_target_pos, &msg.shot_target_pos()); TypeConvert::FromPb(*shot_client_pos, &msg.shot_client_pos()); } else { shot_target_pos = nullptr; shot_client_pos = nullptr; } last_cmmove_frameno = room->GetFrameNo(); trace_target_uniid = msg.trace_target_uniid(); skill_hold = msg.skill_hold(); #ifdef MYDEBUG1 a8::XPrintf("move_dir:%f %f frameno:%d %d moving:%d\n", { msg.move_dir().x(), msg.move_dir().y(), pre_frameno, room->GetFrameNo(), moving ? 1 : 0 }); #endif #ifdef MYDEBUG1 if (msg.has_drop_weapon()) { SendDebugMsg(a8::Format("zzzzzzzz frameno:%d drop_weapon:%d", {room->GetFrameNo(), msg.drop_weapon()})); } if (msg.has_interaction()) { for (auto& obj_id : interaction_objids) { SendDebugMsg(a8::Format("zzzzzzzz frameno:%d takeon obj_id:%d", {room->GetFrameNo(), obj_id})); } } #endif } void Player::_CMImmediateMsg(f8::MsgHdr* hdr, const cs::CMImmediateMsg& msg) { if (msg.stop_move()) { moving = false; } if (msg.stop_shot()) { shot_start = false; SetShotHold(false); series_shot_frames = 0; } } void Player::UpdateDropWeapon() { if (!FreezeOperate()) { #if 0 DropWeapon(drop_weapon_idx, drop_num); #endif } ResetAction(); AutoLoadingBullet(); drop_weapon = false; drop_weapon_idx = 0; } void Player::UpdateUseScope() { if (IS_1XSCOPE + use_scope_idx >= IS_1XSCOPE && IS_1XSCOPE + use_scope_idx <= IS_15XSCOPE) { if (GetInventory(IS_1XSCOPE + use_scope_idx) > 0) { curr_scope_idx = use_scope_idx; MarkSyncActivePlayer(__FILE__, __LINE__, __func__); } } use_scope = false; use_scope_idx = 0; } void Player::_CMEmote(f8::MsgHdr* hdr, const cs::CMEmote& msg) { } void Player::_CMVoice(f8::MsgHdr* hdr, const cs::CMVoice& msg) { cs::SMVoiceNotify notifymsg; notifymsg.set_account_id(account_id); notifymsg.set_download_url(msg.download_url()); auto send_func = [¬ifymsg] (Player* hum) { hum->SendNotifyMsg(notifymsg); }; room->TraversePlayerList(send_func); } void Player::_CMGameOver(f8::MsgHdr* hdr, const cs::CMGameOver& msg) { if (room->GetGasData().GetGasMode() == GasInactive) { stats->is_run_away = true; if (GetTeam()) { GetTeam()->RunAway(this); } } stats->abandon_battle = 1; CancelRevive(); if (!dead) { if (room->IsMobaModeRoom()) { SendGameOver(); } else { BeKill(GetUniId(), name, 0, GetUniId(), name); } } else { SendGameOver(); } } void Player::_CMWatchWar(f8::MsgHdr* hdr, const cs::CMWatchWar& msg) { if (!room->IsMobaModeRoom()) { AsyncRequestWatchWar(true); } } void Player::_CMLeave(f8::MsgHdr* hdr, const cs::CMLeave& msg) { if (room->GetGasData().GetGasMode() == GasInactive) { stats->is_run_away = true; } if (!leave_) { if (room->BattleStarted()) { //如果战斗已经开始算自杀 BeKill(GetUniId(), name, 0, GetUniId(), name); } leave_ = true; leave_frameno_ = room->GetFrameNo(); } cs::SMLeave respmsg; SendNotifyMsg(respmsg); } void Player::_CMRevive(f8::MsgHdr* hdr, const cs::CMRevive& msg) { Human* hum = room->GetHumanByUniId(msg.target_uniid()); if (hum && !hum->real_dead && hum->dead && !a8::HasBitFlag(status, CS_Reviving) && GetNetData()->GetReviveCoin() > 0) { a8::SetBitFlag(status, CS_Reviving); { std::string url; JsonDataMgr::Instance()->GetApiUrl(url); if (url.find('?') != std::string::npos) { url += "&c=Battle&a=decReviveCoin"; } else { url += "?&c=Battle&a=decReviveCoin"; } auto url_params = a8::MutableXObject::CreateObject(); url_params->SetVal("account_id", account_id); url_params->SetVal("session_id", session_id); url_params->SetVal("target_id", hum->account_id); url_params->SetVal("num", 1); std::string room_uuid = room->GetRoomUuid(); auto target_uniid = msg.target_uniid(); HttpProxy::Instance()->HttpGet ( [room_uuid, account_id = account_id, target_uniid] (bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx) { auto room = RoomMgr::Instance()->GetRoomByUuid(room_uuid); if (!room) { return; } Player* hum = room->GetPlayerByAccountId(account_id); if (!hum) { return; } if (ok) { if (room->IsGameOver()) { return; } if (rsp_obj->GetType() == a8::XOT_OBJECT && rsp_obj->Get("errcode").GetInt() == 0) { int revive_coin = rsp_obj->Get("revive_coin"); room->xtimer.SetTimeoutEx ( NEXT_FRAME_TIMER, [hum, target_uniid, revive_coin] (int event, const a8::Args* args) { if (a8::TIMER_EXEC_EVENT == event) { a8::UnSetBitFlag(hum->status, CS_Reviving); hum->InternalRevive(target_uniid, revive_coin); } }, &hum->xtimer_attacher); } } else { a8::UnSetBitFlag(hum->status, CS_Reviving); } }, url.c_str(), *url_params ); } } } void Player::_CMCancelRevive(f8::MsgHdr* hdr, const cs::CMCancelRevive& msg) { CancelRevive(); } void Player::_CMRequestBulletDmg(f8::MsgHdr* hdr, const cs::CMRequestBulletDmg& msg) { auto itr = room->report_bullet_hash.find(msg.bullet_uniid()); if (itr == room->report_bullet_hash.end()) { #ifdef MYDEBUG a8::XPrintf("CMRequestBulletDmg bullet_uniid:%d shield_hit:%d strengthen_wall_uniid:%d target_uniid:%d found:%d pos:%f,%f,%f equip_id:%d\n", { msg.bullet_uniid(), msg.shield_hit(), msg.strengthen_wall_uniid(), msg.target_uniid(), itr == room->report_bullet_hash.end() ? 0 :1, msg.pos().x(), msg.pos().y(), msg.pos().z(), 0 }); #endif return; } int equip_id = 0; Entity* bullet_entity = room->GetEntityByUniId(msg.bullet_uniid()); if (bullet_entity && bullet_entity->GetEntityType() == ET_Bullet) { equip_id = ((Bullet*)bullet_entity)->gun_meta->id(); ((Bullet*)bullet_entity)->ProcRequestBulletDmg ( msg.shield_hit(), msg.strengthen_wall_uniid(), msg.target_uniid(), glm::vec3(msg.pos().x(), msg.pos().y(), msg.pos().z()) ); } #ifdef MYDEBUG a8::XPrintf("CMRequestBulletDmg bullet_uniid:%d shield_hit:%d strengthen_wall_uniid:%d target_uniid:%d found:%d pos:%f,%f,%f equip_id:%d\n", { msg.bullet_uniid(), msg.shield_hit(), msg.strengthen_wall_uniid(), msg.target_uniid(), itr == room->report_bullet_hash.end() ? 0 :1, msg.pos().x(), msg.pos().y(), msg.pos().z(), equip_id }); #endif room->report_bullet_hash.erase(msg.bullet_uniid()); } void Player::_CMRequestThrowDmg(f8::MsgHdr* hdr, const cs::CMRequestThrowDmg& msg) { ProcThrowDmg(msg.throw_uniid()); } void Player::_CMStowShield(f8::MsgHdr* hdr, const cs::CMStowShield& msg) { RemoveBuffByEffectId(kBET_HoldShield); } void Player::_CMTeamMarkTargetPos(f8::MsgHdr* hdr, const cs::CMTeamMarkTargetPos& msg) { if (GetTeam()) { if (msg.has_pos()) { glm::vec3 pos; pos.x = msg.pos().x(); pos.y = 0.0f; pos.z = msg.pos().y(); GetTeam()->target_pos[GetUniId()] = pos; } else { GetTeam()->target_pos.erase(GetUniId()); } } NotifyTeamMarkTargetPos(); } void Player::ProcPreSettlementInfo(const std::string& pre_settlement_info) { std::vector tmp_strings; a8::Split(pre_settlement_info, tmp_strings, ','); if (tmp_strings.size() >= 4) { game_times = a8::XValue(tmp_strings[0]); win_times = a8::XValue(tmp_strings[1]); kill_times = a8::XValue(tmp_strings[2]); rank = a8::XValue(tmp_strings[3]); } } void Player::UpdateAiming() { if (aiming) { if (!HasBuffEffect(kBET_HoldShield)) { if (aiming_frameno == 0) { aiming_frameno = room->GetFrameNo(); power_idx = -1; } if (HasBuffEffect(kBET_Camouflage) && camouflage_aiming_addition_ <= 0) { RemoveBuffByEffectId(kBET_Camouflage); } Weapon* p_weapon = GetCurrWeapon(); if (second_weapon.meta) { p_weapon = &second_weapon; } if (!p_weapon->meta->_power_charge.empty() && !GetCurrWeapon()->meta->IsMultistageGun()) { if (power_idx + 1 > p_weapon->meta->_power_charge.size()) { A8_ABORT(); } else if (power_idx + 1 == p_weapon->meta->_power_charge.size()) { } else { long long passed_time = (room->GetFrameNo() - aiming_frameno) * FRAME_RATE_MS; if (passed_time >= std::get<0>(p_weapon->meta->_power_charge.at(power_idx + 1))) { ++power_idx; ClearAimingBuffs(); int buff_id = std::get<2>(p_weapon->meta->_power_charge.at(power_idx)); MustBeAddBuff(this, buff_id); aiming_buffs.push_back(buff_id); } } } } } else { aiming_frameno = 0; if (!GetCurrWeapon()->meta->IsMultistageGun()) { power_idx = -1; } if (!aiming_buffs.empty()) { ClearAimingBuffs(); } } } void Player::UpdateFollow() { DoFollow(follow); follow = -1; } void Player::UpdateDive() { DoDive(); dive = 0; } void Player::CheckShotHoldState(Weapon* weapon) { if (weapon->meta->_buff_meta && weapon->meta->_buff_meta->trigger_type() == kBTT_SeriesShot) { if (GetCurrWeapon()->weapon_idx != 0 && GetCurrWeapon()->ammo <= 0) { if (!shot_hold_timer.expired()) { room->xtimer.Delete(shot_hold_timer); } return; } if (!shot_hold_timer.expired()) { a8::Args args({weapon->meta->_buff_meta->buff_id()}); room->xtimer.FireEvent(shot_hold_timer, kCheckShotHoldStateTimerEvent, &args); } //second if (shot_hold_timer.expired()) { MustBeAddBuff(this, weapon->meta->_buff_meta->buff_id()); int buff_id = weapon->meta->_buff_meta->buff_id(); shot_hold_timer = room->xtimer.SetIntervalWpEx ( 1, [this, buff_id] (int event, const a8::Args* args) { if (a8::TIMER_EXEC_EVENT == event) { if (dead || !shot_hold) { room->xtimer.Delete(shot_hold_timer); } } else if (kCheckShotHoldStateTimerEvent == event) { if (args->Get(0) != buff_id) { room->xtimer.Delete(shot_hold_timer); } } else if (a8::TIMER_DELETE_EVENT == event) { RemoveBuffById(buff_id); } }, &xtimer_attacher); } } } void Player::SetAttackDir(const glm::vec3& attack_dir) { MoveableEntity::SetAttackDir(attack_dir); } void Player::AsyncRequestWatchWar(bool send_rsp_msg) { if (!watch_war_req_timer_.expired()) { return; } auto cb = [this] (int event, const a8::Args* args) { if (a8::TIMER_EXEC_EVENT == event) { cs::SMWatchWar respmsg; Human* target = room->GetWatchWarTarget(this); if (target) { respmsg.set_name(target->GetName()); SendNotifyMsg(respmsg); FollowTarget(target); target->StartRefreshViewTimer(); } else { respmsg.set_error_code(1); respmsg.set_error_msg("no watch war"); SendNotifyMsg(respmsg); } } }; watch_war_req_timer_ = room->xtimer.SetTimeoutWpEx ( NEXT_FRAME_TIMER, cb, &xtimer_attacher); } void Player::InternalRevive(int target_uniid, int revive_coin) { if (room->IsGameOver()) { return; } if (!dead) { return; } GetNetData()->SetReviveCoin(revive_coin); room->frame_event.AddPropChg (GetWeakPtrRef(), kPropReviveCion, 0, GetNetData()->GetReviveCoin(), true); Human* hum = room->GetHumanByUniId(target_uniid); if (hum) { ++stats->revive; hum->dead = false; hum->real_dead = false; hum->downed = false; SetHP(GetMaxHP()); SyncAroundPlayers(__FILE__, __LINE__, __func__); room->frame_event.AddRevive(GetWeakPtrRef()); if (!dead_timer.expired()) { room->xtimer.Delete(dead_timer); } f8::UdpLog::Instance()->Debug ("InternalRevive sender:%s target:%s pos:%f,%f", { account_id, hum->account_id, hum->GetPos().GetX(), hum->GetPos().GetY() }); { int buff_uniid = TryAddBuff(this, kInvincibleBuffId); if (buff_uniid) { Buff* buff = GetBuffByUniId(buff_uniid); if (buff) { room->xtimer.ModifyTime(buff->remover_timer, 6 * SERVER_FRAME_RATE); } } } } } void Player::UpdateThrowBomb() { if (downed) { throw_bomb.reset(); return; } if (IsCar()) { throw_bomb.reset(); return; } if (HasBuffEffect(kBET_Jump) || HasBuffEffect(kBET_Fly) || HasBuffEffect(kBET_Floating)) { throw_bomb.reset(); return; } if (action_type == AT_Reload || action_type == AT_Rescue || action_type == AT_UseItem || action_type == AT_Relive) { CancelAction(); throw_bomb.reset(); return; } if (pending_throw_bomb.find(throw_bomb->throw_uniid()) != pending_throw_bomb.end() || !throw_bomb->throw_uniid()) { throw_bomb.reset(); return; } const mt::Equip* equip_meta = mt::Equip::GetById(throw_bomb->weapon_id()); if (equip_meta && equip_meta->_inventory_slot() > 0) { int slot_id = 0; switch (equip_meta->_inventory_slot()) { case IS_FRAG: case IS_SMOKE: { slot_id = SPEC1_SLOT_BEGIN + equip_meta->_inventory_slot() - IS_FRAG; } break; case IS_MOLOTOR_COCKTAIL: { slot_id = SPEC2_SLOT_BEGIN + equip_meta->_inventory_slot() - IS_MINE; } break; default: { } break; }//end switch if (slot_id > 0 && slot_id < weapons.size()) { Weapon& weapon = weapons[slot_id]; if (weapon.weapon_idx != 0 && weapon.meta && weapon.ammo > 0) { glm::vec3 bomb_pos = glm::vec3( throw_bomb->pos().x(), throw_bomb->pos().y(), throw_bomb->pos().z() ); glm::vec3 bomb_dir = glm::vec3( throw_bomb->dir().x(), throw_bomb->dir().y(), throw_bomb->dir().z() ); Throw(slot_id, bomb_pos, bomb_dir, throw_bomb->fly_distance(), 0); } } } throw_bomb.reset(); } void Player::_CMSetRevivePosition(f8::MsgHdr* hdr, const cs::CMSetRevivePosition& msg) { } void Player::_CMGetSettlementTeamList(f8::MsgHdr* hdr, const cs::CMGetSettlementTeamList& msg) { cs::SMGetSettlementTeamList rspmsg; std::vector sorted_teams; room->TraverseTeams ( [&sorted_teams] (Team* team) -> bool { sorted_teams.push_back(team); return true; } ); std::sort(sorted_teams.begin(), sorted_teams.end(), [] (Team* a, Team *b) -> bool { if (a->team_rank == 0 && b->team_rank == 0) { return a->GetTeamId() < b->GetTeamId(); } return a->team_rank < b->team_rank; }); int team_rank = 1; for (auto& team : sorted_teams) { auto p = rspmsg.add_team_list(); p->set_team_id(team->GetTeamId()); p->set_team_rank(team_rank); team->TraverseMembers ( [p] (Human* hum) -> bool { auto m = p->add_members(); m->set_obj_uniid(hum->GetUniId()); m->set_account_id(hum->account_id); m->set_name(hum->name); m->set_hero_id(hum->meta->id()); return true; }); ++team_rank; } SendNotifyMsg(rspmsg); } void Player::_CMReportHookHitPos(f8::MsgHdr* hdr, const cs::CMReportHookHitPos& msg) { #ifdef MYDEBUG a8::XPrintf("CMReportHookHitPos id:%d hit_obj:%d pos:%d %d %d\n", {msg.bullet_uniid(), msg.hit_obj_uniid(), msg.pos().x(), msg.pos().y(), msg.pos().z(), }); #endif Entity* e = room->GetEntityByUniId(msg.bullet_uniid()); if (e && e->GetEntityType() == ET_Bullet) { Bullet* b = (Bullet*)e; glm::vec3 hit_pos; TypeConvert::FromPb(hit_pos, &msg.pos()); b->ReportHookHitPos(msg.hit_obj_uniid(), hit_pos); } } void Player::_CMReportSpecShotHitPos(f8::MsgHdr* hdr, const cs::CMReportSpecShotHitPos& msg) { #if 0 for (int target_uniid : msg.target_list()) { Creature* target = room->GetCreatureByUniId(target_uniid); if (target && IsProperTarget(target)) { glm::vec3 pos; TypeConvert::FromPb(pos, &msg.bullet_pos()); if (target->GetPos().Distance2D2(pos) < 200) { float real_dmg_out = 0.0f; target->DecHP(100, GetUniId(), GetName(), VW_Weapon, GetUniId(), GetName(), real_dmg_out); } } } #else Buff* buff = GetBuffByEffectId(kBET_Floating); if (buff && buff->meta->GetBuffParam4(buff) > 0) { if (buff->GetV(0) < buff->meta->GetBuffParam5(buff)) { for (int target_uniid : msg.target_list()) { Creature* target = room->GetCreatureByUniId(target_uniid); if (target && IsProperTarget(target)) { glm::vec3 pos; TypeConvert::FromPb(pos, &msg.bullet_pos()); if (target->GetPos().Distance2D2(pos) < 200) { float real_dmg_out = 0.0f; target->DecHP(100, GetUniId(), GetName(), VW_Weapon, GetUniId(), GetName(), real_dmg_out, 0, 0); } } } buff->IncV(0, 1); } } #endif } void Player::_CMWatchTarget(f8::MsgHdr* hdr, const cs::CMWatchTarget& msg) { cs::SMWatchTarget rsp_msg; Human* target = room->GetHumanByUniId(msg.target_uniid()); if (target) { FollowTarget(target); target->StartRefreshViewTimer(); rsp_msg.set_target_uniid(target->GetUniId()); } else { rsp_msg.set_error_code(1); } SendNotifyMsg(rsp_msg); } void Player::_CMTeamCommand(f8::MsgHdr* hdr, const cs::CMTeamCommand& msg) { cs::SMTeamCommandNotify notify_msg; notify_msg.set_sender_id(GetUniId()); notify_msg.set_custom_command(msg.custom_command()); for (int target_uniid : msg.target_list()) { Human* hum = room->GetHumanByUniId(target_uniid); if (hum) { hum->SendNotifyMsg(notify_msg); } } } void Player::SetShotHold(bool hold) { if (!hold && shot_hold) { int i = 0; } shot_hold = hold; }