This commit is contained in:
aozhiwei 2021-07-28 10:58:50 +08:00
commit 10e04da61c
25 changed files with 482 additions and 44 deletions

View File

@ -78,7 +78,9 @@ void Buff::ProcIntervalAddBuff()
void Buff::ProcBatchAddBuff() void Buff::ProcBatchAddBuff()
{ {
std::shared_ptr<Ability> old_context_ability = owner->context_ability; std::shared_ptr<Ability> old_context_ability = owner->context_ability;
a8::Vec2 old_context_dir = owner->context_dir;
a8::Vec2 old_context_pos = owner->context_pos; a8::Vec2 old_context_pos = owner->context_pos;
owner->context_dir = owner->GetAttackDir();
owner->context_pos = owner->GetPos(); owner->context_pos = owner->GetPos();
for (auto& tuple : meta->batch_add_list) { for (auto& tuple : meta->batch_add_list) {
@ -112,6 +114,7 @@ void Buff::ProcBatchAddBuff()
} }
} }
owner->context_dir = old_context_dir;
owner->context_pos = old_context_pos; owner->context_pos = old_context_pos;
owner->context_ability = old_context_ability; owner->context_ability = old_context_ability;
} }
@ -128,7 +131,9 @@ void Buff::InternalTimerAddBuff()
SkillCasterState* caster_state = (SkillCasterState*)param.param1.GetUserData(); SkillCasterState* caster_state = (SkillCasterState*)param.param1.GetUserData();
if (caster_state->caster.Get()) { if (caster_state->caster.Get()) {
std::shared_ptr<Ability> old_context_ability = receiver->context_ability; std::shared_ptr<Ability> old_context_ability = receiver->context_ability;
a8::Vec2 old_context_dir = receiver->context_dir;
a8::Vec2 old_context_pos = receiver->context_pos; a8::Vec2 old_context_pos = receiver->context_pos;
receiver->context_dir = receiver->GetAttackDir();
receiver->context_pos = receiver->GetPos(); receiver->context_pos = receiver->GetPos();
int buff_id = param.param2; int buff_id = param.param2;
@ -142,6 +147,7 @@ void Buff::InternalTimerAddBuff()
caster_state->caster.Get()->RecoverSkillCasterState(&old_caster_state); caster_state->caster.Get()->RecoverSkillCasterState(&old_caster_state);
} }
receiver->context_dir = old_context_dir;
receiver->context_pos = old_context_pos; receiver->context_pos = old_context_pos;
receiver->context_ability = old_context_ability; receiver->context_ability = old_context_ability;
} }
@ -458,20 +464,60 @@ void Buff::ProcTurnOver()
a8::Vec2 old_pos = owner->GetPos(); a8::Vec2 old_pos = owner->GetPos();
float distance = float distance =
owner->HasBuffEffect(kBET_Car) ? phase->param1.GetDouble() * 1.5 : phase->param1.GetDouble(); owner->HasBuffEffect(kBET_Car) ? phase->param1.GetDouble() * 1.5 : phase->param1.GetDouble();
if (meta->int_param1 == 1) { owner->_UpdateMove(distance);
//穿墙 int moved_distance = (int)owner->GetPos().Distance(old_pos);
} else { moved_distance = std::min(moved_distance, 200);
owner->_UpdateMove(distance); if (!meta->param1_int_list.empty() && moved_distance > 2) {
std::set<Creature*> target_list;
owner->TraverseCreatures
(
[this, &target_list] (Creature* c, bool& stop)
{
if (owner->IsProperTarget(c) && owner->GetPos().Distance(c->GetPos()) < 300) {
target_list.insert(c);
}
});
a8::Vec2 curr_pos = owner->GetPos();
a8::Vec2 dir = owner->GetPos() - old_pos;
dir.Normalize();
for (int i = 5; i < moved_distance; i += 5) {
owner->SetPos(old_pos + dir * i);
std::list<Creature*> hit_objects;
for (auto& target : target_list) {
if (owner->TestCollision(owner->room, target)) {
hit_objects.push_back(target);
}
}
for (auto& target : hit_objects) {
target_list.erase(target);
target->room->xtimer.AddDeadLineTimerAndAttach
(
meta->int_param4 / FRAME_RATE_MS * (i / moved_distance),
a8::XParams()
.SetSender(target)
.SetParam1(meta)
.SetParam2(owner->GetUniId()),
[] (const a8::XParams& param)
{
Creature* c = (Creature*)param.sender.GetUserData();
MetaData::Buff* buff_meta = (MetaData::Buff*)param.param1.GetUserData();
Entity* caster = c->room->GetEntityByUniId(param.param2);
if (caster && caster->IsCreature(c->room)) {
for (int buff_id : buff_meta->param1_int_list) {
c->TryAddBuff((Creature*)caster, buff_id);
}
}
},
&target->xtimer_attacher.timer_list_);
}
}
owner->SetPos(curr_pos);
} }
if (!meta->param2_int_list.empty()) { if (!meta->param2_int_list.empty()) {
int time = 0;
float moved_distance = owner->GetPos().Distance(old_pos);
if (std::abs(moved_distance) > 0.01f) {
time = ((moved_distance / distance) * meta->param3) / FRAME_RATE_MS;
}
owner->room->xtimer.AddDeadLineTimerAndAttach owner->room->xtimer.AddDeadLineTimerAndAttach
( (
time, meta->int_param4 / FRAME_RATE_MS,
a8::XParams() a8::XParams()
.SetSender(owner) .SetSender(owner)
.SetParam1(meta), .SetParam1(meta),
@ -479,9 +525,16 @@ void Buff::ProcTurnOver()
{ {
Creature* c = (Creature*)param.sender.GetUserData(); Creature* c = (Creature*)param.sender.GetUserData();
MetaData::Buff* buff_meta = (MetaData::Buff*)param.param1.GetUserData(); MetaData::Buff* buff_meta = (MetaData::Buff*)param.param1.GetUserData();
for (int buff_id : buff_meta->param2_int_list) { c->TraverseCreatures
c->TryAddBuff(c, buff_id); (
} [c, buff_meta] (Creature* target, bool& stop)
{
if (c->GetPos().Distance(target->GetPos()) < buff_meta->int_param3) {
for (int buff_id : buff_meta->param2_int_list) {
target->TryAddBuffWithTarget(c, buff_id);
}
}
});
}, },
&owner->xtimer_attacher.timer_list_ &owner->xtimer_attacher.timer_list_
); );
@ -529,3 +582,74 @@ void Buff::ProcOnceChgAttr()
{ {
} }
void Buff::ProcAutoShot()
{
owner->room->xtimer.AddRepeatTimerAndAttach
(
1,
a8::XParams()
.SetSender(this),
[] (const a8::XParams& param)
{
Buff* buff = (Buff*)param.sender.GetUserData();
if (buff->owner->IsHuman()) {
#if 0
buff->owner->AsHuman()->shot_start = true;
#endif
buff->owner->AsHuman()->shot_hold = true;
buff->owner->AsHuman()->series_shot_frames = 0;
}
},
&xtimer_attacher.timer_list_,
[] (const a8::XParams& param)
{
Buff* buff = (Buff*)param.sender.GetUserData();
if (buff->owner->IsHuman()) {
#if 0
buff->owner->AsHuman()->shot_start = false;
#endif
buff->owner->AsHuman()->shot_hold = false;
buff->owner->AsHuman()->series_shot_frames = 0;
}
});
}
void Buff::ProcBeatBack()
{
if (caster_.Get()) {
if (std::abs(caster_.Get()->context_dir.x) > FLT_EPSILON ||
std::abs(caster_.Get()->context_dir.x) > FLT_EPSILON) {
if (std::abs(meta->int_param1) > 0) {
a8::Vec2 old_move_dir = owner->GetMoveDir();
owner->SetMoveDir(caster_.Get()->context_dir);
owner->_UpdateMove(meta->param1);
owner->SetMoveDir(old_move_dir);
}
}
}
}
void Buff::ProcDisperse()
{
std::vector<int> del_buffs;
owner->TraverseBuff
(
[this, &del_buffs] (Buff* buff, bool& stop)
{
for (int tag : meta->param1_int_set) {
if (buff->meta->tags.find(tag) != buff->meta->tags.end()) {
del_buffs.push_back(buff->buff_uniid);
break;
}
}
});
for (int buff_uniid : del_buffs) {
owner->RemoveBuffByUniId(buff_uniid);
}
}
void Buff::ProcAISeting()
{
}

View File

@ -69,6 +69,10 @@ class Buff
void ProcSeletTargetWithSelfPos(); void ProcSeletTargetWithSelfPos();
void ProcTurnOver(); void ProcTurnOver();
void ProcPullToWalkable(); void ProcPullToWalkable();
void ProcAutoShot();
void ProcBeatBack();
void ProcDisperse();
void ProcAISeting();
private: private:
void InternalTimerAddBuff(); void InternalTimerAddBuff();

View File

@ -54,9 +54,19 @@ void Bullet::RecalcSelfCollider()
void Bullet::OnHit(std::set<Entity*>& objects) void Bullet::OnHit(std::set<Entity*>& objects)
{ {
std::shared_ptr<Ability> old_context_ability = sender.Get()->context_ability;
a8::Vec2 old_context_dir = sender.Get()->context_dir;
a8::Vec2 old_context_pos = sender.Get()->context_pos;
sender.Get()->context_dir = dir;
sender.Get()->context_pos = GetPos();
for (auto& target : objects) { for (auto& target : objects) {
target->OnBulletHit(this); target->OnBulletHit(this);
} }
sender.Get()->context_dir = old_context_dir;
sender.Get()->context_pos = old_context_pos;
sender.Get()->context_ability = old_context_ability;
} }
void Bullet::ProcBomb() void Bullet::ProcBomb()
@ -357,6 +367,9 @@ void Bullet::Check(float distance)
//穿人 //穿人
return; return;
} }
if (c->HasBuffEffect(kBET_BulletThrough)) {
return;
}
AabbCollider aabb_box; AabbCollider aabb_box;
c->GetHitAabbBox(aabb_box); c->GetHitAabbBox(aabb_box);
if (c != sender.Get() && !c->dead && TestCollision(room, &aabb_box)) { if (c != sender.Get() && !c->dead && TestCollision(room, &aabb_box)) {
@ -528,7 +541,9 @@ void Bullet::AddGunBuff()
{ {
if (sender.Get()) { if (sender.Get()) {
std::shared_ptr<Ability> old_context_ability = sender.Get()->context_ability; std::shared_ptr<Ability> old_context_ability = sender.Get()->context_ability;
a8::Vec2 old_context_dir = sender.Get()->context_dir;
a8::Vec2 old_context_pos = sender.Get()->context_pos; a8::Vec2 old_context_pos = sender.Get()->context_pos;
sender.Get()->context_dir = dir;
sender.Get()->context_pos = GetPos(); sender.Get()->context_pos = GetPos();
if (IsCurrWeapon()) { if (IsCurrWeapon()) {
sender.Get()->context_ability = ability_; sender.Get()->context_ability = ability_;
@ -542,6 +557,7 @@ void Bullet::AddGunBuff()
1 1
); );
} }
sender.Get()->context_dir = old_context_dir;
sender.Get()->context_pos = old_context_pos; sender.Get()->context_pos = old_context_pos;
sender.Get()->context_ability = old_context_ability; sender.Get()->context_ability = old_context_ability;
} }

View File

@ -275,6 +275,9 @@ void Car::OnBulletHit(Bullet* bullet)
GetAbility()->GetAttrAbs(kHAT_Def); GetAbility()->GetAttrAbs(kHAT_Def);
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K); float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
finaly_dmg = std::max(finaly_dmg, 0.0f); finaly_dmg = std::max(finaly_dmg, 0.0f);
if (bullet->meta->buff_meta) {
MustBeAddBuff(bullet->sender.Get(), bullet->meta->i->buffid());
}
DecHP(finaly_dmg, DecHP(finaly_dmg,
bullet->sender.Get()->GetUniId(), bullet->sender.Get()->GetUniId(),
bullet->sender.Get()->GetName(), bullet->sender.Get()->GetName(),

View File

@ -359,6 +359,7 @@ enum ObstacleType_e
kObstacleGully = 7, kObstacleGully = 7,
kObstacleAirDropBox = 8, kObstacleAirDropBox = 8,
kObstacleOilBucket = 9, kObstacleOilBucket = 9,
kObstacleKeepRangeBuff = 10,
}; };
enum BulletHit_e enum BulletHit_e

View File

@ -67,6 +67,7 @@ enum BuffEffectType_e
kBET_Rescue = 45, //救援 kBET_Rescue = 45, //救援
kBET_AddCarBuff = 46, //给载具加buff kBET_AddCarBuff = 46, //给载具加buff
kBET_RemoveCarBuff = 47, //移除载具身上的buff kBET_RemoveCarBuff = 47, //移除载具身上的buff
kBET_BulletThrough = 48, //穿透
kBET_FollowMaster = 49, //跟随主人 kBET_FollowMaster = 49, //跟随主人
kBET_ThroughWall = 50, //穿墙 kBET_ThroughWall = 50, //穿墙
@ -85,6 +86,10 @@ enum BuffEffectType_e
kBET_MountainTop = 63, //在山顶 kBET_MountainTop = 63, //在山顶
kBET_UseSkill = 64, //使用技能 kBET_UseSkill = 64, //使用技能
kBET_CamouflageAddition = 65, //对抗伪装 kBET_CamouflageAddition = 65, //对抗伪装
kBET_AutoShot = 66, //自动射击
kBET_BeatBack = 67, //击退
kBET_Disperse = 68, //驱散
kBET_AiSeting = 69, //设置ai参数
kBET_End kBET_End
}; };

