1. We have added the ability to collapse/expand forum categories and widgets on forum home.
    Dismiss Notice
  2. Photobucket has changed its policy concerning hotlinking images and now requires an account with a $399.00 annual fee to allow hotlink. More information is available at: this link.
    Dismiss Notice
  3. All Civ avatars are brought back and available for selection in the Avatar Gallery! There are 945 avatars total.
    Dismiss Notice
  4. To make the site more secure, we have installed SSL certificates and enabled HTTPS for both the main site and forums.
    Dismiss Notice
  5. Civ6 is released! Order now! (Amazon US | Amazon UK | Amazon CA | Amazon DE | Amazon FR)
    Dismiss Notice
  6. Dismiss Notice
  7. Forum account upgrades are available for ad-free browsing.
    Dismiss Notice

[MODCOMP] Occasional Promotions

Discussion in 'Civ4 - Mod Components' started by killmeplease, Feb 21, 2010.

  1. killmeplease

    killmeplease Mk Z on Steam

    Joined:
    Nov 22, 2007
    Messages:
    2,690
    Location:
    Samara
    This modcomp makes it possible for units to receive promotions in non-ordinary way: any unit has a chanse to get free promotion depending on how well and in what conditions it fights.

    take a look at this picture:


    Jaguar Warrior has promoted to Cover. You can also notice that one of barbarian archers promoted to City Garrison I.

    How does it work?
    In every battle a unit has a chanse of getting a free promotion. Tougher battle it fights, higher chanse for it to get promotion. Chanse of it equals to (100-winning probability). E.g. if you have 50% chanse to win a battle, you will have 50% chanse of promotion as you won it. Also there is a bonus for saved HP. saved HP bonus = ((hp after battle)/(hp before battle))^2: +100% if you lose 0% hp, +25% if you lose 50% etc. So if you won a battle at 60% winning chanse and lost 20% of initial HP during it, you have a 40*1.64 = 65.6% chanse to get promotion.

    Type of free promotion is determined by battle conditions and promotions your unit already has. E.g. for Jaguar Warrior on the picture above, it's possible to get either cover, or city raider I, or guerilla III (if he had guerilla I and II already), or Amphibious (if he had combat II), or Combat II (if he had combat I).

    i hope you understand my english :blush:

    Download here
     
  2. NotSoGood

    NotSoGood Chieftain

    Joined:
    Jan 25, 2009
    Messages:
    1,077
    Location:
    Finland
    Wow, nice modcomp. I might actually add it to my mod when I get it work again. :goodjob: Good job!
    EDIT: This way units can have more promotions than normally (->awesome), or did I get the idea wrong?
     
  3. killmeplease

    killmeplease Mk Z on Steam

    Joined:
    Nov 22, 2007
    Messages:
    2,690
    Location:
    Samara
  4. killmeplease

    killmeplease Mk Z on Steam

    Joined:
    Nov 22, 2007
    Messages:
    2,690
    Location:
    Samara
    Yeah, units can get free promotions from combats as well as those from getting levels.
     
  5. cybrxkhan

    cybrxkhan Asian Xwedodah

    Joined:
    Aug 10, 2006
    Messages:
    9,687
    Location:
    The Universe
    This is quite something! I think this is how the promotion system should have been all along, and it makes more sense. I might add it in the final version of WoL.

    Goodjob, anyhow.
     
  6. primordial stew

    primordial stew Chieftain

    Joined:
    Sep 1, 2005
    Messages:
    1,219
    Location:
    a puddle
    A really great idea ;)

    If I were to use it in a mod I'd allow certain promos to be received only through combat. Basic strength, flanking, movement.. from XP, but city attack/defense, anti-archer/melee/tank... only through direct combat in an appropriate way. City attack/defense from attacking/defending cities or forts only!
     
  7. Manifold

    Manifold ModderProtectionAdvocate

    Joined:
    Aug 27, 2007
    Messages:
    1,444
    Very good idea. just one question please: if a unit get promotions by battle, is it not necessary to great more and weaker promotions, otherwise we get a lot of overly strong units in the game? What is the chance for a unit to get a battlepromotion? How is it chance changeable?
     
  8. killmeplease

    killmeplease Mk Z on Steam

    Joined:
    Nov 22, 2007
    Messages:
    2,690
    Location:
    Samara
    I want to thank everyone for your feedback!

    Chanse to get a battle promotion is inversely proportional to a chanse of winning a battle, so it is difficult for a unit to get many promotions from battles. there is no mechanism to change this chanse so far. maybe i have to add a specific modifier tag to gameinfo.xml..
     
  9. killmeplease

    killmeplease Mk Z on Steam

    Joined:
    Nov 22, 2007
    Messages:
    2,690
    Location:
    Samara
    I had the same idea too but it seemed to much tedious coding for me (adding new xml tags, :twitch:)
     
  10. NotSoGood

    NotSoGood Chieftain

    Joined:
    Jan 25, 2009
    Messages:
    1,077
    Location:
    Finland
    How it's defined what promotion will be given?
     
  11. killmeplease

    killmeplease Mk Z on Steam

    Joined:
    Nov 22, 2007
    Messages:
    2,690
    Location:
    Samara
    at first i define a vector to store info about what promotions can be obtained. then i loop through promotion types and add ones that fit conditions. if size of vector is greater than zero, i use RNG to test if a unit will get promotion. if it will, i use RNG again to determine what promotion to give.

    code:
    Spoiler :

    Code:
    	std::vector<PromotionTypes> aAttackerAvailablePromotions;
    	std::vector<PromotionTypes> aDefenderAvailablePromotions;
    	int iI;
    	for (iI = 0; iI < GC.getNumPromotionInfos(); iI++)	//loop through promotions
    	{
    		if (pDefender->isDead() || bDefenderWithdrawn)
    		{
    			//* defender withdrawn, give him withdrawal promo
    			if (bDefenderWithdrawn && GC.getPromotionInfo((PromotionTypes)iI).getWithdrawalChange() > 0 &&
    				pDefender->canAcquirePromotion((PromotionTypes)iI))
    			{
    				aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    		
    			if (!canAcquirePromotion((PromotionTypes)iI)) //attacker can not acquire this promotion
    			{
    				continue;
    			}
    
    			//* attacker was crossing river
    			if (GC.getPromotionInfo((PromotionTypes)iI).isRiver() && cdDefenderDetails.iRiverAttackModifier != 0)	//this bonus is being applied to defender
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* attack from water
    			else if (GC.getPromotionInfo((PromotionTypes)iI).isAmphib() && cdDefenderDetails.iAmphibAttackModifier != 0)
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* attack terrain
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getTerrainAttackPercent((int)pPlot->getTerrainType()) > 0)
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* attack feature
    			else if (pPlot->getFeatureType() != NO_FEATURE && 
    				GC.getPromotionInfo((PromotionTypes)iI).getFeatureAttackPercent((int)pPlot->getFeatureType()) > 0)
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* attack hills
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getHillsAttackPercent() > 0 && pPlot->isHills())
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* attack city
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getCityAttackPercent() > 0 && pPlot->isCity(true))	//count forts too
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* first strikes/chanses promotions
    			else if ((GC.getPromotionInfo((PromotionTypes)iI).getFirstStrikesChange() > 0 || 
    				GC.getPromotionInfo((PromotionTypes)iI).getChanceFirstStrikesChange() > 0) && (firstStrikes() > 0 || chanceFirstStrikes() > 0)	)
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* unit combat mod
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getUnitCombatModifierPercent((int)pDefender->getUnitCombatType()) > 0)
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* combat strength promotions
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getCombatPercent() > 0)
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* domain mod
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getDomainModifierPercent((int)pDefender->getDomainType()))
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* blitz
    			else if (GC.getPromotionInfo((PromotionTypes)iI).isBlitz() && bAttackerHasLostNoHP)
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    		}	//if defender is dead or withdrawn
    		else	//attacker is dead or withdrawn
    		{
    			//* attacker withdrawn
    			if (bAttackerWithdrawn && GC.getPromotionInfo((PromotionTypes)iI).getWithdrawalChange() > 0 && canAcquirePromotion((PromotionTypes)iI))
    			{
    				aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			
    			if (!pDefender->canAcquirePromotion((PromotionTypes)iI)) 
    			{
    				continue;
    			}
    
    			//* defend terrain
    			if (GC.getPromotionInfo((PromotionTypes)iI).getTerrainDefensePercent((int)pPlot->getTerrainType()) > 0)
    			{
    				aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* defend feature
    			else if (pPlot->getFeatureType() != NO_FEATURE && 
    				GC.getPromotionInfo((PromotionTypes)iI).getFeatureDefensePercent((int)pPlot->getFeatureType()) > 0)
    			{
    				aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* defend hills
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getHillsDefensePercent() > 0 && pPlot->isHills())
    			{
    				aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* defend city
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getCityDefensePercent() > 0 && pPlot->isCity(true))	//count forts too
    			{
    				aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* first strikes/chanses promotions
    			else if ((GC.getPromotionInfo((PromotionTypes)iI).getFirstStrikesChange() > 0 || 
    				GC.getPromotionInfo((PromotionTypes)iI).getChanceFirstStrikesChange() > 0) && 
    				(pDefender->firstStrikes() > 0 || pDefender->chanceFirstStrikes() > 0))
    			{
    				aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* unit combat mod vs attacker unit type
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getUnitCombatModifierPercent((int)getUnitCombatType()) > 0)
    			{
    				aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* combat strength promotions
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getCombatPercent() > 0)
    			{
    				aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    			//* domain mod
    			else if (GC.getPromotionInfo((PromotionTypes)iI).getDomainModifierPercent((int)getDomainType()))
    			{
    				aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
    			}
    		}	//if attacker withdrawn
    	}	//end promotion types cycle
    
    	//promote attacker:
    	if (!isDead() && aAttackerAvailablePromotions.size() > 0)
    	{
    		int iHealthPercent = (maxHitPoints() - getDamage()) * 100 / (maxHitPoints() - iAttackerInitialDamage);
    		int iPromotionChanseModifier = iHealthPercent * iHealthPercent / maxHitPoints();
    		int iPromotionChanse = (GC.getDefineINT("COMBAT_DIE_SIDES") - iWinningOdds) * (100 + iPromotionChanseModifier) / 100;
    		
    		if (GC.getGameINLINE().getSorenRandNum(GC.getDefineINT("COMBAT_DIE_SIDES"), "Occasional Promotion") < iPromotionChanse)
    		{
    			//select random promotion from available
    			PromotionTypes ptPromotion = aAttackerAvailablePromotions[
    				GC.getGameINLINE().getSorenRandNum(aAttackerAvailablePromotions.size(), "Select Promotion Type")];
    			//promote
    			setHasPromotion(ptPromotion, true);
    			//show message
    			CvWString szBuffer = gDLL->getText("TXT_KEY_MISC_YOUR_UNIT_PROMOTED_IN_BATTLE", getNameKey(), GC.getPromotionInfo(ptPromotion).getText());
    			gDLL->getInterfaceIFace()->addMessage(
    				getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, 
    				GC.getPromotionInfo((PromotionTypes)0).getSound(), MESSAGE_TYPE_INFO, NULL, 
    				(ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), this->plot()->getX_INLINE(), this->plot()->getY_INLINE());
    		}
    	}
    	//promote defender:
    	if (!pDefender->isDead() && aDefenderAvailablePromotions.size() > 0)
    	{
    		int iHealthPercent = (maxHitPoints() - pDefender->getDamage()) * 100 / (maxHitPoints() - iDefenderInitialDamage);
    		int iPromotionChanseModifier = iHealthPercent * iHealthPercent / maxHitPoints();
    		int iPromotionChanse = iWinningOdds * (100 + iPromotionChanseModifier) / 100;
    	
    		if (GC.getGameINLINE().getSorenRandNum(GC.getDefineINT("COMBAT_DIE_SIDES"), "Occasional Promotion") < iPromotionChanse)
    		{
    			//select random promotion from available
    			PromotionTypes ptPromotion = aDefenderAvailablePromotions[
    				GC.getGameINLINE().getSorenRandNum(aDefenderAvailablePromotions.size(), "Select Promotion Type")];
    			//promote
    			pDefender->setHasPromotion(ptPromotion, true);
    			//show message
    			CvWString szBuffer = gDLL->getText("TXT_KEY_MISC_YOUR_UNIT_PROMOTED_IN_BATTLE", pDefender->getNameKey(), 
    				GC.getPromotionInfo(ptPromotion).getText());
    			gDLL->getInterfaceIFace()->addMessage(
    				pDefender->getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, 
    				GC.getPromotionInfo((PromotionTypes)0).getSound(), MESSAGE_TYPE_INFO, NULL, 
    				(ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());
    		}
    	}
    
    p.s.: defender can not to withdraw in this modcomp, i added bDefenderWithdrawn check for compatibility with my other modcomp.
     
  12. Shiggs713

    Shiggs713 Immortal

    Joined:
    Mar 11, 2007
    Messages:
    2,361
    Location:
    Indianapolis
    ok your mods are merged! :thumbsup: I am having some kind of issue with the commanders not promoting but I think that can easily be fixed. Also you were missing a little game text for the promotions in battle, here's all I noticed for now.

    Code:
    <TEXT>
    		<Tag>TXT_KEY_MISC_YOUR_UNIT_PROMOTED_IN_BATTLE</Tag>
    		<English>Your unit has been promoted in battle!</English>
    		<French/>
    		<German/>
    		<Italian/>
    		<Spanish/>
    	</TEXT>
    thanks
     
  13. killmeplease

    killmeplease Mk Z on Steam

    Joined:
    Nov 22, 2007
    Messages:
    2,690
    Location:
    Samara
    make sure you've copied CIV4GameText_MOD_OP.xml into your Assets\XML\Text forlder
     
  14. Shiggs713

    Shiggs713 Immortal

    Joined:
    Mar 11, 2007
    Messages:
    2,361
    Location:
    Indianapolis
    LOL, yea your right, I only copied the game text from commanders. :lol:
     
  15. Sephi

    Sephi Chieftain

    Joined:
    Jan 25, 2009
    Messages:
    2,908
    thanks for this modcomp :goodjob:
     
  16. NBAfan

    NBAfan boss

    Joined:
    Aug 30, 2007
    Messages:
    3,351
    Location:
    Dallas TX,United States
    This modcomp is great! Thank you for making it!:goodjob: Afforess put it in A New Dawn so there is quite a lot of people playing with it.
     
  17. keldath

    keldath LivE LonG AnD PrOsPeR

    Joined:
    Dec 20, 2005
    Messages:
    6,137
    Location:
    israel
    very coll mod comp - great work!
     
  18. Arian

    Arian No more ghostbusting!!

    Joined:
    May 10, 2008
    Messages:
    2,088
    Location:
    The Netherlands
    :bump:

    What happens if a unit runs out of promotions? Will this generate a CTD?
     
  19. killmeplease

    killmeplease Mk Z on Steam

    Joined:
    Nov 22, 2007
    Messages:
    2,690
    Location:
    Samara
    No, nothing will happen
     
  20. Arian

    Arian No more ghostbusting!!

    Joined:
    May 10, 2008
    Messages:
    2,088
    Location:
    The Netherlands
    Ok, thanks for the info :)
     

Share This Page