One of my favorite MMO experiences by far has been participating in “World Bosses” in World of Warcraft Classic where guilds need to coordinate to defeat a boss that spawns in the open world. I’m interested in recreating this experience on chain into a format that could be scalable across the loot universe.
Motivation: Create a community experience that lets all enthusiasts of the loot universe play together to collectively defeat a world boss that exists as a Solidity contract. This contract would have mechanisms to reward the player based on their loot and loot derivatives. The primary mechanics would work as follows:
Constructor
We start with an unslain dragon with a million hitpoints. This number is pretty arbitrary but it should feel big and daunting to deplete.
uint public dragonHP = 1000000;
bool public dragonSlain = false;
We save all adventurers once in this array of addresses and we store how much damage they’ve done in a “combat log” map.
address[] public adventurers;
mapping(address => uint) public combatlog;
Then we instantiate contracts to call:
- Loot + xLoot = add value prop to stronger weapons in the token market
- SyntheticLoot = allow non token holders to participate and provide an alternative if your loot/xloot weapons are weaker.
- LootComponents = utility for getting weapon index which we use to calculate damage
// Loot
address public lootAddress = 0xFF9C1b15B16263C61d017ee9F65C50e4AE0113D7;
// xLoot
address public xLootAddress = 0x8bf2f876E2dCD2CAe9C3d272f325776c82DA366d;
// Synthetic Loot
address public syntheticLootAddress = 0x869Ad3Dfb0F9ACB9094BA85228008981BE6DBddE;
// LootComponents
address public lootComponentsAddress = 0x3eb43b1545a360d1D065CB7539339363dFD445F3;
Battle
Adventurers can participate in the battle by calling the contracts doDamage(uint lootId)
function. First, we find their weapon index based on the lootId passed (non holders can enter 0).
uint[5] memory weaponInfo;
if (lootId == 0) {
weaponInfo = syntheticLoot.weaponComponents(msg.sender);
} else if (lootId < 8001) {
require(loot.ownerOf(lootId) == msg.sender, "Not the owner of this loot");
weaponInfo = lootComponents.weaponComponents(lootId);
} else if (lootId <= 16000) {
require(xLoot.ownerOf(lootId) == msg.sender, "Not the owner of this xLoot");
weaponInfo = lootComponents.weaponComponents(lootId);
}
From my interpretation of the original loot contract, the stronger weapons have lower weapon indeces, so we start with the total amount of weapons (18) and then subtract our weapon index (weaponInfo[0]
) to get our weapon power level. Then multiply it by 1000 since the boss has a lot of HP.
uint damage = (18 - weaponInfo[0]) * 1000;
Then save our adventurer if we haven’t recorded them and log how much damage they did:
if (combatLog[msg.sender] == 0) {
adventurers.push(msg.sender);
}
combatLog[msg.sender] += damage;
Once enough people have hit the dragon it will be slain:
// calculate totalDamage
if (totalDamage >= dragonHP) {
dragonSlain = true;
// calculate loot dstribution
}
Boss Loot
Once totalDamage >= dragonHP
, some logic will execute that sets the following state variables:
bool public dragonSlain;
uint public top10CutOff;
uint public totalUncommon;
uint public uncommonIdx;
uint public commonIdx;
address firstOnDamage;
address secondOnDamage;
Once dragonSlain == true
, participating adventurers can call claimLoot()
to mint an NFT of a “common” part of the dragon, such as scales or hide. The top 10% damage dealers would also be issued a more uncommon piece of the dragon like teeth or claws. Finally the top 2 damage dealers would also receive the head (token 1) and the heart of the dragon (token 2).
function getBossLoot(uint tokenId) private returns (string memory) {
if (tokenId == 1) {
return "Head of the Dragon";
} else if (tokenId == 2) {
return "Heart of the Dragon";
} else if (tokenId <= top10CutOff) {
return "Tooth of the Dragon";
} else {
return "Scale of the Dragon";
}
}
Ultimately this would manifest itself as a Loot style NFT that is open to interpretation and value:
Conclusion / Thoughts
- Can the doDamage() be more dynamic / challenging? maybe clusters of attacks in the same block do more damage? maybe the dragon heals if there hasnt been an attack in x time.
- Are the numbers right? How much HP and how many weapon swings should it take to defeat the world boss? This will dictate how many can participate and how many boss loot NFTs will be minted.
- How can we make it more “fair” without making the code too complex? Right now holders of strong weapons who can afford gas wars would have a significant advantage.
- How can other derivatives be included? Most likely candidate is probably ability-stats/character-stats eg strength increases mace damage, intelligence increases wand damage. Knights do more damage with swords, priests with staves, etc.
- Keeping in the spirit of loot this should be free to play and community driven, so would be great if a DAO could fund the contract deployment and potentially put up og Loot at stake - eg if you send the Head of the Dragon to the DAO they will award you an og loot NFT.
- Is this experience valuable enough to warrant the amount of energy/gas that would be spent? While I think this could be a really fun experiment we should also consider more efficient solutions.
- Any ideas for a name? “Dragon” is just a placeholder for now.
Please feel free to leave any helpful comments and feedback here!