diff --git a/server/gameserver/android.ai.cc b/server/gameserver/android.ai.cc index 3c0bd22..d675bce 100644 --- a/server/gameserver/android.ai.cc +++ b/server/gameserver/android.ai.cc @@ -429,6 +429,9 @@ void AndroidNewAI::UpdateNewAI() abort(); } } + if (hum->playing_skill) { + hum->UpdateSkill(); + } ++node_.exec_frame_num; hum->shot_hold = false; switch (node_.main_state) { diff --git a/server/gameserver/buff.cc b/server/gameserver/buff.cc index 2b89e6f..0659eca 100644 --- a/server/gameserver/buff.cc +++ b/server/gameserver/buff.cc @@ -6,6 +6,7 @@ #include "room.h" #include "collider.h" #include "skill.h" +#include "incubator.h" int Buff::GetLeftTime() { @@ -145,6 +146,24 @@ void Buff::ProcSummonHero(Creature* caster) } } +void Buff::ProcBeRecycle(Creature* caster) +{ + owner->room->xtimer.AddRepeatTimerAndAttach + ( + SERVER_FRAME_RATE * 2, + a8::XParams() + .SetSender(this), + [] (const a8::XParams& param) + { + Buff* buff = (Buff*)param.sender.GetUserData(); + if (buff->owner->IsHuman()) { + buff->owner->room->GetIncubator()->RecycleAndroid((Human*)buff->owner); + } + }, + &xtimer_attacher.timer_list_ + ); +} + bool Buff::NeedSync(Human* hum) { return !meta->i->only_server() || !(meta->i->only_self() && owner == hum); diff --git a/server/gameserver/buff.h b/server/gameserver/buff.h index bcf9c29..bc3c860 100644 --- a/server/gameserver/buff.h +++ b/server/gameserver/buff.h @@ -36,6 +36,7 @@ class Buff void ProcIntervalAddBuff(Creature* caster); void ProcBatchAddBuff(Creature* caster); void ProcSummonHero(Creature* caster); + void ProcBeRecycle(Creature* caster); private: void InternalTimerAddBuff(Creature* caster); diff --git a/server/gameserver/bullet.cc b/server/gameserver/bullet.cc index 99050e4..6c2b6de 100644 --- a/server/gameserver/bullet.cc +++ b/server/gameserver/bullet.cc @@ -75,6 +75,11 @@ void Bullet::OnHit(std::set& objects) #if 0 sender->stats.damage_amount_out += finaly_dmg; #endif +#ifdef DEBUG + if (App::Instance()->HasFlag(1) && hum->IsPlayer()) { + continue; + } +#endif hum->DecHP(finaly_dmg, sender.Get()->GetEntityUniId(), sender.Get()->GetName(), gun_meta->i->id()); #ifdef DEBUG sender.Get()->SendDebugMsg(a8::Format("bullet weapon_id:%d atk:%f", @@ -417,6 +422,18 @@ void Bullet::ProcPosionGasBomb(int delay_time) void Bullet::ProcMolotorCocktailBomb(int delay_time) { if (sender.Get()) { + #if 1 + a8::Vec2 old_buff_vec2_param1 = sender.Get()->buff_vec2_param1; + sender.Get()->buff_vec2_param1 = GetPos(); + MetaData::Buff * buff_meta = MetaMgr::Instance()->GetBuff(gun_meta->i->buffid()); + if (buff_meta) { + sender.Get()->AddBuff(sender.Get(), + buff_meta, + 1 + ); + } + sender.Get()->buff_vec2_param1 = old_buff_vec2_param1; + #else MolotorCocktailMiTask* task = new MolotorCocktailMiTask(); task->room = room; task->sender.Attach(sender.Get()); @@ -442,5 +459,6 @@ void Bullet::ProcMolotorCocktailBomb(int delay_time) }, &room->timer_attacher.timer_list_ ); + #endif } } diff --git a/server/gameserver/constant_export.h b/server/gameserver/constant_export.h index 87df2f9..cfa4968 100644 --- a/server/gameserver/constant_export.h +++ b/server/gameserver/constant_export.h @@ -9,6 +9,8 @@ const int kRecoilBuffId = 7005; const int kInGrassBuffId = 7006; const int kInWaterBuffId = 7007; const int kInIceBuffId = 7008; +const int kBeRecycleBuffId = 7009; +const int kTraceBuffId = 7011; enum BuffEffectType_e { @@ -59,6 +61,8 @@ enum BuffEffectType_e kBET_InWater = 57, //在水里 kBET_InIce = 58, //在冰里 kBET_BatchAddBuff = 60, //批量添加buff + kBET_BeRecycle = 61, //待回收 + kBET_Trace = 62, //追踪玩家 kBET_End }; diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index db32d7d..483a4ba 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -146,9 +146,11 @@ void Creature::AddBuff(Creature* caster, int skill_lv, MetaData::Skill* buff_skill_meta) { + #if 0 if (GetBuffById(buff_meta->i->buff_id())) { return; } + #endif if (IsImmuneBuffEffect(buff_meta->i->buff_effect())) { return; } @@ -484,6 +486,12 @@ bool Creature::CanUseSkill(int skill_id) if (!skill) { return false; } + if (dead) { + return false; + } + if (playing_skill) { + return false; + } return skill->GetCurrTimes() > 0; } @@ -513,7 +521,10 @@ void Creature::DoSkill(int skill_id, std::set target_list; SelectSkillTargets(CurrentSkill(), GetPos(), target_list); TriggerBuff(CurrentSkill(), target_list, kBTT_UseSkill); - UpdateSkill(); + if (!CurrentSkill()->meta->phases.empty() && + CurrentSkill()->meta->phases[0].time_offset <= 0) { + UpdateSkill(); + } } else { Entity* entity = room->GetEntityByUniId(skill_target_id_); if (entity && entity->IsEntityType(ET_Player)) { @@ -564,7 +575,7 @@ void Creature::ResetSkill() void Creature::UpdateSkill() { - if (CurrentSkill()) { + if (CurrentSkill() && !dead) { if (curr_skill_phase < CurrentSkill()->meta->phases.size()) { MetaData::SkillPhase* phase = &CurrentSkill()->meta->phases[curr_skill_phase]; if (phase->time_offset >= CurrentSkill()->GetPassedTime()) { @@ -574,6 +585,8 @@ void Creature::UpdateSkill() } else { playing_skill = false; } + } else { + playing_skill = false; } } @@ -848,9 +861,11 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff) break; case kBET_SummonObstacle: { - a8::Vec2 target_pos = caster->GetPos() + caster->skill_dir_ * caster->skill_distance_; - target_pos = buff_vec2_param1; - SummonObstacle(buff->meta->param1, target_pos); + if (!dead) { + a8::Vec2 target_pos = caster->GetPos() + caster->skill_dir_ * caster->skill_distance_; + target_pos = buff_vec2_param1; + SummonObstacle(buff->meta->param1, target_pos); + } } break; case kBET_Sprint: @@ -875,6 +890,11 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff) buff->ProcBatchAddBuff(caster); } break; + case kBET_BeRecycle: + { + buff->ProcBeRecycle(caster); + } + break; default: { } @@ -1149,7 +1169,14 @@ void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok, float fly_distance) int weapon_idx = GetCurrWeapon()->weapon_idx; *GetCurrWeapon() = Weapon(); GetCurrWeapon()->weapon_idx = weapon_idx; - SetCurrWeapon(ChooseNextWeapon(slot_id, SPEC1_IS_BEGIN, SPEC1_IS_END)); + Weapon* next_weapon = ChooseNextWeapon(slot_id, SPEC1_IS_BEGIN, SPEC1_IS_END); + if (!next_weapon) { + next_weapon = ChooseNextWeapon(SPEC2_IS_BEGIN, SPEC2_IS_BEGIN, SPEC2_IS_END); + } + if (!next_weapon) { + next_weapon = AutoChgWeapon(); + } + SetCurrWeapon(next_weapon); AutoLoadingBullet(); } } @@ -1170,7 +1197,14 @@ void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok, float fly_distance) int weapon_idx = GetCurrWeapon()->weapon_idx; *GetCurrWeapon() = Weapon(); GetCurrWeapon()->weapon_idx = weapon_idx; - SetCurrWeapon(ChooseNextWeapon(slot_id, SPEC2_IS_BEGIN, SPEC2_IS_END)); + Weapon* next_weapon = ChooseNextWeapon(slot_id, SPEC2_IS_BEGIN, SPEC2_IS_END); + if (!next_weapon) { + next_weapon = ChooseNextWeapon(SPEC1_IS_BEGIN, SPEC1_IS_BEGIN, SPEC1_IS_END); + } + if (!next_weapon) { + next_weapon = AutoChgWeapon(); + } + SetCurrWeapon(next_weapon); AutoLoadingBullet(); } } @@ -1190,6 +1224,7 @@ void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok, float fly_distance) last_shot_frameno_ = room->GetFrameNo(); if (!need_sync_active_player && IsPlayer()) { room->frame_event.AddBulletNumChg((Human*)this); + room->frame_event.AddWeaponAmmoChg((Human*)this); } shot_ok = true; } @@ -1453,7 +1488,7 @@ Weapon* Creature::ChooseNextWeapon(int curr_weapon_slot_id, int begin_slot_id, i break; } } - return next_weapon ? next_weapon : AutoChgWeapon(); + return next_weapon; } void Creature::SetCurrWeapon(Weapon* weapon) diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index 7709f12..ca48fdf 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -45,6 +45,7 @@ class Creature : public MoveableEntity std::function on_move_collision; bool poisoning = false; long long poisoning_time = 0; + bool playing_skill = false; Weapon car_weapon; a8::Vec2 buff_vec2_param1; @@ -140,6 +141,7 @@ class Creature : public MoveableEntity Weapon* GetCurrWeapon() { return curr_weapon_; }; void SetCurrWeapon(Weapon* weapon); void ResetAllSkillCd(); + void UpdateSkill(); private: @@ -148,7 +150,6 @@ private: virtual void DoSkillPreProc(int skill_id, int target_id, const a8::Vec2& target_pos); virtual void DoSkillPostProc(bool used, int skill_id, int target_id, const a8::Vec2& target_pos); - void UpdateSkill(); void ProcSkillPhase(MetaData::SkillPhase* phase); void ProcBuffEffect(Creature* caster, Buff* buff); void TriggerOneObjectBuff(Skill* skill, Creature* target, BuffTriggerType_e trigger_type); @@ -177,7 +178,6 @@ private: a8::Vec2 skill_dir_; float skill_param1 = 0; - bool playing_skill = false; size_t curr_skill_phase = 0; Skill* curr_skill_ = nullptr; int skill_target_id_ = 0; diff --git a/server/gameserver/framemaker.cc b/server/gameserver/framemaker.cc index 4b35ed1..e006aaf 100644 --- a/server/gameserver/framemaker.cc +++ b/server/gameserver/framemaker.cc @@ -6,6 +6,7 @@ #include "typeconvert.h" #include "metamgr.h" #include "car.h" +#include "app.h" cs::SMUpdate* FrameMaker::MakeUpdateMsg(Human* hum) { @@ -31,6 +32,16 @@ cs::SMUpdate* FrameMaker::MakeUpdateMsg(Human* hum) if (hum->IsPlayer()) { itr->FillMFObjectFull(room, (Human*)hum, msg->add_full_objects()); } + #ifdef DEBUG + if (App::Instance()->HasFlag(2) && itr->GetEntityType() == ET_Player) { + room->BroadcastDebugMsg(a8::Format("投放 %d pos:%d,%d 出现", + { + itr->GetEntityUniId(), + itr->GetPos().x, + itr->GetPos().y, + })); + } + #endif } for (auto& itr : hum->part_objects) { Entity* entity = itr; @@ -52,9 +63,25 @@ cs::SMUpdate* FrameMaker::MakeUpdateMsg(Human* hum) } for (auto& itr : hum->del_objects) { msg->add_del_objids(itr); + #ifdef DEBUG + if (App::Instance()->HasFlag(2)) { + room->BroadcastDebugMsg(a8::Format("投放 删除对象%d", + { + itr + })); + } + #endif } for (auto& itr : hum->out_objects) { msg->add_out_objids(itr); + #ifdef DEBUG + if (App::Instance()->HasFlag(2)) { + room->BroadcastDebugMsg(a8::Format("投放 移除视野对象%d", + { + itr + })); + } + #endif } for (size_t idx : hum->shots_) { if (idx < room->frame_event.shots_.size()) { diff --git a/server/gameserver/handlermgr.cc b/server/gameserver/handlermgr.cc index efdc4ed..2bb072c 100644 --- a/server/gameserver/handlermgr.cc +++ b/server/gameserver/handlermgr.cc @@ -87,6 +87,7 @@ void HandlerMgr::RegisterNetMsgHandlers() RegisterNetMsgHandler(&ggmsghandler, &RoomMgr::_CMReconnect); RegisterNetMsgHandler(&ggmsghandler, &Player::_CMMove); + RegisterNetMsgHandler(&ggmsghandler, &Player::_CMExecCommand); RegisterNetMsgHandler(&ggmsghandler, &Player::_CMEmote); RegisterNetMsgHandler(&ggmsghandler, &Player::_CMVoice); RegisterNetMsgHandler(&ggmsghandler, &Player::_CMGameOver); diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index c0f40a2..ffcbe2b 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -27,6 +27,7 @@ #include "aicomponent.h" #include "jsondatamgr.h" #include "skill.h" +#include "incubator.h" #include "framework/cpp/utils.h" #include "framework/cpp/httpclientpool.h" @@ -942,6 +943,12 @@ void Human::DecHP(float dec_hp, int killer_id, const std::string& killer_name, i &xtimer_attacher.timer_list_ ); SyncAroundPlayers(__FILE__, __LINE__, __func__); + if (GetNearbyTeammateNum(MetaMgr::Instance()->refresh_ai_downed_nearby_range) < + MetaMgr::Instance()->refresh_ai_downed_nearby_teammate_num) { + #if 0 + room->GetIncubator()->AllocAndroid(this, 1 + rand() % 2); + #endif + } } else { BeKill(killer_id, killer_name, weapon_id); } @@ -976,6 +983,11 @@ int Human::GetPartObjectsCount() return part_objects.size(); } +bool Human::InNewObjects(Entity* target) +{ + return new_objects.find(target) != new_objects.end(); +} + bool Human::InPartObjects(Entity* target) { return part_objects.find(target) != part_objects.end(); @@ -1047,6 +1059,21 @@ bool Human::HasNoDownedTeammate() return false; } +int Human::GetNearbyTeammateNum(float range) +{ + int num = 0; + if (team_members) { + for (auto& hum : *team_members) { + if (hum != this && !hum->dead && !hum->downed) { + if (hum->GetPos().Distance(GetPos()) <= range) { + ++num; + } + } + } + } + return num; +} + bool Human::CanUseSkill(int skill_id) { return !downed && Creature::CanUseSkill(skill_id); @@ -1770,12 +1797,14 @@ void Human::_UpdateSpecMove() void Human::_UpdateMove(int speed) { - do { - int distance = std::min(5, speed); - _InternalUpdateMove(distance); - speed -= distance; - } while (speed > 0); - CheckSpecObject(); + if (!HasBuffEffect(kBET_Vertigo)) { + do { + int distance = std::min(5, speed); + _InternalUpdateMove(distance); + speed -= distance; + } while (speed > 0); + CheckSpecObject(); + } } void Human::ChangeToRace(RaceType_e race, int level) @@ -2638,7 +2667,9 @@ Skin* Human::GetSkinByIdx(int idx) void Human::AddBuffPostProc(Creature* caster, Buff* buff) { - room->frame_event.AddBuff(this, buff); + if (!buff->meta->i->only_server()) { + room->frame_event.AddBuff(this, buff); + } } int Human::GetItemNum(int item_id) @@ -2712,6 +2743,22 @@ void Human::DropItems(Obstacle* obstacle) } else { ++normal_drop_times_; } + { + if (behavior.curr_start_destory_box_frameno <= 0 || + behavior.curr_destory_box_times >= MetaMgr::Instance()->refresh_ai_destory_box_times || + (room->GetFrameNo() - behavior.curr_start_destory_box_frameno > + MetaMgr::Instance()->refresh_ai_destory_box_time * SERVER_FRAME_RATE)){ + behavior.curr_start_destory_box_frameno = room->GetFrameNo(); + behavior.curr_destory_box_times = 0; + } + behavior.curr_destory_box_times++; + behavior.total_destory_box_times++; + if (behavior.curr_destory_box_times >= MetaMgr::Instance()->refresh_ai_destory_box_times) { + #if 0 + room->GetIncubator()->AllocAndroid(this, 1 + rand() % 2); + #endif + } + } #ifdef DEBUG #if 0 a8::UdpLog::Instance()->Debug("DropItems normal:%d box:%d drop_id:%d is_treasure_box:%d", @@ -3198,7 +3245,9 @@ void Human::OnBuffRemove(const Buff& buff) default: break; } - room->frame_event.RemoveBuff(this, buff.meta->i->buff_id()); + if (!buff.meta->i->only_server()) { + room->frame_event.RemoveBuff(this, buff.meta->i->buff_id()); + } } void Human::OnLand() @@ -3206,6 +3255,27 @@ void Human::OnLand() //着陆 RemoveBuffByEffectId(kBET_Jump); RemoveBuffByEffectId(kBET_ThroughWall); + if (IsAndroid() && team_uuid.empty()) { + MustBeAddBuff(this, kBeRecycleBuffId); + } + if (IsPlayer()) { + refresh_view_timer_ = room->xtimer.AddRepeatTimerAndAttach + ( + SERVER_FRAME_RATE * MetaMgr::Instance()->refresh_view_time, + a8::XParams() + .SetSender(this), + [] (const a8::XParams& param) + { + Human* hum = (Human*)param.sender.GetUserData(); + hum->UpdateViewObjects(); + }, + &xtimer_attacher.timer_list_, + [] (const a8::XParams& param) + { + Human* hum = (Human*)param.sender.GetUserData(); + hum->refresh_view_timer_ = nullptr; + }); + } if (IsCollisionInMapService()) { a8::Vec2 old_pos = GetPos(); std::vector dirs; @@ -3396,3 +3466,122 @@ void Human::GetHitAabbBox(AabbCollider& aabb_box) aabb_box._max.y = GetHitRadius(); } } + +void Human::UpdateViewObjects() +{ + if (view_objects_.size() >= 2) { + std::vector deleted_humans; + for (Human* hum : view_objects_) { + if (hum->dead || + hum->GetPos().ManhattanDistance(GetPos()) > MetaMgr::Instance()->view_objects_out_distance) { + deleted_humans.push_back(hum); + } + } + for (Human* hum : deleted_humans) { + view_objects_.erase(hum); + } + } + if (view_objects_.size() < 2) { + TouchAllLayerHumanList + ( + [this] (Human* hum, bool& stop) + { + if (hum->IsAndroid() && !hum->dead && view_objects_.find(hum) == view_objects_.end()) { + if (hum->GetPos().ManhattanDistance(GetPos()) < + MetaMgr::Instance()->view_objects_in_distance) { + view_objects_.insert(hum); + } + if (view_objects_.size() >= 2) { + stop = true; + return; + } + } + }); + } + if (view_objects_.size() < 2) { + room->GetIncubator()->AllocAndroid(this, 1 + rand() % 2); + if (refresh_view_timer_) { + room->xtimer.ModifyTimer(refresh_view_timer_, + SERVER_FRAME_RATE * (MetaMgr::Instance()->refresh_view_time + (rand() % 3)) + ); + } + } +} + +void Human::GMAddItem(int item_id, int item_num) +{ + MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquip(item_id); + if (!item_meta) { + return; + } + if (item_meta->i->_inventory_slot() >= 0 && + item_meta->i->_inventory_slot() < IS_END) { + if (GetInventory(item_meta->i->_inventory_slot()) >= + GetVolume(item_meta->i->_inventory_slot()) + ) { + /* + cs::SMPickup notifymsg; + notifymsg.set_error_code(1); + SendNotifyMsg(notifymsg); + */ + return; + } + int add_num = GetVolume(item_meta->i->_inventory_slot()) - + GetInventory(item_meta->i->_inventory_slot()); + add_num = std::min(item_num, add_num); + + AddInventory(item_meta->i->_inventory_slot(), add_num); + switch (item_meta->i->_inventory_slot()) { + case IS_FRAG: + case IS_SMOKE: + { + Weapon* weapon = &weapons[SPEC1_SLOT_BEGIN + + (item_meta->i->_inventory_slot() - SPEC1_IS_BEGIN) + ]; + weapon->weapon_id = item_id; + weapon->weapon_lv = 1; + weapon->ammo += item_num; + weapon->meta = item_meta; + weapon->Recalc(); + DecInventory(item_meta->i->_inventory_slot(), add_num); + } + break; + case IS_1XSCOPE: + case IS_2XSCOPE: + case IS_4XSCOPE: + case IS_8XSCOPE: + case IS_15XSCOPE: + { + if (item_meta->i->_inventory_slot() - IS_1XSCOPE > curr_scope_idx) { + curr_scope_idx = item_meta->i->_inventory_slot() - IS_1XSCOPE; + } + } + break; + case IS_POSION_GAS_BOMB: + case IS_MOLOTOR_COCKTAIL: + case IS_TRAP: + case IS_MINE: + { + Weapon* weapon = &weapons[SPEC2_SLOT_BEGIN + + (item_meta->i->_inventory_slot() - SPEC2_IS_BEGIN) + ]; + weapon->weapon_id = item_id; + weapon->weapon_lv = 1; + weapon->ammo += item_num; + weapon->meta = item_meta; + weapon->Recalc(); + DecInventory(item_meta->i->_inventory_slot(), add_num); + } + break; + default: + { +#if 0 + abort(); +#endif + } + break; + } + } + need_sync_active_player = true; + SyncAroundPlayers(__FILE__, __LINE__, __func__); +} diff --git a/server/gameserver/human.h b/server/gameserver/human.h index 46ad98c..f548941 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -52,6 +52,7 @@ class Human : public Creature int today_enter_times = 0; int account_registertime = 0; int channel = 0; + HumanBehavior behavior; MetaData::Player* meta = nullptr; MetaData::Equip* helmet_meta = nullptr; MetaData::Equip* chest_meta = nullptr; @@ -163,6 +164,7 @@ class Human : public Creature void AddToNewObjects(Entity* entity); void AddToPartObjects(Entity* entity); void RemovePartObjects(Entity* entity); + bool InNewObjects(Entity* target); bool InPartObjects(Entity* target); int GetPartObjectsCount(); void RemoveObjects(Entity* entity); @@ -170,6 +172,7 @@ class Human : public Creature void RemoveOutObjects(Entity* entity); bool HasLiveTeammate(); bool HasNoDownedTeammate(); + int GetNearbyTeammateNum(float range); void DoJump(); virtual bool CanUseSkill(int skill_id) override; virtual Skill* SelectSkill(); @@ -241,6 +244,8 @@ class Human : public Creature void SetSeat(int seat) { seat_ = seat; } void DeadDrop(); virtual std::string GetName() override { return name;}; + void UpdateViewObjects(); + void GMAddItem(int item_id, int item_num); protected: void _InternalUpdateMove(float speed); @@ -328,6 +333,8 @@ protected: bool follow_synced_active_player = false; Car* car_ = nullptr; int seat_ = 0; + std::set view_objects_; + xtimer_list* refresh_view_timer_ = nullptr; private: CircleCollider* self_collider_ = nullptr; diff --git a/server/gameserver/incubator.cc b/server/gameserver/incubator.cc new file mode 100644 index 0000000..87552ed --- /dev/null +++ b/server/gameserver/incubator.cc @@ -0,0 +1,186 @@ +#include "precompile.h" + +#include "incubator.h" +#include "room.h" +#include "human.h" +#include "metamgr.h" + +void Incubator::Init() +{ + xtimer_attacher_.xtimer = &room->xtimer; + room->xtimer.AddRepeatTimerAndAttach + ( + SERVER_FRAME_RATE * (2 + rand() % 3), + a8::XParams() + .SetSender(this), + [] (const a8::XParams& param) + { + Incubator* incubator = (Incubator*)param.sender.GetUserData(); + incubator->AutoAllocAndroid(); + }, + &xtimer_attacher_.timer_list_); +} + +void Incubator::UnInit() +{ + +} + +void Incubator::AllocAndroid(Human* target, int num) +{ + if (room->xtimer.GetRunningTimer() == nullptr) { + abort(); + } + int try_count = 0; + a8::Vec2 dir = a8::Vec2::UP; + while (num > 0 && try_count < 20 && !hold_humans_.empty()) { + dir.Rotate(a8::RandAngle()); + int rand_len = rand() % MetaMgr::Instance()->incubator_rand_length; + Human* hum = hold_humans_[0]; + a8::Vec2 old_pos = hum->GetPos(); + hum->SetPos(target->GetPos() + dir * (MetaMgr::Instance()->incubator_base_length + rand_len)); + if (hum->CollisonDetection() || !CanSet(hum, target)) { + hum->SetPos(old_pos); + } else { + room->EnableHuman(hum); +#ifdef DEBUG + if (!target->InNewObjects(hum)) { + abort(); + } + if (hum->dead) { + abort(); + } +#endif + hum->MustBeAddBuff(hum, kTraceBuffId); + hold_humans_.erase(hold_humans_.begin()); + --num; +#ifdef DEBUG + room->BroadcastDebugMsg(a8::Format("投放机器人 %d:%s pos:%d,%d pos1:%d,%d %d num:%d", + {hum->GetEntityUniId(), + hum->name, + hum->GetPos().x, + hum->GetPos().y, + target->GetPos().x, + target->GetPos().y, + hum->GetPos().Distance(target->GetPos()), + hold_humans_.size()})); +#endif + } + ++try_count; + } +#ifdef DEBUG + if (num > 0) { + room->BroadcastDebugMsg(a8::Format("投放机器人 分配失败 %d", {hold_humans_.size()})); + } +#endif +} + +void Incubator::RecycleAndroid(Human* hum) +{ + Human* nearest_hum = nullptr; + Human* target = hum; + float distance = 10000000; + room->TouchAlivePlayers + ( + a8::XParams(), + [&nearest_hum, target, &distance] (Human* hum, a8::XParams& param) -> bool + { + float tmp_distance = hum->GetPos().ManhattanDistance(target->GetPos()); + if (tmp_distance < distance) { + nearest_hum = hum; + distance = tmp_distance; + } + return true; + }); + if (hum->dead) { + #ifdef DEBUG + room->BroadcastDebugMsg(a8::Format("回收机器人 %d:%s 角色已死亡", + {hum->GetEntityUniId(), + hum->name})); + #endif + hum->RemoveBuffByEffectId(kBET_BeRecycle); + return; + } + if (distance < MetaMgr::Instance()->incubator_canset_distance) { + #ifdef DEBUG + room->BroadcastDebugMsg(a8::Format("回收机器人 %d:%s 距离太近", + {hum->GetEntityUniId(), + hum->name})); + #endif + hum->RemoveBuffByEffectId(kBET_BeRecycle); + return; + } + if (distance > MetaMgr::Instance()->incubator_canset_distance + 100) { + hum->RemoveBuffByEffectId(kBET_BeRecycle); + hold_humans_.push_back(hum); + room->DisableHuman(hum); + #ifdef DEBUG + room->BroadcastDebugMsg(a8::Format("回收机器人 %d:%s:%d 添加到回收列表", + {hum->GetEntityUniId(), + hum->name, + hold_humans_.size() + })); + #endif + return; + } +} + +bool Incubator::CanSet(Human* hum, Human* exclude_hum) +{ + Human* target = hum; + bool can_set = true; + room->TouchAlivePlayers + ( + a8::XParams(), + [target, exclude_hum, &can_set] (Human* hum, a8::XParams& param) -> bool + { + if (hum != exclude_hum) { + if (target->GetPos().ManhattanDistance(hum->GetPos()) < + MetaMgr::Instance()->incubator_canset_distance) { + can_set = false; + return false; + } + } + return true; + }); + return can_set; +} + +void Incubator::AutoAllocAndroid() +{ + switch (room->GetGasData().gas_mode) { + case GasWaiting: + case GasMoving: + { + if (!hold_humans_.empty()){ + Human* hum = hold_humans_[0]; + if (room->GetGasData().gas_mode == GasWaiting && + hold_humans_.size() > 1 && + ((rand() % 100) > 40)) { + Human* killer = nullptr; + if (hold_humans_.size() == 2) { + killer = hold_humans_[1]; + } else { + killer = hold_humans_[1 + (rand() % (hold_humans_.size() - 1))]; + } + hum->BeKill(killer->GetEntityUniId(), + killer->name, + killer->GetCurrWeapon()->weapon_id); + } else if (room->GetGasData().gas_count > 1) { + hum->BeKill(VP_SafeArea, + TEXT("battle_server_killer_gas", "毒圈"), + VW_SafeArea); + } else { + return; + } + hold_humans_.erase(hold_humans_.begin()); + room->xtimer.ModifyTimer(room->xtimer.GetRunningTimer(), SERVER_FRAME_RATE * (3 + rand() % 5)); + } + } + break; + default: + { + } + break; + } +} diff --git a/server/gameserver/incubator.h b/server/gameserver/incubator.h new file mode 100644 index 0000000..47a293b --- /dev/null +++ b/server/gameserver/incubator.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +class Human; +class Room; +class Incubator +{ + public: + Room* room = nullptr; + + void Init(); + void UnInit(); + void AllocAndroid(Human* target, int num); + void RecycleAndroid(Human* hum); + +private: + bool CanSet(Human* hum, Human* exclude_hum); + void AutoAllocAndroid(); + +private: + std::vector hold_humans_; + a8::XTimerAttacher xtimer_attacher_; +}; diff --git a/server/gameserver/metamgr.cc b/server/gameserver/metamgr.cc index 4816e07..d6b61b0 100755 --- a/server/gameserver/metamgr.cc +++ b/server/gameserver/metamgr.cc @@ -237,6 +237,19 @@ public: METAMGR_READ(teammate_bekill_color, 0x00FF00); METAMGR_READ(self_kill_color, 0xFFFF00); METAMGR_READ(self_bekill_color, 0x00FF00); + METAMGR_READ(refresh_ai_destory_box_time, 30); + METAMGR_READ(refresh_ai_destory_box_times, 5); + METAMGR_READ(refresh_ai_downed_nearby_teammate_num, 1); + METAMGR_READ(refresh_ai_downed_nearby_range, 580); + + METAMGR_READ(view_objects_out_distance, 530); + METAMGR_READ(view_objects_in_distance, 530); + + METAMGR_READ(incubator_base_length, 501); + METAMGR_READ(incubator_rand_length, 10); + METAMGR_READ(incubator_canset_distance, 520); + + METAMGR_READ(refresh_view_time, 4); { METAMGR_READ_STR(level0room_spec_things, ""); std::vector tmpstrings; diff --git a/server/gameserver/metamgr.h b/server/gameserver/metamgr.h index ecef472..d4af9fb 100755 --- a/server/gameserver/metamgr.h +++ b/server/gameserver/metamgr.h @@ -139,6 +139,20 @@ class MetaMgr : public a8::Singleton float ice_show_time = 0.5f; float ice_invisible_time2 = 2.0f; + int refresh_ai_destory_box_time = 30; + int refresh_ai_destory_box_times = 5; + int refresh_ai_downed_nearby_teammate_num = 1; + int refresh_ai_downed_nearby_range = 580; + + int view_objects_out_distance = 580; + int view_objects_in_distance = 580; + + int incubator_base_length = 580; + int incubator_rand_length = 100; + int incubator_canset_distance = 100; + + int refresh_view_time = 8; + #if 0 int refresh_robot_min_num = 0; int refresh_robot_max_num = 0; diff --git a/server/gameserver/molotor_cocktail_mitask.cc b/server/gameserver/molotor_cocktail_mitask.cc index 3d65a2e..e255c88 100644 --- a/server/gameserver/molotor_cocktail_mitask.cc +++ b/server/gameserver/molotor_cocktail_mitask.cc @@ -64,14 +64,14 @@ void MolotorCocktailMiTask::Check() } } ); - a8::Vec2 old_buff_vec2_param1 = sender.Get()->buff_vec2_param1; - sender.Get()->buff_vec2_param1 = sender.Get()->GetPos(); for (Creature* target : objects) { if (!target->GetBuffById(meta->i->buffid())) { + a8::Vec2 old_buff_vec2_param1 = target->buff_vec2_param1; + target->buff_vec2_param1 = target->GetPos(); target->MustBeAddBuff(sender.Get(), meta->i->buffid()); + target->buff_vec2_param1 = old_buff_vec2_param1; } } - sender.Get()->buff_vec2_param1 = old_buff_vec2_param1; } } diff --git a/server/gameserver/player.cc b/server/gameserver/player.cc index 68795aa..96d4948 100644 --- a/server/gameserver/player.cc +++ b/server/gameserver/player.cc @@ -129,7 +129,10 @@ void Player::InternalUpdate(int delta_time) if (has_use_item_id) { UpdateUseItemId(); } - } + if (playing_skill) { + UpdateSkill(); + } + } } void Player::UpdateMove() @@ -624,7 +627,7 @@ void Player::LootInteraction(Loot* entity) case IS_15XSCOPE: { if (item_meta->i->_inventory_slot() - IS_1XSCOPE > curr_scope_idx) { - curr_scope_idx = item_meta->i->_inventory_slot() - IS_1XSCOPE; + curr_scope_idx = item_meta->i->_inventory_slot() - IS_1XSCOPE; } } break; @@ -1089,6 +1092,23 @@ void Player::_CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg) last_cmmove_frameno = room->GetFrameNo(); } +void Player::_CMExecCommand(f8::MsgHdr& hdr, const cs::CMExecCommand& msg) +{ + std::vector cmds; + a8::Split(msg.cmd().c_str(), cmds, ' '); + if (cmds.empty()) { + return; + } + std::string cmd = cmds[0]; + if (cmd == "gps") { + SendDebugMsg(a8::Format("%d %d", {GetPos().x, GetPos().y})); + }else if (cmd == "additem" && cmds.size() >= 2) { + int item_id = a8::XValue(cmds[1]); + int item_num = a8::XValue(cmds[2]); + GMAddItem(item_id, item_num); + } +} + void Player::UpdateDropWeapon() { if (drop_weapon_idx >= 0 && diff --git a/server/gameserver/player.h b/server/gameserver/player.h index 3209c6c..138d7d0 100644 --- a/server/gameserver/player.h +++ b/server/gameserver/player.h @@ -102,6 +102,7 @@ class Player : public Human void _CMReconnect(f8::MsgHdr& hdr, const cs::CMReconnect& msg); void _CMMove(f8::MsgHdr& hdr, const cs::CMMove& msg); + void _CMExecCommand(f8::MsgHdr& hdr, const cs::CMExecCommand& msg); void _CMEmote(f8::MsgHdr& hdr, const cs::CMEmote& msg); void _CMVoice(f8::MsgHdr& hdr, const cs::CMVoice& msg); void _CMGameOver(f8::MsgHdr& hdr, const cs::CMGameOver& msg); diff --git a/server/gameserver/posiongas_mitask.cc b/server/gameserver/posiongas_mitask.cc index 9a4efc3..6a349b1 100644 --- a/server/gameserver/posiongas_mitask.cc +++ b/server/gameserver/posiongas_mitask.cc @@ -64,14 +64,14 @@ void PosionGasMiTask::Check() } } ); - a8::Vec2 old_buff_vec2_param1 = sender.Get()->buff_vec2_param1; - sender.Get()->buff_vec2_param1 = sender.Get()->GetPos(); for (Creature* target : objects) { if (!target->GetBuffById(meta->i->buffid())) { + a8::Vec2 old_buff_vec2_param1 = target->buff_vec2_param1; + target->buff_vec2_param1 = target->GetPos(); target->MustBeAddBuff(sender.Get(), meta->i->buffid()); + target->buff_vec2_param1 = old_buff_vec2_param1; } } - sender.Get()->buff_vec2_param1 = old_buff_vec2_param1; } } diff --git a/server/gameserver/room.cc b/server/gameserver/room.cc index 01210fc..0d29afd 100644 --- a/server/gameserver/room.cc +++ b/server/gameserver/room.cc @@ -29,6 +29,7 @@ #include "perfmonitor.h" #include "mapinstance.h" #include "mapmgr.h" +#include "incubator.h" #include "framework/cpp/utils.h" @@ -85,6 +86,9 @@ void Room::Init() CreateDropObjs(); InitObstacleDatas(); ShuaAndroid(); + incubator_ = new Incubator(); + incubator_->room = this; + incubator_->Init(); if (room_type_ == RT_NewBrid && creator_game_times_ <= 0) { CreateLevel0RoomSpecThings(); } @@ -95,9 +99,12 @@ void Room::Init() void Room::UnInit() { + incubator_->UnInit(); #ifdef DEBUG UnInitDebugInfo(); #endif + incubator_->UnInit(); + A8_SAFE_DELETE(incubator_); timer_attacher.ClearTimerList(); xtimer_attacher_.ClearTimerList(); for (auto& pair : accountid_hash_) { @@ -1077,6 +1084,31 @@ void Room::TouchEntityList(a8::XParams param, } } +void Room::TouchAlivePlayers(a8::XParams param, + std::function func) +{ + for (auto& pair : alive_player_hash_) { + if (!func(pair.second, param)) { + break; + } + } +} + +void Room::BroadcastDebugMsg(const std::string& debug_msg) +{ + #ifdef DEBUG + TouchHumanList + ( + a8::XParams() + .SetParam1(debug_msg), + [] (Human* hum, a8::XParams& param) -> bool + { + hum->SendDebugMsg(param.param1); + return true; + }); + #endif +} + void Room::UpdateGas() { switch (gas_data_.gas_mode) { @@ -2279,13 +2311,23 @@ void Room::EnableHuman(Human* target) target->GetEntityUniId() }); #endif + #if 0 + target->OnEnable(); + AddToMoveableHash(target); + if (!target->real_dead) { + AddToAliveHumanHash(target); + } + #else if (a8::HasBitFlag(target->status, HS_Disable)) { target->OnEnable(); AddToMoveableHash(target); if (!target->real_dead) { AddToAliveHumanHash(target); } + } else { + abort(); } + #endif #ifdef DEBUG CheckPartObjects(); #endif @@ -2293,9 +2335,11 @@ void Room::EnableHuman(Human* target) void Room::DisableHuman(Human* target) { + #if 0 if (!RuningInTimer()) { abort(); } + #endif #ifdef DEBUG CheckPartObjects(); a8::UdpLog::Instance()->Debug("disablehuman %d %d", @@ -2658,6 +2702,15 @@ bool Room::HasPlayerInRound(const a8::Vec2& pos, float rad) void Room::ProcDisableHuman() { + #if 1 + for (auto& pair : human_hash_) { + if (pair.second->IsAndroid() && + pair.second->team_uuid.empty() && + !a8::HasBitFlag(pair.second->status, HS_Disable)) { + DisableHuman(pair.second); + } + } + #else if (room_type_ == RT_NewBrid || room_type_ == RT_MidBrid) { for (auto& pair : human_hash_) { if (pair.second->IsAndroid() && @@ -2667,6 +2720,7 @@ void Room::ProcDisableHuman() } } } + #endif } void Room::OnHumanGridChg(Human* target) @@ -2968,6 +3022,9 @@ void Room::AddToHumanHash(Human* hum) void Room::AddToAliveHumanHash(Human* hum) { alive_human_hash_[hum->GetEntityUniId()] = hum; + if (hum->IsPlayer()) { + alive_player_hash_[hum->GetEntityUniId()] = hum; + } } void Room::AddToMoveableHash(MoveableEntity* entity) @@ -3008,6 +3065,9 @@ void Room::RemoveFromHuamnHash(Human* hum) void Room::RemoveFromAliveHumanHash(Human* hum) { alive_human_hash_.erase(hum->GetEntityUniId()); + if (hum->IsPlayer()) { + alive_player_hash_.erase(hum->GetEntityUniId()); + } } void Room::RemoveFromLaterAddHash(RoomEntity* entity) @@ -3662,6 +3722,7 @@ void Room::ForwardGasRing(int n) } gas_data_.rad_old = gas_data_.old_area_meta->i->rad(); gas_data_.rad_new = gas_data_.new_area_meta->i->rad(); + gas_data_.gas_count++; --n; } } diff --git a/server/gameserver/room.h b/server/gameserver/room.h index 3ef2d51..8703f1d 100644 --- a/server/gameserver/room.h +++ b/server/gameserver/room.h @@ -36,6 +36,7 @@ class AabbCollider; class Android; class Car; class Hero; +class Incubator; class Room { public: @@ -98,6 +99,9 @@ public: std::function func); void TouchEntityList(a8::XParams param, std::function func); + void TouchAlivePlayers(a8::XParams param, + std::function func); + void BroadcastDebugMsg(const std::string& debug_msg); void ScatterDrop(a8::Vec2 center, int drop_id); void DropItem(a8::Vec2 pos, int item_id, int item_count, int item_lv); @@ -170,6 +174,7 @@ public: int GetOnlinePlayerNum(); RoomObstacle* CreateObstacle(int id, float x, float y); int AllocUniid(); + Incubator* GetIncubator() { return incubator_;}; private: void ShuaAndroid(); @@ -311,6 +316,7 @@ private: std::map later_add_hash_; std::map human_hash_; std::map alive_human_hash_; + std::map alive_player_hash_; std::map last_human_hash_; std::map born_point_hash_; @@ -320,4 +326,8 @@ private: std::vector obstacle_datas_; xtimer_list* auto_jump_timer_ = nullptr; + + Incubator* incubator_ = nullptr; + + friend class Incubator; }; diff --git a/server/gameserver/types.h b/server/gameserver/types.h index 989b6b3..fbff66c 100755 --- a/server/gameserver/types.h +++ b/server/gameserver/types.h @@ -29,6 +29,7 @@ struct GasData MetaData::SafeArea* old_area_meta = nullptr; MetaData::SafeArea* new_area_meta = nullptr; bool is_last_gas = false; + int gas_count = 0; }; struct Weapon @@ -131,6 +132,13 @@ struct HumanAbility float fire_rate = 0.0f; }; +struct HumanBehavior +{ + long long curr_start_destory_box_frameno = 0; + int curr_destory_box_times = 0; + int total_destory_box_times = 0; +}; + struct ObstacleData { int flags = 0; diff --git a/server/gameserver/zombiemode.ai.cc b/server/gameserver/zombiemode.ai.cc index 18441df..0cbedbe 100644 --- a/server/gameserver/zombiemode.ai.cc +++ b/server/gameserver/zombiemode.ai.cc @@ -93,6 +93,9 @@ void ZombieModeAI::UpdateAI() abort(); } } + if (hum->playing_skill) { + hum->UpdateSkill(); + } ++node_->exec_frame_num; hum->shot_hold = false; switch (node_->main_state) { diff --git a/server/tools/protobuild/cs_msgid.proto b/server/tools/protobuild/cs_msgid.proto index 50ecbc3..4f5cf81 100644 --- a/server/tools/protobuild/cs_msgid.proto +++ b/server/tools/protobuild/cs_msgid.proto @@ -20,6 +20,7 @@ enum CMMessageId_e _CMAdEnd = 214; _CMGetBoxInfo = 215; _CMOpenBox = 216; + _CMExecCommand = 217; } enum SMMessageId_e diff --git a/server/tools/protobuild/cs_proto.proto b/server/tools/protobuild/cs_proto.proto index 59ad856..b502753 100755 --- a/server/tools/protobuild/cs_proto.proto +++ b/server/tools/protobuild/cs_proto.proto @@ -899,6 +899,12 @@ message CMMove optional int32 get_on = 36; } +//执行GM指令 +message CMExecCommand +{ + optional string cmd = 1; //指令 +} + //丢弃道具 message CMDropItem { diff --git a/third_party/a8engine b/third_party/a8engine index 2b5f0d3..8b64108 160000 --- a/third_party/a8engine +++ b/third_party/a8engine @@ -1 +1 @@ -Subproject commit 2b5f0d3b41e764d61181089b95c4fa568b1e1942 +Subproject commit 8b6410826da2c0c667abdacadae6d7c00f70300d