LoneGazebo / Community-Patch-DLL

Community Patch for Civilization V - Brave New World
Other
280 stars 155 forks source link

On Mercenaries #1679

Closed JFDaly closed 7 years ago

JFDaly commented 8 years ago

I am here with a rundown of what the Mercenaries system would need, if you are still willing and able to incorporate it into the DLL sometime (in response to the issues that I have with TableSaverLoader).

Essentially, the Mercenaries system is a range of 'Contracts' that can be taken out by the player, exchanging Gold for a limited ownership of a particular unit (or units). Contracts are global - only one player can take one Contract at a given time, and they each cost Maintenance. Some also provide resources, to compensate for what would be deficiency otherwise when you contract Mounted Units or units requiring Iron/Oil, etc.

At the moment, I have 1 dummy policy per Contract, which I thought might increase stability (alleviating how much info is cached), but this appears not to be the case - so they're just needlessly cluttering up the database, pushing to that ~256 limit.

The following attributes are variable, and need to be cached: the player that has taken out the contract, the turns remaining on the contract, the maintenance of the contract, the unit assigned to the contract and any associated resources. I do wonder, however, if it would be possible to cut out the cached resources with some sort of unit:SetHasNoResourceRequirement(boolean) function - something to override the unit's resource requirement.

I have a table (JFD_Contracts) set up which stores the contracts in the database. So any functions would need to refer to the IDs of those entries. I consider the following functions to be what I'd need:

Game.SetContractOwner(contractID, playerID) -- would need to support playerID being set to nil. Game.GetContractOwner(contractID) -- returns playerID from the above. Game.SetContractUnit(contractID, unitID) Game.GetContractUnit(contractID) -- returns unitID) from the above Game.SetContractTurns(contractID, value) Game.GetContractTurns(contractID) -- returns value) from the above. Game.SetContractMaintenance(contractID, value) Game.GetContractMaintenance(contractID) -- returns value) from the above

GameEvents.ContractStarts(playerID, contractID)

And If nullifying the resource requirement of specific unit objects is not possible:

Game.SetContractResources(contractID, resourceID, value) Game.GetContractResources(contractID) -- returns resourceID and resource count from the above.

The following things are non-essential, and can be re-created in Lua, but would be convenient:

Game.IsContractActive(contractID) -- checks the playerID of Game.GetContractOwner() and, if null, returns false. Player:HasContract(contractID) -- checks if Game.GetContractOwner() equals this player's ID. GetContractTurns(contractID) should change SetContractTurns each turn by an established Game Define (which would only ever be 1, so could be hardcoded).

GameEvents.ContractEnds.Add(playerID, contractID) -- would only be needed if the turn time decay is automatically set up, and would trigger when that turn time reaches 0.

I'm not asking this to be worked on any time soon, of course, but let me know your thoughts on how possible this looks.

JFDaly commented 7 years ago

Ah, that'll be it - I forgot to invoke DoUpdateContracts(); I was expecting GameEvents.GetContractUnit() to update automatically (just absent-mindedly; it works as intended). However, invoking that (whether manually or automatically via era change) is now causing an infinite loop and the game to freeze.

Without Game.GetContractUnit(), how do I return the unit ID tied to the Contract, for UI purposes?

They might disband, yes. I'm not sure what that function would do, so probably not :p

LoneGazebo commented 7 years ago

I guess if you wanted to create a lua panel to look at all contract units that snaps to their location, you could do that.

I'm revising the memory profile a little for this, gimme a little. Should fix freeze.

LoneGazebo commented 7 years ago

(1) Community Patch (bv3 723).zip

New version. Fixes and additions. Moved memory to game data (Was in player data), so note the change for unit setting/getting from player to game. Disband unit added, but not working 100% at present.

LoneGazebo commented 7 years ago

All changes should be on contracts table.

JFDaly commented 7 years ago

DoUpdateContracts() no longer causes a freeze, but StartContract now appears to have problems - not exactly sure how to describe it. When invoked, the game began to slow down terribly, and units begin to be (stutteringly) spawned on the map (must be going through the units table, as it started with 2 Settlers, and moved onto 2 Workers, 2 Workboats, 2 Great Artists, and so forth).

I also still don't see what I should be using as a subtitute for Game.GetContractUnit().

JFDaly commented 7 years ago

Still encountering the problem described above on the 27th July version. StartContract iterates and attempts to spawn every unit in the Units data table.

LoneGazebo commented 7 years ago

Huh. Sounds like your Lua hook is adding a type of unit for ever

LoneGazebo commented 7 years ago

Crap. Hit comment too early. Sounds like your hook is adding a unit or two to every unit type. It should check to see if the unit type matches your tables unit, and if it does, return a value greater than zero. Otherwise, it should return zero.

Re: Game.GetContractUnit, I'm not sure I understand.

JFDaly commented 7 years ago

Yeap, didn't realise that's how it worked. Thanks. EDIT: Yup, that works better. But the contract units didn't appear to start with their promotion.

Game.GetContractUnit was originally how I retrieved the unit ID tied to the Contract, so I could display that in the UI. But since you removed that method, I'm not sure how to get that info.

LoneGazebo commented 7 years ago

Cool. The promotion should work using the table if the promotion is valid for the unit combat type. Make sure you've set unit combat validity for units.

Regarding getting the unit type, there should be a Lua function for it. Let me get back to you on that.

LoneGazebo commented 7 years ago

Use Game.GetContractUnits(ContractType eContract, UnitType eUnit) to grab the number of a unit type attached to your UI. This will return the integer value from the lua hook we discussed above. You can then use the function to pass any unit type above 0 into your UI reader. Make sense? I did it this way so that you could, theoretically, have different units of different types in the same contract (a la your wikia page).

JFDaly commented 7 years ago

Ah, right. That should be everything covered then. I'll let you know if I have any more trouble.

LoneGazebo commented 7 years ago

Cool.