diff --git a/Contents/mods/CommunityAPI/media/lua/shared/CommunityAPIShared.lua b/Contents/mods/CommunityAPI/media/lua/shared/CommunityAPIShared.lua index 6110378..5352207 100644 --- a/Contents/mods/CommunityAPI/media/lua/shared/CommunityAPIShared.lua +++ b/Contents/mods/CommunityAPI/media/lua/shared/CommunityAPIShared.lua @@ -14,6 +14,9 @@ CommunityAPI.Utils = { CommunityAPI.Shared = { BodyLocations = require("BodyLocationsAPI/BodyLocationsAPIShared"), Event = require("EventAPI/EventAPIShared"), + Perk = require("PerkAPI/PerkAPIClient"), + Profession = require("ProfessionAPI/ProfessionAPIClient"), + Trait = require("TraitAPI/TraitAPIClient"), } ----------------------------------------------------------------------------------- diff --git a/Contents/mods/CommunityAPI/media/lua/shared/PerkAPI/InitPerks.lua b/Contents/mods/CommunityAPI/media/lua/shared/PerkAPI/InitPerks.lua new file mode 100644 index 0000000..d0c4298 --- /dev/null +++ b/Contents/mods/CommunityAPI/media/lua/shared/PerkAPI/InitPerks.lua @@ -0,0 +1,23 @@ +require("CommunityAPI") +local PerkAPI = CommunityAPI.Shared.Perk +local EventAPI = CommunityAPI.Shared.Event + +local function PerkAPIAddPerks() + for categoryName, categoryPerksData in pairs(PerkAPI.PerkList) do + -- Add base category perk. If exist - get from Perks + local categoryPerk = Perks.FromString(categoryName) + if tostring(categoryPerk) == "MAX" then + Perk.new(categoryName) + categoryPerk = Perks.FromString(categoryName) + PerkFactory.AddPerk(categoryPerk, categoryName, Perks.None, 50, 100, 200, 500, 1000, 2000, 3000, 4000, 5000, 6000); + end + + for _, perkData in ipairs(categoryPerksData) do + Perk.new(perkData[1]) + PerkFactory.AddPerk(Perks.FromString(perkData[1]), perkData[1], categoryPerk, perkData[2], perkData[3], perkData[4], perkData[5], perkData[6], perkData[7], perkData[8], perkData[9], perkData[10], perkData[11]) + end + end + EventAPI.Trigger("CommunityAPI", "OnInitCustomPerks") -- Trigger event for start init traits +end + +Events.OnGameBoot.Add(PerkAPIAddPerks) diff --git a/Contents/mods/CommunityAPI/media/lua/shared/PerkAPI/PerkAPIClient.lua b/Contents/mods/CommunityAPI/media/lua/shared/PerkAPI/PerkAPIClient.lua new file mode 100644 index 0000000..fa5bd5f --- /dev/null +++ b/Contents/mods/CommunityAPI/media/lua/shared/PerkAPI/PerkAPIClient.lua @@ -0,0 +1,41 @@ +---@class PerkAPI +local PerkAPI = {} +PerkAPI.PerkList = {} + +--- Adds perk. If not write xp for levels - will set default: 50, 100, 200, 500, 1000, 2000, 3000, 4000, 5000, 6000 +---@param perkName string +---@param categoryName string +---@param _xpLvl1 number +---@param _xpLvl2 number +---@param _xpLvl3 number +---@param _xpLvl4 number +---@param _xpLvl5 number +---@param _xpLvl6 number +---@param _xpLvl7 number +---@param _xpLvl8 number +---@param _xpLvl9 number +---@param _xpLvl10 number +---@return nil +function PerkAPI.AddPerk(perkName, categoryName, _xpLvl1, _xpLvl2, _xpLvl3, _xpLvl4, _xpLvl5, _xpLvl6, _xpLvl7, _xpLvl8, _xpLvl9, _xpLvl10) + if tostring(Perks.FromString(perkName)) ~= "MAX" then return end -- Don't add default skills again + + -- Set default skill lvl requirements + if _xpLvl1 == nil then + _xpLvl1, _xpLvl2, _xpLvl3, _xpLvl4, _xpLvl5, _xpLvl6, _xpLvl7, _xpLvl8, _xpLvl9, _xpLvl10 = 50, 100, 200, 500, 1000, 2000, 3000, 4000, 5000, 6000 + end + + if PerkAPI.PerkList[categoryName] == nil then + PerkAPI.PerkList[categoryName] = {} + end + table.insert(PerkAPI.PerkList[categoryName], { perkName, _xpLvl1, _xpLvl2, _xpLvl3, _xpLvl4, _xpLvl5, _xpLvl6, _xpLvl7, _xpLvl8, _xpLvl9, _xpLvl10 }) +end + +--- Get perk by name +---@param perkName string +---@return any PerkFactory.Perk Java object +function PerkAPI.GetPerk(perkName) + if Perks.FromString(perkName) == Perks.getMaxIndex() then return nil end + return Perks.FromString(perkName) +end + +return PerkAPI diff --git a/Contents/mods/CommunityAPI/media/lua/shared/ProfessionAPI/InitProfessions.lua b/Contents/mods/CommunityAPI/media/lua/shared/ProfessionAPI/InitProfessions.lua new file mode 100644 index 0000000..2a4cf6f --- /dev/null +++ b/Contents/mods/CommunityAPI/media/lua/shared/ProfessionAPI/InitProfessions.lua @@ -0,0 +1,65 @@ +local EventAPI = CommunityAPI.Shared.Event + +local function ProfessionAPI_InitProfessions() + require("CommunityAPI") + local ProfessionAPI = CommunityAPI.Shared.Profession + + -- Set default professions + local profList = ProfessionFactory.getProfessions() + for i=1, profList:size() do + local profObj = profList:get(i-1) + local profObjType = profObj:getType() + + local profAPIObj = ProfessionAPI.ProfessionList[profObjType] + + if profAPIObj == nil then + ProfessionAPI.ProfessionList[profObjType] = ProfessionAPI.Profession:new(profObjType) + profAPIObj = ProfessionAPI.ProfessionList[profObjType] + + profAPIObj:setUIName(profObj:getName()) + profAPIObj:setTextureName(profObj:getIconPath()) + profAPIObj:setProfessionScoreCost(profObj:getCost()) + + if ProfessionAPI.ChangeItemCostList[profObjType] ~= nil then + profAPIObj:setItemScoreCost(ProfessionAPI.ChangeItemCostList[profObjType]) + else + profAPIObj:setItemScoreCost(-profObj:getCost()) + end + + local freeTraits = profObj:getFreeTraits() + for j=0, freeTraits:size()-1 do + profAPIObj:addFreeTrait(freeTraits:get(j)) + end + + local table = transformIntoKahluaTable(profObj:getXPBoostMap()) + for perk, value in pairs(table) do + profAPIObj:addXPBoost(perk:getId(), value) + end + + local freeRecipes = profObj:getFreeRecipes() + for j=0, freeRecipes:size()-1 do + profAPIObj:addRecipe(freeRecipes:get(j)) + end + end + end + + for profName, profAPIObj in pairs(ProfessionAPI.ProfessionList) do + local professionObj = ProfessionFactory.addProfession(profName, profAPIObj.UIName, profAPIObj.textureName, profAPIObj.professionScoreCost) + + for _, boostData in ipairs(profAPIObj.xpBoosts) do + professionObj:addXPBoost(Perks.FromString(boostData[1]), boostData[2]) + end + + for _, freeTrait in ipairs(profAPIObj.freeTraits) do + professionObj:addFreeTrait(freeTrait); + end + + for _, recipeName in ipairs(profAPIObj.freeRecipes) do + professionObj:getFreeRecipes():add(recipeName) + end + + BaseGameCharacterDetails.SetProfessionDescription(professionObj) + end +end + +EventAPI.Add("CommunityAPI", "OnInitCustomTraits", ProfessionAPI_InitProfessions) diff --git a/Contents/mods/CommunityAPI/media/lua/shared/ProfessionAPI/ProfessionAPIClient.lua b/Contents/mods/CommunityAPI/media/lua/shared/ProfessionAPI/ProfessionAPIClient.lua new file mode 100644 index 0000000..0a7ece8 --- /dev/null +++ b/Contents/mods/CommunityAPI/media/lua/shared/ProfessionAPI/ProfessionAPIClient.lua @@ -0,0 +1,140 @@ +---@class Profession +local Profession = {} + +---@param name string +---@return table +function Profession:new(name) + local o = {} + setmetatable(o, self) + self.__index = self + + o.name = name + o.UIName = "UNDEFINED" + o.textureName = "" + o.professionScoreCost = 0 + o.itemScoreCost = 0 + o.freeTraits = {} + o.xpBoosts = {} + o.freeRecipes = {} + o.specificItems = {} + + o.isFormattedDescription = false + + return o +end + +---@param name string +function Profession:setUIName(name) + self.UIName = getText(name) +end + +---@param name string +function Profession:setTextureName(name) + self.textureName = name +end + +---@param scoreCost number +function Profession:setProfessionScoreCost(scoreCost) + self.professionScoreCost = scoreCost +end + +---Set how many points will give for start items choose (need for Expanded Character Creation) +---@param scoreCost number +function Profession:setItemScoreCost(scoreCost) + self.itemScoreCost = scoreCost +end + +---@param traitName string +function Profession:addFreeTrait(traitName) + table.insert(self.freeTraits, traitName) +end + +---@param perkName string +---@param value string From 1 to 3: 1 = +75%, 2 = +100%, 3 = +125% +function Profession:addXPBoost(perkName, value) + table.insert(self.xpBoosts, { perkName, value }) +end + +---@param recipeName string +function Profession:addRecipe(recipeName) + table.insert(self.freeRecipes, recipeName) +end + +---Adds specific items to start item choose (need for Expanded Character Creation) +---@param itemName string +---@param cost number +function Profession:addSpecificItem(itemName, cost) + self.specificItems[itemName] = cost +end + +--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- + +---@class ProfessionAPI +local ProfessionAPI = {} +ProfessionAPI.ProfessionList = {} +ProfessionAPI.Profession = Profession +ProfessionAPI.ChangeProfessionCostList = {} +ProfessionAPI.ChangeItemCostList = {} +ProfessionAPI.SpecificItemList = {} + +---@param name string +---@return table Profession +function ProfessionAPI.CreateProfession(name) + ProfessionAPI.ProfessionList[name] = Profession:new(name) + return ProfessionAPI.ProfessionList[name] +end + +---@param name string +---@return table Profession +function ProfessionAPI.GetProfession(name) + return ProfessionAPI.ProfessionList[name] +end + + +---Get how many points will give for start items choose (need for Expanded Character Creation). Works with default professions too +---@param name string +---@return number +function ProfessionAPI.GetProfessionItemCost(name) + if ProfessionAPI.ProfessionList[name] == nil then + return 0 + end + return ProfessionAPI.ProfessionList[name].itemScoreCost +end + +---@param name string +---@param cost number +function ProfessionAPI.ChangeProfessionCost(name, cost) + if ProfessionAPI.ProfessionList[name] ~= nil then + ProfessionAPI.ProfessionList[name].professionScoreCost = cost + else + ProfessionAPI.ChangeProfessionCostList[name] = cost + end +end + +---Change how many points will give for start items choose (need for Expanded Character Creation). Works with default professions too +---@param name string +---@param cost number +function ProfessionAPI.ChangeItemCost(name, cost) + if ProfessionAPI.ProfessionList[name] ~= nil then + ProfessionAPI.ProfessionList[name].itemScoreCost = cost + else + ProfessionAPI.ChangeItemCostList[name] = cost + end +end + +---Adds specific items to start item choose (need for Expanded Character Creation). Works with default professions too +---@param professionName string +---@param itemName string +---@param cost number +function ProfessionAPI.AddSpecificItem(professionName, itemName, cost) + if ProfessionAPI.ProfessionList[professionName] ~= nil then + ProfessionAPI.ProfessionList[professionName].specificItems[itemName] = cost + else + if ProfessionAPI.SpecificItemList[professionName] == nil then + ProfessionAPI.SpecificItemList[professionName] = {} + end + ProfessionAPI.SpecificItemList[professionName][itemName] = cost + end +end + +return ProfessionAPI diff --git a/Contents/mods/CommunityAPI/media/lua/shared/TraitAPI/InitTraits.lua b/Contents/mods/CommunityAPI/media/lua/shared/TraitAPI/InitTraits.lua new file mode 100644 index 0000000..cb87c37 --- /dev/null +++ b/Contents/mods/CommunityAPI/media/lua/shared/TraitAPI/InitTraits.lua @@ -0,0 +1,86 @@ +require("CommunityAPI") +local TraitAPI = CommunityAPI.Shared.Trait +local EventAPI = CommunityAPI.Shared.Event + +function TraitAPI_InitTraits() + -- Add default traits as TraitAPIObj + local existTraits = TraitFactory.getTraits() + for i=0, existTraits:size()-1 do + local traitObj = existTraits:get(i) + local traitObjType = traitObj:getType() + local traitAPIObj = TraitAPI.TraitList[traitObjType] + + if traitAPIObj == nil then + TraitAPI.TraitList[traitObjType] = TraitAPI.Trait:new(traitObjType) + traitAPIObj = TraitAPI.TraitList[traitObjType] + + traitAPIObj:setUIName(traitObj:getLabel()) + traitAPIObj:setDescription(traitObj:getDescription()) + traitAPIObj:setIsProfessionTrait(traitObj:isFree()) + traitAPIObj:setRemoveInMP(traitObj:isRemoveInMP()) + + if TraitAPI.ChangeTraitCostList[traitObjType] ~= nil then + traitAPIObj:setTraitScoreCost(TraitAPI.ChangeTraitCostList[traitObjType]) + else + traitAPIObj:setTraitScoreCost(traitObj:getCost()) + end + + local incompTraits = traitObj:getMutuallyExclusiveTraits() + for j=0, incompTraits:size()-1 do + traitAPIObj:addIncompatibleTrait(incompTraits:get(j)) + end + + local table = transformIntoKahluaTable(traitObj:getXPBoostMap()) + for perk, value in pairs(table) do + traitAPIObj:addXPBoost(perk:getId(), value) + end + + local freeRecipes = traitObj:getFreeRecipes() + for j=0, freeRecipes:size()-1 do + traitAPIObj:addRecipe(freeRecipes:get(j)) + end + + if TraitAPI.ChangeItemCostList[traitObjType] ~= nil then + traitAPIObj:setItemScoreCost(TraitAPI.ChangeItemCostList[traitObjType]) + else + if traitAPIObj.traitScoreCost > 0 then + traitAPIObj:setItemScoreCost(-1) + else + traitAPIObj:setItemScoreCost(1) + end + end + + if TraitAPI.SpecificItemList[traitObjType] ~= nil then + for itemName, cost in pairs(TraitAPI.SpecificItemList[traitObjType]) do + traitAPIObj:addSpecificItem(itemName, cost) + end + end + + traitAPIObj.isFormattedDescription = true + end + end + + for traitName, traitAPIObj in pairs(TraitAPI.TraitList) do + local traitObj = TraitFactory.addTrait(traitAPIObj.name, traitAPIObj.UIName, traitAPIObj.traitScoreCost, traitAPIObj.UIDescriptionName, traitAPIObj.isProfessionTrait, traitAPIObj.removeInMP) + + for _, boostData in ipairs(traitAPIObj.xpBoosts) do + traitObj:addXPBoost(Perks.FromString(boostData[1]), boostData[2]) + end + + for _, incompatibleTrait in ipairs(traitAPIObj.incompatibleTraits) do + TraitFactory.setMutualExclusive(traitName, incompatibleTrait) + end + + for _, recipeName in ipairs(traitAPIObj.freeRecipes) do + traitObj:getFreeRecipes():add(recipeName) + end + + if not traitAPIObj.isFormattedDescription then + BaseGameCharacterDetails.SetTraitDescription(traitObj) + end + end + + EventAPI.Trigger("CommunityAPI", "OnInitCustomTraits") -- Trigger event for start Profession init +end + +EventAPI.Add("CommunityAPI", "OnInitCustomPerks", TraitAPI_InitTraits) diff --git a/Contents/mods/CommunityAPI/media/lua/shared/TraitAPI/TraitAPIClient.lua b/Contents/mods/CommunityAPI/media/lua/shared/TraitAPI/TraitAPIClient.lua new file mode 100644 index 0000000..9460d0a --- /dev/null +++ b/Contents/mods/CommunityAPI/media/lua/shared/TraitAPI/TraitAPIClient.lua @@ -0,0 +1,155 @@ +---@class Trait +local Trait = {} + +---@param name string +---@return table +function Trait:new(name) + local o = {} + setmetatable(o, self) + self.__index = self + + o.name = name + o.UIName = "UNDEFINED" + o.UIDescriptionName = "UNDEFINED" + o.traitScoreCost = 0 + o.itemScoreCost = 0 + o.isProfessionTrait = false + o.removeInMP = false + + o.incompatibleTraits = {} + o.xpBoosts = {} + o.freeRecipes = {} + o.specificItems = {} + + o.isFormattedDescription = false + + return o +end + +---@param name string +function Trait:setUIName(name) + self.UIName = getText(name) +end + +---@param description string +function Trait:setDescription(descriptionName) + self.UIDescriptionName = getText(descriptionName) +end + +---@param scoreCost number +function Trait:setTraitScoreCost(scoreCost) + self.traitScoreCost = scoreCost +end + +---Set how many points will give for start items choose (need for Expanded Character Creation) +---@param scoreCost number +function Trait:setItemScoreCost(scoreCost) + self.itemScoreCost = scoreCost +end + +---If true, then the player will not be able to choose trait. Need for add trait only by profession (Don't foget add trait in when create new/change old Profession!) +---@param value boolean +function Trait:setIsProfessionTrait(value) + self.isProfessionTrait = value +end + +---If true - will be removed in Multiplayer +---@param value boolean +function Trait:setRemoveInMP(value) + self.removeInMP = value +end + +---@param traitName string +function Trait:addIncompatibleTrait(traitName) + table.insert(self.incompatibleTraits, traitName) +end + +---@param perkName string +---@param value number From 1 to 3: 1 = +75%, 2 = +100%, 3 = +125% +function Trait:addXPBoost(perkName, value) + table.insert(self.xpBoosts, { perkName, value }) +end + +---@param recipeName string +function Trait:addRecipe(recipeName) + table.insert(self.freeRecipes, recipeName) +end + +---Adds specific items to start item choose (need for Expanded Character Creation) +---@param itemName string +---@param cost number +function Trait:addSpecificItem(itemName, cost) + self.specificItems[itemName] = cost +end + +--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- +---@class TraitAPI +local TraitAPI = {} +TraitAPI.Trait = Trait +TraitAPI.TraitList = {} +TraitAPI.ChangeTraitCostList = {} +TraitAPI.ChangeItemCostList = {} +TraitAPI.SpecificItemList = {} + + +---@param name string +---@return table Trait +function TraitAPI.CreateTrait(name) + TraitAPI.TraitList[name] = Trait:new(name) + return TraitAPI.TraitList[name] +end + +---@param name string +---@return table Trait +function TraitAPI.GetTrait(name) + return TraitAPI.TraitList[name] +end + +---Change trait cost without full rewriting trait. Works with default traits +---@param name string +---@param cost number +function TraitAPI.ChangeTraitCost(name, cost) + if TraitAPI.TraitList[name] ~= nil then + TraitAPI.TraitList[name].traitScoreCost = cost + else + TraitAPI.ChangeTraitCostList[name] = cost + end +end + +---Change how many points will give for start items choose (need for Expanded Character Creation). Works with default traits too +---@param name string +---@param cost number +function TraitAPI.ChangeItemCost(name, cost) + if TraitAPI.TraitList[name] ~= nil then + TraitAPI.TraitList[name].itemScoreCost = cost + else + TraitAPI.ChangeItemCostList[name] = cost + end +end + +---Get how many points will give for start items choose (need for Expanded Character Creation). Works with default traits too +---@param name string +---@return number +function TraitAPI.GetTraitItemCost(name) + if TraitAPI.TraitList[name] == nil then + return 0 + end + return TraitAPI.TraitList[name].itemScoreCost +end + +---Adds specific items to start item choose (need for Expanded Character Creation). Works with default traits too +---@param traitName string +---@param itemName string +---@param cost number +function TraitAPI.AddSpecificItem(traitName, itemName, cost) + if TraitAPI.TraitList[traitName] ~= nil then + TraitAPI.TraitList[traitName].specificItems[itemName] = cost + else + if TraitAPI.SpecificItemList[traitName] == nil then + TraitAPI.SpecificItemList[traitName] = {} + end + TraitAPI.SpecificItemList[traitName][itemName] = cost + end +end + +return TraitAPI