Alliance Duel (VS)
Weekly alliance-vs-alliance ("VS"), one theme per server day; the server day starts 02:00 UTC.
Entry wiring
Duel = activity 55000 (type 14, EnumActivity.AllianceCompete) in the init push activity map live. Entry fields: id: 55000, activityid: "70000" (heroactivity row — the id the detail read must send), name: "370026" (locale key), startTime/endTime/readyTime/matchGroupId, uuid (32 hex = today's eventList actId). The only live entry whose activityid differs from id [live 2026-10-06].
- Detail read:
hero.event.info.get {activityId: "70000"}— sending"55000"returns bare{success=true}, noeventList.ActivityEventInfoGetMessageonly processes replies lacking thesuccesskey (ActivityEventInfoGetMessage.lua:26). Override logic inActivityInfoData:ParseActivityData(ActivityInfoData.lua:126-128, 160-161); sent as UtfString (ActivityListDataManager.lua:158-163). - Reply live:
activityId,type == 15(routing,ActivityListDataManager.lua:1180-1186),ranking,isFix,eventList. - Per-entry:
st/et(unix ms — live has nobegintime/endtime; client reads that pair first perActivityEventInfo.lua:69-74, thenst/etperActivityListDataManager.lua:1193-1198),rt,t(15),eventId(heroeventrows 110000-110005),actId/actName/actDesc,score(|-joinedscoretable ids),target(|-joined chest thresholds — live:40000|150000|540000|660000|1000000|2300000|2600000|3600000|7200000),value,reward,reward_science,userScore {score, rewardFlagList, newRewardFlagList, finishFlag, canRwdFlag, level, actId, hardMode, refreshTime, sendReward, uid},vsAllianceInfo[] {allianceId, alName, abbr, icon, power, serverId, win, winScore, alScore, scoreHistory[{score, day}], mvpPlayer{uid, name, pic, picVer, monthCardEndTime}},fightStartTime,fightEndTime,weekEndTime,minDayScore,minWeekScore,winReward,winWeekReward,isCrossFight,crossFight,canAttackCity,nextId,nextName(empty live). - Pick the entry
t == 15containing now; never fall back — a stale scoring list is another day's.
Week map (TB:heroactivity#70000) static
| Day | eventId | Theme |
|---|---|---|
| Mon | 110000 | Radar Training |
| Tue | 110001 | Base Expansion |
| Wed | 110002 | Age of Science |
| Thu | 110003 | Train Heroes |
| Fri | 110004 | Total Mobilization |
| Sat | 110005 | Enemy Buster |
| Sun | — | rest day |
Confirmed live Tue 2026-10-06: theme 110001, window ends 02:00 UTC.
Score model
score table rows {id, type, value, points}; type = ScoreType (EnumType.lua:15728-15744). Predicted award = units × points × (1 + Σ effects) (GetAllyDuelScoreInfo.lua:39-43).
Types in use: 4 train unit (value = tier), 20 shop, 23 building power, 42 recruit hero, 51 speed-up minute (value = queue: 4 training, 6 research, 7 construction, 9 healing — keyed by queue, not item), 82 radar task, 98 UR trade truck (value 5), 99 UR secret task, 119 use item (itemId|count), 120 recruit survivor.
Live 2026-10-06 scoring list: 90201 (51/7, 50 pts), 90202 (23, 10), 90203 (98/5, 100,000), 90204 (99/5, 75,000), 90000 (20, 30), 100910 (120, 1,500), 110301 (119/801000|1, 1), 110302 (119/801001|1, 2,500).
- Score push static:
push.act.score.obtain(Arms Race always; duel whentype == 15,PushActScoreObtainMessage.lua:6-16) →GetDuelScoreManager:PushScoreChangeByType. - Chest claim static:
accept.personal.reward {actId: UtfString, stage: Int (target value), eventType: 15}; claimable whenuserScore.score≥ target and flag not innewRewardFlagList(comma-joined claimed indexes, e.g.1,2,3live); index within tech-unlocked chest count (3/6/9/12).
Speed-up items-only forms (UISpeedView.lua:1540-1586)
build.ccd.m.new {bUUID: Long, isFixRuins: false, itemIDs: "tmpl;n|tmpl;n"}queue.ccd.m.new {qUUID: Long, itemIDs: "tmpl;n|..."}building.camp.accel {uuid: Long, itemId: "tmpl;n|..."}
Diamond form = useGold key (+ empty itemIDs for queue instant finish); isGold never put on the wire (QueueCcdMNewMessage.lua:3-17); golloesSpeedTime = separate free-time pool.
Speed-up goods (goods static, type2 = menu, para3 = seconds): 200200-200207 universal (type2 1), 200210-200217 construction (7), 200220-200227 research (6) — each 60/300/900/3,600/10,800/28,800/86,400/432,000; 200230-200235 training (3), 200240-200245 healing (4) — first six.
Radar tasks (march-free types {6, 18, 26, 44} + talks 14)
Gates: radar_quick_operation_switch in init dataConfig; playerServerSeasonInfo.seasonId ≥ 2 (lw_function_season row 106); radar level ≥ 6 (detect_config.k100, from get.detect.info reply level).
detect.event.batch.put.point.in.world {uuidList: "uuid|uuid"}(state 3→0)- types 6/26:
start.pick.garbage {uuid}… ≥3 s …finish.sampling {uuid}(44 addsfinish.visitor) - 18:
detect.event.help.start/end {uuid, eventType: 18}(10 stamina unlesscost == 1) - 14:
start.detect.event.talk {uuid}…end.detect.event.talk {uuid}(claims at once) - the real client never sends
reset.detect.event(diamond re-roll) - Task-bank model: refresh adds N tasks, loses
eventNum + N − max(show − slots, 0) − maxNumwhen full (detect_level,UIDetectEventCtrl.lua:371-394)