以下地址是以1.0.0.26.(221715) (10/07/2016)版本为例。所有地址和偏移都是十六进制。

核心看GameCore_Base_FinalRelease.dll。在ida中一般以180001000作为起始地址,而实际运行时会改变所以动态跟踪要做地址映射。
例如某次跟踪得到GameCore_Base_FinalRelease.dll的base = 21170000

新版本支持方法:
1. PlayerAddress:导向玩家列表
  1. 搜索lGetTreasury或任意下面“玩家相关”一节列出的关键字
  2. 得到一个lua函数,进入后第一个函数进入几层就会得到这个常量
2. ConstTextAddress:导向单位、城市的名称
  1. 搜索lGetExperience,并找到同函数注册的另一个函数lGetName
  1. 得到一个lua函数,第2个函数会有"Unknown Unit"的字样
  1. 参考下面lGetName的反汇编结构找到我标注了“重要”的那一行
3. 通常还有若干偏移会改变,只好一一回归测试一下

lua技巧:
1. 函数名都是l开头,尤其是hks_pushnamedcclosure注册的函数
2. lGetXXX一般返回userdata,返回之前会有一个函数包含hksi_lua_setfield说明返回类型,hksi_lua_setfield的下面一句会注册成员函数
3. 成员函数一般先从lua_state调用一个函数用于解开userdata,其返回值必然用于实际地址
4. 以下针对的是Player、PlayerCities等类,注意游戏的lua对应的其实是CachePlayer、CachePlayerCities等,这些类
   也可以修改而且更加简单可惜是只读的(即游戏中数值修改后Cache*的值会跟着改变,反过来不行。没有找到同步的方
   法)。

C++技巧:
1. 这里有个入口 sub_18008AD00
    这里给每个类注册了构造和析构,只看构造。一般GetPlayer之后紧接着的函数是init,里面会注册成员变量并赋初值
    Unit
      sub_1801E9180
        sub_1801A29F0
          sub_1801D9830
    Formation
      sub_1801E9110
    City::Instance
      sub_180061820
    Trade::Edge
      sub_1801CFF90
    Control::Contract
      sub_1802D4010
    District::Instance
      sub_180061890
    AI::CityBuild
      sub_1802AF1D0
    BehaviorTree
      sub_1803D8280
    AI::Operation
      sub_18035E6E0
    DynamicModifier
      sub_18052F050
2. 找到成员声明后,代码可以和lua代码结合看,例如Unit与Unit对比时m_eTypeIndex与lua的lGetType结合看,
      memmove(??, "m_eTypeIndex", 0xC);
      ...
      *(_QWORD *)(v3 + 0xB0) = &off_180628F10;
      *(_DWORD *)(v3 + 0xD0) = 0;               在连续赋初值中,这个与lua一致,所以猜测其他变量也是如此
      *(_QWORD *)(v3 + 0xD8) = v3;              注意个别变量没有上面那句,但是这句会有,这时可以自己-8推出缺失的赋值
      *(_DWORD *)(v3 + 0xE0) = 0;

玩家相关
  CachePlayer刚才说改了没用,这里只是记录一下
    有若干list不确定什么意思
    1. ? = [180728970] + 37748 + 4 * index
    2. ? = [180728970] + 37618 + 4 * index
    3. cachePlayer = [180728970] + D88 * index + 8
    目前实测要用3
    类型CachePlayer,成员函数在这里注册 sub_180489E80
    此后cachePlayerTreasury = cachePlayer + 7D0
    返回类型CachePlayerTreasury参考 sub_180494A70 注册的
      lGetGoldBalance = DWORD[cachePlayerTreasury + 88]
      但是CachePlayerTreasury不像PlayerTreasury那样,这里没有SetGoldBalance。间接证明CachePlayerTreasury是没办法写修改器的。
  
  类型Player,成员函数在这里注册 sub_18029CFF0
    lGetCities            ok
    lGetUnits             ok
    lGetTechs             ok
    lGetTrade             ok
    lGetTreasury          ok
    lGetCulture           不太好下手,包含文化值的提供方、文化开销、是否解锁政府、是否解锁政策
    lGetDiplomacy         不太好下手,包含是否与他国有战争、是否遇见、是否可见
    lGetReligion          ok
    lGetResources         ok,要在交易页面看到结果或者等到下一回合
    lGetGreatPeoplePoints 没必要,可以买来
    lGetInfluence         ok
    lGetEras              ok
    
金币 64bits。乘以256的定点小数
  lGetTreasury
    playerTreasury = [[1807185D8] + 8 * index + 210] + 7D60
    返回类型PlayerTreasury参考 sub_1802A46B0 注册的lGetGoldBalance
      goldBalance = [playerTreasury + A0]

