Boss updates

This commit is contained in:
syahirAmali 2024-11-01 05:37:36 +08:00
parent 3aa429fdd7
commit 76fc15faab
4 changed files with 1173 additions and 668 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +1,50 @@
type Player @entity { type Player @entity {
id: ID! # player address id: ID! # player address
createdAt: BigInt! createdAt: BigInt!
lastRaidedAt: BigInt! lastRaidedAt: BigInt!
totalMinted: BigInt! totalMinted: BigInt!
currentBalance: BigInt! currentBalance: BigInt!
numberOfRaids: Int! numberOfRaids: Int!
army: Army! @derivedFrom(field: "player") army: Army! @derivedFrom(field: "player")
armyStrength: BigInt! # Calculated field for total army power armyStrength: BigInt! # Calculated field for total army power
rank: Int # Position in leaderboard, can be updated periodically rank: Int # Position in leaderboard, can be updated periodically
prestigeLevel: BigInt!
totalRuns: Int! # Track number of times player has started a new run
bossesDefeated: Int!
totalRewards: BigInt! # Track total DAO tokens earned from boss battles
isActiveSession: Boolean! # Track if player has an active session
} }
type Army @entity { type Army @entity {
id: ID! # player address id: ID! # player address
player: Player! player: Player!
molochDenierLevel: Int! molochDenierLevel: Int!
apprenticeLevel: Int! apprenticeLevel: Int!
anointedLevel: Int! anointedLevel: Int!
championLevel: Int! championLevel: Int!
profitPerSecond: BigInt! profitPerSecond: BigInt!
projectedDailyEarnings: BigInt! # Derived from profitPerSecond projectedDailyEarnings: BigInt! # Derived from profitPerSecond
totalUnitsPurchased: Int! totalUnitsPurchased: Int!
lastUnitPurchaseTime: BigInt lastUnitPurchaseTime: BigInt
currentBossLevel: Int! # Track current boss level
} }
type GlobalStat @entity { type GlobalStat @entity {
id: ID! # Can be "1" as we only need one instance id: ID! # Can be "1" as we only need one instance
totalPlayers: Int! totalPlayers: Int!
totalGeldMinted: BigInt! totalGeldMinted: BigInt!
totalArmyUnits: Int! totalArmyUnits: Int!
lastUpdateTime: BigInt! lastUpdateTime: BigInt!
topEarnerProfit: BigInt! # Track highest profit per second topEarnerProfit: BigInt! # Track highest profit per second
} totalPrestigeLevels: Int! # Sum of all player prestige levels
totalBossesDefeated: Int!
totalRuns: Int! # Track total number of runs across all players
}
type BossDefeat @entity {
id: ID! # player address + timestamp
player: Player!
bossLevel: Int!
earnings: BigInt!
timestamp: BigInt!
}

View File

