Announcement

Collapse
No announcement yet.

simple mod blog : adding a harvester unit (aka crawler in smac)

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • simple mod blog : adding a harvester unit (aka crawler in smac)

    Hi,

    I'm trying to start to understand civ4 modding. The first thing I'd like to do, is to add a technology ("harvesting") with the pre-requisites "agriculture" and "mining", which gives a new unit, a "harvester" that can be used to harvest resources, just like crawlers in smac work.

    This is a small mod, but I think I'll need a little bit of everything to make it work, and thus serves as a good learning experience. I'll need graphics, xml editing and python scripting.

    So far, graphics seem the most difficult part, so I have started with re-using existing graphics (the indian worker seems a nice candidate).

    OK, so, what follows is a basic description of what I've done and associated problems/questions/remarks. I hope others who want to start modding can get usefull info from this.

    [edit]I had to change all xml tags to use {} instead of < and >, because this forum tried to interpret them as html, and I didn't find the option to turn that off.[/edit]

    => First, I created a directory in the "mods" directory: "Harvester"

    => I noticed all current mods have a .ini file. I have searched for, but nowhere found, a list of options to set here. So, for now, I've just copied the .ini from the Dessert War mod. The 5 options here are pretty self-explanatory.

    => Next, let's add the technology. I'll use the indian fast worker button graphics as the tech icon.
    --> Created a folder "Harvester\Assets\XML\Technologies\"
    --> Copied the file "CIV4TechInfos.xml" (from the default assets folder)
    --> Look in the file "CIV4TechInfos_schema.xml", to know the structure of a {TechInfo} element. (Not really necessary, as you can guess the same info very reasonable from the other techs in the xml file).
    --> Most elements are again self-explained, but some of them aren't. Here a short list I'd like more info about:
    Code:
    iAIWeight		(0-?)
    iAITradeModifier	(0 or 10)
    iPower		(0-10)
    iAsset		(1-6)*8
    CommerceFlexible	sub-elements
    Most of these I've guessed, and so came up with this {TechInfo} element for the new tech:
    PHP Code:
            <TechInfo>
                <
    Type>TECH_HARVESTING</Type>
                <
    Description>Harvesting</Description>
                <
    Civilopedia>Enables you to produce harvester units</Civilopedia>
                <
    Help />
                <
    Strategy>This is an important techIt makes small cities powerfull</Strategy>
                <
    Advisor>ADVISOR_GROWTH</Advisor>
                <
    iAIWeight>0</iAIWeight>
                <
    iAITradeModifier>10</iAITradeModifier>
                <
    iCost>180</iCost>
                <
    Era>ERA_ANCIENT</Era>
                <
    FirstFreeUnitClass>NONE</FirstFreeUnitClass>
                <
    iWorkerSpeedModifier>0</iWorkerSpeedModifier>
                <
    iTradeRoutes>0</iTradeRoutes>
                <
    iHealth>0</iHealth>
                <
    iHappiness>0</iHappiness>
                <
    iFirstFreeTechs>0</iFirstFreeTechs>
                <
    iAsset>24</iAsset>
                <
    iPower>3</iPower>
                <
    bRepeat>0</bRepeat>
                <
    bTrade>1</bTrade>
                <
    bDisable>0</bDisable>
                <
    bGoodyTech>1</bGoodyTech>
                <
    bExtraWaterSeeFrom>0</bExtraWaterSeeFrom>
                <
    bMapCentering>0</bMapCentering>
                <
    bMapVisible>0</bMapVisible>
                <
    bMapTrading>0</bMapTrading>
                <
    bTechTrading>0</bTechTrading>
                <
    bGoldTrading>0</bGoldTrading>
                <
    bOpenBordersTrading>0</bOpenBordersTrading>
                <
    bDefensivePactTrading>0</bDefensivePactTrading>
                <
    bPermanentAllianceTrading>0</bPermanentAllianceTrading>
                <
    bBridgeBuilding>0</bBridgeBuilding>
                <
    bIrrigation>0</bIrrigation>
                <
    bIgnoreIrrigation>0</bIgnoreIrrigation>
                <
    bWaterWork>0</bWaterWork>
                <
    iGridX>2</iGridX>
                <
    iGridY>15</iGridY>
                <
    DomainExtraMoves/>
                <
    CommerceFlexible/>
                <
    TerrainTrades/>
                <
    Flavors>
                    <
    Flavor>
                        <
    FlavorType>FLAVOR_PRODUCTION</FlavorType>
                        <
    iFlavor>5</iFlavor>
                    </
    Flavor>
                    <
    Flavor>
                        <
    FlavorType>FLAVOR_GROWTH</FlavorType>
                        <
    iFlavor>3</iFlavor>
                    </
    Flavor>
                    <
    Flavor>
                        <
    FlavorType>FLAVOR_GOLD</FlavorType>
                        <
    iFlavor>2</iFlavor>
                    </
    Flavor>
                    <
    Flavor>
                        <
    FlavorType>FLAVOR_SCIENCE</FlavorType>
                        <
    iFlavor>2</iFlavor>
                    </
    Flavor>
                </
    Flavors>
                <
    OrPreReqs/>
                <
    AndPreReqs>
                    <
    PrereqTech>TECH_MINING</PrereqTech>
                    <
    PrereqTech>TECH_AGRICULTURE</PrereqTech>
                </
    AndPreReqs>
                <
    Quote>some random text about crawlers in SMAC</Quote>
                <
    Sound />
                <
    SoundMP />
                <
    Button>Art/Interface/Buttons/Units/Fastworker.dds</Button>
            </
    TechInfo
    --> While the schema tells me I can add a new {TechInfos} section, with my own {TechInfo} elements, this turned out not to work. When I added my {TechInfo} to the existing {TechInfos} list of {TechInfo} elements, the tech showed up in the civilopedia, the tech tree and so forth...

    => But, something is still wrong here. The tech doesn't have any pre-requisites. I can research it immediately, the prerequisites are not listed in the civilopedia, this tech is not listed as a "leads to" tech for agriculture and mining, it doesn't have any obligatory icons in the tech tree (nor any connectin lines) ... I have not yet solved this problem, but hopefully I will soon.


    next up:
    => make the prerequisites for this tech work
    => copy all indian fast worker graphics and xml and rename to "harvester"
    => make the harvester available with this tech
    => modify the xml so it isn't a worker anymore
    => write python code that runs each turn and adds food/production/gold to the home city of each harvester.
    Last edited by PJayTycy; November 6, 2005, 19:58.
    no sig

  • #2
    Will the AI be able to undersstand this?
    "Build Ports when possible. A port gives you extra resources, as well as an extra tile for a unit to stand on." - Infogrames

    Comment


    • #3
      Originally posted by Akaoz
      Will the AI be able to undersstand this?
      Probably not, but it's not really my intention to build a real mod to be used by a lot of players (as I get the impression most civ-players hated the crawlers in smac). It just seemed an interesting small mod to learn a little bit of everything related to modding civ4.
      no sig

      Comment


      • #4
        While debugging this, I did something wrong and got a few XML errors. Well, after hitting OK on about 150 xml-error popups, I'm wondering if I can't set some option to not popup xml errors, but put them only in a log file or something...

        these weren't XML errors at all though, I just had to clear my cache.


        so, what did I change?
        I copied an existing tech with 2 prerequiste techs exactly and put it below my tech (I used the flight tech). I just changed the tech_tag. Trying to see if this worked.

        Now, what happens : the flight2 tech gets the pre-requisites for my harvesting tech....

        Did any mod succesfully add a tech to the tech tree ??


        I'll probably have to add a "dummy" tech above my harvesting tech with the right prerequisites. This is kind of stupid. I could also try what happens if I put my tech on the top of the list, but I fear some game code might rely on the exact tech order or the prerequisites for all other techs might get messed up...
        Last edited by PJayTycy; November 8, 2005, 11:43.
        no sig

        Comment


        • #5
          Ok, tried with putting my tech in the front... what a mess this got me:




          You can see all prerequisites are wrong (like I kind of expected).

          Also, it's stupid to have the "give this screenshot a name" dialog on-screen in a screenshot.



          Now, I can add a dummy tech, and try to remember to put the pre-requisites in the tech above the one I need, but if a patch solves this problem, I'll have to re-change it again.


          BTW: is this officially a bug to be patched now ?
          no sig

          Comment


          • #6
            So, I seem to have solved the problem anyway:


            I removed all comments and changed all empty tags from

            {blah /} to {blah/} (ie: removed the space before /)

            I'll now try with adding comments again... It's probably all due to the extra space I'm used to type before the />

            [edit]Nope, I was wrong, the comments are the problem, not the space before /> . So, general rule for xml-editing : don't add comments...[/edit]


            I'm glad I finally got this to work, so I can now move on to the harvesting unit, and hopefully some python code soon.
            Last edited by PJayTycy; November 8, 2005, 12:19.
            no sig

            Comment


            • #7
              Re: simple mod blog : adding a harvester unit (aka crawler in smac)

              --> Most elements are again self-explained, but some of them aren't. Here a short list I'd like more info about:
              Code:
              iAIWeight		(0-?)
              iAITradeModifier	(0 or 10)
              iPower		(0-10)
              iAsset		(1-6)*8
              CommerceFlexible	sub-elements
              CommerceFlexible:
              This is the only one of these I'm confident about. Drama is the only tech with this setting changed... This setting is the one that controls whether you can spend income on culture.

              Going by what I know about previous Civs, the two AI ones probably control how the AI deals with researching or trading the techs...

              iAITradeModifier - I'd guess that this tech controls how aggressively AI civs will trade for these techs.

              iAIWeight - I'd guess that this controls how likely the AI's are to research a specific tech, prior to any flavor estimates.

              iPower & iAsset:
              The actual technical purpose of these I can't guess. I did notice, however, that iAsset coincides directly with the tech era and iPower is higher for techs that grant larger offensive weapons (Fission & Artillery, for example). Probably more AI decisions, but I don't know.
              Last edited by Gelondil; November 10, 2005, 03:53.

              Comment


              • #8
                I've got all the xml working now (tech + unit), except for the few xml-tags above that I'm still unsure of. I noticed the ai didn't really want to research my new tech, but once I got it, they all came asking for it and offered a tech of theirs + gold. So I should probably tune down the iAITradeModifier a bit :-)

                Anyway, I'm now moving on to the python side of things. At the end of each player's turn, I have to search for all harvester units "supported" by each base and then add a certain amount of hammers / gold / food to that city.

                In Locutus' "initial Python reference" here, I see a lot of possibile events that could trigger my code. I don't really know which one to use:

                onBeginGameTurn
                'Called at the beginning of the end of each turn'
                arguments: iGameTurn

                onEndGameTurn
                'Called at the end of the end of each turn'
                arguments: iGameTurn

                onBeginPlayerTurn
                'Called at the beginning of a players turn'
                arguments: iGameTurn, iPlayer

                onEndPlayerTurn
                'Called at the end of a players turn'
                arguments: iGameTurn, iPlayer

                onEndTurnReady
                -
                arguments: iGameTurn

                onCityDoTurn
                'City Production'
                arguments: pCity, iPlayer


                I tried to add this code to each of these events:
                Code:
                		iGameTurn = argsList
                		popup = Popup.PyPopup()
                		popup.setHeaderString( "onBeginGameTurn" )
                		popup.setBodyString( 'iGameTurn = %d' , iGameTurn )
                		popup.launch()
                to see when each event was triggered, but I don't see any popup at all.
                no sig

                Comment


                • #9
                  Well, some code was wrong in my eventManager...

                  => By enabling the logging in the .ini file, I was able to find the causes fast (wrong number of arguments + typo).

                  Now the popups showed, but the game was kind of "locked" after I closed them (interface works, direct map and unit interaction doesn't work)

                  The game doesn't "halt" when a popup is shown. It just continues. Because I had a popup in each of these events, I spawned a lot of popups, apparently too much for the game to handle.

                  => Don't spawn more than 10 (or 11) popups or the game will go in this "halted" state.


                  Ofcourse I have now also deducted the order in which the events fire (starting when the player hits "end turn") :

                  onBeginPlayerTurn (player = 0)
                  onCityDoTurn(player = 0, city = ...)
                  onCityDoTurn(player = 0, city = ...)
                  onCityDoTurn(player = 0, city = ...)
                  onEndPlayerTurn (player = 0)

                  onBeginPlayerTurn (player = 1)
                  onCityDoTurn(player = 1, city = ...)
                  onCityDoTurn(player = 1, city = ...)
                  onCityDoTurn(player = 1, city = ...)
                  onEndPlayerTurn (player = 1)

                  onBeginPlayerTurn (player = 2)
                  onCityDoTurn(player = 2, city = ...)
                  onCityDoTurn(player = 2, city = ...)
                  onCityDoTurn(player = 2, city = ...)
                  onEndPlayerTurn (player = 2)

                  ...

                  onBeginPlayerTurn(player = 18)
                  onEndPlayerTurn(player = 18)

                  onBeginGameTurn()
                  onEndGameTurn()



                  So, I think I'll use the onCityDoTurn() events to modify the hammers / food / gold. I didn't see any onEndTurnReady() events, and as there is no description about it in Locutus' reference, I'll assume this event never fires.

                  An other problem here I realised after playing a few civ4 games : units don't have the notion of a "home city" anymore. I'll have to check into this to see how I can link each crawler/harvester to 1 city.
                  no sig

                  Comment


                  • #10
                    Originally posted by PJayTycy
                    So, I seem to have solved the problem anyway:


                    I removed all comments and changed all empty tags from

                    {blah /} to {blah/} (ie: removed the space before /)

                    I'll now try with adding comments again... It's probably all due to the extra space I'm used to type before the />

                    [edit]Nope, I was wrong, the comments are the problem, not the space before /> . So, general rule for xml-editing : don't add comments...[/edit]


                    I'm glad I finally got this to work, so I can now move on to the harvesting unit, and hopefully some python code soon.
                    I was wondering if removing the comments would help get rid of a little bug in my mod...

                    I'll try that, thanks! Also, never played SMAC but I'll have to check out this unit when you're done

                    Comment


                    • #11
                      Originally posted by PJayTycy
                      So, I seem to have solved the problem anyway:


                      I removed all comments and changed all empty tags from

                      {blah /} to {blah/} (ie: removed the space before /)

                      I'll now try with adding comments again... It's probably all due to the extra space I'm used to type before the />

                      [edit]Nope, I was wrong, the comments are the problem, not the space before /> . So, general rule for xml-editing : don't add comments...[/edit]


                      I'm glad I finally got this to work, so I can now move on to the harvesting unit, and hopefully some python code soon.
                      I was wondering if removing the comments would help get rid of a little bug in my mod...

                      I'll try that, thanks! Also, never played SMAC but I'll have to check out this unit when you're done

                      P.S. It worked! Thanks!

                      Comment


                      • #12
                        Originally posted by kallussed
                        I was wondering if removing the comments would help get rid of a little bug in my mod...

                        P.S. It worked! Thanks!

                        You're welcome !

                        It's good to see I'm not the only one to stumble upon this and ofcourse it's also good to see somebody had some use of this monologue-like thread.
                        no sig

                        Comment


                        • #13
                          I'm still thinking about how to do this in python (didn't write code yet). My current idea is to create a new class to store all necessary info about the harvesters in a vector :
                          => a reference to the unit
                          => home city
                          => state (ie: not harvesting / food / production / gold)

                          I started to think about what I should do when a harvester is "detached" from its home city. This happens when a city flips, is conquered, is razed, ... It also happens when the unit is captured / gifted / ... to an other player. I've decided for now to automaticly assign it to the nearest city of this player.

                          So, with all this in mind, I looked through the python API to find the functions I'll probably need. This is what I've found:

                          CyCity.changeFood ( +x )
                          CyCity.changeProduction ( +x )
                          CyPlayer.changeGold ( +x )

                          Notice here that gold is a global resource, while food and production are city-specific.

                          CyUnit.getX()
                          CyUnit.getY()
                          CyMap.findCity(x, y, owner, ...)

                          I'll have to test this last one, but I think this finds the city closest to the given x, y co-ordinates, owned by a certain player. If so, this is exactly what I'll need

                          Next, I check which events I'll need to use and what I'll need to do:

                          onGameStart() initialize all my data structures
                          onSaveGame() write important data to the save file (?)
                          onLoadGame() load saved data from the save file (?)
                          onBeginPlayerTurn(iPlayer) add food/production/gold to cities / global treasure.
                          onUnitBuilt(city, unit) if harvester type : add city, unit pair to my vector
                          onUnitLost(unit) ?


                          I'm not really sure when the onUnitLost will trigger. Will this trigger when a unit is captured by or given to another player ? Because I couldn't find any specific events for those. Will it trigger when a unit is killed ? Because there IS a specific event for killing a unit.


                          An other thing I'm unsure of, is the onSaveGame and onLoadGame events. I should be able to somehow store and retrieve my data without corrupting the save file.


                          Well, apart from these 2 issues (capturing / donating units and saving / loading games), I think I can have this working this evening. I think however, there will be a small difference in respect to crawlers in smac : if I use the changeProduction() function to add 5 hammers, these 5 hammers won't be affected by production bonusses in the city.


                          When I have a first version working, I'll upload it here. There's also a graphics artist from the C4:AC mod who created a 3D model of the smac crawler, we still need to transform it into a civ model though. Once all this is finished, this will be a small, but very varied mod (xml, python, graphics).
                          no sig

                          Comment


                          • #14
                            Ok, a small follow up:


                            I've got almost everything working now, except for the "hard" parts:


                            DONE AND WORKING:
                            xml : adding technology
                            xml : adding unit "crawler"
                            python : dynamicly finding crawler class ID on game init (ie: no fixed "crawler = unit 78" stuff)
                            python : storing home city for each crawler
                            python : adding food/hammers/gold to the city each turn when unit is crawling

                            CURRENT PROBLEMS (done and not working):

                            => Giving the command to start crawling.
                            I added a new BuildInfo object and added it as (the only) item to the {builds} list for my crawler. However, it doesn't show up where the worker buttons normally show up. Just for testing, I tried adding the build order to the normal worker too, but it doesn't show up either. In python I can get to the BuildInfo object without problems, but the button is not painted on the screen.
                            I looked in the CvMainScreen.py file, to find where these buttons are painted. I didn't find it. They use "getActionInfo", which is listed in the Python API to use the "XML\Units\Civ4ActionInfos.xml" file, but that file doesn't exist. There are other files I could try however. Besides the BuildInfo, also the MissionInfo.xml file looks promissing, but the comment at the top : "{!--Changes must be reflected in CvEnums.h--}" doensn't look very promissing untill the SDK comes out.
                            Ofcourse, I could just copy the CvMainInterface.py file, and add in the buttons myself, but I don't think I want to do that yet (it's 2800+ lines). So, has anybody had any succes in getting an extra button to show on the main interface?
                            I have tried keyboad commands, but didn't have much luck with those either (there just aren't that many combinations free anymore).
                            Next thing I'll try is to just allow the "build farm", "build mine", "build cottage" commands for the crawler, and then try to catch them in python so no farm/mine/cottage/... is actually built.

                            => Getting a button to show on the interface is one thing. Capturing when it's clicked is another...



                            NOT INVESTIGATED YET
                            => How to store / load extra info in the save game file? Is there any mod doing this already? Anybody who can give me a clue?
                            => Trying to catch all cases where a city-worker pair might be destroyed : units gifted away, killed, self-destructed, captured, ... and cities gifted, taken, razed, ...
                            => Instead of changing the actual food/hammer/gold reserve, making the extra input visible on the production/food bars and the commerce counter.


                            Basicly, I get the feeling of wanting to push too much in python, while I should be better of waiting for the SDK. However, I will continue to try to get this to work (at least basicly) in Python and Xml alone.
                            no sig

                            Comment


                            • #15
                              wow, great work!
                              i wanted to do a similar thing and was looking for some good code in a mod and luckily i found this thread
                              the only thing i want to say is that you have at least one big fan

                              Comment

                              Working...
                              X