信仰 64bits。乘以256的定点小数
  lGetReligion
    playerReligion = [[1807185D8] + 8 * index + 210] + 6A88
  
  返回类型PlayerReligion参考 sub_1802A2D70 注册的lGetFaithBalance
    faithBalance = [playerReligion + A8]

影响力 64bits。乘以256的定点小数
  lGetInfluence
    playerInfluence = [[1807185D8] + 8 * index + 210] + 7520

  返回类型PlayerInfluence参考 sub_1802A11A0 注册的
    lGetPointsEarned = [playerInfluence + D0]
    lGetPointsPerTurn
    lGetTokensPerThreshold

矿产资源 32bits
  lGetResources
    playerResources = [[1807185D8] + 8 * index + 210] + 51C8
  返回类型PlayerResources参考 sub_1802A3360 注册的
    lHasResource
    lGetResourceAmount
    这两个函数其实是一样的,has就等于amount == 0
    其中resourceIndex参考GameInfo.Resources()的每个元素的.Index
      Base/Assets/Gameplay/Data/Improvments.xml
      获取index的函数是 sub_1800A7C20
        v2 = sub_180251A00();
          [[180717920] + 20] + 0xA68
        return sub_1800A6B30(v2, state)
            [v2 + 0]、[v2 + 8]是列表开始、结束位置,此后
            [列表项 + 0]、[列表项 + 8]分别是2个什么数字
            returnDWORD [v6 + 4]
        实测发现就是0、1、2、...、0x30,应该是字符串到index的映射。也就是v3 = index,由于有顺序所以我们不用管sub_1800A7C20这个函数
    获得index之后 sub_180185530
        DWORD[[[v4 + 198] + 18 * index] + 4 * 0];
  
伟人点数
  lGetGreatPeoplePoints
    playerGreatPeoplePoints = [[1807185D8] + 8 * index + 210] + 7290
  返回类型PlayerGreatPeoplePoints参考 sub_1802A0E00 注册的
    lGetPointsTotal
      没继续看

时代 32bits
  lGetEras
    playerEras = [[1807185D8] + 8 * index + 210] + 71D8
  返回类型PlayerEras参考 sub_1802A0A60 注册的
      GetEra = DWORD[playerEras + A0]

自然科学 byte
  lGetTechs
    playerTechs = [[1807185D8] + 8 * index + 210] + 66E8
  返回类型PlayerTechs参考 sub_1802A36C0 注册的
    CanResearch
    HasTech = BYTE[[playerTechs + 1E0] + index]
    lGetScienceYield * 256 = 以下各项目相加
      LOC_PLAYER_YIELD_SCIENCE_FROM_CITIES                ?                                             城市科研也是来自多个渠道,所以比较麻烦
      LOC_PLAYER_YIELD_SCIENCE_FROM_TOKENS                [playerTechs + 78] + 7520 => sub_180166840    没看下去
      LOC_PLAYER_YIELD_SCIENCE_FROM_TRIBUTARIES           [playerTechs + 78] + 7520  => sub_1801668B0   没看下去
      LOC_PLAYER_YIELD_SCIENCE_FROM_OTHER                 DWORD[playerTechs + 1A8]                      也就这个简单一点
      LOC_PLAYER_YIELD_SCIENCE_MODIFIER_FROM_TRIBUTARIES  [playerTechs + 78] + 7520 => sub_180166920    没看下去

社会科学 byte
  lGetCulture
    playerCulture = [[1807185D8] + 8 * index + 210] + 4338
  返回类型PlayerCulture参考 sub_18029F8E0 注册的
    lGetCultureCost
    lIsPolicyUnlocked
    lIsGovernmentUnlocked
    lHasCivic = BYTE[[playerCulture + 4D8] + index]
    lGetCultureYield * 256 = 以下各项目相加 sub_1801244E0
      LOC_PLAYER_YIELD_CULTURE_FROM_CITY
      LOC_PLAYER_YIELD_CULTURE_FROM_BELIEFS
      LOC_PLAYER_YIELD_CULTURE_FROM_TOKENS
      LOC_PLAYER_YIELD_CULTURE_FROM_TRIBUTARIES
      LOC_PLAYER_YIELD_CULTURE_FROM_OTHER                DWORD[playerCulture + 6E8] 最简单
      LOC_PLAYER_YIELD_CULTURE_MODIFIER_FROM_TRIBUTARIES
          
贸易 32bits
  lGetTrade
    playerTrade = [[1807185D8] + 8 * index + 210] + A28
  返回类型PlayerTrade参考 sub_1802A4430 注册的
    CountOutgoingRoutes
    GetOutgoingRouteCapacity = DWORD[playerTrade + 98]

