Naval Mines

No, they are ANDs. Thus the name getPrereqAndTechs(), but GE is right about the single value controlling which tech panel it gets put on. I forgot about that part.

It's scary how much Civ4 API stuff I have learned but forgotten over the past 3 years. Guess my stack is overflowing. :lol:
 
Yes, the array makes perfect sense, but the extra single-value accessor is odd. I suppose they had the single value first and then needed multiple values and added the array instead of replacing the single value. C'est la vie.

In that code, self.iUnit accesses a value from the screen. You won't have that. Instead you have the pUnit2.getUnitType().

Code:
pUnit2 = pPlot.getUnit(iUnitLoop)
info = gc.getUnitInfo(pUnit2.getUnitType())
iMaxEra = -1
[COLOR="Red"][B]iTech = info.getPrereqAndTech()[/B][/COLOR]
if iTech != -1:
    iEra = gc.getTechInfo(iTech).getEra()
    if iEra > iMaxEra:
        iMaxEra = iEra
for i in range(gc.getNUM_AND_TECH_PREREQS()):
    iTech = info.getPrereqAndTechs(i)
    if iTech != -1:
        iEra = gc.getTechInfo(iTech).getEra()
        if iEra > iMaxEra:
            iMaxEra = iEra

iMaxEra is now the latest era of all required techs or -1 if there were no required techs. This assumes that eras are in natural order (they normally are).

I get the following error on the red line:

Attribute Error: "NoneType" object has no attribute getPrereqAndTech.
 
Do you have the code above exactly as I have it?

Code:
info = gc.getUnitInfo(pUnit2.getUnitType())

Unless pUnit2.getUnitType() is returning NO_UNIT, info should be a valid CvUnitInfo. :confused:
 
Do you have the code above exactly as I have it?

Code:
info = gc.getUnitInfo(pUnit2.getUnitType())

Unless pUnit2.getUnitType() is returning NO_UNIT, info should be a valid CvUnitInfo. :confused:

It is as you have it displayed. I'm confused too, as the error comes up on every other ship I move into the plot. Strange!

Orion Veteran :cool:
 
Until we figure out this error, I have come up with a work around function that produces the correct Era for the specified unit.

Spoiler :

Code:
def getUnitEra(MyUnit):
	# Returns the Era for the specified Naval Unit
	
	rEra = -1
		
	NavalUnitData = {
		"UNIT_TRANSPORT": "ERA_INDUSTRIAL",
		"UNIT_GALLEON": "ERA_RENAISSANCE",
		"UNIT_NETHERLANDS_OOSTINDIEVAARDER": "ERA_RENAISSANCE",
		"UNIT_GALLEY": "ERA_ANCIENT",
		"UNIT_WORKBOAT": "ERA_ANCIENT",
		"UNIT_BATTLESHIP": "ERA_INDUSTRIAL",
		"UNIT_CARRIER": "ERA_MODERN",
		"UNIT_MISSILE_CRUISER": "ERA_MODERN",
		"UNIT_STEALTH_DESTROYER": "ERA_MODERN",
		"UNIT_ATTACK_SUBMARINE": "ERA_MODERN",
		"UNIT_DESTROYER": "ERA_INDUSTRIAL",
		"UNIT_NAVAL_MINE_LAYER": "ERA_RENAISSANCE",
		"UNIT_NAVAL_MINE_SWEEPER": "ERA_RENAISSANCE",
		"UNIT_SUBMARINE": "ERA_MODERN",
		"UNIT_IRONCLAD": "ERA_INDUSTRIAL",
		"UNIT_SHIP_OF_THE_LINE": "ERA_RENAISSANCE",	
		"UNIT_FRIGATE": "ERA_RENAISSANCE",
		"UNIT_PRIVATEER": "ERA_RENAISSANCE",
		"UNIT_PORTUGAL_CARRACK": "ERA_MEDIEVAL",
		"UNIT_CARAVEL": "ERA_MEDIEVAL",
		"UNIT_TRIREME": "ERA_ANCIENT"
	}
	
	for szUnit, iEra in NavalUnitData.iteritems():
		iUnit = gc.getInfoTypeForString(szUnit)
		if iUnit == MyUnit:
			rEra = str(iEra)			
			break
		
	return str(iEra)


This function is called by the following:

Code:
pUnitUnitEra = getUnitEra(pUnitType)
Age = gc.getInfoTypeForString(pUnitUnitEra)

It is a good temporary solution to the problem. I stress temporary, because I would rather not require users of the mod to change this function everytime a new Naval unit is added to the game. So, if someone does finally figure out why we are getting the Attribute Error: "NoneType" object has no attribute getPrereqAndTech; I will use that code instead.


Orion Veteran :cool:
 
Did you try the following?

Code:
[COLOR="DarkRed"]if info != None:[/COLOR]
	iTech = info.getPrereqAndTech()
	if iTech != -1:
		iEra = gc.getTechInfo(iTech).getEra()
		if iEra > iMaxEra:
			iMaxEra = iEra
	for i in range(gc.getNUM_AND_TECH_PREREQS()):
		iTech = info.getPrereqAndTechs(i)
		if iTech != -1:
			iEra = gc.getTechInfo(iTech).getEra()
			if iEra > iMaxEra:
				iMaxEra = iEra

I'm not totaly certain of this but from my experience it appears that there are pointers to non valid units on a plot when combat and/or movement occur. It appears that when Civ creates a new CvUnit object for a given unit or if a unit is killed, the old CvUnit object is kept until the end of the turn. When I ran accross this in the past I just altered the code to ignore them and everything worked OK. As I said above I'm not totally certain this is happening, but that's what it looks like to me. Has anybody else ever noticed this behavior?

