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