View File

@ -102,7 +102,9 @@ void InternalShot(Creature* c,
{ {
if (weapon_meta->i->_inventory_slot() == IS_TRAP || if (weapon_meta->i->_inventory_slot() == IS_TRAP ||
weapon_meta->i->_inventory_slot() == IS_MINE) { weapon_meta->i->_inventory_slot() == IS_MINE) {
a8::Vec2 old_context_dir = c->context_dir;
a8::Vec2 old_context_pos = c->context_pos; a8::Vec2 old_context_pos = c->context_pos;
c->context_dir =c->GetAttackDir();
c->context_pos = c->GetPos() + c->GetAttackDir() * fly_distance; c->context_pos = c->GetPos() + c->GetAttackDir() * fly_distance;
MetaData::Buff * buff_meta = MetaMgr::Instance()->GetBuff(bullet_meta->i->buffid()); MetaData::Buff * buff_meta = MetaMgr::Instance()->GetBuff(bullet_meta->i->buffid());
if (buff_meta) { if (buff_meta) {
@ -111,6 +113,7 @@ void InternalShot(Creature* c,
1 1
); );
} }
c->context_dir = old_context_dir;
c->context_pos = old_context_pos; c->context_pos = old_context_pos;
return; return;
} }
@ -363,7 +366,6 @@ int Creature::AddBuff(Creature* caster,
} }
} }
} }
return new_buff_uniid;
#ifdef DEBUG #ifdef DEBUG
SendDebugMsg(a8::Format("添加buff_id:%d effect:%d %s params:%d,%d,%d,%d,%d", SendDebugMsg(a8::Format("添加buff_id:%d effect:%d %s params:%d,%d,%d,%d,%d",
{ {
@ -377,6 +379,7 @@ int Creature::AddBuff(Creature* caster,
buff_meta->int_param5, buff_meta->int_param5,
})); }));
#endif #endif
return new_buff_uniid;
} }
bool Creature::IsImmuneBuffEffect(int buff_effect) bool Creature::IsImmuneBuffEffect(int buff_effect)
@ -407,12 +410,60 @@ int Creature::TryAddBuff(Creature* caster, int buff_id)
return -1; return -1;
} }
int Creature::TryAddBuffWithTarget(Creature* caster, int buff_id)
{
MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id);
if (buff_meta) {
bool be_add = false;
switch (buff_meta->i->buff_target()) {
case kBuffTargetSelf:
{
be_add = caster == this;
}
break;
case kBuffTargetFriendly:
{
team_id == caster->team_id;
}
break;
case kBuffTargetEnemy:
{
team_id != caster->team_id;
}
break;
default:
{
}
break;
}
return TryAddBuff(caster, buff_id);
}
return -1;
}
void Creature::RemoveBuffById(int buff_id) void Creature::RemoveBuffById(int buff_id)
{ {
std::vector<std::tuple<MetaData::Buff*, Creature*>> removed_buffs; int buff_uniid = 0;
for (auto itr = buff_list_.begin(); itr != buff_list_.end(); ++itr) { for (auto itr = buff_list_.begin(); itr != buff_list_.end(); ++itr) {
Buff& buff = *itr; Buff& buff = *itr;
if (buff.meta->i->buff_id() == buff_id) { if (buff.meta->i->buff_id() == buff_id) {
buff_uniid = buff.buff_uniid;
break;
}
}
if (buff_uniid != 0) {
RemoveBuffByUniId(buff_uniid);
}
}
void Creature::RemoveBuffByUniId(int buff_uniid)
{
int buff_id = 0;
std::vector<std::tuple<MetaData::Buff*, Creature*>> removed_buffs;
for (auto itr = buff_list_.begin(); itr != buff_list_.end(); ++itr) {
Buff& buff = *itr;
if (buff.buff_uniid == buff_uniid) {
buff_id = buff.meta->i->buff_id();
removed_buffs.push_back(std::make_tuple(buff.meta, buff.GetCaster().Get())); removed_buffs.push_back(std::make_tuple(buff.meta, buff.GetCaster().Get()));
OnBuffRemove(buff); OnBuffRemove(buff);
buff.UnInit(); buff.UnInit();
@ -472,7 +523,7 @@ void Creature::RemoveBuffById(int buff_id)
SendDebugMsg(a8::Format("移除buff_id:%d", SendDebugMsg(a8::Format("移除buff_id:%d",
{ {
buff_id buff_id
})); }));
#endif #endif
} }
@ -730,6 +781,7 @@ void Creature::DoSkill(int skill_id,
skill_distance_ = skill_distance; skill_distance_ = skill_distance;
curr_skill_ = skill; curr_skill_ = skill;
playing_skill = true; playing_skill = true;
context_dir = skill_dir_;
context_pos = GetPos() + skill_dir_ * skill_distance_; context_pos = GetPos() + skill_dir_ * skill_distance_;
CurrentSkill()->last_use_frameno = room->GetFrameNo(); CurrentSkill()->last_use_frameno = room->GetFrameNo();
if (CurrentSkill()->meta->i->skill_target() == kST_Self if (CurrentSkill()->meta->i->skill_target() == kST_Self
@ -912,6 +964,7 @@ Skill* Creature::CurrentSkill()
void Creature::ProcBuffEffect(Creature* caster, Buff* buff) void Creature::ProcBuffEffect(Creature* caster, Buff* buff)
{ {
MetaData::Buff* buff_meta = buff->meta;
switch (buff->meta->i->buff_effect()) { switch (buff->meta->i->buff_effect()) {
case kBET_ChgAttr: case kBET_ChgAttr:
case kBET_Car: case kBET_Car:
@ -1209,6 +1262,26 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff)
} }
} }
break; break;
case kBET_AutoShot:
{
buff->ProcAutoShot();
}
break;
case kBET_BeatBack:
{
buff->ProcBeatBack();
}
break;
case kBET_Disperse:
{
buff->ProcDisperse();
}
break;
case kBET_AiSeting:
{
buff->ProcAISeting();
}
break;
default: default:
{ {
} }
@ -1830,6 +1903,9 @@ void Creature::SummonObstacle(Buff* buff, int id, const a8::Vec2& pos)
obstacle->Active(); obstacle->Active();
obstacle->context_ability = context_ability; obstacle->context_ability = context_ability;
slave_things_.push_back(std::make_tuple(buff->meta->i->buff_id(), obstacle)); slave_things_.push_back(std::make_tuple(buff->meta->i->buff_id(), obstacle));
#ifdef DEBUG
SendDebugMsg(a8::Format("召唤物件 buff_id:%d thing_id:%d", {buff->meta->i->buff_id(), id}));
#endif
} else { } else {
abort(); abort();
} }
@ -2418,3 +2494,14 @@ void Creature::ProcOnceChgAttrBuff(MetaData::Buff* buff_meta)
break; break;
} }
} }
void Creature::TraverseBuff(std::function<void (Buff*, bool&)> func)
{
bool stop = false;
for (auto& buff : buff_list_) {
func(&buff, stop);
if (stop) {
return;
}
}
}

