浏览代码

vcmi: skill-agnostic tactics

Tactics is split to 2 bonuses, and it is now possible to
block tactics without having tactics itself. But tactics
for two sides is not implemented, because it is huge rework
and not high priority for me now, I want to do basic
secondary skill rework first.
Konstantin 2 年之前
父节点
当前提交
f264c541fb
共有 4 个文件被更改,包括 49 次插入16 次删除
  1. 1 1
      client/windows/CHeroWindow.cpp
  2. 11 5
      config/skills.json
  3. 2 0
      lib/HeroBonus.h
  4. 35 10
      lib/battle/BattleInfo.cpp

+ 1 - 1
client/windows/CHeroWindow.cpp

@@ -315,7 +315,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
 
 	dismissButton->block(!!curHero->visitedTown || noDismiss);
 
-	if(curHero->getSecSkillLevel(SecondarySkill::TACTICS) == 0)
+	if(curHero->valOfBonuses(Selector::type()(Bonus::BEFORE_BATTLE_REPOSITION)) == 0)
 	{
 		tacticsButton->block(true);
 	}

+ 11 - 5
config/skills.json

@@ -542,25 +542,31 @@
 		"base" : {
 			"effects" : {
 				"main" : {
-					"subtype" : "skill.tactics",
-					"type" : "SECONDARY_SKILL_PREMY",
+					"type" : "BEFORE_BATTLE_REPOSITION",
+					"valueType" : "BASE_NUMBER"
+				},
+				"block" : {
+					"type" : "BEFORE_BATTLE_REPOSITION_BLOCK",
 					"valueType" : "BASE_NUMBER"
 				}
 			}
 		},
 		"basic" : {
 			"effects" : {
-				"main" : { "val" : 2 }
+				"main" : { "val" : 2 },
+				"block" : { "val" : 2 }
 			}
 		},
 		"advanced" : {
 			"effects" : {
-				"main" : { "val" : 4 }
+				"main" : { "val" : 4 },
+				"block" : { "val" : 4 }
 			}
 		},
 		"expert" : {
 			"effects" : {
-				"main" : { "val" : 6 }
+				"main" : { "val" : 6 },
+				"block" : { "val" : 6 }
 			}
 		}
 	},

+ 2 - 0
lib/HeroBonus.h

@@ -338,6 +338,8 @@ public:
 	BONUS_NAME(LEARN_MEETING_SPELL_LIMIT) /*skill-agnostic scholar, subtype is -1 for all, TODO for others (> 0)*/\
 	BONUS_NAME(ROUGH_TERRAIN_DISCOUNT) /*skill-agnostic pathfinding*/\
 	BONUS_NAME(WANDERING_CREATURES_JOIN_BONUS) /*skill-agnostic diplomacy*/\
+	BONUS_NAME(BEFORE_BATTLE_REPOSITION) /*skill-agnostic tactics, bonus for allowing tactics*/\
+	BONUS_NAME(BEFORE_BATTLE_REPOSITION_BLOCK) /*skill-agnostic tactics, bonus for blocking opposite tactics. For now donble side tactics is TODO.*/\
 	/* end of list */
 
 

+ 35 - 10
lib/battle/BattleInfo.cpp

@@ -483,22 +483,47 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
 	//tactics
 	bool isTacticsAllowed = !creatureBank; //no tactics in creature banks
 
-	int tacticLvls[2] = {0};
-	for(int i = 0; i < ARRAY_COUNT(tacticLvls); i++)
+	constexpr int sideSize = 2;
+
+	std::array<int, sideSize> battleRepositionHex = {};
+	std::array<int, sideSize> battleRepositionHexBlock = {};
+	for(int i = 0; i < sideSize; i++)
 	{
 		if(heroes[i])
-			tacticLvls[i] += heroes[i]->valOfBonuses(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::TACTICS));
+		{
+			battleRepositionHex[i] += heroes[i]->valOfBonuses(Selector::type()(Bonus::BEFORE_BATTLE_REPOSITION));
+			battleRepositionHexBlock[i] += heroes[i]->valOfBonuses(Selector::type()(Bonus::BEFORE_BATTLE_REPOSITION_BLOCK));
+		}
 	}
-	int tacticsSkillDiff = tacticLvls[0] - tacticLvls[1];
+	int tacticsSkillDiffAttacker = battleRepositionHex[BattleSide::ATTACKER] - battleRepositionHexBlock[BattleSide::DEFENDER];
+	int tacticsSkillDiffDefender = battleRepositionHex[BattleSide::DEFENDER] - battleRepositionHexBlock[BattleSide::ATTACKER];
 
-	if(tacticsSkillDiff && isTacticsAllowed)
+	/* for current tactics, we need to choose one side, so, we will choose side when first - second > 0, and ignore sides
+	   when first - second <= 0. If there will be situations when both > 0, attacker will be chosen. Anyway, in OH3 this
+	   will not happen because tactics block opposite tactics on same value.
+	   TODO: For now, it is an error to use BEFORE_BATTLE_REPOSITION bonus without counterpart, but it can be changed if
+	   double tactics will be implemented.
+	*/
+
+	if(isTacticsAllowed)
 	{
-		curB->tacticsSide = tacticsSkillDiff < 0;
-		//bonus specifies distance you can move beyond base row; this allows 100% compatibility with HMM3 mechanics
-		curB->tacticDistance = 1 + std::abs(tacticsSkillDiff);
+		if(tacticsSkillDiffAttacker > 0 && tacticsSkillDiffDefender > 0)
+			logGlobal->warn("Double tactics is not implemented, only attacker will have tactics!");
+		if(tacticsSkillDiffAttacker > 0)
+		{
+			curB->tacticsSide = BattleSide::ATTACKER;
+			//bonus specifies distance you can move beyond base row; this allows 100% compatibility with HMM3 mechanics
+			curB->tacticDistance = 1 + tacticsSkillDiffAttacker;
+		}
+		else if(tacticsSkillDiffDefender > 0)
+		{
+			curB->tacticsSide = BattleSide::DEFENDER;
+			//bonus specifies distance you can move beyond base row; this allows 100% compatibility with HMM3 mechanics
+			curB->tacticDistance = 1 + tacticsSkillDiffDefender;
+		}
+		else
+			curB->tacticDistance = 0;
 	}
-	else
-		curB->tacticDistance = 0;
 
 	return curB;
 }