diff --git a/server/gameserver/bullet.cc b/server/gameserver/bullet.cc index 3d506d6..024c104 100644 --- a/server/gameserver/bullet.cc +++ b/server/gameserver/bullet.cc @@ -519,6 +519,17 @@ void Bullet::ProcC4Bomb(Car* target, int delay_time) task->bomb_pos = GetPos(); if (target) { task->follow_target.Attach(target); + task->force_target.Attach(target); + if (gun_meta->int_param1 > 0) { + int buff_uniid = target->TryAddBuff(sender.Get(), gun_meta->int_param1); + if (buff_uniid != 0) { + Buff* buff = target->GetBuffByUniId(buff_uniid); + if (buff && buff->remover_timer) { + target->room->xtimer.ModifyTimer(buff->remover_timer, + std::max(1, (int)(delay_time / FRAME_RATE_MS))); + } + } + } } task->gun_meta = gun_meta; task->meta = meta; diff --git a/server/gameserver/car.cc b/server/gameserver/car.cc index 667043b..e41b98a 100644 --- a/server/gameserver/car.cc +++ b/server/gameserver/car.cc @@ -303,6 +303,48 @@ void Car::OnBulletHit(Bullet* bullet) } } +void Car::OnExplosionHit(Explosion* e) +{ + if (IsInvincible()) { + return; + } + if (dead) { + return; + } + if (e->IsPreBattleExplosion()) { + return; + } + if (HasBuffEffect(kBET_Jump) || + HasBuffEffect(kBET_Fly)) { + return; + } + + float dmg = e->GetDmg(); + float def = GetDef() * (1 + GetAbility()->GetAttrRate(kHAT_Def)) + + GetAbility()->GetAttrAbs(kHAT_Def); + float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K); + finaly_dmg = std::max(finaly_dmg, 0.0f); +#ifdef DEBUG + { + room->BroadcastDebugMsg(a8::Format("explosion dmg:%d def:%d finaly_dmg:%d", + {dmg, + def, + finaly_dmg})); + } +#endif +#if 1 + DecHP(finaly_dmg, + 1, + "", + 1); +#else + DecHP(finaly_dmg, + sender.Get()->GetUniId(), + sender.Get()->GetName(), + gun_meta->i->id()); +#endif +} + void Car::DecHP(float dec_hp, int killer_id, const std::string& killer_name, int weapon_id) { if (dec_hp < 0.001f) { diff --git a/server/gameserver/car.h b/server/gameserver/car.h index 7ca3280..6b806f6 100644 --- a/server/gameserver/car.h +++ b/server/gameserver/car.h @@ -26,6 +26,7 @@ class Car : public Creature virtual void FillMFObjectPart(Room* room, Human* hum, cs::MFObjectPart* part_data) override; virtual void FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data) override; virtual void OnBulletHit(Bullet* bullet) override; + virtual void OnExplosionHit(Explosion* e) override; virtual void GetAabbBox(AabbCollider& aabb_box) override; virtual void GetHitAabbBox(AabbCollider& aabb_box) override; diff --git a/server/gameserver/explosion.cc b/server/gameserver/explosion.cc index 9693ba3..569a556 100644 --- a/server/gameserver/explosion.cc +++ b/server/gameserver/explosion.cc @@ -117,6 +117,9 @@ void Explosion::InternalAttack() } } ); + if (force_target_.Get() && objects.find(force_target_.Get()) == objects.end()) { + objects.insert(force_target_.Get()); + } for (auto& target : objects) { if (target->IsCreature(room_) && ((Creature*)target)->HasBuffEffect(kBET_BulletThrough)) { continue; @@ -129,3 +132,8 @@ bool Explosion::IsPreBattleExplosion() { return create_frameno_ <= room_->GetBattleStartFrameNo() || room_->GetBattleStartFrameNo() == 0; } + +void Explosion::AddForceTarget(CreatureWeakPtr force_target) +{ + force_target_ = force_target; +} diff --git a/server/gameserver/explosion.h b/server/gameserver/explosion.h index 80a8bd6..130d3d5 100644 --- a/server/gameserver/explosion.h +++ b/server/gameserver/explosion.h @@ -26,6 +26,8 @@ class Explosion int explosion_effect, float dmg, long long special_damage_type = 0); + void AddForceTarget(CreatureWeakPtr force_target); + private: void InternalAttack(); @@ -33,6 +35,7 @@ class Explosion int type_ = 0; Room* room_ = nullptr; CreatureWeakPtr sender_; + CreatureWeakPtr force_target_; float explosion_range_ = 0; int explosion_effect_ = 0; float dmg_ = 0; diff --git a/server/gameserver/frag_mitask.cc b/server/gameserver/frag_mitask.cc index c614757..28fc845 100644 --- a/server/gameserver/frag_mitask.cc +++ b/server/gameserver/frag_mitask.cc @@ -15,9 +15,13 @@ void FragMiTask::Done() a8::Vec2 center = bomb_pos; if (follow_target.Get()) { bomb_pos = follow_target.Get()->GetPos(); + center = bomb_pos; } Explosion explosion; + if (force_target.Get()) { + explosion.AddForceTarget(force_target); + } explosion.EnemyAndObstacleAttack(sender, center, explosion_range, diff --git a/server/gameserver/frag_mitask.h b/server/gameserver/frag_mitask.h index d360c4e..9d85a56 100644 --- a/server/gameserver/frag_mitask.h +++ b/server/gameserver/frag_mitask.h @@ -17,6 +17,7 @@ class FragMiTask : public MicroTask a8::Vec2 bomb_pos; CreatureWeakPtr sender; CreatureWeakPtr follow_target; + CreatureWeakPtr force_target; MetaData::Equip* gun_meta = nullptr; MetaData::Equip* meta = nullptr; float explosion_range = 1; diff --git a/server/gameserver/metadata.cc b/server/gameserver/metadata.cc index 29e0063..db884cb 100644 --- a/server/gameserver/metadata.cc +++ b/server/gameserver/metadata.cc @@ -216,6 +216,9 @@ namespace MetaData ) ); lock_time += strings2.size() > 3 ? a8::XValue(strings2[3]).GetInt() : 0; + if (strings2.size() > 4 && a8::XValue(strings2[4]).GetInt() == 1) { + lock_time = 0; + } } } {