This commit is contained in:
aozhiwei 2021-04-07 11:44:48 +08:00
commit dc3dacc865
25 changed files with 658 additions and 167 deletions

View File

@ -173,7 +173,7 @@ void Bullet::ProcBomb()
block = true;
}
}
float delay_time = 0;
int delay_time = 0;
if (!block) {
delay_time = gun_meta->i->missiles_time();
}
@ -206,16 +206,12 @@ void Bullet::ProcBomb()
case IS_POSION_GAS_BOMB:
{
//毒气弹
a8::Vec2 bomb_pos = GetPos();
room->frame_event.AddSmoke(this, meta->i->id(), bomb_pos);
ProcPosionGasBomb(delay_time);
}
break;
case IS_MOLOTOR_COCKTAIL:
{
//燃烧瓶
a8::Vec2 bomb_pos = GetPos();
room->frame_event.AddSmoke(this, meta->i->id(), bomb_pos);
ProcMolotorCocktailBomb(delay_time);
}
break;
@ -313,7 +309,9 @@ void Bullet::Check(float distance)
(
[this, &objects] (Human* hum, bool& stop)
{
if (hum != sender.Get() && !hum->dead && TestCollision(room, hum)) {
AabbCollider aabb_box;
hum->GetHitAabbBox(aabb_box);
if (hum != sender.Get() && !hum->dead && TestCollision(room, &aabb_box)) {
objects.insert(hum);
}
});
@ -345,13 +343,9 @@ void Bullet::Check(float distance)
}
}
void Bullet::ProcFragBomb(float delay_time)
void Bullet::ProcFragBomb(int delay_time)
{
if (sender.Get()) {
RoomObstacle* dummy_obstacle = nullptr;
if (delay_time > 0.0001) {
dummy_obstacle = room->CreateObstacle(0, 0, 0);
}
FragMiTask* task = new FragMiTask();
task->room = room;
task->sender.Attach(sender.Get());
@ -359,9 +353,8 @@ void Bullet::ProcFragBomb(float delay_time)
task->gun_meta = gun_meta;
task->meta = meta;
task->atk = GetAtk();
task->dummy_obstacle_uniid = dummy_obstacle ? dummy_obstacle->GetEntityUniId() : 0;
room->xtimer.AddDeadLineTimerAndAttach
(std::max(1, (int)(SERVER_FRAME_RATE * delay_time)),
(std::max(1, (int)(delay_time / FRAME_RATE_MS)),
a8::XParams()
.SetSender(task),
[] (const a8::XParams& param)
@ -379,12 +372,64 @@ void Bullet::ProcFragBomb(float delay_time)
}
}
void Bullet::ProcPosionGasBomb(float delay_time)
void Bullet::ProcPosionGasBomb(int delay_time)
{
if (sender.Get()) {
PosionGasMiTask* task = new PosionGasMiTask();
task->room = room;
task->sender.Attach(sender.Get());
task->bomb_pos = GetPos();
task->gun_meta = gun_meta;
task->meta = meta;
task->Initialzie();
room->xtimer.AddDeadLineTimerAndAttach
(delay_time / FRAME_RATE_MS,
a8::XParams()
.SetSender(task),
[] (const a8::XParams& param)
{
PosionGasMiTask* task = (PosionGasMiTask*)param.sender.GetUserData();
task->room->frame_event.AddExplosionEx
(task->sender,
task->meta->i->id(),
task->bomb_pos,
task->gun_meta->i->explosion_effect());
task->Active();
},
&room->timer_attacher.timer_list_
);
}
}
void Bullet::ProcMolotorCocktailBomb(float delay_time)
void Bullet::ProcMolotorCocktailBomb(int delay_time)
{
if (sender.Get()) {
MolotorCocktailMiTask* task = new MolotorCocktailMiTask();
task->room = room;
task->sender.Attach(sender.Get());
task->bomb_pos = GetPos();
task->gun_meta = gun_meta;
task->meta = meta;
task->Initialzie();
room->xtimer.AddDeadLineTimerAndAttach
(delay_time / FRAME_RATE_MS,
a8::XParams()
.SetSender(task),
[] (const a8::XParams& param)
{
MolotorCocktailMiTask* task = (MolotorCocktailMiTask*)param.sender.GetUserData();
task->room->frame_event.AddExplosionEx
(task->sender,
task->meta->i->id(),
task->bomb_pos,
task->gun_meta->i->explosion_effect());
task->Active();
},
&room->timer_attacher.timer_list_
);
}
}

View File

@ -43,9 +43,9 @@ protected:
void OnHit(std::set<Entity*>& objects);
void ProcBomb();
void ProcSmokeBomb();
void ProcFragBomb(float delay_time);
void ProcPosionGasBomb(float delay_time);
void ProcMolotorCocktailBomb(float delay_time);
void ProcFragBomb(int delay_time);
void ProcPosionGasBomb(int delay_time);
void ProcMolotorCocktailBomb(int delay_time);
bool IsBomb();
inline void MapServiceUpdate();
float GetAtk();

View File

@ -178,3 +178,9 @@ void Car::SyncPos()
room->grid_service->MoveCreature(this);
}
}
float Car::GetRadius()
{
abort();
return 0;
}

View File

