Merging BUG with other Mods

Hi,

I don't know if this has been asked before, but I'm not trawling through 25 pages to see if it has. Sorry. But is it possible to add the 40civs dll file to this mod? I have no other modifications to my BAT install apart from to revert to original flags.

Thanks,
M J
 
BAT includes its own DLL (BULL). For the next release we'll consider making this an option as it's probably desired by many players.
 
Hi

I'm sorry if I'm posting in the wrong place but I did a search for this forum for 'score' and nothing showed up.

I'm trying to merge the mod "Merged Mod" and Asio3x's mod and I'm having a bit of trouble with one of the component which show the score which I believe to be part of BUG (sorry if this is the wrong forum). Specifically the green(+)/(-)red integer representing the variation in score for the current civ compared to the last turn. During the first few turns it only varies if the score goes down. If it goes up or remains the same it is still written "WhatEverNumber +WhatEverNumber".

I have also had problems with the score. For example, when I started a scenario the startup score for all civs was 0 and remained as such for ever and when I highlighted my own score the game crashed like in this thread (http://forums.civfanatics.com/showthread.php?t=363259). I partially fixed things by modifying the function CvGame::initScoreCalculation() so that all divisions by 0 would be treated and they are.

Afterwards I logged the values of the CvGame's m_initPopulation, m_initLand, m_InitTech and m_Init_Wonders. All of them were 0. Then I stumpled on the function CvGame::initScoreCalculation() and after logging the results I realized that it was never called. So in the accessors CvGame::getInitPopulation() (the first one called for the score calculation) I added a line which called the initScoreCalculation() function and now the score are shown in the following manner :

Spoiler :

At turn 0 (stated in ratio of turns in the top right portion of the screen) every civ has a different score and the 'variation indicator' is identical to the preceding score. I noticed that is normal when I begin any scenario/game which contains BUG. So so far so good.

At turn 1 all the scores are modified but only the 'variation indicator' who are in red show the real variation. For the civs who's score has either increased or remained the same the 'variation indicator' shows the current score. This is what I would like to fix but I haven't found out how.

At turn 2 all the scores are updated and the 'variation indicator' for all civs is updated and correct. All further turns are correct on both accounts.


I don't know how to fix the score on turn 1 :(

Any help would be appreciated :D

Thanks for your time
 
I have again a problem, i'm assisting someone to merge one of my modcomponents in a mod with improper used BUG python:


The mod (not published here) uses BUG, but the merged python there is not merged like it should, like you show it in your tutorial, instead it uses it's own CvEventManager.

Now an user wants to merge in this. there's only one big function attached after onGameStart.
We've tried to merge it in in the "BUG way", and into the CvEventManager, both times we get an error (the displayed one is in the "BUG way").
The CvEventManager itself has also modifications in onGameStart. Could it be, that something is conflicting there?
Any ideas, what/where the problem could be (besides the misuse)?
 
Post their CvEventManager and your module that contains onGameStart() here in [code] blocks, and I'll take a look. Also, post the stack trace from PythonErr.log when you tried the BUG-way merge.
 
First: Thanks for the help :).

Do you really mean the whole CvEventManager :crazyeye:?
....oh, crap, i can't, it's to long. The file is attached here, if necessary.

The part after onGameStart from the CvEventManager:
Spoiler :
PHP:
	def onGameStart(self, argsList):
		'Called at the start of the game'
	
		if (gc.getGame().getGameTurnYear() == gc.getDefineINT("START_YEAR") and not gc.getGame().isOption(GameOptionTypes.GAMEOPTION_ADVANCED_START)):
			for iPlayer in range(gc.getMAX_PLAYERS()):
				player = gc.getPlayer(iPlayer)
				if (player.isAlive() and player.isHuman()):
					popupInfo = CyPopupInfo()
					popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON_SCREEN)
					popupInfo.setText(u"showDawnOfMan")
					popupInfo.addPopup(iPlayer)
		else:
			CyInterface().setSoundSelectionReady(true)

		if gc.getGame().isPbem():
			for iPlayer in range(gc.getMAX_PLAYERS()):
				player = gc.getPlayer(iPlayer)
				if (player.isAlive() and player.isHuman()):
					popupInfo = CyPopupInfo()
					popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_DETAILS)
					popupInfo.setOption1(true)
					popupInfo.addPopup(iPlayer)