城市列表
  lGetCities
   playerCities = [[1807185D8] + 8 * index + 210] + 1738
  返回类型PlayerCities参考 sub_18029E360 注册的
    lGetCount = DWORD[playerCities + A0]
    lMembersAux
      没有人用到
    lMembers返回迭代器,看不太懂
    lGetCapitalCity
      next = [playerCities + B8]
      while next
        city = *next
        if [city + 220]
          是首都
        next = BYTE[next + 10]
    每个member类型City参考 sub_1802701B0 注册的
      lGetName = C_STRING[city + 718]
      lGetPopulation = DWORD[city + 1E8]
      lGetCitizens
        cityCitizens = city + E48 + 20
        返回类型CityCitizens参考 sub_1802706F0 这是普通table没有注册函数
      lGetGrowth sub_180270770
        growth = city + 970 + 20
        返回类型CityGrowth参考 sub_180273240 注册的
        lGetTurnsUntilGrowth
        lGetFoodSurplus * 256 = sub_180057230 
          production_base = [growth]
          LOC_CITY_YIELD_FROM_TILES_SUMMARY_TOOLTIP
          LOC_CITY_YIELD_FROM_BUILDINGS_SUMMARY_TOOLTIP
          LOC_CITY_YIELD_FROM_POPULATION_TOOLTIP
          LOC_CITY_YIELD_FROM_DISTRICTS_SUMMARY_TOOLTIP
          LOC_CITY_YIELD_FROM_OUTGOING_TRADE_ROUTES_TOOLTIP
          LOC_CITY_YIELD_FROM_INCOMING_TRADE_ROUTES_TOOLTIP
          LOC_CITY_YIELD_FROM_PASSING_TRADE_ROUTES_TOOLTIP
          LOC_CITY_YIELD_FROM_GREATWORKS_TOOLTIP
          LOC_CITY_YIELD_FROM_GAMEEFFECTS_TOOLTIP             DWORD[production_base + 4 * v4 + 500] << 8 其中
                                                              v4 = 0时表示改造者产出食物
                                                              v4 = 1时表示改造者产出生产力
                                                              v4 = 2时表示改造者产出金币
                                                              v4 = 3时表示改造者产出科技
                                                              v4 = 4时表示改造者产出文化
                                                              v4 = 5时表示改造者产出信仰
          LOC_CITY_YIELD_FROM_PROJECT_TOOLTIP
          LOC_CITY_YIELD_FROM_UNIT_PRODUCTION_BONUS           DWORD[production_base + 3A8] << 8 好像没用
          LOC_CITY_YIELD_FROM_BUILDING_PRODUCTION_BONUS       DWORD[production_base + 3E0] << 8  
          LOC_CITY_YIELD_FROM_DISTRICT_PRODUCTION_BONUS       DWORD[production_base + 418] << 8 好像没用
          LOC_CITY_YIELD_FROM_MODIFIER_GAMEEFFECTS_TOOLTIP    DWORD[production_base + 4 * v13 + 450] << 8
                                                              v13定义与上面的GAMEEFFECTS一致,单位是百分数
          LOC_CITY_YIELD_FROM_RELIGIOUS_BUILDINGS_TOOLTIP
          LOC_CITY_YIELD_FROM_RELIGIOUS_FOLLOWERS_TOOLTIP
          LOC_CITY_YIELD_FROM_HAPPINESS_TOOLTIP
          LOC_CITY_YIELD_FROM_OCCUPATION_TOOLTIP
        lGetHousing = DWORD[growth + 30] + DWORD[growth + 34] + DWORD[growth + 38] + 一堆看不懂的东西
        lGetHousingFromWater
        lGetHousingFromBuildings
        lGetHousingFromImprovements
        lGetHousingFromDistricts
        lGetHousingFromCivics = DWORD[growth + 30]
        lGetAmenities = DWORD[growth + 3C] + DWORD[growth + 40] + DWORD[growth + 44] + DWORD[growth + 48] + DWORD[growth + 4C] + DWORD[growth + 50] + 一堆看不懂的东西
          但其中[+ 4C]的部分每回合会重算所以不能改
        lGetAmenitiesFromLuxuries
        lGetAmenitiesFromEntertainment
        lGetAmenitiesFromCivics
        lGetHappiness
      lGetBuildings
        cityBuildings = city + F50 + 20
        返回类型CityBuildings参考 sub_180270CB0 注册的
        lHasBuilding
        lSetBuildingLocation
        lGetBuildingLocation
        lRemoveBuilding
        lIsPillaged
        lSetPillaged
        还没想到要改什么
      lGetDistricts
        cityDistricts = city + CA8 + 20
        返回类型CityDistricts参考 sub_180272B00 注册的
          lGetNumDistricts
          lGetNumDistrictsOfType
          lHasDistrict
          lGetDistrict
          lGetDistrictByIndex
            返回类型District参考 sub_180279A70 注册的
            ...
          lGetDistrictAtLocation
        还没想到要改什么
      lGetReligion
        cirtReligion = city + AF0 + 20
        返回类型CityReligion参考 sub_180274090 注册的
          lGetMajorityReligion
          lGetActivePantheon
          lGetNumFollowers
        还没想到要改什么

  还要参考C++类 City::Instance sub_180052DE0
    m_aFollowerYieldModifiers  +4A8 +4B0 +4B8
    m_kGold +888
    m_kGrowth +990
    m_kCombat +AC0 +AC8 +AB8
    好像也不比lua信息更多了,这与Unit不一样
    
