aozhiwei d7f09c299f 1
2024-08-23 21:43:17 +08:00

3754 lines
119 KiB
C++

#include "precompile.h"
#include <math.h>
#include <float.h>
#include <a8/mutable_xobject.h>
#include <a8/collision.h>
#include <f8/utils.h>
#include <f8/udplog.h>
#include "human.h"
#include "room.h"
#include "bullet.h"
#include "loot.h"
#include "app.h"
#include "roommgr.h"
#include "android.h"
#include "gamelog.h"
#include "typeconvert.h"
#include "obstacle.h"
#include "roomobstacle.h"
#include "player.h"
#include "buff.h"
#include "car.h"
#include "roomobstacle.h"
#include "jsondatamgr.h"
#include "skill.h"
#include "incubator.h"
#include "team.h"
#include "explosion.h"
#include "killmgr.h"
#include "tracemgr.h"
#include "httpproxy.h"
#include "skillhelper.h"
#include "shot.h"
#include "netdata.h"
#include "mapinstance.h"
#include "movement.h"
#include "pbutils.h"
#include "trigger.h"
#include "ability.h"
#include "stats.h"
#include "hero.h"
#include "bornpoint.h"
#include "ingamevoice.h"
#include "boxdrop.h"
#include "buff/sprint.h"
#include "mt/Param.h"
#include "mt/Hero.h"
#include "mt/Equip.h"
#include "mt/Buff.h"
#include "mt/Skill.h"
#include "mt/SkillNumber.h"
#include "mt/SafeArea.h"
#include "mt/MapThing.h"
#include "mt/Text.h"
#include "mt/Map.h"
#include "mt/PveGemini.h"
#include "mt/PveGeminiMode.h"
#include "mt/RankReward.h"
#include "mt/RankPoint.h"
#include "mt/KillReward.h"
#include "mt/KillPoint.h"
#include "mt/Drop.h"
#include "mt/MergeItem.h"
#include "mt/BattleBasicAttribute.h"
#include "mt/BattleHeroGrow.h"
#include "mt/MobaRoom.h"
#include "pbutils.h"
Human::Human():Creature()
{
default_weapon.weapon_idx = 0;
default_weapon.weapon_id = 30102;
default_weapon.ammo = 1;
default_weapon.meta = mt::Equip::GetById(default_weapon.weapon_id);
default_weapon.Recalc();
for (int i = 0; i < kSkinNum; ++i) {
Skin& skin = a8::FastAppend(skins);
skin.skin_id = 0;
skin.skin_lv = 1;
}
weapons[0] = default_weapon;
if (mt::Param::s().fighting_mode) {
AddInventory(IS_9MM, FIGHTING_MODE_BULLET_NUM);
AddInventory(IS_556MM, FIGHTING_MODE_BULLET_NUM);
AddInventory(IS_762MM, FIGHTING_MODE_BULLET_NUM);
AddInventory(IS_12GAUGE, FIGHTING_MODE_BULLET_NUM);
AddInventory(IS_RPG, FIGHTING_MODE_BULLET_NUM);
AddInventory(IS_ICE, FIGHTING_MODE_BULLET_NUM);
}
stats = std::make_shared<PlayerStats>();
}
Human::~Human()
{
SetDestorying();
int i = 0;
}
void Human::Initialize()
{
Creature::Initialize();
volume_ = meta->_volume;
observers_.insert(this);
SetCurrWeapon(&weapons[0]);
SetOxygen(mt::Param::s().dive_oxygen_total);
}
bool Human::IsDead(Room * room)
{
return dead;
}
long long Human::GetDeadFrameNo(Room* room)
{
return dead_frameno;
}
long long Human::GetRealDeadFrameNo(Room* room)
{
return real_dead_frameno;
}
void Human::CarShot(const glm::vec3& target_dir)
{
if (!second_weapon.meta) {
return;
}
if (second_weapon.weapon_idx != 0 &&
second_weapon.ammo <= 0) {
AutoLoadingBullet();
return;
}
if (action_type == AT_Reload) {
CancelAction();
}
if (action_type == AT_Reload ||
action_type == AT_Rescue ||
action_type == AT_UseItem ||
action_type == AT_Relive) {
CancelAction();
}
InternalShot(this,
second_weapon.meta,
second_weapon.bullet_meta,
nullptr,
5,
0,
0);
--second_weapon.ammo;
last_shot_frameno_ = room->GetFrameNo();
}
void Human::BeKill(int killer_id, const std::string& killer_name, int weapon_id,
int real_killer_id, const std::string& real_killer_name)
{
if (!dead && !room->IsGameOver() && !real_dead && !a8::HasBitFlag(status, CS_PreDieSuspended)) {
GetTrigger()->PreDie(killer_id, weapon_id);
#ifdef MYDEBUG
{
if (!f8::IsTestEnv()) {
a8::XPrintf("BeKill killer_id:%d killer_name:%s over_delay_time:%d\n",
{
killer_id,
killer_name,
over_delay_time
});
}
}
#endif
if (over_delay_time > 0) {
std::shared_ptr<KillInfo> info = std::make_shared<KillInfo>();
info->killer_id = killer_id;
info->killer_name = killer_name;
info->weapon_id = weapon_id;
info->real_killer_id = real_killer_id;
info->real_killer_name = real_killer_name;
a8::SetBitFlag(status, CS_PreDieSuspended);
room->xtimer.SetTimeoutEx
(over_delay_time / FRAME_RATE_MS,
[this, info] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
over_delay_time = 0;
a8::UnSetBitFlag(status, CS_PreDieSuspended);
InternalBeKill
(
info->killer_id,
info->killer_name,
info->weapon_id,
info->real_killer_id,
info->real_killer_name
);
}
},
&xtimer_attacher);
} else {
InternalBeKill(killer_id, killer_name, weapon_id, real_killer_id, real_killer_name);
}
}
}
void Human::DecHP(float dec_hp, int killer_id, const std::string killer_name, int weapon_id,
int real_killer_id, const std::string real_killer_name,
float& real_dmg_out,
int dmg_type,
int dmg_bp)
{
real_dmg_out = 0.0f;
if (!room->BattleStarted()) {
return;
}
#ifdef MYDEBUG
if (a8::HasBitFlag(status, CS_NoDie)) {
return;
}
if (dmg_bp > 0) {
int i = 0;
}
#endif
#ifdef MYDEBUG
#if 0
if (IsPlayer()) {
return;
}
#endif
#endif
{
#if 0
Buff* buff = GetBuffByEffectId(kBET_Shield);
if (buff) {
dec_hp = std::max((float)1.0, dec_hp - buff->meta->_buff_param2);
}
#endif
}
if (HasBuffEffect(kBET_Invincible) && killer_id != VP_Gas) {
return;
}
{
Human* hum = room->GetHumanByUniId(real_killer_id);
if (hum) {
attacker_hash_[real_killer_id] = room->GetFrameNo();
}
}
struct DownedInfo
{
int killer_id = 0;
std::string killer_name;
int weapon_id = 0;
int real_killer_id = 0;
std::string real_killer_name;
};
last_receive_dmg_frameno = room->GetFrameNo();
float old_hp = GetHP();
if (armor_shield > 0.0001f){
float old_armor_shield = armor_shield;
armor_shield = std::max(0.0f, armor_shield - dec_hp);
if (old_armor_shield - armor_shield > 0.001f) {
real_dmg_out = old_armor_shield - armor_shield;
}
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropArmorShield,
armor_shield,
max_armor_shield,
false);
GetTrigger()->ReceiveDmg();
} else if (energy_shield > 0.001f) {
float old_energy_shield = energy_shield;
energy_shield = std::max(0.0f, energy_shield - dec_hp);
if (old_energy_shield - energy_shield > 0.001f) {
real_dmg_out = old_energy_shield - energy_shield;
}
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropEnergyShield,
energy_shield,
max_energy_shield,
false);
GetTrigger()->ReceiveDmg();
if (energy_shield <= 0) {
GetTrigger()->DestoryEnergyShield();
}
} else {
float old_health = GetHP();
float new_health = std::max(0.0f, GetHP() - dec_hp);
AdjustDecHp(old_health, new_health);
SetHP(std::max(0.0f, new_health));
if (old_health - GetHP() > 0.001f) {
stats->damage_amount_in += old_health - GetHP();
real_dmg_out = old_health - GetHP();
GetTrigger()->ReceiveDmg();
}
if (GetHP() <= 0.0001f && !dead) {
if (downed) {
if (!downed_timer.expired()) {
room->xtimer.Delete(downed_timer);
}
downed = false;
BeKill(killer_id, killer_name, weapon_id, real_killer_id, real_killer_name);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
} else {
if ((mt::Param::s().downed_switch && HasNoDownedTeammate() && !room->IsPveRoom() &&
!room->IsMobaModeRoom()) ||
GetInventory(IS_SHEN_BAO) > 0) {
SetHP(GetMaxHP() *
std::min(1.0f, (float)mt::Param::GetFloatParam("downed_recover_hp")));
downed = true;
if (HasBuffEffect(kBET_Camouflage)) {
RemoveBuffByEffectId(kBET_Camouflage);
}
CancelAction();
DoGetDown();
std::shared_ptr<DownedInfo> info = std::make_shared<DownedInfo>();
info->killer_id = killer_id;
info->killer_name = killer_name;
info->weapon_id = weapon_id;
info->real_killer_id = real_killer_id;
info->real_killer_name = real_killer_name;
downed_timer = room->xtimer.SetIntervalWpEx
(
SERVER_FRAME_RATE,
[this, info] (int event, const a8::Args* args) mutable
{
if (a8::TIMER_EXEC_EVENT == event) {
if (!downed) {
FreeDownedTimer();
return;
}
if (dead) {
FreeDownedTimer();
return;
}
if (!HasLiveTeammate()) {
BeKill(info->killer_id, info->killer_name, info->weapon_id,
info->real_killer_id, info->real_killer_name);
FreeDownedTimer();
return;
}
float dmg_out = 0.0f;
int dec_hp = GetMaxHP() *
std::min(1.0f, (float)mt::Param::GetFloatParam("downed_dec_hp"));
DecHP(dec_hp, info->killer_id, info->killer_name, info->weapon_id,
info->real_killer_id, info->real_killer_name,
dmg_out,
0,
0);
}
},
&xtimer_attacher);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
TryAddBuff(this, kDownBuffId);
GetTrigger()->Downed();
} else {
BeKill(killer_id, killer_name, weapon_id, real_killer_id, real_killer_name);
}
}
}
room->frame_event.AddHpChg(GetWeakPtrRef());
}
Creature* killer = room->GetCreatureByUniId(real_killer_id);
if (killer && real_dmg_out > 0.999) {
if (!nature_recover_hp_idle_timer.expired()) {
room->xtimer.FireEvent
(
nature_recover_hp_idle_timer,
kRemoveNatureRecoverTimerEvent,
nullptr);
}
last_battling_frameno = room->GetFrameNo();
if (!battling_grass_hide_delay_timer.expired()) {
room->xtimer.ResetTimer(battling_grass_hide_delay_timer);
}
bool only_self = !room->IsMobaModeRoom();
if (killer->IsHuman()) {
room->frame_event.AddPropChgEx
(
killer->GetWeakPtrRef(),
kPropDmgShow,
GetUniId(),
real_dmg_out,
dmg_bp,
killer->GetUniId(),
only_self);
if (only_self && IsPlayer()) {
room->frame_event.AddPropChgEx
(
GetWeakPtrRef(),
kPropDmgShow,
GetUniId(),
real_dmg_out,
dmg_bp,
killer->GetUniId(),
only_self);
}
} else if (killer->IsHero()) {
if (killer->AsHero()->master.Get() &&
killer->AsHero()->master.Get()->IsPlayer()) {
room->frame_event.AddPropChgEx
(
killer->AsHero()->master.Get()->GetWeakPtrRef(),
kPropDmgShow,
GetUniId(),
real_dmg_out,
dmg_bp,
killer->AsHero()->master.Get()->GetUniId(),
only_self);
}
if (IsPlayer()) {
room->frame_event.AddPropChgEx
(
GetWeakPtrRef(),
kPropDmgShow,
GetUniId(),
real_dmg_out,
dmg_bp,
killer->AsHero()->master.Get() ?
killer->AsHero()->master.Get()->GetUniId() : killer->GetUniId(),
only_self);
}
}
GetTrigger()->BeAttack(killer_id);
}
GetTrigger()->HpChg();
room->OnTeamPartChg(this);
}
void Human::AddToNewObjects(Entity* entity)
{
framedata_.new_objects[entity->GetUniId()] = entity->GetEntityWeakPtrRef();
}
void Human::AddToImageObjects(Creature* c)
{
framedata_.image_objects[c->GetUniId()] = c->GetWeakPtrRef();
}
void Human::AddToPartObjects(Entity* entity)
{
#ifdef MYDEBUG1
{
if (!follow_target_) {
for (Human* ob : observers_) {
if (ob->IsPlayer()) {
TraceMgr::Instance()->Trace
(a8::Format("add part_object %d->%d frameno:%d %d",
{
GetUniId(),
ob->GetUniId(),
room->GetFrameNo(),
entity->GetUniId()
}));
}
}
}
}
#endif
PartObject part_obj;
part_obj.entity_uniid = entity->GetUniId();
part_obj.entity_type = entity->GetEntityType();
part_obj.entity_subtype = entity->GetEntitySubType();
part_obj.add_frameno = room->GetFrameNo();
part_obj.object = entity->GetEntityWeakPtrRef();
framedata_.part_objects[entity->GetUniId()] = part_obj;
entity->OnAddToTargetPartObject(this);
}
void Human::RemovePartObjects(Entity* entity)
{
#ifdef MYDEBUG1
if (!follow_target_) {
for (Human* observer : observers_) {
if (observer->IsPlayer()) {
observer->SendDebugMsg(a8::Format("view_debug %d->%d frameno:%d remove_part_obj:%d",
{
GetUniId(),
observer->GetUniId(),
room->GetFrameNo(),
entity->GetUniId()
}));
}
}
}
#endif
framedata_.part_objects.erase(entity->GetUniId());
entity->OnRemoveFromTargetPartObject(this);
}
void Human::ClearPartObjects()
{
framedata_.part_objects.clear();
}
int Human::GetPartObjectsCount()
{
return framedata_.part_objects.size();
}
bool Human::InNewObjects(Entity* target)
{
return framedata_.new_objects.find(target->GetUniId()) != framedata_.new_objects.end();
}
bool Human::InPartObjects(Entity* target)
{
return framedata_.part_objects.find(target->GetUniId()) != framedata_.part_objects.end();
}
void Human::RemoveObjects(Entity* entity)
{
framedata_.del_objects.insert(entity->GetUniId());
framedata_.new_objects.erase(entity->GetUniId());
}
void Human::AddOutObjects(Entity* entity)
{
framedata_.out_objects.insert(entity->GetUniId());
}
void Human::RemoveOutObjects(Entity* entity)
{
framedata_.out_objects.erase(entity->GetUniId());
}
bool Human::HasLiveTeammate()
{
bool has = false;
if (GetTeam()) {
GetTeam()->TraverseMembers
(
[this, &has] (Human* member)
{
if (member != this && !member->dead) {
has = true;
return false;
}
return true;
});
}
return has;
}
bool Human::HasNoDownedTeammate()
{
bool has = false;
if (GetTeam()) {
GetTeam()->TraverseMembers
(
[this, &has] (Human* member)
{
if (member != this && !member->dead && !member->downed) {
has = true;
return false;
}
return true;
});
}
return has;
}
int Human::GetNearbyTeammateNum(float range)
{
int num = 0;
if (GetTeam()) {
GetTeam()->TraverseMembers
(
[this, &num, range] (Human* member)
{
if (member != this && !member->dead && !member->downed) {
if (member->GetPos().Distance2D2(GetPos()) <= range) {
++num;
}
}
return true;
});
}
return num;
}
void Human::DoJump()
{
if (HasBuffEffect(kBET_Fly)) {
a8::UnSetBitFlag(status, CS_DisableAttack);
RemoveBuffByEffectId(kBET_Fly);
MustBeAddBuff(this, kThroughWall_BUFFID);
MustBeAddBuff(this, JUMP_BUFFID);
jump_frameno_ = room->GetFrameNo();
SyncAroundPlayers(__FILE__, __LINE__, __func__);
if (IsPlayer()) {
room->xtimer.SetTimeoutEx
(
SERVER_FRAME_RATE,
[this] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
SyncVolume(-1);
}
},
&xtimer_attacher);
}
}
}
void Human::DoGetOn(int obj_uniid)
{
if (room->GetGasData().GetGasMode() == GasInactive) {
return;
}
Entity* entity = room->GetEntityByUniId(obj_uniid);
if (!entity) {
return;
}
if (GetPos().Distance2D2(entity->GetPos()) > mt::Param::s().max_mount_horse_distance) {
return;
}
if (downed) {
return;
}
#if 0
if (HasBuffEffect(kBET_Become)) {
return;
}
#endif
switch (entity->GetEntityType()) {
case ET_Loot:
{
DoGetOnWithLoot((Loot*)entity);
}
break;
case ET_Car:
{
DoGetOnWithCar((Car*)entity);
}
break;
default:
break;
}
}
void Human::RefreshView()
{
#if 1
room->grid_service->TraverseCreatures
(
room->GetRoomIdx(),
GetGridList(),
[this] (Creature* c, bool& stop)
{
c->AddToNewObjects(this);
c->AddToPartObjects(this);
AddToNewObjects(c);
AddToPartObjects(c);
});
#else
TraverseAllLayerHumanList
(
[this] (Human* hum, bool& stop)
{
hum->AddToNewObjects(this);
hum->AddToPartObjects(this);
AddToNewObjects(hum);
AddToPartObjects(hum);
});
#endif
TraverseAllLayerEntityList
(
[this] (Entity* entity, bool& stop)
{
switch (entity->GetEntityType()) {
case ET_Building:
case ET_Obstacle:
case ET_Loot:
case ET_MapBlock:
{
AddToNewObjects(entity);
}
break;
default:
{
}
break;
}
});
}
void Human::OnGridListChange(std::set<GridCell*>& old_grids,
std::set<GridCell*>& inc_grids,
std::set<GridCell*>& dec_grids
)
{
ProcIncGridList(old_grids, inc_grids, dec_grids);
ProcDecGridList(old_grids, inc_grids, dec_grids);
if (IsPlayer() && on_grid_chg) {
on_grid_chg(this);
}
if (HasObserver()) {
}
}
void Human::SyncAroundPlayers(const char* file, int line, const char* func)
{
#if 0
if (a8::HasBitFlag(status, CS_Disable)) {
return;
}
#endif
#ifdef MYDEBUG
#if 0
room->CheckPartObjects();
f8::UdpLog::Instance()->Debug("room_idx:%d syncaround begin %s %d %s",
{
room->GetRoomIdx(),
file,
line,
func
});
#endif
#endif
TraverseAllLayerHumanList
(
[this, file, line, func] (Human* hum, bool& stop)
{
hum->AddToNewObjects(this);
#ifdef MYDEBUG
#if 0
{
std::string objs_str;
for (auto& obj : hum->part_objects) {
objs_str += a8::Format("%d ", {(long long)obj});
}
f8::UdpLog::Instance()->Debug("hum1 %d %s", {(long long)hum, objs_str});
}
{
std::string objs_str;
for (auto& obj : part_objects) {
objs_str += a8::Format("%d ", {(long long)obj});
}
f8::UdpLog::Instance()->Debug("hum2 %d %s", {(long long)this, objs_str});
}
room->CheckPartObjects(hum, this);
hum->InPartObjects(this);
#endif
#endif
assert(hum->InPartObjects(this));
if (!hum->InPartObjects(this)) {
static long long last_debugout_tick = 0;
if (a8::XGetTickCount() - last_debugout_tick > 1000 * 10) {
last_debugout_tick = a8::XGetTickCount();
f8::UdpLog::Instance()->Warning
("SyncAroundPlayers error room_idx:%d, file:%s line:%d func:%s",
{
room->GetRoomIdx(),
file,
line,
func
});
}
}
});
#ifdef MYDEBUG
#if 0
room->CheckPartObjects();
f8::UdpLog::Instance()->Debug("syncaround end %s %d %s",
{
file,
line,
func
});
#endif
#endif
}
void Human::RecalcVolume()
{
const mt::Equip* backpack_meta = mt::Equip::GetById(backpack);
for (size_t i = 0; i < IS_END; ++i) {
volume_[i] = meta->_volume[i];
volume_[i] += buff_inventory_[i].num;
if (backpack_meta) {
volume_[i] += backpack_meta->_volume[i];
}
}
}
void Human::RecalcBaseAttr()
{
#if 0
xxxxxxxx
const mt::Equip* chest_meta = mt::Equip::GetById(chest);
float def = meta->def();
if (chest_meta) {
def += chest_meta->def();
}
const mt::Equip* helmet_meta = mt::Equip::GetById(helmet);
if (helmet_meta) {
def += helmet_meta->def();
}
SetDef(def);
#endif
}
int Human::GetVolume(int slot_id)
{
if (!IsValidSlotId(slot_id)) {
A8_ABORT();
}
return volume_[slot_id];
}
void Human::RecoverHp(int inc_hp)
{
if (!dead) {
float hp = GetHP();
hp += inc_hp;
SetHP(hp);
SetHP(std::min(GetHP(), GetMaxHP()));
}
}
void Human::AddObserver(Human* observer)
{
observers_.insert(observer);
}
void Human::RemoveObserver(Human* observer)
{
observers_.erase(observer);
}
bool Human::HasObserver()
{
return observers_.size() > 1;
}
void Human::FollowTarget(Human* target)
{
if (target == this) {
return;
}
int pre_uniid = 0;
if (follow_target_) {
pre_uniid = follow_target_->GetUniId();
follow_target_->RemoveObserver(this);
}
target->AddObserver(this);
follow_target_ = target;
follow_synced_active_player = false;
#ifdef MYDEBUG
SendDebugMsg(a8::Format("观战 watch %d->%d->%d frameno:%d",
{
room->GetFrameNo(),
pre_uniid,
follow_target_->GetUniId(),
GetUniId()
}));
#endif
}
void Human::UpdateAction()
{
int passed_time = (room->GetFrameNo() - action_frameno) * FRAME_RATE_MS;
int left_time = std::max(0, action_duration - passed_time);
if (left_time <= 0) {
switch (action_type) {
case AT_Reload:
{
ProcReloadAction();
}
break;
case AT_UseItem:
{
ProcUseItemAction();
}
break;
case AT_Relive:
{
ProcReliveAction();
}
break;
case AT_Rescue:
{
RemoveBuffByEffectId(kBET_Rescuer);
}
break;
default:
{
}
break;
}
ResetAction();
}
}
void Human::UpdateMove()
{
Creature::UpdateMove();
}
void Human::DeadDrop()
{
if (room->IsMobaModeRoom()) {
return;
}
#ifdef MYDEBUG
a8::XPrintf("DeadDrop\n", {});
//room->DropItem(GetPos(), 30908, 1, 1);
//return;
#endif
auto SkinCanDrop =
[this] (Skin* skin) -> bool
{
#ifdef MYDEBUG
return false;
#else
return skin->skin_id != 0;
#endif
};
if (a8::HasBitFlag(status, CS_DeadNoDrop)) {
return;
}
#if 1
if (true) {
#else
if (!(HasBuffEffect(kBET_Become) && GetBuffByEffectId(kBET_Become)->FreezeOperate())) {
#endif
#ifdef NEW_WEAPON_SYS
#else
for (auto& weapon : weapons) {
if (weapon.weapon_id != 0 &&
weapon.weapon_id != default_weapon.weapon_id
) {
Position drop_pos = GetPos();
room->DropItem(drop_pos.ToGlmVec3(), weapon.weapon_id, 1, 1);
if (weapon.ammo > 0 && weapon.bullet_meta && weapon.ammo < 200) {
if (IsPlayer() &&
weapon.bullet_meta &&
IsValidSlotId(weapon.bullet_meta->_inventory_slot())) {
AddInventory(weapon.bullet_meta->_inventory_slot(), weapon.ammo);
}
}
if (IsAndroid() && weapon.bullet_meta) {
int drop_num = weapon.bullet_meta->group_num();
room->DropItem(GetPos().ToGlmVec3(), weapon.bullet_meta->id(), drop_num, 1);
}
weapon.Clear();
}
}
{
weapons[0] = default_weapon;
SetCurrWeapon(&weapons[0]);
}
#endif
}
#if 0
{
Skin* old_skin = GetSkinByIdx(kSkinSlot_HAT);
if (old_skin && old_skin->skin_id != 0 && SkinCanDrop(old_skin)) {
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
Position drop_pos = GetPos();
drop_pos.AddGlmVec3(dir * (40.0f + rand() % 50));
room->CreateLoot(old_skin->skin_id, drop_pos.ToGlmVec3(), 1, 1);
*old_skin = Skin();
}
}
{
Skin* old_skin = GetSkinByIdx(kSkinSlot_CLOTH);
if (old_skin && old_skin->skin_id != 0 && SkinCanDrop(old_skin)) {
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
Position drop_pos = GetPos();
drop_pos.AddGlmVec3(dir * (40.0f + rand() % 50));
room->CreateLoot(old_skin->skin_id, drop_pos.ToGlmVec3(), 1, 1);
*old_skin = Skin();
}
}
#endif
{
//头盔
if (helmet != 0) {
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
Position drop_pos = GetPos();
drop_pos.AddGlmVec3(dir * (40.0f + rand() % 50));
room->CreateLoot(helmet, GetPos().ToGlmVec3(), drop_pos.ToGlmVec3(), 1, 1);
helmet = 0;
}
//衣服
if (chest != 0) {
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
Position drop_pos = GetPos();
drop_pos.AddGlmVec3(dir * (40.0f + rand() % 50));
room->CreateLoot(chest, GetPos().ToGlmVec3(), drop_pos.ToGlmVec3(), 1, 1);
chest = 0;
}
//背包
if (backpack != 0) {
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
Position drop_pos = GetPos();
drop_pos.AddGlmVec3(dir * (40.0f + rand() % 50));
room->CreateLoot(backpack, GetPos().ToGlmVec3(), drop_pos.ToGlmVec3(), 1, 1);
backpack = 0;
}
}
for (size_t slot = 0; slot < GetInventoryData().size(); ++slot) {
if (GetInventory(slot) > 0 && mt::Param::s().fighting_mode) {
const mt::Equip* equip_meta = mt::Equip::GetByIdBySlotId(slot);
if (equip_meta) {
int drop_num = equip_meta->group_num();
switch (equip_meta->_inventory_slot()) {
case IS_FRAG:
case IS_SMOKE:
case IS_MOLOTOR_COCKTAIL:
{
if (drop_num > 0) {
Position drop_pos = GetPos();
if (IsPlayer()) {
room->DropItem(drop_pos.ToGlmVec3(), equip_meta->id(), GetInventory(slot), 1);
} else {
room->DropItem(drop_pos.ToGlmVec3(), equip_meta->id(), drop_num, 1);
}
DecInventory(slot, GetInventory(slot));
SyncVolume(slot);
}
}
break;
case IS_POSION_GAS_BOMB:
case IS_TRAP:
case IS_MINE:
case IS_C4:
case IS_SHIELD_WALL:
case IS_SINGAL_GUN:
case IS_OIL_BUCKET:
{
}
break;
case IS_9MM:
case IS_556MM:
case IS_762MM:
case IS_12GAUGE:
case IS_RPG:
case IS_ICE:
{
}
break;
default:
{
if (drop_num > 0) {
Position drop_pos = GetPos();
if (IsPlayer()) {
room->DropItem(drop_pos.ToGlmVec3(), equip_meta->id(), GetInventory(slot), 1);
} else {
#if 1
if (GetCurrWeapon()) {
}
#else
room->DropItem(drop_pos, equip_meta->id(), drop_num, 1);
#endif
}
DecInventory(slot, GetInventory(slot));
SyncVolume(slot);
}
}
break;
}
#if 0
} else {
Position drop_pos = GetPos();
room->DropItem(drop_pos.ToGlmVec3(), equip_meta->id(), GetInventory(slot), 1);
}
#endif
}
}
}
{
on_dead_remove_objects_.clear();
}
{
if (!room->IsGameOver() && IsAndroid()) {
if (!room->IsPveRoom()) {
for (int id : meta->_drop_list) {
room->ScatterDrop(GetPos().ToGlmVec3(), id);
}
}
#if 0
if (GetCurrWeapon() &&
GetCurrWeapon()->weapon_idx == GUN_SLOT1) {
int num = 1 + rand() % 2;
for (int i = 0; i < num; ++i) {
room->CreateLoot(GetCurrWeapon()->meta->id(), GetPos().ToGlmVec3(), GetPos().ToGlmVec3(), 1, 1);
}
}
#endif
}
}
{
if (GetInventory(IS_YELLOW_STONE) > 0 && gemstone > 0) {
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropYellowStone,
0,
0,
false);
const mt::Equip* gem_stone_meta = mt::Equip::GetYellowStone();
if (gem_stone_meta) {
Position drop_pos = GetPos();
room->DropItem(drop_pos.ToGlmVec3(), gem_stone_meta->id(), gemstone, 1);
}
SetMaxHP(GetNetData()->GetMaxHP());
gemstone = 0;
DecInventory(IS_YELLOW_STONE, GetInventory(IS_YELLOW_STONE));
SyncVolume(IS_YELLOW_STONE);
}
ClearGemStoneBuffs();
}
{
#if 0
if (GetInventory(IS_BLUE_STONE) > 0) {
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropBlueStone,
0,
0,
false);
const mt::Equip* blue_stone_meta = mt::Equip::GetBlueStone();
if (blue_stone_meta) {
Position drop_pos = GetPos();
room->DropItem(drop_pos.ToGlmVec3(), blue_stone_meta->id(), GetInventory(IS_BLUE_STONE), 1);
}
DecInventory(IS_BLUE_STONE, GetInventory(IS_BLUE_STONE));
SyncVolume(IS_BLUE_STONE);
}
Skill* main_skill = GetMainSkill();
if (main_skill) {
main_skill->Reset();
}
#endif
}
{
if (GetInventory(IS_WEAPON_STONE) > 0) {
const mt::Equip* weapon_stone_meta = mt::Equip::GetWeaponStone();
if (weapon_stone_meta) {
Position drop_pos = GetPos();
room->DropItem(drop_pos.ToGlmVec3(), weapon_stone_meta->id(), GetInventory(IS_WEAPON_STONE), 1);
}
DecInventory(IS_WEAPON_STONE, GetInventory(IS_WEAPON_STONE));
SyncVolume(IS_WEAPON_STONE);
}
}
{
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropPurpleStone,
0,
0,
false);
DecInventory(IS_PURPLE_STONE, GetInventory(IS_PURPLE_STONE));
SyncVolume(IS_PURPLE_STONE);
armor_shield = 0;
max_armor_shield = 0;
}
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
}
void Human::ProcLootSkin(AddItemDTO& dto)
{
switch (dto.item_meta->equip_subtype()) {
case 11:
{
//装饰
Skin* old_skin = GetSkinByIdx(kSkinSlot_HAT);
if (old_skin) {
if (old_skin->skin_id != 0) {
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
Position drop_pos = GetPos();
drop_pos.AddGlmVec3(dir * (40.0f + rand() % 50));
room->CreateLoot(old_skin->skin_id, GetPos().ToGlmVec3(), drop_pos.ToGlmVec3(), 1, 1);
}
*old_skin = Skin();
old_skin->skin_id = dto.item_meta->id();
old_skin->skin_lv = 1;
SyncAroundPlayers(__FILE__, __LINE__, __func__);
}
}
break;
case 12:
{
//衣服
Skin* old_skin = GetSkinByIdx(kSkinSlot_CLOTH);
if (old_skin) {
if (old_skin->skin_id != 0) {
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
Position drop_pos = GetPos();
drop_pos.AddGlmVec3(dir * (40.0f + rand() % 50));
room->CreateLoot(old_skin->skin_id, GetPos().ToGlmVec3(), drop_pos.ToGlmVec3(), 1, 1);
}
*old_skin = Skin();
old_skin->skin_id = dto.item_meta->id();
old_skin->skin_lv = 1;
SyncAroundPlayers(__FILE__, __LINE__, __func__);
}
}
break;
}
dto.handled = true;
}
void Human::ProcLootCar(AddItemDTO& dto)
{
DoGetOn(dto.uniid);
dto.handled = true;
}
void Human::ProcNormalItem(AddItemDTO& dto)
{
AddItem(dto.item_meta->id(), 1);
dto.handled = true;
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
}
void Human::ProcSpoils(AddItemDTO& dto)
{
dto.handled = true;
}
void Human::OnDie()
{
{
if (HasBuffEffect(kBET_Camouflage)) {
RemoveBuffByEffectId(kBET_Camouflage);
}
DoGetDown();
}
real_dead_frameno = room->GetFrameNo();
room->OnHumanDie(this);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
AllocDeadExp(stats->killer_id);
if (GetTeam()) {
GetTeam()->TraverseMembers
(
[this] (Human* member) -> bool
{
if (this != member &&
member->action_type == AT_Relive &&
member->action_target_id == GetUniId()) {
member->CancelAction();
}
return true;
});
}
if (IsPlayer()) {
int i = 0;
}
if (real_dead) {
std::set<Human*> over_humans;
if (!leave_) {
if (!HasNoDownedTeammate()) {
if (GetTeam()) {
GetTeam()->GetOveredHumans(over_humans);
} else {
over_humans.insert(this);
}
} else {
over_humans.insert(this);
}
}
if (room->GetAliveTeamNum() == 1) {
Team* alive_team = room->GetAliveTeam();
if (alive_team) {
alive_team->GetOveredHumans(over_humans);
}
}
for (Human* hum : over_humans) {
hum->SendGameOver();
}
}
if (observers_.size() > 1) {
std::vector<Human*> exclude_self_observers;
for (auto& observer : observers_) {
if (observer != this && !observer->IsOb()) {
exclude_self_observers.push_back(observer);
}
}
for (auto& observer : exclude_self_observers) {
observers_.erase(observer);
observer->OnWatcherDie(this);
}
}
DeadDrop();
}
void Human::FreeDownedTimer()
{
RemoveBuffById(kDownBuffId);
if (!downed_timer.expired()) {
room->xtimer.Delete(downed_timer);
}
}
void Human::FreeReviveTimer()
{
if (!revive_timer.expired()) {
room->xtimer.Delete(revive_timer);
}
}
void Human::SetSkin(int idx, int skin_id)
{
if (idx < kSkinNum) {
Skin& skin = skins[idx];
skin.skin_id = skin_id;
skin.skin_lv = 1;
}
}
Skin* Human::GetSkinByIdx(int idx)
{
int i = 0;
for (auto& skin : skins) {
if (i == idx) {
return &skin;
}
++i;
}
return nullptr;
}
void Human::AddBuffPostProc(Creature* caster, Buff* buff)
{
}
int Human::GetItemNum(int item_id)
{
auto itr = items_.find(item_id);
return itr != items_.end() ? itr->second : 0;
}
void Human::DecItem(int item_id, int item_num)
{
auto itr = items_.find(item_id);
if (itr != items_.end()) {
itr->second -= item_num;
room->frame_event.AddItemChg(GetWeakPtrRef(), item_id, std::max(0, itr->second));
if (itr->second <= 0) {
if (battling_items_.find(item_id) == battling_items_.end()) {
//items_.erase(itr); //为啥?????
}
items_.erase(itr);
}
}
}
void Human::DropItems(Obstacle* obstacle)
{
bool is_treasure_box = false;
std::vector<int> drops = obstacle->meta->RandDrop();
for (int drop_id : drops) {
room->ScatterDrop(obstacle->GetPos().ToGlmVec3(), drop_id);
}
if (is_treasure_box) {
++box_drop_times_;
} else {
++normal_drop_times_;
}
}
void Human::DropItems(const glm::vec3& center, std::vector<int>& drops)
{
for (int drop_id : drops) {
room->ScatterDrop(center, drop_id);
}
}
void Human::Revive()
{
{
int wait_revive_time = mt::Param::GetIntParam("revive_time", 25) +
kReviveTimeAdd;
revive_timer = room->xtimer.SetTimeoutWpEx
(SERVER_FRAME_RATE * wait_revive_time,
[this] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
dead = true;
real_dead = true;
downed = false;
OnDie();
}
},
&xtimer_attacher);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
}
}
void Human::CancelRevive()
{
if (dead && !revive_timer.expired() && !real_dead) {
dead = true;
real_dead = true;
downed = false;
FreeDownedTimer();
OnDie();
FreeReviveTimer();
}
}
void Human::AdjustDecHp(float old_health, float& new_health)
{
Buff* buff = GetBuffByEffectId(kBET_NewProtect);
if (buff) {
if (new_health < GetMaxHP() * buff->meta->_buff_param1) {
new_health = std::max(GetMaxHP() * buff->meta->_buff_param1, (float)0);
}
}
}
void Human::OnEnable()
{
a8::UnSetBitFlag(status, CS_Disable);
enable_frameno = room->GetFrameNo();
room->grid_service->MoveCreature(this);
FindLocation();
RefreshView();
}
void Human::OnDisable()
{
a8::SetBitFlag(status, CS_Disable);
RemoveFromScene();
framedata_.ClearFrameData(this);
ClearPartObjects();
}
void Human::GetViewObjects(std::set<Entity*>& view_objects)
{
TraverseCreatures
(
[&view_objects] (Creature* c, bool& stop)
{
view_objects.insert(c);
});
TraverseAllLayerEntityList
(
[&view_objects] (Entity* entity, bool& stop)
{
switch (entity->GetEntityType()) {
case ET_Building:
case ET_Obstacle:
case ET_Loot:
case ET_MapBlock:
{
view_objects.insert(entity);
}
break;
default:
{
}
break;
}
});
}
void Human::ProcIncGridList(std::set<GridCell*>& old_grids,
std::set<GridCell*>& inc_grids,
std::set<GridCell*>& dec_grids)
{
room->grid_service->TraverseCreatures
(
room->GetRoomIdx(),
inc_grids,
[this, &old_grids] (Creature* c, bool& stop)
{
if (!room->grid_service->CreatureInGridList(c, old_grids)) {
c->AddToNewObjects(this);
c->AddToPartObjects(this);
c->RemoveOutObjects(this);
AddToNewObjects(c);
AddToPartObjects(c);
RemoveOutObjects(c);
}
});
room->grid_service->TraverseAllLayerEntityList
(
room->GetRoomIdx(),
inc_grids,
[this] (Entity* entity, bool& stop)
{
switch (entity->GetEntityType()) {
case ET_Building:
case ET_Obstacle:
case ET_Loot:
case ET_MapBlock:
{
AddToNewObjects(entity);
RemoveOutObjects(entity);
}
break;
default:
{
}
break;
}
});
}
void Human::ProcDecGridList(std::set<GridCell*>& old_grids,
std::set<GridCell*>& inc_grids,
std::set<GridCell*>& dec_grids)
{
room->grid_service->TraverseCreatures
(
room->GetRoomIdx(),
dec_grids,
[this] (Creature* c, bool& stop)
{
if (!room->grid_service->CreatureInGridList(c, GetGridList())) {
AddOutObjects(c);
c->AddOutObjects(this);
#ifdef MYDEBUG
#if 0
f8::UdpLog::Instance()->Debug("addoutobjects %d %d",
{
(long long)c,
c->GetUniId()
});
#endif
#endif
}
});
room->grid_service->TraverseAllLayerEntityList
(
room->GetRoomIdx(),
dec_grids,
[this] (Entity* entity, bool& stop)
{
if (!room->grid_service->EntityInGridList(room, entity, GetGridList())) {
switch (entity->GetEntityType()) {
case ET_Building:
case ET_Obstacle:
case ET_Loot:
case ET_MapBlock:
{
AddOutObjects(entity);
}
break;
default:
{
}
break;
}
}
});
}
void Human::RemoveFromScene()
{
room->grid_service->DeatchHuman(this);
room->TraverseHumanList
(
[this] (Human* hum)
{
hum->RemovePartObjects(this);
return true;
});
}
void Human::ProcReloadAction()
{
Weapon* p_weapon = GetCurrWeapon();
if (second_weapon.meta) {
p_weapon = &second_weapon;
}
if (p_weapon->weapon_idx == action_target_id &&
p_weapon->weapon_id == action_item_id &&
p_weapon->weapon_idx != 0) {
const mt::Equip* bullet_meta = mt::Equip::GetById(p_weapon->meta->use_bullet());
if (bullet_meta) {
int ammo = p_weapon->ammo;
if (ammo < p_weapon->GetClipVolume(this)) {
if (bullet_meta->_inventory_slot() >= 0 &&
bullet_meta->_inventory_slot() < IS_END) {
if (GetInventory(bullet_meta->_inventory_slot()) > 0) {
int add_num = 0;
if (GetInventory(bullet_meta->_inventory_slot()) <=
p_weapon->GetClipVolume(this) - ammo) {
add_num = GetInventory(bullet_meta->_inventory_slot());
if (p_weapon->meta->reloadtype() == 1) {
add_num = 1;
}
DecInventory(bullet_meta->_inventory_slot(), add_num);
SyncVolume(bullet_meta->_inventory_slot());
} else {
add_num = p_weapon->GetClipVolume(this) - ammo;
if (p_weapon->meta->reloadtype() == 1) {
add_num = 1;
}
DecInventory(bullet_meta->_inventory_slot(), add_num);
SyncVolume(bullet_meta->_inventory_slot());
}
p_weapon->ammo += add_num;
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
if (p_weapon->meta->reloadtype() == 1) {
int weapon_idx = p_weapon->weapon_idx;
int weapon_id = p_weapon->weapon_id;
room->xtimer.SetTimeoutEx
(1,
[this, weapon_idx, weapon_id]
(int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
NextReload(weapon_id, weapon_idx);
}
},
&xtimer_attacher);
}
}
}
}
}
}
GetTrigger()->EndReload();
}
void Human::ProcUseItemAction()
{
#if 1
const mt::Equip* item_meta = mt::Equip::GetById(action_item_id);
#else
const mt::Equip* item_meta = mt::Equip::GetByIdBySlotId(action_item_id);
#endif
if (!item_meta) {
return;
}
if (GetInventory(item_meta->_inventory_slot()) <= 0) {
return;
}
switch (item_meta->_inventory_slot()) {
case IS_HEALTHKIT:
{
+stats->use_medicine_times;
float heal = std::get<1>(item_meta->_heal);
switch (std::get<0>(item_meta->_heal)) {
case 1:
{
AddHp(heal * (1.0f + GetNetData()->GetDrugEfficacyPct()));
}
break;
case 2:
{
AddHp((heal * GetMaxHP()) * (1.0f + GetNetData()->GetDrugEfficacyPct()));
}
break;
default:
{
}
break;
}
DecInventory(item_meta->_inventory_slot(), 1);
SyncVolume(item_meta->_inventory_slot());
GetTrigger()->UseItemAction(item_meta->_inventory_slot());
}
break;
case IS_PAIN_KILLER:
{
+stats->use_medicine_times;
if (!pain_killer_timer.expired()) {
int passed_time = (room->GetFrameNo() - pain_killer_frameno) * FRAME_RATE_MS;
int left_time = std::max(0, pain_killer_lastingtime * 1000 - passed_time);
int anodyne_max_time = item_meta->time();
left_time = std::min(left_time, anodyne_max_time * 1000);
pain_killer_lastingtime += std::min(item_meta->time() * 1000,
anodyne_max_time * 1000 - left_time) / 1000;
} else {
pain_killer_frameno = room->GetFrameNo();
pain_killer_lastingtime = item_meta->time();
if (pain_killer_lastingtime > 0) {
pain_killer_timer = room->xtimer.SetIntervalWpEx
(
SERVER_FRAME_RATE,
[this, item_meta] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
float heal = std::get<1>(item_meta->_heal);
switch (std::get<0>(item_meta->_heal)) {
case 1:
{
AddHp(heal * (1.0f + GetNetData()->GetDrugEfficacyPct()));
}
break;
case 2:
{
AddHp((heal * GetMaxHP()) * (1.0f + GetNetData()->GetDrugEfficacyPct()));
}
break;
default:
{
}
break;
}
if (room->GetFrameNo() - pain_killer_frameno >
pain_killer_lastingtime * SERVER_FRAME_RATE) {
room->xtimer.Delete(pain_killer_timer);
}
}
},
&xtimer_attacher);
}
float heal = std::get<1>(item_meta->_heal);
switch (std::get<0>(item_meta->_heal)) {
case 1:
{
AddHp(heal * (1.0f + GetNetData()->GetDrugEfficacyPct()));
}
break;
case 2:
{
AddHp((heal * GetMaxHP()) * (1.0f + GetNetData()->GetDrugEfficacyPct()));
}
break;
default:
{
}
break;
}
}
DecInventory(item_meta->_inventory_slot(), 1);
SyncVolume(item_meta->_inventory_slot());
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
GetTrigger()->UseItemAction(item_meta->_inventory_slot());
}
break;
case IS_SHEN_BAO:
{
+stats->use_medicine_times;
if (!dead && downed) {
downed = false;
if (!downed_timer.expired()) {
room->xtimer.Delete(downed_timer);
}
if (GetBuffById(kDownBuffId)) {
RemoveBuffById(kDownBuffId);
}
SyncAroundPlayers(__FILE__, __LINE__, __func__);
float heal = std::get<1>(item_meta->_heal);
switch (std::get<0>(item_meta->_heal)) {
case 1:
{
AddHp(heal * (1.0f + GetNetData()->GetDrugEfficacyPct()));
}
break;
case 2:
{
AddHp((heal * GetMaxHP()) * (1.0f + GetNetData()->GetDrugEfficacyPct()));
}
break;
default:
{
}
break;
}
}
DecInventory(item_meta->_inventory_slot(), 1);
SyncVolume(item_meta->_inventory_slot());
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
GetTrigger()->UseItemAction(item_meta->_inventory_slot());
}
break;
default:
{
}
break;
}
}
void Human::ProcReliveAction()
{
RemoveBuffByEffectId(kBET_InRescue);
Entity* entity = room->GetEntityByUniId(action_target_id);
if (!entity->IsEntityType(ET_Player)) {
return;
}
Human* hum = (Human*)entity;
if (hum->action_type == AT_Rescue) {
hum->CancelAction();
}
if (!dead && downed) {
SetHP(mt::Param::GetFloatParam("downed_relive_recover_hp") * GetMaxHP());
downed = false;
if (!downed_timer.expired()) {
room->xtimer.Delete(downed_timer);
}
++hum->stats->rescue_member;
if (hum->guild_id != 0 && hum->guild_id == guild_id) {
++hum->stats->rescue_guild_member;
}
if (GetBuffById(kDownBuffId)) {
RemoveBuffById(kDownBuffId);
}
}
SyncAroundPlayers(__FILE__, __LINE__, __func__);
}
void Human::OnBuffRemove(Buff& buff)
{
Creature::OnBuffRemove(buff);
}
void Human::NextReload(int prev_weapon_id, int prev_weapon_idx)
{
if (action_type != AT_None) {
return;
}
Weapon* p_weapon = GetCurrWeapon();
if (second_weapon.meta) {
p_weapon = &second_weapon;
}
if (p_weapon &&
p_weapon->weapon_id == prev_weapon_id &&
p_weapon->weapon_idx == prev_weapon_idx) {
AutoLoadingBullet(true);
}
}
void Human::DoGetDown()
{
if (GetCar()) {
GetCar()->GetDown(this);
}
}
void Human::DoGetOnWithLoot(Loot* entity)
{
const mt::Equip* item_meta = mt::Equip::GetById(entity->item_id);
if (!item_meta) {
return;
}
if (GetCar()) {
GetCar()->GetDown(this);
}
Car* car = room->CreateCar(
this,
entity->GetUniId(),
item_meta,
entity->GetPos().ToGlmVec3(),
team_id,
nullptr);
car->GetOn(this);
#ifdef MYDEBUG
a8::XPrintf("DoGetOnWithLoot uniid:%d car_uniid:%d\n", {car->GetUniId(), car->car_uniid});
#endif
}
void Human::DoGetOnWithCar(Car* car)
{
car->GetOn(this);
}
void Human::DoSkillPreProc(int skill_id, int target_ids)
{
if (action_type == AT_Reload ||
action_type == AT_UseItem
) {
CancelAction();
}
}
void Human::DoSkillPostProc(bool used, int skill_id, int target_id)
{
if (used) {
++stats->skill_times;
Skill* skill = GetSkill(skill_id);
if (skill) {
skill->DecTimes();
room->frame_event.AddSkillCdChg(AllocWeakPtr(), skill_id, skill->GetLeftTime());
room->frame_event.AddSkillCurrTimesChg(AllocWeakPtr(), skill_id, skill->GetCurrTimes());
}
OnAttack();
}
}
float Human::GetRadius()
{
return meta->radius();
}
float Human::GetHitRadius()
{
return meta->hit_radius();
}
void Human::UpdateViewObjects()
{
if (dead) {
return;
}
if (view_objects_.size() >= 2) {
std::vector<Human*> deleted_humans;
for (Human* hum : view_objects_) {
if (hum->dead ||
hum->GetPos().ManhattanDistance2D(GetPos()) > mt::Param::s().view_objects_out_distance) {
deleted_humans.push_back(hum);
}
}
for (Human* hum : deleted_humans) {
view_objects_.erase(hum);
}
}
if (view_objects_.size() < 2) {
TraverseAllLayerHumanList
(
[this] (Human* hum, bool& stop)
{
if (hum->IsAndroid() && !hum->dead && view_objects_.find(hum) == view_objects_.end() &&
hum->team_id != team_id) {
if (hum->GetPos().ManhattanDistance2D(GetPos()) <
mt::Param::s().view_objects_in_distance) {
view_objects_.insert(hum);
}
if (view_objects_.size() >= 2) {
stop = true;
return;
}
}
});
}
if (view_objects_.size() < 2) {
room->GetIncubator()->AllocAndroid(this, 1 + rand() % 2, nullptr);
if (!refresh_view_timer_.expired()) {
room->xtimer.ModifyTime
(refresh_view_timer_,
SERVER_FRAME_RATE * (mt::Param::s().refresh_view_time + (rand() % 3))
);
}
}
}
void Human::GMAddItem(int item_id, int item_num)
{
const mt::Equip* item_meta = mt::Equip::GetById(item_id);
if (!item_meta) {
return;
}
AddItemDTO dto;
dto.uniid = 0;
dto.item_id = item_id;
dto.count = item_num;
dto.item_level = 1;
dto.handled = false;
dto.item_meta = item_meta;
ProcAddItemDto(dto);
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
}
void Human::OnBulletHit(IBullet* bullet)
{
if (IsInvincible()) {
return;
}
#ifdef MYDEBUG
if (a8::HasBitFlag(status, CS_NoDie)) {
return;
}
#endif
if (HasBuffEffect(kBET_Jump) ||
HasBuffEffect(kBET_Fly)) {
return;
}
{
Buff* buff = GetBuffByEffectId(kBET_Camouflage);
if (buff && buff->meta->_int_buff_param2 == 1) {
return;
}
}
#ifdef MYDEBUG
#if 0
if (IsPlayer()) {
return;
}
#endif
#endif
if (bullet->GetSender().Get()) {
bullet->GetSender().Get()->GetTrigger()->BulletHit(bullet, this);
SetLastAttacker(bullet->GetSender());
}
RemoveBuffByEffectId(kBET_PeaceMode);
RemoveHideEffect(kOnBulletHitReason);
if (!nature_recover_hp_idle_timer.expired()) {
room->xtimer.FireEvent
(
nature_recover_hp_idle_timer,
kRemoveNatureRecoverTimerEvent,
nullptr);
}
last_battling_frameno = room->GetFrameNo();
if (!battling_grass_hide_delay_timer.expired()) {
room->xtimer.ResetTimer(battling_grass_hide_delay_timer);
}
GetTrigger()->Attacked(bullet->GetSender().Get());
if (!dead && (bullet->IsBomb() || bullet->GetSender().Get()->team_id != team_id)) {
float finaly_dmg = 0;
int dmg_bp = 0;
if (bullet->GetSkillMeta() && SkillHelper::ProcBulletDmg(bullet, this, finaly_dmg)) {
} else {
finaly_dmg = bullet->GetSender().Get()->GetNetData()->CalcDmg(this, bullet);
dmg_bp = bullet->GetSender().Get()->GetNetData()->GetDmgBp();
}
if (bullet->GetSender().Get()->IsHuman()) {
bullet->GetSender().Get()->AsHuman()->stats->damage_amount_out += finaly_dmg;
}
if (bullet->GetBulletMeta()->_buff_meta) {
MustBeAddBuff(bullet->GetSender().Get(), bullet->GetBulletMeta()->buffid());
}
if (bullet->GetSender().Get()->GetNetData()->IsCrit()) {
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropCritDmg,
0,
bullet->GetSender().Get()->GetNetData()->GetCritDmg()
);
}
if (bullet->GetSender().Get() && bullet->GetSender().Get()->IsCar() && bullet->GetPassenger().Get()) {
if (!bullet->IsPreBattleBullet()) {
float dmg_out = 0.0f;
DecHP(finaly_dmg,
bullet->GetPassenger().Get()->GetUniId(),
bullet->GetPassenger().Get()->GetName(),
bullet->GetGunMeta()->id(),
bullet->GetPassenger().Get()->GetUniId(),
bullet->GetPassenger().Get()->GetName(),
dmg_out,
0,
dmg_bp);
bullet->GetSender().Get()->GetTrigger()->DmgOut(this, dmg_out);
if (bullet->GetSender().Get() &&
!bullet->GetSender().Get()->dead &&
dmg_out > 0.0f &&
!bullet->GetSkillMeta()
) {
{
if (bullet->GetSender().Get()->GetNetData()->GetBrainLifePct() > 0.0f) {
float recover_hp = dmg_out *
bullet->GetSender().Get()->GetNetData()->GetBrainLifePct();
if (recover_hp > 0.0f) {
bullet->GetSender().Get()->AddHp(recover_hp);
}
}
}
{
if (bullet->GetSender().Get()->IsEntityType(ET_Hero)) {
Hero* hero = (Hero*)bullet->GetSender().Get();
if (hero->GetAbility()->GetSwitchTimes(kEnableDmgForwardTimes) > 0 &&
hero->master.Get() &&
!hero->master.Get()->dead &&
hero->master.Get()->GetNetData()->GetBrainLifePct() > 0.0f){
float recover_hp = dmg_out *
hero->master.Get()->GetNetData()->GetBrainLifePct();
if (recover_hp > 0.0f) {
hero->master.Get()->AddHp(recover_hp);
}
}
}
}
}
}
} else {
if (!bullet->IsPreBattleBullet()) {
if (bullet->GetSender().Get() && bullet->GetSender().Get()->IsHuman()) {
bullet->GetSender().Get()->AsHuman()->stats->IncWeaponDamageOut
(bullet->GetGunMeta()->id(), finaly_dmg);
}
float dmg_out = 0.0f;
int real_killer_id = bullet->GetSender().Get()->GetUniId();
std::string real_killer_name = bullet->GetSender().Get()->GetName();
if (bullet->GetSender().Get()->master.Get()) {
real_killer_id = bullet->GetSender().Get()->master.Get()->GetUniId();
real_killer_name = bullet->GetSender().Get()->master.Get()->GetName();
}
DecHP(finaly_dmg,
bullet->GetSender().Get()->GetUniId(),
bullet->GetSender().Get()->GetName(),
bullet->GetGunMeta()->id(),
real_killer_id,
real_killer_name,
dmg_out,
0,
dmg_bp);
#if 0
if (bullet->GetSender().Get()->IsEntityType(ET_Hero)) {
a8::XPrintf("被炮塔打出血 %f %f %f\n", {GetHP(), GetMaxHP(), dmg_out});
}
#endif
bullet->GetSender().Get()->GetTrigger()->DmgOut(this, dmg_out);
if (bullet->GetSender().Get() &&
!bullet->GetSender().Get()->dead &&
dmg_out > 0.0f &&
!bullet->GetSkillMeta()) {
{
if (bullet->GetSender().Get()->GetNetData()->GetBrainLifePct() > 0.0f) {
float recover_hp = dmg_out *
bullet->GetSender().Get()->GetNetData()->GetBrainLifePct();
if (recover_hp > 0.0f) {
bullet->GetSender().Get()->AddHp(recover_hp);
}
}
}
{
if (bullet->GetSender().Get()->IsEntityType(ET_Hero)) {
Hero* hero = (Hero*)bullet->GetSender().Get();
if (hero->GetAbility()->GetSwitchTimes(kEnableDmgForwardTimes) > 0 &&
hero->master.Get() &&
!hero->master.Get()->dead
){
if (hero->master.Get()->GetNetData()->GetBrainLifePct() > 0.0f) {
float recover_hp = dmg_out *
hero->master.Get()->GetNetData()->GetBrainLifePct();
if (recover_hp > 0.0f) {
hero->master.Get()->AddHp(recover_hp);
}
}
hero->master.Get()->GetTrigger()->DmgOut(this, dmg_out);
}
}
}
}
}
}
}
}
void Human::OnExplosionHit(Explosion* e)
{
if (IsInvincible()) {
return;
}
#ifdef MYDEBUG
if (a8::HasBitFlag(status, CS_NoDie)) {
return;
}
#endif
if (dead) {
return;
}
if (e->IsPreBattleExplosion()) {
return;
}
if (HasBuffEffect(kBET_Jump) ||
HasBuffEffect(kBET_Fly)) {
return;
}
if (HasBuffEffect(kBET_Dive) && !mt::Param::s().dive_explosion_dmg_switch) {
return;
}
int real_killer_id = 0;
std::string real_killer_name;
if (e->GetSender().Get()) {
real_killer_id = e->GetSender().Get()->GetUniId();
real_killer_name = e->GetSender().Get()->GetName();
SetLastAttacker(e->GetSender());
}
RemoveBuffByEffectId(kBET_PeaceMode);
RemoveHideEffect(kOnExplosionHitReason);
if (!nature_recover_hp_idle_timer.expired()) {
room->xtimer.FireEvent
(
nature_recover_hp_idle_timer,
kRemoveNatureRecoverTimerEvent,
nullptr);
}
last_battling_frameno = room->GetFrameNo();
if (!battling_grass_hide_delay_timer.expired()) {
room->xtimer.ResetTimer(battling_grass_hide_delay_timer);
}
float finaly_dmg = GetNetData()->CalcDmg(e);
#if 1
{
#else
if (e->GetSender().Get()) {
#endif
float dmg_out = 0.0f;
DecHP(finaly_dmg,
VP_Explosion,
"",
e->GetExplosionEffect(),
real_killer_id,
real_killer_name,
dmg_out,
0,
0);
}
}
void Human::SendRollMsgEx(KillInfo& info,
const char* fmt,
std::initializer_list<a8::XValue> args
)
{
}
void Human::ProcUseItem(int item_id)
{
if (downed) {
return;
}
const mt::Equip* item_meta = mt::Equip::GetById(item_id);
if (item_meta && GetItemNum(item_id) > 0) {
if (item_meta->use_scene() == 1 && !HasBuffEffect(kBET_InWater)) {
SendSysPiaoMsg(TEXT("only_inwater_use", "only in water use"),
a8::MkRgb(255, 0, 0),
3
);
return;
}
if (GetCar() && item_meta->equip_type() == EQUIP_TYPE_CAMOUFLAGE) {
return;
}
std::shared_ptr<Ability> old_context_ability = context_ability;
glm::vec3 old_context_dir = context_dir;
Position old_context_pos = context_pos;
context_dir = GetAttackDir();
context_pos = GetPos();
if (item_meta->buffid() != 0) {
TryAddBuff(this, item_meta->buffid());
}
DecItem(item_id, 1);
context_dir = old_context_dir;
context_pos = old_context_pos;
context_ability = old_context_ability;
}
}
Weapon* Human::TakeonWeapon(const mt::Equip* equip_meta)
{
if (equip_meta->equip_type() != EQUIP_TYPE_WEAPON) {
return nullptr;
}
if (equip_meta->equip_subtype() == 1) {
return nullptr;
}
Weapon* weapon = nullptr;
for (int idx = GUN_SLOT1; idx <= GUN_SLOT2; ++idx) {
if (weapons[idx].weapon_id == 0) {
weapon = &weapons[idx];
weapon->weapon_idx = idx;
break;
}
}
return weapon;
}
void Human::StartRefreshViewTimer()
{
if (!refresh_view_timer_.expired()) {
return;
}
refresh_view_timer_ = room->xtimer.SetIntervalWpEx
(
SERVER_FRAME_RATE * mt::Param::s().refresh_view_time,
[this] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
UpdateViewObjects();
}
},
&xtimer_attacher);
}
void Human::ProcLootBag(AddItemDTO& dto)
{
const mt::Equip* old_item_meta = mt::Equip::GetById(backpack);
if (old_item_meta) {
if (old_item_meta->equip_lv() >= dto.item_meta->equip_lv()) {
return;
}
room->DropItem(GetPos().ToGlmVec3(), old_item_meta->id(), 1, 1);
}
backpack = dto.item_meta->id();
RecalcVolume();
dto.handled = true;
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
}
void Human::ProcLootProtection(AddItemDTO& dto)
{
if (dto.item_meta->equip_subtype() == 1) {
//盔甲
const mt::Equip* old_item_meta = mt::Equip::GetById(chest);
if (old_item_meta) {
if (old_item_meta->equip_lv() >= dto.item_meta->equip_lv()) {
return;
}
room->DropItem(GetPos().ToGlmVec3(), old_item_meta->id(), 1, 1);
}
chest = dto.item_meta->id();
RecalcBaseAttr();
} else if (dto.item_meta->equip_subtype() == 2) {
//头盔
const mt::Equip* old_item_meta = mt::Equip::GetById(helmet);
if (old_item_meta) {
if (old_item_meta->equip_lv() >= dto.item_meta->equip_lv()) {
return;
}
room->DropItem(GetPos().ToGlmVec3(), old_item_meta->id(), 1, 1);
}
helmet = dto.item_meta->id();
RecalcBaseAttr();
}
dto.handled = true;
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
}
void Human::ProcLootSpecItem(AddItemDTO& dto)
{
if (dto.item_meta->_inventory_slot() >= 0 &&
dto.item_meta->_inventory_slot() < IS_END) {
if (GetInventory(dto.item_meta->_inventory_slot()) >=
GetVolume(dto.item_meta->_inventory_slot())
) {
return;
}
int add_num = GetVolume(dto.item_meta->_inventory_slot()) -
GetInventory(dto.item_meta->_inventory_slot());
add_num = std::min(dto.count, add_num);
AddInventory(dto.item_meta->_inventory_slot(), add_num);
SyncVolume(dto.item_meta->_inventory_slot());
switch (dto.item_meta->_inventory_slot()) {
case IS_FRAG:
case IS_SMOKE:
{
Weapon* weapon = &weapons[SPEC1_SLOT_BEGIN +
(dto.item_meta->_inventory_slot() - SPEC1_IS_BEGIN)
];
weapon->weapon_id = dto.item_id;
weapon->ammo += add_num;
weapon->meta = dto.item_meta;
weapon->Recalc();
#if 0
DecInventory(dto.item_meta->_inventory_slot(), add_num);
#endif
}
break;
case IS_1XSCOPE:
case IS_2XSCOPE:
case IS_4XSCOPE:
case IS_8XSCOPE:
case IS_15XSCOPE:
{
if (dto.item_meta->_inventory_slot() - IS_1XSCOPE > curr_scope_idx) {
curr_scope_idx = dto.item_meta->_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 +
(dto.item_meta->_inventory_slot() - SPEC2_IS_BEGIN)
];
weapon->weapon_id = dto.item_id;
weapon->ammo += add_num;
weapon->meta = dto.item_meta;
weapon->Recalc();
#if 0
DecInventory(dto.item_meta->_inventory_slot(), add_num);
#endif
}
break;
case IS_C4:
case IS_SHIELD_WALL:
case IS_SINGAL_GUN:
case IS_OIL_BUCKET:
{
Weapon* weapon = &weapons[SPEC3_SLOT_BEGIN +
(dto.item_meta->_inventory_slot() - SPEC3_IS_BEGIN)
];
weapon->weapon_id = dto.item_id;
weapon->ammo += add_num;
weapon->meta = dto.item_meta;
weapon->Recalc();
#if 0
DecInventory(dto.item_meta->_inventory_slot(), add_num);
#endif
}
break;
default:
{
int i = 0;
#if 0
A8_ABORT();
#endif
}
break;
}
if (add_num < dto.count) {
//刷新数量
Entity* entity = room->GetEntityByUniId(dto.uniid);
if (entity && entity->IsEntityType(ET_Loot)) {
((Loot*)entity)->count -= add_num;
((Loot*)entity)->BroadcastFullState(room);
}
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
if (action_type == AT_None) {
AutoLoadingBullet();
}
return;
}
}
if (action_type == AT_None) {
AutoLoadingBullet();
}
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
dto.handled = true;
}
void Human::ProcGiftPackage(AddItemDTO& dto)
{
if (dto.item_meta->equip_type() == EQUIP_TYPE_GIFT_PACKAGE) {
const mt::Drop* drop_meta = mt::Drop::GetById(dto.item_meta->drop_id());
if (drop_meta) {
std::vector<std::tuple<int, int, int>> drop_items;
drop_meta->RandItems(drop_items);
for (auto& item : drop_items) {
int item_id = std::get<0>(item);
int item_num = std::get<1>(item);
auto itr = battlein_items.find(item_id);
if (itr != battlein_items.end()) {
itr->second += item_num;
} else {
battlein_items[item_id] = item_num;
}
}
}
}
dto.handled = true;
}
void Human::ProcLootWeapon(AddItemDTO& dto)
{
//装备
if (dto.item_meta->equip_subtype() == 1) {
//近战
#ifdef NEW_WEAPON_SYS
if (default_weapon.weapon_id != weapons[0].weapon_id) {
return;
} else {
weapons[0].weapon_idx = 0;
weapons[0].weapon_id = dto.item_id;
weapons[0].ammo = 0;
weapons[0].meta = dto.item_meta;
weapons[0].Recalc();
}
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
#endif
dto.handled = true;
} else {
#if 0
if (GetBuffByEffectId(kBET_Passenger) ||
GetBuffByEffectId(kBET_Vertigo)) {
return;
}
#else
if (FreezeOperate()) {
return;
}
#endif
if (mt::Param::s().compose_mode) {
ProcLootWeaponNew(dto);
} else {
bool droped = false;
if (weapons[GUN_SLOT1].weapon_id != 0 && weapons[GUN_SLOT2].weapon_id != 0) {
if (GetCurrWeapon() == &weapons[GUN_SLOT1]) {
if (mt::Param::s().pickup_weapon_replace_type) {
DropWeapon(GUN_SLOT2, 1);
} else {
DropWeapon(GUN_SLOT1, 1);
}
} else {
if (mt::Param::s().pickup_weapon_replace_type) {
DropWeapon(GUN_SLOT1, 1);
} else {
DropWeapon(GUN_SLOT2, 1);
}
}
droped = true;
}
bool switch_gun = false;
Weapon* weapon = TakeonWeapon(dto.item_meta);
if (weapon && GetCurrWeapon() != weapon) {
if (GetCurrWeapon()->weapon_idx == 0) {
switch_gun = true;
}
}
if (!weapon) {
return;
}
if (droped && !mt::Param::s().pickup_weapon_replace_type) {
switch_gun = true;
}
weapon->weapon_id = dto.item_id;
weapon->meta = dto.item_meta;
weapon->ammo = 0;
weapon->Recalc();
weapon->ammo = weapon->GetClipVolume(this);
AutoLoadingBullet();
if (switch_gun) {
SetCurrWeapon(weapon);
}
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
dto.handled = true;
}
}
}
void Human::ProcLootWeaponNew(AddItemDTO& dto)
{
if (GetCurrWeapon()->weapon_idx == GUN_SLOT0 ||
GetCurrWeapon()->weapon_idx == GUN_SLOT1 ||
GetCurrWeapon()->weapon_idx == GUN_SLOT2) {
if (GetCurrWeapon()->weapon_id == dto.item_meta->id()) {
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
dto.handled = true;
} else {
int old_weapon_idx = GetCurrWeapon()->weapon_idx;
if (GetCurrWeapon()->weapon_idx == GUN_SLOT0) {
old_weapon_idx = GUN_SLOT1;
DropWeapon(old_weapon_idx, 1);
} else {
DropWeapon(GetCurrWeapon()->weapon_idx, 1);
}
Weapon* weapon = &weapons[old_weapon_idx];
weapon->weapon_id = dto.item_id;
weapon->meta = dto.item_meta;
weapon->ammo = 0;
weapon->Recalc();
weapon->ammo = weapon->GetClipVolume(this);
AutoLoadingBullet();
SetCurrWeapon(weapon);
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
dto.handled = true;
}
}
}
void Human::LootInteraction(Loot* entity)
{
#ifdef MYDEBUG1
a8::XPrintf("LootInteraction start %d:%d\n", {entity->GetUniId(), entity->item_id});
#endif
if (entity->pickuped ||
entity->count <= 0) {
#ifdef MYDEBUG1
a8::XPrintf("LootInteraction error1 %d:%d\n", {entity->GetUniId(), entity->item_id});
#endif
return;
}
if (entity->pickup_flag != 0) {
if (entity->pickup_flag == 1) {
if (!(entity->master.Get() && entity->master.Get() == this)) {
return;
}
} else if (entity->pickup_flag == 2) {
if (!(entity->master.Get() && entity->master.Get()->team_id == team_id)) {
return;
}
}
}
AddItemDTO dto;
dto.uniid = entity->GetUniId();
dto.item_id = entity->item_id;
dto.count = entity->count;
dto.item_level = entity->item_level;
dto.handled = false;
dto.item_meta = mt::Equip::GetById(entity->item_id);
ProcAddItemDto(dto);
if (dto.handled) {
entity->pickuped = true;
room->xtimer.SetTimeoutEx
(NEXT_FRAME_TIMER,
[this, target_uniid = entity->GetUniId()] (int event, const a8::Args* args)
{
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropPickUp,
0,
target_uniid,
false);
},
&xtimer_attacher);
room->RemoveObjectLater(entity);
}
}
void Human::ObstacleInteraction(Obstacle* entity)
{
entity->DoInteraction(this);
}
void Human::ProcAddItemDto(AddItemDTO& dto)
{
if (!dto.item_meta) {
#ifdef MYDEBUG
a8::XPrintf("LootInteraction error20 %d:%d\n", {dto.uniid, dto.item_id});
#endif
return;
}
switch (dto.item_meta->equip_type()) {
case EQUIP_TYPE_WEAPON:
{
ProcLootWeapon(dto);
}
break;
case EQUIP_TYPE_PROTECTION:
{
ProcLootProtection(dto);
}
break;
case EQUIP_TYPE_BAG:
{
ProcLootBag(dto);
}
break;
case EQUIP_TYPE_OLDSKIN:
{
A8_ABORT();
}
break;
case EQUIP_TYPE_SKIN:
{
ProcLootSkin(dto);
}
break;
case EQUIP_TYPE_CAR:
{
ProcLootCar(dto);
}
break;
case EQUIP_TYPE_SPOILS:
{
ProcSpoils(dto);
}
break;
case EQUIP_TYPE_CAMOUFLAGE:
case EQUIP_TYPE_SINGAL_EMITTER:
{
ProcNormalItem(dto);
}
break;
case EQUIP_TYPE_GIFT_PACKAGE:
{
ProcGiftPackage(dto);
}
break;
case EQUIP_TYPE_GEMSTONE:
{
if (dto.item_meta->equip_subtype() == GEMSTONE_SUB_EQUIP_ENERGY) {
ProcYellowStoneItem(dto);
} else if (dto.item_meta->equip_subtype() == GEMSTONE_SUB_EQUIP_SKILL) {
ProcBlueStoneItem(dto);
} else if (dto.item_meta->equip_subtype() == GEMSTONE_SUB_EQUIP_SHIELD) {
ProcPurpleStoneItem(dto);
} else if (dto.item_meta->equip_subtype() == GEMSTONE_SUB_EQUIP_WEAPON) {
ProcWeaponStoneItem(dto);
}
}
break;
case EQUIP_TYPE_LOVE:
{
ProcLoveItem(dto);
}
break;
default:
{
ProcLootSpecItem(dto);
}
break;
}
}
void Human::DropWeapon(int weapon_idx, int num)
{
num = std::max(1, num);
switch (weapon_idx) {
case 101:
case 102:
case 103:
{
int slot_id = -1;
if (weapon_idx == 101) {
slot_id = IS_HEALTHKIT;
} else if (weapon_idx == 102) {
slot_id = IS_PAIN_KILLER;
} else if (weapon_idx == 103) {
slot_id = IS_SHEN_BAO;
}
if (slot_id >= 0 && GetInventory(slot_id) > 0) {
const mt::Equip* item_meta = mt::Equip::GetByIdBySlotId(slot_id);
if (item_meta) {
num = std::max(1, GetInventory(slot_id));
DecInventory(slot_id, num);
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
glm::vec3 drop_dir = GlmHelper::UP;
GlmHelper::RotateY(drop_dir, a8::RandAngle());
Position drop_pos = GetPos();
drop_pos.AddGlmVec3(drop_dir * (25.0f + rand() % 50));
room->DropItem(drop_pos.ToGlmVec3(), item_meta->id(), num, 1);
}
}
return;
}
default:
{
}
break;
}
if (weapon_idx < 0 ||
weapon_idx >= weapons.size()) {
return;
}
bool is_curr_weapon = weapon_idx == GetCurrWeapon()->weapon_idx;
#if 1
//888
int stack_num = 0;
#else
int stack_num = is_curr_weapon ? GetCompose()->GetNum() + 1: 0;
#endif
bool drop_ok = false;
Weapon* weapon = &weapons[weapon_idx];
int weapon_id = weapon->weapon_id;
int weapon_ammo = weapon->ammo;
const mt::Equip* weapon_meta = weapon->meta;
if (weapon->weapon_id != 0) {
switch (weapon->weapon_idx) {
case GUN_SLOT0:
{
if (weapon->weapon_id != default_weapon.weapon_id) {
drop_ok = true;
*weapon = default_weapon;
}
}
break;
case GUN_SLOT1:
{
drop_ok = true;
*weapon = Weapon();
weapon->weapon_idx = weapon_idx;
if (GetCurrWeapon() == weapon) {
if (weapons[GUN_SLOT2].weapon_id != 0) {
SetCurrWeapon(&weapons[GUN_SLOT2]);
} else {
SetCurrWeapon(&weapons[0]);
}
}
}
break;
case GUN_SLOT2:
{
drop_ok = true;
*weapon = Weapon();
weapon->weapon_idx = weapon_idx;
if (GetCurrWeapon() == weapon) {
if (weapons[GUN_SLOT1].weapon_id != 0) {
SetCurrWeapon(&weapons[GUN_SLOT1]);
} else {
SetCurrWeapon(&weapons[0]);
}
}
}
break;
case FRAG_SLOT:
{
weapon_ammo = std::min(weapon->ammo, num);
if (weapon_ammo > 0) {
drop_ok = true;
weapon->ammo = std::max(0, weapon->ammo - weapon_ammo);
int slot_id = weapon->meta->_inventory_slot();
DecInventory(slot_id, weapon_ammo);
SyncVolume(slot_id);
if (weapon->ammo <= 0) {
*weapon = Weapon();
weapon->weapon_idx = 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]);
}
}
}
}
}
break;
case SMOKE_SLOT:
{
weapon_ammo = std::min(weapon->ammo, num);
if (weapon_ammo > 0) {
drop_ok = true;
weapon->ammo = std::max(0, weapon->ammo - weapon_ammo);
int slot_id = weapon->meta->_inventory_slot();
DecInventory(slot_id, weapon_ammo);
SyncVolume(slot_id);
if (weapon->ammo <= 0) {
*weapon = Weapon();
weapon->weapon_idx = 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]);
}
}
}
}
}
break;
default:
{
weapon_ammo = std::min(weapon->ammo, num);
if (weapon_ammo > 0) {
drop_ok = true;
weapon->ammo = std::max(0, weapon->ammo - weapon_ammo);
int slot_id = weapon->meta->_inventory_slot();
DecInventory(slot_id, weapon_ammo);
SyncVolume(slot_id);
if (weapon->ammo <= 0) {
*weapon = Weapon();
weapon->weapon_idx = weapon_idx;
if (GetCurrWeapon() == weapon) {
Weapon* next_weapon = ChooseNextSpecWeapon(weapon_idx);
if (!next_weapon) {
next_weapon = AutoChgWeapon();
}
if (next_weapon) {
SetCurrWeapon(next_weapon);
}
}
}
}
}
break;
}
if (drop_ok) {
bool create_loot = true;
if (weapon_ammo > 0) {
const mt::Equip* bullet_meta = mt::Equip::GetById(weapon_meta->use_bullet());
if (bullet_meta && bullet_meta->_inventory_slot() > 0) {
#if 1
int drop_num = weapon_ammo;
#else
int volume = GetVolume(bullet_meta->_inventory_slot());
int inventory = GetInventory(bullet_meta->_inventory_slot());
int add_inventory = std::min(weapon_ammo, volume - std::min(volume, inventory));
if (add_inventory > 0 &&
!(weapon_idx == FRAG_SLOT || weapon_idx == SMOKE_SLOT)) {
AddInventory(bullet_meta->_inventory_slot(), add_inventory);
}
int drop_num = weapon_ammo - add_inventory;
#endif
if (drop_num > 0) {
glm::vec3 drop_dir = GlmHelper::UP;
GlmHelper::RotateY(drop_dir, a8::RandAngle());
Position drop_pos = GetPos();
drop_pos.FromGlmVec3(GetPos().ToGlmVec3() + drop_dir * (25.0f + rand() % 50));
#if 1
{
room->DropItem(drop_pos.ToGlmVec3(), bullet_meta->id(), drop_num, 1);
create_loot = false;
}
#else
if (bullet_meta->_inventory_slot() == IS_FRAG ||
bullet_meta->_inventory_slot() == IS_SMOKE) {
//只有手雷和烟雾弹会掉落
room->DropItem(drop_pos, bullet_meta->id(), drop_num, 1);
create_loot = false;
}
#endif
}
}
}
if (create_loot ||
weapon_idx == GUN_SLOT0 ||
weapon_idx == GUN_SLOT1 ||
weapon_idx == GUN_SLOT2) {
int drop_num = std::max(1, stack_num);
for (int i = 0; i < drop_num; ++i) {
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
Position pos = GetPos();
pos.FromGlmVec3(GetPos().ToGlmVec3() + dir * (40.0f + rand() % 50));
room->CreateLoot(weapon_id, GetPos().ToGlmVec3(), pos.ToGlmVec3(), 1, 1);
}
}
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
}
}
}
void Human::DoFollow(int target_id)
{
if (target_id == 0){
if (follow_target.Get()) {
follow_target.Detach();
room->frame_event.AddPropChg(GetWeakPtrRef(), kPropFollowTarget, 0, 0, true);
if (!follow_target_timer_.expired()) {
room->xtimer.Delete(follow_target_timer_);
}
}
} else {
if (GetTeam()) {
Human* member = GetTeam()->GetMemberByUniId(target_id);
if (member && member->CanFollow(this)) {
#ifdef MYDEBUG
a8::XPrintf("DoFollow %d->%d\n", {GetUniId(), member->GetUniId()});
#endif
if (follow_target.Get()) {
follow_target.Detach();
if (!follow_target_timer_.expired()) {
room->xtimer.Delete(follow_target_timer_);
}
}
follow_target_last_chg_move_dir_times_ = -1;
follow_target.Attach(member);
room->frame_event.AddPropChg(GetWeakPtrRef(), kPropFollowTarget, 0, target_id, true);
follow_target_timer_ = room->xtimer.SetIntervalWpEx
(
400 / FRAME_RATE_MS,
[this] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
if (!follow_target.Get()) {
if (IsPlayer()) {
AsPlayer()->moving = false;
AsPlayer()->moved_frames = 0;
}
room->xtimer.DeleteCurrentTimer();
return;
}
if (room->GetGasData().GetGasMode() != GasInactive &&
!(follow_target.Get()->HasBuffEffect(kBET_Fly) ||
follow_target.Get()->HasBuffEffect(kBET_Jump))
){
if (IsPlayer()) {
AsPlayer()->moving = false;
AsPlayer()->moved_frames = 0;
}
follow_target.Detach();
room->xtimer.DeleteCurrentTimer();
return;
}
if (follow_target.Get()->HasBuffEffect(kBET_Jump)) {
if (HasBuffEffect(kBET_Jump)) {
FollowToTarget();
} else {
DoJump();
}
}
}
},
&xtimer_attacher);
}
}
}
IncFollowTimes();
}
void Human::DoDive()
{
if (!HasBuffEffect(kBET_InWater)) {
return;
}
if (HasBuffEffect(kBET_Dive)) {
return;
}
if (HasBuffEffect(kBET_Driver) ||
HasBuffEffect(kBET_Passenger)) {
return;
}
if (HasBuffEffect(kBET_Floating)) {
return;
}
#if 0
if (HasBuffEffect(kBET_Become)) {
return;
}
#endif
if (HasBuffEffect(kBET_Camouflage) ) {
RemoveBuffByEffectId(kBET_Camouflage);
}
MustBeAddBuff(this, kDiveBuffId);
}
void Human::OnWatcherDie(Human* watcher)
{
if (follow_target_ == watcher) {
if (SocketIsValid() && IsPlayer()) {
((Player*)this)->AsyncRequestWatchWar(true);
}
} else {
#ifdef MYDEBUG
A8_ABORT();
#endif
}
}
void Human::TraverseObservers(std::function<void (Human*, bool&)> func)
{
bool stop = false;
for (auto& observer : observers_) {
func(observer, stop);
if (stop) {
break;
}
}
}
void Human::AddOxygen(int val)
{
oxygen_ += val;
oxygen_ = std::min(mt::Param::s().dive_oxygen_total, oxygen_);
}
void Human::DecOxygen(int val)
{
oxygen_ -= val;
oxygen_ = std::max(0, oxygen_);
}
void Human::WinPveScore(int score)
{
stats->pve_rank_score += score;
}
void Human::InternalBeKill(int killer_id, const std::string& killer_name, int weapon_id,
int real_killer_id, const std::string& real_killer_name)
{
#ifdef MYDEBUG
if (IsPlayer()) {
a8::XPrintf("BeKill %d\n", {GetUniId()});
}
#endif
if (!dead && !room->IsGameOver() && !real_dead) {
room->GetBoxDrop()->OnHumanDeadDrop(this);
KillInfo info;
{
info.killer_id = killer_id;
info.killer_name = killer_name;
info.weapon_id = weapon_id;
info.real_killer_id = real_killer_id;
info.real_killer_name = real_killer_name;
}
{
++stats->dead_times;
stats->killer_id = real_killer_id;
stats->killer_name = real_killer_name;
stats->weapon_id = weapon_id;
}
{
Entity* killer = room->GetEntityByUniId(real_killer_id);
if (killer && killer->IsCreature(room)) {
((Creature*)killer)->GetTrigger()->Kill(this, weapon_id);
info.real_killer_team_id = ((Creature*)killer)->team_id;
}
}
if (room->IsPveRoom()) {
dead = true;
real_dead = false;
downed = false;
SetHP(0.0f);
if (real_killer_id != GetUniId() && GetTeam() && GetTeam()->HasReviveCoin(this)) {
real_dead = true;
dead_frameno = room->GetFrameNo();
GetTrigger()->Die(killer_id, weapon_id);
if (real_dead) {
real_dead = false;
OnDie();
KillMgr::Instance()->OnHumanDead(this, &info);
room->frame_event.AddDead(GetWeakPtrRef(), 1000 * mt::Param::s().revive_time);
dead_timer = room->xtimer.SetTimeoutWpEx
(mt::Param::s().revive_time * SERVER_FRAME_RATE,
[this] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
real_dead = true;
SendGameOver();
}
},
&xtimer_attacher);
} else {
OnDie();
KillMgr::Instance()->OnHumanDead(this, &info);
room->frame_event.AddDead(GetWeakPtrRef(), 0);
}
} else {
real_dead = true;
dead_frameno = room->GetFrameNo();
GetTrigger()->Die(killer_id, weapon_id);
OnDie();
KillMgr::Instance()->OnHumanDead(this, &info);
room->frame_event.AddDead(GetWeakPtrRef(), 0);
}
} else if (room->IsMobaModeRoom()) {
dead = true;
real_dead = false;
downed = false;
SetHP(0.0f);
dead_frameno = room->GetFrameNo();
GetTrigger()->Die(killer_id, weapon_id);
OnDie();
KillMgr::Instance()->OnHumanDead(this, &info);
room->frame_event.AddDead(GetWeakPtrRef(),
room->GetMapMeta()->GetMobaRoomMeta()->revive_time() * 1000);
a8::SetBitFlag(status, CS_Reviving);
dead_timer = room->xtimer.SetTimeoutWpEx
(room->GetMapMeta()->GetMobaRoomMeta()->revive_time() * SERVER_FRAME_RATE,
[this] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
if (!room->IsGameOver()) {
if (dead) {
App::Instance()->verify_set_pos = 1;
SetPos(GetBornPoint()->RandPoint(room));
room->grid_service->MoveCreature(this);
App::Instance()->verify_set_pos = 0;
GetMovement()->ClearPath();
InitMobaRoad();
a8::UnSetBitFlag(status, CS_Reviving);
++stats->revive;
dead = false;
real_dead = false;
downed = false;
SetHP(GetMaxHP());
AdjustMobaBornDir();
room->frame_event.AddPropChg(GetWeakPtrRef(),
kPropFlyTo,
0,
0,
false);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
room->frame_event.AddRevive(GetWeakPtrRef());
{
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);
}
}
}
room->GetInGameVoice()->OnHumanRevive(this);
SendViewerUiMemberUpdate({GetUniId()});
}
}
}
},
&xtimer_attacher);
++revive_count;
} else {
if (room->GetGasData().old_area_meta &&
room->GetGasData().old_area_meta->CanRevive() &&
revive_count < mt::Param::s().revive_count) {
dead = true;
real_dead = false;
downed = false;
SetHP(0.0f);
dead_frameno = room->GetFrameNo();
GetTrigger()->Die(killer_id, weapon_id);
OnDie();
KillMgr::Instance()->OnHumanDead(this, &info);
room->frame_event.AddDead(GetWeakPtrRef(),
1000 * mt::Param::s().pvp_revive_time);
dead_timer = room->xtimer.SetTimeoutWpEx
(mt::Param::s().pvp_revive_time * SERVER_FRAME_RATE,
[this] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
}
},
&xtimer_attacher);
++revive_count;
} else {
dead = true;
real_dead = true;
downed = false;
SetHP(0.0f);
dead_frameno = room->GetFrameNo();
GetTrigger()->Die(killer_id, weapon_id);
OnDie();
KillMgr::Instance()->OnHumanDead(this, &info);
room->frame_event.AddDead(GetWeakPtrRef(), 0);
}
}
room->GetInGameVoice()->OnHumanBeKill(real_killer_id, this);
}
SendViewerUiMemberUpdate({GetUniId(), killer_id, real_killer_id});
room->NotifyUiUpdate();
}
int Human::GetTeamMode()
{
return GetTeam()->GetMemberNum() <= 1 ? 0 : 1;
}
void Human::CalcAssists(Human* target)
{
if (GetTeam() && GetTeam()->GetMemberNum() > 1) {
GetTeam()->TraverseMembers
(
[target, this] (Human* hum)
{
if (hum->GetUniId() == this->GetUniId()) {
return true;
}
int assist_time = mt::Param::GetIntParam("assist_time", 5);
auto itr = target->attacker_hash_.find(hum->GetUniId());
if (itr != target->attacker_hash_.end()) {
if (hum->room->GetFrameNo() - itr->second <
SERVER_FRAME_RATE * assist_time) {
++hum->stats->assist;
room->NotifyUiUpdate();
}
}
return true;
});
}
}
void Human::SyncVolume(int slot_id)
{
if (room->GetFrameNo() - join_frameno < SERVER_FRAME_RATE * 0.5) {
return;
}
if (slot_id < 0) {
for (int i = 0; i < IS_END; ++i) {
if (volume_[i] > 0) {
room->xtimer.SetTimeoutEx
(
NEXT_FRAME_TIMER,
[this, i] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
room->frame_event.AddPropChgEx(GetWeakPtrRef(), kPropVolume, i, GetInventory(i), volume_[i], 0, true);
}
},
&xtimer_attacher);
}
}
} else if (slot_id < IS_END){
room->frame_event.AddPropChgEx(GetWeakPtrRef(), kPropVolume, slot_id, GetInventory(slot_id), volume_[slot_id], 0, true);
}
}
void Human::ProcYellowStoneItem(AddItemDTO& dto)
{
if (GetInventory(IS_YELLOW_STONE) >= GetVolume(IS_YELLOW_STONE)) {
return;
}
AddInventory(IS_YELLOW_STONE, 1);
gemstone += 1;
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropYellowStone,
0,
gemstone,
false);
#if 0
auto context = A8_MAKE_SMART_ANON_STRUCT_SHARED
(
CreatureWeakPtr owner;
AttrRateHandle handle;
);
context->owner = GetWeakPtrRef();
context->_destory_cb =
[context = context.get()] ()
{
if (context->owner.Get() &&
context->owner.Get()->room->IsDestorying() &&
!context->handle.expired()
) {
context->owner.Get()->GetAbility()->RemoveAttrRate(context->handle);
}
};
context->handle = GetAbility()->AddAttrRate(kHAT_Atk, dto.item_meta->_atk);
on_dead_remove_objects_.push_back(context);
SetMaxHP(GetMaxHP() + dto.item_meta->_max_hp * GetNetData()->GetMaxHP());
SetHP(GetHP() + dto.item_meta->_max_hp * GetNetData()->GetMaxHP());
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropHp,
0,
GetHP(),
true);
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropMaxHp,
0,
GetMaxHP(),
true);
#endif
if (GetInventory(IS_YELLOW_STONE) % 3 == 0) {
ClearGemStoneBuffs();
auto merge_item_meta = mt::MergeItem::GetById(mt::Equip::YELLOW_STONE_ID);
if (merge_item_meta) {
std::set<int>* buffs = merge_item_meta->GetBuffs(GetInventory(IS_YELLOW_STONE) / 3);
if (buffs) {
for (int buff_id : *buffs) {
gemstone_hold_buffs.push_back(TryAddBuff(this, buff_id, nullptr));
}
}
}
}
SyncVolume(IS_YELLOW_STONE);
//刷新数量
int add_num = 1;
Entity* entity = room->GetEntityByUniId(dto.uniid);
if (entity && entity->IsEntityType(ET_Loot)) {
((Loot*)entity)->count -= add_num;
}
dto.handled = true;
}
void Human::ProcBlueStoneItem(AddItemDTO& dto)
{
//技能
if (GetInventory(IS_BLUE_STONE) >= GetVolume(IS_BLUE_STONE)) {
return;
}
Skill* skill = GetMainSkill();
if (!skill) {
return;
}
if (!skill->Actived()) {
skill->Active();
}
AddInventory(IS_BLUE_STONE, 1);
skill->LevelUp();
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropYellowStone,
0,
GetInventory(IS_BLUE_STONE),
false);
//刷新数量
int add_num = 1;
Entity* entity = room->GetEntityByUniId(dto.uniid);
if (entity && entity->IsEntityType(ET_Loot)) {
((Loot*)entity)->count -= add_num;
}
SyncVolume(IS_BLUE_STONE);
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
dto.handled = true;
}
void Human::ProcPurpleStoneItem(AddItemDTO& dto)
{
//护盾
if (GetInventory(IS_PURPLE_STONE) >= GetVolume(IS_PURPLE_STONE)) {
return;
}
AddInventory(IS_PURPLE_STONE, 1);
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropPurpleStone,
0,
GetInventory(IS_PURPLE_STONE),
false);
max_armor_shield = GetMaxHP();
armor_shield += max_armor_shield * dto.item_meta->_float_param1;
armor_shield = std::min(armor_shield, max_armor_shield);
room->frame_event.AddPropChg
(
GetWeakPtrRef(),
kPropArmorShield,
armor_shield,
max_armor_shield,
true);
//刷新数量
int add_num = 1;
Entity* entity = room->GetEntityByUniId(dto.uniid);
if (entity && entity->IsEntityType(ET_Loot)) {
((Loot*)entity)->count -= add_num;
}
SyncVolume(IS_PURPLE_STONE);
dto.handled = true;
}
void Human::ProcWeaponStoneItem(AddItemDTO& dto)
{
MarkSyncActivePlayer(__FILE__, __LINE__, __func__);
SyncAroundPlayers(__FILE__, __LINE__, __func__);
AddInventory(IS_WEAPON_STONE, 1);
SyncVolume(IS_WEAPON_STONE);
dto.handled = true;
}
void Human::CalcStats()
{
if (statsed_) {
return;
}
statsed_ = true;
int rank = 0;
{
std::vector<Human*> human_list;
room->TraverseHumanList(
[&human_list] (Human* hum) -> bool
{
human_list.push_back(hum);
return true;
});
std::sort(human_list.begin(), human_list.end(),
[] (Human* a, Human* b )
{
if (a->real_dead && b->real_dead) {
if (a->dead_frameno == b->dead_frameno) {
return a->GetUniId() < b->GetUniId();
} else {
return a->dead_frameno == 0 ||
(b->dead_frameno != 0 && a->dead_frameno > b->dead_frameno);
}
} else {
if (a->real_dead) {
return false;
}
if (b->real_dead) {
return true;
}
return a->GetUniId() < b->GetUniId();
}
});
rank = human_list.size();
for (size_t i = 0; i < human_list.size(); ++i) {
if (human_list[i] == this) {
rank = i + 1;
break;
}
}
if (room->GetAliveTeamNum() == 1) {
if (room->GetAliveTeam() == GetTeam()) {
rank = 1;
}
}
stats->rank = rank;
if (room->IsPveRoom()) {
stats->pve_wave = room->pve_data.GetPassedWave();
if (room->pve_data.pve_kill_boss) {
stats->victory = true;
stats->settlement_color = 1;
GetTeam()->settlement_color = 1;
GetTeam()->team_rank = 1;
} else {
if (GetTeam()->GetAliveNum() <= 0) {
stats->victory = false;
stats->settlement_color = 0;
GetTeam()->settlement_color = 0;
GetTeam()->team_rank = 1;
}
}
} if (room->IsMobaModeRoom()) {
stats->victory = GetTeam() == room->GetVictoryTeam();
if (GetTeam() == room->GetVictoryTeam()) {
GetTeam()->team_rank = 1;
room->GetMobaEnemyTeam(GetTeam())->team_rank = 2;
} else {
GetTeam()->team_rank = 2;
room->GetMobaEnemyTeam(GetTeam())->team_rank = 1;
}
if (GetTeam()->team_rank == 1) {
stats->settlement_color = 1;
GetTeam()->settlement_color = 1;
} else {
}
} else {
stats->victory = stats->rank == 1;
if (GetTeam()->GetAliveNum() <= 0) {
GetTeam()->team_rank = room->GetAliveTeamNum() + 1;
stats->pvp_settlement_type = GetTeam()->GetMemberNum() > 1 ? 1 : 0;
stats->settlement_color = 1;
GetTeam()->settlement_color = 1;
} else {
if (room->GetAliveTeamNum() == 1) {
if (room->GetAliveTeam() == GetTeam()) {
GetTeam()->team_rank = 1;
stats->pvp_settlement_type = GetTeam()->GetMemberNum() > 1 ? 1 : 0;
stats->settlement_color = 1;
GetTeam()->settlement_color = 1;
}
}
}
if (rank < 10) {
stats->settlement_color = 1;
GetTeam()->settlement_color = 1;
}
if (stats->victory) {
GetTeam()->team_rank = 1;
}
}
}
if (!stats->statemented) {
stats->Statement(this);
}
int alive_time = room->GetFrameNo() * FRAME_RATE_MS;
if (!dead) {
stats->alive_time = alive_time;
} else {
alive_time = (dead_frameno - room->GetBattleStartFrameNo()) * FRAME_RATE_MS;
if (room->GetBattleStartFrameNo() <= 0) {
alive_time = 0;
}
stats->alive_time = alive_time;
}
#if 0
GetTeam()->team_rank = 1;
#endif
if (stats->victory) {
room->SetVictoryTeam(GetTeam());
}
if (GetTeam()->team_rank) {
GetTeam()->TraverseMembers
(
[] (Human* hum)
{
hum->CalcStats();
return true;
});
}
}
void Human::ProcLoveItem(AddItemDTO& dto)
{
dto.handled = true;
if (dto.item_meta->buffid()) {
Entity* e = room->GetEntityByUniId(dto.uniid);
if (e && e->IsEntityType(ET_Loot)) {
Loot* loot = (Loot*)e;
TryAddBuff(this,
dto.item_meta->buffid(),
loot->skill_meta,
nullptr,
loot->buff_vars
);
}
}
}
void Human::ShiledBreak()
{
Buff* hold_shield_buff = GetBuffByEffectId(kBET_HoldShield);
if (hold_shield_buff) {
GetTrigger()->ShieldDestory();
if (hold_shield_buff->meta->_buff_param1_int_list.size() > 0) {
TryAddBuff(this, hold_shield_buff->meta->_buff_param1_int_list[0]);
}
RemoveBuffByUniId(hold_shield_buff->buff_uniid);
}
}
void Human::SendPersonalBattleReport()
{
if (room->IsPveRoom()) {
return;
}
if (room->GetBattleStartFrameNo() <= 0) {
return;
}
std::shared_ptr<a8::MutableXObject> params = a8::MutableXObject::CreateObject();
{
params->SetVal("account_id", account_id);
params->SetVal("session_id", session_id);
params->SetVal("version", 2023030201);
params->SetVal("battle_uuid", a8::XValue(GetTeam()->GetBattleUuid()));
params->SetVal("room_uuid", a8::XValue(room->GetRoomUuid()));
params->SetVal("room_mode", room->GetReportRoomMode());
params->SetVal("team_id", GetTeam()->GetTeamId());
params->SetVal("pvp_personal_rank", stats->rank);
}
std::string url;
JsonDataMgr::Instance()->GetApiUrl(url);
params->SetVal("c", "Battle");
params->SetVal("a", "personalReport");
std::string data;
params->ToUrlEncodeStr(data);
HttpProxy::Instance()->HttpGet
(
[data]
(bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx)
{
if (!ok) {
f8::UdpLog::Instance()->Error("personalReport http error params: %s response: %s",
{
data,
""
});
}
},
url,
params
);
}
void Human::SetBornPoint(std::shared_ptr<BornPoint> born_point)
{
#ifdef MYDEBUG
auto itr = debug_data_.find(1);
if (itr == debug_data_.end()) {
debug_data_[1] = 1;
itr = debug_data_.find(1);
} else {
itr->second++;
}
if (itr->second > 1) {
//TraceMgr::Instance()->PrintBackTrace();
}
a8::XPrintf
(
"SetBornPoint uniid:%d wo_meta:%d\n",
{
GetUniId(),
(long long)born_point->wo_meta.get()
}
);
#endif
switch (side) {
case 1:
case 2:
{
if (born_point->wo_meta.get() != std::get<0>(room->GetMapMeta()->moba_born_points.at(side - 1)).get()) {
abort();
}
}
break;
default:
{
break;
}
}
born_point_ = born_point;
}
bool Human::SocketIsValid()
{
return GetSocketHandle() != 0;
}
void Human::SetSocketHandle(int socket_handle)
{
#ifdef MYDEBUG
a8::XPrintf("SetSocketHandle account_id:%s room_uuid:%s socket_handle:%d\n",
{
account_id,
room->GetRoomUuid(),
socket_handle
});
if (socket_handle == 0) {
TraceMgr::Instance()->PrintBackTrace();
}
#endif
socket_handle_ = socket_handle;
}
void Human::SetIpSaddr(long ip_saddr)
{
ip_saddr_ = ip_saddr;
}
int Human::GetHeroQuality()
{
return hero_quality_;
}
void Human::SetHeroQuality(int quality)
{
hero_quality_ = quality;
}