## Limited Religions Start ##

		if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_PICK_RELIGION):

			CyGame().setOption(gc.getInfoTypeForString("GAMEOPTION_LIMITED_RELIGIONS"), False)

## Limited Religions End ##
## Real Always War Start ##

		if not gc.getGame().isOption(GameOptionTypes.GAMEOPTION_ALWAYS_WAR):

			CyGame().setOption(gc.getInfoTypeForString("GAMEOPTION_REAL_ALWAYS_WAR"), False)

		if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_ALWAYS_WAR):
			if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_REAL_ALWAYS_WAR):
                       		for i in xrange(gc.getMAX_CIV_TEAMS()):
                               		FirstTeam = gc.getTeam(i)
                                	if FirstTeam.isHuman():continue
                                	for j in xrange(gc.getMAX_CIV_TEAMS()):
                                       		SecondTeam = gc.getTeam(j)
                                        	if SecondTeam.isHuman():continue
                                       		if i==j:continue
                                       		FirstTeam.declareWar(j,False,WarPlanTypes.WARPLAN_TOTAL)
                                        	FirstTeam.setPermanentWarPeace(j,True)
                                        	SecondTeam.declareWar(i,False,WarPlanTypes.WARPLAN_TOTAL)
                                        	SecondTeam.setPermanentWarPeace(i,True)

## Real Always War End ##

		for iPlayerLoop in xrange(gc.getMAX_CIV_PLAYERS()):

			pPlayer = gc.getPlayer(iPlayerLoop)
			iPlayer = pPlayer.getID()
			pTeam = gc.getTeam(pPlayer.getTeam())
			iTrait = gc.getInfoTypeForString("TRAIT_SPIRITUAL")
			if pPlayer.isAlive():

## NO STARTING TECHS START ##
				if (gc.getGame().getGameTurnYear() == gc.getDefineINT("START_YEAR") and gc.getGame().isOption(GameOptionTypes.GAMEOPTION_NO_STARTING_TECHS)):

					iTech1 = gc.getInfoTypeForString("TECH_FISHING")
					iTech2 = gc.getInfoTypeForString("TECH_THE_WHEEL")
					iTech3 = gc.getInfoTypeForString("TECH_AGRICULTURE")
					iTech4 = gc.getInfoTypeForString("TECH_HUNTING")
					iTech5 = gc.getInfoTypeForString("TECH_MINING")
					pTeam.setHasTech(iTech1, false, iPlayer, false, false)
					pTeam.setHasTech(iTech2, false, iPlayer, false, false)
					pTeam.setHasTech(iTech3, false, iPlayer, false, false)
					pTeam.setHasTech(iTech4, false, iPlayer, false, false)
					pTeam.setHasTech(iTech5, false, iPlayer, false, false)
## NO STARTING TECHS END ##
## Spiritual Trait Start ##
				if pPlayer.hasTrait(iTrait):
					iTech = gc.getInfoTypeForString("TECH_MYSTICISM")
					pTeam.setHasTech(iTech, true, iPlayer, false, false)
## Spiritual Trait End ##

		CvAdvisorUtils.resetNoLiberateCities()

the module:
Spoiler :
PHP:
# Starting Points

from CvPythonExtensions import *
import BugUtil
###Starting points part 1 start###
import StartingPointsUtil
###Starting points part 1 end###
gc = CyGlobalContext()