View File

@ -69,6 +69,7 @@ class Creature : public MoveableEntity
Weapon second_weapon; Weapon second_weapon;
a8::Vec2 context_pos; a8::Vec2 context_pos;
a8::Vec2 context_dir;
std::shared_ptr<Ability> context_ability; std::shared_ptr<Ability> context_ability;
bool need_sync_active_player = false; bool need_sync_active_player = false;
@ -89,6 +90,7 @@ class Creature : public MoveableEntity
virtual void RemoveOutObjects(Entity* entity) {}; virtual void RemoveOutObjects(Entity* entity) {};
virtual bool Attackable(Room* room) override; virtual bool Attackable(Room* room) override;
virtual bool ReceiveExplosionDmg(Explosion* explosion) override; virtual bool ReceiveExplosionDmg(Explosion* explosion) override;
virtual bool IsCreature(Room* room) override { return true;};
bool HasBuffEffect(int buff_effect_id); bool HasBuffEffect(int buff_effect_id);
Buff* GetBuffByEffectId(int effect_id); Buff* GetBuffByEffectId(int effect_id);
Buff* GetBuffById(int buff_id); Buff* GetBuffById(int buff_id);
@ -101,7 +103,9 @@ class Creature : public MoveableEntity
bool IsImmuneBuffEffect(int buff_effect); bool IsImmuneBuffEffect(int buff_effect);
int MustBeAddBuff(Creature* caster, int buff_id); int MustBeAddBuff(Creature* caster, int buff_id);
int TryAddBuff(Creature* caster, int buff_id); int TryAddBuff(Creature* caster, int buff_id);
int TryAddBuffWithTarget(Creature* caster, int buff_id);
void RemoveBuffById(int buff_id); void RemoveBuffById(int buff_id);
void RemoveBuffByUniId(int buff_uniid);
void ClearBuffById(int buff_id); void ClearBuffById(int buff_id);
void RecalcBuffAttr(); void RecalcBuffAttr();
void RemoveBuffByEffectId(int buff_effect_id); void RemoveBuffByEffectId(int buff_effect_id);
@ -206,6 +210,7 @@ class Creature : public MoveableEntity
Trigger* GetTrigger() { return trigger_; }; Trigger* GetTrigger() { return trigger_; };
std::shared_ptr<Ability>& GetAbility() { return ability_; }; std::shared_ptr<Ability>& GetAbility() { return ability_; };
void RefreshHP(); void RefreshHP();
void TraverseBuff(std::function<void (Buff*, bool&)> func);
protected: protected:

