爬塔流程设计

爬塔流程设计

爬塔状态

  • 正常流程步骤:依次向下执行;
  • 【4.0】新增选择突变种子,如果没有突变,则服务端直接跳过这一步;
  • 客户端在收到状态为Roguelike_State_Doing时,请求爬塔相关数据;
enum RoguelikeState
{
    Roguelike_State_Init = 0,                // 初始状态,未开始
    Roguelike_State_Start,                    // 已开始,扣除了爬塔体力值
    Roguelike_State_Select_Chr,                // 已选择爬塔武将
    Roguelike_State_Select_Servant,            // 已选择侍灵
    Roguelike_State_Select_Seed,            // 已选择突变种子 【4.0】
    Roguelike_State_Doing,                    // 爬塔进行中
    Roguelike_State_Over,                    // 爬塔结束
};

效果来源

// 来源
enum EffectFrom
{
    from_unknow = 0,            // 未知
    from_start = 1,                // 开始新征程
    from_chr_star = 2,            // 武将星级
    from_difficulty = 3,        // 困难度
    from_event_fight = 4,        // 战斗事件
    from_event_normal = 5,        // 普通事件
    from_event_select = 6,        // 选择事件
    from_event_shop = 7,        // 商店事件
    from_level_up = 8,            // 升级
    from_round_pass = 9,        // 通关
    from_round_over = 10,        // 一轮结束(通关失败)
    from_daily_update = 11,        // 每日更新
    from_goods_buy = 12,        // 道具购买
    from_gm = 13,                // gm命令
    from_chr_self = 14,         // 武将本身
    from_skin = 15,             // 武将皮肤
    from_event_qa = 16,            // 答题事件
    from_servant = 17,            // 侍灵
    from_buff = 18,             // buff获得
    from_spell = 19,             // 技能获得
    from_battlepass_extreme = 20,  // 战令至尊
    from_seed = 21,              // 突变种子 【4.0】
};

突变种子机制

  • 详细查看配置描述;
  • 在选择侍灵后,服务端计算可选的突变种子并通知客户端(没有突变则直接跳过);
  • 突变种子与选择的困难度关联;
  • 选择了突变种子后,在进入战斗前会对玩家进行effect加成,包括敌方、己方、双方;
  • 选择了突变种子后,在通关时会进行分数的加减计算

移除主公技能

  • 客户端在根据武将显示技能时,需要将主公技移除,例如选将界面;

协议交互

  • 搜索【4.0】查看改动

获取爬塔武将数据

ABROAD_ROGUELIKE_CHR_DATA_REP = 48509
struct ClientRoguelikeChrDataRep : public PacketBase
{
    enum emResult
    {
        ok = 0,
        failed = 1,
        not_start = 2,  // 未开始
        not_select = 3, // 没有选将
        data_error = 4, // 数据异常,收到该错误请返回模式准备界面
    };

    unsigned int result;
    unsigned int chrId;  // 武将id
    unsigned int skinId; // 武将皮肤
    bool         isDynamic;  // 是否是动态皮肤
    unsigned int skinMaxGrade;  // 武将皮肤拥有的最高品级
    unsigned int chrStar;  // 武将星级
    unsigned int coinNum;  // 金币数
    unsigned int spellNum; // 技能槽数目(额外获得的+武将自带的)
    unsigned int difficulty; // 困难度
    unsigned int playerLevel; // 等级
    unsigned int playerExp; // 当前经验值
    unsigned int playerUpExp; // 升级的经验值 playerExp > playerUpExp表示可升级
    unsigned int initCardNum; // 手牌初始数目
    int limitCardNum; // 手牌上限增量值
    unsigned int initHpNum; // 初始体力
    unsigned int limitHpNum; // 体力上限
    unsigned int useSQKNum; // 可使用手气卡次数
    unsigned int score;  // 积分
    unsigned int reliveCount;  // 还可以复活几次
    unsigned int seed;    // 突变种子【4.0】