@ -28,6 +28,7 @@ class Car : public Creature
void GetDown(Human* passenger);
void GetOn(Human* passenger);
void SyncPos();
virtual float GetRadius() override;
private:
int AllocSeat();

View File

@ -89,8 +89,6 @@ enum InventorySlot_e
IS_SMOKE = 6,
IS_HEALTHKIT = 7, //医疗包
IS_PAIN_KILLER = 8, //止痛药
IS_POSION_GAS_BOMB = 9,
IS_MOLOTOR_COCKTAIL = 10,
IS_1XSCOPE = 12,
IS_2XSCOPE = 13,
@ -98,6 +96,11 @@ enum InventorySlot_e
IS_8XSCOPE = 15,
IS_15XSCOPE = 16,
IS_POSION_GAS_BOMB = 17, //毒气弹
IS_MOLOTOR_COCKTAIL = 18, //燃烧瓶
IS_TRAP = 19, //陷井
IS_MINE = 20, //地雷
IS_END
};
@ -145,7 +148,18 @@ enum BuffEffectType_e
kBET_HunLuan = 23, //混乱,在烟雾弹中不自动瞄准
kBET_Fly = 24, //飞行中
kBET_Jump = 25, //跳伞中
kBET_IntervalAddBuff = 26, //持续掉血
//kBET_LastAddHp = 27, //持续加血
//kBET_OnceAddHp = 28, //加血
kBET_SummonHero = 29, //召唤英雄
//kBET_SummonHero = 30, //向前跳跃
kBET_Shield = 31, //护盾
kBET_Hide = 32, //隐身
kBET_CrazyMode = 33, //暴走模式
kBET_ShockWave = 34, //冲击波
kBET_Sprint = 35, //冲刺
kBET_SummonObstacle = 36, //召唤物件
kBET_FlashMove = 37, //瞬间移动
kBET_ThroughWall = 50, //穿墙
kBET_Driver = 51, //驾驶中
@ -355,6 +369,12 @@ enum GameChannel_e
kTouTiaoChannelId = 6006
};
enum PostBuffAction_e
{
kRemoveBuffByIdAction = 1,
kRemoveBuffByEffectAction = 2
};
const char* const PROJ_NAME_FMT = "game%d_gameserver";
const char* const PROJ_ROOT_FMT = "/data/logs/%s";
@ -368,7 +388,7 @@ const int SERVER_FRAME_RATE = 20;
const int SYNC_FRAME_RATE = 10;
const float FRAME_RATE_MS = 1000.0f / SERVER_FRAME_RATE;
const int MAX_WEAPON_NUM = 5;
const int MAX_WEAPON_NUM = 9;
const int MAX_SKIN_LV = 9;
const int GUN_SLOT1 = 1;

View File