View File

@ -14,6 +14,19 @@ void DummyEntity::Initialize()
for (auto& obj : *blocks) { for (auto& obj : *blocks) {
switch (obj.shape()) { switch (obj.shape()) {
case 1: case 1:
{
CircleCollider* collider = new CircleCollider();
collider->owner = this;
collider->pos = a8::Vec2(obj.x(), obj.y());
collider->rad = obj.rad();
if (obj.bullet_penetrate()) {
a8::SetBitFlag(collider->tag, kHalfWallTag);
}
AddEntityCollider(collider);
permanent_map_service->AddCollider(collider);
}
break;
case 2:
{ {
AabbCollider* collider = new AabbCollider(); AabbCollider* collider = new AabbCollider();
collider->owner = this; collider->owner = this;
@ -21,21 +34,14 @@ void DummyEntity::Initialize()
obj.y() - obj.height()/2.0); obj.y() - obj.height()/2.0);
collider->_max = a8::Vec2(obj.x() + obj.width()/2.0, collider->_max = a8::Vec2(obj.x() + obj.width()/2.0,
obj.y() + obj.height()/2.0); obj.y() + obj.height()/2.0);
if (obj.bullet_penetrate()) {
a8::SetBitFlag(collider->tag, kHalfWallTag);
}
AddEntityCollider(collider); AddEntityCollider(collider);
collider_list.push_back(collider); collider_list.push_back(collider);
permanent_map_service->AddCollider(collider); permanent_map_service->AddCollider(collider);
} }
break; break;
case 2:
{
CircleCollider* collider = new CircleCollider();
collider->owner = this;
collider->pos = a8::Vec2(obj.x(), obj.y());
collider->rad = obj.rad();
AddEntityCollider(collider);
permanent_map_service->AddCollider(collider);
}
break;
default: default:
{ {
} }

View File

@ -30,6 +30,7 @@ class Entity
virtual float GetHitRadius() { return GetRadius();}; virtual float GetHitRadius() { return GetRadius();};
virtual void GetCircleBox(CircleCollider& circle_box); virtual void GetCircleBox(CircleCollider& circle_box);
virtual bool IsDead(Room* room) { return false;}; virtual bool IsDead(Room* room) { return false;};
virtual bool IsCreature(Room* room) { return false;};
virtual long long GetDeadFrameNo(Room* room) { return 0;}; virtual long long GetDeadFrameNo(Room* room) { return 0;};
virtual void OnPreCollision(Room* room) {}; virtual void OnPreCollision(Room* room) {};
virtual void RecalcSelfCollider() {}; virtual void RecalcSelfCollider() {};

View File

@ -116,6 +116,9 @@ void Explosion::InternalAttack()
} }
); );
for (auto& target : objects) { for (auto& target : objects) {
if (target->IsCreature(room_) && ((Creature*)target)->HasBuffEffect(kBET_BulletThrough)) {
continue;
}
target->OnExplosionHit(this); target->OnExplosionHit(this);
} }
} }

