遊戲中,玩家物品的管理是通過每個玩家獨有的物品管理進程,結合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}.