Boss mechanics compile
This commit is contained in:
parent
64832617cc
commit
ecbadf3809
@ -48,14 +48,14 @@ contract RaidGeld is ERC20, Ownable, Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
modifier onlyActiveSession() {
|
modifier onlyActiveSession() {
|
||||||
require(players[msg.sender].active_session, "Session is not active, you need to buy into the game first");
|
require(players[msg.sender].has_active_session, "Session is not active, you need to buy into the game first");
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier newPlay() {
|
modifier newPlay() {
|
||||||
Player memory player = players[msg.sender];
|
Player memory player = players[msg.sender];
|
||||||
bool notRegistered = player.created_at == 0;
|
bool notRegistered = player.created_at == 0;
|
||||||
bool returningPlayer = player.has_registered && !player.has_active_session;
|
bool returningPlayer = player.is_registered && !player.has_active_session;
|
||||||
require(notRegistered || returningPlayer, "Active session already in progress");
|
require(notRegistered || returningPlayer, "Active session already in progress");
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ contract RaidGeld is ERC20, Ownable, Constants {
|
|||||||
Player memory player = players[addr];
|
Player memory player = players[addr];
|
||||||
uint32 current_n_runs = player.n_runs + 1;
|
uint32 current_n_runs = player.n_runs + 1;
|
||||||
uint256 current_total_rewards = player.total_rewards;
|
uint256 current_total_rewards = player.total_rewards;
|
||||||
bool has_registered = player.is_registered;
|
bool current_is_registered = player.is_registered;
|
||||||
// Set initial states
|
// Set initial states
|
||||||
players[msg.sender] = Player({
|
players[msg.sender] = Player({
|
||||||
total_minted: INITIAL_GELD,
|
total_minted: INITIAL_GELD,
|
||||||
@ -94,7 +94,8 @@ contract RaidGeld is ERC20, Ownable, Constants {
|
|||||||
last_raided_at: block.timestamp,
|
last_raided_at: block.timestamp,
|
||||||
n_runs: current_n_runs,
|
n_runs: current_n_runs,
|
||||||
total_rewards: current_total_rewards,
|
total_rewards: current_total_rewards,
|
||||||
active_session: false
|
has_active_session: false,
|
||||||
|
is_registered: current_is_registered
|
||||||
});
|
});
|
||||||
armies[msg.sender] = Army({
|
armies[msg.sender] = Army({
|
||||||
moloch_denier: Raider({level: 0}),
|
moloch_denier: Raider({level: 0}),
|
||||||
@ -148,7 +149,7 @@ contract RaidGeld is ERC20, Ownable, Constants {
|
|||||||
|
|
||||||
// Manual minting for itchy fingers
|
// Manual minting for itchy fingers
|
||||||
function raid() external onlyActiveSession {
|
function raid() external onlyActiveSession {
|
||||||
performRaid();
|
performRaid(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper so we can use it when buying units too
|
// Helper so we can use it when buying units too
|
||||||
@ -202,9 +203,7 @@ contract RaidGeld is ERC20, Ownable, Constants {
|
|||||||
uint256 time_past = block.timestamp - players[msg.sender].last_raided_at;
|
uint256 time_past = block.timestamp - players[msg.sender].last_raided_at;
|
||||||
uint256 new_geld = armies[msg.sender].profit_per_second * time_past;
|
uint256 new_geld = armies[msg.sender].profit_per_second * time_past;
|
||||||
require(balanceOf(msg.sender) + new_geld >= cost, "Not enough GELD to add this unit");
|
require(balanceOf(msg.sender) + new_geld >= cost, "Not enough GELD to add this unit");
|
||||||
uint256 totalMinted = performRaid(msg.sender);
|
performRaid(msg.sender);
|
||||||
|
|
||||||
// Emit event
|
|
||||||
|
|
||||||
// TODO: Since we are first minting then burning the token, this could be simplified
|
// TODO: Since we are first minting then burning the token, this could be simplified
|
||||||
// by first calculating the difference and then minting / burning in just one operation
|
// by first calculating the difference and then minting / burning in just one operation
|
||||||
@ -246,14 +245,14 @@ contract RaidGeld is ERC20, Ownable, Constants {
|
|||||||
|
|
||||||
function battle_with_boss() external onlyActiveSession {
|
function battle_with_boss() external onlyActiveSession {
|
||||||
// first perform raid
|
// first perform raid
|
||||||
performRaid();
|
performRaid(msg.sender);
|
||||||
Boss memory boss_to_attack = bosses[msg.sender];
|
Boss memory boss_to_attack = bosses[msg.sender];
|
||||||
// calculate how much the player will put into battle
|
// calculate how much the player will put into battle
|
||||||
uint256 geld_to_burn = balanceOf(msg.sender) >= RaidGeldUtils.BOSS_POWERS[boss_to_attack.level]
|
uint256 geld_to_burn = balanceOf(msg.sender) >= RaidGeldUtils.getBossPower(boss_to_attack.level)
|
||||||
? RaidGeldUtils.BOSS_POWERS[boss_to_attack.level]
|
? RaidGeldUtils.getBossPower(boss_to_attack.level)
|
||||||
: balanceOf(msg.sender);
|
: balanceOf(msg.sender);
|
||||||
bool hasWonBattle = RaidGeldUtils.calculateBossFight(
|
bool hasWonBattle = RaidGeldUtils.calculateBossFight(
|
||||||
boss_to_attack.level, geld_to_burn, block.timestamp, block.difficulty
|
boss_to_attack.level, geld_to_burn, block.prevrandao
|
||||||
);
|
);
|
||||||
if (hasWonBattle) {
|
if (hasWonBattle) {
|
||||||
// Burn geld, get some sweet DAO Token and continue
|
// Burn geld, get some sweet DAO Token and continue
|
||||||
@ -268,7 +267,7 @@ contract RaidGeld is ERC20, Ownable, Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function player_dies(address player) private {
|
function player_dies(address player) private {
|
||||||
reset_player();
|
reset_player(player);
|
||||||
players[player].has_active_session = false;
|
players[player].has_active_session = false;
|
||||||
_burn(msg.sender, balanceOf(player));
|
_burn(msg.sender, balanceOf(player));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,26 +19,32 @@ library RaidGeldUtils {
|
|||||||
uint256 constant ANOINTED_BASE_COST = 30096000;
|
uint256 constant ANOINTED_BASE_COST = 30096000;
|
||||||
uint256 constant CHAMPION_BASE_COST = 255816000;
|
uint256 constant CHAMPION_BASE_COST = 255816000;
|
||||||
|
|
||||||
// Boss lvels
|
|
||||||
uint256[7] constant BOSS_POWERS = [
|
|
||||||
9000000, // 900e4
|
|
||||||
90000000, // 900e5
|
|
||||||
900000000, // 900e6
|
|
||||||
9000000000, // 900e7
|
|
||||||
90000000000, // 900e8
|
|
||||||
900000000000, // 900e9
|
|
||||||
9000000000000 // 900e10
|
|
||||||
];
|
|
||||||
|
|
||||||
// First boss is almost guaranteed, others arent
|
|
||||||
uint256[7] constant BOSS_CHANCES = [99, 89, 80, 70, 62, 51, 40];
|
|
||||||
|
|
||||||
// These are cumulative chances from above with precision 18
|
|
||||||
uint256[7] constant CUMULATIVE_BOSS_CHANCES =
|
|
||||||
[99e16, 8811e14, 7048e14, 493416e12, 30591792e10, 1560181392e8, 6240725568e7];
|
|
||||||
|
|
||||||
uint256 constant RISK_BETA = 15e17;
|
uint256 constant RISK_BETA = 15e17;
|
||||||
|
|
||||||
|
function getBossPower(uint8 level) internal pure returns (uint256 power) {
|
||||||
|
require(level <= 7, "Bosses only go to level 7");
|
||||||
|
if (level == 0) return 9000000; // 900e4
|
||||||
|
else if (level == 1) return 90000000; // 900e5
|
||||||
|
else if (level == 2) return 900000000; // 900e6
|
||||||
|
else if (level == 3) return 9000000000; // 900e7
|
||||||
|
else if (level == 4) return 90000000000; // 900e8
|
||||||
|
else if (level == 5) return 900000000000; // 900e9
|
||||||
|
else if (level == 6) return 9000000000000; // 900e10
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBossCumulativeChance(uint8 level) internal pure returns (uint256 chance) {
|
||||||
|
// for boss chances (percent) [99, 89, 80, 70, 62, 51, 40]
|
||||||
|
// where cumulative chance is in the form of 18 precision related to 1e18
|
||||||
|
require(level <= 7, "Bosses only go to level 7");
|
||||||
|
if (level == 0) return 99e16;
|
||||||
|
else if (level == 1) return 8811e14;
|
||||||
|
else if (level == 2) return 7048e14;
|
||||||
|
else if (level == 3) return 493416e12;
|
||||||
|
else if (level == 4) return 30591792e10;
|
||||||
|
else if (level == 5) return 1560181392e8;
|
||||||
|
else if (level == 6) return 6240725568e7;
|
||||||
|
}
|
||||||
|
|
||||||
function calculateUnitPrice(uint8 unit, uint16 currentLevel, uint16 units) internal pure returns (uint256) {
|
function calculateUnitPrice(uint8 unit, uint16 currentLevel, uint16 units) internal pure returns (uint256) {
|
||||||
require(unit <= 3, "No matching unit found");
|
require(unit <= 3, "No matching unit found");
|
||||||
uint256 rollingPriceCalculation = MOLOCH_DENIER_BASE_COST;
|
uint256 rollingPriceCalculation = MOLOCH_DENIER_BASE_COST;
|
||||||
@ -67,24 +73,23 @@ library RaidGeldUtils {
|
|||||||
uint256 apprentice_profit = army.apprentice.level * APPRENTICE_PROFIT;
|
uint256 apprentice_profit = army.apprentice.level * APPRENTICE_PROFIT;
|
||||||
uint256 anointed_profit = army.anointed.level * ANOINTED_PROFIT;
|
uint256 anointed_profit = army.anointed.level * ANOINTED_PROFIT;
|
||||||
uint256 champion_profit = army.champion.level * CHAMPION_PROFIT;
|
uint256 champion_profit = army.champion.level * CHAMPION_PROFIT;
|
||||||
|
|
||||||
return moloch_denier_profit + apprentice_profit + anointed_profit + champion_profit;
|
return moloch_denier_profit + apprentice_profit + anointed_profit + champion_profit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns how much Dao Token player is due for winning
|
// Returns how much Dao Token player is due for winning
|
||||||
function calculateBossReward(uint256 bossLevel) public view returns (uint256) {
|
function calculateBossReward(uint8 bossLevel) internal pure returns (uint256) {
|
||||||
return BOSS_POWERS[bossLevel] * (CUMULATIVE_BOSS_CHANCES[bossLevel] * 10 / 5) ** 2;
|
return getBossPower(bossLevel) * (getBossCumulativeChance(bossLevel) * 10 / 5) ** 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates whether user survives the fight
|
// Calculates whether user survives the fight
|
||||||
function calculateBossFight(uint8 bossLevel, uint256 geldBurnt, uint256 timestamp, uint256 difficulty)
|
function calculateBossFight(uint8 bossLevel, uint256 geldBurnt, uint256 prevrandao)
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
returns (uint256)
|
returns (bool)
|
||||||
{
|
{
|
||||||
uint256 bossPower = BOSS_POWERS[bossLevel];
|
uint256 bossPower = getBossPower(bossLevel);
|
||||||
require(geldBurnt <= bossPower, "Cant try to defeat boss with more than what boss power is");
|
require(geldBurnt <= bossPower, "Cant try to defeat boss with more than what boss power is");
|
||||||
uint256 random_n = random(timestamp, difficulty, 1, 100);
|
uint256 random_n = random(prevrandao, 1, 100);
|
||||||
// Relative power as in, you can only put in 800 geld to defeat 900 geld boss,
|
// Relative power as in, you can only put in 800 geld to defeat 900 geld boss,
|
||||||
// but you will get exponentially worse chances
|
// but you will get exponentially worse chances
|
||||||
uint256 relativePower = ((geldBurnt ** 2) * 100) / bossPower ** 2;
|
uint256 relativePower = ((geldBurnt ** 2) * 100) / bossPower ** 2;
|
||||||
@ -93,10 +98,10 @@ library RaidGeldUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement actual randomness
|
// TODO: Implement actual randomness
|
||||||
function random(uint256 timestamp, uint256 difficulty, uint256 min, uint256 max) internal pure returns (uint256) {
|
function random(uint256 prevrandao, uint256 min, uint256 max) internal pure returns (uint256) {
|
||||||
// returns 0 - 100
|
// returns 0 - 100
|
||||||
require(max >= min, "Max must be greater than or equal to min");
|
require(max >= min, "Max must be greater than or equal to min");
|
||||||
uint256 range = max - min + 1;
|
uint256 range = max - min + 1;
|
||||||
return min + (uint256(keccak256(abi.encodePacked(timestamp, difficulty))) % range);
|
return min + (uint256(keccak256(abi.encodePacked(prevrandao))) % range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ contract raid_geldTest is Test {
|
|||||||
assertGt(price, basePriceChamp * 12);
|
assertGt(price, basePriceChamp * 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_1_profits_per_second(uint16 _dLvl, uint16 _apLvl, uint16 _anLvl, uint16 _cLvl) public {
|
function test_1_profits_per_second(uint16 _dLvl, uint16 _apLvl, uint16 _anLvl, uint16 _cLvl) public pure {
|
||||||
Army memory army = Army({
|
Army memory army = Army({
|
||||||
moloch_denier: Raider({level: 1}),
|
moloch_denier: Raider({level: 1}),
|
||||||
apprentice: Raider({level: 0}),
|
apprentice: Raider({level: 0}),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user