View File

@ -91,7 +91,7 @@ void Hero::OnBulletHit(Bullet* bullet)
sender->stats.damage_amount_out += finaly_dmg; sender->stats.damage_amount_out += finaly_dmg;
#endif #endif
if (bullet->meta->buff_meta) { if (bullet->meta->buff_meta) {
MustBeAddBuff(this, bullet->meta->i->buffid()); MustBeAddBuff(bullet->sender.Get(), bullet->meta->i->buffid());
} }
DecHP(finaly_dmg, DecHP(finaly_dmg,
bullet->sender.Get()->GetUniId(), bullet->sender.Get()->GetUniId(),

View File

@ -1141,6 +1141,7 @@ void Human::RefreshView()
case ET_Building: case ET_Building:
case ET_Obstacle: case ET_Obstacle:
case ET_Loot: case ET_Loot:
case ET_MapBlock:
{ {
AddToNewObjects(entity); AddToNewObjects(entity);
} }
@ -2715,6 +2716,7 @@ void Human::GetViewObjects(std::set<Entity*>& view_objects)
case ET_Building: case ET_Building:
case ET_Obstacle: case ET_Obstacle:
case ET_Loot: case ET_Loot:
case ET_MapBlock:
{ {
view_objects.insert(entity); view_objects.insert(entity);
} }
@ -2799,6 +2801,7 @@ void Human::ProcIncGridList(std::set<GridCell*>& old_grids,
case ET_Building: case ET_Building:
case ET_Obstacle: case ET_Obstacle:
case ET_Loot: case ET_Loot:
case ET_MapBlock:
{ {
AddToNewObjects(entity); AddToNewObjects(entity);
RemoveOutObjects(entity); RemoveOutObjects(entity);
@ -2847,6 +2850,7 @@ void Human::ProcDecGridList(std::set<GridCell*>& old_grids,
case ET_Building: case ET_Building:
case ET_Obstacle: case ET_Obstacle:
case ET_Loot: case ET_Loot:
case ET_MapBlock:
{ {
AddOutObjects(entity); AddOutObjects(entity);
} }
@ -3541,7 +3545,7 @@ void Human::OnBulletHit(Bullet* bullet)
sender->stats.damage_amount_out += finaly_dmg; sender->stats.damage_amount_out += finaly_dmg;
#endif #endif
if (bullet->meta->buff_meta) { if (bullet->meta->buff_meta) {
MustBeAddBuff(this, bullet->meta->i->buffid()); MustBeAddBuff(bullet->sender.Get(), bullet->meta->i->buffid());
} }
if (bullet->sender.Get() && bullet->sender.Get()->IsCar() && bullet->passenger.Get()) { if (bullet->sender.Get() && bullet->sender.Get()->IsCar() && bullet->passenger.Get()) {
DecHP(finaly_dmg, DecHP(finaly_dmg,

View File

@ -1,6 +1,10 @@
#include "precompile.h" #include "precompile.h"
#include "mapblock.h" #include "mapblock.h"
#include "collider.h"
#include "cs_proto.pb.h"
#include "typeconvert.h"
#include "metamgr.h"
MapBlock::MapBlock() MapBlock::MapBlock()
{ {
@ -24,22 +28,67 @@ void MapBlock::RecalcSelfCollider()
void MapBlock::FillMFObjectPart(Room* room, Human* hum, cs::MFObjectPart* part_data) void MapBlock::FillMFObjectPart(Room* room, Human* hum, cs::MFObjectPart* part_data)
{ {
part_data->set_object_type(ET_Obstacle);
cs::MFObstaclePart* p = part_data->mutable_union_obj_2();
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
p->set_scale(1.0f);
} }
void MapBlock::FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data) void MapBlock::FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data)
{ {
full_data->set_object_type(ET_Obstacle);
if (IsClientCached(hum)) {
int object_flags = 0;
a8::SetBitFlag(object_flags, kOfReadCache);
full_data->set_obj_uniid(GetUniId());
full_data->set_object_flags(object_flags);
return;
}
cs::MFObstacleFull* p = full_data->mutable_union_obj_2();
if (CanClientCache(hum)) {
int object_flags = 0;
a8::SetBitFlag(object_flags, kOfWriteCache);
#if 0
full_data->set_obj_uniid(GetUniId());
#endif
full_data->set_object_flags(object_flags);
AddClientCache(hum);
}
p->set_obj_uniid(GetUniId());
TypeConvert::ToPb(GetPos(), p->mutable_pos());
p->set_scale(1.0f);
p->set_obstacle_id(meta->i->thing_id());
p->set_health(0);
p->set_dead(false);
p->set_dead_at_thisframe(false);
p->set_is_door(false);
{
cs::MFCollider* collider = full_data->mutable_union_obj_2()->mutable_collider();
collider->set_shape(shape);
if (shape == 1) {
collider->set_width(rad);
collider->set_height(rad);
} else {
collider->set_width(width);
collider->set_height(height);
}
}
} }
void MapBlock::GetAabbBox(AabbCollider& aabb_box) void MapBlock::GetAabbBox(AabbCollider& aabb_box)
{ {
aabb_box.active = false;
aabb_box.owner = this;
} }
void MapBlock::GetCircleBox(CircleCollider& circle_box) void MapBlock::GetCircleBox(CircleCollider& circle_box)
{ {
circle_box.active = false;
circle_box.owner = this;
} }
bool MapBlock::IsDead(Room* room) bool MapBlock::IsDead(Room* room)

View File

@ -45,8 +45,6 @@ protected:
MapBlock(); MapBlock();
protected: protected:
CircleCollider* self_collider_ = nullptr;
AabbCollider* self_collider2_ = nullptr;
friend class EntityFactory; friend class EntityFactory;
}; };

View File

@ -280,11 +280,27 @@ void MapInstance::CreateBlock()
for (auto& obj : *blocks) { for (auto& obj : *blocks) {
switch (obj.shape()) { switch (obj.shape()) {
case 1: case 1:
{
}
break;
case 2: case 2:
{ {
if (!obj.bullet_penetrate()) {
MapBlock* block = EntityFactory::Instance()->MakeBlock(++current_map_block_uniid_);
block->meta = MetaMgr::Instance()->GetMapThing
(obj.bullet_penetrate() ? 40002 : 40001);
block->shape = obj.shape();
block->width = obj.width();
block->height = obj.height();
block->rad = obj.rad();
block->permanent_map_service = map_service_;
block->SetPos(a8::Vec2(obj.x(), obj.y()));
block->Initialize();
uniid_hash_[block->GetUniId()] = block;
grid_service_->AddPermanentEntity(block);
if (!block->meta) {
abort();
}
} else {
int i = 0;
}
} }
break; break;
default: default:

View File

@ -822,6 +822,7 @@ namespace MetaData
a8::Split(i->buff_param1(), strings, '|'); a8::Split(i->buff_param1(), strings, '|');
for (auto& str : strings) { for (auto& str : strings) {
param1_int_list.push_back(a8::XValue(str).GetInt()); param1_int_list.push_back(a8::XValue(str).GetInt());
param1_int_set.insert(a8::XValue(str).GetInt());
} }
} }
{ {
@ -849,6 +850,13 @@ namespace MetaData
param4_int_list.push_back(a8::XValue(str).GetInt()); param4_int_list.push_back(a8::XValue(str).GetInt());
} }
} }
{
std::vector<std::string> strings;
a8::Split(i->tag(), strings, '|');
for (auto& str : strings) {
tags.insert(a8::XValue(str).GetInt());
}
}
{ {
std::vector<std::string> strings; std::vector<std::string> strings;
a8::Split(i->post_remove_action(), strings, '|'); a8::Split(i->post_remove_action(), strings, '|');

View File

@ -213,6 +213,7 @@ namespace MetaData
int int_param5 = 0; int int_param5 = 0;
std::vector<int> param1_int_list; std::vector<int> param1_int_list;
std::vector<int> param2_int_list; std::vector<int> param2_int_list;
std::set<int> param1_int_set;
std::set<int> param2_int_set; std::set<int> param2_int_set;
std::vector<int> param3_int_list; std::vector<int> param3_int_list;
std::vector<int> param4_int_list; std::vector<int> param4_int_list;
@ -220,6 +221,7 @@ namespace MetaData
std::vector<std::tuple<int, std::vector<int>>> post_remove_action; std::vector<std::tuple<int, std::vector<int>>> post_remove_action;
std::set<int> immune_buffeffect; std::set<int> immune_buffeffect;
std::vector<std::tuple<int, float, float, int, int>> hero_infos; std::vector<std::tuple<int, float, float, int, int>> hero_infos;
std::set<int> tags;
std::vector<int> child_buff_list; std::vector<int> child_buff_list;
}; };

View File

@ -764,12 +764,15 @@ std::tuple<long long, a8::Vec2>* Obstacle::GetInteractionData(Human* sender)
void Obstacle::AddObstacleBuff(Creature* c) void Obstacle::AddObstacleBuff(Creature* c)
{ {
a8::Vec2 old_context_dir = c->context_dir;
a8::Vec2 old_context_pos = c->context_pos; a8::Vec2 old_context_pos = c->context_pos;
c->context_dir = c->GetAttackDir();
c->context_pos = c->GetPos(); c->context_pos = c->GetPos();
for (int buff_id : meta->buff_list) { for (int buff_id : meta->buff_list) {
c->TryAddBuff(c, buff_id); c->TryAddBuff(c, buff_id);
} }
c->context_pos = old_context_pos; c->context_pos = old_context_pos;
c->context_dir = old_context_dir;
} }
void Obstacle::ClearObstacleBuff(Creature* c) void Obstacle::ClearObstacleBuff(Creature* c)

View File

@ -210,7 +210,7 @@ void Player::UpdateShot()
series_shot_frames = 0; series_shot_frames = 0;
return; return;
} }
if (HasBuffEffect(kBET_Vertigo)) { if (HasBuffEffect(kBET_Vertigo) && !HasBuffEffect(kBET_AutoShot)) {
return; return;
} }
if (GetCar()) { if (GetCar()) {
@ -1056,8 +1056,19 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg)
std::abs(msg.attack_dir().y()) > 0.00001f std::abs(msg.attack_dir().y()) > 0.00001f
) )
){ ){
if (!HasBuffEffect(kBET_Vertigo) && bool can_set = true;
!(GetCar() && (GetCar()->HasBuffEffect(kBET_Vertigo) || !GetCar()->HasOil()))) { if (HasBuffEffect(kBET_Vertigo)) {
can_set = HasBuffEffect(kBET_AutoShot);
} else if (GetCar()) {
if (GetCar()->HasOil()) {
if (GetCar()->HasBuffEffect(kBET_Vertigo)) {
can_set = GetCar()->HasBuffEffect(kBET_AutoShot);
}
} else {
can_set = false;
}
}
if (can_set) {
a8::Vec2 attack_dir; a8::Vec2 attack_dir;
TypeConvert::FromPb(attack_dir, &msg.attack_dir()); TypeConvert::FromPb(attack_dir, &msg.attack_dir());
attack_dir.Normalize(); attack_dir.Normalize();
@ -1065,8 +1076,6 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg)
if (GetCar() && GetCar()->IsDriver(this)) { if (GetCar() && GetCar()->IsDriver(this)) {
GetCar()->SetAttackDir(GetAttackDir()); GetCar()->SetAttackDir(GetAttackDir());
} }
} else {
int i = 0;
} }
} }
} else { } else {
@ -1084,8 +1093,10 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg)
if (shot_start && !shot_hold) { if (shot_start && !shot_hold) {
} else { } else {
shot_start = msg.shot_start(); if (!HasBuffEffect(kBET_AutoShot)) {
shot_hold = msg.shot_hold(); shot_start = msg.shot_start();
shot_hold = msg.shot_hold();
}
} }
fly_distance = std::min(200.0f, msg.fly_distance()); fly_distance = std::min(200.0f, msg.fly_distance());
if (!shot_hold) { if (!shot_hold) {

View File

@ -41,6 +41,9 @@ RoomObstacle::~RoomObstacle()
if (!grid_list_) { if (!grid_list_) {
A8_SAFE_DELETE(grid_list_); A8_SAFE_DELETE(grid_list_);
} }
if (!hit_objects_) {
A8_SAFE_DELETE(hit_objects_);
}
} }
void RoomObstacle::Initialize() void RoomObstacle::Initialize()
@ -277,6 +280,11 @@ void RoomObstacle::Active()
ActiveAirDrop(); ActiveAirDrop();
} }
break; break;
case kObstacleKeepRangeBuff:
{
ActiveKeepRangeBuff();
}
break;
default: default:
{ {
} }
@ -465,3 +473,79 @@ Entity* RoomObstacle::GetRealObject(Room* room)
{ {
return room->GetEntityByUniId(real_object_uniid); return room->GetEntityByUniId(real_object_uniid);
} }
void RoomObstacle::ActiveKeepRangeBuff()
{
auto check_cb =
[] (const a8::XParams& param)
{
RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData();
obstacle->ProcKeepRangeBuff();
};
room->xtimer.AddRepeatTimerAndAttach
(
1,
a8::XParams()
.SetSender(this),
check_cb,
&xtimer_attacher.timer_list_
);
room->xtimer.AddDeadLineTimerAndAttach
(
meta->i->time() / FRAME_RATE_MS,
a8::XParams()
.SetSender(this),
[] (const a8::XParams& param)
{
RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData();
obstacle->DetachFromMaster();
},
&xtimer_attacher.timer_list_
);
}
void RoomObstacle::ProcKeepRangeBuff()
{
if (!grid_list_) {
grid_list_ = new std::set<GridCell*>();
room->grid_service->GetAllCellsByXy(room, GetPos().x, GetPos().y, *grid_list_);
}
if (!hit_objects_) {
hit_objects_ = new std::map<int, CreatureWeakPtr>();
}
if (grid_list_ && master.Get() && !IsDead(room)) {
std::set<Creature*> target_list;
room->grid_service->TraverseCreatures
(room->GetRoomIdx(),
*grid_list_,
[this, &target_list] (Creature* hum, bool& stop)
{
if (master.Get()->team_id != hum->team_id && TestCollision(room, hum)) {
target_list.insert(hum);
}
}
);
for (Creature* hum : target_list) {
for (int buff_id : meta->buff_list) {
MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id);
if (buff_meta && hum->GetBuffById(buff_id)) {
hum->AddBuff(master.Get(),
buff_meta,
1);
}
}
if (hit_objects_->find(hum->GetUniId()) == hit_objects_->end()) {
(*hit_objects_)[hum->GetUniId()] = hum->GetWeakPtrRef();
}
}
for (auto& pair : *hit_objects_) {
for (int buff_id : meta->buff_list) {
if (pair.second.Get() && target_list.find(pair.second.Get()) == target_list.end()) {
pair.second.Get()->RemoveBuffById(buff_id);
}
}
}
} else {
room->xtimer.DeleteTimer(room->xtimer.GetRunningTimer());
}
}