def onGameStart(argsList):
    'Called at the start of the game'
    ###Starting points part 2 start###
    MapName = CyMap().getMapScriptName ()
    if ((".civ" in MapName) or(".Civ" in MapName))and (not gc.getGame().isOption(GameOptionTypes.GAMEOPTION_ADVANCED_START)) and (gc.getGame().getGameTurnYear() == gc.getDefineINT("START_YEAR")):
        if "civbeyondswordwbsave" in MapName:
            MapName = MapName[0:-21]
            if "CivBeyondSwordWBSave" in MapName:
                MapName = MapName[0:-21]                                   
            if "CivWarlordsWBSave" in MapName:
                MapName = MapName[0:-18]
            if "Civ4WorldBuilderSave" in MapName:
                MapName = MapName[0:-21]
            if "civ4worldbuildersave" in MapName:
                MapName = MapName[0:-21]                                
                            
            Debuging = False
            AddPositionsToMap = False
            try:
                MyFile=open("Mods/StartingPoints/Assets/XML/CustomXML/"+MapName+"_StartingPoints.xml")
            except:                        
                iNameLength = len(MapName)
                iCutPoint = -1
                for iChar in xrange(iNameLength):
                    if MapName[iChar]=="\\":
                        iCutPoint = iChar                                                                            
                MapName = MapName[iCutPoint:iNameLength]                                            
                MyFile=open("Mods/StartingPoints/Assets/XML/CustomXML/"+MapName+"_StartingPoints.xml")
            StartingPointsUtil.ReadMyFile(MyFile,Debuging,AddPositionsToMap)                        
            MyFile.close()

###Starting points part 2 end###

The XML:
PHP:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--
    Starting Points - real starting poistions for all civs
-->
<mod id="StartingPoints" module="StartingPoints">
    <event type="GameStart" function="onGameStart"/>
</mod>

i've told him to edit the .init.xml, so that the end looks like this:
PHP:
    <load mod="StartingPoints"/>

</bug>


For the stack trace, i have to ask first.

Another thing...er...okay, more or less the same: If i have a CvEventManager, and a module, where the same event is used, do they somehow interact with each other?
 
I'll take a look at the files now. In the meantime . . .

If i have a CvEventManager, and a module, where the same event is used, do they somehow interact with each other?

Each event handler is run in the order they were added. They interact with each other only if you program them to, meaning if one sets a variable that the other has access to they can communicate. BUG doesn't pass information from one to the other.

There are three exceptions, but neither apply here: The OnLoad event returns some magic string, OnSave does the same, and consumable events (keyDown) stop calling handlers as soon as one returns non-zero. Again, GameStart is not affected by these.
 
I don't see anything obvious there. Post the stack trace. Have you tried adding debugging messages using BugUtil.debug() or PyPrint()?
 
Haven't got the stack trace yet, can't also test it myself, and haven't had the time to think over reasonable places where to add the statements...*sigh*.

Each event handler is run in the order they were added. They interact with each other only if you program them to, meaning if one sets a variable that the other has access to they can communicate. BUG doesn't pass information from one to the other.

Short version: No, right :D?

I asked, because i have somewhere else the problem, that an event seems to be triggered twice, and i don't know atm, what could be the cause.



Another thing, which has been strange:
Adding the first mentioned mod component in the normal CvEventManager caused an exception in onBeginActivePlayerTurn, in Civ4lerts.WorstEnemyInstance and in Civ4lerts.RefuseToTalkInstance, which really confuses me, because the code, which seemed to trigger this (small optional part), was still placed in onGameStart, and was so 100% not related to that.
 
...double post...

The debuging resulted in the knowledge, that the erros where fallout of a failed file loading. My code tried to access a file, but i didn't check before if it exists, and the user added the wrong folder name of the mod and the exception handling was obviously not able to handle it.
I guess this might maybe be helpful, because i know that some RevDCM based mods need to access different files and sometimes get problems like this.
-> no BUG problem.
And thanks for the help :D.


Another question: I guess BUG doesn't change anything of the default API calls (as Python only it can't, right?)?
Because there's still a strange problem, where getMapScriptName seems to return a wrong value :dunno:.
 
BUG doesn't change any core API calls, but anyone can. Each of the exposed classes such as CyCity can be mucked with just like any normal Python class.

Type all this in the Python console:

Code:
function ignoreNewCityName(self, szName):
    CyInterface.addImmediateMessage("No changing city names!", "")

CyCity.setName = ignoreNewCityName

Now try to change the name of your capital. You should see the above message and the city won't change its name. If not, go through the console again:

Code:
pPlayer = gc.getPlayer(0)
pCity = p.getCity(0)
pCity.setName("New Capital City")
 
I don't think, that anyone would change the mapscript name function, so that it returns an invalid value.
I guess i have to debug a bit more, probably my string cutting code is wrong.

But agains thanks, and sorry for bothering you.
 
Are any of you guys still having outstanding problems with BUG? I've got a lot of open threads, and I can't tell exactly what the current state of these issues is. I'm working on a new release today, so if anyone's around a quick reply with status would be great.
 
