#include "precompile.h" #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 "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" 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(); } { 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 DEBUG { 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, GetBattleContext()->GetReviveCoin(), true); } }, &xtimer_attacher); } } 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)) { Global::Instance()->verify_set_pos = 1; GetMutablePos().FromGlmVec3(room->plane.curr_pos); Global::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 (moving) { UpdateMoving(); } } 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(); } } } void Player::UpdateMoving() { #ifdef DEBUG1 a8::XPrintf("UpdateMoving\n", {}); #endif if (action_type == AT_Relive) { CancelAction(); } if (dead || room->IsWaitingStart()) { 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(); Global::Instance()->verify_set_pos = 1; UpdateMove(); Global::Instance()->verify_set_pos = 0; if (GetCar() && GetCar()->IsDriver(this)) { 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 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) || HasBuffEffect(kBET_MachineGun) )) { shot_start = false; shot_hold = false; series_shot_frames = 0; return; } if (HasBuffEffect(kBET_HoldShield)) { shot_start = false; shot_hold = false; series_shot_frames = 0; return; } if (HasBuffEffect(kBET_Sprint)) { shot_start = false; shot_hold = 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) { shot_start = false; shot_hold = 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) { shot_hold = 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) { shot_hold = 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 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 - GetAbility()->GetAttrRate(kHAT_DrugTime); use_time -= GetAbility()->GetAttrAbs(kHAT_DrugTime); 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() { 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; } } 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; } cs::SMGetItemNotify notify_msg; 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().Distance2D2(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().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.items().size(); ++i) { auto pair = notify_msg.mutable_items(i); if (pair->key() == loot->item_id) { pair->set_value(pair->value() + real_get_count); found = true; break; } } if (!found) { auto pair = notify_msg.add_items(); pair->set_key(loot->item_id); pair->set_value(real_get_count); } } } 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(); if (notify_msg.items().size() > 0) { SendNotifyMsg(notify_msg); } } 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; } int downed_relive_time = mt::Param::GetIntParam("downed_relive_time") * 1000; downed_relive_time -= GetAbility()->GetAttrAbs(kHAT_RescueTime); 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; GetBattleContext()->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); } } void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg) { long long pre_frameno = last_cmmove_frameno_; last_cmmove_frameno_ = room->GetFrameNo(); moving = false; if (msg.has_move_dir()) { #ifdef DEBUG1 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 DEBUG1 a8::XPrintf("has_move_dir0\n", {}); #endif if (!HasBuffEffect(kBET_Vertigo)) { #ifdef DEBUG1 a8::XPrintf("has_move_dir1\n", {}); #endif if (!(HasBuffEffect(kBET_Jump) && follow_target.Get())) { if (GetDisableMoveDirTimes() <= 0) { 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 DEBUG1 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)) { GetCar()->SetAttackDir(GetAttackDir()); } } } #ifdef DEBUG 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 DEBUG1 a8::XPrintf("attack_dir 0,0\n", {}); #endif } } else { #ifdef DEBUG1 a8::XPrintf("moving:%d times:%d\n", {moving ? 1 : 0, GetDisableAttackDirTimes()}); #endif if (moving && GetDisableAttackDirTimes() <= 0) { SetAttackDir(GetMoveDir()); if (GetCar() && GetCar()->IsDriver(this)) { 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(); 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()) { 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 = msg.throw_bomb(); } else { throw_bomb.reset(); } last_cmmove_frameno = room->GetFrameNo(); trace_target_uniid = msg.trace_target_uniid(); #ifdef DEBUG1 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 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::_CMImmediateMsg(f8::MsgHdr& hdr, const cs::CMImmediateMsg& msg) { if (msg.stop_move()) { moving = false; } if (msg.stop_shot()) { shot_start = false; shot_hold = false; series_shot_frames = 0; } } 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().GetX(), GetPos().GetY()})); } 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 == "killself") { float dmg_out = 0; float dmg = GetMaxHP() + 10; DecHP(dmg, VP_Gas, TEXT("battle_server_killer_gas", "毒圈"), VW_Gas, VP_Gas, TEXT("battle_server_killer_gas", "毒圈"), dmg_out); } 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}; // 999 #if 1 #else room->ShuaMon(GetPos(), mons, 100); #endif } else if (cmd == "jiuyuan") { TryAddBuff(this, kRescuerBuffId); int downed_relive_time = mt::Param::GetIntParam("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]); const mt::Buff* buff_meta = mt::Buff::GetById(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 == "autodie") { #if DEBUG if (cmds.size() >= 2) { if (cmds[1] == "open") { App::Instance()->debug_params[120] = 1; } else if (cmds[1] == "close") { App::Instance()->debug_params.erase(120); } } else { App::Instance()->debug_params[120] = 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.expired()) { room->xtimer.ModifyTime(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 (!FreezeOperate()) { DropWeapon(drop_weapon_idx, drop_num); } 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; } CancelRevive(); if (!dead) { BeKill(GetUniId(), name, 0, GetUniId(), name); } else { SendGameOver(); } } void Player::_CMWatchWar(f8::MsgHdr& hdr, const cs::CMWatchWar& msg) { 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) && GetBattleContext()->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); long long room_uuid = room->GetRoomUuid(); std::string account_id = account_id; auto target_uniid = msg.target_uniid(); HttpProxy::Instance()->HttpGet ( [room_uuid, account_id, target_uniid] (bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx) { Room* 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 = trace_bullet_hash_.find(msg.bullet_uniid()); #ifdef DEBUG a8::XPrintf("CMRequestBulletDmg bullet_uniid:%d shield_hit:%d strengthen_wall_uniid:%d target_uniid:%d found:%d\n", { msg.bullet_uniid(), msg.shield_hit(), msg.strengthen_wall_uniid(), msg.target_uniid(), itr == trace_bullet_hash_.end() ? 0 :1 }); #endif if (itr == trace_bullet_hash_.end()) { return; } auto& tuple = itr->second; Entity* bullet_entity = room->GetEntityByUniId(msg.bullet_uniid()); if (bullet_entity && bullet_entity->GetEntityType() == ET_Bullet) { Bullet* bullet = (Bullet*)bullet_entity; Entity* entity = room->GetEntityByUniId(msg.target_uniid()); if (entity && entity->IsCreature(room) && entity != this && !entity->IsDead(room)) { Creature* c = (Creature*)entity; float dmg = c->GetBattleContext()->CalcDmg(c, bullet); if (msg.strengthen_wall_uniid()) { dmg *= 2; } bool shield = false; if (dmg > 0.00001f) { if (msg.shield_hit()) { Buff* hold_shield_buff = c->GetBuffByEffectId(kBET_HoldShield); if (hold_shield_buff) { c->shield_hp_ = std::max(0.0f, c->shield_hp_ - dmg); room->frame_event.AddPropChg(c->GetWeakPtrRef(), kPropShieldHp, c->shield_max_hp_, c->shield_hp_); if (c->shield_hp_ <= 0) { c->GetTrigger()->ShieldDestory(); c->RemoveBuffByUniId(hold_shield_buff->buff_uniid); } shield = true; } } if (!shield) { bullet->strengthen_wall = msg.strengthen_wall_uniid() ? 1 : 0; std::set objects; objects.insert(c); bullet->OnHit(objects); #if 0 c->OnBulletHit(bullet); #endif } } #ifdef DEBUG a8::XPrintf("dmg:%f shield:%d\n", { dmg, shield ? 1 : 0 }); #endif } } trace_bullet_hash_.erase(itr); } 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::PushJoinRoomMsg() { if (!a8::HasBitFlag(status, CS_ForceTeam)) { cs::SMJoinedNotify notifymsg; notifymsg.set_error_code(0); 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()->map_id()); #if 1 notifymsg.set_map_id(1001); #endif notifymsg.set_map_width(room->GetMapMeta()->map_width()); notifymsg.set_map_height(room->GetMapMeta()->map_height()); notifymsg.set_room_mode((int)room->GetRoomMode()); notifymsg.set_server_info(JsonDataMgr::Instance()->server_info); notifymsg.set_player_id(GetUniId()); notifymsg.set_started(false); notifymsg.set_room_uuid(a8::XValue(room->GetRoomUuid()).GetString()); notifymsg.set_match_mode(GetBattleContext()->GetMatchMode()); notifymsg.set_pve_instance_id(room->pve_instance ? room->pve_instance->gemini_id() : 0); notifymsg.set_mapid(room->GetMapMeta()->map_id()); 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]); } } 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()) { 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[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::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; } GetBattleContext()->SetReviveCoin(revive_coin); room->frame_event.AddPropChg (GetWeakPtrRef(), kPropReviveCion, 0, GetBattleContext()->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)) { 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) { if (HasBuffEffect(kBET_Hide)) { RemoveBuffByEffectId(kBET_Hide); } --weapon.ammo; room->frame_event.AddPropChgEx ( GetWeakPtrRef(), kPropWeaponAmmo, weapon.weapon_idx, weapon.ammo, weapon.GetClipVolume(this), 0, true ); 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() ); room->frame_event.AddBullet ( room->AllocUniid(), GetWeakPtrRef(), equip_meta, 1, bomb_pos, bomb_dir, throw_bomb->fly_distance(), 0, 1 ); pending_throw_bomb[throw_bomb->throw_uniid()] = throw_bomb; int throw_uniid = throw_bomb->throw_uniid(); room->xtimer.SetTimeoutEx ( SERVER_FRAME_RATE * 15, [this, throw_uniid] (int event, const a8::Args* args) { if (a8::TIMER_DELETE_EVENT == event) { ProcThrowDmg(throw_uniid); } }, &room->xtimer_attacher_); } } } throw_bomb.reset(); }