英雄遠征Erlang源碼分析(11)-物品相關操作解析

遊戲中,玩家物品的管理是通過每個玩家獨有的物品管理進程,結合ETS緩存表實現的。

物品相關模塊有mod_goods.erl,lib_goods.erl,goods_util.erl和lib_make.erl

mod_goods.erl:物品管理進程模塊,負責創建進程,進程內接收消息並調用相關操作。
lib_goods.erl:負責物品的發放和刪除,物品屬性修改,揹包內物品更改(物品堆疊處理),掉落管理,
goods_util.erl:負責服務器啓動時和用戶登錄時物品數據的初始化;通過指定id或者屬性獲取對應的物品
lib_make.erl:負責物品品質升級,強化,打洞,鑲嵌,洗練的計算

遊戲中的物品主要分爲兩種:物品原型(type_goods)和玩家所屬物品(goods)。當玩家獲得物品的時候,需要根據物品原型生成相應的玩家所屬物品,將一些未確定的物品屬性確定下來,將其和玩家id進行關聯,並將物品id記錄到玩家揹包中。

物品的初始化分爲兩個步驟:
1.服務器啓動時的初始化:在mod_kenel.erl中調用init_goods(),將數據庫中的物品原型數據和物品屬性加載進ETS緩存。
2.玩家登錄時的初始化:玩家登錄時調用mod_goods:start(PlayerId,CellNum,Equip)創建物品管理進程,並返回Pid,保存在#player_status.goods_pid中。

物品管理進程初始化方法:

init([PlayerId,CellNum, Equip]) ->
    ok = goods_util:init_goods_online(PlayerId),    %% 從數據庫中加載玩家物品信息,放入ETS緩存
    NullCells = goods_util:get_null_cells(PlayerId, CellNum),    %% 計算揹包空格
    EquipSuit = goods_util:count_equip_suit_list(PlayerId, Equip),    %% 計算套裝
    GoodsStatus = #goods_status{ player_id = PlayerId, null_cells = NullCells, equip_current = [0,0,0], equip_suit_list=EquipSuit },    %% 生成物品管理進程state
    NewStatus = goods_util:get_current_equip(GoodsStatus, Equip),    %% 獲取武器,坐騎,衣服列表
    {ok, NewStatus}.

進程state:

-record(goods_status, {
        player_id = 0,              % 用戶ID            (REF:player-player_id)
        null_cells = [],            % 揹包空格子位置
        equip_current = [0,0,0],    % 當前裝備類型ID - [武器, 衣服, 坐騎]
        equip_suit = [],            % 套裝屬性
        ct_time = 0                 % 使用藥品的冷卻時間
    }).

玩家5個放放物品的位置:套裝1,套裝2,套裝3,套裝4,套裝5

物品的相關操作,試着使用思維導圖整理了一些,初學思維導圖,感覺整理還不是很到位,當做一次練手吧:


除去基本的物品增刪改查,主要還有物品的屬性強化(品質升級,裝備強化,洗練等),揹包整理,掉落管理的操作。所有的都羅列出來有流水賬的嫌疑,這裏選取一些比較關鍵的方法進行解析:

揹包內物品的疊加計算:如果是可疊加的物品,加入揹包時需要和原有的同類型物品進行疊加,減少揹包格子的佔用

%% 更新原有的可疊加物品
%% 返回疊加現有物品後剩餘的物品數量
update_overlap_goods(GoodsInfo, [Num, MaxOverlap]) ->
    case Num > 0 of
        true when GoodsInfo#goods.num =/= MaxOverlap andalso MaxOverlap > 0 ->
            {LapHasNum, RestNum} = 
                case Num + GoodsInfo#goods.num > MaxOverlap of
                     %% 總數超出可疊加數
                     true ->
                         {MaxOverlap, Num + GoodsInfo#goods.num - MaxOverlap};
                     false ->
                         {Num + GoodsInfo#goods.num, 0}
                end,
            %% 更新現有物品數量
            change_goods_num(GoodsInfo, LapHasNum);
        true ->
            RestNum = Num;
        false ->
            RestNum = 0
    end,
    [RestNum, MaxOverlap].

怪物掉落的隨機系統:

%% 隨機一條掉落規則,規則內包含相關的掉落物品
rand_drop_num_rule(MonId) ->
    Pattern1 = #ets_goods_drop_num{ mon_id=MonId, _='_' },
    %% 獲取掉落配置
    NumRuleList = goods_util:get_goods_list_from_ets(?ETS_GOODS_DROP_NUM, Pattern1),
    case length(NumRuleList) > 0 of
        true ->
            %% 總權重
            TotalRatio1 = lists:foldl(fun(R, Sum) -> R#ets_goods_drop_num.ratio + Sum end, 0, NumRuleList),
            Ratio1 = util:rand(1, TotalRatio1),
            %% 根據隨機數從權重中選取掉落規則
            F1 = fun(Rule, [Ratio, First, Result]) ->
                End = First + Rule#ets_goods_drop_num.ratio,
                case Ratio > First andalso Ratio =< End of
                    true -> [Ratio, End, Rule];
                    false -> [Ratio, End, Result]
                end
                 end,
            [Ratio1, _, NumRule] = lists:foldl(F1, [Ratio1, 0, {}], NumRuleList);
       false ->
            NumRule = {}
    end,
    NumRule.

人物裝備屬性的計算:

%% 人物裝備屬性重新計算
count_role_equip_attribute(PlayerStatus, GoodsStatus, GoodsInfo) ->
    %% 裝備屬性
    Effect = get_equip_attribute(PlayerStatus#player_status.id, PlayerStatus#player_status.equip, GoodsStatus#goods_status.equip_suit_list),
    %% 檢查武器、衣服
    [NewGoodsStatus, _] = count_current_equip_by_info(GoodsInfo, [GoodsStatus, on]),
    %% 更新人物屬性
    PlayerStatus1 = PlayerStatus#player_status{
                           equip_current = NewGoodsStatus#goods_status.equip_current,
                           equip_attribute = Effect
                    },
    %% 人物屬性重新計算
    NewPlayerStatus = lib_player:count_player_attribute(PlayerStatus1),
    {ok, NewPlayerStatus, NewGoodsStatus}.


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章