2025-06-04 05:02:57 +08:00

694 lines
20 KiB
Plaintext

FunctionFood = class("FunctionFood")
local PotEffect_Path =
{
[SceneFood_pb.ECOOKTYPE_JIANCHAO] = "Common/RoyalWorkTop",
[SceneFood_pb.ECOOKTYPE_BARBECUE] = "Common/AdventureBarbecue",
[SceneFood_pb.ECOOKTYPE_SOUP] = "Common/MagicStockpot",
[SceneFood_pb.ECOOKTYPE_DESSERT] = "Common/RomanticTrain",
};
local PotEffect_Action =
{
Prepareing = "show",
Cooking = "cook",
Compelete_Success = "get",
Compelete_Fail = "fail",
}
local Role_Perform =
{
SoundPath_Compelete_TopEP_Success = "Common/cook_get", --"Common/24ForgingSuccess",
SoundPath_Compelete_TopEP_Fail = "Common/cook_fail", --"Common/25ForgingFailure",
ActionName_Prepareing = "cook_ready",
ActionName_Cooking = "cook_ing",
ActionName_Compelete_Success = "cook_get",
ActionName_Compelete_Fail = "cook_fail",
}
function FunctionFood.Me()
if nil == FunctionFood.me then
FunctionFood.me = FunctionFood.new()
end
return FunctionFood.me
end
function FunctionFood:ctor()
self.potEffectMap = {};
if(Table_Recipe)then
self.recipe_Type_Map = {};
self.recipe_totalCount_Map = {};
local materials_totalCount;
for id, recipeData in pairs(Table_Recipe)do
local rtype = recipeData.Type;
if(nil == self.recipe_Type_Map[rtype])then
self.recipe_Type_Map[rtype] = {};
end
materials_totalCount = 0;
for i=1,#recipeData.Material do
materials_totalCount = materials_totalCount + recipeData.Material[i][3];
end
self.recipe_totalCount_Map[id] = materials_totalCount;
table.insert(self.recipe_Type_Map[rtype], recipeData);
end
for _,recipeDatas in pairs(self.recipe_Type_Map)do
table.sort(recipeDatas, FunctionFood.SortRecipes);
end
end
EventManager.Me():AddEventListener(SkillEvent.SkillCastBegin,self.HandleStartSkill,self)
EventManager.Me():AddEventListener(SkillEvent.SkillCastEnd,self.HandleStopSkill,self)
end
local rot_V3 = LuaVector3();
function FunctionFood:HandleStartSkill(evt)
local creature = evt.data;
if(creature == Game.Myself)then
local skill = creature.skill;
local skillId = skill and skill:GetSkillID();
if(skillId and Table_Skill[skillId] and Table_Skill[skillId].SkillType == "Eat")then
local myTrans = Game.Myself.assetRole.completeTransform
local viewPort = CameraConfig.FoodEat_ViewPort
rot_V3:Set(CameraConfig.FoodEat_Rotation_OffsetX, CameraConfig.FoodEat_Rotation_OffsetY, 0);
self.cft = CameraEffectFocusAndRotateTo.new(myTrans, nil, viewPort, rot_V3, CameraConfig.UI_Duration);
FunctionCameraEffect.Me():Start(self.cft);
end
end
end
function FunctionFood:HandleStopSkill(evt)
local creature = evt.data;
if(creature == Game.Myself)then
local skill = creature.skill;
local skillId = skill and skill:GetSkillID();
if(skillId and Table_Skill[skillId] and Table_Skill[skillId].SkillType == "Eat")then
if(self.cft)then
FunctionCameraEffect.Me():End(self.cft);
self.cft = nil;
end
end
end
end
function FunctionFood.SortRecipes(a,b)
return a.id < b.id;
end
function FunctionFood:DoMakeFood(potType, material_guids, skipAnim, recipeMap)
self.lastPotType = potType;
-- local guidStr = ""
-- for i=1,#material_guids do
-- guidStr = guidStr .. material_guids[i];
-- if i<#material_guids then
-- guidStr = guidStr .. ","
-- end
-- end
-- helplog(string.format("DoMakeFood: PotType:%s | RecipeID:%s | material_guids = {%s} | material_itemids = {%s} | skilAnim = %s",
-- potType, recipeId, guidStr, itemidStr, skipAnim));
ServiceSceneFoodProxy.Instance:CallStartCook(potType, material_guids, skipAnim, recipeMap);
end
function FunctionFood:GetLastPotType()
return self.lastPotType;
end
function FunctionFood:UpdateMakeState(playerid, server_CookStateMsg)
local potEffectInfo = self.potEffectMap[ playerid ];
local state = server_CookStateMsg.state;
local scenePlayer = NSceneUserProxy.Instance:Find(playerid);
local isMine = false;
if(playerid == Game.Myself.data.id)then
isMine = true;
GameFacade.Instance:sendNotification(FoodEvent.MakeStateChange, server_CookStateMsg);
else
scenePlayer = NSceneUserProxy.Instance:Find(playerid);
end
if(scenePlayer == nil)then
if(potEffectInfo ~= nil and potEffectInfo[1] ~= nil)then
potEffectInfo[1]:Destroy();
end
return;
end
local cooktype = server_CookStateMsg.cooktype;
if(state == SceneFood_pb.ECOOKSTATE_NONE)then
if(potEffectInfo~=nil and potEffectInfo[1]~=nil)then
potEffectInfo[1]:Destroy();
end
if(isMine)then
GameFacade.Instance:sendNotification(UIEvent.CloseUI, UIViewType.NormalLayer);
end
return;
elseif(state == SceneFood_pb.ECOOKSTATE_PREPAREING)then
if(cooktype == nil or cooktype ==0)then
if(potEffectInfo~=nil and potEffectInfo[1]~=nil)then
potEffectInfo[1]:Destroy();
end
return;
end
end
if(cooktype)then
if(potEffectInfo == nil)then
potEffectInfo = {};
self:PlayPotEffect(scenePlayer, cooktype, potEffectInfo);
self.potEffectMap[playerid] = potEffectInfo;
elseif(potEffectInfo[2] ~= cooktype)then
potEffectInfo[1]:Destroy();
potEffectInfo[3] = false
self:PlayPotEffect(scenePlayer, cooktype, potEffectInfo);
self.potEffectMap[playerid] = potEffectInfo;
end
end
if(potEffectInfo == nil)then
return;
end
local progress = server_CookStateMsg.progress;
local success = server_CookStateMsg.success;
if(state == SceneFood_pb.ECOOKSTATE_PREPAREING)then
potEffectInfo[1]:ResetAction(PotEffect_Action.Prepareing, 0);
if(potEffectInfo[3])then
scenePlayer:Client_PlayAction(Role_Perform.ActionName_Prepareing, nil, false);
else
potEffectInfo[4] = Role_Perform.ActionName_Prepareing;
end
if(potEffectInfo[6])then
potEffectInfo[6]:Destroy();
potEffectInfo[6] = nil;
end
elseif(state == SceneFood_pb.ECOOKSTATE_COOKING)then
potEffectInfo[1]:ResetAction(PotEffect_Action.Cooking, 0);
scenePlayer:Client_PlayAction(Role_Perform.ActionName_Cooking, nil, false);
if(potEffectInfo[6])then
potEffectInfo[6]:Destroy();
potEffectInfo[6] = nil;
end
elseif(state == SceneFood_pb.ECOOKSTATE_COMPLETE)then
local actionName,soundName,parentname;
if(success)then
parentname = "liaoli_get";
potEffectInfo[1]:ResetAction(PotEffect_Action.Compelete_Success, 0);
actionName = Role_Perform.ActionName_Compelete_Success;
soundName = Role_Perform.SoundPath_Compelete_TopEP_Success;
else
parentname = "liaoli_fail";
potEffectInfo[1]:ResetAction(PotEffect_Action.Compelete_Fail, 0);
actionName = Role_Perform.ActionName_Compelete_Fail;
soundName = Role_Perform.SoundPath_Compelete_TopEP_Fail;
end
if(isMine)then
AudioUtility.PlayOneShot2D_Path( ResourcePathHelper.AudioSE(soundName) );
end
if(actionName)then
-- TableUtil.Print(server_CookStateMsg.foodid)
if #server_CookStateMsg.foodid > 1 then
local foodid = server_CookStateMsg.foodid[1];
-- helplog("===UpdateMakeState===foodid>>>", foodid)
local npcid = Table_Food[foodid].NpcId;
self:DelayRolePlayAction(2, playerid, actionName, function ()
if(potEffectInfo[6])then
potEffectInfo[6]:Destroy();
potEffectInfo[6] = nil;
end
if(potEffectInfo[1] == nil)then
return;
end
local effectHandle = potEffectInfo[1]:GetEffectHandle();
if(effectHandle)then
local npcdata = Table_Npc[npcid];
if(npcdata == nil)then
return;
end
local parent = GameObjectUtil.Instance:DeepFind(effectHandle.gameObject, parentname);
if(parent == nil)then
return;
end
potEffectInfo[6] = Asset_RolePart.Create( Asset_Role.PartIndex.Body, npcdata.Body, self.ModelCreateCall, self)
potEffectInfo[6]:SetLayer(parent.gameObject.layer);
potEffectInfo[6]:ResetParent(parent.transform);
potEffectInfo[6]:ResetLocalPositionXYZ(0,0,0);
local scale = npcdata.Scale or 1;
potEffectInfo[6]:ResetLocalScaleXYZ(scale*0.5, scale*0.5, scale*0.5);
potEffectInfo[6]:ResetLocalEulerAnglesXYZ(0,0,0);
potEffectInfo[6]:RegisterWeakObserver(self);
end
end);
end
end
end
end
function FunctionFood.ModelCreateCall(rolePart, self)
if(rolePart)then
local nameHash = ActionUtility.GetNameHash("state1002")
rolePart:PlayAction(nameHash, nameHash, 1, 0);
end
end
function FunctionFood:DelayRolePlayAction(delaytime, playerid, actionName, callback, calbackParam)
if(self.lt)then
self.lt:cancel();
self.lt = nil;
end
self.lt = LeanTween.delayedCall(delaytime, FunctionFood._RolePlayAction);
self.lt.onCompleteParam = {self, playerid, actionName, callback, calbackParam};
end
function FunctionFood._RolePlayAction(onCompleteParam)
local self, playerid, actionName, callback, calbackParam = onCompleteParam[1], onCompleteParam[2], onCompleteParam[3], onCompleteParam[4], onCompleteParam[5];
local scenePlayer = NSceneUserProxy.Instance:Find(playerid);
if(scenePlayer)then
scenePlayer:Client_PlayAction(actionName, nil, false);
end
if(callback)then
callback(calbackParam);
end
if(self.lt)then
self.lt = nil;
end
end
function FunctionFood:PlayPotEffect( scenePlayer, potType, effectInfo )
-- 播放特效
local path = PotEffect_Path[potType];
if(path)then
effectInfo[1] = scenePlayer.assetRole:PlayEffectOn(
path,
0,
nil,
FunctionFood._RealPlayPotEffect,
{scenePlayer, effectInfo});
effectInfo[1]:ResetLocalPositionXYZ(0,0,1);
effectInfo[1]:RegisterWeakObserver(self);
effectInfo[2] = potType;
end
end
function FunctionFood._RealPlayPotEffect(effectHandle, param)
local scenePlayer, effectInfo = param[1], param[2];
if(scenePlayer and effectInfo)then
effectInfo[3] = true;
if(effectInfo[4])then
scenePlayer:Client_PlayAction(effectInfo[4], nil, false);
effectInfo[4] = nil;
end
if(effectInfo[5])then
end
end
end
function FunctionFood:ObserverDestroyed(effect)
for key,effectInfo in pairs(self.potEffectMap)do
if(effectInfo[1] == effect)then
if(effectInfo[6] ~= nil)then
effectInfo[6]:Destroy();
effectInfo[6] = nil;
end
self.potEffectMap[key] = nil;
break;
elseif(effectInfo[6] == effect)then
effectInfo[6] = nil;
end
end
end
function FunctionFood:MatchRecipe(type, itemIdCountList)
local itemids
local recipes = type and self.recipe_Type_Map[type];
if(recipes == nil)then
return;
end
local filter_Recipes = {};
local copyItemCountlist = {};
for i=1, #itemIdCountList do
copyItemCountlist[#copyItemCountlist + 1] = {itemId = itemIdCountList[i].itemId, num = itemIdCountList[i].num}
end
local items_totalCount = 0
for i=1,#copyItemCountlist do
items_totalCount = items_totalCount + copyItemCountlist[i].num
end
local materials, materials_totalCount;
--遍歷配方,找符合要求的,種類篩選
for i=1,#recipes do
local recipeData = recipes[i];
materials = recipeData.Material;
materials_totalCount = self.recipe_totalCount_Map[ recipeData.id ];
if(materials_totalCount and materials_totalCount<=items_totalCount)then
local recipe = {};
recipe[1] = recipeData.id;
recipe[2] = 0;
local cpyMaterial = {};
for i=1, #materials do
cpyMaterial[i] = {};
TableUtility.ArrayShallowCopy(cpyMaterial[i], materials[i]);
end
recipe[3] = cpyMaterial;
-- 先篩選數量
table.insert(filter_Recipes, recipe);
end
end
local resultRecipes = {};
-- local itemid;
local sData, score;
--選出可以做的配方
local itemsIndex = #copyItemCountlist;
for i=1,itemsIndex do
itemidcount = copyItemCountlist[i]; --itemid
for j=1, #filter_Recipes do
materials = filter_Recipes[j][3];
if(materials)then
local isMatched = true;
for _, material in pairs(materials)do
if(material[3] > 0)then
if(material[1] == 1)then
if(itemidcount.itemId == material[2])then
material[3] = math.max(material[3] - itemidcount.num, 0); -- 減一定數量
filter_Recipes[j][2] = filter_Recipes[j][2] + 10 + (itemsIndex - i);
end
elseif(material[1] == 2)then
sData = Table_Item[itemidcount.itemId];
if(sData.Type == material[2])then
material[3] = math.max(material[3] - itemidcount.num, 0);
filter_Recipes[j][2] = filter_Recipes[j][2] + 10 + (itemsIndex - i);
end
end
if(material[3] > 0)then
isMatched = false;
end
end
end
if(isMatched)then
table.insert(resultRecipes, filter_Recipes[j]);
filter_Recipes[j][3] = nil;
end
end
end
end
--選擇權重最大的
-- local resultRecipeID;
-- local maxWeight = 0, 0;
-- for i=1,#resultRecipes do
-- local id, weight = resultRecipes[i][1], resultRecipes[i][2], resultRecipes[i][3];
-- helplog("ResultRecipe:", id, weight);
-- resultRecipes[i][2]
-- -- if(weight > maxWeight)then
-- -- maxWeight = weight;
-- -- resultRecipeID = id;
-- -- end
-- end
table.sort(resultRecipes, function (x, y)
return x[2] > y[2]
end)
--選出權重列表以後, 減去最大量
local resultRecipeIDCountMap = {}
for i=1,#resultRecipes do
local totallv = 0
local totalCount = 0
for i=1,#copyItemCountlist do
local itemIdCount = copyItemCountlist[i]
totalCount = totalCount + itemIdCount.num
local materialInfo = FoodProxy.Instance:Get_MaterialExpInfo(itemIdCount.itemId);
if(materialInfo)then
totallv = materialInfo.level * itemIdCount.num + totallv
else
totallv = totallv + itemIdCount.num;
end
end
if totalCount >0 then
local avgmateriallv = totallv/totalCount
local recCount = self:GetMaxRecipeCount( resultRecipes[i][1], copyItemCountlist)
if recCount > 0 then
resultRecipeIDCountMap[#resultRecipeIDCountMap + 1] = { recipeId = resultRecipes[i][1], num = recCount, avgMatLevel = avgmateriallv}
end
end
end
--{ recipid, recipNum}
--每個配方單獨計算概率, 食材等級 計算 概率
return resultRecipeIDCountMap;
end
function FunctionFood:GetMaxRecipeCount( recipeId, itemCountList )
local recipeData = Table_Recipe[recipeId]
if recipeData then
local materials = recipeData.Material
local minPecipeCount = 99999999
for _, material in pairs(materials)do
if(material[3] > 0)then
-- id 型別
if(material[1] == 1)then
for i=1, #itemCountList do
local itemidcount = itemCountList[i]
if(itemidcount.itemId == material[2])then
local newRecipeCount = math.floor(itemidcount.num/material[3])
if newRecipeCount < minPecipeCount then
minPecipeCount = newRecipeCount
end
end
end
-- type 型別
elseif(material[1] == 2)then
local newRecipeCount = 0
for i=1, #itemCountList do
local itemidcount = itemCountList[i]
local sData = Table_Item[itemidcount.itemId];
if(sData.Type == material[2])then
local matTimes = math.floor(itemidcount.num/material[3])
newRecipeCount = newRecipeCount + matTimes
end
end
if newRecipeCount < minPecipeCount then
minPecipeCount = newRecipeCount
end
end
end
end
if minPecipeCount == 99999999 then
return 0;
end
for _, material in pairs(materials)do
if(material[3] > 0)then
-- id 型別
if(material[1] == 1)then
for i=1, #itemCountList do
local itemidcount = itemCountList[i]
if(itemidcount.itemId == material[2])then
itemidcount.num = itemidcount.num - material[3] * minPecipeCount
end
end
-- type 型別
elseif(material[1] == 2)then
local leftRecipeCount = minPecipeCount
for i=1, #itemCountList do
local itemidcount = itemCountList[i]
local sData = Table_Item[itemidcount.itemId];
if(sData.Type == material[2])then
local matTimes = math.floor(itemidcount.num/material[3])
itemidcount.num = itemidcount.num - material[3] * math.min(matTimes, leftRecipeCount)
if matTimes > leftRecipeCount then
break;
else
leftRecipeCount = leftRecipeCount - matTimes
end
end
end
end
end
end
return minPecipeCount
end
return 0
end
function FunctionFood:GetRecipeByFoodId(foodid)
if(not self.initRecipe_foodkeyMap)then
self.initRecipe_foodkeyMap = true;
self.recipe_foodkeyMap = {};
for id, recipeData in pairs(Table_Recipe)do
local productid = recipeData.Product;
self.recipe_foodkeyMap[productid] = recipeData;
end
end
return self.recipe_foodkeyMap[foodid];
end
function FunctionFood:Match_MakeNum(recipeid)
local recipeData = Table_Recipe[recipeid];
local material = recipeData.Material;
local bagProxy = BagProxy.Instance;
local resultNum;
local items;
for i=1,#material do
local m = material[i];
local num = 0;
if(m[1] == 1)then
num = bagProxy:GetItemNumByStaticID(m[2], BagProxy.BagType.Food);
num = math.floor(num/m[3]);
elseif(m[1] == 2)then
local itype = m[2]
items = bagProxy:GetBagItemsByType(itype, BagProxy.BagType.Food)
for i=1,#items do
num = num + items[i].num;
end
num = math.floor(num/m[3]);
end
if(resultNum == nil)then
resultNum = num;
else
resultNum = math.min(num, resultNum);
end
end
return resultNum;
end
function FunctionFood:CalculateSuccessRate()
return 0;
end
function FunctionFood:AccessFoodNpc(target)
GameFacade.Instance:sendNotification(UIEvent.JumpPanel, {view = PanelConfig.EatFoodPopUp, viewdata = {npcguid = target.data.id}});
end
function FunctionFood:UnLockRecipe(recipeId)
local recipeData = Table_Recipe[recipeId];
if(recipeData == nil)then
return;
end
local itemData = Table_Item[recipeData.Product];
if(itemData == nil)then
return;
end
local data = {};
data.icontype = 1;
data.icon = itemData.Icon;
data.content = string.format(ZhString.FunctionFood_UnLockRecipe, recipeData.Name);
GameFacade.Instance:sendNotification(UIEvent.ShowUI, {viewname = "SystemUnLockView"})
GameFacade.Instance:sendNotification(SystemUnLockEvent.CommonUnlockInfo, data);
end
function FunctionFood.Material_LvUp(itemid, lv, playAnim)
-- if(not playAnim)then
-- return;
-- end
-- GameFacade.Instance:sendNotification(FoodEvent.MaterialExp_LvUp);
-- -- local icon, datas, effectIndex, content = viewdata.icon, viewdata.datas, viewdata.effectIndex, viewdata.content;
-- local data = {};
-- local itemData = Table_Item[itemid];
-- data.icontype = 1;
-- data.icon = itemData.Icon;
-- data.content = string.format(ZhString.FunctionFood_FoodCookLvUp, itemData.NameZh, lv);
-- GameFacade.Instance:sendNotification(UIEvent.ShowUI, {viewname = "SystemUnLockView"})
-- GameFacade.Instance:sendNotification(SystemUnLockEvent.CommonUnlockInfo, data);
end
function FunctionFood.FoodCook_LvUp(itemid, lv, playAnim)
if(not playAnim)then
return;
end
GameFacade.Instance:sendNotification(FoodEvent.FoodCookExp_LvUp);
-- local icon, datas, effectIndex, content = viewdata.icon, viewdata.datas, viewdata.effectIndex, viewdata.content;
local data = {};
local itemData = Table_Item[itemid];
data.icontype = 1;
data.icon = itemData.Icon;
data.content = string.format(ZhString.FunctionFood_FoodCookLvUp, itemData.NameZh, lv);
GameFacade.Instance:sendNotification(UIEvent.ShowUI, {viewname = "SystemUnLockView"})
GameFacade.Instance:sendNotification(SystemUnLockEvent.CommonUnlockInfo, data);
end
function FunctionFood.FoodEat_LvUp(itemid, lv, playAnim)
if(not playAnim)then
return;
end
GameFacade.Instance:sendNotification(FoodEvent.FoodEatExp_LvUp);
-- local icon, datas, effectIndex, content = viewdata.icon, viewdata.datas, viewdata.effectIndex, viewdata.content;
local data = {};
local itemData = Table_Item[itemid];
data.icontype = 1;
data.icon = itemData.Icon;
data.content = string.format(ZhString.FunctionFood_FoodTasteLvUp, itemData.NameZh, lv);
GameFacade.Instance:sendNotification(UIEvent.ShowUI, {viewname = "SystemUnLockView"})
GameFacade.Instance:sendNotification(SystemUnLockEvent.CommonUnlockInfo, data);
end
function FunctionFood.MyCookerLvChange(oldvalue, newvalue)
if(not Table_CookerLevel[newvalue])then
return;
end
AudioUtility.PlayOneShot2D_Path( ResourcePathHelper.AudioSE("Common/FoodLvUp") );
Game.Myself.assetRole:PlayEffectOneShotOn(EffectMap.Maps.CookLvUp, RoleDefines_EP.Top);
GameFacade.Instance:sendNotification(UIEvent.ShowUI, {viewname = "FoodMakeLvUpPopUp", cooklv = newvalue})
end
function FunctionFood.MyTasterLvChange(oldvalue, newvalue)
if(not Table_TasterLevel[newvalue])then
return;
end
AudioUtility.PlayOneShot2D_Path( ResourcePathHelper.AudioSE("Common/FoodLvUp") );
Game.Myself.assetRole:PlayEffectOneShotOn(EffectMap.Maps.EatLvUp, RoleDefines_EP.Top);
GameFacade.Instance:sendNotification(UIEvent.ShowUI, {viewname = "FoodTastLvUpPopUp", tasterlv = newvalue})
end