    ClientRoguelikeChrDataRep() :PacketBase(ABROAD_ROGUELIKE_CHR_DATA_REP, sizeof(ClientRoguelikeChrDataRep))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientRoguelikeChrDataRep));
    }
};

获取章节事件数据

ABROAD_ROGUELIKE_CHAPTER_DATA_REP = 48521
struct ClientRoguelikeChapterDataRep : public PacketBase
{
    static const unsigned int sc_max_event_show_num = 10;

    enum emResult
    {
        ok = 0,
        failed = 1,
        not_start = 2, // 未开始
        data_error = 3, // 数据异常,收到该错误请返回模式准备界面
    };

    enum emFlag
    {
        flag_normal = 0,  // 数据查询或其他
        flag_event_change = 1,  // 事件变化
        flag_chapter_change = 2, // 章节变化
        flag_judge_update = 3,  // 判定事件更新
    };

    struct EventData
    {
        unsigned int no;        // 第几个事件
        unsigned int id;        // 事件id,客户端根据id去找配置进行显示
        unsigned int srcId;     // 原事件id,如果原事件是判定事件,则srcId与事件id的不一样 【4.0】
    };

    unsigned int result;
    BYTE flag;   // 消息标记
    unsigned int chapterNo;  // 当前第几个章节
    unsigned int eventNo; // 当前章节里第几个事件
    unsigned int eventTotalNum; // 当前章节事件总数目
    unsigned int totalChapterNum; // 章节总数目
    unsigned int showEventNum; // 显示的事件数目
    EventData events[sc_max_event_show_num]; // 显示的事件数据

    ClientRoguelikeChapterDataRep() :PacketBase(ABROAD_ROGUELIKE_CHAPTER_DATA_REP, sizeof(ClientRoguelikeChapterDataRep))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientRoguelikeChapterDataRep));
    }

    friend bostream& operator<<(bostream& bos, const ClientRoguelikeChapterDataRep& t)
    {
        bos << t.result << t.flag << t.chapterNo << t.eventNo << t.eventTotalNum << t.totalChapterNum << t.showEventNum ;
        for (unsigned int i = 0; i < t.showEventNum; i++)
        {
            bos << t.events[i].no << t.events[i].id << t.events[i].srcId;
            if (i >= sc_max_event_show_num) break;
        }
        return bos;
    }
};

选择突变种子

// 通知选择
ABROAD_ROGUELIKE_SEED_SELECT_NTF = 48560
struct ClientRoguelikeSeedSelectNtf : public PacketBase
{
    static const unsigned int sc_seed_max_num = 50;

    unsigned int count;
    unsigned int seeds[sc_seed_max_num];

    ClientRoguelikeSeedSelectNtf() :PacketBase(ABROAD_ROGUELIKE_SEED_SELECT_NTF, sizeof(ClientRoguelikeSeedSelectNtf))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientRoguelikeSeedSelectNtf));
    }
};

// 选择请求
ABROAD_ROGUELIKE_SEED_SELECT_REQ = 48561
struct ClientRoguelikeSeedSelectReq : public PacketBase
{
    unsigned int seedId;

    ClientRoguelikeSeedSelectReq() :PacketBase(ABROAD_ROGUELIKE_SEED_SELECT_REQ, sizeof(ClientRoguelikeSeedSelectReq))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientRoguelikeSeedSelectReq));
    }
};

ABROAD_ROGUELIKE_SEED_SELECT_REP = 48562
struct ClientRoguelikeSeedSelectRep : public PacketBase
{
    enum emResult
    {
        ok = 0,
        failed = 1,
        no_config = 2, // 没有配置
        data_error = 3,
    };

    unsigned int result;
    unsigned int seedId;
    unsigned int state;

    ClientRoguelikeSeedSelectRep() :PacketBase(ABROAD_ROGUELIKE_SEED_SELECT_REP, sizeof(ClientRoguelikeSeedSelectRep))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientRoguelikeSeedSelectRep));
    }
};

升级或选项选择的EffectItemData变动

// 【4.0】value取值
struct EffectItemData
{
    // 类型,emRoguelikeEffectType
    unsigned int type;