单位列表
  lGetUnits
    playerUnits = [[1807185D8] + 8 * index + 210] + 10A0
  返回类型PlayerUnits参考 sub_1802A4E40 注册的
    lGetCount = DWORD[playerCities + A0]
    lMembers
      从构造看跟playerCities是一样的,所以遍历方法也一样
    lFindID
  如果是类型Unit,参考 sub_1802A7CC0 注册的
    lGetX
    lGetY
    lGetType
      DWORD[unit + D0]
    lGetName  sub_1801E0A10
      if DWORD[unit + F38] != -1 && DWORD[unit + F3C] != -1 {
        // 伟人的名字
        names = [[[180717920] + 20] + 720]
        names_head = [names]
        names_tail = [names + 8]
        name_id = DWORD[unit + F38]
        name_1 = [names_head + 10 * name_id + 8]
        name_2 = [names_head + 10 * name_id + 0]
        return C_STRING[name_? + 40]
      }
      result = C_STRING[unit + E90] // 似乎是用户自定义名称
      if result.empty {
        names = [[[180717920] + 20] + DE0] // 重要:名字集合
        result = C_STRING[[names + 8 * 2 * [unit + D0]] + 88] // 重要:单位类型以及在名字集合中的位置
      }
    lGetDamage = DWORD[unit + 528]
    lGetMaxDamage
    lGetExperience
      experience = unit + E58 + 20
      返回类型Unit::Experience参考 sub_1802A8670 注册的
        lGetExperiencePoints = DWORD[experience + C]
        lHasPromotion = BYTE[[experience + 28] + index]
    lGetFortifyTurns
    lGetUpgradeCost
    lGetReligion
      unitReligion = unit + F68 + 20
      返回类型Unit::Religion参考 sub_1802A8EE0 注册的
        lGetReligiousStrength = DWORD[unitReligion + 8]
        lGetReligionType = DWORD[unitReligion + C]
        lGetSpreadCharges = DWORD[unitReligion + 10]
        lGetNWDeferredCharges = DWORD[unitReligion + 14]
        lGetInitiationYield = DWORD[unitReligion + 18]
        lGetInitiationAmount = DWORD[unitReligion + 1C]
        lGetEvictPercent = DWORD[unitReligion + 20]
        lGetForeignSpreadModifier = DWORD[unitReligion + 24]
        lIsConvertsBarbarians = BYTE[unitReligion + 28] == 0
        lIsNoForeignSpread = BYTE[unitReligion + 29] == 0
        lIsRelicUponDeath = BYTE[unitReligion + 2A] == 0

  还要参考C++类 Unit sub_1801D9830
    已验证m_eTypeIndex、m_iDamage的地址C++类和lua地址一致。下面是其他:
    m_aiBonusPointsPerKill    +430
    m_iFortifyTurns           +560
    m_xMovesRemaining         移动力*256 = [unit + 608]
    m_iAttacksRemaining       +640  攻击次数?
    m_iBuildCharges           +6B0  剩余劳动力
    m_iAirSlotsModifier       +6E8
    m_bDominantConquer        +720
    m_iUpgradeDiscount        +790
    m_iBarbarianTribeIndex    +7C8
    m_bAttackAfterMoving      +800
    m_bMoveAfterAttacking     +838
    m_bEmbarked               +870
    m_bDelayedDeath           +8A8
    m_bIgnoreTerrainCost      +8E0
    m_bIgnoreZOC              +918
    m_bExertZOC               +950
    m_bCanSeeThroughFeatures  +988
    m_bImmobile               +9C0
    m_bProcessedTurn          +9F8
    m_kSightModifiers         +C58  视距
    m_kAttackRangeModifiers   +C90
    看样子k、i都是uint32,x是uint32/256,b是byte/bool