@ -8,6 +8,7 @@
#include "skill.h"
#include "human.h"
#include "collider.h"
#include "roomobstacle.h"
void InternalShot(Creature* c,
MetaData::Equip* weapon_meta,
@ -18,6 +19,17 @@ void InternalShot(Creature* c,
float fly_distance,
bool is_tank_skin)
{
if (weapon_meta->i->_inventory_slot() == IS_TRAP ||
weapon_meta->i->_inventory_slot() == IS_MINE) {
MetaData::Buff * buff_meta = MetaMgr::Instance()->GetBuff(bullet_meta->i->buffid());
if (buff_meta) {
c->AddBuff(c,
buff_meta,
1
);
}
return;
}
for (auto& tuple : weapon_meta->bullet_born_offset) {
a8::Vec2 bullet_born_offset = a8::Vec2(std::get<0>(tuple), std::get<1>(tuple));
bullet_born_offset.Rotate(c->attack_dir.CalcAngle(a8::Vec2::UP));
@ -76,6 +88,15 @@ void InternalShot(Creature* c,
Creature::Creature():MoveableEntity()
{
weapons.reserve(MAX_WEAPON_NUM);
for (size_t i = 0; i < MAX_WEAPON_NUM; ++i) {
auto& weapon = a8::FastAppend(weapons);
weapon.weapon_idx = i;
weapon.weapon_id = 0;
weapon.weapon_lv = 0;
weapon.ammo = 0;
}
weak_ptr_chunk_.Set(this);
inventory_[IS_1XSCOPE] = 1;
@ -203,17 +224,41 @@ void Creature::MustBeAddBuff(Creature* caster, int buff_id)
void Creature::RemoveBuffById(int buff_id)
{
std::vector<MetaData::Buff*> removed_buffs;
for (auto itr = buff_list_.begin(); itr != buff_list_.end(); ++itr) {
const Buff& buff = *itr;
if (buff.meta->i->buff_id() == buff_id) {
if (buff_effect_[buff.meta->i->buff_effect()] == &(*itr)) {
buff_effect_[buff.meta->i->buff_effect()] = nullptr;
}
removed_buffs.push_back(buff.meta);
OnBuffRemove(buff);
buff_list_.erase(itr);
break;
}
}
for (MetaData::Buff* buff_meta : removed_buffs) {
for (const auto& tuple : buff_meta->post_remove_action) {
switch (std::get<0>(tuple)) {
case kRemoveBuffByIdAction:
{
for (int buff_id :std::get<1>(tuple)) {
RemoveBuffById(buff_id);
}
}
break;
case kRemoveBuffByEffectAction:
{
for (int buff_effect :std::get<1>(tuple)) {
RemoveBuffByEffectId(buff_effect);
}
}
break;
default:
break;
}
}
}
RecalcBuffAttr();
#ifdef DEBUG
SendDebugMsg(a8::Format("移除buff_id:%d",
@ -239,7 +284,8 @@ void Creature::RecalcBuffAttr()
buff_attr_rate_ = {};
for (auto& buff : buff_list_) {
if (buff.meta->i->buff_effect() == kBET_ChgAttr ||
buff.meta->i->buff_effect() == kBET_Car) {
buff.meta->i->buff_effect() == kBET_Car ||
buff.meta->i->buff_effect() == kBET_CrazyMode) {
int attr_type = (int)buff.meta->param1;
int calc_type = (int)buff.meta->param2;
if (IsValidHumanAttr(attr_type)) {
@ -261,8 +307,9 @@ void Creature::OnBuffRemove(const Buff& buff)
void Creature::RemoveBuffByEffectId(int buff_effect_id)
{
Buff* buff = GetBuffByEffectId(buff_effect_id);
if (buff) {
while (buff) {
RemoveBuffById(buff->meta->i->buff_id());
buff = GetBuffByEffectId(buff_effect_id);
}
}
@ -434,7 +481,11 @@ bool Creature::CanUseSkill(int skill_id)
return skill->GetLeftTime() <= 0;
}
void Creature::DoSkill(int skill_id, int target_id, const a8::Vec2& skill_dir, const a8::Vec2& target_pos)
void Creature::DoSkill(int skill_id,
int target_id,
const a8::Vec2& skill_dir,
float skill_distance,
const a8::Vec2& target_pos)
{
DoSkillPreProc(skill_id, target_id, target_pos);
Skill* skill = GetSkill(skill_id);
@ -443,6 +494,7 @@ void Creature::DoSkill(int skill_id, int target_id, const a8::Vec2& skill_dir, c
skill_target_id_ = target_id;
skill_target_pos_ = target_pos;
skill_dir_ = skill_dir;
skill_distance_ = skill_distance;
curr_skill_ = skill;
playing_skill = true;
CurrentSkill()->last_use_frameno = room->GetFrameNo();
@ -609,6 +661,7 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff)
switch (buff->meta->i->buff_effect()) {
case kBET_ChgAttr:
case kBET_Car:
case kBET_CrazyMode:
{
RecalcBuffAttr();
if (buff->meta->i->buff_effect() == kBET_Car) {
@ -661,19 +714,26 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff)
if (caster == this) {
abort();
}
float target_distance = caster->GetPos().Distance(GetPos());
if (target_distance <= 0.000001f) {
SetPos(caster->GetPos());
target_pos = caster->GetPos();
} else {
if (target_distance <= buff->meta->param3) {
if (caster->GetEntitySubType() == EST_Android) {
float target_distance = caster->GetPos().Distance(GetPos());
if (target_distance <= 0.000001f) {
SetPos(caster->GetPos());
target_pos = caster->GetPos();
} else {
move_dir = caster->GetPos() - GetPos();
move_dir.Normalize();
target_pos = GetPos() + move_dir * (target_distance - buff->meta->param3);
if (target_distance <= buff->meta->param3) {
SetPos(caster->GetPos());
target_pos = caster->GetPos();
} else {
move_dir = caster->GetPos() - GetPos();
move_dir.Normalize();
target_pos = GetPos() + move_dir * (target_distance - buff->meta->param3);
}
}
} else {
caster->skill_dir_.Normalize();
target_pos = caster->GetPos() + caster->skill_dir_ * caster->skill_distance_;
move_dir = target_pos - GetPos();
move_dir.Normalize();
}
}
break;
@ -748,26 +808,57 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff)
{
if (caster->GetEntityType() == ET_Player) {
room->xtimer.AddDeadLineTimerAndAttach
(
SERVER_FRAME_RATE * buff->meta->param1,
a8::XParams()
.SetSender(this)
.SetParam1(caster)
.SetParam2(buff->meta->param2)
.SetParam3(((Human*)caster)->CurrentSkill()->meta),
[] (const a8::XParams& param)
{
Human* hum = (Human*)param.sender.GetUserData();
Human* caster = (Human*)param.param1.GetUserData();
int buff_id = param.param2;
MetaData::Skill* skill = (MetaData::Skill*)param.param3.GetUserData();
(
SERVER_FRAME_RATE * buff->meta->param1,
a8::XParams()
.SetSender(this)
.SetParam1(caster)
.SetParam2(buff->meta->param2)
.SetParam3(((Creature*)caster)->CurrentSkill()->meta),
[] (const a8::XParams& param)
{
Human* hum = (Human*)param.sender.GetUserData();
Human* caster = (Human*)param.param1.GetUserData();
int buff_id = param.param2;
MetaData::Skill* skill = (MetaData::Skill*)param.param3.GetUserData();
MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id);
if (buff_meta && skill == caster->CurrentSkill()->meta && caster) {
hum->AddBuff(caster, buff_meta, 1, skill);
}
},
&buff->xtimer_attacher.timer_list_);
}
}
break;
case kBET_IntervalAddBuff:
{
room->xtimer.AddRepeatTimerAndAttach
(
FRAME_RATE_MS / buff->meta->param1,
a8::XParams()
.SetSender(this)
.SetParam1(caster)
.SetParam2(buff->meta)
.SetParam3(((Creature*)caster)->CurrentSkill()->meta),
[] (const a8::XParams& param)
{
Human* hum = (Human*)param.sender.GetUserData();
Human* caster = (Human*)param.param1.GetUserData();
MetaData::Buff* mother_buff_meta = (MetaData::Buff*)param.param2.GetUserData();
MetaData::Skill* skill = (MetaData::Skill*)param.param3.GetUserData();
for (int buff_id : mother_buff_meta->param2_int_list) {
MetaData::Buff* buff_meta = MetaMgr::Instance()->GetBuff(buff_id);
if (buff_meta && skill == caster->CurrentSkill()->meta && caster) {
hum->AddBuff(caster, buff_meta, 1, skill);
}
},
&buff->xtimer_attacher.timer_list_);
}
}
},
&buff->xtimer_attacher.timer_list_);
}
break;
case kBET_SummonHero:
{
}
break;
case kBET_Shield:
@ -775,6 +866,28 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff)
}
break;
case kBET_Hide:
{
}
break;
case kBET_SummonObstacle:
{
SummonObstacle(buff->meta->param1, GetPos());
}
break;
case kBET_Sprint:
{
}
break;
case kBET_FlashMove:
{
a8::Vec2 old_pos = GetPos();
a8::Vec2 new_pos = GetPos() + skill_dir_ * skill_distance_;
SetPos(new_pos);
}
break;
default:
{
}
@ -1194,3 +1307,90 @@ void Creature::CheckSpecObject()
}
#endif
}
RoomObstacle* Creature::SummonObstacle(int id, const a8::Vec2& pos)
{
RoomObstacle* obstacle = room->CreateObstacle(id, pos.x, pos.y);
if (obstacle) {
obstacle->master.Attach(this);
room->xtimer.AddRepeatTimerAndAttach
(
SERVER_FRAME_RATE,
a8::XParams()
.SetSender(obstacle),
[] (const a8::XParams& param)
{
RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData();
obstacle->ActiveTimerFunc();
},
&obstacle->xtimer_attacher.timer_list_
);
room->xtimer.AddRepeatTimerAndAttach
(
SERVER_FRAME_RATE,
a8::XParams()
.SetSender(obstacle),
[] (const a8::XParams& param)
{
RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData();
obstacle->UpdateTimerFunc();
},
&obstacle->xtimer_attacher.timer_list_
);
} else {
abort();
}
return obstacle;
}
bool Creature::CollisonDetection()
{
#if 0
if (room->OverBorder(GetPos(), GetRadius())){
return true;
}
if (HasBuffEffect(kBET_ThroughWall) ||
HasBuffEffect(kBET_Fly)) {
return false;
}
std::set<ColliderComponent*> colliders;
room->map_service->GetColliders(room, GetX(), GetY(), colliders);
AabbCollider aabb_box;
GetAabbBox(aabb_box);
for (ColliderComponent* collider : colliders) {
switch (collider->owner->GetEntityType()) {
case ET_Obstacle:
{
Obstacle* obstacle = (Obstacle*)collider->owner;
if (!obstacle->IsDead(room) &&
(
(collider->type == CT_Aabb && aabb_box.Intersect((ColliderComponent*)collider)) ||
(collider->type == CT_Circle && self_collider_->Intersect((ColliderComponent*)collider))
)) {
return true;
}
}
break;
case ET_Building:
{
if (
(
(collider->type == CT_Aabb && aabb_box.Intersect((ColliderComponent*)collider)) ||
(collider->type == CT_Circle && self_collider_->Intersect((ColliderComponent*)collider))
)
) {
return true;
}
}
break;
default:
break;
}
}
#endif
return false;
}

View File

@ -15,6 +15,7 @@ namespace MetaData
struct xtimer_list;
class Skill;
class Obstacle;
class RoomObstacle;
class Creature : public MoveableEntity
{
public:
@ -74,7 +75,12 @@ class Creature : public MoveableEntity
const a8::Vec2& target_pos,
std::set<Creature*>& target_list);
virtual bool CanUseSkill(int skill_id);
void DoSkill(int skill_id, int target_id, const a8::Vec2& skill_dir, const a8::Vec2& target_pos);
void DoSkill(int skill_id,
int target_id,
const a8::Vec2& skill_dir,
float skill_distance,
const a8::Vec2& target_pos
);
void ResetSkill();
Skill* CurrentSkill();
MetaData::SkillPhase* GetCurrSkillPhase();
@ -113,6 +119,8 @@ class Creature : public MoveableEntity
virtual void _UpdateMove(int speed) {};
void CheckSpecObject();
RoomObstacle* SummonObstacle(int id, const a8::Vec2& pos);
bool CollisonDetection();
private:
@ -154,6 +162,7 @@ private:
Skill* curr_skill_ = nullptr;
int skill_target_id_ = 0;
a8::Vec2 skill_target_pos_;
float skill_distance_ = 0.0f;
std::map<int, Skill*> skill_hash_;
std::map<int, Skill*> passive_skill_hash_;
std::array<int, IS_END - 1> inventory_ = {};

View File

@ -22,6 +22,9 @@ class Entity
virtual void FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data) {};
virtual float GetSpeed() { return 1.0f;};
virtual void GetAabbBox(AabbCollider& aabb_box);
virtual void GetHitAabbBox(AabbCollider& aabb_box) { GetAabbBox(aabb_box);};
virtual float GetRadius() { return 0;};
virtual float GetHitRadius() { return GetRadius();};
virtual void GetCircleBox(CircleCollider& circle_box);
virtual bool IsDead(Room* room) { return false;};
virtual long long GetDeadFrameNo(Room* room) { return 0;};

View File

@ -5,13 +5,101 @@
#include "player.h"
#include "metadata.h"
#include "metamgr.h"
#include "gridservice.h"
#include "creature.h"
#include "obstacle.h"
void FragMiTask::Done()
{
if (sender.Get()) {
room->frame_event.AddExplosionEx(sender,
meta->i->id(),
bomb_pos,
gun_meta->i->explosion_effect());
if (!sender.Get()) {
return;
}
room->frame_event.AddExplosionEx(sender,
meta->i->id(),
bomb_pos,
gun_meta->i->explosion_effect());
std::set<GridCell*> grid_list;
sender.Get()->room->grid_service->GetAllCellsByXy
(
sender.Get()->room,
bomb_pos.x,
bomb_pos.y,
grid_list
);
std::set<Creature*> objects;
sender.Get()->room->grid_service->TouchCreatures
(
sender.Get()->room->GetRoomIdx(),
grid_list,
[this, &objects] (Creature* c, bool& stop)
{
if (sender.Get()->IsProperTarget(c)) {
if (bomb_pos.Distance(c->GetPos()) < meta->i->explosion_range()) {
objects.insert(c);
}
}
}
);
std::set<Entity*> entitys;
sender.Get()->room->grid_service->TouchAllLayerEntityList
(
sender.Get()->room->GetRoomIdx(),
grid_list,
[this, &entitys] (Entity* entity, bool& stop)
{
}
);
for (auto& target : objects) {
if (target->HasBuffEffect(kBET_Invincible) ||
target->HasBuffEffect(kBET_AdPlaying)) {
continue;
}
if (sender.Get()->room->GetRoomMode() == kZombieMode &&
sender.Get()->GetRace() == target->GetRace()) {
continue;
}
if (!target->dead) {
float dmg = GetAtk() * (1 + sender.Get()->GetAttrRate(kHAT_Atk)) +
sender.Get()->GetAttrAbs(kHAT_Atk);
float def = target->ability.def * (1 + target->GetAttrRate(kHAT_Def)) +
target->GetAttrAbs(kHAT_Def);
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
finaly_dmg = std::max(finaly_dmg, 0.0f);
target->DecHP(finaly_dmg,
sender.Get()->GetEntityUniId(),
sender.Get()->GetName(),
gun_meta->i->id());
}
}
for (auto& target : entitys) {
if (target->GetEntityType() != ET_Obstacle) {
continue;
}
Obstacle* obstacle = (Obstacle*)target;
if (!obstacle->IsDead(room) &&
obstacle->Attackable() &&
!obstacle->IsTerminatorAirDropBox(room)) {
float dmg = GetAtk() * (1 + sender.Get()->GetAttrRate(kHAT_Atk)) +
sender.Get()->GetAttrAbs(kHAT_Atk);
float def = 0;
float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K);
obstacle->SetHealth(room, std::max(0.0f, obstacle->GetHealth(room) - finaly_dmg));
if (obstacle->GetHealth(room) <= 0.01f) {
obstacle->Die(room);
}
if (obstacle->IsDead(room)) {
if (obstacle->meta->i->damage_dia() > 0.01f &&
obstacle->meta->i->damage() > 0.01f) {
#if 0
obstacle->Explosion(this);
#endif
}
sender.Get()->DropItems(obstacle);
}
obstacle->BroadcastFullState(room);
}
}
}

View File

@ -19,7 +19,6 @@ class FragMiTask : public MicroTask
MetaData::Equip* gun_meta = nullptr;
MetaData::Equip* meta = nullptr;
float atk = 0;
int dummy_obstacle_uniid = 0;
void Done();
float GetAtk() { return atk; }

View File

@ -187,3 +187,9 @@ void Hero::RecalcSelfCollider()
self_collider_->pos = a8::Vec2();
self_collider_->rad = meta->i->radius();
}
float Hero::GetRadius()
{
return meta->i->radius();
}

View File

@ -30,6 +30,7 @@ public:
virtual void GetAabbBox(AabbCollider& aabb_box) override;
virtual float GetSpeed() override;
virtual float GetRadius() override;
protected:
virtual void _UpdateMove(int speed) override;

View File

@ -43,14 +43,6 @@ Human::Human():Creature()
default_weapon.ammo = 1;
default_weapon.meta = MetaMgr::Instance()->GetEquip(default_weapon.weapon_id);
default_weapon.Recalc();
weapons.reserve(MAX_WEAPON_NUM);
for (size_t i = 0; i < MAX_WEAPON_NUM; ++i) {
auto& weapon = a8::FastAppend(weapons);
weapon.weapon_idx = i;
weapon.weapon_id = 0;
weapon.weapon_lv = 0;
weapon.ammo = 0;
}
for (int i = 0; i < kSkinNum; ++i) {
Skin& skin = a8::FastAppend(skins);
skin.skin_id = 0;
@ -637,11 +629,6 @@ void Human::FindPathInMapService()
SetPos(old_pos);
}
float Human::GetRadius()
{
return meta->i->radius();
}
float Human::GetHP()
{
return ability.hp;
@ -1886,43 +1873,6 @@ void Human::WinExp(Human* sender, int exp)
}
}
RoomObstacle* Human::SummonObstacle(int id, const a8::Vec2& pos)
{
RoomObstacle* obstacle = room->CreateObstacle(id, pos.x, pos.y);
if (obstacle) {
obstacle->master.Attach(this);
room->xtimer.AddRepeatTimerAndAttach
(
SERVER_FRAME_RATE,
a8::XParams()
.SetSender(obstacle),
[] (const a8::XParams& param)
{
RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData();
obstacle->ActiveTimerFunc();
},
&obstacle->xtimer_attacher.timer_list_
);
room->xtimer.AddRepeatTimerAndAttach
(
SERVER_FRAME_RATE,
a8::XParams()
.SetSender(obstacle),
[] (const a8::XParams& param)
{
RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData();
obstacle->UpdateTimerFunc();
},
&obstacle->xtimer_attacher.timer_list_
);
} else {
abort();
}
return obstacle;
}
void Human::_InternalUpdateMove(float speed)
{
float nx = move_dir.x * speed;
@ -3413,3 +3363,33 @@ void Human::DoSkillPostProc(bool used, int skill_id, int target_id, const a8::Ve
OnAttack();
}
}
float Human::GetRadius()
{
return meta->i->radius();
}
float Human::GetHitRadius()
{
return meta->i->hit_radius();
}
void Human::GetHitAabbBox(AabbCollider& aabb_box)
{
if (!meta) {
abort();
}
aabb_box.active = true;
aabb_box.owner = this;
if (GetCar() && GetCar()->IsDriver(this)) {
aabb_box._min.x = -GetCar()->meta->i->rad();
aabb_box._min.y = -GetCar()->meta->i->rad();
aabb_box._max.x = GetCar()->meta->i->rad();
aabb_box._max.y = GetCar()->meta->i->rad();
} else {
aabb_box._min.x = -GetHitRadius();
aabb_box._min.y = -GetHitRadius();
aabb_box._max.x = GetHitRadius();
aabb_box._max.y = GetHitRadius();
}
}

View File

@ -143,7 +143,10 @@ class Human : public Creature
void FillMFObjectLess(Room* room, Human* hum, cs::MFPlayerFull* full_data);
virtual void FillMFObjectFull(Room* room, Human* hum, cs::MFObjectFull* full_data) override;
virtual void FillMFPlayerStats(cs::MFPlayerStats* stats);
virtual float GetRadius() override;
virtual float GetHitRadius() override;
virtual void GetAabbBox(AabbCollider& aabb_box) override;
virtual void GetHitAabbBox(AabbCollider& aabb_box) override;
virtual bool IsDead(Room* room) override;
virtual long long GetDeadFrameNo(Room* room) override;
void FillItemList(::google::protobuf::RepeatedPtrField<::cs::MFPair>* pb_item_list);
@ -153,7 +156,6 @@ class Human : public Creature
virtual void RecalcSelfCollider() override;
bool IsCollisionInMapService();
void FindPathInMapService();
float GetRadius();
float GetHP();
float GetMaxHP();
void BeKill(int killer_id, const std::string& killer_name, int weapon_id);
@ -238,7 +240,6 @@ class Human : public Creature
int GetSeat() { return seat_; }
void SetSeat(int seat) { seat_ = seat; }
void DeadDrop();
RoomObstacle* SummonObstacle(int id, const a8::Vec2& pos);
virtual std::string GetName() override { return name;};
protected:

View File

@ -521,6 +521,39 @@ namespace MetaData
immune_buffeffect.insert(a8::XValue(str));
}
}
{
std::vector<std::string> strings;
a8::Split(i->buff_param2(), strings, ':');
for (auto& str : strings) {
param2_int_list.push_back(a8::XValue(str).GetInt());
}
}
{
std::vector<std::string> strings;
a8::Split(i->post_remove_action(), strings, '|');
for (auto& str : strings) {
std::vector<std::string> strings2;
a8::Split(str, strings2, ':');
if (strings2.size() > 2) {
std::vector<std::string> strings3;
a8::Split(strings2[1], strings3, ';');
if (strings2[0] == "remove_buff_by_id" ||
strings2[0] == "remove_buff_by_effect") {
auto& action = a8::FastAppend(post_remove_action);
if (strings2[0] == "remove_buff_by_id") {
std::get<0>(action) = kRemoveBuffByIdAction;
} else if (strings2[0] == "remove_buff_by_effect") {
std::get<0>(action) = kRemoveBuffByEffectAction;
}
for (auto& str3 : strings3) {
if (!str3.empty()) {
std::get<1>(action).push_back(a8::XValue(str3));
}
}
}
}
}
}
}
bool Buff::EffectCanStack()

View File

@ -169,6 +169,8 @@ namespace MetaData
float param2 = 0.0f;
float param3 = 0.0f;
float param4 = 0.0f;
std::vector<int> param2_int_list;
std::vector<std::tuple<int, std::vector<int>>> post_remove_action;
std::set<int> immune_buffeffect;
};

View File

@ -5,37 +5,73 @@
#include "player.h"
#include "metadata.h"
void MolotorCocktailMiTask::Initialzie()
{
sender.Get()->room->grid_service->GetAllCellsByXy
(
sender.Get()->room,
bomb_pos.x,
bomb_pos.y,
grid_list
);
}
void MolotorCocktailMiTask::Active()
{
room->xtimer.AddRepeatTimerAndAttach
(SERVER_FRAME_RATE / 2,
a8::XParams()
.SetSender(this),
[] (const a8::XParams& param)
{
MolotorCocktailMiTask* task = (MolotorCocktailMiTask*)param.sender.GetUserData();
task->Check();
},
&timer_attacher.timer_list_);
room->xtimer.AddDeadLineTimerAndAttach
(SERVER_FRAME_RATE * meta->i->time(),
a8::XParams()
.SetSender(this),
[] (const a8::XParams& param)
{
},
&timer_attacher.timer_list_,
[] (const a8::XParams& param)
{
MolotorCocktailMiTask* task = (MolotorCocktailMiTask*)param.sender.GetUserData();
task->Done();
delete task;
}
);
}
void MolotorCocktailMiTask::Check()
{
{
std::list<Player*> deleted_hums;
for (auto& hum : player_set) {
if (bomb_pos.Distance(hum->GetPos()) > gun_meta->i->bullet_rad() + hum->meta->i->radius()) {
hum->RemoveBuffByEffectId(kBET_HunLuan);
deleted_hums.push_back(hum);
}
}
for (auto& hum : deleted_hums) {
player_set.erase(hum);
}
}
room->TouchPlayerList
(a8::XParams(),
[this] (Player* hum, a8::XParams&) -> bool
{
if (bomb_pos.Distance(hum->GetPos()) < gun_meta->i->bullet_rad() + hum->meta->i->radius()) {
if (!hum->HasBuffEffect(kBET_HunLuan)) {
hum->AddBuff(nullptr, buff_meta, 1, nullptr);
player_set.insert(hum);
if (sender.Get()) {
std::set<Creature*> objects;
sender.Get()->room->grid_service->TouchCreatures
(
sender.Get()->room->GetRoomIdx(),
grid_list,
[this, &objects] (Creature* c, bool& stop)
{
if (sender.Get()->IsProperTarget(c)) {
if (bomb_pos.Distance(c->GetPos()) < meta->i->explosion_range()) {
objects.insert(c);
}
}
}
return true;
});
);
for (Creature* target : objects) {
if (!target->GetBuffById(meta->i->buffid())) {
target->MustBeAddBuff(sender.Get(), meta->i->buffid());
}
}
}
}
void MolotorCocktailMiTask::Done()
{
for (auto& hum : player_set) {
hum->RemoveBuffByEffectId(kBET_HunLuan);
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "microtask.h"
#include "gridcell.h"
namespace MetaData
{
@ -15,10 +16,13 @@ class MolotorCocktailMiTask : public MicroTask
public:
Room* room = nullptr;
a8::Vec2 bomb_pos;
std::set<Player*> player_set;
MetaData::Buff* buff_meta = nullptr;
CreatureWeakPtr sender;
MetaData::Equip* gun_meta = nullptr;
MetaData::Equip* meta = nullptr;
std::set<GridCell*> grid_list;
void Initialzie();
void Active();
void Check();
void Done();
};

View File

@ -393,7 +393,7 @@ void Player::UpdateUseSkill()
if (HasBuffEffect(kBET_Vertigo)) {
return;
}
DoSkill(use_skill_id, skill_target_id, skill_dir, a8::Vec2());
DoSkill(use_skill_id, skill_target_id, skill_dir, skill_distance, a8::Vec2());
use_skill = false;
}
@ -439,7 +439,7 @@ void Player::Shot()
int slot_id = curr_weapon->meta->i->_inventory_slot();
//扔完手雷,如无手雷则优先换武器1>武器2
switch (slot_id) {
case 5:
case IS_FRAG:
{
//手雷
if (curr_weapon->ammo <= 0) {
@ -462,7 +462,7 @@ void Player::Shot()
SyncAroundPlayers(__FILE__, __LINE__, __func__);
}
break;
case 6:
case IS_SMOKE:
{
//烟雾弹
if (curr_weapon->ammo <= 0) {
@ -1130,6 +1130,7 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg)
} else {
skill_dir = a8::Vec2();
}
skill_distance = msg.skill_distance();
} else {
use_skill = false;
}

View File

@ -61,6 +61,7 @@ class Player : public Human
int use_skill_id = 0;
int skill_target_id = 0;
a8::Vec2 skill_dir;
float skill_distance = 0.0f;
bool get_down = false;
int get_on = 0;

View File

@ -5,37 +5,73 @@
#include "player.h"
#include "metadata.h"
void PosionGasMiTask::Initialzie()
{
sender.Get()->room->grid_service->GetAllCellsByXy
(
sender.Get()->room,
bomb_pos.x,
bomb_pos.y,
grid_list
);
}
void PosionGasMiTask::Active()
{
room->xtimer.AddRepeatTimerAndAttach
(SERVER_FRAME_RATE / 2,
a8::XParams()
.SetSender(this),
[] (const a8::XParams& param)
{
PosionGasMiTask* task = (PosionGasMiTask*)param.sender.GetUserData();
task->Check();
},
&timer_attacher.timer_list_);
room->xtimer.AddDeadLineTimerAndAttach
(SERVER_FRAME_RATE * meta->i->time(),
a8::XParams()
.SetSender(this),
[] (const a8::XParams& param)
{
},
&timer_attacher.timer_list_,
[] (const a8::XParams& param)
{
PosionGasMiTask* task = (PosionGasMiTask*)param.sender.GetUserData();
task->Done();
delete task;
}
);
}
void PosionGasMiTask::Check()
{
{
std::list<Player*> deleted_hums;
for (auto& hum : player_set) {
if (bomb_pos.Distance(hum->GetPos()) > gun_meta->i->bullet_rad() + hum->meta->i->radius()) {
hum->RemoveBuffByEffectId(kBET_HunLuan);
deleted_hums.push_back(hum);
}
}
for (auto& hum : deleted_hums) {
player_set.erase(hum);
}
}
room->TouchPlayerList
(a8::XParams(),
[this] (Player* hum, a8::XParams&) -> bool
{
if (bomb_pos.Distance(hum->GetPos()) < gun_meta->i->bullet_rad() + hum->meta->i->radius()) {
if (!hum->HasBuffEffect(kBET_HunLuan)) {
hum->AddBuff(nullptr, buff_meta, 1, nullptr);
player_set.insert(hum);
if (sender.Get()) {
std::set<Creature*> objects;
sender.Get()->room->grid_service->TouchCreatures
(
sender.Get()->room->GetRoomIdx(),
grid_list,
[this, &objects] (Creature* c, bool& stop)
{
if (sender.Get()->IsProperTarget(c)) {
if (bomb_pos.Distance(c->GetPos()) < meta->i->explosion_range()) {
objects.insert(c);
}
}
}
return true;
});
);
for (Creature* target : objects) {
if (!target->GetBuffById(meta->i->buffid())) {
target->MustBeAddBuff(sender.Get(), meta->i->buffid());
}
}
}
}
void PosionGasMiTask::Done()
{
for (auto& hum : player_set) {
hum->RemoveBuffByEffectId(kBET_HunLuan);
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "microtask.h"
#include "gridcell.h"
namespace MetaData
{
@ -15,10 +16,13 @@ class PosionGasMiTask : public MicroTask
public:
Room* room = nullptr;
a8::Vec2 bomb_pos;
std::set<Player*> player_set;
MetaData::Buff* buff_meta = nullptr;
CreatureWeakPtr sender;
MetaData::Equip* gun_meta = nullptr;
MetaData::Equip* meta = nullptr;
std::set<GridCell*> grid_list;
void Initialzie();
void Active();
void Check();
void Done();
};

View File

@ -157,7 +157,10 @@ void RoomObstacle::UpdateTimerFunc()
Explosion();
Die(room);
BroadcastFullState(room);
room->xtimer.DeleteTimer(room->xtimer.GetRunningTimer());
}
} else {
room->xtimer.DeleteTimer(room->xtimer.GetRunningTimer());
}
}

View File

@ -467,7 +467,17 @@ void ZombieModeAI::DoShot()
void ZombieModeAI::DoSkill(int skill_id)
{
Human* myself = (Human*)owner;
myself->DoSkill(skill_id, node_->target.Get()->GetEntityUniId(), a8::Vec2(), node_->target.Get()->GetPos());
a8::Vec2 skill_dir;
float skill_distance = node_->target.Get()->GetPos().Distance(myself->GetPos());
if (fabs(skill_distance) > 0.00001f) {
skill_dir = node_->target.Get()->GetPos() - myself->GetPos();
skill_dir.Normalize();
}
myself->DoSkill(skill_id,
node_->target.Get()->GetEntityUniId(),
a8::Vec2(),
skill_distance,
node_->target.Get()->GetPos());
}
int ZombieModeAI::GetAttackTimes()

View File

@ -106,7 +106,7 @@ message Equip
optional string param2 = 44;
optional int32 reloadtype = 46;
optional float Recoil_force = 47;
optional float missiles_time = 48;
optional int32 missiles_time = 48;
optional int32 heroid = 49;
optional string inventory_slot = 31; //
@ -146,6 +146,7 @@ message Player
optional int32 revive_time = 22;
optional string name = 23;
optional int32 normal_skill = 24;
optional float hit_radius = 25;
}
message Robot
@ -205,6 +206,7 @@ message Buff
required float duration_time = 10;
optional float buff_valueup = 11;
required string immune_buffeffect_list = 12;
optional string post_remove_action = 13;
}
message Drop