Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- this is a hack to get access to production module resource numbers that are not available to MD
- local function GetProductionResources(event, param)
- local data = GetLibraryEntry(GetMacroData(param, "infolibrary"), param)
- AddUITriggeredEvent("faction_fix_pack", "resource_data", {param, data})
- end
- RegisterEvent("GetProductionResources", GetProductionResources)
- -- hack to address the AI shipyard build drones getting lost
- -- hack to set NPC blacklist to a special internal one so traders avoid Xenon sectors
- -- update to make 'sellable' actually respected by the UI
- -- those really shouldn't be in this file, but I don't want to deal with patching the ui.xml again right now
- -- ffi setup
- local ffi = require("ffi")
- local C = ffi.C
- ffi.cdef[[
- typedef uint64_t UniverseID;
- typedef struct {
- const char* macro;
- int amount;
- } SupplyOverride;
- void UpdateSupplyOverrides(UniverseID containerid, SupplyOverride* overrides, uint32_t numoverrides);
- uint32_t GetNumSupplyOrders(UniverseID containerid, bool defaultorders);
- uint32_t GetSupplyOrders(SupplyOverride* result, uint32_t resultlen, UniverseID containerid, bool defaultorders);
- typedef int32_t BlacklistID;
- typedef uint64_t UniverseID;
- typedef struct {
- uint32_t nummacros;
- uint32_t numfactions;
- } BlacklistCounts;
- typedef struct {
- uint32_t id;
- const char* type;
- const char* name;
- bool usemacrowhitelist;
- uint32_t nummacros;
- const char** macros;
- bool usefactionwhitelist;
- uint32_t numfactions;
- const char** factions;
- const char* relation;
- bool hazardous;
- } BlacklistInfo2;
- BlacklistID CreateBlacklist2(BlacklistInfo2 info);
- uint32_t GetAllBlacklists(BlacklistID* result, uint32_t resultlen);
- uint32_t GetNumAllBlacklists(void);
- void UpdateBlacklist2(BlacklistInfo2 info);
- void SetControllableBlacklist(UniverseID controllableid, BlacklistID id, const char* listtype, bool value);
- void RemoveBlacklist(BlacklistID id);
- bool GetBlacklistInfo2(BlacklistInfo2* info, BlacklistID id);
- BlacklistCounts GetBlacklistInfoCounts(BlacklistID id);
- ]]
- local BLACKLIST_NAME = "Internal NPC Blacklist"
- local CachedBlacklistID = -1
- local ExtraFactionBlacklistsCreated = false
- -- todo grab relations from ingame and reset periodically in case they change dynamically?
- local FactionsWithExtraBlacklists = {}
- -- base game factions
- FactionsWithExtraBlacklists["antigone"] = {"holyorder", "holyorderfanatic", "scaleplate", "fallensplit", "split"}
- FactionsWithExtraBlacklists["argon"] = {"holyorder", "holyorderfanatic", "scaleplate", "fallensplit", "split"}
- FactionsWithExtraBlacklists["holyorder"] = {"antigone", "argon", "ministry", "paranid", "scaleplate", "teladi", "fallensplit", "boron"}
- FactionsWithExtraBlacklists["holyorderfanatic"] = {"antigone", "argon", "paranid", "trinity", "fallensplit", "pioneers", "terran", "boron"}
- FactionsWithExtraBlacklists["ministry"] = {"holyorder", "scaleplate", "fallensplit"}
- FactionsWithExtraBlacklists["paranid"] = {"holyorder", "holyorderfanatic", "scaleplate", "fallensplit"}
- FactionsWithExtraBlacklists["teladi"] = {"holyorder", "fallensplit"}
- FactionsWithExtraBlacklists["trinity"] = {"holyorderfanatic", "scaleplate", "fallensplit"}
- -- split
- FactionsWithExtraBlacklists["court"] = {"fallensplit", "scaleplate"}
- FactionsWithExtraBlacklists["fallensplit"] = {"antigone", "argon", "court", "holyorder", "holyorderfanatic", "ministry", "paranid", "split", "teladi", "trinity", "pioneers", "terran", "boron"}
- FactionsWithExtraBlacklists["freesplit"] = {"scaleplate", "boron"}
- FactionsWithExtraBlacklists["split"] = {"antigone", "argon", "court", "fallensplit", "scaleplate", "boron"}
- -- terran
- FactionsWithExtraBlacklists["pioneers"] = {"fallensplit", "holyorderfanatic", "scaleplate"}
- FactionsWithExtraBlacklists["terran"] = {"fallensplit", "holyorderfanatic", "scaleplate"}
- -- boron
- FactionsWithExtraBlacklists["boron"] = {"fallensplit","freesplit","holyorder","holyorderfanatic","scaleplate","split"}
- local BlacklistIDsForSpecificFactions = {}
- local Super_ffiVLA = Helper.ffiVLA
- local function CacheNPCBlacklist()
- local blacklists = {}
- Super_ffiVLA(blacklists, "BlacklistID", C.GetNumAllBlacklists, C.GetAllBlacklists)
- local found = false
- for i = #blacklists, 1, -1 do
- local id = blacklists[i]
- local counts = C.GetBlacklistInfoCounts(id)
- local buf = ffi.new("BlacklistInfo2")
- buf.nummacros = counts.nummacros
- buf.macros = Helper.ffiNewHelper("const char*[?]", counts.nummacros)
- buf.numfactions = counts.numfactions
- buf.factions = Helper.ffiNewHelper("const char*[?]", counts.numfactions)
- if C.GetBlacklistInfo2(buf, id) then
- if ffi.string(buf.name) == BLACKLIST_NAME then
- -- sanity check nobody has messed with it
- --[[ this does not work after all: seems 'relation' is always relative to player, not the ship owner!
- if ffi.string(buf.relation) == "nemesis" then
- ]]
- if buf.numfactions == 1 and ffi.string(buf.factions[0]) == "xenon" then
- CachedBlacklistID = id;
- else
- DebugError("Found NPC blacklist with the appropriate name but incorrect settings, resetting...")
- C.RemoveBlacklist(id)
- end
- end
- for faction in pairs(FactionsWithExtraBlacklists) do
- if ffi.string(buf.name) == (BLACKLIST_NAME .. " " .. faction) then
- BlacklistIDsForSpecificFactions[faction] = id
- ExtraFactionBlacklistsCreated = true
- end
- end
- end
- end
- end
- local function CreateExtraFactionBlacklists()
- for faction in pairs(FactionsWithExtraBlacklists) do
- local blacklist = ffi.new("BlacklistInfo2")
- blacklist.type = Helper.ffiNewString("sectortravel")
- blacklist.name = Helper.ffiNewString(BLACKLIST_NAME .. " " .. faction)
- blacklist.relation = ""
- blacklist.hazardous = false
- blacklist.nummacros = 0
- blacklist.macros = Helper.ffiNewHelper("const char*[?]", blacklist.nummacros)
- local enemyFactions = FactionsWithExtraBlacklists[faction]
- blacklist.numfactions = table.getn(FactionsWithExtraBlacklists[faction]) + 1
- blacklist.factions = Helper.ffiNewHelper("const char*[?]", blacklist.numfactions)
- blacklist.factions[0] = Helper.ffiNewString("xenon")
- for i,enemyFaction in pairs(FactionsWithExtraBlacklists[faction]) do
- blacklist.factions[i] = Helper.ffiNewString(enemyFaction)
- end
- blacklist.usemacrowhitelist = false
- blacklist.usefactionwhitelist = false
- BlacklistIDsForSpecificFactions[faction] = C.CreateBlacklist2(blacklist)
- end
- end
- local function RemoveNPCBlacklist(event, param)
- local NPC = ConvertIDTo64Bit(param)
- C.SetControllableBlacklist(NPC, -1, "sectortravel", false)
- end
- local function SetNPCBlacklist(event, param)
- local NPC = ConvertIDTo64Bit(param)
- local owner = GetComponentData(NPC, "owner")
- -- does not work for Xenon, see below
- -- TODO: could create separate blacklist, but it doesn't seem worth it at the moment
- if owner == "xenon" then
- RemoveNPCBlacklist(event, param)
- return
- end
- if CachedBlacklistID == -1 then
- CacheNPCBlacklist()
- end
- if ExtraFactionBlacklistsCreated == false then
- CreateExtraFactionBlacklists()
- ExtraFactionBlacklistsCreated = true
- end
- local SpecialBlacklistID = BlacklistIDsForSpecificFactions[owner]
- if SpecialBlacklistID ~= nil then
- C.SetControllableBlacklist(NPC, SpecialBlacklistID, "sectortravel", true)
- return
- end
- -- use global default blacklist
- if CachedBlacklistID ~= -1 then
- C.SetControllableBlacklist(NPC, CachedBlacklistID, "sectortravel", true)
- else
- local blacklist = ffi.new("BlacklistInfo2")
- blacklist.type = Helper.ffiNewString("sectortravel")
- blacklist.name = Helper.ffiNewString(BLACKLIST_NAME)
- --[[ this does not work after all: seems 'relation' is always relative to player, not the ship owner!
- -- TODO: 'kill' would theoretically be better but going conservative for now - especially concerned about smugglers (does blacklist use cover owner or true owner? what happens if they get uncovered mid-flight? etc)
- blacklist.relation = Helper.ffiNewString("nemesis")
- blacklist.hazardous = false
- blacklist.nummacros = 0
- blacklist.macros = Helper.ffiNewHelper("const char*[?]", blacklist.nummacros)
- blacklist.numfactions = 0
- blacklist.factions = Helper.ffiNewHelper("const char*[?]", blacklist.numfactions)
- ]]
- blacklist.relation = ""
- blacklist.hazardous = false
- blacklist.nummacros = 0
- blacklist.macros = Helper.ffiNewHelper("const char*[?]", blacklist.nummacros)
- blacklist.numfactions = 1
- blacklist.factions = Helper.ffiNewHelper("const char*[?]", blacklist.numfactions)
- blacklist.factions[0] = Helper.ffiNewString("xenon")
- blacklist.usemacrowhitelist = false
- blacklist.usefactionwhitelist = false
- CachedBlacklistID = C.CreateBlacklist2(blacklist)
- C.SetControllableBlacklist(NPC, CachedBlacklistID, "sectortravel", true)
- end
- end
- RegisterEvent("SetNPCBlacklist", SetNPCBlacklist)
- RegisterEvent("RemoveNPCBlacklist", RemoveNPCBlacklist)
- -- this is ugly but it's the only viable catch point for all places in the UI that request all blacklists
- local function OverrideBlacklistItems(result, vlaType, vlaSizeFunction, vlaFunction, ...)
- Super_ffiVLA(result, vlaType, vlaSizeFunction, vlaFunction, ...)
- if vlaSizeFunction == C.GetNumAllBlacklists and #result then
- if CachedBlacklistID == -1 then
- CacheNPCBlacklist()
- end
- for i = #result, 1, -1 do
- if result[i] == CachedBlacklistID then
- table.remove(result, i)
- end
- -- todo make work
- -- for specialBlackListId in ipairs(BlacklistIDsForSpecificFactions) do
- -- if result[i] == specialBlackListId then
- -- table.remove(result, i)
- -- end
- -- end
- end
- end
- end
- Helper.ffiVLA = OverrideBlacklistItems
- local function FixShipyardBuildDrones(event, param)
- local Shipyard = ConvertIDTo64Bit(param)
- local old_amount = 0
- local n = C.GetNumSupplyOrders(Shipyard, true)
- local buf = ffi.new("SupplyOverride[?]", n)
- n = C.GetSupplyOrders(buf, n, Shipyard, true)
- for i = 0, n - 1 do
- local macro = ffi.string(buf[i].macro)
- if macro == "ship_gen_xs_buildingdrone_01_a_macro" then
- old_amount = buf[i].amount
- end
- end
- local overrides = ffi.new("SupplyOverride[?]", 1)
- overrides[0].macro = Helper.ffiNewString("ship_gen_xs_buildingdrone_01_a_macro")
- if GetComponentData(Shipyard, "isshipyard") then
- if GetComponentData(Shipyard, "owner") == "xenon" then
- overrides[0].amount = math.max(old_amount, 20)
- else
- overrides[0].amount = math.max(old_amount, 50)
- end
- else
- overrides[0].amount = math.max(old_amount, 15)
- end
- C.UpdateSupplyOverrides(Shipyard, overrides, 1)
- Helper.ffiClearNewHelper()
- end
- RegisterEvent("FixShipyardBuildDrones", FixShipyardBuildDrones)
- local menu = nil
- local Funcs = {}
- local territory_data = {}
- local function InitMenu()
- for _, OrigMenu in ipairs(Menus) do
- if OrigMenu.name == "InteractMenu" then
- menu = OrigMenu
- Funcs.Super_insertLuaAction = menu.insertLuaAction
- menu.insertLuaAction = Funcs.insertLuaAction
- break
- end
- end
- end
- function Funcs.insertLuaAction(actiontype, istobedisplayed)
- if actiontype == "sellships" then
- -- copy/paste from the top of the original
- local convertedComponent = ConvertStringTo64Bit(tostring(menu.componentSlot.component))
- local isplayerownedtarget = GetComponentData(convertedComponent, "isplayerowned")
- if #menu.selectedplayerships > 0 then
- if not isplayerownedtarget then
- local shiptrader, isdock, iswharf, isshipyard = GetComponentData(convertedComponent, "shiptrader", "isdock", "iswharf", "isshipyard")
- if shiptrader and isdock and (iswharf or isshipyard) then
- local cansell = false
- for _, ship in ipairs(menu.selectedplayerships) do
- if C.CanContainerBuildShip(menu.componentSlot.component, ship) then
- cansell = true
- break
- end
- end
- if cansell then
- local sellable = true
- local unsellable_list = GetNPCBlackboard(ConvertStringTo64Bit(tostring(C.GetPlayerID())), "$unsellable_ships")
- if unsellable_list then
- for _, selected in ipairs(menu.selectedplayerships) do
- for _, ship in ipairs(unsellable_list) do
- if ConvertStringTo64Bit(tostring(ship)) == selected then
- sellable = false
- break
- end
- end
- if not sellable then
- break
- end
- end
- end
- menu.insertInteractionContent("selected_orders", { type = actiontype, text = (#menu.selectedplayerships == 1) and ReadText(1001, 7855) or ReadText(1001, 7856), helpOverlayID = "interactmenu_sellships", helpOverlayText = " ", helpOverlayHighlightOnly = true, script = menu.buttonSellShips, active = sellable })
- end
- end
- end
- end
- else
- Funcs.Super_insertLuaAction(actiontype, istobedisplayed)
- end
- end
- InitMenu()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement