aozhiwei b366492f0e 1
2024-08-23 14:42:02 +08:00

382 lines
11 KiB
C++

#include "precompile.h"
#include <random>
#include <glm/glm.hpp>
#include <a8/mutable_xobject.h>
#include <f8/app.h>
#include <f8/udplog.h>
#include "boxdrop.h"
#include "room.h"
#include "hero.h"
#include "roomobstacle.h"
#include "httpproxy.h"
#include "jsondatamgr.h"
#include "player.h"
#include "mapinstance.h"
#include "human.h"
#include "stats.h"
#include "mt/MapMode.h"
#include "mt/Hero.h"
#include "mt/MapThing.h"
#include "mt/Param.h"
const int BOX_ID = 150001;
BoxDrop::BoxDrop(Room* room):room_(room)
{
}
void BoxDrop::Init()
{
}
void BoxDrop::UnInit()
{
}
void BoxDrop::OnHeroDeadDrop(Hero* hero)
{
int box_num = GetAndDecObjBoxNum(hero->GetUniId());
if (box_num > 0) {
Drop(box_num, hero->GetPos().ToGlmVec3());
}
}
void BoxDrop::OnObstacleDeadDrop(Obstacle* ob)
{
int box_num = GetAndDecObjBoxNum(ob->GetUniId());
if (box_num > 0) {
Drop(box_num, ob->GetPos().ToGlmVec3());
}
}
void BoxDrop::OnHumanDeadDrop(Human* hum)
{
if (hum->box_num <= 0) {
return;
}
if (room_->IsGameOver()) {
return;
}
if (room_->GetVictoryTeam()) {
return;
}
int rnd = a8::RandEx(0, 100);
if (hum->stats->abandon_battle) {
if (rnd <= mt::Param::s().battle_event_end_loss_rate_quit * 100) {
Drop(hum->box_num, hum->GetPos().ToGlmVec3());
}
} else {
if (rnd <= mt::Param::s().battle_event_end_loss_rate_dead * 100) {
Drop(hum->box_num, hum->GetPos().ToGlmVec3());
}
}
}
void BoxDrop::Drop(int num, const glm::vec3& center)
{
for (int i = 0; i < num; ++i) {
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
glm::vec3 born_pos = center;
GlmHelper::Normalize(dir);
glm::vec3 start = born_pos;
room_->map_instance->Scale(start);
glm::vec3 real_pos = born_pos;
float distance = 25.0f + rand() % 50;
for (int i = 0; i < 4; ++i) {
glm::vec3 end = born_pos + dir * distance;
glm::vec3 hit_point;
bool hit_result = false;
room_->map_instance->Scale(end);
if (room_->map_instance->Raycast(start,
end,
hit_point,
hit_result,
room_->map_instance->GetMoveIncludeFlags(),
room_->map_instance->GetMoveExcludeFlags())) {
room_->map_instance->UnScale(hit_point);
if (GlmHelper::Norm2D(hit_point - born_pos) > 5) {
real_pos = hit_point;
break;
}
}
GlmHelper::RotateY(dir, glm::radians(90.0f));
}
room_->CreateObstacle(BOX_ID, real_pos.x, real_pos.y, real_pos.z);
}
}
void BoxDrop::OnBattleStart()
{
if (room_->GetMapModeMeta() && room_->GetMapModeMeta()->mapMode() == mt::kTreasureBoxMode) {
get_box_num_timer_ = room_->xtimer.SetIntervalWpEx
(SERVER_FRAME_RATE * 20,
[this] (int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT == event) {
if (!room_->IsGameOver() && !room_->GetVictoryTeam()) {
if (!alloced_) {
RequestAllocBoxNum();
}
}
}
},
&room_->xtimer_attacher_);
RequestAllocBoxNum();
}
}
void BoxDrop::RequestAllocBoxNum()
{
std::string account_id;
std::string session_id;
if (!FillAccountIdSessionId(account_id, session_id)) {
return;
}
std::string url;
JsonDataMgr::Instance()->GetApiUrl(url);
auto url_params = a8::MutableXObject::CreateObject();
url_params->SetVal("c", "Battle");
url_params->SetVal("a", "requestAllocBoxNum");
url_params->SetVal("room_uuid", room_->GetRoomUuid());
url_params->SetVal("account_id", account_id);
url_params->SetVal("session_id", session_id);
HttpProxy::Instance()->HttpGet
(
[room_wp = room_->weak_from_this(), room_uuid = room_->GetRoomUuid()]
(bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx)
{
if (ok) {
f8::UdpLog::Instance()->Info
("RequestAllocBoxNum ok room_uuid:%s %s",
{
room_uuid,
rsp_obj->ToJsonStr()
});
if (rsp_obj->GetType() != a8::XOT_OBJECT ||
!rsp_obj->HasKey("errcode")) {
return;
}
if (!room_wp.expired()) {
auto room = room_wp.lock();
if (rsp_obj->Get("errcode").GetInt() == 0) {
int box_num = rsp_obj->Get("box_num").GetInt();
room->GetBoxDrop()->OnAllocOk(box_num);
} else {
room->GetBoxDrop()->OnAllocFail();
}
}
} else {
f8::UdpLog::Instance()->Warning
("RequestAllocBoxNum error room_uuid:%s",
{
room_uuid
});
}
},
url,
url_params
);
}
void BoxDrop::RequestReturnBoxNum()
{
if (alloc_box_num_ <= 0) {
return;
}
if (room_->GetMapModeMeta() && room_->GetMapModeMeta()->mapMode() == mt::kTreasureBoxMode) {
if (returned_) {
return;
}
returned_ = true;
std::string account_id;
std::string session_id;
if (!FillAccountIdSessionId(account_id, session_id)) {
return;
}
std::string url;
JsonDataMgr::Instance()->GetApiUrl(url);
auto url_params = a8::MutableXObject::CreateObject();
url_params->SetVal("c", "Battle");
url_params->SetVal("a", "requestReturnBoxNum");
url_params->SetVal("account_id", account_id);
url_params->SetVal("session_id", session_id);
url_params->SetVal("room_uuid", room_->GetRoomUuid());
url_params->SetVal("used_num", GetUsedBoxNum());
url_params->SetVal("alloc_box_num", alloc_box_num_);
HttpProxy::Instance()->HttpGet
(
[room_uuid = room_->GetRoomUuid()]
(bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx)
{
if (ok) {
f8::UdpLog::Instance()->Info
("RequestReturnBoxNum ok room_uuid:%s %s",
{
room_uuid,
rsp_obj->ToJsonStr()
});
if (rsp_obj->GetType() != a8::XOT_OBJECT ||
!rsp_obj->HasKey("errcode")) {
return;
}
} else {
f8::UdpLog::Instance()->Warning
("RequestReturnBoxNum error room_uuid:%s",
{
room_uuid
});
}
},
url,
url_params
);
}
}
bool BoxDrop::FillAccountIdSessionId(std::string& account_id, std::string& session_id)
{
bool ok = false;
room_->TraversePlayerList
([&ok, &account_id, &session_id] (Player* hum) -> bool
{
ok = true;
account_id = hum->account_id;
session_id = hum->session_id;
return true;
});
return ok;
}
void BoxDrop::OnAllocOk(int box_num)
{
if (!get_box_num_timer_.expired()) {
room_->xtimer.Delete(get_box_num_timer_);
}
if (alloced_) {
return;
}
alloced_ = true;
alloc_box_num_ = box_num;
AllocBoxToRoom();
}
void BoxDrop::OnAllocFail()
{
if (!get_box_num_timer_.expired()) {
room_->xtimer.Delete(get_box_num_timer_);
}
}
void BoxDrop::AllocBoxToRoom()
{
if (alloc_box_num_ <= 0) {
return;
}
std::vector<Entity*> all_list;
std::vector<Creature*> hero_list;
std::vector<Obstacle*> box_list;
room_->TraverseEntityList
(
[this, &all_list, &hero_list, &box_list] (Entity* e) -> bool
{
if (e->IsCreature(room_) && ((Creature*)e)->IsHero()) {
Hero* hero = (Hero*)e;
if (hero->meta->HasDrop()) {
hero_list.push_back(hero);
all_list.push_back(e);
}
} else if (e->IsRoomObstacle()) {
RoomObstacle* ob = (RoomObstacle*)e;
if (ob->meta->HasDrop()) {
box_list.push_back(ob);
all_list.push_back(e);
}
}
return true;
});
std::shuffle(all_list.begin(),
all_list.end(),
std::default_random_engine(a8::XGetTickCount()));
std::shuffle(hero_list.begin(),
hero_list.end(),
std::default_random_engine(a8::XGetTickCount()));
std::shuffle(box_list.begin(),
box_list.end(),
std::default_random_engine(a8::XGetTickCount()));
#ifdef MYDEBUG
f8::UdpLog::Instance()->Info
("AllocBoxToRoom room_uuid:%s all:%d hero:%d box:%d",
{
room_->GetRoomUuid(),
all_list.size(),
hero_list.size(),
box_list.size()
});
#endif
for (int i = 0; i < alloc_box_num_; ++i) {
if (drop_hash_.size() < all_list.size()) {
drop_hash_[all_list.at(i)->GetUniId()] = 1;
}
}
}
int BoxDrop::GetAndDecObjBoxNum(int uniid)
{
auto itr = drop_hash_.find(uniid);
if (itr != drop_hash_.end()) {
int num = itr->second;
itr->second = 0;
return num;
}
return 0;
}
int BoxDrop::GetUsedBoxNum()
{
int num = 0;
room_->TraverseHumanList
(
[&num] (Human* hum) -> bool
{
num += hum->box_num;
return true;
});
return num;
}
bool BoxDrop::GetNextBoxPos(glm::vec3& pos)
{
for (auto& pair : drop_hash_) {
if (pair.second > 0) {
Entity* e = room_->GetEntityByUniId(pair.first);
if (e) {
pos = e->GetPos().ToGlmVec3();
return true;
}
}
}
return false;
}
void BoxDrop::DropByUuid(int obj_uniid, const glm::vec3& center)
{
int box_num = GetAndDecObjBoxNum(obj_uniid);
if (box_num > 0) {
Drop(box_num, center);
}
}