bfdz49 发表于 3 天前

远征源代码增加假人系统DLL文件

本帖最后由 bfdz49 于 2026-6-4 23:45 编辑

<blockquote>假人系统,不通过客户端连接 — 服务端直接调用内部登录流程创建角色,不走客户端 → Gateway → LoginServer 链路
struct SDummyRuntimeProp
{
    DWORD   dwRoleID;               // 角色ID
    DWORD   dwUserID;               // 账号ID
    char    szRoleName;         // 角色名
    WORD    wFaceID;                // 头像
    BYTE    nVocation;            // 职业(命魂)
    BYTE    nDiVocation;            // 地魂职业
    BYTE    nTianVocation;          // 天魂职业
    BYTE    nNation;                // 国家
    BYTE    nSex;                   // 性别
    BYTE    nCurLingHun;            // 当前灵魂态
    DWORD   dwMapID;                // 当前地图ID
    int   nLocX;                  // X坐标
    int   nLocY;                  // Y坐标
    BYTE    nLevel;               // 等级
    DWORD   dwCurHP;                // 当前生命
    DWORD   dwMaxHP;                // 最大生命
    DWORD   dwCurMP;                // 当前法术
    DWORD   dwMaxMP;                // 最大法术
    DWORD   dwMoney;                // 金钱
    DWORD   dwBindMoney;            // 绑定金钱
    DWORD   dwGold;               // 金币(RMB)
    DWORD   dwGoldBind;             // 绑定金币
    DWORD   dwExp;                  // 经验
    DWORD   dwClanID;               // 帮会ID
    DWORD   dwKinID;                // 家族ID
    int   nAttackValue;         // 攻击力
    int   nDefenceValue;          // 防御力
    int   nNewPowerValue;         // 战力值
    DWORD   dwTeamID;               // 队伍ID
    BYTE    nTeamRole;            // 队伍角色(0=队员,1=队长)
    DWORD   dwCurrentQuestID;       // 当前任务ID
    emDummyState eState;            // 当前行为状态

