#include "precompile.h" #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 "app.h" #include "collider.h" #include "typeconvert.h" #include "playermgr.h" #include "perfmonitor.h" #include "jsondatamgr.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; skill_meta_ = MetaMgr::Instance()->GetSkill(41001); RecalcBaseAttr(); } 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 (HasSpecMove()) { _UpdateSpecMove(); } else { 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 (get_down) { UpdateGetDown(); } if (shot_start || shot_hold) { UpdateShot(); } if (use_skill) { UpdateUseSkill(); } if (aiming) { if (HasBuffEffect(kBET_Camouflage)) { RemoveBuffByEffectId(kBET_Camouflage); } } if (has_use_item_id) { UpdateUseItemId(); } } } 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 (HasBuffEffect(kBET_Camouflage)) { RemoveBuffByEffectId(kBET_Camouflage); } ++moved_frames; if (moved_frames > 4) { moving = false; moved_frames = 0; return; } _UpdateMove(std::max(1, (int)GetSpeed())); if (GetLastCollisionDoor() && !TestCollision(room, GetLastCollisionDoor())) { SetLastCollisionDoor(nullptr); } #if 0 a8::Vec2 old_pos = GetPos(); if (tank_weapon.meta) { CheckSkinTank(); tank_oil_value -= old_pos.Distance(GetPos()) * (MetaMgr::Instance()->average_oil / 100.0f); tank_oil_value = std::max(0.0f, tank_oil_value); } #endif #ifdef DEBUG room->CheckPartObjects(); #endif } void Player::UpdateShot() { if (dead || downed || room->IsWaitingStart()) { shot_start = false; shot_hold = false; series_shot_frames = 0; return; } if (HasBuffEffect(kBET_Vertigo)) { return; } if (shot_start) { shot_start = false; Shot(); return; } Weapon* p_weapon = curr_weapon; if (car_weapon.meta) { p_weapon = &car_weapon; } if (shot_hold) { ++series_shot_frames; if (last_shot_frameno_ == 0 || ( (room->GetFrameNo() - last_shot_frameno_) * (1000 / SERVER_FRAME_RATE)) >= p_weapon->GetAttrValue(kHAT_FireRate) ) { Shot(); } if (series_shot_frames > 8) { shot_hold = false; series_shot_frames = 0; } } if (HasBuffEffect(kBET_Camouflage)) { RemoveBuffByEffectId(kBET_Camouflage); } } void Player::UpdateSelectWeapon() { if (selected_weapon_idx >= 0 && selected_weapon_idx < weapons.size()) { Weapon* old_weapon = curr_weapon; Weapon* weapon = &weapons[selected_weapon_idx]; if (weapon->weapon_id != 0) { curr_weapon = 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 (downed) { return; } if (use_item_idx >= 0 && use_item_idx < IS_END) { switch (use_item_idx) { case IS_HEALTHKIT: { MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquipBySlotId(use_item_idx); if (item_meta) { StartAction( AT_UseItem, item_meta->i->use_time(), use_item_idx, 0 ); } } break; case IS_PAIN_KILLER: { MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquipBySlotId(use_item_idx); if (item_meta) { StartAction( AT_UseItem, item_meta->i->use_time(), use_item_idx, 0 ); } } break; default: { } break; } } use_item_idx = 0; use_item = false; } void Player::UpdateUseItemId() { if (downed) { return; } MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquip(use_item_id); if (item_meta && item_meta->i->equip_type() == EQUIP_TYPE_CAMOUFLAGE) { int item_num = GetItemNum(use_item_id); if (item_num > 0) { MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(item_meta->i->buffid()); if (buff_meta && !GetBuffById(item_meta->i->buffid())) { if (HasBuffEffect(kBET_Camouflage)) { RemoveBuffByEffectId(kBET_Camouflage); } AddBuff(this, buff_meta, 1); DecItem(use_item_id, 1); } } } use_item_id = 0; has_use_item_id = false; } void Player::UpdateSpectate() { if (room->GetGasData().gas_mode == GasInactive) { spectate = false; return; } BeKill(GetEntityUniId(), name, VW_Spectate); spectate = false; } void Player::UpdateEmote() { room->frame_event.AddEmote(this, emote_id); emote = false; emote_id = 0; } void Player::UpdateGetDown() { DoGetDown(); get_down = false; } void Player::UpdateUseSkill() { if (HasBuffEffect(kBET_Vertigo)) { return; } DoSkill(); } void Player::Shot() { if (car_weapon.meta) { CarShot(attack_dir); return; } if (!curr_weapon->meta) { return; } if (curr_weapon->weapon_idx != 0 && curr_weapon->ammo <= 0) { AutoLoadingBullet(); return; } if (action_type == AT_Reload) { CancelAction(); } if (action_type == AT_Reload || action_type == AT_Rescue || action_type == AT_UseItem || action_type == AT_Relive) { CancelAction(); } InternalShot(this, curr_weapon->meta, curr_weapon->GetUpgradeMeta(), curr_weapon->bullet_meta, curr_weapon->weapon_lv, 0, fly_distance, false); if (curr_weapon->weapon_idx != 0) { --curr_weapon->ammo; } int slot_id = curr_weapon->meta->i->_inventory_slot(); //扔完手雷,如无手雷,则优先换武器1>武器2 switch (slot_id) { case 5: { //手雷 if (curr_weapon->ammo <= 0) { if (GetInventory(slot_id) > 0) { DecInventory(slot_id, 1); ++curr_weapon->ammo; } else { int weapon_idx = curr_weapon->weapon_idx; *curr_weapon = Weapon(); curr_weapon->weapon_idx = weapon_idx; if (weapons[SMOKE_SLOT].weapon_id != 0) { curr_weapon = &weapons[SMOKE_SLOT]; } else { AutoChgWeapon(); } AutoLoadingBullet(); } } need_sync_active_player = true; SyncAroundPlayers(__FILE__, __LINE__, __func__); } break; case 6: { //烟雾弹 if (curr_weapon->ammo <= 0) { if (GetInventory(slot_id) > 0) { DecInventory(slot_id, 1); ++curr_weapon->ammo; } else { int weapon_idx = curr_weapon->weapon_idx; *curr_weapon = Weapon(); curr_weapon->weapon_idx = weapon_idx; if (weapons[FRAG_SLOT].weapon_id != 0) { curr_weapon = &weapons[FRAG_SLOT]; } else { AutoChgWeapon(); } AutoLoadingBullet(); } } need_sync_active_player = true; SyncAroundPlayers(__FILE__, __LINE__, __func__); } break; } if (curr_weapon->weapon_idx != 0 && curr_weapon->ammo <= 0) { AutoLoadingBullet(); } last_shot_frameno_ = room->GetFrameNo(); room->frame_event.AddWeaponAmmoChg(this); } void Player::ProcInteraction() { if (room->GetGasData().gas_mode == GasInactive) { return; } for (auto obj_id : interaction_objids) { Entity* entity = room->GetEntityByUniId(obj_id); if (entity) { switch (entity->GetEntityType()) { case ET_Obstacle: { ObstacleInteraction((Obstacle*)entity); } break; case ET_Loot: { LootInteraction((Loot*)entity); } break; case ET_Player: { HumanInteraction((Human*)entity); } break; default: break; } } } interaction_objids.Clear(); } void Player::ObstacleInteraction(Obstacle* entity) { if (entity->IsDoor()) { if (entity->GetDoorState(room) == DoorStateClose) { entity->SetDoorState(room, DoorStateOpen); float x = entity->GetBuilding()->GetX() + entity->GetDoorState1()->x() - entity->GetBuilding()->meta->i->tilewidth() / 2.0; float y = entity->GetBuilding()->GetY() + entity->GetDoorState1()->y() - entity->GetBuilding()->meta->i->tileheight() / 2.0; entity->SetPos(a8::Vec2(x, y)); } else { entity->SetDoorState(room, DoorStateClose); float x = entity->GetBuilding()->GetX() + entity->GetDoorState0()->x() - entity->GetBuilding()->meta->i->tilewidth() / 2.0; float y = entity->GetBuilding()->GetY() + entity->GetDoorState0()->y() - entity->GetBuilding()->meta->i->tileheight() / 2.0; entity->SetPos(a8::Vec2(x, y)); } entity->IncDoorOpenTimes(room); entity->RecalcSelfCollider(); room->TouchHumanList(a8::XParams(), [entity] (Human* hum, a8::XParams& param) -> bool { hum->AddToNewObjects(entity); if (entity->TestCollision(hum->room, hum)) { hum->SetLastCollisionDoor(entity); } else if (hum->GetLastCollisionDoor() == entity) { hum->SetLastCollisionDoor(nullptr); } return true; }); } } void Player::LootInteraction(Loot* entity) { if (room->GetRoomMode() == kZombieMode && GetRace() == kZombieRace) { return; } if (entity->pickuped || entity->count <= 0) { return; } MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquip(entity->item_id); if (!item_meta) { return; } switch (item_meta->i->equip_type()) { case EQUIP_TYPE_WEAPON: { //装备 if (item_meta->i->equip_subtype() == 1) { //近战 if (default_weapon.weapon_id != weapons[0].weapon_id) { /* cs::SMPickup notifymsg; notifymsg.set_error_code(2); SendNotifyMsg(notifymsg); */ return; } else { weapons[0].weapon_idx = 0; weapons[0].weapon_id = entity->item_id; #if 1 weapons[0].weapon_lv = std::max(1, entity->item_level); #else weapons[0].weapon_lv = std::max(1, GetWeaponConfigLv(weapons[0].weapon_id)); #endif weapons[0].ammo = 0; weapons[0].meta = item_meta; weapons[0].Recalc(); } need_sync_active_player = true; SyncAroundPlayers(__FILE__, __LINE__, __func__); } else { Weapon* weapon = nullptr; if (weapons[GUN_SLOT1].weapon_id == 0) { weapon = &weapons[GUN_SLOT1]; weapon->weapon_idx = GUN_SLOT1; if (curr_weapon != &weapons[GUN_SLOT2]) { curr_weapon = &weapons[GUN_SLOT1]; } } else if (weapons[GUN_SLOT2].weapon_id == 0) { weapon = &weapons[GUN_SLOT2]; weapon->weapon_idx = GUN_SLOT2; if (curr_weapon != &weapons[GUN_SLOT1]) { curr_weapon = &weapons[GUN_SLOT2]; } } if (!weapon) { /* cs::SMPickup notifymsg; notifymsg.set_error_code(2); SendNotifyMsg(notifymsg); */ return; } weapon->weapon_id = entity->item_id; #if 1 weapon->weapon_lv = std::max(1, entity->item_level); #else weapon->weapon_lv = std::max(1, GetWeaponConfigLv(weapon->weapon_id)); #endif weapon->ammo = 0; weapon->meta = item_meta; weapon->Recalc(); if (room->GetRoomMode() == kZombieMode && HasBuffEffect(kBET_Car)) { } else { AutoLoadingBullet(); } need_sync_active_player = true; SyncAroundPlayers(__FILE__, __LINE__, __func__); } if (room->GetRoomType() == RT_NewBrid && !a8::HasBitFlag(status, HS_AlreadyEquip)) { a8::SetBitFlag(status, HS_AlreadyEquip); ProcNewBieLogic(); } } break; case EQUIP_TYPE_OLDSKIN: { abort(); } break; case EQUIP_TYPE_SKIN: { ProcLootSkin(entity, item_meta); } break; case EQUIP_TYPE_CAR: { ProcLootCar(entity, item_meta); } break; case EQUIP_TYPE_CAMOUFLAGE: { ProcCamoutflage(entity, item_meta); } break; default: { 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()) ) { /* cs::SMPickup notifymsg; notifymsg.set_error_code(1); SendNotifyMsg(notifymsg); */ return; } int add_num = GetVolume(item_meta->i->_inventory_slot()) - GetInventory(item_meta->i->_inventory_slot()); add_num = std::min(entity->count, add_num); AddInventory(item_meta->i->_inventory_slot(), add_num); if (item_meta->i->_inventory_slot() == 5 || item_meta->i->_inventory_slot() == 6) { Weapon* weapon = &weapons[3 + (item_meta->i->_inventory_slot() - 5)]; weapon->weapon_id = entity->item_id; weapon->weapon_lv = 1; weapon->ammo += entity->count; weapon->meta = item_meta; weapon->Recalc(); DecInventory(item_meta->i->_inventory_slot(), add_num); } if (item_meta->i->_inventory_slot() > 12) { if (item_meta->i->_inventory_slot() - 12 > curr_scope_idx) { curr_scope_idx = item_meta->i->_inventory_slot() - 12; } } if (add_num < entity->count) { //刷新数量 entity->count -= add_num; entity->BroadcastFullState(room); return; } } else { switch (item_meta->i->equip_type()) { case 7: { //背包 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()) { return; } room->DropItem(GetPos(), old_item_meta->i->id(), 1, 1); } backpack = item_meta->i->id(); RecalcVolume(); } break; case 4: { //防具 if (item_meta->i->equip_subtype() == 1) { //盔甲 MetaData::Equip* old_item_meta = MetaMgr::Instance()->GetEquip(chest); if (old_item_meta) { if (old_item_meta->i->equip_lv() >= item_meta->i->equip_lv()) { return; } room->DropItem(GetPos(), old_item_meta->i->id(), 1, 1); } chest = item_meta->i->id(); RecalcBaseAttr(); } else if (item_meta->i->equip_subtype() == 2) { //头盔 MetaData::Equip* old_item_meta = MetaMgr::Instance()->GetEquip(helmet); if (old_item_meta) { if (old_item_meta->i->equip_lv() >= item_meta->i->equip_lv()) { return; } room->DropItem(GetPos(), old_item_meta->i->id(), 1, 1); } helmet = item_meta->i->id(); RecalcBaseAttr(); } } break; } } if (action_type == AT_None) { AutoLoadingBullet(); } need_sync_active_player = true; SyncAroundPlayers(__FILE__, __LINE__, __func__); } break; } entity->pickuped = true; room->RemoveObjectLater(entity); } void Player::HumanInteraction(Human* hum) { if (downed) { return; } if (hum == this) { return; } if (!hum->downed) { return; } if (hum->action_type == AT_Rescue) { return; } hum->StartAction( AT_Rescue, MetaMgr::Instance()->GetSysParamAsInt("downed_relive_time") * 1000, room->GetFrameNo(), GetEntityUniId() ); StartAction( AT_Relive, MetaMgr::Instance()->GetSysParamAsInt("downed_relive_time") * 1000, room->GetFrameNo(), hum->GetEntityUniId() ); } 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) { switch (item_meta->i->equip_type()) { case EQUIP_TYPE_WEAPON: { //装备 if (item_meta->i->equip_subtype() == 1) { //近战 if (default_weapon.weapon_id == weapons[0].weapon_id) { weapons[0].weapon_idx = 0; weapons[0].weapon_id = equip_id; weapons[0].weapon_lv = std::max(1, GetWeaponConfigLv(weapons[0].weapon_id)); weapons[0].ammo = 0; weapons[0].meta = item_meta; weapons[0].Recalc(); } } else { Weapon* weapon = nullptr; if (weapons[GUN_SLOT1].weapon_id == 0) { weapon = &weapons[GUN_SLOT1]; weapon->weapon_idx = GUN_SLOT1; if (curr_weapon != &weapons[GUN_SLOT2]) { curr_weapon = &weapons[GUN_SLOT1]; } } else if (weapons[GUN_SLOT2].weapon_id == 0) { weapon = &weapons[GUN_SLOT2]; weapon->weapon_idx = GUN_SLOT2; if (curr_weapon != &weapons[GUN_SLOT1]) { curr_weapon = &weapons[GUN_SLOT2]; } } if (weapon) { weapon->weapon_id = equip_id; weapon->weapon_lv = std::max(1, GetWeaponConfigLv(weapon->weapon_id)); weapon->ammo = 0; weapon->meta = item_meta; weapon->Recalc(); } } } break; case EQUIP_TYPE_CAR: { int car_uniid = room->CreateAndTakeonCar(item_meta->i->id(), GetPos()); if (car_uniid != -1) { car_.car_uniid = car_uniid; car_.car_id = item_meta->i->id(); car_.meta = item_meta; MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(car_.meta->i->buffid()); if (buff_meta) { AddBuff(this, buff_meta, 1); } } } break; default: { 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()) ) { break; } int add_num = GetVolume(item_meta->i->_inventory_slot()) - GetInventory(item_meta->i->_inventory_slot()); add_num = std::min(1, add_num); AddInventory(item_meta->i->_inventory_slot(), add_num); if (item_meta->i->_inventory_slot() == 5 || item_meta->i->_inventory_slot() == 6) { Weapon* weapon = &weapons[3 + (item_meta->i->_inventory_slot() - 5)]; weapon->weapon_id = equip_id; weapon->weapon_lv = 1; weapon->ammo += 1; weapon->meta = item_meta; weapon->Recalc(); DecInventory(item_meta->i->_inventory_slot(), add_num); } if (item_meta->i->_inventory_slot() > 12) { if (item_meta->i->_inventory_slot() - 12 > curr_scope_idx) { curr_scope_idx = item_meta->i->_inventory_slot() - 12; } } } else { switch (item_meta->i->equip_type()) { case 7: { //背包 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; case 4: { //防具 if (item_meta->i->equip_subtype() == 1) { //盔甲 MetaData::Equip* old_item_meta = MetaMgr::Instance()->GetEquip(chest); 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); } chest = item_meta->i->id(); RecalcBaseAttr(); } else if (item_meta->i->equip_subtype() == 2) { //头盔 MetaData::Equip* old_item_meta = MetaMgr::Instance()->GetEquip(helmet); 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); } helmet = item_meta->i->id(); RecalcBaseAttr(); } } break; } } } break; } } }//end for if (curr_weapon) { MetaData::Equip* bullet_meta = MetaMgr::Instance()->GetEquip(curr_weapon->meta->i->use_bullet()); if (bullet_meta) { int add_num = GetInventory(bullet_meta->i->_inventory_slot()); add_num = curr_weapon->GetClipVolume(); curr_weapon->ammo = add_num; } } for (auto& spec_weapon : spec_weapons) { MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquip(spec_weapon.weapon_id); if (item_meta && item_meta->i->equip_type() == EQUIP_TYPE_WEAPON) { 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 = spec_weapon.weapon_id; weapon->weapon_lv = spec_weapon.weapon_lv; weapon->ammo = spec_weapon.ammo; weapon->meta = item_meta; weapon->Recalc(); curr_weapon = &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::_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; TouchAllLayerHumanList ( [this] (Human* hum, bool& stop) { AddToNewObjects(hum); } ); need_sync_active_player = true; cs::SMReconnect respmsg; respmsg.set_errcode(0); respmsg.set_errmsg("战斗重连成功"); 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) { 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; TypeConvert::FromPb(move_dir, &msg.move_dir()); move_dir.Normalize(); moving = true; } } assert(!isnan(move_dir.x) && !isnan(move_dir.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 ) ){ TypeConvert::FromPb(attack_dir, &msg.attack_dir()); attack_dir.Normalize(); } } else { if (moving) { attack_dir = move_dir; } } if (moving) { moved_frames = 0; } shot_start = msg.shot_start(); shot_hold = msg.shot_hold(); fly_distance = std::min(200.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_use_skill()) { use_skill = msg.use_skill(); skill_target_id = msg.skill_target_id(); } else { use_skill = false; } last_cmmove_frameno = room->GetFrameNo(); } void Player::UpdateDropWeapon() { if (drop_weapon_idx >= 0 && drop_weapon_idx < weapons.size() && !HasBuffEffect(kBET_Terminator)) { bool drop_ok = false; Weapon* weapon = &weapons[drop_weapon_idx]; int weapon_id = weapon->weapon_id; int weapon_lv = weapon->weapon_lv; int weapon_ammo = weapon->ammo; MetaData::Equip* weapon_meta = weapon->meta; if (weapon->weapon_id != 0) { if (weapon->weapon_idx == 0) { if (weapon->weapon_id != default_weapon.weapon_id) { drop_ok = true; *weapon = default_weapon; } } else if (weapon->weapon_idx == GUN_SLOT1) { drop_ok = true; *weapon = Weapon(); weapon->weapon_idx = drop_weapon_idx; if (curr_weapon == weapon) { if (weapons[GUN_SLOT2].weapon_id != 0) { curr_weapon = &weapons[GUN_SLOT2]; } else { curr_weapon = &weapons[0]; } } } else if (weapon->weapon_idx == GUN_SLOT2) { drop_ok = true; *weapon = Weapon(); weapon->weapon_idx = drop_weapon_idx; if (curr_weapon == weapon) { if (weapons[GUN_SLOT1].weapon_id != 0) { curr_weapon = &weapons[GUN_SLOT1]; } else { curr_weapon = &weapons[0]; } } } else if (weapon->weapon_idx == FRAG_SLOT) { drop_ok = true; *weapon = Weapon(); weapon->weapon_idx = drop_weapon_idx; if (curr_weapon == weapon) { if (weapons[GUN_SLOT1].weapon_id != 0) { curr_weapon = &weapons[GUN_SLOT1]; } else if (weapons[GUN_SLOT2].weapon_id != 0) { curr_weapon = &weapons[GUN_SLOT2]; } else { curr_weapon = &weapons[0]; } } } else if (weapon->weapon_idx == SMOKE_SLOT) { drop_ok = true; *weapon = Weapon(); weapon->weapon_idx = drop_weapon_idx; if (curr_weapon == weapon) { if (weapons[GUN_SLOT1].weapon_id != 0) { curr_weapon = &weapons[GUN_SLOT1]; } else if (weapons[GUN_SLOT2].weapon_id != 0) { curr_weapon = &weapons[GUN_SLOT2]; } else { curr_weapon = &weapons[0]; } } } if (drop_ok) { if (drop_weapon_idx == 0 || drop_weapon_idx == GUN_SLOT1 || drop_weapon_idx == GUN_SLOT2 || drop_weapon_idx == FRAG_SLOT || drop_weapon_idx == SMOKE_SLOT ) { a8::Vec2 dir = a8::Vec2::UP; dir.Rotate(a8::RandAngle()); room->CreateLoot(weapon_id, GetPos() + dir * (40 + rand() % 50), 1, weapon_lv); } if (weapon_ammo > 0) { MetaData::Equip* bullet_meta = MetaMgr::Instance()->GetEquip(weapon_meta->i->use_bullet()); if (bullet_meta && bullet_meta->i->_inventory_slot() > 0) { int volume = GetVolume(bullet_meta->i->_inventory_slot()); int inventory = GetInventory(bullet_meta->i->_inventory_slot()); int add_inventory = std::min(weapon_ammo, volume - std::min(volume, inventory)); if (add_inventory > 0 && !(drop_weapon_idx == FRAG_SLOT || drop_weapon_idx == SMOKE_SLOT)) { AddInventory(bullet_meta->i->_inventory_slot(), add_inventory); } int drop_num = weapon_ammo - add_inventory; if (drop_num > 0) { a8::Vec2 drop_dir = a8::Vec2::UP; drop_dir.Rotate(a8::RandAngle()); a8::Vec2 drop_pos = GetPos() + drop_dir * (25 + rand() % 50); if (bullet_meta->i->_inventory_slot() == IS_FRAG || bullet_meta->i->_inventory_slot() == IS_SMOKE) { //只有手雷和烟雾弹会掉落 room->DropItem(drop_pos, bullet_meta->i->id(), drop_num, 1); } } } } need_sync_active_player = true; SyncAroundPlayers(__FILE__, __LINE__, __func__); } } } 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->TouchPlayerList(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) { cs::SMWatchWar respmsg; Human* target = room->GetWatchWarTarget(this); if (target) { SendNotifyMsg(respmsg); hdr.hum->FollowTarget(target); } else { respmsg.set_error_code(1); SendNotifyMsg(respmsg); } } void Player::_CMLeave(f8::MsgHdr& hdr, const cs::CMLeave& msg) { if (!leave_) { if (room->BattleStarted()) { //如果战斗已经开始算自杀 BeKill(GetEntityUniId(), name, VW_Spectate); } 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(); ability.hp = 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, HS_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::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, HS_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, HS_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() { { 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()); GGListener::Instance()->SendToClient(socket_handle, 0, notifymsg); } } 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]); } }