diff --git a/server/gameserver/constant.h b/server/gameserver/constant.h index 1b86bd3..a56794f 100755 --- a/server/gameserver/constant.h +++ b/server/gameserver/constant.h @@ -82,7 +82,9 @@ enum InventorySlot_e IS_2XSCOPE = 13, IS_4XSCOPE = 14, IS_8XSCOPE = 15, - IS_15XSCOPE = 16, + IS_15XSCOPE = 16, + + IS_END }; const char* const PROJ_NAME_FMT = "game%d_gameserver"; @@ -98,7 +100,6 @@ 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_INVENTORY_NUM = 17; const int MAX_WEAPON_NUM = 5; const int GUN_SLOT1 = 1; diff --git a/server/gameserver/global.cc b/server/gameserver/global.cc index 3a40f38..14f96c9 100755 --- a/server/gameserver/global.cc +++ b/server/gameserver/global.cc @@ -30,3 +30,8 @@ bool Global::IsTimeToReset(int time) int Global::g_nowtime = time(nullptr); int Global::g_time_zone = 8; bool Global::g_shutdown = false; + +bool IsValidSlotId(int slot_id) +{ + return slot_id >= 0 && slot_id < IS_END; +} diff --git a/server/gameserver/global.h b/server/gameserver/global.h index f4fe915..9d9df3c 100755 --- a/server/gameserver/global.h +++ b/server/gameserver/global.h @@ -18,3 +18,5 @@ class Global : public a8::Singleton static int g_time_zone; // 默认东八区 static bool g_shutdown; }; + +bool IsValidSlotId(int slot_id); diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index 7819a08..b56e31c 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -27,11 +27,7 @@ Human::Human() } weapons[0] = default_weapon; curr_weapon = &weapons[0]; - inventory.reserve(MAX_INVENTORY_NUM); - for (size_t i = 0; i < MAX_INVENTORY_NUM; ++i) { - inventory.push_back(0); - } - inventory[12] = 1; + inventory_[IS_1XSCOPE] = 1; } Human::~Human() @@ -42,6 +38,7 @@ void Human::Initialize() { Entity::Initialize(); RecalcSelfCollider(); + volume_ = meta->volume; } float Human::GetSpeed() @@ -190,8 +187,8 @@ void Human::Shot(Vector2D& target_dir) case 5: { //手雷 - if (inventory[slot_id] > 0) { - --inventory[slot_id]; + if (GetInventory(slot_id) > 0) { + DecInventory(slot_id, 1); ++curr_weapon->ammo; } else { int weapon_idx = curr_weapon->weapon_idx; @@ -211,8 +208,8 @@ void Human::Shot(Vector2D& target_dir) case 6: { //烟雾弹 - if (inventory[slot_id] > 0) { - --inventory[slot_id]; + if (GetInventory(slot_id) > 0) { + DecInventory(slot_id, 1); ++curr_weapon->ammo; } else { int weapon_idx = curr_weapon->weapon_idx; @@ -384,9 +381,9 @@ void Human::AutoLoadingBullet(bool manual) MetaData::Equip* bullet_meta = MetaMgr::Instance()->GetEquip(curr_weapon->meta->i->use_bullet()); if (bullet_meta && bullet_meta->i->_inventory_slot() >= 0 && - bullet_meta->i->_inventory_slot() < MAX_INVENTORY_NUM + bullet_meta->i->_inventory_slot() < inventory_.size() ) { - if (inventory[bullet_meta->i->_inventory_slot()] > 0) { + if (GetInventory(bullet_meta->i->_inventory_slot()) > 0) { StartAction(AT_Reload, curr_weapon->meta->i->reload_time(), curr_weapon->weapon_id, @@ -776,7 +773,7 @@ void Human::FillMFActivePlayerData(cs::MFActivePlayerData* player_data) auto p = player_data->add_weapons(); weapon.ToPB(p); } - for (auto& num : inventory) { + for (auto& num : inventory_) { player_data->add_inventory(num); } if (pain_killer_timer) { @@ -839,3 +836,47 @@ void Human::RecalcAttr() def += helmet_meta->i->def(); } } + +void Human::RecalcVolume() +{ + MetaData::Equip* backpack_meta = MetaMgr::Instance()->GetEquip(backpack); + if (backpack_meta) { + for (size_t i = 0; i < backpack_meta->volume.size(); ++i) { + volume_[i] = meta->volume[i] + backpack_meta->volume[i]; + } + } +} + +int Human::GetInventory(int slot_id) +{ + if (!IsValidSlotId(slot_id)) { + abort(); + } + return inventory_[slot_id]; +} + +void Human::AddInventory(int slot_id, int num) +{ + assert(num > 0); + if (!IsValidSlotId(slot_id)) { + abort(); + } + inventory_[slot_id] += num; +} + +void Human::DecInventory(int slot_id, int num) +{ + assert(num > 0); + if (!IsValidSlotId(slot_id)) { + abort(); + } + inventory_[slot_id] -= num; +} + +int Human::GetVolume(int slot_id) +{ + if (!IsValidSlotId(slot_id)) { + abort(); + } + return volume_[slot_id]; +} diff --git a/server/gameserver/human.h b/server/gameserver/human.h index 66aad2e..a6a27c4 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -65,7 +65,6 @@ class Human : public Entity Weapon* curr_weapon = nullptr; int curr_scope_idx = 0; - std::vector inventory; bool need_sync_team_data = false; bool need_sync_teammate_data = false; @@ -132,9 +131,16 @@ class Human : public Entity void FillMFGasData(cs::MFGasData* gas_data); bool CanSee(Human* hum); void RecalcAttr(); + void RecalcVolume(); + int GetInventory(int slot_id); + void AddInventory(int slot_id, int num); + void DecInventory(int slot_id, int num); + int GetVolume(int slot_id); protected: long long last_shot_frameno_ = 0; + std::array inventory_ = {}; + std::array volume_ = {}; std::set new_objects; std::set part_objects; std::set del_objects; diff --git a/server/gameserver/metadata.cc b/server/gameserver/metadata.cc index 98ac813..53ea3c3 100644 --- a/server/gameserver/metadata.cc +++ b/server/gameserver/metadata.cc @@ -46,17 +46,55 @@ namespace MetaData void Equip::Init() { - std::vector strings; - a8::Split(i->bullet_born_offset(), strings, '|'); - for (auto& str : strings) { - std::vector strings2; - a8::Split(str, strings2, ':'); - assert(strings2.size() == 2); - bullet_born_offset.push_back(std::make_tuple( - a8::XValue(strings2[0]).GetDouble(), - a8::XValue(strings2[1]).GetDouble() - ) - ); + { + std::vector strings; + a8::Split(i->bullet_born_offset(), strings, '|'); + for (auto& str : strings) { + std::vector strings2; + a8::Split(str, strings2, ':'); + assert(strings2.size() == 2); + bullet_born_offset.push_back(std::make_tuple( + a8::XValue(strings2[0]).GetDouble(), + a8::XValue(strings2[1]).GetDouble() + ) + ); + } + } + { + std::vector strings; + a8::Split(i->volume(), strings, '|'); + for (auto& str : strings) { + std::vector strings2; + a8::Split(str, strings2, ':'); + assert(strings2.size() == 2); + if (strings2.size() >= 2) { + int slot = a8::XValue(strings2[0]); + int num = a8::XValue(strings2[1]); + if (slot >= 0 && slot < volume.size()){ + volume[slot] = num; + } + } + } + } + } + + void Player::Init() + { + { + std::vector strings; + a8::Split(i->volume(), strings, '|'); + for (auto& str : strings) { + std::vector strings2; + a8::Split(str, strings2, ':'); + assert(strings2.size() == 2); + if (strings2.size() >= 2) { + int slot = a8::XValue(strings2[0]); + int num = a8::XValue(strings2[1]); + if (slot >= 0 && slot < volume.size()){ + volume[slot] = num; + } + } + } } } diff --git a/server/gameserver/metadata.h b/server/gameserver/metadata.h index 3d58d2e..03a7589 100755 --- a/server/gameserver/metadata.h +++ b/server/gameserver/metadata.h @@ -47,6 +47,7 @@ namespace MetaData const metatable::Equip* i = nullptr; std::vector> bullet_born_offset; + std::array volume = {}; void Init(); }; @@ -54,6 +55,10 @@ namespace MetaData struct Player { const metatable::Player* i = nullptr; + + std::array volume = {}; + + void Init(); }; struct Building diff --git a/server/gameserver/metamgr.cc b/server/gameserver/metamgr.cc index 1bbb55b..c519259 100755 --- a/server/gameserver/metamgr.cc +++ b/server/gameserver/metamgr.cc @@ -151,6 +151,7 @@ private: for (auto& meta : player_meta_list) { MetaData::Player& item = a8::FastAppend(player_list); item.i = &meta; + item.Init(); player_hash[item.i->id()] = &item; } diff --git a/server/gameserver/player.cc b/server/gameserver/player.cc index fe4c3c4..20bd90c 100644 --- a/server/gameserver/player.cc +++ b/server/gameserver/player.cc @@ -192,16 +192,16 @@ void Player::UpdateAction() int ammo = curr_weapon->ammo; if (ammo < curr_weapon->meta->i->clip_volume()) { if (bullet_meta->i->_inventory_slot() >= 0 && - bullet_meta->i->_inventory_slot() < MAX_INVENTORY_NUM) { - if (inventory[bullet_meta->i->_inventory_slot()] > 0) { + bullet_meta->i->_inventory_slot() < IS_END) { + if (GetInventory(bullet_meta->i->_inventory_slot()) > 0) { int add_num = 0; - if (inventory[bullet_meta->i->_inventory_slot()] <= + if (GetInventory(bullet_meta->i->_inventory_slot()) <= curr_weapon->meta->i->clip_volume() - ammo) { - add_num = inventory[bullet_meta->i->_inventory_slot()]; - inventory[bullet_meta->i->_inventory_slot()] -= add_num; + add_num = GetInventory(bullet_meta->i->_inventory_slot()); + DecInventory(bullet_meta->i->_inventory_slot(), add_num); } else { add_num = curr_weapon->meta->i->clip_volume() - ammo; - inventory[bullet_meta->i->_inventory_slot()] -= add_num; + DecInventory(bullet_meta->i->_inventory_slot(), add_num); } curr_weapon->ammo += add_num; need_sync_active_player = true;; @@ -219,12 +219,12 @@ void Player::UpdateAction() { MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquipBySlotId(action_item_id); if (item_meta){ - if (inventory[item_meta->i->_inventory_slot()] > 0) { + if (GetInventory(item_meta->i->_inventory_slot()) > 0) { float old_health = health; health += item_meta->i->heal(); health = std::min(health, GetMaxHP()); stats.heal_amount += health - old_health; - --inventory[item_meta->i->_inventory_slot()]; + DecInventory(item_meta->i->_inventory_slot(), 1); need_sync_active_player = true; SyncAroundPlayers(); } @@ -235,7 +235,7 @@ void Player::UpdateAction() { MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquipBySlotId(action_item_id); if (item_meta){ - if (inventory[item_meta->i->_inventory_slot()] > 0) { + if (GetInventory(item_meta->i->_inventory_slot()) > 0) { if (pain_killer_timer) { int passed_time = (room->frame_no - pain_killer_frameno) * FRAME_RATE_MS; int left_time = std::max(0, pain_killer_lastingtime * 1000 - passed_time); @@ -267,7 +267,7 @@ void Player::UpdateAction() &xtimer_attacher.timer_list_ ); } - --inventory[item_meta->i->_inventory_slot()]; + DecInventory(item_meta->i->_inventory_slot(), 1); need_sync_active_player = true; } } @@ -317,7 +317,7 @@ void Player::UpdateCancelAction() void Player::UpdateUseItemIdx() { - if (use_item_idx >= 0 && use_item_idx < MAX_INVENTORY_NUM) { + if (use_item_idx >= 0 && use_item_idx < IS_END) { switch (use_item_idx) { case IS_HEALTHKIT: { @@ -450,8 +450,8 @@ void Player::Shot() case 5: { //手雷 - if (inventory[slot_id] > 0) { - --inventory[slot_id]; + if (GetInventory(slot_id) > 0) { + DecInventory(slot_id, 1); ++curr_weapon->ammo; } else { int weapon_idx = curr_weapon->weapon_idx; @@ -471,8 +471,8 @@ void Player::Shot() case 6: { //烟雾弹 - if (inventory[slot_id] > 0) { - --inventory[slot_id]; + if (GetInventory(slot_id) > 0) { + DecInventory(slot_id, 1); ++curr_weapon->ammo; } else { int weapon_idx = curr_weapon->weapon_idx; @@ -560,7 +560,8 @@ void Player::ObstacleInteraction(Obstacle* entity) void Player::LootInteraction(Loot* entity) { - if (entity->pickuped) { + if (entity->pickuped || + entity->count <= 0) { return; } MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquip(entity->item_id); @@ -629,8 +630,20 @@ void Player::LootInteraction(Loot* entity) default: { if (item_meta->i->_inventory_slot() >= 0 && - item_meta->i->_inventory_slot() < MAX_INVENTORY_NUM) { - inventory[item_meta->i->_inventory_slot()] += entity->count; + 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(entity->count, add_num); + + AddInventory(item_meta->i->_inventory_slot(), add_num); if (item_meta->i->_inventory_slot() == 5 || item_meta->i->_inventory_slot() == 6) { Weapon* weapon = &weapons[3 + (item_meta->i->_inventory_slot() - 5)]; @@ -639,7 +652,7 @@ void Player::LootInteraction(Loot* entity) weapon->weapon_lv = 1; weapon->ammo += entity->count; weapon->meta = item_meta; - inventory[item_meta->i->_inventory_slot()] -= entity->count; + DecInventory(item_meta->i->_inventory_slot(), add_num); } } if (item_meta->i->_inventory_slot() > 12) { @@ -647,6 +660,12 @@ void Player::LootInteraction(Loot* entity) curr_scope_idx = item_meta->i->_inventory_slot() - 12; } } + if (add_num < entity->count) { + //刷新数量 + entity->count -= add_num; + entity->BroadcastFullState(); + return; + } } else { switch (item_meta->i->equip_type()) { case 7: @@ -660,6 +679,7 @@ void Player::LootInteraction(Loot* entity) room->DropItem(pos, old_item_meta->i->id(), 1); } backpack = item_meta->i->id(); + RecalcVolume(); } break; case 4: @@ -894,8 +914,8 @@ void Player::UpdateDropWeapon() void Player::UpdateUseScope() { - if (12 + use_scope_idx >= 12 && 12 + use_scope_idx < 16) { - if (inventory[12 + use_scope_idx] > 0) { + if (IS_1XSCOPE + use_scope_idx >= IS_1XSCOPE && IS_1XSCOPE + use_scope_idx <= IS_15XSCOPE) { + if (GetInventory(IS_1XSCOPE + use_scope_idx) > 0) { curr_scope_idx = use_scope_idx; need_sync_active_player = true; } diff --git a/server/tools/protobuild/metatable.proto b/server/tools/protobuild/metatable.proto index e9bc105..1304e61 100755 --- a/server/tools/protobuild/metatable.proto +++ b/server/tools/protobuild/metatable.proto @@ -64,7 +64,7 @@ message Equip optional int32 use_time = 15; //使用时间 optional int32 heal = 16; //瞬间生命恢复 optional int32 time = 17; //时间 - optional int32 volume = 19; //装备容量 + optional string volume = 19; //装备容量 optional int32 bullet_rad = 20; //子弹半径 optional string bullet_born_offset = 30; //子弹出生偏移 @@ -79,6 +79,7 @@ message Player optional int32 health = 3; //初始血量 optional int32 move_speed = 4; //移动速度 optional float def = 5; //防御 + optional string volume = 6; //初始库存 } message Skill