diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index c770fb59..774cda7b 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -14,426 +14,7 @@ #include "car.h" #include "bullet.h" #include "skillhelper.h" - -#include -#include -#include - -static const auto hero_transform = - glm::rotate( - glm::mat4(1.0), - glm::radians(65.0f), - glm::vec3(0.0, 0.0, 1.0) - ); - -struct BulletInfo -{ - CreatureWeakPtr c; - long long weapon_uniid = 0; - MetaData::Equip* weapon_meta = nullptr; - MetaData::Equip* bullet_meta = nullptr; - MetaData::Skill* skill_meta = nullptr; - a8::Vec2 bullet_born_pos; - a8::Vec2 bullet_dir; - float fly_distance = 0; - int weapon_lv = 0; - int delay_time = 0; - int recoil_force = 0; - int invincible_buff_uniid = 0; - int trace_target_uniid = 0; - float track_change_time = 0; - int is_through = 0; - int hand = 0; - float shot_animi_time = 0; - std::weak_ptr keep_shot_animi_timer_ptr; -}; - -static void InternalCreateBullet(BulletInfo& bullet_info) -{ - if (!bullet_info.c.Get()) { - return; - } - Creature* c = bullet_info.c.Get(); - if (c->dead) { - return; - } - if (c->downed) { - return; - } - if (bullet_info.delay_time <= 0) { - if (c->GetCurrWeapon()->meta->i->bullet_consume_type() == kBulletConsumeMulti) { - if (c->GetCurrWeapon()->ammo <= 0) { - return; - } - --c->GetCurrWeapon()->ammo; - if (c->GetCurrWeapon()->ammo <= 0) { - c->AutoLoadingBullet(); - } - if ((c->IsPlayer() || c->IsCar())) { - c->room->frame_event.AddBulletNumChg(c->GetWeakPtrRef()); - c->room->frame_event.AddWeaponAmmoChg(c->GetWeakPtrRef()); - } - } - if (bullet_info.recoil_force > 0) { - if (c->GetCurrWeapon()->ammo <= 0) { - c->DoRecoilForce(bullet_info.recoil_force); - bullet_info.bullet_born_pos = bullet_info.bullet_born_pos - - (bullet_info.bullet_dir * bullet_info.recoil_force); - } - } - int bullet_uniid = 0; - if (MetaMgr::Instance()->prebattle_can_use_skill || - !(c->HasBuffEffect(kBET_Jump) || c->HasBuffEffect(kBET_Fly))) { - bullet_uniid = c->room->CreateBullet - (c, - c->shot_passenger, - bullet_info.weapon_meta, - bullet_info.bullet_meta, - bullet_info.skill_meta, - bullet_info.bullet_born_pos, - bullet_info.bullet_dir, - bullet_info.fly_distance, - bullet_info.weapon_uniid, - bullet_info.trace_target_uniid, - bullet_info.hand, - bullet_info.keep_shot_animi_timer_ptr, - bullet_info.shot_animi_time); -#ifdef DEBUG1 - if (bullet_info.c.Get()->IsPlayer()) { - bullet_info.c.Get()->SendDebugMsg(a8::Format("CreateBullet id:%d", - {bullet_info.weapon_meta->i->id()})); - } -#endif - } - bullet_uniid = bullet_uniid ? bullet_uniid : c->room->AllocUniid(); - c->room->frame_event.AddBullet - (bullet_uniid, - c->GetWeakPtrRef(), - bullet_info.weapon_meta, - bullet_info.weapon_lv, - bullet_info.bullet_born_pos, - bullet_info.bullet_dir, - bullet_info.fly_distance, - bullet_info.trace_target_uniid, - bullet_info.hand); - if (bullet_uniid && bullet_info.trace_target_uniid) { - c->AddTraceBullet( - bullet_uniid, - bullet_info.trace_target_uniid, - bullet_info.weapon_meta->i->id() - ); - } - } else { - BulletInfo* info_copy = new BulletInfo(); - *info_copy = bullet_info; - xtimer_list* timer = bullet_info.c.Get()->room->xtimer.AddDeadLineTimerAndAttach - ( - bullet_info.delay_time / FRAME_RATE_MS, - a8::XParams() - .SetSender(info_copy), - [] (const a8::XParams& param) - { - BulletInfo* info_copy = (BulletInfo*)param.sender.GetUserData(); - info_copy->delay_time = 0; - InternalCreateBullet(*info_copy); - }, - &bullet_info.c.Get()->xtimer_attacher.timer_list_, - [] (const a8::XParams& param) - { - BulletInfo* info_copy = (BulletInfo*)param.sender.GetUserData(); - delete info_copy; - } - ); - if (!c->room->BattleStarted()) { - c->room->AddToPostBattleAutoFreeList(timer); - } - } -} - -static void CalcGunMuzzlePosition(Creature* c, - MetaData::Equip* weapon_meta, - MetaData::HeroShotAnimation* shot_animi, - glm::vec4& gun_muzzle_position, - int bulletIdx, - int bulletNum) -{ - if (shot_animi) { - if (weapon_meta->i->double_gun()&& - bulletIdx > (int)(bulletNum / 2)) { - gun_muzzle_position += - glm::vec4( - shot_animi->l_x, - shot_animi->l_y, - shot_animi->l_z, - 0 - ); - } else { - if (c->IsCar() && !weapon_meta->i->double_gun()) { - switch (c->shot_hole) { - case 1: - { - gun_muzzle_position += - glm::vec4( - shot_animi->p3_x, - shot_animi->p3_y, - shot_animi->p3_z, - 0 - ); - } - break; - case 2: - { - gun_muzzle_position += - glm::vec4( - shot_animi->p4_x, - shot_animi->p4_y, - shot_animi->p4_z, - 0 - ); - } - break; - case 3: - { - gun_muzzle_position += - glm::vec4( - shot_animi->p5_x, - shot_animi->p5_y, - shot_animi->p5_z, - 0 - ); - } - break; - default: - { - } - break; - } - } else { - gun_muzzle_position += - glm::vec4( - shot_animi->r_x, - shot_animi->r_y, - shot_animi->r_z, - 0 - ); - } - } - }//end if - if (weapon_meta->gun_muzzle_position) { - gun_muzzle_position += -#if 1 - glm::vec4( - -std::get<0>(*weapon_meta->gun_muzzle_position.get()), - std::get<1>(*weapon_meta->gun_muzzle_position.get()), - std::get<2>(*weapon_meta->gun_muzzle_position.get()), - 0 - ); -#else - glm::vec4( - std::get<0>(*weapon_meta->gun_muzzle_position.get()), - std::get<1>(*weapon_meta->gun_muzzle_position.get()), - std::get<2>(*weapon_meta->gun_muzzle_position.get()), - 0 - ); - #endif - } - #if 0 - if (weapon_meta->movex_position) { - gun_muzzle_position -= - glm::vec4( - std::get<0>(*weapon_meta->movex_position.get()), - std::get<1>(*weapon_meta->movex_position.get()), - std::get<2>(*weapon_meta->movex_position.get()), - 0 - ); - } - #endif -} - -void InternalShot(Creature* c, - MetaData::Equip* weapon_meta, - MetaData::Equip* bullet_meta, - MetaData::Skill* skill_meta, - float fly_distance, - long long weapon_uniid, - int trace_target_uniid) -{ - if (weapon_meta->i->_inventory_slot() == IS_TRAP || - weapon_meta->i->_inventory_slot() == IS_MINE) { - if (!skill_meta) { - c->room->frame_event.AddShot(c->GetWeakPtrRef()); - } - if (weapon_meta->i->cast_time() > 0) { - int buff_uniid = c->TryAddBuff(c, kVertigoBuffId); - Buff* buff = c->GetBuffByUniId(buff_uniid); - if (buff && buff->remover_timer) { - c->room->xtimer.ModifyTimer(buff->remover_timer, weapon_meta->i->cast_time() / FRAME_RATE_MS); - } - } - a8::Vec2 old_context_dir = c->context_dir; - a8::Vec2 old_context_pos = c->context_pos; - c->context_dir =c->GetAttackDir(); - c->context_pos = c->GetPos() + c->GetAttackDir() * fly_distance; - MetaData::Buff * buff_meta = MetaMgr::Instance()->GetBuff(bullet_meta->i->buffid()); - if (buff_meta) { - c->AddBuff(c, - buff_meta - ); - } - c->context_dir = old_context_dir; - c->context_pos = old_context_pos; - return; - } - for (auto& tuple : weapon_meta->bullet_born_offset) { - a8::Vec2 bullet_born_offset = a8::Vec2(std::get<0>(tuple), std::get<1>(tuple)); - float bullet_born_angle = c->GetAttackDir().CalcAngleEx(a8::Vec2::UP); - if (c->GetAttackDir().x > 0.00001f) { - bullet_born_angle = -bullet_born_angle; - } - bullet_born_offset.Rotate(bullet_born_angle); - a8::Vec2 bullet_born_pos = c->GetPos() + bullet_born_offset; - if (c->room->OverBorder(bullet_born_pos, 0.0f)) { - return; - } - } - if (!skill_meta || weapon_meta->i->equip_type() == EQUIP_TYPE_THROW) { - c->room->frame_event.AddShot(c->GetWeakPtrRef()); - } - int invincible_buff_uniid = 0; - if (weapon_meta->lock_time > 0) { - int buff_uniid = c->TryAddBuff(c, kVertigoBuffId); - Buff* buff = c->GetBuffByUniId(buff_uniid); - if (buff && buff->remover_timer) { - c->room->xtimer.ModifyTimer(buff->remover_timer, weapon_meta->lock_time / FRAME_RATE_MS); - } - } - if (weapon_meta->i->cast_time() > 0) { - int buff_uniid = c->TryAddBuff(c, kVertigoBuffId); - Buff* buff = c->GetBuffByUniId(buff_uniid); - if (buff && buff->remover_timer) { - c->room->xtimer.ModifyTimer(buff->remover_timer, weapon_meta->i->cast_time() / FRAME_RATE_MS); - } - } - MetaData::HeroShotAnimation* shot_animi = c->GetHeroMeta() ? - c->GetHeroMeta()->GetShotAnimi(weapon_meta->i->shootfire()) : nullptr; - std::weak_ptr keep_shot_animi_timer_ptr; - { - int shot_animi_time = (shot_animi ? shot_animi->t : 0); - if (weapon_meta && weapon_meta->i->equip_subtype() == GUN_SUB_EQUIP_TYPE_FLY_HOOk) { - keep_shot_animi_timer_ptr = c->TryDelayAddBuff(c, kKeepShotAnimiBuffId, shot_animi_time); - } - } - int bulletIdx = 0; - int bulletNum = weapon_meta->bullet_born_offset.size(); - for (auto& tuple : weapon_meta->bullet_born_offset) { - ++bulletIdx; - a8::Vec2 bullet_born_offset = a8::Vec2(std::get<0>(tuple), std::get<1>(tuple)); - a8::Vec2 bullet_born_pos = c->GetPos() + c->shoot_offset + bullet_born_offset; - a8::Vec2 bullet_dir = c->GetShotDir(); - float bullet_angle = std::get<2>(tuple); - if (weapon_meta->i->bullet_angle() >= 0.10f) { - int angle = (int)weapon_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 shot_animi_time = (shot_animi ? shot_animi->t : 0); - if (shot_animi_time > 0) { - shot_animi_time = std::max(100, shot_animi_time); - } - { - bool is_player = c->IsPlayer(); - bool is_car = c->IsCar(); - float bullet_born_angle = c->GetAttackDir().CalcAngleEx(a8::Vec2::RIGHT); - if (c->GetAttackDir().y > 0.00001f) { - bullet_born_angle = -bullet_born_angle; - } - float old_bullet_born_angle = bullet_born_angle; - bullet_born_offset.Rotate(bullet_born_angle); - - auto transform = glm::rotate(hero_transform, - bullet_born_angle * A8_PI, - glm::vec3(0.0, 1.0, 0.0)); - glm::vec4 gun_muzzle_position(0.0, 0.0, 0.0, 0.0); - CalcGunMuzzlePosition(c, weapon_meta, shot_animi, gun_muzzle_position, bulletIdx, bulletNum); - glm::vec4 v = transform * gun_muzzle_position; - bullet_born_offset = a8::Vec2(v.z *10*1, v.x*10*-1); - bullet_born_pos = c->GetPos() + bullet_born_offset; - if (c->IsPlayer() || c->IsCar()) { -#ifdef DEBUG - a8::XPrintf("idx:%d offset:%f,%f angle:%f old_angle:%f angle_xy:%f,%f %f %f gun_muzzle_position:%f,%f,%f pos:%f,%f gun_id:%d t:%d\n", - { - bulletIdx, - bullet_born_offset.x, - bullet_born_offset.y, - bullet_born_angle, - old_bullet_born_angle, - c->GetAttackDir().x, - c->GetAttackDir().y, - (bullet_born_angle * 180), - (bullet_born_angle - glm::radians(90.0f) / A8_PI) * 180, - gun_muzzle_position.x, - gun_muzzle_position.y, - gun_muzzle_position.z, - bullet_born_pos.x, - bullet_born_pos.y, - weapon_meta->i->id(), - shot_animi_time - }); -#endif - } - } - { - BulletInfo bullet_info; - bullet_info.c = c->GetWeakPtrRef(); - bullet_info.weapon_uniid = weapon_uniid; - bullet_info.weapon_meta = weapon_meta; - bullet_info.skill_meta = skill_meta; - bullet_info.bullet_meta = bullet_meta; - bullet_info.bullet_born_pos = bullet_born_pos; - bullet_info.bullet_dir = bullet_dir; - bullet_info.fly_distance = fly_distance; - bullet_info.delay_time = std::get<3>(tuple); - bullet_info.recoil_force = std::get<4>(tuple); - bullet_info.invincible_buff_uniid = invincible_buff_uniid; - bullet_info.trace_target_uniid = trace_target_uniid; - bullet_info.keep_shot_animi_timer_ptr = keep_shot_animi_timer_ptr; - bullet_info.shot_animi_time = shot_animi_time; - if (skill_meta && - (skill_meta->GetMagicId() == MAGIC_AXXF || - skill_meta->GetMagicId() == MAGIC_HJHX)) { - bullet_info.trace_target_uniid = c->GetSkillTargetId(); - } - if (weapon_meta->i->double_gun() && - bulletIdx > (int)(bulletNum / 2)) { - bullet_info.hand = 1; - } -#ifdef DEBUG - if (bullet_info.trace_target_uniid) { - a8::XPrintf("bullet trace_target_uniid:%d\n", {bullet_info.trace_target_uniid}); - } -#endif - InternalCreateBullet(bullet_info); - } - } - c->GetTrigger()->Shot(weapon_meta); - if (weapon_meta->i->recoil_force() > 0.000001) { - c->DoRecoilForce(weapon_meta->i->recoil_force()); - } - if (c->HasBuffEffect(kBET_Hide)) { - c->RemoveBuffByEffectId(kBET_Hide); - } - if (trace_target_uniid) { - c->LockAttackDir(1000); - } - if (c->aiming) { - c->aiming = false; - c->aiming_frameno = 0; - c->power_idx = -1; - c->ClearAimingBuffs(); - } -} +#include "shot.h" Creature::Creature():MoveableEntity() { diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index ed86f60a..4bb55e9a 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -372,11 +372,3 @@ private: friend class Skill; friend class Trigger; }; - -void InternalShot(Creature* sender, - MetaData::Equip* weapon_meta, - MetaData::Equip* bullet_meta, - MetaData::Skill* skill_meta, - float fly_distance, - long long weapon_uniid, - int trace_target_uniid); diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index 97107f79..382dbf60 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -37,6 +37,7 @@ #include "tracemgr.h" #include "httpproxy.h" #include "skillhelper.h" +#include "shot.h" const int kReviveTimeAdd = 12; const int kSkinNum = 4; diff --git a/server/gameserver/shot.cc b/server/gameserver/shot.cc new file mode 100644 index 00000000..32e1dd0a --- /dev/null +++ b/server/gameserver/shot.cc @@ -0,0 +1,426 @@ +#include "precompile.h" + +#include +#include +#include + +#include "shot.h" +#include "metamgr.h" +#include "creature.h" +#include "room.h" + +static const auto hero_transform = + glm::rotate( + glm::mat4(1.0), + glm::radians(65.0f), + glm::vec3(0.0, 0.0, 1.0) + ); + +struct BulletInfo +{ + CreatureWeakPtr c; + long long weapon_uniid = 0; + MetaData::Equip* weapon_meta = nullptr; + MetaData::Equip* bullet_meta = nullptr; + MetaData::Skill* skill_meta = nullptr; + a8::Vec2 bullet_born_pos; + a8::Vec2 bullet_dir; + float fly_distance = 0; + int weapon_lv = 0; + int delay_time = 0; + int recoil_force = 0; + int invincible_buff_uniid = 0; + int trace_target_uniid = 0; + float track_change_time = 0; + int is_through = 0; + int hand = 0; + float shot_animi_time = 0; + std::weak_ptr keep_shot_animi_timer_ptr; +}; + +static void InternalCreateBullet(BulletInfo& bullet_info) +{ + if (!bullet_info.c.Get()) { + return; + } + Creature* c = bullet_info.c.Get(); + if (c->dead) { + return; + } + if (c->downed) { + return; + } + if (bullet_info.delay_time <= 0) { + if (c->GetCurrWeapon()->meta->i->bullet_consume_type() == kBulletConsumeMulti) { + if (c->GetCurrWeapon()->ammo <= 0) { + return; + } + --c->GetCurrWeapon()->ammo; + if (c->GetCurrWeapon()->ammo <= 0) { + c->AutoLoadingBullet(); + } + if ((c->IsPlayer() || c->IsCar())) { + c->room->frame_event.AddBulletNumChg(c->GetWeakPtrRef()); + c->room->frame_event.AddWeaponAmmoChg(c->GetWeakPtrRef()); + } + } + if (bullet_info.recoil_force > 0) { + if (c->GetCurrWeapon()->ammo <= 0) { + c->DoRecoilForce(bullet_info.recoil_force); + bullet_info.bullet_born_pos = bullet_info.bullet_born_pos - + (bullet_info.bullet_dir * bullet_info.recoil_force); + } + } + int bullet_uniid = 0; + if (MetaMgr::Instance()->prebattle_can_use_skill || + !(c->HasBuffEffect(kBET_Jump) || c->HasBuffEffect(kBET_Fly))) { + bullet_uniid = c->room->CreateBullet + (c, + c->shot_passenger, + bullet_info.weapon_meta, + bullet_info.bullet_meta, + bullet_info.skill_meta, + bullet_info.bullet_born_pos, + bullet_info.bullet_dir, + bullet_info.fly_distance, + bullet_info.weapon_uniid, + bullet_info.trace_target_uniid, + bullet_info.hand, + bullet_info.keep_shot_animi_timer_ptr, + bullet_info.shot_animi_time); +#ifdef DEBUG1 + if (bullet_info.c.Get()->IsPlayer()) { + bullet_info.c.Get()->SendDebugMsg(a8::Format("CreateBullet id:%d", + {bullet_info.weapon_meta->i->id()})); + } +#endif + } + bullet_uniid = bullet_uniid ? bullet_uniid : c->room->AllocUniid(); + c->room->frame_event.AddBullet + (bullet_uniid, + c->GetWeakPtrRef(), + bullet_info.weapon_meta, + bullet_info.weapon_lv, + bullet_info.bullet_born_pos, + bullet_info.bullet_dir, + bullet_info.fly_distance, + bullet_info.trace_target_uniid, + bullet_info.hand); + if (bullet_uniid && bullet_info.trace_target_uniid) { + c->AddTraceBullet( + bullet_uniid, + bullet_info.trace_target_uniid, + bullet_info.weapon_meta->i->id() + ); + } + } else { + BulletInfo* info_copy = new BulletInfo(); + *info_copy = bullet_info; + xtimer_list* timer = bullet_info.c.Get()->room->xtimer.AddDeadLineTimerAndAttach + ( + bullet_info.delay_time / FRAME_RATE_MS, + a8::XParams() + .SetSender(info_copy), + [] (const a8::XParams& param) + { + BulletInfo* info_copy = (BulletInfo*)param.sender.GetUserData(); + info_copy->delay_time = 0; + InternalCreateBullet(*info_copy); + }, + &bullet_info.c.Get()->xtimer_attacher.timer_list_, + [] (const a8::XParams& param) + { + BulletInfo* info_copy = (BulletInfo*)param.sender.GetUserData(); + delete info_copy; + } + ); + if (!c->room->BattleStarted()) { + c->room->AddToPostBattleAutoFreeList(timer); + } + } +} + +static void CalcGunMuzzlePosition(Creature* c, + MetaData::Equip* weapon_meta, + MetaData::HeroShotAnimation* shot_animi, + glm::vec4& gun_muzzle_position, + int bulletIdx, + int bulletNum) +{ + if (shot_animi) { + if (weapon_meta->i->double_gun()&& + bulletIdx > (int)(bulletNum / 2)) { + gun_muzzle_position += + glm::vec4( + shot_animi->l_x, + shot_animi->l_y, + shot_animi->l_z, + 0 + ); + } else { + if (c->IsCar() && !weapon_meta->i->double_gun()) { + switch (c->shot_hole) { + case 1: + { + gun_muzzle_position += + glm::vec4( + shot_animi->p3_x, + shot_animi->p3_y, + shot_animi->p3_z, + 0 + ); + } + break; + case 2: + { + gun_muzzle_position += + glm::vec4( + shot_animi->p4_x, + shot_animi->p4_y, + shot_animi->p4_z, + 0 + ); + } + break; + case 3: + { + gun_muzzle_position += + glm::vec4( + shot_animi->p5_x, + shot_animi->p5_y, + shot_animi->p5_z, + 0 + ); + } + break; + default: + { + } + break; + } + } else { + gun_muzzle_position += + glm::vec4( + shot_animi->r_x, + shot_animi->r_y, + shot_animi->r_z, + 0 + ); + } + } + }//end if + if (weapon_meta->gun_muzzle_position) { + gun_muzzle_position += +#if 1 + glm::vec4( + -std::get<0>(*weapon_meta->gun_muzzle_position.get()), + std::get<1>(*weapon_meta->gun_muzzle_position.get()), + std::get<2>(*weapon_meta->gun_muzzle_position.get()), + 0 + ); +#else + glm::vec4( + std::get<0>(*weapon_meta->gun_muzzle_position.get()), + std::get<1>(*weapon_meta->gun_muzzle_position.get()), + std::get<2>(*weapon_meta->gun_muzzle_position.get()), + 0 + ); + #endif + } + #if 0 + if (weapon_meta->movex_position) { + gun_muzzle_position -= + glm::vec4( + std::get<0>(*weapon_meta->movex_position.get()), + std::get<1>(*weapon_meta->movex_position.get()), + std::get<2>(*weapon_meta->movex_position.get()), + 0 + ); + } + #endif +} + +void InternalShot(Creature* c, + MetaData::Equip* weapon_meta, + MetaData::Equip* bullet_meta, + MetaData::Skill* skill_meta, + float fly_distance, + long long weapon_uniid, + int trace_target_uniid) +{ + if (weapon_meta->i->_inventory_slot() == IS_TRAP || + weapon_meta->i->_inventory_slot() == IS_MINE) { + if (!skill_meta) { + c->room->frame_event.AddShot(c->GetWeakPtrRef()); + } + if (weapon_meta->i->cast_time() > 0) { + int buff_uniid = c->TryAddBuff(c, kVertigoBuffId); + Buff* buff = c->GetBuffByUniId(buff_uniid); + if (buff && buff->remover_timer) { + c->room->xtimer.ModifyTimer(buff->remover_timer, weapon_meta->i->cast_time() / FRAME_RATE_MS); + } + } + a8::Vec2 old_context_dir = c->context_dir; + a8::Vec2 old_context_pos = c->context_pos; + c->context_dir =c->GetAttackDir(); + c->context_pos = c->GetPos() + c->GetAttackDir() * fly_distance; + MetaData::Buff * buff_meta = MetaMgr::Instance()->GetBuff(bullet_meta->i->buffid()); + if (buff_meta) { + c->AddBuff(c, + buff_meta + ); + } + c->context_dir = old_context_dir; + c->context_pos = old_context_pos; + return; + } + for (auto& tuple : weapon_meta->bullet_born_offset) { + a8::Vec2 bullet_born_offset = a8::Vec2(std::get<0>(tuple), std::get<1>(tuple)); + float bullet_born_angle = c->GetAttackDir().CalcAngleEx(a8::Vec2::UP); + if (c->GetAttackDir().x > 0.00001f) { + bullet_born_angle = -bullet_born_angle; + } + bullet_born_offset.Rotate(bullet_born_angle); + a8::Vec2 bullet_born_pos = c->GetPos() + bullet_born_offset; + if (c->room->OverBorder(bullet_born_pos, 0.0f)) { + return; + } + } + if (!skill_meta || weapon_meta->i->equip_type() == EQUIP_TYPE_THROW) { + c->room->frame_event.AddShot(c->GetWeakPtrRef()); + } + int invincible_buff_uniid = 0; + if (weapon_meta->lock_time > 0) { + int buff_uniid = c->TryAddBuff(c, kVertigoBuffId); + Buff* buff = c->GetBuffByUniId(buff_uniid); + if (buff && buff->remover_timer) { + c->room->xtimer.ModifyTimer(buff->remover_timer, weapon_meta->lock_time / FRAME_RATE_MS); + } + } + if (weapon_meta->i->cast_time() > 0) { + int buff_uniid = c->TryAddBuff(c, kVertigoBuffId); + Buff* buff = c->GetBuffByUniId(buff_uniid); + if (buff && buff->remover_timer) { + c->room->xtimer.ModifyTimer(buff->remover_timer, weapon_meta->i->cast_time() / FRAME_RATE_MS); + } + } + MetaData::HeroShotAnimation* shot_animi = c->GetHeroMeta() ? + c->GetHeroMeta()->GetShotAnimi(weapon_meta->i->shootfire()) : nullptr; + std::weak_ptr keep_shot_animi_timer_ptr; + { + int shot_animi_time = (shot_animi ? shot_animi->t : 0); + if (weapon_meta && weapon_meta->i->equip_subtype() == GUN_SUB_EQUIP_TYPE_FLY_HOOk) { + keep_shot_animi_timer_ptr = c->TryDelayAddBuff(c, kKeepShotAnimiBuffId, shot_animi_time); + } + } + int bulletIdx = 0; + int bulletNum = weapon_meta->bullet_born_offset.size(); + for (auto& tuple : weapon_meta->bullet_born_offset) { + ++bulletIdx; + a8::Vec2 bullet_born_offset = a8::Vec2(std::get<0>(tuple), std::get<1>(tuple)); + a8::Vec2 bullet_born_pos = c->GetPos() + c->shoot_offset + bullet_born_offset; + a8::Vec2 bullet_dir = c->GetShotDir(); + float bullet_angle = std::get<2>(tuple); + if (weapon_meta->i->bullet_angle() >= 0.10f) { + int angle = (int)weapon_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 shot_animi_time = (shot_animi ? shot_animi->t : 0); + if (shot_animi_time > 0) { + shot_animi_time = std::max(100, shot_animi_time); + } + { + bool is_player = c->IsPlayer(); + bool is_car = c->IsCar(); + float bullet_born_angle = c->GetAttackDir().CalcAngleEx(a8::Vec2::RIGHT); + if (c->GetAttackDir().y > 0.00001f) { + bullet_born_angle = -bullet_born_angle; + } + float old_bullet_born_angle = bullet_born_angle; + bullet_born_offset.Rotate(bullet_born_angle); + + auto transform = glm::rotate(hero_transform, + bullet_born_angle * A8_PI, + glm::vec3(0.0, 1.0, 0.0)); + glm::vec4 gun_muzzle_position(0.0, 0.0, 0.0, 0.0); + CalcGunMuzzlePosition(c, weapon_meta, shot_animi, gun_muzzle_position, bulletIdx, bulletNum); + glm::vec4 v = transform * gun_muzzle_position; + bullet_born_offset = a8::Vec2(v.z *10*1, v.x*10*-1); + bullet_born_pos = c->GetPos() + bullet_born_offset; + if (c->IsPlayer() || c->IsCar()) { +#ifdef DEBUG + a8::XPrintf("idx:%d offset:%f,%f angle:%f old_angle:%f angle_xy:%f,%f %f %f gun_muzzle_position:%f,%f,%f pos:%f,%f gun_id:%d t:%d\n", + { + bulletIdx, + bullet_born_offset.x, + bullet_born_offset.y, + bullet_born_angle, + old_bullet_born_angle, + c->GetAttackDir().x, + c->GetAttackDir().y, + (bullet_born_angle * 180), + (bullet_born_angle - glm::radians(90.0f) / A8_PI) * 180, + gun_muzzle_position.x, + gun_muzzle_position.y, + gun_muzzle_position.z, + bullet_born_pos.x, + bullet_born_pos.y, + weapon_meta->i->id(), + shot_animi_time + }); +#endif + } + } + { + BulletInfo bullet_info; + bullet_info.c = c->GetWeakPtrRef(); + bullet_info.weapon_uniid = weapon_uniid; + bullet_info.weapon_meta = weapon_meta; + bullet_info.skill_meta = skill_meta; + bullet_info.bullet_meta = bullet_meta; + bullet_info.bullet_born_pos = bullet_born_pos; + bullet_info.bullet_dir = bullet_dir; + bullet_info.fly_distance = fly_distance; + bullet_info.delay_time = std::get<3>(tuple); + bullet_info.recoil_force = std::get<4>(tuple); + bullet_info.invincible_buff_uniid = invincible_buff_uniid; + bullet_info.trace_target_uniid = trace_target_uniid; + bullet_info.keep_shot_animi_timer_ptr = keep_shot_animi_timer_ptr; + bullet_info.shot_animi_time = shot_animi_time; + if (skill_meta && + (skill_meta->GetMagicId() == MAGIC_AXXF || + skill_meta->GetMagicId() == MAGIC_HJHX)) { + bullet_info.trace_target_uniid = c->GetSkillTargetId(); + } + if (weapon_meta->i->double_gun() && + bulletIdx > (int)(bulletNum / 2)) { + bullet_info.hand = 1; + } +#ifdef DEBUG + if (bullet_info.trace_target_uniid) { + a8::XPrintf("bullet trace_target_uniid:%d\n", {bullet_info.trace_target_uniid}); + } +#endif + InternalCreateBullet(bullet_info); + } + } + c->GetTrigger()->Shot(weapon_meta); + if (weapon_meta->i->recoil_force() > 0.000001) { + c->DoRecoilForce(weapon_meta->i->recoil_force()); + } + if (c->HasBuffEffect(kBET_Hide)) { + c->RemoveBuffByEffectId(kBET_Hide); + } + if (trace_target_uniid) { + c->LockAttackDir(1000); + } + if (c->aiming) { + c->aiming = false; + c->aiming_frameno = 0; + c->power_idx = -1; + c->ClearAimingBuffs(); + } +} diff --git a/server/gameserver/shot.h b/server/gameserver/shot.h new file mode 100644 index 00000000..e3844e24 --- /dev/null +++ b/server/gameserver/shot.h @@ -0,0 +1,17 @@ +#pragma once + +namespace MetaData +{ + struct Equip; + struct Skill; +}; + +class Creature; + +void InternalShot(Creature* sender, + MetaData::Equip* weapon_meta, + MetaData::Equip* bullet_meta, + MetaData::Skill* skill_meta, + float fly_distance, + long long weapon_uniid, + int trace_target_uniid);