    // 参数值
    // 一般只有value[0]有效
    // type=Effect_Hp,  value[0]为增加上限(需支持负值,至多到0);value[1]为体力,可不配,不配默认和value[0]一致,不可大于value[0]值
    // type=Effect_Spell/Effect_Buff/Effect_Card/Effect_Equip,  
    //       value[2] (可不填,默认为0)     value[0](可不填,默认为0)              value[1]          
    //        0 增加                             增加指定的技能id                  从特定组随机增加一个
    //        1 移除                             移除指定的技能id                  随机移除几个
    int value[3];

    unsigned int extremeLv;  // 需要达到的战令至尊等级
};

爬塔结算通知

ABROAD_ROGUELIKE_RESULT_NTF = 48532
struct ClientRoguelikeResultNtf : public PacketBase
{
    static const unsigned int sc_max_enemy_count = 8;
    static const unsigned int sc_max_reward_count = 20;

    struct RewardGood
    {
        unsigned int goodsId;
        unsigned int goodsCount;
    };

    unsigned int season;
    unsigned int times;  // 第几次闯关
    unsigned int difficulty;  // 困难度
    bool isWin;
    unsigned int score;  // 本轮计算的总积分
    unsigned int noReliveScore;  // 本轮为使用复活的增加积分 【4.0】
    unsigned int seedScore;  // 本轮突变种子的增加积分 【4.0】
    unsigned int coinGet;  // 本轮获得金币
    unsigned int equipPrice;  // 本轮装备价值
    unsigned int fightCount;   // 本轮对局数
    unsigned int fightTm;   // 本轮所有对局总时长
    unsigned int roundTm;   // 本轮闯关时长
    unsigned int overEventId;  // 最后一个事件id
    unsigned int count;  // 奖励数目
    RewardGood reward[sc_max_reward_count];  // 奖励

    ClientRoguelikeResultNtf() :PacketBase(ABROAD_ROGUELIKE_RESULT_NTF, sizeof(ClientRoguelikeResultNtf))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientRoguelikeResultNtf));
    }

    friend bostream& operator<<(bostream& bos, const ClientRoguelikeResultNtf& t)
    {
        bos << t.season << t.times << t.difficulty << t.isWin << t.score << t.noReliveScore << t.seedScore << t.coinGet << t.equipPrice << t.fightCount
            << t.fightTm << t.roundTm << t.overEventId << t.count;
        for (unsigned int i = 0; i < t.count; i++)
        {
            bos << t.reward[i].goodsId << t.reward[i].goodsCount;
            if (i >= sc_max_reward_count) break;
        }
        return bos;
    }
};

爬塔对局结算通知

struct RoguelikeEffectData
{
    unsigned int type;
    int value;    // 【4.0】类型改变 unsigned int改为int
    unsigned int flag; //【4.0】 type=8技能/9祝福/10牌库牌/11装备牌时,flag=0表示添加, flag=1表示移除指定的value, flag=2表示随机移除value数目
};

ABROAD_ROGUELIKE_GAME_OVER = 48536
struct ClientRoguelikeGameOver : public PacketBase
{
    static const unsigned int sc_max_effect_count = 20;

    enum emOverType  //【4.0】
    {
        Over_By_Normal = 0,             // 正常对局结算
        Over_By_Special_Kill = 1,       // 击杀指定玩家
        Over_By_Turn_Alive = 2,         // 轮次内加持存活
        Over_By_Turn_HP = 3,            // 轮次内血量满
        Over_By_Turn_Kill = 4,          // 轮次内击杀
    };

    unsigned int result;
    unsigned int overType;  //【4.0】结算类型(替换掉了原来的bool isRunaway)
    unsigned int count;
    RoguelikeEffectData effects[sc_max_effect_count];

    ClientRoguelikeGameOver() :PacketBase(ABROAD_ROGUELIKE_GAME_OVER, sizeof(ClientRoguelikeGameOver))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientRoguelikeGameOver));
    }
};