I've been running BUG 3.6 with Better AI v1.00e and my own mod. for over a year but now I want to upgrade to BUG 4.4. I have BUG in CustomAssets. My mod just mainly adds new units, tech tree changes, etc. I can get the game to come up fine without my mod but with the mod the first thing that I see when I create a new game is the Tech Advisor and there's an error message: "Buginit cannot find XML file for mod init". Can someone assist please?
 
This is due to a rushed fix I created to allow people to have BUG and BAT/BUFFY installed together. :( In the CustomAssets folder, go to Python / BUG and open BugPath.py in Notepad or some other text editor. Search for this using Find:

Code:
if not isNoCustomAssets() and not isMod():

and change it to this:

Code:
if not isNoCustomAssets():

Here you're telling BUG that it's okay to look for init.xml in the CustomAssets folder even when you're running as a mod.
 
Thanks! Got much farther now - everything seems to work fine but I get the message:

Buginit: init UnitUtil failed

the first time I start a game.
 
Please follow the instructions on the Troubleshooting thread (see my sig) for how to enable logging. Then post the PythonErr.log file from you My Games / BTS / Logs folder. In there and/or PythonDbg.log you should see the reason for the error.

UnitUtil.py processes the units in the XML to build an in-memory representation used by BUG's Military Advisor screen, specifically for the Strategic Advantages tab. Most likely you have a unit class with an incorrectly specified default unit type, but I cannot be sure without the error log.
 
I've just added a new specialist type to my mod and I noticed that the topmost specialist on the cityscreen doesn't function. No tooltip appears on mouseover and the add specialist button does nothing despite having the appropriate building available.

Is there some setting or change I need to make to CvMainInterface.py or elsewhere? I found this group of variables:

Code:
# BUG - city specialist - start
g_iSuperSpecialistCount = 0
g_iCitySpecialistCount = 0
g_iAngryCitizensCount = 0
SUPER_SPECIALIST_STACK_WIDTH = 15
SPECIALIST_ROW_HEIGHT = 34
SPECIALIST_ROWS = 3
MAX_SPECIALIST_BUTTON_SPACING = 30
SPECIALIST_AREA_MARGIN = 45
# BUG - city specialist - end

MAX_CITIZEN_BUTTONS = 8

Are they any use?
 
What does dll="5" signify in the config xml files? Does changing the number there do anything important? Also what does dirtybit signify? It seems if I want the dll to read a value from bug I need to use that dll= thing, but I'm not sure if I should just keep copying 5, or if I should be using some other number, as I have no idea what it does. The dirtybit is less important to me, though I am curious. Also if I define something in the config xml that uses that dll= thing, am I allowed to write a get and set function for it, or not?

As an example, say I have something like this:

Code:
			<option id="RevDCMHiddenAttitude" key="RevDCMHiddenAttitude" 
					type="boolean" default="True" dll="5" 
					get="isRevDCMHiddenAttitude" set="setRevDCMHiddenAttitude"/>

Is this legal? What is the dll="5" doing, and can I or should I change it? Can I reference the isRevDCMHiddenAttitude function in the python files, and would the above be successfully exposed to the dll so that some function could read it using the this code: getBugOptionBOOL("RevDCM__RevDCMHiddenAttitude", true, "REVDCM_HIDDEN_ATTITUDE") ?
 
dll=some number tells BUG that this feature needs BULL with api version 5 or higher. There should be no need to change that, unless you port a feature from the SDK to python, in that case you could remove that whole dll= thing. If you create a whole new feature for BUG that requires new functionality in the dll then you could bump the api version by one.
Basically dll="5" causes the option to be grayed out if the dll had BUG_DLL_API_VERSION (see BugMod.h) set to a number smaller than 5. It is only needed for BUg because the dll comes in a different package and you could mix a brand new BUG with an old BULL - in that case BUG knows which features are actually available and which aren't. For RevDCM-only features it's probably not so dramatic if you don't add any dll= parts but when in doubt, just put dll="6" (which is the latest api version afaik) for new features.
Dirtybits signify something has changed that affects a few bigger things which will need to be recalculated/redrawn at a later time. I think..
 
Top Bottom