【补丁使用】
该补丁分为两部分。
请先将第一部分补丁放在Sango2.exe同一目录下，并运行第一部分补丁。
然后，将Script文件夹内的文件复制到群2游戏根目录下。有重复则覆盖。
修改有风险，请注意备份。


【说明】
BUG描述：如果同一年同一君主下有N个人成年，则只会显示其中一人成年的信息，并且重复N次。

很容易猜到该问题的成因是，在调用脚本的相应函数时，反复多次设置了INTV_ATTACKER_GENERAL / INTV_DEFENDER_GENERAL / INTV_ATTACKER_KING_GENERAL，而由于脚本执行的特点，在这些属性被复写之前，脚本并未执行。
先确定目标脚本函数：System.so的SearchTalk，callsign为5. 成年事件是该函数的一个分支，当唯一参数==20时，为成年事件。此时，intvAttackerGeneral是父亲，intvAttackerKingGeneral是子女，intvDefenderGeneral是君主。
然后确定调用者：SearchGeneralByBlood (423476). 符合猜想，确实是先设置了对应的位置，然后贸然立即调用DoScript_1. 

不过，之前改了之后，接到报告称模拟器运行时，原有修改方法可能会出错。一种可能是内存操作导致的问题，另一种可能是，模拟器运行时，原有的防止多线程冲突的判断法并不能真的保证多线程之间不会冲突。
总而言之，看来得重新改了。

解决方案二：

如果要规避内存操作的话，唯一的办法是手工指定INTV偏移。
查找上游函数，循环发生在SearchBloodGeneral_0 (423681) 函数中。这里的问题是，后面的两层函数调用里虽然只有一堆if，但是任何一个if都可能导致不会成年，因而最外层函数不知道进去的时候到底是第几个成年。因此一个自然的想法是使用全局变量（ONCE AGAIN...）。这里倒是可以用某个固定的INTV，反正这个时候应该不会有别人瞎改。不过，这里又是脚本剧情的高发地，只能但愿竹外大神之类不会借这些INTV玩什么骚操作了。
那么做法也就变得很明显了。

全局成年数counter：intvMagicAttackValue (INTV04) 0x4A6888
固定君主武将：intvAttackerKingGeneral (INTV09) 0x4A689C
Right-Left combinations: 从INTV30开始。预留的空间中有64个INTV，应该足够了。

修改之处：
1) SearchBloodGeneral_0 (423681) 需要在循环之前挤出一个赋值（初始化全局成年数counter）。
看起来很挤。不过，似乎浪费了一个寄存器赋值；并且之后neg sbb 再neg的操作，是为了进行!=0的判断，但实际上没什么意义，后面只用来判断。所以这些都可以省去。当然，后面的判断得改了。

2) SearchGeneralByBlood (423476) 需要读取这个赋值，设置相应的INTV，然后调用新增的脚本（仍然使用callsign 10）。
这部分改起来很舒服，不用腾空间，直接改对INTV赋值的部分即可。因为原来是通过调用函数来赋值的，改成直接赋值，至少push和add esp都可以省去；加上强行重新取一遍pKing，空间其实富裕得很。我保留了重新取pKing的逻辑，也才刚刚好够空间，如果这部分省去的话就会出来一堆nop了。

3) 新增相应的脚本。


【UE修改内容（第一部分）】
从: 
229A1: 8B 55 FC 52 E8 38 C3 FF FF 83 C4 04 8B 45 FC 8B 88 CB 00 00 00 8B 51 0C 52 E8 16 C3 FF FF 83 C4 04 8B 45 08 50 E8 FD C2 FF FF 83 C4 04 6A 14
229D1: 05
22A8F: 8B 45 F4 25 00 00 01 00 F7 D8 1B C0 F7 D8 89 45 F8
22B1B: 01 75

改为: 
229A1: B9 88 68 4A 00 8B 01 50 40 89 01 01 C0 8D 14 85 E8 68 4A 00 8B 4D 08 89 0A 8B 45 FC 89 42 04 8B 88 CB 00 00 00 8B 51 0C 89 15 9C 68 4A 00 90
229D1: 0A
22A8F: 25 00 00 01 00 89 45 F8 31 C0 A3 88 68 4A 00 90 90
22B1B: 00 74

【第二部分】
System.so新增代码如下（以下内容使用“三国2脚本伪代码编译器”v0.9.4编译，将其添加到System.cpp中编译即可）：

// Main execution function
// Index indicates which children is mature. Index starts from 0. 
void function ChildGenTalkNew (int index) callsign 10 {

	// follow the original "mutual exclusion" code. 
	// In theory it shouldn't work at all. Do it anyway.
	do {
		Delay(1);
	} while(GetGlobal(1) != 0);
	SetGlobal(1, 1);

	// use INTVs after 30 to get general pointers.
	General* pChild = (General *) GetIntv(30 + index * 2);
	General* pParent = (General *) GetIntv(30 + index * 2 + 1);	
	General* pKingGeneral = (General *) intvAttackerKingGeneral;

	SetSXString(0, 3, GetGeneralName(pChild));	// %S3%
	SetSXString(0, 1, GetGeneralName(pParent));	// %S1%

	// King's child
	if (pParent == pKingGeneral) {
		PromptWithMessageIndex1(0, pParent, 816);	
		PromptWithMessageIndex1(1, pChild, Rand(870, 874));
		PlaySound1("SUCCESS", 255);

		PromptWithMessageIndex1(0, pKingGeneral, Rand(875, 878));
		PromptWithMessageIndex1(1, pChild, Rand(890, 893));
		Prompt1(0, pKingGeneral, "%e");

	// Suggested by parent
	} else {
		PromptWithMessageIndex1(0, pParent, 817);
		PromptWithMessageIndex1(1, pChild, 818);
		PlaySound1("SUCCESS", 255);

		PromptWithMessageIndex1(0, pKingGeneral, Rand(894, 899));
		PromptWithMessageIndex1(1, pChild, Rand(900, 903));
		PromptWithMessageIndex1(0, pKingGeneral, 812);
		PromptWithMessageIndex1(0, pParent, Rand(904, 907));
	}

	Delay(1);
	SetGlobal(1, 0);
}
