#include "precompile.h" #include #include #include "playermgr.h" #include "player.h" #include "cs_proto.pb.h" #include "room.h" #include "metamgr.h" #include "bullet.h" #include "obstacle.h" #include "building.h" #include "loot.h" #include "car.h" #include "app.h" #include "collider.h" #include "typeconvert.h" #include "playermgr.h" #include "perfmonitor.h" #include "jsondatamgr.h" #include "skill.h" #include "team.h" const int kREVIVE_BUFF_ID = 1005; Player::Player():Human() { ++PerfMonitor::Instance()->entity_num[ET_Player]; } Player::~Player() { --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(); } } void Player::Update(int delta_time) { if (UpdatedTimes() <= 0) { if (room->GetFrameNo() % 2 != 0) { return; } } InternalUpdate(delta_time); ++updated_times_; } void Player::InternalUpdate(int delta_time) { if (poisoning) { poisoning_time += delta_time; } if (HasBuffEffect(kBET_Fly)) { SetPos(room->plane.curr_pos); 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().ManhattanDistance(follow_target.Get()->GetPos()) > 70) { moving = true; moved_frames = 0; } if (moving) { UpdateMove(); } } if (room->GetFrameNo() % 2 == 0) { if (drop_weapon) { UpdateDropWeapon(); } if (interaction_objids.size() > 0) { 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 (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(); } } } void Player::UpdateMove() { if (action_type == AT_Relive) { CancelAction(); } if (dead || room->IsWaitingStart()) { moving = false; moved_frames = 0; SetLastCollisionDoor(nullptr); 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; } a8::Vec2 old_pos = GetPos(); if (GetCar() && GetCar()->IsDriver(this)) { _UpdateMove(std::max(1, (int)GetCar()->GetSpeed())); } else { _UpdateMove(std::max(1, (int)GetSpeed())); } if (GetLastCollisionDoor() && !TestCollision(room, GetLastCollisionDoor())) { SetLastCollisionDoor(nullptr); } if (GetCar() && GetCar()->IsDriver(this)) { GetCar()->SyncPos(); float dec_oil = old_pos.Distance(GetPos()) * GetCar()->meta->i->average_oil() / 100; GetCar()->DecOil(dec_oil); room->frame_event.AddPropChg(GetCar()->GetWeakPtrRef(), kPropCarOil, GetCar()->GetCurOil(), GetCar()->GetMaxOil()); } #ifdef DEBUG room->CheckPartObjects(); #endif } void Player::UpdateShot() { if (dead || downed || room->IsWaitingStart() || HasBuffEffect(kBET_Jump) || HasBuffEffect(kBET_Fly)) { shot_start = false; shot_hold = false; series_shot_frames = 0; return; } if (HasBuffEffect(kBET_Vertigo) && !HasBuffEffect(kBET_AutoShot)) { return; } Weapon* p_weapon = GetCurrWeapon(); if (second_weapon.meta) { p_weapon = &second_weapon; } if (!p_weapon->meta->power_charge.empty() && power_idx < 1) { shot_start = false; shot_hold = false; series_shot_frames = 0; return; } if (GetCar()) { if (GetCar()->CanShot(this)) { bool shot_ok = false; a8::Vec2 target_dir = GetAttackDir(); a8::Vec2 old_car_shoot_offset = GetCar()->shoot_offset; a8::Vec2 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()->SetAttackDir(GetAttackDir()); GetCar()->Shot(target_dir, shot_ok, fly_distance); if (!moving && GetCar()->IsDriver(this)) { GetCar()->SetMoveDir(GetAttackDir()); } if (!GetCar()->IsDriver(this)) { GetCar()->SetAttackDir(old_car_attack_dir); } GetCar()->shot_hole = old_car_shot_hole; GetCar()->shoot_offset = old_car_shoot_offset; GetCar()->shot_passenger = old_car_shot_passenger; } shot_start = false; 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->GetAttrValue(kHAT_FireRate) ) { Shot(); } if (room->GetFrameNo() - last_cmmove_frameno >= 4) { shot_hold = false; series_shot_frames = 0; } } } if (HasBuffEffect(kBET_Camouflage)) { RemoveBuffByEffectId(kBET_Camouflage); } } void Player::UpdateSelectWeapon() { if (!FreezeOperate()) { if (selected_weapon_idx >= 0 && selected_weapon_idx < weapons.size()) { Weapon* old_weapon = GetCurrWeapon(); Weapon* weapon = &weapons[selected_weapon_idx]; if (weapon->weapon_id != 0) { SetCurrWeapon(weapon); ResetAction(); need_sync_active_player = true; 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 1 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) { MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquipBySlotId(use_item_idx); if (item_meta) { int use_time = item_meta->i->use_time(); switch (use_item_idx) { case IS_HEALTHKIT: case IS_PAIN_KILLER: case IS_SHEN_BAO: { GetTrigger()->UseItemAction(use_item_idx); use_time -= GetAbility()->GetAttrAbs(kHAT_DrugTime); use_time = std::max(1, use_time); StartAction( AT_UseItem, use_time, use_item_idx, 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; need_sync_active_player = true; } void Player::UpdateSpectate() { if (room->GetGasData().gas_mode == GasInactive || room->GetGasData().gas_mode == GasJump || HasBuffEffect(kBET_Fly)) { spectate = false; return; } BeKill(GetUniId(), name, 0); 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().Distance(room->last_player_jump_pos) > 64 * 4) { size_t num = 2 + rand() % 2; for (size_t i = 0; i < num; ++i){ room->xtimer.AddDeadLineTimerAndAttach (SERVER_FRAME_RATE / 10, a8::XParams() .SetSender(this), [] (const a8::XParams& param) { Human* hum = (Human*)param.sender.GetUserData(); hum->room->TraverseHumanList ( a8::XParams() .SetSender(hum), [] (Human* hum, a8::XParams& param) -> bool { if (hum->HasBuffEffect(kBET_Fly) && hum->IsAndroid()) { hum->DoJump(); return false; } return true; }); }, &xtimer_attacher.timer_list_); } } room->last_player_jump_pos = GetPos(); if (follow_target.Get()) { follow_target.Detach(); if (follow_target_timer_) { room->xtimer.DeleteTimer(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() { DoSkill(use_skill_id, skill_target_id, skill_dir, skill_distance, a8::Vec2()); use_skill = false; } void Player::Shot() { if (second_weapon.meta) { CarShot(GetAttackDir()); return; } bool shot_ok = false; a8::Vec2 target_dir = GetAttackDir(); Creature::Shot(target_dir, shot_ok, fly_distance); } void Player::ProcInteraction() { if (room->GetGasData().gas_mode == GasInactive) { return; } if (HasBuffEffect(kBET_Fly)) { return; } if (HasBuffEffect(kBET_Jump)) { return; } for (auto obj_id : interaction_objids) { Entity* entity = room->GetEntityByUniId(obj_id); #ifdef DEBUG a8::XPrintf("LootInteraction %d\n", {obj_id}); #endif if (entity) { if (entity->GetPos().Distance(GetPos()) > 600) { #ifdef DEBUG 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().Distance(GetPos()) > 150) { break; } LootInteraction((Loot*)entity); } break; case ET_Player: { HumanInteraction((Human*)entity); } break; default: { } break; } } else { #ifdef DEBUG a8::XPrintf("LootInteraction error4 %d\n", {obj_id}); #endif } } interaction_objids.Clear(); } void Player::ObstacleInteraction(Obstacle* entity) { entity->DoInteraction(this); } void Player::HumanInteraction(Human* hum) { if (downed) { return; } if (hum == this) { return; } if (!hum->downed) { return; } if (hum->GetActionType() == AT_Rescue) { return; } TryAddBuff(this, kRescueBuffId); int downed_relive_time = MetaMgr::Instance()->GetSysParamAsInt("downed_relive_time") * 1000; downed_relive_time -= GetAbility()->GetAttrAbs(kHAT_RescueTime); downed_relive_time = std::max(0, downed_relive_time); hum->StartAction( AT_Rescue, downed_relive_time, room->GetFrameNo(), GetUniId() ); StartAction( AT_Relive, downed_relive_time, room->GetFrameNo(), hum->GetUniId() ); } void Player::ProcPrepareItems(const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& prepare_items) { std::set handled_items; for (int equip_id : prepare_items) { if (handled_items.find(equip_id) != handled_items.end()) { continue; } handled_items.insert(equip_id); MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquip(equip_id); if (item_meta) { AddItemDTO dto; dto.uniid = 0; dto.item_id = item_meta->i->id(); dto.count = 1; dto.item_level = 1; dto.handled = false; dto.item_meta = item_meta; ProcAddItemDto(dto); } }//end for if (GetCurrWeapon()) { MetaData::Equip* bullet_meta = MetaMgr::Instance()->GetEquip(GetCurrWeapon()->meta->i->use_bullet()); if (bullet_meta) { int add_num = GetInventory(bullet_meta->i->_inventory_slot()); add_num = GetCurrWeapon()->GetClipVolume(); GetCurrWeapon()->ammo = add_num; } } for (auto& spec_weapon : spec_weapons) { MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquip(second_weapon.weapon_id); if (item_meta) { if (item_meta->i->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_idx = weapon_idx; weapon->weapon_id = second_weapon.weapon_id; weapon->weapon_lv = second_weapon.weapon_lv; weapon->ammo = second_weapon.ammo; weapon->meta = item_meta; weapon->Recalc(); SetCurrWeapon(&weapons[GUN_SLOT1]); } } } } need_sync_active_player = true; if (!prepare_items.size() > 0) { SyncAroundPlayers(__FILE__, __LINE__, __func__); } } void Player::ProcPrepareItems2(const ::google::protobuf::RepeatedPtrField< cs::MFPair >& prepare_items) { for (auto& pair : prepare_items) { AddItem(pair.key(), pair.value()); } } void Player::ProcSkillList(const ::google::protobuf::RepeatedPtrField< cs::MFPair >& skill_list) { for (auto& pair : skill_list) { AddSkill(pair.key()); } } 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); } ); need_sync_active_player = true; cs::SMReconnect respmsg; respmsg.set_errcode(0); respmsg.set_errmsg(TEXT("battle_server_reconnect_ok", "战斗重连成功")); SendNotifyMsg(respmsg); PlayerMgr::Instance()->ReBindSocket(this); a8::UdpLog::Instance()->Debug ("战斗服重连成功 %s %d %d", { account_id, hdr.socket_handle, old_socket_handle }); } void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg) { last_cmmove_frameno_ = room->GetFrameNo(); moving = false; if (msg.has_move_dir()) { if (std::abs(msg.move_dir().x()) > FLT_EPSILON || std::abs(msg.move_dir().y()) > FLT_EPSILON ) { a8::Vec2 old_move_dir; a8::Vec2 new_move_dir; TypeConvert::FromPb(new_move_dir, &msg.move_dir()); if (!HasBuffEffect(kBET_Vertigo)) { if (!(HasBuffEffect(kBET_Jump) && follow_target.Get())) { if (GetDisableMoveDirTimes() <= 0) { new_move_dir.Normalize(); SetMoveDir(new_move_dir); moving = true; } } } } } assert(!isnan(GetMoveDir().x) && !isnan(GetMoveDir().y)); if (msg.has_attack_dir()) { if (std::isfinite(msg.attack_dir().x()) && std::isfinite(msg.attack_dir().y()) && ( std::abs(msg.attack_dir().x()) > 0.00001f || std::abs(msg.attack_dir().y()) > 0.00001f ) ){ bool can_set = true; if (HasBuffEffect(kBET_Vertigo)) { can_set = HasBuffEffect(kBET_AutoShot); } else if (GetCar()) { if (GetCar()->HasOil()) { if (GetCar()->HasBuffEffect(kBET_Vertigo)) { can_set = GetCar()->HasBuffEffect(kBET_AutoShot); } } else { can_set = false; } } if (can_set) { if (GetDisableMoveDirTimes() <= 0) { a8::Vec2 attack_dir; TypeConvert::FromPb(attack_dir, &msg.attack_dir()); attack_dir.Normalize(); SetAttackDir(attack_dir); if (GetCar() && GetCar()->IsDriver(this)) { GetCar()->SetAttackDir(GetAttackDir()); } } } } } else { if (moving) { SetAttackDir(GetMoveDir()); if (GetCar() && GetCar()->IsDriver(this)) { GetCar()->SetAttackDir(GetAttackDir()); } } } if (moving) { moved_frames = 0; } //前一个状态是纯点射 if (shot_start && !shot_hold) { } else { if (!HasBuffEffect(kBET_AutoShot)) { shot_start = msg.shot_start(); shot_hold = msg.shot_hold(); } } fly_distance = std::min(500.0f, msg.fly_distance()); if (!shot_hold) { series_shot_frames = 0; } if (msg.has_interaction()) { interaction_objids = msg.interaction_objids(); } 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(); } 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_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 ) { TypeConvert::FromPb(skill_dir, &msg.skill_dir()); skill_dir.Normalize(); } else { skill_dir = a8::Vec2(); } skill_distance = msg.skill_distance(); } else { use_skill = false; } last_cmmove_frameno = room->GetFrameNo(); #ifdef DEBUG1 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::_CMExecCommand(f8::MsgHdr& hdr, const cs::CMExecCommand& msg) { std::vector cmds; a8::Split(msg.cmd().c_str(), cmds, ' '); if (cmds.empty()) { return; } std::string cmd = cmds[0]; if (cmd == "gps") { SendDebugMsg(a8::Format("%d %d", {GetPos().x, GetPos().y})); } else if (cmd == "setmode") { if (cmds.empty()) { App::Instance()->UnSetFlag(20); } else { if (cmds[1] == "peace") { App::Instance()->SetFlag(20); } else { App::Instance()->UnSetFlag(20); } } } else if (cmd == "additem" && cmds.size() >= 3) { int item_id = a8::XValue(cmds[1]); int item_num = a8::XValue(cmds[2]); GMAddItem(item_id, item_num); } else if (cmd == "infinite_bullet_mode") { room->SetInfiniteBulletMode(); } else if (cmd == "watchwar") { AsyncRequestWatchWar(false); } else if (cmd == "shuaguai" && cmds.size() >= 3) { int hero_id = a8::XValue(cmds[1]); int hero_num = a8::XValue(cmds[2]); std::vector mons = std::vector{hero_id}; room->ShuaMon(GetPos(), mons, 100); } else if (cmd == "jiuyuan") { TryAddBuff(this, kRescueBuffId); int downed_relive_time = MetaMgr::Instance()->GetSysParamAsInt("downed_relive_time") * 1000; downed_relive_time -= GetAbility()->GetAttrAbs(kHAT_RescueTime); downed_relive_time = std::max(0, downed_relive_time); downed_relive_time = 1000 * 30; StartAction( AT_Relive, downed_relive_time, room->GetFrameNo(), 0 ); } else if (cmd == "addbuff" && cmds.size() >= 2) { int buff_id = a8::XValue(cmds[1]); MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id); if (buff_meta) { MustBeAddBuff(this, buff_id); } } else if (cmd == "getattr" && cmds.size() >= 2) { int attr_id = a8::XValue(cmds[1]); float abs_val = GetAbility()->GetAttrAbs(attr_id); float rate_val = GetAbility()->GetAttrRate(attr_id); SendDebugMsg(a8::Format("attr_id:%d abs_val:%f rate_val:%f", {attr_id, abs_val, rate_val})); } else if (cmd == "bufflist") { SendDebugMsg(DebugOutBuffList()); } else if (cmd == "set_inactive_time" && cmds.size() >= 2) { #if DEBUG App::Instance()->debug_params[1] = a8::XValue(cmds[1]); #endif } else if (cmd == "set_born_frameno_offset" && cmds.size() >= 2) { #if DEBUG App::Instance()->debug_params[118] = a8::XValue(cmds[1]); #endif } else if (cmd == "chiji") { #if DEBUG if (cmds.size() >= 2) { if (cmds[1] == "open") { App::Instance()->debug_params[119] = 1; } else if (cmds[1] == "close") { App::Instance()->debug_params.erase(119); } } else { App::Instance()->debug_params[119] = 1; } #endif } else if (cmd == "wudi") { int buff_uniid = TryAddBuff(this, 1005); if (buff_uniid != 0) { Buff* buff = GetBuffByUniId(buff_uniid); if (buff->remover_timer) { room->xtimer.ModifyTimer(buff->remover_timer, SERVER_FRAME_RATE * 10000); } } } else if (cmd == "reset_skill" && cmds.size() >= 2) { int skill_id = a8::XValue(cmds[1]); Skill* skill = GetSkill(skill_id); if (skill) { skill->Accelerate(-10000000); } } } void Player::UpdateDropWeapon() { if (drop_weapon_idx >= 0 && drop_weapon_idx < weapons.size() && !HasBuffEffect(kBET_Terminator) && !FreezeOperate()) { DropWeapon(drop_weapon_idx); } 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; need_sync_active_player = true; } } 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 = [] (Player* hum, a8::XParams& param) { cs::SMVoiceNotify* msg = (cs::SMVoiceNotify*)param.sender.GetUserData(); hum->SendNotifyMsg(*msg); }; room->TraversePlayerList(a8::XParams() .SetSender(¬ifymsg), send_func); } void Player::_CMGameOver(f8::MsgHdr& hdr, const cs::CMGameOver& msg) { CancelRevive(); SendGameOver(); } void Player::_CMWatchWar(f8::MsgHdr& hdr, const cs::CMWatchWar& msg) { AsyncRequestWatchWar(true); } void Player::_CMLeave(f8::MsgHdr& hdr, const cs::CMLeave& msg) { if (!leave_) { if (room->BattleStarted()) { //如果战斗已经开始算自杀 BeKill(GetUniId(), name, 0); } leave_ = true; leave_frameno_ = room->GetFrameNo(); } cs::SMLeave respmsg; SendNotifyMsg(respmsg); } void Player::_CMRevive(f8::MsgHdr& hdr, const cs::CMRevive& msg) { if (real_dead) { SendGameOver(); return; } if (dead && !real_dead && revive_timer) { dead = false; real_dead = false; downed = false; FreeDownedTimer(); SetHP(GetMaxHP()); SyncAroundPlayers(__FILE__, __LINE__, __func__); FreeReviveTimer(); #if 1 { MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(kREVIVE_BUFF_ID); if (buff_meta) { AddBuff(this, buff_meta, 1); } } #endif InternalAdOk(); } } void Player::_CMCancelRevive(f8::MsgHdr& hdr, const cs::CMCancelRevive& msg) { CancelRevive(); } void Player::_CMAdStart(f8::MsgHdr& hdr, const cs::CMAdStart& msg) { if (downed || dead) { return; } if (GetBuffByEffectId(kBET_LordMode)) { return; } if (GetBuffByEffectId(kBET_AdPlaying)) { return; } if (a8::HasBitFlag(status, CS_AlreadyLordMode)) { return; } if (ad_timer_) { room->xtimer.DeleteTimer(ad_timer_); ad_timer_ = nullptr; } MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(ADPLAY_BUFFID); if (buff_meta) { AddBuff(this, buff_meta, 1); room->xtimer. AddDeadLineTimerAndAttach( buff_meta->i->duration_time() * SERVER_FRAME_RATE + 2, a8::XParams() .SetSender(this), [] (const a8::XParams& param) { Player* hum = (Player*)param.sender.GetUserData(); hum->InternalAdCancel(); }, &xtimer_attacher.timer_list_, [] (const a8::XParams& param) { Human* hum = (Human*)param.sender.GetUserData(); hum->ad_timer_ = nullptr; } ); } } void Player::_CMAdCancel(f8::MsgHdr& hdr, const cs::CMAdCancel& msg) { InternalAdCancel(); } void Player::_CMAdEnd(f8::MsgHdr& hdr, const cs::CMAdEnd& msg) { if (GetBuffByEffectId(kBET_LordMode)) { return; } InternalAdOk(); } void Player::_CMGetBoxInfo(f8::MsgHdr& hdr, const cs::CMGetBoxInfo& msg) { cs::SMGetBoxInfo respmsg; respmsg.set_box_id(msg.box_id()); std::vector>* items = GetBox(msg.box_id()); if (items) { for (auto& tuple : *items) { auto p = respmsg.add_items(); p->add_values(std::get<0>(tuple)); p->add_values(std::get<1>(tuple)); } } SendNotifyMsg(respmsg); } void Player::_CMOpenBox(f8::MsgHdr& hdr, const cs::CMOpenBox& msg) { cs::SMOpenBox respmsg; respmsg.set_box_id(msg.box_id()); respmsg.set_errcode(0); if (msg.box_id() == 1) { if (receved_box_hash_.find(msg.box_id()) == receved_box_hash_.end()) { std::vector>* items = GetBox(msg.box_id()); if (items) { for (auto& tuple : *items) { MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquip(std::get<0>(tuple)); if (item_meta) { auto p = respmsg.add_items(); p->add_values(std::get<0>(tuple)); p->add_values(std::get<1>(tuple)); if (item_meta->i->_inventory_slot() >= 0 && item_meta->i->_inventory_slot() < IS_END) { if (GetInventory(item_meta->i->_inventory_slot()) < GetVolume(item_meta->i->_inventory_slot())) { int add_num = GetVolume(item_meta->i->_inventory_slot()) - GetInventory(item_meta->i->_inventory_slot()); add_num = std::min(std::get<1>(tuple), add_num); AddInventory(item_meta->i->_inventory_slot(), add_num); } } else { switch (item_meta->i->equip_type()) { case 7: { //背包 if (backpack == 0) { MetaData::Equip* old_item_meta = MetaMgr::Instance()->GetEquip(backpack); if (old_item_meta) { if (old_item_meta->i->equip_lv() >= item_meta->i->equip_lv()) { break; } room->DropItem(GetPos(), old_item_meta->i->id(), 1, 1); } backpack = item_meta->i->id(); RecalcVolume(); } } break; default: break; } } } } need_sync_active_player = true; } receved_box_hash_.insert(msg.box_id()); } else { respmsg.set_errcode(1); respmsg.set_errmsg(TEXT("battle_server_received", "不能重复领取")); } } SendNotifyMsg(respmsg); } void Player::InternalAdCancel() { if (GetBuffByEffectId(kBET_AdPlaying)) { RemoveBuffByEffectId(kBET_AdPlaying); if (ad_timer_) { room->xtimer.DeleteTimer(ad_timer_); ad_timer_ = nullptr; } } if (GetBuffByEffectId(kBET_LordMode)) { return; } } void Player::InternalAdOk() { if (a8::HasBitFlag(status, CS_AlreadyLordMode)) { return; } MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(ADPLAY_BUFFID); if (buff_meta) { MetaData::Buff* lord_buff_meta = nullptr; if (rand() % 2 < 1) { lord_buff_meta = MetaMgr::Instance()->GetBuff(buff_meta->param1); } else { lord_buff_meta = MetaMgr::Instance()->GetBuff(buff_meta->param2); } if (lord_buff_meta) { a8::SetBitFlag(status, CS_AlreadyLordMode); AddBuff(this, lord_buff_meta, 1); std::vector strings; a8::Split(lord_buff_meta->i->buff_param1(), strings, ':'); for (auto& str : strings) { int buff_id = a8::XValue(str); MetaData::Buff* ext_buff_meta = MetaMgr::Instance()->GetBuff(buff_id); if (ext_buff_meta) { AddBuff(this, ext_buff_meta, 1); } } } } RemoveBuffByEffectId(kBET_AdPlaying); if (ad_timer_) { room->xtimer.DeleteTimer(ad_timer_); ad_timer_ = nullptr; } } void Player::PushJoinRoomMsg() { if (!a8::HasBitFlag(status, CS_ForceTeam)) { cs::SMJoinedNotify notifymsg; notifymsg.set_error_code(0); notifymsg.set_room_mode((int)room->GetRoomMode()); notifymsg.set_server_info(JsonDataMgr::Instance()->server_info); room->FillSMJoinedNotify(this, notifymsg); GGListener::Instance()->SendToClient(socket_handle, 0, notifymsg); } { cs::SMMapInfo notifymsg; notifymsg.set_map_id(room->GetMapMeta()->i->map_id()); notifymsg.set_map_width(room->GetMapMeta()->i->map_width()); notifymsg.set_map_height(room->GetMapMeta()->i->map_height()); //notifymsg.set_room_mode((int)room->GetRoomMode()); notifymsg.set_server_info(JsonDataMgr::Instance()->server_info); //notifymsg.set_team_mode(team_mode()); notifymsg.set_player_id(GetUniId()); notifymsg.set_started(false); notifymsg.set_room_uuid(a8::XValue(room->GetRoomUuid()).GetString()); GGListener::Instance()->SendToClient(socket_handle, 0, notifymsg); #ifdef DEBUG a8::XPrintf("PushJoinRooMmsg %d\n", {GetUniId()}); #endif } } 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]); } } std::vector>* Player::GetBox(int box_id) { if (box_id != 1) { return nullptr; } { auto itr = box_hash_.find(box_id); if (itr != box_hash_.end()) { return &itr->second; } } int drop_id = 0; drop_id = MetaMgr::Instance()->prebattle_box_id_chiji; MetaData::Drop* drop_meta = MetaMgr::Instance()->GetDrop(drop_id); if (drop_meta) { std::vector> drop_items; drop_meta->RandItems(drop_items); box_hash_[box_id] = drop_items; } { auto itr = box_hash_.find(box_id); return itr != box_hash_.end() ? &itr->second : nullptr; } } void Player::UpdateAiming() { if (aiming) { 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()) { if (power_idx + 1 > p_weapon->meta->power_charge.size()) { 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[power_idx + 1])) { ++power_idx; ClearAimingBuffs(); int buff_id = std::get<2>(p_weapon->meta->power_charge[power_idx]); MustBeAddBuff(this, buff_id); aiming_buffs.push_back(buff_id); } } } } else { aiming_frameno = 0; power_idx = -1; if (!aiming_buffs.empty()) { ClearAimingBuffs(); } } } void Player::UpdateFollow() { DoFollow(follow); follow = -1; } void Player::CheckShotHoldState(Weapon* weapon) { if (weapon->meta->buff_meta && weapon->meta->buff_meta->i->trigger_type() == kBTT_SeriesShot) { if (GetCurrWeapon()->weapon_idx != 0 && GetCurrWeapon()->ammo <= 0) { if (shot_hold_timer) { room->xtimer.DeleteTimer(shot_hold_timer); } return; } if (shot_hold_timer) { if (weapon->meta->buff_meta->i->buff_id() != room->xtimer.MutableParams(shot_hold_timer)->param1.GetInt()) { room->xtimer.DeleteTimer(shot_hold_timer); } } //second if (!shot_hold_timer) { MustBeAddBuff(this, weapon->meta->buff_meta->i->buff_id()); shot_hold_timer = room->xtimer.AddRepeatTimerAndAttach ( 1, a8::XParams() .SetSender(this) .SetParam1(weapon->meta->buff_meta->i->buff_id()), [] (const a8::XParams& param) { Human* hum = (Human*)param.sender.GetUserData(); if (hum->dead || !hum->shot_hold) { hum->room->xtimer.DeleteTimer(hum->shot_hold_timer); } }, &xtimer_attacher.timer_list_, [] (const a8::XParams& param) { Human* hum = (Human*)param.sender.GetUserData(); hum->RemoveBuffById(param.param1); hum->shot_hold_timer = nullptr; }); } } } void Player::SetAttackDir(const a8::Vec2& attack_dir) { MoveableEntity::SetAttackDir(attack_dir); } void Player::AsyncRequestWatchWar(bool send_rsp_msg) { if (watch_war_req_timer_) { return; } auto cb = [] (const a8::XParams& param) { Player* hum = (Player*)param.sender.GetUserData(); cs::SMWatchWar respmsg; Human* target = hum->room->GetWatchWarTarget(hum); if (target) { respmsg.set_name(target->GetName()); hum->SendNotifyMsg(respmsg); hum->FollowTarget(target); target->StartRefreshViewTimer(); } else { respmsg.set_error_code(1); respmsg.set_error_msg("无法观战"); hum->SendNotifyMsg(respmsg); } }; watch_war_req_timer_ = room->xtimer.AddDeadLineTimerAndAttach ( NEXT_FRAME_TIMER, a8::XParams() .SetSender(this), cb, &xtimer_attacher.timer_list_, [] (const a8::XParams& param) { Player* hum = (Player*)param.sender.GetUserData(); hum->watch_war_req_timer_ = nullptr; }); }