@ -1,164 +1,258 @@
import { import {
PlayerRegistered, PlayerRegistered,
RaidPerformed, RaidPerformed,
UnitAdded UnitAdded,
} from "../generated/RaidGeld/RaidGeld" PlayerStrikesAgain,
import { Player, Army, GlobalStat } from "../generated/schema" BossDefeated,
import { BigInt } from "@graphprotocol/graph-ts" PrestigeGained,
} from "../generated/RaidGeld/RaidGeld";
import { Player, Army, GlobalStat, BossDefeat } from "../generated/schema";
import { BigInt } from "@graphprotocol/graph-ts";
// Constants from RaidGeldUtils // Constants from RaidGeldUtils
const PRECISION = BigInt.fromI32(10000) const PRECISION = BigInt.fromI32(10000);
const PRICE_FACTOR = BigInt.fromI32(11500) const PRICE_FACTOR = BigInt.fromI32(11500);
// Unit profits // Unit profits
const MOLOCH_DENIER_PROFIT = BigInt.fromI32(2533) const MOLOCH_DENIER_PROFIT = BigInt.fromI32(2533);
const APPRENTICE_PROFIT = BigInt.fromI32(27863) const APPRENTICE_PROFIT = BigInt.fromI32(27863);
const ANOINTED_PROFIT = BigInt.fromI32(306493) const ANOINTED_PROFIT = BigInt.fromI32(306493);
const CHAMPION_PROFIT = BigInt.fromI32(3371423) const CHAMPION_PROFIT = BigInt.fromI32(3371423);
// Base costs (not used in profit calculation but useful for reference) // Base costs (not used in profit calculation but useful for reference)
const MOLOCH_DENIER_BASE_COST = BigInt.fromI32(380000) const MOLOCH_DENIER_BASE_COST = BigInt.fromI32(380000);
const APPRENTICE_BASE_COST = BigInt.fromI32(3420000) const APPRENTICE_BASE_COST = BigInt.fromI32(3420000);
const ANOINTED_BASE_COST = BigInt.fromI32(30096000) const ANOINTED_BASE_COST = BigInt.fromI32(30096000);
const CHAMPION_BASE_COST = BigInt.fromI32(255816000) const CHAMPION_BASE_COST = BigInt.fromI32(255816000);
function calculateProfitPerSecond( function calculateProfitPerSecond(
molochLevel: i32, molochLevel: i32,
apprenticeLevel: i32, apprenticeLevel: i32,
anointedLevel: i32, anointedLevel: i32,
championLevel: i32 championLevel: i32
): BigInt { ): BigInt {
// Exactly matching the RaidGeldUtils calculation // Exactly matching the RaidGeldUtils calculation
let molochDenierProfit = MOLOCH_DENIER_PROFIT.times(BigInt.fromI32(molochLevel)) let molochDenierProfit = MOLOCH_DENIER_PROFIT.times(
let apprenticeProfit = APPRENTICE_PROFIT.times(BigInt.fromI32(apprenticeLevel)) BigInt.fromI32(molochLevel)
let anointedProfit = ANOINTED_PROFIT.times(BigInt.fromI32(anointedLevel)) );
let championProfit = CHAMPION_PROFIT.times(BigInt.fromI32(championLevel)) let apprenticeProfit = APPRENTICE_PROFIT.times(
BigInt.fromI32(apprenticeLevel)
);
let anointedProfit = ANOINTED_PROFIT.times(BigInt.fromI32(anointedLevel));
let championProfit = CHAMPION_PROFIT.times(BigInt.fromI32(championLevel));
return molochDenierProfit return molochDenierProfit
.plus(apprenticeProfit) .plus(apprenticeProfit)
.plus(anointedProfit) .plus(anointedProfit)
.plus(championProfit) .plus(championProfit);
} }
function getOrCreateGlobalStats(): GlobalStat { function getOrCreateGlobalStats(): GlobalStat {
let stats = GlobalStat.load("1") let stats = GlobalStat.load("1");
if (!stats) { if (!stats) {
stats = new GlobalStat("1") stats = new GlobalStat("1");
stats.totalPlayers = 0 stats.totalPlayers = 0;
stats.totalGeldMinted = BigInt.fromI32(0) stats.totalGeldMinted = BigInt.fromI32(0);
stats.totalArmyUnits = 0 stats.totalArmyUnits = 0;
stats.lastUpdateTime = BigInt.fromI32(0) stats.lastUpdateTime = BigInt.fromI32(0);
stats.topEarnerProfit = BigInt.fromI32(0) stats.topEarnerProfit = BigInt.fromI32(0);
} }
return stats return stats;
} }
function calculateArmyStrength(army: Army): BigInt { function calculateArmyStrength(army: Army): BigInt {
// Using the exact same profit calculation for army strength // Using the exact same profit calculation for army strength
return calculateProfitPerSecond( return calculateProfitPerSecond(
army.molochDenierLevel, army.molochDenierLevel,
army.apprenticeLevel, army.apprenticeLevel,
army.anointedLevel, army.anointedLevel,
army.championLevel army.championLevel
) );
} }
function calculateProjectedDailyEarnings(profitPerSecond: BigInt): BigInt { function calculateProjectedDailyEarnings(profitPerSecond: BigInt): BigInt {
return profitPerSecond.times(BigInt.fromI32(86400)) // 86400 seconds in a day return profitPerSecond.times(BigInt.fromI32(86400)); // 86400 seconds in a day
} }
export function handlePlayerRegistered(event: PlayerRegistered): void { export function handlePlayerRegistered(event: PlayerRegistered): void {
let player = new Player(event.params.player.toHexString()) let player = new Player(event.params.player.toHexString());
player.createdAt = event.block.timestamp player.createdAt = event.block.timestamp;
player.lastRaidedAt = event.block.timestamp player.lastRaidedAt = event.block.timestamp;
player.totalMinted = event.params.initialGeld player.totalMinted = event.params.initialGeld;
player.currentBalance = event.params.initialGeld player.currentBalance = event.params.initialGeld;
player.numberOfRaids = 0 player.numberOfRaids = 0;
player.armyStrength = BigInt.fromI32(0) player.armyStrength = BigInt.fromI32(0);
player.rank = 0 player.rank = 0;
player.save() // Initialize new fields
player.prestigeLevel = BigInt.fromI32(0);
player.totalRuns = 1;
player.bossesDefeated = 0;
player.totalRewards = BigInt.fromI32(0);
player.isActiveSession = true;
player.save();
let army = new Army(event.params.player.toHexString()) let army = new Army(event.params.player.toHexString());
army.player = player.id army.player = player.id;
army.molochDenierLevel = 0 army.molochDenierLevel = 0;
army.apprenticeLevel = 0 army.apprenticeLevel = 0;
army.anointedLevel = 0 army.anointedLevel = 0;
army.championLevel = 0 army.championLevel = 0;
army.profitPerSecond = BigInt.fromI32(0) army.profitPerSecond = BigInt.fromI32(0);
army.projectedDailyEarnings = BigInt.fromI32(0) army.projectedDailyEarnings = BigInt.fromI32(0);
army.totalUnitsPurchased = 0 army.totalUnitsPurchased = 0;
army.lastUnitPurchaseTime = event.block.timestamp army.lastUnitPurchaseTime = event.block.timestamp;
army.save() army.currentBossLevel = 0;
army.save();
let stats = getOrCreateGlobalStats() let stats = getOrCreateGlobalStats();
stats.totalPlayers += 1 stats.totalPlayers += 1;
stats.totalGeldMinted = stats.totalGeldMinted.plus(event.params.initialGeld) stats.totalGeldMinted = stats.totalGeldMinted.plus(
stats.lastUpdateTime = event.block.timestamp event.params.initialGeld
stats.save() );
stats.totalRuns += 1;
stats.lastUpdateTime = event.block.timestamp;
stats.save();
}
export function handlePlayerStrikesAgain(event: PlayerStrikesAgain): void {
let player = Player.load(event.params.player.toHexString());
if (!player) return;
player.totalRuns += 1;
player.currentBalance = event.params.initialGeld;
player.totalMinted = event.params.initialGeld;
player.lastRaidedAt = event.block.timestamp;
player.isActiveSession = true;
player.save();
// Reset army for new run
let army = Army.load(event.params.player.toHexString());
if (!army) return;
army.molochDenierLevel = 0;
army.apprenticeLevel = 0;
army.anointedLevel = 0;
army.championLevel = 0;
army.profitPerSecond = BigInt.fromI32(0);
army.projectedDailyEarnings = BigInt.fromI32(0);
army.currentBossLevel = 0;
army.save();
let stats = getOrCreateGlobalStats();
stats.totalRuns += 1;
stats.lastUpdateTime = event.block.timestamp;
stats.save();
}
export function handleBossDefeated(event: BossDefeated): void {
let player = Player.load(event.params.player.toHexString());
if (!player) return;
player.bossesDefeated += 1;
player.totalRewards = player.totalRewards.plus(event.params.earnings);
player.save();
let army = Army.load(event.params.player.toHexString());
if (!army) return;
army.currentBossLevel += 1;
army.save();
// Create boss defeat record
let bossDefeat = new BossDefeat(
event.params.player.toHexString() +
"-" +
event.block.timestamp.toString()
);
bossDefeat.player = player.id;
bossDefeat.bossLevel = event.params.bossLevel;
bossDefeat.earnings = event.params.earnings;
bossDefeat.timestamp = event.block.timestamp;
bossDefeat.save();
let stats = getOrCreateGlobalStats();
stats.totalBossesDefeated += 1;
stats.lastUpdateTime = event.block.timestamp;
stats.save();
}
export function handlePrestigeGained(event: PrestigeGained): void {
let player = Player.load(event.params.player.toHexString());
if (!player) return;
player.prestigeLevel = event.params.prestigeLevel;
player.isActiveSession = false;
player.save();
let stats = getOrCreateGlobalStats();
stats.totalPrestigeLevels += 1;
stats.lastUpdateTime = event.block.timestamp;
stats.save();
} }
export function handleRaidPerformed(event: RaidPerformed): void { export function handleRaidPerformed(event: RaidPerformed): void {
let player = Player.load(event.params.player.toHexString()) let player = Player.load(event.params.player.toHexString());
if (!player) return if (!player) return;
// Calculate new GELD minted in this raid // Calculate new GELD minted in this raid
let newGeldMinted = event.params.totalMinted.minus(player.totalMinted) let newGeldMinted = event.params.totalMinted.minus(player.totalMinted);
player.totalMinted = event.params.totalMinted
player.currentBalance = event.params.geldBalance
player.lastRaidedAt = event.block.timestamp
player.numberOfRaids += 1
player.save()
let stats = getOrCreateGlobalStats() player.totalMinted = event.params.totalMinted;
stats.totalGeldMinted = stats.totalGeldMinted.plus(newGeldMinted) player.currentBalance = event.params.geldBalance;
stats.lastUpdateTime = event.block.timestamp player.lastRaidedAt = event.block.timestamp;
stats.save() player.numberOfRaids += 1;
player.save();
let stats = getOrCreateGlobalStats();
stats.totalGeldMinted = stats.totalGeldMinted.plus(newGeldMinted);
stats.lastUpdateTime = event.block.timestamp;
stats.save();
} }
export function handleUnitAdded(event: UnitAdded): void { export function handleUnitAdded(event: UnitAdded): void {
let army = Army.load(event.params.player.toHexString()) let army = Army.load(event.params.player.toHexString());
if (!army) return if (!army) return;
// Update army levels based on the event // Update army levels based on the event
if (event.params.unitType == 0) { if (event.params.unitType == 0) {
army.molochDenierLevel = event.params.molochDenierLevel army.molochDenierLevel = event.params.molochDenierLevel;
} else if (event.params.unitType == 1) { } else if (event.params.unitType == 1) {
army.apprenticeLevel = event.params.apprenticeLevel army.apprenticeLevel = event.params.apprenticeLevel;
} else if (event.params.unitType == 2) { } else if (event.params.unitType == 2) {
army.anointedLevel = event.params.anointedLevel army.anointedLevel = event.params.anointedLevel;
} else if (event.params.unitType == 3) { } else if (event.params.unitType == 3) {
army.championLevel = event.params.championLevel army.championLevel = event.params.championLevel;
} }
// Calculate new profit per second using exact RaidGeldUtils values // Calculate new profit per second using exact RaidGeldUtils values
let profitPerSecond = calculateProfitPerSecond( let profitPerSecond = calculateProfitPerSecond(
army.molochDenierLevel, army.molochDenierLevel,
army.apprenticeLevel, army.apprenticeLevel,
army.anointedLevel, army.anointedLevel,
army.championLevel army.championLevel
) );
army.profitPerSecond = profitPerSecond
army.projectedDailyEarnings = calculateProjectedDailyEarnings(profitPerSecond)
army.totalUnitsPurchased += event.params.nUnits
army.lastUnitPurchaseTime = event.block.timestamp
army.save()
// Update player's army strength and balance army.profitPerSecond = profitPerSecond;
let player = Player.load(event.params.player.toHexString()) army.projectedDailyEarnings =
if (!player) return calculateProjectedDailyEarnings(profitPerSecond);
army.totalUnitsPurchased += event.params.nUnits;
player.currentBalance = event.params.geldBalance army.lastUnitPurchaseTime = event.block.timestamp;
player.armyStrength = calculateArmyStrength(army) army.save();
player.save()
// Update global stats // Update player's army strength and balance
let stats = getOrCreateGlobalStats() let player = Player.load(event.params.player.toHexString());
stats.totalArmyUnits += event.params.nUnits if (!player) return;
if (profitPerSecond > stats.topEarnerProfit) {
stats.topEarnerProfit = profitPerSecond player.currentBalance = event.params.geldBalance;
} player.armyStrength = calculateArmyStrength(army);
stats.lastUpdateTime = event.block.timestamp player.save();
stats.save()
} // Update global stats
let stats = getOrCreateGlobalStats();
stats.totalArmyUnits += event.params.nUnits;
if (profitPerSecond > stats.topEarnerProfit) {
stats.topEarnerProfit = profitPerSecond;
}
stats.lastUpdateTime = event.block.timestamp;
stats.save();
}

