Everything the build does with ads: which formats run, every placement and what triggers it, the interstitial cooldown rules, how ads get removed, and the full AppLovin MAX mediation stack with its networks. Ad service is SibirGames.Ads.AdManager; config is AdManagerConfig. Values read from the store build v1.18.8.
Interstitials are throttled by three cooldowns in AdManagerConfig. All three are baked at 45 seconds in this build (extracted/by_class/AdManagerConfig.json). An interstitial can only show when the active cooldown has elapsed (CanShowInterstitial / IsInterstitialCooldownFinished; TimeUntilNextInterstitial exposes the remaining time).
| Cooldown | Config key | Value | What it gates |
|---|---|---|---|
| Before first | IntAdCDBeforeFirst | 45s | Grace period from session start before the first interstitial can show. |
| After interstitial | IntAdCDAfterIntAd | 45s | Wait after showing an interstitial before the next one is allowed. |
| After rewarded | IntAdCDAfterRewAd | 45s | Wait after a rewarded video before an interstitial is allowed — watching a rewarded ad also pushes back the next interstitial. |
OnlineConfigBase fields, so a server sheet could override them — but the live build loaded 0 config sheets, so the baked 45/45/45 was in effect.Rewarded ads are always opt-in: the player taps a button to watch and gets a reward. Each placement below is a class in the build that injects the ad service and shows a rewarded video. Rewarded ads are never disabled — not by the ad-free pack, not for payers.
| Placement | Trigger | What it does | Conf. |
|---|---|---|---|
Multiply level rewardBattleResultWindow | Tap the ad button on the win / result screen | Watch a rewarded video to multiply the level-clear loot by a configured factor. The button only shows when an ad is loaded. GAP placement string level_complete is inferred | FACT |
Reroll skill choiceSkillUpgradeWindow | Tap the ad-reroll button during the in-run skill pick | Reroll the three offered skill upgrades for free by watching an ad, instead of paying currency. One ad-reroll is tracked per offer. | FACT |
Revive heroReviveWindow | Tap the ad button on the death / revive popup | Watch an ad to revive after dying and continue the run, instead of paying currency. There is a free first revive from level 2. | FACT |
Speed up idle incomeSpeedUpIncomeWindow | Tap the ad button on the idle-income collect popup | Fast-forward / boost the accumulated AFK income by watching an ad. Daily-limited (the popup shows the ads-left count). GAP daily cap value not extracted | FACT |
Double AFK rewardsAFKRewardsManager | Collect offline rewards via the ad option | Claim the ad-doubled variant of the offline / away rewards. Capped per day (MaxAdCount). GAP cap value not extracted | FACT |
Get energy with an adMetaEnergyIncreaseManager | Tap the ad option when energy is low | Refill energy by watching an ad rather than spending currency. One of four energy sources (Ad / Currency / Daily / none); daily-capped. GAP cap value not extracted | FACT |
Time acceleratorTimeAcceleratorManager | Watch an ad to activate a speed-up buff | Watch a rewarded video to switch on a time-acceleration buff on a timed system (e.g. adventure / production). | FACT |
Pay-with-an-ad (generic)AdCost / AdCostProcessor | Any shop / vendor action priced as an AdCost | A reusable cost type: some shop or vendor items use 'one rewarded ad' as the price instead of currency or real money. GAP which specific SKUs use AdCost not enumerated | FACT |
Hunt Passhunt_pass placement | Hunt-pass (battle-pass) reward / claim flow | The hunt_pass placement constant exists and the hunt-pass manager is wired to ads; the exact button is not pinned in the dump. GAP specific trigger not byte-proven | INFER |
Dungeon / Tower eventsDungeonEvent / TowerEvent | Inside the limited-time event modes | Both event managers inject the ad service — plausibly an ad-for-reward or ad-to-continue inside the event. Not byte-confirmed. GAP specific trigger not byte-proven | INFER |
Watch-ads questWatchAdsQuest | Passive — counts every rewarded ad watched | Not its own placement: a quantity quest that listens to 'rewarded ad shown' and ticks up. Rewards the player for watching N ads. | FACT |
These are the forced full-screen ads (no reward). The IL2CPP dump has empty method bodies, so the classes that wire up the ad service are provable but the exact placement string at each call site is inferred from the five declared placement constants (level_complete, main_window, initialization, increase_energy_over_time, hunt_pass). All are subject to the 45s cooldown.
| Placement | Trigger | What it does | Conf. |
|---|---|---|---|
Level endFinishLevelState | Automatic when a level finishes | The natural forced interstitial slot — runs on level completion, subject to the cooldown gate below. GAP call site inferred (placement level_complete); empty method bodies hide the literal | INFER |
Return to main menuLevelsManager | Returning to the main window between runs | The main_window placement constant exists and this manager injects the ad service; a between-runs interstitial is the likely trigger. GAP call site inferred | INFER |
App initializationinitialization placement | On boot / first load | An initialization placement + first_initialize reason exist, pointing to a launch-time interstitial. GAP call site inferred | INFER |
Banners are off in this build. Both platform flags are false (isEnabledBannerAndroid = false, isEnabledBannerIOS = false) and the AppLovin banner ad-unit IDs are empty on both platforms. The banner plumbing exists (SetBannerEnabled, IsBannerEnabled, persisted state) but nothing turns it on. No MRec, no app-open ad either. So the only formats a player actually sees are rewarded video and interstitial.
DisableAdsConfig.DisableAdsIfPayer = false — spending money does not remove ads on its own.DisableAdsManager only toggles interstitials. Rewarded ads stay available because they are player-initiated and pay out a reward.AdFreePermanentPatch is a one-time, permanent (ActiveTime = -1) interstitial-off grant, delivered by the IAP product ad_free_patch (product group "noads", store SKU gift_pack05). After buying it, interstitials are off forever; rewarded ads remain.gift_pack05). Needs a billing capture to read the price.Before showing an ad, the game can persist a small record — ad type, placement, and whether the device was online (AdManager.SaveLeaveAdData → PersistentData.LeaveAdData). If the player force-quits or the app dies mid-ad, the record survives and is flushed to analytics on the next launch (ReportLeaveAdData → ClearLeaveAdData). It is an abandoned-impression / reward-fraud tracker. In this build it is off: IsSendLeaveAdAnalytics = false, so nothing is reported.
The mediation layer is AppLovin MAX, confirmed three ways: live traffic to ms4.applovin.com/1.0/mediate and prod-mediate-events.applovin.com, ten bundled MAX adapters, and the SDK settings file in resources. The native client classes (MaxSdkAndroid, MaxSdkCallbacks) handle Interstitial, Rewarded, Banner, MRec and AppOpen — but only Rewarded and Interstitial are configured.
| Format | Android unit | iOS unit | Status |
|---|---|---|---|
| Rewarded video | ff8a34f9b562056a | 1188d3d995c262b1 | Active |
| Interstitial | 9c25c806be3de897 | e93a1fdd0b7e8f63 | Active |
| Banner | (empty) | (empty) | Disabled |
| MRec | — | — | Not configured |
| App-open | — | — | Not configured |
AppLovin SDK key (res/raw/applovin_settings.json): 6AQkyPv9b4u7yTtMH9PT40gXg00uJOTsmBOf7hDxa_-FnNZvt_qTLnJAiKeb5-2_T8GsI_dGQKKKrtwZTlCzAR
Ten networks are bundled as MAX adapters. Nine of ten were contacted live in the captured session; only ironSource stayed silent. Google/AdMob was reached as a bidder despite having no MAX adapter. Heaviest real demand came from Unity Ads and Moloco.
| Network | Bundled | Live in capture | Evidence / IDs |
|---|---|---|---|
| Unity Ads | Yes | Yes — heaviest | gateway.unityads.unity3d.com; SDK v8.8.0 |
| Moloco | Yes | Yes — heavy bidding | sdkapi.dsp-api.moloco.com, prod-e.axon.ai (32 bid calls) |
| Vungle (Liftoff) | Yes | Yes | bidding placements INT_BIDDING-8904821 / REW_BIDDING-7609656, is_hb:true |
| Mintegral | Yes | Yes | configure.rayjump.com; publisher_id 18803; SDK MAL_16.8.51 |
| InMobi | Yes | Yes | config.inmobi.com; SDK 9.0.1; GDPR transmit on |
| BidMachine | Yes | Yes | api.bidmachine.io; named in mediate flow |
| Fyber / DT FairBid | Yes | Yes | InnerActive app 203012 / pub 210342; int spot 2521652, rew spot 2302703 |
| YSO Network / Sonic | Yes | Yes | cfg.sonicsads.com, maxesads.com, onegg.site |
| BigoAds | Yes | CDN only | creative CDN gdl.news-cdn.site; likely served via the YSO adapter |
| ironSource | Yes | No traffic | bundled adapter but silent in the captured session |
| AdMob / Google | No adapter | Yes (bidder) | googleads.g.doubleclick.net; app id ca-app-pub-7663884898922975~1306944555 |
The build uses the AppLovin Unified CMP consent flow (res/raw/applovin_consent_flow_unified_cmp.json): it checks the GDPR region first (is_al_gdpr); in a GDPR region it loads and shows a TCF CMP, otherwise it falls back to an optional terms / privacy-policy alert. At runtime the CMP is Google UMP / Funding Choices, with region logic supplied by Azur Games (integrations.cdn.azurgames.com/cmpregions). Networks honour consent downstream (InMobi GDPR transmit on, etc.).
AdManagerConfig.json. Payers not auto ad-free (DisableAdsIfPayer=false); ad-free pack = one-time permanent interstitial-off via IAP gift_pack05 / group noads; rewarded never disabled. Leave-ad analytics off (IsSendLeaveAdAnalytics=false). Mediator = AppLovin MAX; ad units ff8a34f9b562056a (rew/Android), 9c25c806be3de897 (int/Android), iOS 1188d3d995c262b1 / e93a1fdd0b7e8f63; SDK key in applovin_settings.json. 10 bundled networks, 9 contacted live (ironSource silent), AdMob bid in without an adapter. Consent via AppLovin Unified CMP + Google UMP, region logic from Azur Games. Rewarded placements (BattleResultWindow, SkillUpgradeWindow, ReviveWindow, SpeedUpIncomeWindow, AFKRewardsManager, MetaEnergyIncreaseManager, TimeAcceleratorManager, AdCost, WatchAdsQuest) are byte-confirmed via injected ad-service + ad-button fields.
INFER: exact placement string per interstitial call site (level-end, return-to-menu, init) — the classes are wired to ads but empty method bodies hide the literal; HuntPass and Dungeon/Tower event ad triggers are wired but the specific button is not pinned; cooldown unit = seconds.
GAPS: (1) daily caps and reward multipliers (SpeedUpIncome, energy, AFK, level-reward ×) are config-driven but the numbers were not extracted; (2) real-money price of the ad-free pack (runtime Google Play); (3) which shop SKUs use the AdCost "pay with an ad" cost; (4) MAX SDK version (adapter tokens date the build to early 2025); (5) full ordered waterfall + floor prices (the mediate response body was not decoded). Items 1, 3 close with a Frida hook on AdManager.ShowRewarded/ShowInterstitial + the cost manager over a controlled session.