Contract 4: GameEngine - The Game Logic Hub
Combat System
function fightEnemy(uint256 tokenId) external nonReentrant {
require(evolutionNFT.ownerOf(tokenId) == msg.sender, "Not owner");
require(block.timestamp >= lastActionTime[tokenId] + 1 hours, "Cooldown active");
uint256 currentLevel = traitFusion.getTraitAsUint(address(evolutionNFT), tokenId, "level");
uint256 currentEnergy = traitFusion.getTraitAsUint(address(evolutionNFT), tokenId, "energy");
require(currentEnergy >= 20, "Not enough energy");
What's happening here?
Checks if player owns the NFT
Enforces 1-hour cooldown between fights
Gets current level and energy from TraitFusion
Requires at least 20 energy to fight
// Consume energy
traitFusion.setTraitUint(address(evolutionNFT), tokenId, "energy", currentEnergy - 20);
// Gain XP and potentially level up
uint256 xpGain = 10 + (currentLevel / 2);
uint256 newLevel = currentLevel + (xpGain / 100);
if (newLevel > currentLevel) {
traitFusion.setTraitUint(address(evolutionNFT), tokenId, "level", newLevel);
// Increase strength on level up
uint256 currentStrength = traitFusion.getTraitAsUint(address(evolutionNFT), tokenId, "strength");
traitFusion.setTraitUint(address(evolutionNFT), tokenId, "strength", currentStrength + 5);
}
What's happening here?
Reduces energy by 20 points
Calculates XP gain (higher level = more XP)
Every 100 XP = 1 level up
When leveling up, adds 5 strength points
This is where the evolution happens!
Real-World Data Integration
function updateSteps(uint256 tokenId, uint256 steps) external onlyRole(ORACLE_ROLE) {
dailySteps[tokenId] = steps;
// Convert steps to stamina (1 step = 0.01 stamina)
uint256 currentStamina = traitFusion.getTraitAsUint(address(evolutionNFT), tokenId, "stamina");
uint256 staminaBonus = steps / 100;
uint256 newStamina = currentStamina + staminaBonus;
if (newStamina > 200) newStamina = 200; // Cap at 200
traitFusion.setTraitUint(address(evolutionNFT), tokenId, "stamina", newStamina);
What's happening here?
Only oracle can call this (real-world data source)
Converts real walking steps to in-game stamina
100 steps = 1 stamina point
Caps stamina at 200 to prevent infinite growth
// Milestone rewards
if (steps >= 10000) {
gameToken.mint(evolutionNFT.ownerOf(tokenId), 200 * 10**18);
emit QuestCompleted(tokenId, "daily_10k_steps", 200);
}
What's happening here?
If player walks 10,000+ steps, they get 200 game tokens
Real-world activity = in-game rewards!
Loot Box System with Chainlink VRF
function openLootBox(uint256 tokenId) external nonReentrant {
require(evolutionNFT.ownerOf(tokenId) == msg.sender, "Not owner");
require(gameToken.balanceOf(msg.sender) >= 100 * 10**18, "Not enough GAME tokens");
gameToken.burn(msg.sender, 100 * 10**18);
uint256 requestId = vrfCoordinator.requestRandomWords(
keyHash,
subscriptionId,
requestConfirmations,
callbackGasLimit,
1
);
vrfRequests[requestId] = tokenId;
What's happening here?
Player burns 100 tokens to open loot box
Requests truly random number from Chainlink VRF
Maps the request ID to the token ID for later processing
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {
uint256 tokenId = vrfRequests[requestId];
uint256 randomValue = randomWords[0] % 100;
// Loot rarity: 0-49 = common, 50-79 = rare, 80-94 = epic, 95-99 = legendary
if (randomValue >= 95) {
// Legendary loot
uint256 currentStrength = traitFusion.getTraitAsUint(address(evolutionNFT), tokenId, "strength");
traitFusion.setTraitUint(address(evolutionNFT), tokenId, "strength", currentStrength + 50);
traitFusion.setTraitString(address(evolutionNFT), tokenId, "loot_tier", "legendary");
What's happening here?
Chainlink calls this function with random number
Converts random number to percentage (0-99)
5% chance for legendary loot (+50 strength)
15% chance for epic loot (+25 strength)
30% chance for rare loot (+10 strength)
50% chance for common loot (+5 strength)
Last updated