| null = null;
private adGateOff: (() => void) | null = null;
createRenderRoot() {
return this;
}
init() {}
tick() {
if (!this.game.inSpawnPhase()) {
if (!this.bottomRailDestroyed) {
this.bottomRailDestroyed = true;
this.destroyBottomRail();
}
if (!this.cornerAdShown) {
this.cornerAdShown = true;
console.log("[InGamePromo] Spawn phase ended, triggering showAd");
this.showAd();
}
}
}
private destroyBottomRail(): void {
if (!window.ramp) return;
try {
window.ramp.destroyUnits("pw-oop-bottom_rail");
console.log("Bottom rail ad destroyed after spawn phase");
} catch (e) {
console.error("Error destroying bottom_rail ad:", e);
}
}
private showAd(): void {
if (window.innerWidth < 1100) return;
if (window.innerHeight < 750) return;
if (!window.adsEnabled) return;
// Show the intrusive in-game ad only to users who have been blocker-free.
// Once a blocker is ever detected the gate latches suppressed forever
// (persisted across sessions), so whenClear never fires for those users.
this.adGateOff = adGatekeeper.whenClear(() => {
this.shouldShow = true;
this.requestUpdate();
this.updateComplete.then(() => {
this.loadAd();
this.checkForAds();
});
});
}
private checkForAds(): void {
if (this.adCheckInterval) {
clearInterval(this.adCheckInterval);
}
this.adCheckInterval = setInterval(() => {
const hasAds = AD_TYPES.some(({ selectorId }) => {
const el = document.getElementById(selectorId);
return el && el.clientHeight > 50;
});
if (hasAds) {
this.adsVisible = true;
this.requestUpdate();
if (this.adCheckInterval) {
clearInterval(this.adCheckInterval);
this.adCheckInterval = null;
}
}
}, 1000);
}
private loadAd(): void {
if (!window.ramp) {
console.warn("Playwire RAMP not available for in-game ad");
return;
}
try {
window.ramp.que.push(() => {
try {
window.ramp.spaAddAds(
AD_TYPES.map(({ type, selectorId }) => ({ type, selectorId })),
);
console.log(
"In-game bottom-left ads loaded:",
AD_TYPES.map((a) => a.type),
);
} catch (e) {
console.error("Failed to add in-game ads:", e);
}
});
} catch (error) {
console.error("Failed to load in-game ads:", error);
}
}
public hideAd(): void {
if (this.adGateOff) {
this.adGateOff();
this.adGateOff = null;
}
if (this.adCheckInterval) {
clearInterval(this.adCheckInterval);
this.adCheckInterval = null;
}
this.adsVisible = false;
this.destroyBottomRail();
if (!window.ramp) {
console.warn("Playwire RAMP not available for in-game ad");
return;
}
this.shouldShow = false;
try {
for (const { type } of AD_TYPES) {
window.ramp.destroyUnits(type);
}
console.log("successfully destroyed in-game bottom-left ads");
} catch (e) {
console.error("error destroying in-game ads:", e);
}
this.requestUpdate();
}
render() {
if (!this.shouldShow) {
return html``;
}
return html`
`;
}
}