    // 战斗相关
    DWORD   dwTargetID;             // 当前目标ID (玩家/怪物/BOSS)
    DWORD   dwTargetType;         // 目标类型
    DWORD   dwLastSkillTime;      // 上次施法时间
    DWORD   dwComboCount;         // 连击计数
单个假人玩家实现

============================================================
// 初始化
// ============================================================
BOOL CDummyPlayer::Init(DWORD dwUserID, const char* szName, BYTE nVocation, BYTE nNation)
{
    m_stProp.dwUserID = dwUserID;
    m_stProp.dwRoleID = _AllocateRoleID();

    // 设置名字
    if (szName && strlen(szName) > 0)
    {
      strncpy(m_stProp.szRoleName, szName, 31);
    }
    else
    {
      std::string strName = CDummyPlayerNameGen::Instance()->GenerateRandomName();
      strncpy(m_stProp.szRoleName, strName.c_str(), 31);
    }

    // 职业
    if (nVocation > 0)
      m_stProp.nVocation = nVocation;
    else
      m_stProp.nVocation = CDummyPlayerConfig::Instance()->RandomVocation();

    // 国家
    if (nNation > 0)
      m_stProp.nNation = nNation;
    else
      m_stProp.nNation = CDummyPlayerConfig::Instance()->RandomNation();

    // 默认属性 (与TRoleInfo初始值一致)
    m_stProp.nLevel = 1;
    m_stProp.dwCurHP = 85;
    m_stProp.dwMaxHP = 85;
    m_stProp.dwCurMP = 80;
    m_stProp.dwMaxMP = 80;
    m_stProp.dwMoney = 100000;
    m_stProp.dwBindMoney = 200000;
    m_stProp.dwMapID = 1;       // 新手村-云中界
假人聊天系统实现

m_dwChatInterval = 60000;// 默认60秒一条
}

CDummyPlayerChat::~CDummyPlayerChat()
{
}

BOOL CDummyPlayerChat::CanChat()
{
    DWORD dwTick = GetTickCount();

    // 频率限制
    if (dwTick - m_dwLastChatTime < m_dwChatInterval)
      return FALSE;

    // 1分钟内不超过3条
    if (m_dwChatCount >= 3)
      return FALSE;

    return TRUE;
}

BOOL CDummyPlayerChat::SendMessage(emDummyChatChannel eChannel, const char* szContent)
{
    if (!CanChat()) return FALSE;
    if (!szContent || strlen(szContent) == 0) return FALSE;

    m_dwLastChatTime = GetTickCount();
    m_dwChatCount++;

    // TODO: 通过ChatServer发送聊天消息

配置管理器实现

// 全局配置
    m_stGlobalConfig.dwMaxDummyCount      = 5000;
    m_stGlobalConfig.dwLoginInterval      = 200;    // 200ms间隔登录
    m_stGlobalConfig.dwHeartbeatInterval    = 30000;// 30秒心跳
    m_stGlobalConfig.dwBossCheckInterval    = 5000;   // 5秒检查BOSS
    m_stGlobalConfig.dwStatsReportInterval= 60000;// 1分钟统计
    m_stGlobalConfig.dwChatInterval         = 60000;// 60秒一条聊天
    m_stGlobalConfig.dwMaxChatPerMinute   = 3;
    m_stGlobalConfig.dwGuoyunStartHour      = 12;
    m_stGlobalConfig.dwGuoyunEndHour      = 22;
    m_stGlobalConfig.dwGuotanStartHour      = 12;
    m_stGlobalConfig.dwGuotanEndHour      = 22;
    m_stGlobalConfig.bEnableBossFight       = TRUE;
    m_stGlobalConfig.bEnableCountryWar      = TRUE;
    m_stGlobalConfig.bEnableInstance      = TRUE;

    // 地图配置 - 主城
    _AddMap(1,   "云中界(新手村)", MAP_PRIORITY_CITY,   50,80,   2, 110, 420);
    _AddMap(100, "云中仙城",       MAP_PRIORITY_CITY,   80,120,1, 200, 300);
    _AddMap(101, "武陵城",         MAP_PRIORITY_CITY,   60,100,4, 300, 400);
    _AddMap(102, "天都城",         MAP_PRIORITY_CITY,   50,80,   2, 250, 350);

    // 地图配置 - 野外
    _AddMap(200, "碧水森林",       MAP_PRIORITY_FIELD,    30,60,   5, 500, 800);
    _AddMap(201, "幽暗密林",       MAP_PRIORITY_FIELD,    30,50,   3, 400, 600);
    _AddMap(202, "落日荒原",       MAP_PRIORITY_FIELD,    40,70,   4, 600, 900);
    _AddMap(203, "寒冰峡谷",       MAP_PRIORITY_FIELD,    30,60,   6, 300, 500);
    _AddMap(204, "烈焰火山",       MAP_PRIORITY_FIELD,    40,70,   7, 400, 700);
    _AddMap(205, "风暴高原",       MAP_PRIORITY_FIELD,    30,60,   8, 500, 700);
    _AddMap(206, "暗影沼泽",       MAP_PRIORITY_FIELD,    40,60,   9, 400, 600);

    // 地图配置 - 副本
    _AddMap(300, "幽冥洞",         MAP_PRIORITY_INSTANCE, 20,40,   20, 200, 300);
    _AddMap(301, "万妖塔",         MAP_PRIORITY_INSTANCE, 20,40,   30, 200, 300);
    _AddMap(302, "龙宫秘境",       MAP_PRIORITY_INSTANCE, 20,40,   40, 200, 300);
    _AddMap(303, "天宫试炼",       MAP_PRIORITY_INSTANCE, 20,40,   50, 200, 300);
    _AddMap(304, "五行使者",       MAP_PRIORITY_INSTANCE, 20,40,   60, 200, 300);
    _AddMap(305, "昆仑仙境",       MAP_PRIORITY_INSTANCE, 20,40,   70, 200, 300);

    // BOSS配置
    _AddBoss(10001, "树妖王",      200, 15,500,100,100,600);
    _AddBoss(10002, "暗影领主",    201, 25,800,100,200,1200);
    _AddBoss(10003, "荒原蝎王",    202, 35,1200, 200,300,1800);
    _AddBoss(10004, "冰龙",      203, 45,2000, 300,400,2400);
    _AddBoss(10005, "火焰魔神",    204, 55,3000, 400,500,3000);
    _AddBoss(10006, "风暴之主",    205, 65,5000, 500,600,3600);
    _AddBoss(10007, "沼泽女王",    206, 75,8000, 600,700,4200);
    _AddBoss(11001, "幽冥将军",    300, 30,1500, 150,300,1800);
    _AddBoss(11002, "万妖塔主",    301, 40,2500, 200,400,2400);
    _AddBoss(11003, "龙王",      302, 50,4000, 300,500,3000);
    _AddBoss(11004, "天宫守卫",    303, 60,6000, 400,600,3600);
    _AddBoss(11005, "五行使者·金", 304, 70,9000, 500,700,4200);

假人数据库操作实现

/ TODO: 发送 TMSG_DBSVR_ROLE_CREATE_REQ
    // 填充完整 TRoleInfo 结构体(与玩家创建角色完全一致):
    //
    // TRoleInfo stRole;
    // stRole.dwRoleID = dwRoleID;
    // stRole.dwUserID = dwUserID;
    // strcpy(stRole.szRoleName, szRoleName);
    // stRole.nVocation = nVocation;
    // stRole.nNation = nNation;
    // stRole.nSex = nSex;
    // stRole.nLevel = 1;
    // stRole.dwCurHP = 85;
    // stRole.dwMaxHP = 85;
    // stRole.dwCurMP = 80;
    // stRole.dwMaxMP = 80;
    // stRole.dwMoney = 100000;
    // stRole.dwBindMoney = 200000;
    // stRole.dwMapID = 1;
    // stRole.nLocX = 141;
    // stRole.nLocY = 469;
    // stRole.wFaceID = rand() % 20 + 1;
    //
    // _PackRoleInfo → BYTE buffer → SendToDBSvr → 等待回包

    return DB_OK;
}

emDBResult CDummyPlayerDB::ConfirmRoleCreate(DWORD dwRoleID)
{
    if (!m_bDBConnected) return DB_ERR_CONNECT;

    // TODO: 确认角色创建结果
    // 检查 t_role 表中是否存在 dwRoleID
    return DB_OK;
}

emDBResult CDummyPlayerDB::CenterConfirm(DWORD dwRoleID)
{
    if (!m_bDBConnected) return DB_ERR_CONNECT;

    // TODO: 发送 TMSG_DBSVR_ROLE_CENTER_CREATE_REQ
    // 中心库确认角色数据已同步
    return DB_OK;


『来自123云盘用户的分享』
链接:https://1843781346.share.123pan.cn/123pan/clBbTd-mStwh
提取码:PLCT



bfdz49 发表于 3 天前

假人系统,不通过客户端连接 — 服务端直接调用内部登录流程创建角色,不走客户端 → Gateway → LoginServer 链路
占用真实数据库记录 — 账号表/角色表结构与真实玩家完全一致,DBSvr 会为之分配 DB 空间
对真实客户端透明可见 — 真实玩家登录后,会在场景中看到假人走动、打怪、聊天,与之交互完全等同于真实玩家
真实客户端无需任何代码改动,只需要连接 ZoneServer 就能看到假人活跃在游戏世界中。重启 ZoneServer 后即可验证

strategypay11 发表于 3 天前

问题是没有服务端

li110456750 发表于 前天 07:38

就一个文件是什么意思 覆盖任何远征版本都可以吗

鹤舞九天 发表于 前天 08:36

楼主厉害,非常感谢

掏粪狂人 发表于 昨天 23:04

插件模式 省去了封包过程直接内部调用 厉害
页: [1]
查看完整版本: 远征源代码增加假人系统DLL文件

本站内容如若侵犯到您的权益,请来电来函告知,我们会尽快处理!
联系QQ:1953150286,2251387361,123784736,免责申明