MarnokMod - (Explorable lairs)

Careful Jhoniten... it won't be long till you start slipping in a few lines of your own tweaks here and there, and then over here, and then some more here.....You'll become a modder yourself if you merge too much ;) :D

I'm already hooked. I have about 10 little changes I like to make, and now I find myself hesitating to apply new patches because I don't want to have to redo them. I was going to put them in a module, but now I'm trapped on Vista with only Winmerge to help.
 
I feel your pain charleswatkins. Maybe Xienwolf can figure out a way to put all of a modmod info into one xml file, have it use whatever schema is needed for each part and use that in game as if it was a modmod folder.
 
PS: I'd PayPal you 10,000 Pounds Sterling, but that's like $100,000 and I need to buy a tank of gas this week.

TIP : Put a housebrick in your tank, then it takes less gas to fill it.

(Note: In England we call it Petrol, and it plainly is NOT a gas, it's a liquid.)

Anyway, reason for delay - I made some changes, didn't like them, un-doing them.
 
TIP : Put a housebrick in your tank, then it takes less gas to fill it.

(Note: In England we call it Petrol, and it plainly is NOT a gas, it's a liquid.)

Anyway, reason for delay - I made some changes, didn't like them, un-doing them.

Even natural gas used to fuel some cars is actually filled and used under pressure and therefore as a liquid
 
Hey I just looked at the optional events thing and I just got it :) I alwyas realised there was potential there but only now has the penny dropped hard enough to sink in. I'm quite excited now, off to experiment...!
 
Im excited to see your next version as well. I spent most of the weekend goign through your files and playing with different things. We probably wont be enabling the pickle functions and per plot python functions because of the processor cost. but Ive been having a lot of fun with all the great ideas you had for search results.

Here is the current mainmod implementation. I dont post it to suggest that you follow it by any means, in fact I hope you continue on with an ever more elaborate and detailed version. But I would be interested in your feedback on things you think we should add and in the slight chance that anything I've rewritten may be of value to you.

First the heart of it is in the actual explore lair ability:

Code:
def spellExploreLair(caster):
	pPlot = caster.plot()
	iRnd = CyGame().getSorenRandNum(100, "Explore Lair")
	iDestroyLair = 0
	if iRnd < 10:
		iDestroyLair = cf.exploreLairBigBad(caster)
	if iRnd >= 10 and iRnd < 40:
		iDestroyLair = cf.exploreLairBad(caster)
	if iRnd >= 40 and iRnd < 70:
		iDestroyLair = cf.exploreLairNeutral(caster)
	if iRnd >= 70 and iRnd < 90:
		iDestroyLair = cf.exploreLairGood(caster)
	if iRnd >= 90:
		iDestroyLair = cf.exploreLairBigGood(caster)
	if iDestroyLair > CyGame().getSorenRandNum(100, "Explore Lair"):
		CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_LAIR_DESTROYED", ()),'AS2D_POSITIVE_DINK',1,'Art/Interface/Buttons/Spells/Explore Lair.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
		pPlot.setImprovementType(-1)

I simplified down to 5 functions to break off into really bad (boss spawns), bad, neutral (very minor effects and easily dispatched spawns), good and really good effects. That way we can play with the chances of going with each or write different odds for different types of lairs (some many be more likely to have bad results, some more likely to have good results, etc).

Then on to the 5 different functions. In this case each builds a list of potential outcomes, then randomly selects one and applies it:

Code:
	def exploreLairBigBad(self, caster):
		iPlayer = caster.getOwner()
		pPlot = caster.plot()
		pPlayer = gc.getPlayer(caster.getOwner())

		lList = ['UNIT_SPIDER', 'UNIT_GARGOYLE', 'UNIT_OGRE']
		lPromoList = ['PROMOTION_MUTATED', 'PROMOTION_CANNIBALIZE', 'PROMOTION_MOBILITY1', 'PROMOTION_STRONG', 'PROMOTION_BLITZ', 'PROMOTION_COMMAND1', 'PROMOTION_HEROIC_STRENGTH', 'PROMOTION_HEROIC_DEFENSE', 'PROMOTION_MAGIC_IMMUNE', 'PROMOTION_STONESKIN', 'PROMOTION_VALOR', 'PROMOTION_VILE_TOUCH']
		lHenchmanList = ['UNIT_AXEMAN', 'UNIT_WOLF', 'UNIT_AZER', 'UNIT_OGRE', 'UNIT_CHAOS_MARAUDER', 'UNIT_WOLF_RIDER', 'UNIT_MISTFORM', 'UNIT_LION']
		if self.grace() == False:
			lList = lList + ['UNIT_AIR_ELEMENTAL', 'UNIT_EARTH_ELEMENTAL', 'UNIT_FIRE_ELEMENTAL', 'UNIT_CHAMPION', 'UNIT_ASSASSIN', 'UNIT_VAMPIRE', 'UNIT_MYCONID', 'UNIT_EIDOLON', 'UNIT_OGRE_WARCHIEF', 'UNIT_WEREWOLF']
			lPromoList = lPromoList + ['PROMOTION_FIRE2', 'PROMOTION_AIR2', 'PROMOTION_HERO', 'PROMOTION_MARKSMAN', 'PROMOTION_SHADOWWALK']
		if pPlot.getTerrainType() == gc.getInfoTypeForString('TERRAIN_SNOW'):
			lHenchmanList = lHenchmanList + ['UNIT_FROSTLING_ARCHER', 'UNIT_FROSTLING_WOLF_RIDER', 'UNIT_POLAR_BEAR']
		if pPlot.isHills():
			lList = lList + ['UNIT_HILL_GIANT','UNIT_HILL_GIANT','UNIT_HILL_GIANT']
			lPromoList = ['PROMOTION_GUERILLA1','PROMOTION_GUERILLA2']
		if pPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_FOREST'):
			lList = lList + ['UNIT_TREANT','UNIT_SATYR', 'UNIT_SATYR']
			lPromoList = lPromoList + ['PROMOTION_WOODSMAN1', 'PROMOTION_WOODSMAN2']
			lHenchmanList = lHenchmanList + ['UNIT_TIGER', 'UNIT_BABY_SPIDER']
		if pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_BARROW'):
			lList = lList + ['UNIT_LICH', 'UNIT_WRAITH', 'UNIT_SPECTRE']
			lPromoList = lPromoList + ['PROMOTION_DEATH2','PROMOTION_DEATH3']
			lHenchmanList = lHenchmanList + ['UNIT_SKELETON', 'UNIT_PYRE_ZOMBIE']
		if pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_RUINS'):
			lList = lList + ['UNIT_MANTICORE']
			lPromoList = lPromoList + ['POISONED_BLADE']
			lHenchmanList = lHenchmanList + ['UNIT_LIZARDMAN', 'UNIT_GORILLA']
		if CyGame().getGlobalCounter() > 40:
			lList = lList + ['UNIT_PIT_BEAST', 'UNIT_DEATH_KNIGHT', 'UNIT_BALOR']
			lPromoList = lPromoList + ['PROMOTION_FEAR']
			lHenchmanList = lHenchmanList + ['UNIT_IMP', 'UNIT_HELLHOUND']
		if pPlot.isWater():
			lList = ['UNIT_WATER_ELEMENTAL', 'UNIT_SEA_SERPENT', 'UNIT_STYGIAN_GUARD', 'UNIT_KRAKEN', 'UNIT_PIRATE']
			lHenchmanList = ['UNIT_DROWN']
		
		sMonster = lList[CyGame().getSorenRandNum(len(lList), "Pick Monster")-1]
		sHenchman = lHenchmanList[CyGame().getSorenRandNum(len(lHenchmanList), "Pick Henchman")-1]
		sPromo = lPromoList[CyGame().getSorenRandNum(len(lPromoList), "Pick Promotion")-1]
		iUnit = gc.getInfoTypeForString(sMonster)
		iHenchman = gc.getInfoTypeForString(sHenchman)
		newUnit = self.addUnitFixed(caster,iUnit)
		if newUnit != -1:
			newUnit.setHasPromotion(gc.getInfoTypeForString(sPromo), True)
			newUnit.setName(self.MarnokNameGenerator(newUnit))
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_BIGBAD",()),'',1,gc.getUnitInfo(iUnit).getButton(),ColorTypes(7),newUnit.getX(),newUnit.getY(),True,True)
			bPlayer = gc.getPlayer(gc.getBARBARIAN_PLAYER())
			for i in range (CyGame().getSorenRandNum(5, "Pick Henchmen")):
				bPlayer.initUnit(iHenchman, newUnit.getX(), newUnit.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
		return 0

	def exploreLairBad(self, caster):
		iPlayer = caster.getOwner()
		pPlot = caster.plot()
		pPlayer = gc.getPlayer(caster.getOwner())

		lList = ['DEATH', 'COLLAPSE']
		if caster.isAlive():
			lList = lList + ['CRAZED', 'DEMONIC_POSSESSION', 'DISEASED', 'ENRAGED', 'PLAGUED', 'POISONED', 'WITHERED']
		if caster.getUnitCombatType() == gc.getInfoTypeForString('UNITCOMBAT_MELEE'):
			lList = lList + ['RUSTED']
		if pPlot.isWater():
			lList = lList + ['SPAWN_DROWN', 'SPAWN_SEA_SERPENT']
		if pPlot.isWater() == False:
			lList = lList + ['SPAWN_SPIDER', 'SPAWN_SPECTRE']
		
		sGoody = lList[CyGame().getSorenRandNum(len(lList), "Pick Goody")-1]
		if sGoody == 'DEATH':
			caster.kill(True,0)
			CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_DEATH", ()),'',1,'Art/Interface/Buttons/Spells/Explore Lair.dds',ColorTypes(7),pPlot.getX(),pPlot.getY(),True,True)
			return 0
		if sGoody == 'COLLAPSE':
			caster.doDamageNoCaster(50, 90, gc.getInfoTypeForString('DAMAGE_PHYSICAL'), false)
			CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_COLLAPSE", ()),'',1,'Art/Interface/Buttons/Spells/Explore Lair.dds',ColorTypes(7),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'CRAZED':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_CRAZED'), True)
			CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_CRAZED", ()),'',1,'Art/Interface/Buttons/Promotions/Crazed.dds',ColorTypes(7),pPlot.getX(),pPlot.getY(),True,True)
			return 80
		if sGoody == 'DEMONIC_POSSESSION':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_ENRAGED'), True)
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_CRAZED'), True)
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_DEMON'), True)
			CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_POSSESSED", ()),'',1,'Art/Interface/Buttons/Units/UCDemon.dds',ColorTypes(7),pPlot.getX(),pPlot.getY(),True,True)
			return 80
		if sGoody == 'DISEASED':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_DISEASED'), True)
			CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_DISEASED", ()),'',1,'Art/Interface/Buttons/Promotions/Diseased.dds',ColorTypes(7),pPlot.getX(),pPlot.getY(),True,True)
			return 80
		if sGoody == 'WITHERED':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_WITHERED'), True)
			CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_WITHERED", ()),'',1,'Art/Interface/Buttons/Promotions/Withered.dds',ColorTypes(7),pPlot.getX(),pPlot.getY(),True,True)
			return 80
		if sGoody == 'PLAGUED':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_PLAGUED'), True)
			CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_PLAGUED", ()),'',1,'Art/Interface/Buttons/Promotions/Plagued.dds',ColorTypes(7),pPlot.getX(),pPlot.getY(),True,True)
			return 80
		if sGoody == 'POISONED':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_POISONED'), True)
			caster.doDamageNoCaster(25, 90, gc.getInfoTypeForString('DAMAGE_POISON'), false)
			CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_POISONED", ()),'',1,'Art/Interface/Buttons/Promotions/Poisoned.dds',ColorTypes(7),pPlot.getX(),pPlot.getY(),True,True)
			return 80
		if sGoody == 'ENRAGED':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_ENRAGED'), True)
			CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_ENRAGED", ()),'',1,'Art/Interface/Buttons/Promotions/Enraged.dds',ColorTypes(7),pPlot.getX(),pPlot.getY(),True,True)
			return 80		
		if sGoody == 'RUSTED':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_RUSTED'), True)
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_BRONZE_WEAPONS'), False)
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_IRON_WEAPONS'), False)
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MITHRIL_WEAPONS'), False)
			CyInterface().addMessage(caster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_RUSTED", ()),'',1,'Art/Interface/Buttons/Promotions/Rusted.dds',ColorTypes(7),pPlot.getX(),pPlot.getY(),True,True)
			return 80
		if sGoody == 'SPAWN_DROWN':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_SPAWN_DROWN'), caster)
			return 50
		if sGoody == 'SPAWN_SEA_SERPENT':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_SPAWN_SEA_SERPENT'), caster)
			return 50
		if sGoody == 'SPAWN_SPECTRE':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_GRAVE_SPECTRE'), caster)
			return 50
		if sGoody == 'SPAWN_SPIDER':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_SPAWN_SPIDER'), caster)
			return 50
		return 100

	def exploreLairNeutral(self, caster):
		iPlayer = caster.getOwner()
		pPlot = caster.plot()
		pPlayer = gc.getPlayer(caster.getOwner())
		lList = ['NOTHING']
		if pPlot.isWater() == False:
			lList = lList + ['SPAWN_SKELETON', 'SPAWN_LIZARDMAN', 'SPAWN_SPIDER']
			if pPlot.getTerrainType() == gc.getInfoTypeForString('TERRAIN_SNOW'):
				lList = lList + ['SPAWN_FROSTLING']
			if pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_BARROW'):
				lList = lList + ['SPAWN_SKELETON', 'SPAWN_SKELETON']
			if pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_RUINS'):
				lList = lList + ['SPAWN_LIZARDMAN', 'SPAWN_LIZARDMAN']
		if pPlot.isWater():
			lList = ['SPAWN_DROWN']
		if caster.isAlive():
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_MUTATED')) == False:
				lList = lList + ['MUTATED']
		
		sGoody = lList[CyGame().getSorenRandNum(len(lList), "Pick Goody")-1]
		if sGoody == 'MUTATED':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MUTATED'), True)
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_MUTATED",()),'',1,'Art/Interface/Buttons/Promotions/Mutated.dds',ColorTypes(7),caster.getX(),caster.getY(),True,True)
			return 50
		if sGoody == 'NOTHING':
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_NOTHING",()),'',1,'Art/Interface/Buttons/Spells/Explore Lair.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'SPAWN_DROWN':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_SPAWN_DROWN'), caster)
			return 50
		if sGoody == 'SPAWN_FROSTLING':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_SPAWN_FROSTLING'), caster)
			return 50
		if sGoody == 'SPAWN_LIZARDMAN':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_SPAWN_LIZARDMAN'), caster)
			return 50
		if sGoody == 'SPAWN_SKELETON':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_SPAWN_SKELETON'), caster)
			return 50
		if sGoody == 'SPAWN_SPIDER':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_SPAWN_SPIDER'), caster)
			return 50
		return 100

	def exploreLairGood(self, caster):
		iPlayer = caster.getOwner()
		pPlot = caster.plot()
		pPlayer = gc.getPlayer(caster.getOwner())
		lList = ['HIGH_GOLD', 'TREASURE', 'EXPERIENCE']
		if caster.isAlive():
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_SPIRIT_GUIDE')) == False:
				lList = lList + ['SPIRIT_GUIDE']
		if pPlot.isWater() == False:
			lList = lList + ['ITEM_HEALING_SALVE']
		if caster.getUnitCombatType() == gc.getInfoTypeForString('UNITCOMBAT_MELEE'):
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_ENCHANTED_BLADE')) == False:
				lList = lList + ['ENCHANTED_BLADE']
		if caster.getUnitCombatType() == gc.getInfoTypeForString('UNITCOMBAT_ADEPT'):
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_SPELLSTAFF')) == False:
				lList = lList + ['SPELLSTAFF']
		if caster.getUnitCombatType() == gc.getInfoTypeForString('UNITCOMBAT_RECON'):
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_POISONED_BLADE')) == False:
				lList = lList + ['POISONED_BLADE']
		if caster.getUnitCombatType() == gc.getInfoTypeForString('UNITCOMBAT_ARCHER'):
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_FLAMING_ARROWS')) == False:
				lList = lList + ['FLAMING_ARROWS']
		if caster.getUnitCombatType() == gc.getInfoTypeForString('UNITCOMBAT_DISCIPLE'):
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_SHIELD_OF_FAITH')) == False:
				lList = lList + ['SHIELD_OF_FAITH']
		if gc.getUnitInfo(caster.getUnitType()).getWeaponTier() >= 1:
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_MITHRIL_WEAPONS')) == False:
				if gc.getUnitInfo(caster.getUnitType()).getWeaponTier() >= 3:
					lList = lList + ['MITHIL_WEAPONS']
				if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_IRON_WEAPONS')) == False:
					if gc.getUnitInfo(caster.getUnitType()).getWeaponTier() >= 2:
						lList = lList + ['IRON_WEAPONS']
					if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_BRONZE_WEAPONS')) == False:
						lList = lList + ['BRONZE_WEAPONS']

		sGoody = lList[CyGame().getSorenRandNum(len(lList), "Pick Goody")-1]
		if sGoody == 'HIGH_GOLD':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_HIGH_GOLD'), caster)
			return 90
		if sGoody == 'TREASURE':
			pBestPlot = -1
			iBestPlot = -1
			for i in range (CyMap().numPlots()):
				pPlot = CyMap().plotByIndex(i)
				iPlot = -1
				if pPlot.isWater() == False:
					if pPlot.getNumUnits() == 0:
						if pPlot.isCity() == False:
							if pPlot.isImpassable() == False:
								iPlot = CyGame().getSorenRandNum(1000, "Add Unit") + 1000
								iPlot = iPlot - (pPlot.area().getNumTiles() * 10)
								if pPlot.isOwned():
									iPlot = iPlot / 2
								if iPlot > iBestPlot:
									iBestPlot = iPlot
									pBestPlot = pPlot
			if iBestPlot != -1:
				bPlayer = gc.getPlayer(gc.getBARBARIAN_PLAYER())
				newUnit = bPlayer.initUnit(gc.getInfoTypeForString('EQUIPMENT_TREASURE'), pBestPlot.getX(), pBestPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
				CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_TREASURE",()),'',1,'Art/Interface/Buttons/Equipment/Treasure.dds',ColorTypes(8),newUnit.getX(),newUnit.getY(),True,True)
			return 80
		if sGoody == 'EXPERIENCE':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_EXPERIENCE'), caster)
			return 100
		if sGoody == 'SPIRIT_GUIDE':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_SPIRIT_GUIDE'), True)
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_SPIRIT_GUIDE",()),'AS2D_POSITIVE_DINK',1,'Art/Interface/Buttons/Promotions/SpiritGuide.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 80
		if sGoody == 'ITEM_HEALING_SALVE':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_ITEM_HEALING_SALVE'), caster)
			return 100
		if sGoody == 'ITEM_POTION_OF_INVISIBILITY':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_ITEM_POTION_OF_INVISIBILITY'), caster)
			return 100
		if sGoody == 'ITEM_POTION_OF_RESTORATION':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_ITEM_POTION_OF_RESTORATION'), caster)
			return 100
		if sGoody == 'ENCHANTED_BLADE':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_ENCHANTED_BLADE'), True)
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_ENCHANTED_BLADE",()),'',1,'Art/Interface/Buttons/Promotions/EnchantedBlade.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'SPELLSTAFF':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_SPELLSTAFF'), True)
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_SPELLSTAFF",()),'',1,'Art/Interface/Buttons/Promotions/Spellstaff.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'POISONED_BLADE':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_POISONED_BLADE'), True)
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_POISONED_BLADE",()),'',1,'Art/Interface/Buttons/Promotions/PoisonedBlade.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'FLAMING_ARROWS':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_FLAMING_ARROWS'), True)
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_FLAMING_ARROWS",()),'AS2D_POSITIVE_DINK',1,'Art/Interface/Buttons/Promotions/FlamingArrows.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'SHIELD_OF_FAITH':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_SHIELD_OF_FAITH'), True)
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_SHEILD_OF_FAITH",()),'',1,'Art/Interface/Buttons/Promotions/ShieldOfFaith.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'BRONZE_WEAPONS':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_BRONZE_WEAPONS'), True)
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_BRONZE_WEAPONS",()),'',1,'Art/Interface/Buttons/Promotions/BronzeWeapons.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_RUSTED')) == True:
				caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_RUSTED'),False)
			return 100
		if sGoody == 'IRON_WEAPONS':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_IRON_WEAPONS'), True)
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_BRONZE_WEAPONS'), False)
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_IRON_WEAPONS",()),'',1,'Art/Interface/Buttons/Promotions/IronWeapons.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_RUSTED')) == True:
				caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_RUSTED'),False)
			return 100
		if sGoody == 'MITHRIL_WEAPONS':
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_MITHRIL_WEAPONS'), True)
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_IRON_WEAPONS'), False)
			caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_BRONZE_WEAPONS'), False)
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_MITHRIL_WEAPONS",()),'',1,'Art/Interface/Buttons/Promotions/MithrilWeapons.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			if caster.isHasPromotion(gc.getInfoTypeForString('PROMOTION_RUSTED')) == True:
				caster.setHasPromotion(gc.getInfoTypeForString('PROMOTION_RUSTED'),False)
			return 100
		return 100

	def exploreLairBigGood(self, caster):
		iPlayer = caster.getOwner()
		pPlot = caster.plot()
		pPlayer = gc.getPlayer(caster.getOwner())

		lList = ['TREASURE_VAULT', 'PRISONER_ADVENTURER', 'PRISONER_ARTIST', 'PRISONER_COMMANDER', 'PRISONER_ENGINEER', 'PRISONER_MECHANT', 'PRISONER_PROPHET', 'PRISONER_SCIENTIST', 'TECH']
		if pPlot.isWater() == False:
			lList = lList + ['ITEM_JADE_TORC', 'ITEM_ROD_OF_WINDS', 'ITEM_TIMOR_MASK']
			if pPlot.getBonusType(-1) == -1:
				lList = lList + ['BONUS_MANA']
				if pPlayer.isHasTech(gc.getInfoTypeForString('TECH_MINING')):
					lList = lList + ['BONUS_COPPER', 'BONUS_GEMS', 'BONUS_GOLD']
				if pPlayer.isHasTech(gc.getInfoTypeForString('TECH_SMELTING')):
					lList = lList + ['BONUS_IRON']
		if pPlot.isWater():
			lList = lList + ['PRISONER_SEA_SERPENT']
		if self.grace() == False:
			lList = lList + ['PRISONER_ANGEL', 'PRISONER_MONK']
			infoCiv = gc.getCivilizationInfo(pPlayer.getCivilizationType())
			iUnit = infoCiv.getCivilizationUnits('UNIT_ASSASSIN')
			if iUnit != -1:
				lList = lList + ['PRISONER_ASSASSIN']
			iUnit = infoCiv.getCivilizationUnits('UNIT_CHAMPION')
			if iUnit != -1:
				lList = lList + ['PRISONER_CHAMPION']
			iUnit = infoCiv.getCivilizationUnits('UNIT_MAGE')
			if iUnit != -1:
				lList = lList + ['PRISONER_MAGE']
		sGoody = lList[CyGame().getSorenRandNum(len(lList), "Pick Goody")-1]

		if sGoody == 'TREASURE_VAULT':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_TREASURE_VAULT'), caster)
			return 100	
		if sGoody == 'BONUS_COPPER':
			pPlot.setBonusType(gc.getInfoTypeForString('BONUS_COPPER'))
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_BONUS_COPPER",()),'',1,'Art/Interface/Buttons/Spells/Explore Dungeon.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'BONUS_GOLD':
			pPlot.setBonusType(gc.getInfoTypeForString('BONUS_GOLD'))
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_BONUS_GOLD",()),'',1,'Art/Interface/Buttons/Spells/Explore Dungeon.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'BONUS_GEMS':
			pPlot.setBonusType(gc.getInfoTypeForString('BONUS_GEMS'))
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_BONUS_GEMS",()),'',1,'Art/Interface/Buttons/Spells/Explore Dungeon.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'BONUS_IRON':
			pPlot.setBonusType(gc.getInfoTypeForString('BONUS_IRON'))
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_BONUS_IRON",()),'',1,'Art/Interface/Buttons/Spells/Explore Dungeon.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'BONUS_MANA':
			pPlot.setBonusType(gc.getInfoTypeForString('BONUS_MANA'))
			CyInterface().addMessage(iPlayer,True,25,CyTranslator().getText("TXT_KEY_MESSAGE_EXPLORE_LAIR_BONUS_MANA",()),'',1,'Art/Interface/Buttons/Spells/Explore Dungeon.dds',ColorTypes(8),pPlot.getX(),pPlot.getY(),True,True)
			return 100
		if sGoody == 'ITEM_JADE_TORC':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_ITEM_JADE_TORC'), caster)
			return 100
		if sGoody == 'ITEM_ROD_OF_WINDS':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_ITEM_ROD_OF_WINDS'), caster)
			return 100
		if sGoody == 'ITEM_TIMOR_MASK':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_ITEM_TIMOR_MASK'), caster)
			return 100
		if sGoody == 'PRISONER_ADVENTURER':
			pPlayer.receiveGoody(pPlot,gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_ADVENTURER'), caster)
			return 100			
		if sGoody == 'PRISONER_ANGEL':
			pPlayer.receiveGoody(pPlot,gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_ANGEL'), caster)
			return 100			
		if sGoody == 'PRISONER_ARTIST':
			pPlayer.receiveGoody(pPlot,gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_ARTIST'), caster)
			return 100
		if sGoody == 'PRISONER_ASSASSIN':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_ASSASSIN'), caster)
			return 100
		if sGoody == 'PRISONER_CHAMPION':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_CHAMPION'), caster)
			return 100
		if sGoody == 'PRISONER_COMMANDER':
			pPlayer.receiveGoody(pPlot,gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_COMMANDER'), caster)
			return 100	
		if sGoody == 'PRISONER_ENGINEER':
			pPlayer.receiveGoody(pPlot,gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_ENGINEER'), caster)
			return 100	
		if sGoody == 'PRISONER_MAGE':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_MAGE'), caster)
			return 100
		if sGoody == 'PRISONER_MERCHANT':
			pPlayer.receiveGoody(pPlot,gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_MERCHANT'), caster)
			return 100	
		if sGoody == 'PRISONER_MONK':
			pPlayer.receiveGoody(pPlot,gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_MONK'), caster)
			return 100			
		if sGoody == 'PRISONER_PROPHET':
			pPlayer.receiveGoody(pPlot,gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_PROPHET'), caster)
			return 100	
		if sGoody == 'PRISONER_SEA_SERPENT':
			pPlayer.receiveGoody(pPlot,gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_SEA_SERPENT'), caster)
			return 100	
		if sGoody == 'PRISONER_SCIENTIST':
			pPlayer.receiveGoody(pPlot,gc.getInfoTypeForString('GOODY_EXPLORE_LAIR_PRISONER_SCIENTIST'), caster)
			return 100
		if sGoody == 'TECH':
			pPlayer.receiveGoody(pPlot, gc.getInfoTypeForString('GOODY_GRAVE_TECH'), caster)
			return 100
		return 100

This format worked well for me becuase its really easy to make results conditional as well as add and remove results.

As I mentioned you have done some really awesome work and Im already having fun playing with it all in 0.34. Keep the good stuff coming and let me know if there is anythign I can do to help you. :goodjob:
 
Cool thanks Kael! Looking good.

I was actually leaning toward a "pickone" style list for results similar to that used in the name generator. So I would have bundles of results and add different bundles conditionally, then pick one result from the overall list.

Doesn't make a huge difference perhaps, but from my point of view if makes it clearer what's happening and easier for someone to just add their own results without having to reorganize the result tables.

Quickly mock up code because I don't have the files handy:

Code:
lResults = ['Neutral_Result_1', 'Neutral_Result_2', 'Neutral_Result_3']
lBadResults = ['BAD_RESULT_1', 'BAD_RESULT_2']
lGoodResults = ['GOOD_RESULT_1','GOOD_RESULT_2']
lLateResults = ['LATE_RESULTS_1','LATE_RESULTS_2']
lRareResults = ['RARE_RESULTS_1','RARE_RESULTS_2']

lCivResults = [
[ 'CIVILIZATION_HIPPUS',['HIPPUS_EVENT_1', 'HIPPUS_EVENT_2'] ],
]

// Build List

if RND < 10:
    lResults = lResults + lBadResults
if RND < 20: 
    lResults = lResults + lBadResults
    // yes, they get added twice if the result was bad enough, so they have twice the chance to appear
if RND > 60:
    lResults = lResults + lGoodResults
if gameturn > threshold:
    lResults = lResults + lLateResults

// add one from rare list
lResults = lResults +pickone(lRareResults)

// check to see if various other lists can be added. Is the civ in the civ specific list,
// does the civ have any civics from the civics specific list,
// does its religion appear in the religions list, 
// etc.

actaulresult = pickone{lResults)

// just my standard pickone:
def pickone(mylist):
	# returns one entry at random from any list
	return mylist[CyGame().getSorenRandNum(len(mylist), "marnok")-1]

That sort of thing. Similarly the "random monsters" would be lists so I can more easily control the early appearance of nastier monsters, but you already have that.

The idea was that it would be easier for modmodders to add sets of events - add lMyModBadResults[] or just amend my list and drop it in. Easier for casual player to remove events they don't like too (I was actually putting the lists in the settings.py)

I was looking at using pickle to store results and have the results event-based, with the option to back out. So when you find a dungeon it might have the result "there's a big rune-sealed door, do you want to open it" which you know from experience might mean some nasty demon inside; so you might decide to leave it until later, or maybe even defend it paranoid-ly to stop another civ exploring it. (I was playing with ways to add traps and defences to a lair, which players and AIs could use too, but it looked like turning into a whole other mod... hence delays)

Perhaps I should wait until 0.34 is out and other modmodders are playing with it, see what people come up with, then do a new discussion on what to do next. That turned out to be very productive before.
 
event-based lair sound definitely nice. and Kael's words here make it seem like 0.34 is not very far away, which is also very good :D
 
0.34 isnt coming anytime soon. We have a lot to do for it, explorable lairs just happened to be one of the first things checked in. I wouldn't hold up waiting for it.
 
I'd've thought putting explorable lairs in was big enough to justify a release :)

"Marnok's Explorable Lairs 0.34 featuring FfH2"
 
I'd've thought putting explorable lairs in was big enough to justify a release :)

"Marnok's Explorable Lairs 0.34 featuring FfH2"

:lol: You arent far off, it is a pretty cool enhancement to the early game. But we have a few more surprises in store too. ;)
 
For now we stick with Fall Further to play with lairs. :D

Must admit I'm looking forward to the MainMod inclusion myself - I've been meaning to go through what Marnok has been working on and update the version we have included in Fall Further for a while now but this will actually give me a solid reason to do it :)

Looking at that implementation it's going to be an interesting merge, especially with things like the "Adventurer" promotion. Do you mind if I use that code now and have a play around with it for a version of Fall Further before 034, Kael?
 
Must admit I'm looking forward to the MainMod inclusion myself - I've been meaning to go through what Marnok has been working on and update the version we have included in Fall Further for a while now but this will actually give me a solid reason to do it :)

Looking at that implementation it's going to be an interesting merge, especially with things like the "Adventurer" promotion. Do you mind if I use that code now and have a play around with it for a version of Fall Further before 034, Kael?

You know your welcome to anything that helps you! :)
 
@ Marnok: Still changing the system a lot so thats the reason for delay and we can expect something soon? Or are the whole things changing so big you decided to go straight to 0.34 and helping with that solely so we won't see something new here until then? (Some weeks till 0.34 can be a long time. :( But whould be understandable either way.)

Whould be glad to know. ;)
 
Hi Blackmantle,

it's sort of a combination of things - I wanted to revamp anyway, then hearing 0.34 will have a new core of functions to play with meant I was simultaneously
a) more free to try out my own new ideas because the basics will already be there for people, and
b) more reluctant to make big changes when I will have to re-do when 0.34 is out

so I was thinking, just adjust the previous files and re-release while fiddling with my own stuff, but then I got busy and didn't have the time and thought oh, 0.34 is probably not far off, then I though I might as well do it anyway then I got lazy and didn't do it yet.

I think maybe I'll just say "wait for 0.34" then I'll make MarnokMod2 or something, it's like 0.34 is an autosave point for me and I don't want to lose any lives before then!
 
Hey,

Mostly a lurker here and I haven't read the entire thread, but based off the code there/my experiences with it in ff(my apologies if I'm resuggesting any ideas that have been suggested already):

First, any plans for taking the idea of enabling stronger units as time goes on, and expanding it, so early on, when you have weak units, its less likely to spawn strong enemies, and as time goes on, its more and more likely to get monsters that are boss strength(and on the other hand, increase the rewards as well). Could do this by adding more than one copy of the stronger versions as time goes on(and more than one copy of the easier ones for earlier on). eg.

add warrior, champion
if(time <40) add warrior x7,
if(time >80) add champion x3

So at time <40, you are only 1/8th of a chance to spawn a champ, at 40-80 both are 50% likely, and >80 the champ is 4/5ths likely.
Of course if you go this route, prob need to somehow take game speed into account?
(could even throw difficulty in here as well if you want, where it can spawn harder stuff earlier on higher diffs, just load a different prob list for each diff?)


I was also wondering if there was ever an idea for any of the events to be spawn an enemy with a artifact? Would be perhaps a neutral event, and perhaps not enabled till later turn wise? This way you have the risk of the enemy(ideally a somewhat strong one), but provided you can kill it, get the artifact to use later.

Another idea(not sure how possible this is), is to try mixing the boss idea above with other rewards, so that if you are able to beat the boss within some time period, you get a reward(could be the above artifacts, or even other rewards, like cash, resources, etc), otherwise after a fixed number of turns, he stops rampaging and returns into to the lair?

Conceptually it could the following: You explore the lair and manage to steal some gold from a dragons lair. This gives you an initial rewards of some cash, but also spawns a dragon for x number of turns. He will go away(possibly even create a new lair where he is) after 10 turns, but if you manage to defeat him before then, you can get some further reward, if you fail to kill him before he returns to his lair, then theres no way to get the further rewards other than to spawn him from a different lair later.


Another idea would be to have a 2nd set of rarer, higher likelyhood of bigGood/bigBad lairs as well(aka only a few spawn on the map, but its a 40%chance of big good/40% chance of bigBad).


Also, a last idea: have some of the world improvements be unique lairs, either existing improvements or new ones. Would have to perhaps limit them to being explored when they were in your cultural borders, or make it so they aren't destroyed when explored, just marked as explored, but could have unique risk/rewards for them, even possibly some of the new trait possibilities for some civs that have recently been introduced. Would make sense that you have to actually explore the lair/kick out the current residents in order to get the new trait from being inspired by that site.
 
Top Bottom