diff --git a/server/gameserver/frameevent.cc b/server/gameserver/frameevent.cc index ed6b429..3e40306 100644 --- a/server/gameserver/frameevent.cc +++ b/server/gameserver/frameevent.cc @@ -42,7 +42,11 @@ void FrameEvent::AddShot(Human* hum) auto& p = std::get<1>(tuple); p.set_player_id(hum->entity_uniid); - hum->curr_weapon->ToPB(p.mutable_weapon()); + if (hum->tank_weapon.meta) { + hum->tank_weapon.ToPB(p.mutable_weapon()); + } else { + hum->curr_weapon->ToPB(p.mutable_weapon()); + } p.set_offhand(true); p.set_bullskin(10001); } @@ -64,12 +68,21 @@ void FrameEvent::AddBullet(Human* hum, a8::Vec2 born_pos, a8::Vec2 dir, float fl auto& p = std::get<1>(tuple); p.set_player_id(hum->entity_uniid); - p.set_bullet_id(hum->curr_weapon->meta->i->use_bullet()); + if (hum->tank_weapon.meta) { + p.set_bullet_id(hum->tank_weapon.meta->i->use_bullet()); + } else { + p.set_bullet_id(hum->curr_weapon->meta->i->use_bullet()); + } TypeConvert::ToPb(born_pos, p.mutable_pos()); TypeConvert::ToPb(dir, p.mutable_dir()); p.set_bulletskin(10001); - p.set_gun_id(hum->curr_weapon->meta->i->id()); - p.set_gun_lv(hum->curr_weapon->weapon_lv); + if (hum->tank_weapon.meta) { + p.set_gun_id(hum->tank_weapon.meta->i->id()); + p.set_gun_lv(hum->tank_weapon.weapon_lv); + } else { + p.set_gun_id(hum->curr_weapon->meta->i->id()); + p.set_gun_lv(hum->curr_weapon->weapon_lv); + } p.set_fly_distance(fly_distance); } { diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index ab1deb7..6eb271b 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -314,6 +314,48 @@ void Human::Shot(a8::Vec2& target_dir) need_sync_active_player = true; } +void Human::TankShot(a8::Vec2& target_dir) +{ + if (!tank_weapon.meta) { + return; + } + if (tank_weapon.ammo <= 0) { + return; + } + for (auto& tuple : tank_weapon.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 : tank_weapon.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 (tank_weapon.meta->i->bullet_angle() >= 0.01f) { + int angle = (int)tank_weapon.meta->i->bullet_angle() * 1000; + if (tank_weapon.upgrade_meta) { + angle -= tank_weapon.upgrade_meta->GetAttrValue(tank_weapon.weapon_lv, EA_BulletAngle) * 1000; + } + if (angle > 0) { + bullet_angle += (rand() % angle) / 1000.0f * (rand() % 2 == 0 ? 1 : -1); + } + } + bullet_dir.Rotate(bullet_angle / 180.0f); + room->frame_event.AddBullet(this, bullet_born_pos, bullet_dir, fly_distance); + if (room->BattleStarted() || (room->gas_data.gas_mode == GasJump && !a8::HasBitFlag(status, HS_Jump))) { + room->CreateBullet(this, &tank_weapon, bullet_born_pos, bullet_dir, fly_distance); + } + } + --tank_weapon.ammo; + last_shot_frameno_ = room->frame_no; +} + void Human::RecalcSelfCollider() { if (!self_collider_) { @@ -1156,6 +1198,21 @@ void Human::DoSkill() } } +void Human::DoGetDown() +{ + if (skin_tank.skin_id != 0) { + int entity_uniid = room->CreateLoot(skin_tank.skin_id, pos, 1, 1); + Entity* loot_entity = room->GetEntityByUniId(entity_uniid); + if (loot_entity && loot_entity->entity_type == ET_Loot) { + ((Loot*)loot_entity)->bullet_num = skin_tank.bullet_num; + } + skin_tank = Skin(); + tank_weapon = Weapon(); + RecalcSelfCollider(); + SyncAroundPlayers(); + } +} + void Human::FindLocation() { Entity* target = nullptr; @@ -2269,6 +2326,15 @@ void Human::ProcLootSkin(Loot* entity, MetaData::Equip* item_meta) skin_tank.skin_lv = std::max(1, GetSkinConfigLv(skin_tank.skin_id)); skin_tank.bullet_num = entity->bullet_num; skin_tank_meta = item_meta; + { + tank_weapon = Weapon(); + tank_weapon.weapon_idx = 100; + tank_weapon.weapon_id = item_meta->i->use_bullet(); + tank_weapon.weapon_lv = 1; + tank_weapon.ammo = 100; + tank_weapon.meta = MetaMgr::Instance()->GetEquip(item_meta->i->use_bullet()); + tank_weapon.Recalc(); + } RecalcSelfCollider(); RecalcBuff(); SyncAroundPlayers(); diff --git a/server/gameserver/human.h b/server/gameserver/human.h index 5d670fc..604414c 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -92,6 +92,7 @@ class Human : public Entity bool has_pass = 0; Weapon default_weapon; + Weapon tank_weapon; std::vector weapons; Weapon* curr_weapon = nullptr; @@ -136,6 +137,7 @@ class Human : public Entity virtual void GetAabbBox(AabbCollider& aabb_box); void FillMFTeamData(cs::MFTeamData* team_data); void Shot(a8::Vec2& target_dir); + void TankShot(a8::Vec2& target_dir); void RecalcSelfCollider(); bool IsCollision(); bool IsCollisionInMapService(); @@ -165,6 +167,7 @@ class Human : public Entity void Land(); void DoJump(); void DoSkill(); + void DoGetDown(); void FindLocation(); void RefreshView(); void OnGridListChange(std::set& old_grid_list, diff --git a/server/gameserver/player.cc b/server/gameserver/player.cc index 9928a28..c15c78c 100644 --- a/server/gameserver/player.cc +++ b/server/gameserver/player.cc @@ -96,6 +96,9 @@ void Player::Update(int delta_time) if (use_skill) { UpdateUseSkill(); } + if (get_down) { + UpdateGetDown(); + } } } @@ -137,12 +140,16 @@ void Player::UpdateShot() Shot(); return; } + Weapon* p_weapon = curr_weapon; + if (tank_weapon.meta) { + p_weapon = &tank_weapon; + } if (shot_hold) { ++series_shot_frames; if (last_shot_frameno_ == 0 || ( (room->frame_no - last_shot_frameno_) * (1000 / SERVER_FRAME_RATE)) >= - curr_weapon->meta->i->fire_rate() + p_weapon->meta->i->fire_rate() ) { Shot(); } @@ -289,8 +296,18 @@ void Player::UpdateUseSkill() use_skill = false; } +void Player::UpdateGetDown() +{ + DoGetDown(); + get_down = false; +} + void Player::Shot() { + if (tank_weapon.meta) { + TankShot(attack_dir); + return; + } if (!curr_weapon->meta) { return; } @@ -877,6 +894,9 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg) if (msg.has_use_skill()) { use_skill = true; } + if (msg.has_get_down()) { + get_down = msg.get_down(); + } } void Player::UpdateDropWeapon() diff --git a/server/gameserver/player.h b/server/gameserver/player.h index 6544970..26b568c 100644 --- a/server/gameserver/player.h +++ b/server/gameserver/player.h @@ -54,6 +54,8 @@ class Player : public Human bool use_skill = false; + bool get_down = false; + ::google::protobuf::RepeatedField< ::google::protobuf::int32 > interaction_objids; Player(); @@ -72,6 +74,7 @@ class Player : public Human void UpdateEmote(); void UpdateJump(); void UpdateUseSkill(); + void UpdateGetDown(); void Shot(); void ProcInteraction(); void ObstacleInteraction(Obstacle* entity);