diff --git a/server/gameserver/pbutils.cc b/server/gameserver/pbutils.cc index 0c12c08a..89ae5670 100644 --- a/server/gameserver/pbutils.cc +++ b/server/gameserver/pbutils.cc @@ -1,6 +1,7 @@ #include "precompile.h" #include +#include #include @@ -37,6 +38,8 @@ #include "GGListener.h" #include "playermgr.h" #include "matchmgr.h" +#include "frag_mitask.h" +#include "smoke_mitask.h" #include "mt/Param.h" #include "mt/Buff.h" @@ -1051,8 +1054,122 @@ void Human::ProcThrowDmg(int throw_uniid) return; } auto context = itr->second; + + glm::vec3 bomb_pos; + glm::vec3 bomb_dir; + TypeConvert::FromPb(bomb_pos, &context->pos()); + TypeConvert::FromPb(bomb_dir, &context->dir()); + if (!(std::abs(bomb_dir.x) > FLT_EPSILON || + std::abs(bomb_dir.y) > FLT_EPSILON || + std::abs(bomb_dir.z) > FLT_EPSILON + )) { + pending_throw_bomb.erase(throw_uniid); + return; + } + + GlmHelper::Normalize(bomb_dir); + glm::vec3 target_pos = bomb_pos + bomb_dir * context->fly_distance(); const mt::Equip* equip_meta = mt::Equip::GetById(context->weapon_id()); if (equip_meta && equip_meta->_inventory_slot() > 0) { + + auto proc_frag_func = + [this, equip_meta, context, bomb_pos, bomb_dir, target_pos] () + { + std::shared_ptr task = std::shared_ptr(); + task->room = room; + task->sender.Attach(this); + task->bomb_pos.FromGlmVec3(target_pos); + task->gun_meta = equip_meta; + task->meta = equip_meta; + task->atk = equip_meta->atk(); + task->explosion_range = equip_meta->explosion_range(); + int delay_time = equip_meta->missiles_time();; + room->xtimer.SetTimeoutEx + (std::max(1, (int)(delay_time / FRAME_RATE_MS)), + [task] (int event, const a8::Args* args) + { + if (a8::TIMER_EXEC_EVENT == event) { + task->Done(); + } + }, + &task->xtimer_attacher); + }; + auto proc_smoke_func = + [this, equip_meta, context, bomb_pos, bomb_dir, target_pos] () + { + const mt::Buff* buff_meta = mt::Buff::GetById(HUNLUAN_BUFFID); + if (!buff_meta) { + return; + } + std::shared_ptr task = std::make_shared(); + task->room = room; + task->bomb_pos.FromGlmVec3(target_pos); + task->buff_meta = buff_meta; + task->gun_meta = equip_meta; + auto task_wp = std::weak_ptr(task); + room->xtimer.SetIntervalEx + (SERVER_FRAME_RATE / 2, + [task_wp] (int event, const a8::Args* args) + { + if (a8::TIMER_EXEC_EVENT == event) { + if (!task_wp.expired()) { + task_wp.lock()->Check(); + } + } + }, + &task->xtimer_attacher); + + room->xtimer.SetTimeoutEx + (SERVER_FRAME_RATE * mt::Param::GetIntParam("smoke_duration", 10), + [task] (int event, const a8::Args* args) + { + if (a8::TIMER_DELETE_EVENT == event) { + task->Done(); + } + }, + &room->xtimer_attacher_); + }; + auto proc_molotor_cocktail_func = + [this, equip_meta, context, bomb_pos, bomb_dir, target_pos] () + { + std::shared_ptr old_context_ability = context_ability; + glm::vec3 old_context_dir = context_dir; + Position old_context_pos = context_pos; + context_dir = bomb_dir; + context_pos.FromGlmVec3(target_pos); + context_ability = nullptr; + const mt::Buff * buff_meta = mt::Buff::GetById(equip_meta->buffid()); + if (buff_meta) { + AddBuff(this, + buff_meta + ); + } + context_dir = old_context_dir; + context_pos = old_context_pos; + context_ability = old_context_ability; + }; + switch (equip_meta->_inventory_slot()) { + case IS_FRAG: + { + proc_frag_func(); + } + break; + case IS_SMOKE: + { + proc_smoke_func(); + } + break; + case IS_MOLOTOR_COCKTAIL: + { + proc_molotor_cocktail_func(); + } + break; + default: + { + + } + break; + }//end switch } pending_throw_bomb.erase(throw_uniid); }