View File

@ -1,35 +1,44 @@
specVersion: 1.0.0 specVersion: 1.0.0
indexerHints: indexerHints:
prune: auto prune: auto
schema: schema:
file: ./schema.graphql file: ./schema.graphql
dataSources: dataSources:
- kind: ethereum - kind: ethereum
name: RaidGeld name: RaidGeld
network: base-sepolia network: base-sepolia
source: source:
address: "0xC912823B231f5d052eF334a8f8B73F6354909cd0" address: "0xC912823B231f5d052eF334a8f8B73F6354909cd0"
abi: RaidGeld abi: RaidGeld
startBlock: 17213030 startBlock: 17213030
mapping: mapping:
kind: ethereum/events kind: ethereum/events
apiVersion: 0.0.7 apiVersion: 0.0.7
language: wasm/assemblyscript language: wasm/assemblyscript
entities: entities:
- Approval - Approval
- OwnershipTransferred - OwnershipTransferred
- PlayerRegistered - PlayerRegistered
- RaidPerformed - PlayerStrikesAgain
- Transfer - RaidPerformed
- UnitAdded - Transfer
abis: - UnitAdded
- name: RaidGeld - BossDefeated
file: ./abis/RaidGeld.json - PrestigeGained
eventHandlers: abis:
- event: PlayerRegistered(indexed address,uint256) - name: RaidGeld
handler: handlePlayerRegistered file: ./abis/RaidGeld.json
- event: RaidPerformed(indexed address,uint256,uint256) eventHandlers:
handler: handleRaidPerformed - event: PlayerRegistered(indexed address,uint256)
- event: UnitAdded(indexed address,uint8,uint16,uint256,uint256,uint16,uint16,uint16,uint16) handler: handlePlayerRegistered
handler: handleUnitAdded - event: PlayerStrikesAgain(indexed address,uint256,uint256)
file: ./src/raid-geld.ts handler: handlePlayerStrikesAgain
- event: RaidPerformed(indexed address,uint256,uint256)
handler: handleRaidPerformed
- event: UnitAdded(indexed address,uint8,uint16,uint256,uint256,uint16,uint16,uint16,uint16)
handler: handleUnitAdded
- event: BossDefeated(indexed address,uint8,uint256)
handler: handleBossDefeated
- event: PrestigeGained(indexed address,uint32)
handler: handlePrestigeGained
file: ./src/raid-geld.ts