《问天online》仙宠系统介绍
一、数据库表结构设计与初始化
在《问天online》的服务端架构中,仙宠数据的持久化存储依赖于MySQL数据库。首先需要在数据库中创建专用的仙宠表,用于存储玩家的仙宠基础信息、资质属性及战斗状态。请直接在数据库管理工具中执行以下SQL语句完成表结构创建。
```sql CREATE TABLE `user_pet_info` ( `role_id` bigint(20) unsigned NOT NULL COMMENT '角色ID', `pet_id` bigint(20) unsigned NOT NULL COMMENT '仙宠唯一ID', `pet_template_id` int(11) NOT NULL COMMENT '仙宠模板ID', `pet_name` varchar(32) NOT NULL DEFAULT '' COMMENT '仙宠名称', `level` int(11) NOT NULL DEFAULT '1' COMMENT '等级', `exp` int(11) NOT NULL DEFAULT '0' COMMENT '当前经验', `aptitude` int(11) NOT NULL DEFAULT '100' COMMENT '资质', `growth_rate` float NOT NULL DEFAULT '1.0' COMMENT '成长率', `hp` int(11) NOT NULL DEFAULT '100' COMMENT '当前血量', `max_hp` int(11) NOT NULL DEFAULT '100' COMMENT '最大血量', `attack` int(11) NOT NULL DEFAULT '10' COMMENT '攻击力', `defense` int(11) NOT NULL DEFAULT '5' COMMENT '防御力', `state` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0休息,1出战,2跟随', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '获得时间', PRIMARY KEY (`pet_id`), KEY `idx_role_id` (`role_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='玩家仙宠信息表'; ```执行完成后,数据库即具备了存储仙宠数据的能力。注意role_id建立了索引,以保证查询玩家所有仙宠时的性能。
二、服务端核心数据结构定义
服务端采用C++编写,需要定义与数据库字段一一对应的结构体,并处理网络字节序的转换。在头文件PetStruct.h中添加以下代码。这部分定义了内存中仙宠对象的形态,确保逻辑层操作的数据能正确序列化存入数据库。
```cpp pragma pack(push, 1) struct PetBaseInfo { uint64_t pet_id; uint32_t pet_template_id; std::string pet_name; uint32_t level; uint32_t exp; uint32_t aptitude; float growth_rate; uint32_t hp; uint32_t max_hp; uint32_t attack; uint32_t defense; uint8_t state; // 序列化函数,用于发送给客户端 void Encode(PacketWriter& writer) { writer.WriteUint64(pet_id); writer.WriteUint32(pet_template_id); writer.WriteString(pet_name); writer.WriteUint32(level); writer.WriteUint32(exp); writer.WriteUint32(aptitude); writer.WriteFloat(growth_rate); writer.WriteUint32(hp); writer.WriteUint32(max_hp); writer.WriteUint32(attack); writer.WriteUint32(defense); writer.WriteUint8(state); } }; pragma pack(pop) // 玩家仙宠管理类 class PetManager { public: std::unordered_map三、通信协议与数据包封装
为了实现客户端与服务端的交互,必须定义明确的协议号和数据包格式。在Protocol.h文件中定义仙宠相关的指令枚举。这是客户端和服务端通用的语言,严禁私自修改数值。
```cpp enum PetProtocol { PET_CMD_QUERY_LIST = 2001, // 查询仙宠列表 PET_CMD_ACTIVATE = 2002, // 激活/获得仙宠 PET_CMD_DEPLOY = 2003, // 出战/休息 PET_CMD_UPGRADE = 2004, // 升级/喂食 PET_CMD_RENAME = 2005, // 重命名 }; ```以“激活仙宠”为例,客户端发送请求包,服务端处理后返回响应包。以下是请求包的定义结构,必须严格按照此结构打包数据。
```cpp // 客户端请求激活仙宠结构 (C -> S) struct PetActivateReq { uint32_t item_id; // 使用的道具ID,比如“仙宠蛋”的ID uint32_t count; // 使用数量 }; // 服务端返回激活结果结构 (S -> C) struct PetActivateAck { uint8_t result_code; // 0成功,1失败,2背包已满 PetBaseInfo pet_info; // 新获得的仙宠详细信息 }; ```四、静态配置表加载逻辑
仙宠的基础属性(如每级成长多少攻击力)由策划配置在JSON或XML表中。服务端启动时需加载这些配置。假设配置文件名为pet_config.json,我们需要编写加载代码。
配置文件内容示例(pet_config.json):
```json { "1001": { "id": 1001, "name": "灵狐", "init_hp": 150, "init_attack": 20, "init_defense": 10, "hp_growth": 15.5, "atk_growth": 2.5, "def_growth": 1.2 }, "1002": { "id": 1002, "name": "战虎", "init_hp": 200, "init_attack": 25, "init_defense": 8, "hp_growth": 18.0, "atk_growth": 3.0, "def_growth": 1.0 } } ```加载代码实现(C++使用JsonCpp库为例):
```cpp bool PetConfigManager::LoadConfig(const std::string& file_path) { Json::Value root; std::ifstream ifs(file_path); Json::Reader reader; if (!reader.parse(ifs, root)) { std::cerr << "Parse pet_config.json failed!" << std::endl; return false; } Json::Value::Members keys = root.getMemberNames(); for (auto& key : keys) { uint32_t template_id = std::stoul(key); PetTemplate tpl; tpl.id = template_id; tpl.name = root[key]["name"].asString(); tpl.base_hp = root[key]["init_hp"].asInt(); tpl.base_attack = root[key]["init_attack"].asInt(); tpl.base_defense = root[key]["init_defense"].asInt(); tpl.hp_per_level = root[key]["hp_growth"].asDouble(); tpl.atk_per_level = root[key]["atk_growth"].asDouble(); config_map_[template_id] = tpl; } return true; } ```五、核心业务逻辑代码实现
这是系统的核心,处理仙宠的激活、属性计算和状态变更。在PetHandler.cpp中实现HandlePetActivate函数。这里展示了从校验道具、生成数据、写入数据库到通知客户端的完整闭环。
```cpp void PetHandler::HandlePetActivate(Player player, PacketReader& reader) { // 1. 解析请求包 PetActivateReq req; req.item_id = reader.ReadUint32(); req.count = reader.ReadUint32(); // 2. 校验背包道具 if (!player->GetBag()->ConsumeItem(req.item_id, req.count)) { SendActivateAck(player, 1, nullptr); // 1表示道具不足 return; } // 3. 确定仙宠模板ID (假设道具ID-1000即为仙宠模板ID) uint32_t template_id = req.item_id - 1000; auto tpl = PetConfigManager::Instance()->GetTemplate(template_id); if (!tpl) { SendActivateAck(player, 1, nullptr); return; } // 4. 生成新仙宠数据 PetBaseInfo new_pet; new_pet.pet_id = GenerateUniqueID(); new_pet.pet_template_id = template_id; new_pet.pet_name = tpl->name; new_pet.level = 1; new_pet.exp = 0; new_pet.state = 0; // 默认休息 // 计算初始属性 new_pet.max_hp = tpl->base_hp; new_pet.hp = new_pet.max_hp; new_pet.attack = tpl->base_attack; new_pet.defense = tpl->base_defense; // 5. 存入数据库 if (!player->GetPetManager()->UpdatePetToDB(new_pet)) { SendActivateAck(player, 1, nullptr); // 数据库错误 return; } // 6. 加入内存 player->GetPetManager()->pet_list_[new_pet.pet_id] = new_pet; // 7. 发送成功响应 SendActivateAck(player, 0, &new_pet); } // 辅助函数:发送响应包 void PetHandler::SendActivateAck(Player player, uint8_t code, PetBaseInfo pet) { PacketWriter writer(PET_CMD_ACTIVATE); writer.WriteUint8(code); if (code == 0 && pet) { pet->Encode(writer); } player->SendPacket(writer); } ```接下来实现属性计算逻辑。当仙宠升级时,需要根据配置表中的成长率重新计算属性。请在PetManager类中添加以下逻辑:
```cpp void PetManager::UpgradePet(uint64_t pet_id, uint32_t add_exp) { auto it = pet_list_.find(pet_id); if (it == pet_list_.end()) return; PetBaseInfo& pet = it->second; pet.exp += add_exp; // 简单的升级公式:每100经验升1级 uint32_t level_up_count = pet.exp / 100; if (level_up_count > 0) { uint32_t old_level = pet.level; pet.level += level_up_count; pet.exp %= 100; // 重新计算属性 auto tpl = PetConfigManager::Instance()->GetTemplate(pet.pet_template_id); if (tpl) { pet.max_hp = tpl->base_hp + (uint32_t)(tpl->hp_per_level pet.level); pet.attack = tpl->base_attack + (uint32_t)(tpl->atk_per_level pet.level); pet.defense = tpl->base_defense + (uint32_t)(tpl->def_growth pet.level); // 升级补满血量 pet.hp = pet.max_hp; } // 异步更新数据库 UpdatePetToDB(pet); // 推送变化给客户端 NotifyPetUpdate(pet); } } ```六、功能验证与调试指令
代码编写完成后,需要进行验证。首先确保服务端已成功编译并启动,且数据库连接正常。在客户端登录游戏后,可以通过发送封包或使用GM命令进行测试。
1. 验证仙宠激活:给角色发放一个ID为1001的“灵狐蛋”道具。使用该道具,观察服务端日志是否输出“HandlePetActivate”成功字样,并检查数据库user_pet_info表是否新增了一条记录。
2. 验证属性计算:使用GM命令/addpetexp 1001 500(假设此命令调用UpgradePet接口),给仙宠增加500点经验。预期结果是仙宠等级提升5级,攻击力和生命值按照配置表中的成长率增加。
3. 数据库校验SQL:执行以下SQL语句确认数据一致性:
```sql SELECT role_id, pet_name, level, attack, defense FROM user_pet_info WHERE role_id = 10001 ORDER BY create_time DESC LIMIT 1; ```确保查询到的attack字段值等于 base_attack + (atk_growth level)。如果数值不匹配,请检查代码中的强制类型转换是否正确执行。
版权保护: 本文由 741卡盟 原创,转载请保留链接: http://741ka.com/gamenews/25988.html
- 上一篇:2023台服手游最高人气排名前十
- 下一篇:御龙在天偷猪任务怎么做
