diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index 1bd9157..cff1331 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -235,57 +235,27 @@ void Human::Shot() void Human::DirectShot(MetaData::Equip* bullet_meta, int skill_id) { - #if 0 - for (auto& tuple : bullet_meta->bullet_born_offset) { - a8::Vec2 bullet_born_offset = a8::Vec2(std::get<0>(tuple), std::get<1>(tuple)); - bullet_born_offset.Rotate(attack_dir.CalcAngle(a8::Vec2::UP)); - a8::Vec2 bullet_born_pos = pos + bullet_born_offset; - if (room->OverBorder(bullet_born_pos, 0)) { - return; - } - } - room->frame_event.AddShot(this); - for (auto& tuple : bullet_meta->bullet_born_offset) { - a8::Vec2 bullet_born_offset = a8::Vec2(std::get<0>(tuple), std::get<1>(tuple)); - bullet_born_offset.Rotate(attack_dir.CalcAngle(a8::Vec2::UP)); - a8::Vec2 bullet_born_pos = pos + bullet_born_offset; - a8::Vec2 bullet_dir = attack_dir; - float bullet_angle = std::get<2>(tuple); - if (bullet_meta->i->bullet_angle() >= 0.10f) { - int angle = (int)bullet_meta->i->bullet_angle() * 1000; - if (angle > 0) { - bullet_angle += (rand() % angle) / 1000.0f * (rand() % 2 == 0 ? 1 : -1); - } - } - bullet_dir.Rotate(bullet_angle / 180.0f); - int hit_time = 0; - if (bullet_meta->NeedTrace()) { - hit_time = bullet_meta->i->time() * 1000; - } - if (bullet_meta->NeedTrace()) { - if (skill_id != 0) { - room->frame_event.AddBullet(this, bullet_meta->i->id(), - curr_weapon->weapon_lv, bullet_born_pos, bullet_dir, - fly_distance, hit_time, skill_target_id, skill_id); - } else { - room->frame_event.AddBullet(this, bullet_meta->i->id(), - curr_weapon->weapon_lv, bullet_born_pos, bullet_dir, - fly_distance, hit_time, shot_target_id); - } - } else { - room->frame_event.AddBullet(this, bullet_meta->i->id(), - curr_weapon->weapon_lv, - bullet_born_pos, bullet_dir, - fly_distance, hit_time, 0, skill_id); - } - if (room->BattleStarted()) { - if (bullet_meta->i->equip_subtype() != BulletType_Missile) { - room->CreateBullet(this, bullet_meta, bullet_born_pos, bullet_dir, fly_distance); - } - } + for (size_t i = 0; i < bullet_meta->bullet_born_offset.size(); ++i) { + auto& tuple = bullet_meta->bullet_born_offset[i]; + room->xtimer.AddDeadLineTimerAndAttach(std::get<0>(tuple) * FRAME_RATE_MS, + a8::XParams() + .SetSender(this) + .SetParam1(bullet_meta) + .SetParam2(skill_id) + .SetParam3(i), + [] (const a8::XParams& param) + { + Human* sender = (Human*)param.sender.GetUserData(); + MetaData::Equip* bullet_meta = (MetaData::Equip*)param.param1.GetUserData(); + if (sender) { + sender->InternalShot(bullet_meta, + param.param2, + param.param3); + } + }, + &xtimer_attacher.timer_list_); } OnAttack(); - #endif } void Human::RecalcSelfCollider() @@ -2115,3 +2085,60 @@ void Human::ProcSkillPhase(MetaData::SkillPhase* phase) break; } } + +void Human::InternalShot(MetaData::Equip* bullet_meta, int skill_id, size_t offset_idx) +{ + if (offset_idx >= bullet_meta->bullet_born_offset.size()) { + return; + } + const auto& born_points = std::get<1>(bullet_meta->bullet_born_offset[offset_idx]); + for (auto& born_point : born_points) { + a8::Vec2 bullet_born_offset = born_point.born_offset; + bullet_born_offset.Rotate(attack_dir.CalcAngle(a8::Vec2::UP)); + a8::Vec2 bullet_born_pos = pos + bullet_born_offset; + if (room->OverBorder(bullet_born_pos, 0)) { + return; + } + } + room->frame_event.AddShot(this); + for (auto& born_point : born_points) { + a8::Vec2 bullet_born_offset = born_point.born_offset; + bullet_born_offset.Rotate(attack_dir.CalcAngle(a8::Vec2::UP)); + a8::Vec2 bullet_born_pos = pos + bullet_born_offset; + a8::Vec2 bullet_dir = attack_dir; + float bullet_angle = born_point.angle; + if (bullet_meta->i->bullet_angle() >= 0.10f) { + int angle = (int)bullet_meta->i->bullet_angle() * 1000; + if (angle > 0) { + bullet_angle += (rand() % angle) / 1000.0f * (rand() % 2 == 0 ? 1 : -1); + } + } + bullet_dir.Rotate(bullet_angle / 180.0f); + int hit_time = 0; + if (bullet_meta->NeedTrace()) { + hit_time = bullet_meta->i->time() * 1000; + } + if (bullet_meta->NeedTrace()) { + if (skill_id != 0) { + room->frame_event.AddBullet(this, bullet_meta->i->id(), + curr_weapon->weapon_lv, bullet_born_pos, bullet_dir, + fly_distance, hit_time, skill_target_id, skill_id); + } else { + room->frame_event.AddBullet(this, bullet_meta->i->id(), + curr_weapon->weapon_lv, bullet_born_pos, bullet_dir, + fly_distance, hit_time, shot_target_id); + } + } else { + room->frame_event.AddBullet(this, bullet_meta->i->id(), + curr_weapon->weapon_lv, + bullet_born_pos, bullet_dir, + fly_distance, hit_time, 0, skill_id); + } + if (room->BattleStarted()) { + if (bullet_meta->i->equip_subtype() != BulletType_Missile) { + room->CreateBullet(this, bullet_meta, bullet_born_pos, bullet_dir, fly_distance); + } + } + } + OnAttack(); +} diff --git a/server/gameserver/human.h b/server/gameserver/human.h index f0d5b4e..8ebf000 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -224,6 +224,7 @@ private: void SelectSkillTargets(const a8::Vec2& target_pos, std::set& target_list); Buff* GetBuffById(int buff_id); void ProcSkillPhase(MetaData::SkillPhase* phase); + void InternalShot(MetaData::Equip* bullet_meta, int skill_id, size_t offset_idx); protected: long long last_shot_frameno_ = 0;