1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Help creating a unique unit ability

Discussion in 'Civ5 - SDK / LUA' started by CMatthewT, Jan 16, 2021.

  1. CMatthewT

    CMatthewT Chieftain

    Joined:
    Jan 16, 2021
    Messages:
    2
    Hi,

    I'm creating a mod that adds a new Great Person. I want this unit to be able to "construct a wheat farm," that is, set the resource of the tile they're in to wheat and then place a farm on it. In other words, they will be able to instantaneously create an improved wheat tile anywhere a farm can be built regardless of whether wheat was actually on that tile to begin with.

    I understand XML (more or less), and I've successfully created the Great Person and part of the ability.

    XML (abridged):

    <Builds>
    <Row>
    <Type>BUILD_WHEAT</Type>
    <ImprovementType>IMPROVEMENT_FARM</ImprovementType>
    <Description>Construct a Wheat Farm</Description>
    <Help>Unit will be consumed.[NEWLINE][NEWLINE]Will transform this tile into an improved source of [ICON_RES_WHEAT] Wheat.</Help>
    <Kill>1</Kill>
    <EntityEvent>ENTITY_EVENT_MINE</EntityEvent>
    <HotKey>KB_W</HotKey>
    <OrderPriority>96</OrderPriority>
    <IconIndex>21</IconIndex>
    <IconAtlas>UNIT_ACTION_ATLAS</IconAtlas>​
    </Row>​
    </Builds>

    So, I currently have a new Great Person that is consumed by building a farm. Of course, my profound lack of Lua savvy limits me here. (I know next to nothing about Lua.) I tried my best to finish this myself, but I really just need a solution here rather than a comprehensive beginner's guide to Lua.

    I need to know how to set the tile's resource to wheat when the above build is prompted. (The resource should be set to Wheat BEFORE the farm is placed so that the improvement graphic looks like the normal wheat farm.)

    Hopefully, this is a simple thing to figure out. Let me know if anything needs clarifying.

    Thanks!
     
  2. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,538
    Location:
    Near Portsmouth, UK
    You've marked this as solved without giving the solution you used/found - makes it very hard for people who come after you with similar problems to find solutions.

    What you want to do - change a tile mid-game - is one of the most complex pieces of Lua going, due to the number of edge cases it has to consider.

    While pPlot:SetResourceType(iNewResource, iCount) looks like it should work, it is full of pitfalls.

    If the tile is owned by a city, it needs to be unowned first, or any existing resource on that tile will still be used by the city, and the city will not pick up the new resource
    However, before unowning the tile, if a citizen is working it, that citizen needs to be reassigned.
    If there is an improvement on the tile, it needs to be removed.
    However, it that improvement is pillage, it should be repaired first (or effects, like smoke pillars, can continue on the new resource)
    There may be a unit (or units) dependent on that improvement - eg a ship in a coastal fort or planes on an airfield, so they will need relocating
    There may be a unit in the process of building an improvement on the tile, they need to be stopped (don't forget some combat units can build improvements, so don't just look at workers)
    Any existing resource needs to be removed (or the UI Icon Manager can get screwed up)
    Now the new resource can be added and any improvement made
    If the tile was unowned from a city, it needs to be reowned
    The city citizens should all be reassigned depending on the focus of the city

    Phew! (And I've probably forgotten a step or two)

    The best place to find this code is in IGE
     
  3. CMatthewT

    CMatthewT Chieftain

    Joined:
    Jan 16, 2021
    Messages:
    2
    Apologies for not providing the solution. Even knowing very little about Lua, I was able to draw from various sources to come up with at least a partial solution.

    I created a new improvement named IMPROVEMENT_WHEAT_FARM which is just a functionless fort graphic buildable by the Great Person in flat plains, grassland, and desert. When this is built, the below code 1) sets the tile's resource to wheat, 2) sets the improvement to farm, and 3) clears any feature that isn't flood plains:

    function onImprovementCreated(iHexX, iHexY)
    local pPlot = Map.GetPlot(ToGridFromHex(iHexX, iHexY))
    if (pPlot:GetImprovementType() == GameInfo.Improvements.IMPROVEMENT_WHEAT_FARM.ID) then
    pPlot:SetResourceType(6, 1)
    pPlot:SetImprovementType(3)
    if pPlot:GetFeatureType() ~= 4 then pPlot:SetFeatureType(-1) end​
    end​
    end
    Events.SerialEventImprovementCreated.Add(onImprovementCreated)

    I know this is kind of a clunky noob solution, but it's what worked for me. Of course, I hadn't considered the problems you're mentioning. For now, I'll unmark this as solved and update it with a better solution if/when I get all that stuff worked out.

    Thanks!
     
  4. LeeS

    LeeS Imperator Supporter

    Joined:
    Jul 23, 2013
    Messages:
    7,178
    Location:
    Illinois, USA
    Many SerialEvents don't fire unless the human player can see the "action". You need to ensure by testing (since I cannot remember if does or does not) that Events.SerialEventImprovementCreated fires even when the human cannot see the event.
    Code:
    pPlot:SetResourceType(6, 1)
    Using hardcoded integer values rather than pulling the ID # from GameInfoTypes means that any mod which alters the order in which rows are placed in the Resources XML/SQL database table will cause your code to not place Wheat on the tile, but some other resource.
    Code:
    pPlot:SetResourceType(GameInfoTypes.RESOURCE_WHEAT, 1)
    Same issue applies to "SetImprovementType" and "GetFeatureType".
     
  5. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,538
    Location:
    Near Portsmouth, UK

Share This Page