View File

@ -38,13 +38,16 @@ private:
void ActiveHideHouse(); void ActiveHideHouse();
void ActiveGully(); void ActiveGully();
void ActiveAirDrop(); void ActiveAirDrop();
void ActiveKeepRangeBuff();
void SummonAirDropBox(int box_id); void SummonAirDropBox(int box_id);
void ProcKeepRangeBuff();
protected: protected:
std::set<GridCell*>* grid_list_ = nullptr; std::set<GridCell*>* grid_list_ = nullptr;
int explosion_times_ = 0; int explosion_times_ = 0;
bool detached_ = false; bool detached_ = false;
std::map<int, CreatureWeakPtr>* hit_objects_ = nullptr;
RoomObstacle(); RoomObstacle();

View File

@ -219,7 +219,9 @@ void Trigger::TraverseCondBuffs(int cond, std::function<void (Buff*, bool&)> fun
void Trigger::TriggeCondBuffAll(int cond) void Trigger::TriggeCondBuffAll(int cond)
{ {
std::shared_ptr<Ability> old_context_ability = owner_->context_ability; std::shared_ptr<Ability> old_context_ability = owner_->context_ability;
a8::Vec2 old_context_dir = owner_->context_dir;
a8::Vec2 old_context_pos = owner_->context_pos; a8::Vec2 old_context_pos = owner_->context_pos;
owner_->context_dir = owner_->GetAttackDir();
owner_->context_pos = owner_->GetPos(); owner_->context_pos = owner_->GetPos();
TraverseCondBuffs TraverseCondBuffs
(cond, (cond,
@ -227,6 +229,7 @@ void Trigger::TriggeCondBuffAll(int cond)
{ {
AddBuffs(cond, buff->meta->param4_int_list); AddBuffs(cond, buff->meta->param4_int_list);
}); });
owner_->context_dir = old_context_dir;
owner_->context_pos = old_context_pos; owner_->context_pos = old_context_pos;
owner_->context_ability = old_context_ability; owner_->context_ability = old_context_ability;
} }

View File

@ -154,7 +154,7 @@ message MFPropertyChg
// //
message MFCollider message MFCollider
{ {
optional int32 shape = 1; // 1 2width=eight optional int32 shape = 1; // 1 2width=height
optional int32 width = 2; // optional int32 width = 2; //
optional int32 height = 3; // optional int32 height = 3; //
} }

View File

@ -258,6 +258,7 @@ message Buff
optional int32 coexist_num = 18; optional int32 coexist_num = 18;
optional int32 dead_valid = 23; optional int32 dead_valid = 23;
optional int32 buff_interval = 24; optional int32 buff_interval = 24;
optional string tag = 25;
} }
message Drop message Drop
@ -448,4 +449,5 @@ message MapBlockJson
optional float height = 7; optional float height = 7;
optional float width = 8; optional float width = 8;
optional float rad = 9; optional float rad = 9;
optional int32 bullet_penetrate = 10;
} }