Formulas

Damage Formula

VBFI’s damage formula can be found in data\gamesystem\datas\CalcUnit.tjs, line 102.

102
103
104
105
106
107
108
109
110
111
function attackerDamageCalc(atk,atkHP,def,defLnd){
	var sqrtTMP;
	var atkTMP;
	if(def < 1){def = 1;}
	if(defLnd < 1){defLnd = 0;}
	sqrtTMP = Math.sqrt(atkHP) / (def + 5 + Math.sqrt(defLnd));
	atkTMP  = (2 * atk + 5);
dm("A:"+"sqrtTMP="+sqrtTMP+"/atkTMP="+atkTMP+"/def="+def);
	return (int)(atkTMP * sqrtTMP);
}

The full formula is therefore: ( (2*Attack+5) * sqrt(AttackersHP)) / (defense + 5 + sqrt(Land)). Attack very quickly outpaces defense in this game. To survive, you must use skills to their fullest extent, such as Defense Only, or Hardy Physique.

Counterattack Formula

102
103
104
105
106
107
108
109
110
111
	function defenderDamageCalc(atk,atkHP,def,defLnd){
		var sqrtTMP;
		var atkTMP;
		if(def < 1){def = 1;}
		if(defLnd < 1){defLnd = 0;}
		sqrtTMP = Math.sqrt(atkHP) / (def + 5 + Math.sqrt(defLnd));
		atkTMP  = (2 * atk + 5);
dm("D:"+"sqrtTMP="+sqrtTMP+"/atkTMP="+atkTMP+"/def="+def);
		return (int)((atkTMP * sqrtTMP) / 3);
	}

Counterattacks are nearly identical to attacks, except counter-attacks only do 1/3rd damage.

End of Turn Formula

End of Turn, which is used for spells (like Fire Field or Dark Blast), as well as healing (such as Equitable Heal or Group Heal) is also found in data\gamesystem\datas\CalcUnit.tjs, line 124

124
125
126
	function turnEndSkillCalc(hp,value){
		return (int)((hp * (value / 100)) + value);
	}

The only two values that matter are HP of the unit, as well as the SkillValue. All skill values are added together. So if you have Group Heal 3 and Group Heal 7 and 500 HP, you’ll restore 60HP to all of your non-undead allies. 50HP from being 10% of your current HP (500), and then +10 from the +value in the formula.

Unit Formulas

26
27
28
29
	function ExpToLevel( exp_ )
	{
		return (int)( Math.sqrt( exp_/10 ))+1;
	}
48
49
50
51
52
53
54
55
56
	function HPcalc( baseHP_, Level_)
	{
		//HPは、基礎HP×{1+(LV-1)×0.25}で算出される。今回は、
		var HP=0;
		//HP = baseHP_ * (int)(1 + (Level_ - 1 ) * 0.25);
		HP= (int)(baseHP_*(1+((Level_-1)*0.25)));
		if(HP > 9999){HP = 9999;}
		return HP;
	}
58
59
60
61
62
63
64
65
66
67
68
69
	function StatusCalc(sta_,Exp_,par)
	{
		if(par=='mor'){
			sta_ = sta_ + (int)((sta_ * Math.sqrt(Exp_)/500) + (int)(Math.sqrt(Exp_)/40));
			if(sta_ >  99){sta_ =  99;}
		}else{
			sta_ = sta_ + (int)((sta_ * Math.sqrt(Exp_)/200) + (int)(Math.sqrt(Exp_)/25));
			if(sta_ > 999){sta_ = 999;}
		}
		if(sta_ < 1){sta_ = 1;}
		return sta_;
	}

Here we can see the growth of unit stats, specifically HP, Attack, Defense, Speed, and Morale.

HP Grows by 25% of the level1 HP. For example, a unit with 100 HP at level 1, will have 125HP at level 2, and then 150 HP at level 3.

We see that “Level = sqrt(experience/10)” + 1, and we see that Attack/Defense/Speed stats grow at sta_ = sta_ + (int)((sta_ * Math.sqrt(Exp_)/200) + (int)(Math.sqrt(Exp_)/25)), with a cap at 999. A unit that starts with 40 Attack at level 1 (Ex: Tyrca) will gain roughly .63 attack per level from the base stat, as well as +.12 attack from the Math.sqrt(Exp_)/25 portion of the formula.

Or to put it another way: unit stats grow approximately BaseStat/63.24 + .1265 per level.

Unit Cost Formula

1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
	function char_rank_cost(ch){
		//ch.rank,ch.cost
		//雇用時のコスト基礎値=等級値×補充コスト
		var rk= ch.rank+5;
		var co= (ch.cost+2)*(ch.cost+2);
		var lv= ch.level*5;
		return (int)( ((rk*co)/10)+lv );
		//return (int)((((ch.rank+5)*(ch.cost+2))*(ch.cost+2))/10)+(ch.level*5);
		//return (int)((((ch.rank+5)*(ch.cost+2))*(ch.cost+2))/10);
	}
1094
1095
1096
	function char_statick_cost(co_,ch_){
		return (int)(co_*((125-ch_)*0.01));
	}

This one is a bit more complicated. “Rank” for all units starts at 10, and by equipping various prefix or suffix titles, the rank increases. “Cost” is the value found in the unit tables, the value is quadratic, increasaing the cost by x2 causes the total price to grow by x4.

char_statick_cost adjusts the cost downward by “ch_", which happens to be loyalty. 100 loyalty means that the cost will only be 25% of the original, leading to significant (but difficult to calculate) savings. Be sure to max the loyalty stat by firing units and rehiring them after 100 Valor.

The total cost in food (or energy) to deploy a unit is (rank+5) * (cost+2) * (cost+2) / 10 + (level*5). Those 13-cost units are very, VERY expensive to deploy!

Unit Caps Formula

2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
	function add_exp_char(c_,n_){
		var ch= gf.get(c_,gf.char);
		ch.experience+= n_;
		switch(ch.growth){
			case "S": if(ch.experience>222010) ch.experience= 222010; break;
			case "A": if(ch.experience>193210) ch.experience= 193210; break;
			case "B": if(ch.experience>166410) ch.experience= 166410; break;
			case "C": if(ch.experience>141610) ch.experience= 141610; break;
			case "D": if(ch.experience>118810) ch.experience= 118810; break;
			case "E": if(ch.experience>98010) ch.experience= 98010; break;
			case "F": if(ch.experience>79210) ch.experience= 79210; break;
			case "G": if(ch.experience>62410) ch.experience= 62410; break;
		}
		if(ch.experience<0) ch.experience= 0;
		chardata_update2(ch);
	}

With sqrt(exp)/10 +1 converting exp to level, we get the following table:

Growth Class Level Cap
S 150
A 140
B 130
C 120
D 110
E 100
F 90
G 80

A unit’s final stats are proportional to their level (or the sqrt of their experience). A unit with mediocre initial stats can get a decent boost by reaching level 140, or 150, while units with very high initial stats are often Growth Class D or E, reducing their final potential over multiple playthroughs.

You cannot reach the level cap in one normal mode playthrough. So these level caps are for planning New Game+ teams over the course of many playthroughs.