1717 lines
58 KiB
C++
1717 lines
58 KiB
C++
#include "precompile.h"
|
|
|
|
#include <float.h>
|
|
|
|
#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"
|
|
|
|
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();
|
|
}
|
|
|
|
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);
|
|
#ifdef DEBUG
|
|
if (GetCar() && GetCar()->IsDriver(this)) {
|
|
GetCar()->SyncPos();
|
|
}
|
|
#endif
|
|
}
|
|
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 (jump) {
|
|
UpdateJump();
|
|
}
|
|
if (get_down) {
|
|
UpdateGetDown();
|
|
}
|
|
if (get_on) {
|
|
UpdateGetOn();
|
|
}
|
|
if (switch_seat) {
|
|
UpdateSwitchSeat();
|
|
}
|
|
if (shot_start || shot_hold) {
|
|
UpdateShot();
|
|
}
|
|
UpdateAiming();
|
|
if (use_skill) {
|
|
UpdateUseSkill();
|
|
}
|
|
if (has_use_item_id) {
|
|
UpdateUseItemId();
|
|
}
|
|
if (playing_skill) {
|
|
UpdateSkill();
|
|
}
|
|
}
|
|
}
|
|
|
|
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() && GetCar()->HasBuffEffect(kBET_Vertigo)) {
|
|
return;
|
|
}
|
|
if (HasBuffEffect(kBET_Passenger)) {
|
|
return;
|
|
}
|
|
if (HasBuffEffect(kBET_Camouflage)) {
|
|
RemoveBuffByEffectId(kBET_Camouflage);
|
|
}
|
|
++moved_frames;
|
|
if (moved_frames > 4) {
|
|
moving = false;
|
|
moved_frames = 0;
|
|
return;
|
|
}
|
|
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();
|
|
}
|
|
#ifdef DEBUG
|
|
room->CheckPartObjects();
|
|
#endif
|
|
}
|
|
|
|
void Player::UpdateShot()
|
|
{
|
|
if (dead ||
|
|
downed ||
|
|
room->IsWaitingStart() ||
|
|
HasBuffEffect(kBET_Jump)) {
|
|
shot_start = false;
|
|
shot_hold = false;
|
|
series_shot_frames = 0;
|
|
return;
|
|
}
|
|
if (HasBuffEffect(kBET_Vertigo)) {
|
|
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();
|
|
int old_car_shot_hole = GetCar()->shot_hole;
|
|
GetCar()->shoot_offset = shoot_offset;
|
|
GetCar()->shot_hole = GetSeat();
|
|
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;
|
|
}
|
|
shot_start = false;
|
|
return;
|
|
} else {
|
|
if (shot_start) {
|
|
shot_start = false;
|
|
Shot();
|
|
return;
|
|
}
|
|
Weapon* p_weapon = GetCurrWeapon();
|
|
if (second_weapon.meta) {
|
|
p_weapon = &second_weapon;
|
|
}
|
|
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 1
|
|
if (room->GetFrameNo() - last_cmmove_frameno >= 4) {
|
|
#else
|
|
if (series_shot_frames > 8) {
|
|
#endif
|
|
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 (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 (JsonDataMgr::Instance()->channel == kTouTiaoChannelId) {
|
|
item_num = 1;
|
|
}
|
|
#ifdef DEBUG
|
|
if (channel == kTouTiaoChannelId) {
|
|
item_num = 1;
|
|
}
|
|
#endif
|
|
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 ||
|
|
room->GetGasData().gas_mode == GasJump ||
|
|
HasBuffEffect(kBET_Fly)) {
|
|
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::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();
|
|
}
|
|
jump = false;
|
|
}
|
|
|
|
void Player::UpdateGetDown()
|
|
{
|
|
DoGetDown();
|
|
get_down = false;
|
|
}
|
|
|
|
void Player::UpdateGetOn()
|
|
{
|
|
DoGetOn(get_on);
|
|
get_on = 0;
|
|
}
|
|
|
|
void Player::UpdateSwitchSeat()
|
|
{
|
|
if (GetCar()) {
|
|
GetCar()->SwitchSeat(this, switch_seat - 1);
|
|
}
|
|
switch_seat = 0;
|
|
}
|
|
|
|
void Player::UpdateUseSkill()
|
|
{
|
|
if (HasBuffEffect(kBET_Vertigo)) {
|
|
return;
|
|
}
|
|
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;
|
|
}
|
|
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->TraverseHumanList(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 (GetCurrWeapon() != &weapons[GUN_SLOT2] && !FreezeOperate()) {
|
|
SetCurrWeapon(&weapons[GUN_SLOT1]);
|
|
}
|
|
} else if (weapons[GUN_SLOT2].weapon_id == 0) {
|
|
weapon = &weapons[GUN_SLOT2];
|
|
weapon->weapon_idx = GUN_SLOT2;
|
|
if (GetCurrWeapon() != &weapons[GUN_SLOT1] && !FreezeOperate()) {
|
|
SetCurrWeapon(&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;
|
|
case EQUIP_TYPE_SPOILS:
|
|
{
|
|
ProcSpoils(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);
|
|
switch (item_meta->i->_inventory_slot()) {
|
|
case IS_FRAG:
|
|
case IS_SMOKE:
|
|
{
|
|
Weapon* weapon = &weapons[SPEC1_SLOT_BEGIN +
|
|
(item_meta->i->_inventory_slot() - SPEC1_IS_BEGIN)
|
|
];
|
|
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);
|
|
}
|
|
break;
|
|
case IS_1XSCOPE:
|
|
case IS_2XSCOPE:
|
|
case IS_4XSCOPE:
|
|
case IS_8XSCOPE:
|
|
case IS_15XSCOPE:
|
|
{
|
|
if (item_meta->i->_inventory_slot() - IS_1XSCOPE > curr_scope_idx) {
|
|
curr_scope_idx = item_meta->i->_inventory_slot() - IS_1XSCOPE;
|
|
}
|
|
}
|
|
break;
|
|
case IS_POSION_GAS_BOMB:
|
|
case IS_MOLOTOR_COCKTAIL:
|
|
case IS_TRAP:
|
|
case IS_MINE:
|
|
{
|
|
Weapon* weapon = &weapons[SPEC2_SLOT_BEGIN +
|
|
(item_meta->i->_inventory_slot() - SPEC2_IS_BEGIN)
|
|
];
|
|
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);
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
#if 0
|
|
abort();
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
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->GetActionType() == 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<int> 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 (GetCurrWeapon() != &weapons[GUN_SLOT2]) {
|
|
SetCurrWeapon(&weapons[GUN_SLOT1]);
|
|
}
|
|
} else if (weapons[GUN_SLOT2].weapon_id == 0) {
|
|
weapon = &weapons[GUN_SLOT2];
|
|
weapon->weapon_idx = GUN_SLOT2;
|
|
if (GetCurrWeapon() != &weapons[GUN_SLOT1]) {
|
|
SetCurrWeapon(&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) {
|
|
if (GetCar()) {
|
|
abort();
|
|
}
|
|
Car* car = room->CreateCar
|
|
(
|
|
this,
|
|
car_uniid,
|
|
item_meta,
|
|
GetPos(),
|
|
team_id
|
|
);
|
|
car->GetOn(this);
|
|
}
|
|
}
|
|
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 (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 &&
|
|
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 = 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)) {
|
|
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
|
|
)
|
|
){
|
|
if (!HasBuffEffect(kBET_Vertigo)) {
|
|
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 {
|
|
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_get_on()) {
|
|
get_on = msg.get_on();
|
|
}
|
|
if (msg.has_switch_seat()) {
|
|
switch_seat = msg.has_switch_seat();
|
|
}
|
|
if (msg.has_jump()) {
|
|
jump = true;
|
|
}
|
|
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();
|
|
}
|
|
|
|
void Player::_CMExecCommand(f8::MsgHdr& hdr, const cs::CMExecCommand& msg)
|
|
{
|
|
std::vector<std::string> 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 == "shuaguai" && cmds.size() >= 3) {
|
|
int hero_id = a8::XValue(cmds[1]);
|
|
int hero_num = a8::XValue(cmds[2]);
|
|
std::vector<int> mons = std::vector<int>{hero_id};
|
|
room->ShuaMon(GetPos(), mons, 100);
|
|
} 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Player::UpdateDropWeapon()
|
|
{
|
|
if (drop_weapon_idx >= 0 &&
|
|
drop_weapon_idx < weapons.size() &&
|
|
!HasBuffEffect(kBET_Terminator) &&
|
|
!FreezeOperate()) {
|
|
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 (GetCurrWeapon() == weapon) {
|
|
if (weapons[GUN_SLOT2].weapon_id != 0) {
|
|
SetCurrWeapon(&weapons[GUN_SLOT2]);
|
|
} else {
|
|
SetCurrWeapon(&weapons[0]);
|
|
}
|
|
}
|
|
} else if (weapon->weapon_idx == GUN_SLOT2) {
|
|
drop_ok = true;
|
|
*weapon = Weapon();
|
|
weapon->weapon_idx = drop_weapon_idx;
|
|
if (GetCurrWeapon() == weapon) {
|
|
if (weapons[GUN_SLOT1].weapon_id != 0) {
|
|
SetCurrWeapon(&weapons[GUN_SLOT1]);
|
|
} else {
|
|
SetCurrWeapon(&weapons[0]);
|
|
}
|
|
}
|
|
} else if (weapon->weapon_idx == FRAG_SLOT) {
|
|
drop_ok = true;
|
|
*weapon = Weapon();
|
|
weapon->weapon_idx = drop_weapon_idx;
|
|
if (GetCurrWeapon() == weapon) {
|
|
if (weapons[GUN_SLOT1].weapon_id != 0) {
|
|
SetCurrWeapon(&weapons[GUN_SLOT1]);
|
|
} else if (weapons[GUN_SLOT2].weapon_id != 0) {
|
|
SetCurrWeapon(&weapons[GUN_SLOT2]);
|
|
} else {
|
|
SetCurrWeapon(&weapons[0]);
|
|
}
|
|
}
|
|
} else if (weapon->weapon_idx == SMOKE_SLOT) {
|
|
drop_ok = true;
|
|
*weapon = Weapon();
|
|
weapon->weapon_idx = drop_weapon_idx;
|
|
if (GetCurrWeapon() == weapon) {
|
|
if (weapons[GUN_SLOT1].weapon_id != 0) {
|
|
SetCurrWeapon(&weapons[GUN_SLOT1]);
|
|
} else if (weapons[GUN_SLOT2].weapon_id != 0) {
|
|
SetCurrWeapon(&weapons[GUN_SLOT2]);
|
|
} else {
|
|
SetCurrWeapon(&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->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)
|
|
{
|
|
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::_CMGetBoxInfo(f8::MsgHdr& hdr, const cs::CMGetBoxInfo& msg)
|
|
{
|
|
cs::SMGetBoxInfo respmsg;
|
|
respmsg.set_box_id(msg.box_id());
|
|
std::vector<std::tuple<int, int, int>>* 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<std::tuple<int, int, int>>* 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, 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<std::string> 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<std::string> 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<std::tuple<int, int, int>>* 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;
|
|
if (room->GetRoomMode() == kZombieMode) {
|
|
drop_id = MetaMgr::Instance()->prebattle_box_id_zb;
|
|
} else {
|
|
drop_id = MetaMgr::Instance()->prebattle_box_id_chiji;
|
|
}
|
|
MetaData::Drop* drop_meta = MetaMgr::Instance()->GetDrop(drop_id);
|
|
if (drop_meta) {
|
|
std::vector<std::tuple<int, int, int>> 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)) {
|
|
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::CheckShotHoldState(Weapon* weapon)
|
|
{
|
|
if (weapon->meta->buff_meta && weapon->meta->buff_meta->i->trigger_type() == kBTT_SeriesShot) {
|
|
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);
|
|
}
|