Edit: "if not pUnit2.isNone():" Would be slightly more efficient, but I'm not sure if that works all of the time (i.e. when the unit is killed).
 
How are you getting pUnitType?

In any case, you can check the unit type I'm getting against -1 before trying to look up the CvUnitInfo:

Code:
pUnit2 = pPlot.getUnit(iUnitLoop)
[B][COLOR="Red"]iUnitType = pUnit2.getUnitType()
if iUnitType != -1:[/COLOR][/B]
    info = gc.getUnitInfo([B][COLOR="Red"]iUnitType[/COLOR][/B])
    # rest of my code indented
    ...
[B][COLOR="Red"]else:
    iMaxEra = -1[/COLOR][/B]
 
How are you getting pUnitType?

In any case, you can check the unit type I'm getting against -1 before trying to look up the CvUnitInfo:

Code:
pUnit2 = pPlot.getUnit(iUnitLoop)
[B][COLOR="Red"]iUnitType = pUnit2.getUnitType()
if iUnitType != -1:[/COLOR][/B]
    info = gc.getUnitInfo([B][COLOR="Red"]iUnitType[/COLOR][/B])
    # rest of my code indented
    ...
[B][COLOR="Red"]else:
    iMaxEra = -1[/COLOR][/B]

It Worked! :beer:

Note: For my purposes, I didn't need the iMaxEra.
 
hey OrionVeteran, if you need any sounds here ya go. Theres two different ones, I ripped em from AGEod's American Civil War game, but they were created from gamenoise.com so I'm assuming nobody will care if we use them.
 
hey OrionVeteran, if you need any sounds here ya go. Theres two different ones, I ripped em from AGEod's American Civil War game, but they were created from gamenoise.com so I'm assuming nobody will care if we use them.

Thanks for the sounds, but I had already pilfered a good explosion sound from YouTube. I created a link for the soon to be released Mine Warfare Mod:

http://forums.civfanatics.com/showthread.php?t=355343

I have put in many hours on this mod and it should be a big hit with the community.


Orion Veteran :cool:
 
Scenario: Say I have a unit that can move 3 squares per turn. I code python to give the unit a mission go to a specified plot. Is there a way to prevent the unit from making any further movements? In other words, I press the action button and now the unit is locked into place and has 0 movement capability. Any idea how this could be done?
 
Are you saying it shouldn't move at all that turn? It should just queue up the order and drop its MPs to zero? I think there's a callback for groupPushMission() or something. Or you could create a new action.
 
Are you saying it shouldn't move at all that turn? It should just queue up the order and drop its MPs to zero? I think there's a callback for groupPushMission() or something. Or you could create a new action.

I'm saying, once the unit is deployed to a specified plot, I don't want to be able to move it anymore. Kind of like a sentry command, only permanent.
 
One way would be to make a second unit with the DOMAIN_IMMOBILE type and swap it out when the unit reaches its destination.
 
One way would be to make a second unit with the DOMAIN_IMMOBILE type and swap it out when the unit reaches its destination.
I was thinking the same idea. Say I go for this concept. I already know how to terminate a unit with the kill command. How would I bring in a completely new unit to the plot?
 
Instead of using kill() you create a new unit using initUnit() and then you convert the old unit to it (or vice versa, I forget). This makes sure to transfer over the XP, HP, etc. This is how upgrading works, so you can check CvUnit::upgrade() to see how it works.
 
Instead of using kill() you create a new unit using initUnit() and then you convert the old unit to it (or vice versa, I forget). This makes sure to transfer over the XP, HP, etc. This is how upgrading works, so you can check CvUnit::upgrade() to see how it works.

Do you think this might work?

Spoiler :

Code:
Def ActivateMine(pUnit):
	iPlayer = pUnit.getOwner()
	pPlayer = gc.getPlayer(iPlayer)
	iUnitUnArmedNavalMine = gc.getInfoTypeForString("UNIT_UNARMED_NAVAL_MINE")
	iUnitUnArmedNavalMineField = gc.getInfoTypeForString("UNIT_UNARMED_NAVAL_MINE_FIELD")
	iUnitUnArmedNuclearNavalMine = gc.getInfoTypeForString("UNIT_UNARMED_NUCLEAR_NAVAL_MINE")
	iUnitArmedNavalMine = gc.getInfoTypeForString("UNIT_ARMED_NAVAL_MINE")
	iUnitArmedNavalMineField = gc.getInfoTypeForString("UNIT_ARMED_NAVAL_MINE_FIELD")
	iUnitArmedNuclearNavalMine = gc.getInfoTypeForString("UNIT_ARMED_NUCLEAR_NAVAL_MINE")
	iPlotX = pUnit.getX()
	iPlotY = pUnit.getY()
	pPlot = CyMap( ).plot( pUnit.getX( ), pUnit.getY( ) )
	DefaultUnitAI = "UNIT_AI_ATTACK"
	
	if pUnit.getUnitType() == iUnitUnArmedNavalMine:
		pPlayer.initUnit(iUnitArmedNavalMine, iPlotX, iPlotY, DefaultUnitAI, DirectionTypes.NO_DIRECTION )

	elif pUnit.getUnitType() == iUnitUnArmedNavalMineField:
		pPlayer.initUnit(iUnitArmedNavalMineField, iPlotX, iPlotY, DefaultUnitAI, DirectionTypes.NO_DIRECTION )

	elif pUnit.getUnitType() == iUnitUnArmedNuclearNavalMine:
		pPlayer.initUnit(iUnitArmedNuclearNavalMine, iPlotX, iPlotY, DefaultUnitAI, DirectionTypes.NO_DIRECTION )

	pUnit.kill	
	return
 
Back
Top Bottom