On Chain World Boss (for Adventurers)

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!

30 Likes

This is so good!!
I’ll chip in a bit for contract deployment fees, DAO or not.

Related to the gas fees - are you imagining that this has a UI to go with it or is an Etherscan-based thing?

If there’s a UI I think you could maybe get the connected wallet’s Loot info on L1, then run transactions from a server onto Polygon or similar l2/sidechain for the actual battles.

4 Likes

This is an amazing idea! Would love to tackle some world bosses together.

5 Likes

I love this idea. World bosses were always fun events in WoW back in the day.

this is so awesome. expanding on the doDamage function, I wonder if you can incorporate some shield specific to monsters. Only certain weapons can break those shields, necessitating coordination across guilds.

i can already see Vitalik himself playing it.

1 Like

Regarding fairness: maybe it’s best to give each address a limited number of turns?

I think this might be too much for a v1 but can also think about coordination mechanics and similar in the future. Can also think about “hard” or “extreme” modes. Since this would be a first foray into assigning any sort of “stat value” to the items themselves, it’s probably okay to go with calculation and rules.

Using the resulting NFTs as crafting ingredients is interesting. But they’re also awesome as just trophies. :slight_smile:

8 Likes

Ideally, the dragon would deal damage back, which brings armor in to play.

Which brings me to my next thought… Diablo style “hardcore” mode.

5 Likes

Jeeez this is amazing!!!

1 Like

I think this is an awesome idea, but i’m a bit concerned about the gas cost such a batte would involved. It may be fairly prohibitive to participate, though in a way this would add value to the NFT reward once the dragon is slayed :smile:

1 Like

yeah but what about the magic… :wink:

Kid Icarus Uprising had an interesting mechanic where you could wager a specific currency in the game to increase the difficulty of a level, resulting in better loot drops. However, you permanently lose that currency by placing the wager and can only earn it back by defeating enemies in the level.

What if we incorporated something similar to this that would change the dynamic of boss raids? Players could fund the contract with these tokens, then once a certain marker is triggered the raid begins. If they defeat the monster, they get tokens back in proportion to their damage dealt and addresses with more tokens spent into the contract get more rare loot. If they’re defeated by the monster, the tokens are burnt. Players could mint new tokens per season.

This could have interesting economic outcomes.

4 Likes

This is an amazing idea. You have my axe!

…except actually I carry a book :). Maybe you can have us book-carriers apply a buff to the next damage dealt by the next adventurer!

3 Likes

Few more thoughts on this ;

There are a few things we can do to reduce the gas cost though, such as

  1. Signature based battle commitment instead of 1 tx per owner
  2. Stateless data structure instead of doing a bunch of SLOADs reading the contract state

Alternatively, we could do an optimistic battle approach, which requires more work, but would end up being dirt cheap gas wise. Here’s how it could work ;

User commits the hash of an army / team on-chain and store RNG value from that block as well (could use a future block for RNG for more security). Perhaps calling it optimisticBattle(). Then, in a future block, someone can call a reportVictory() function, starting a 48h rebuttal period. If no claim to victory has been filed 24h after the battle, the contract deems the battle a Loss. Claiming to have a victory would require a stake to prevent fraud (e.g. 5 ETH).

During the 48h rebuttal period, If anyone disagrees with the claimed victory, they could stake some ETH (e.g. 5 ETH) and request a proof of victory. Fighters would then need to call the actual function with all the required information. The previously committed army hash and RNG would be used to see if the dragon was indeed slayed. If the reported Victory was correct, the 5ETH is claimed by the fighters. Else, the person requesting the proof claims back the 5ETH and takes the stake from the fraudulent fighters.

3 Likes

I feel like this naturally lends itself to also building out a party and guild system.

Players could form parties and guilds and let them combine damage together for a higher chance at rare drops. These could be DAOs with votes or fractional treasury systems to deal with who gets what drops. You could potentially even bundle party attacks to save gas in fights.

3 Likes

Love this.

edge case - How would these with fractional owners of original Loot?
example: https://fractional.art/vaults/0xEed0E3d08B94CDeEC5aeA38Ba00744B4855D0EEe has a lot of people who collectively own one bag and have $DIVINEs in their wallets.

What an awesome idea. Is it feasible to get a verifiable random number from chainlink to roll some dice on the multiplier for the attack strength?

It would be cool if there were timing elements to the strategy. IE you can only attack once every 10 minutes and the boss becomes weak after certain attack combinations and stays weak for X amount of minutes.

If you want to use ChainLink, it would be infeasible to use it for every attack transaction. But I guess you could use it every so often for a new random seed, for example.

I like the optimistic approach @PhABC outlines, but it does seem more daunting as a first draft. I’m all for iterating, however, I don’t feel like it necessarily has to be live for the first World Boss.

2 Likes

First of all, amazing proposal. You had me at “world boss”.

Now to get the ball rolling (for v1 or v2 of the game) i’ll start with some conceptual ideas:

wBosses should appear once in a while (from 2 to 7 weeks intervals) and at different times. The time part is important because in WoW I’d too often miss a wBoss because I played on EU servers while being in Asia :upside_down_face:

wBoss expiry – Option 1: wBoss Smart Contract should expire after x amount of time. Option 2: wBoss SC would expire after x amount of resets. Reset = when x amount of time has passed without the wBoss receiving new attacks.

wBoss SC should be a new one every time. SC can be virtually the same, but its important that hte wBoss doesnt pop up from the same address. Just to make it a bit harder for people to automate the process of participating in a fight. Would also be cool if we could think of a way to make the discovery of the wBoss non-trivial. And thus maybe reward the one who discovers the wBoss SC first. Once the wBoss SC is found though, everyone can be notified of it.
- ^ Discovering a wBoss: wBoss SC is created and sends some $dmg to a random LootRealm owner, attacking their lands. (idk need to think about this one more).

Can we follow the Dark Forest (Dark Forest) model somehow to avoid huge gas costs during those world events?

Boss should deal damage. Randomly is preferable rather than going after higher gear/damage players. Some players will get one-shotted (sometimes several players at once - AoE) and would not be able to hit the wBoss again because of that. It will be frustrating for them, but that’s what gaming is about. They will still be able to claim loot if they managed to hit the wBoss at least once.

Last point, and I cannot stress this enough: we need wipes. People failing from time to time because the boss was way stronger than the last will just get everyone pumped about being better prepared for next time.

Gonna think a bit about how to code some of this!
Oh and needless to say that all of the above suggestions can be binned, i’m just thinking out loud here, no hard feelings if nothing I said is kept : ))

love all these ideas and I definitely don’t see myself being the sole contributor to this contract so feel free to code your own version, deploy it, test it, share it etc - the community should ultimately decide which contract to value.

100% agree about the discoverability of the world boss - one of the biggest parts of world bosses in WoW was having a group of degenerate guildies patrolling the spawn zone to alert the rest of the guild on spawn. Something similar that rewards the curious and dedicated could be fun. Wiping + taking damage is also something that would add a lot to the experience IMO

4 Likes