Contract Name:
PepemonCardOracle
Contract Source Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./Roles.sol";
contract AdminRole {
using Roles for Roles.Role;
event AdminAdded(address indexed account);
event AdminRemoved(address indexed account);
Roles.Role private admins;
constructor() {
_addAdmin(msg.sender);
}
modifier onlyAdmin() {
require(isAdmin(msg.sender));
_;
}
function isAdmin(address account) public view returns (bool) {
return admins.has(account);
}
function addAdmin(address account) public onlyAdmin {
_addAdmin(account);
}
function renounceAdmin() public {
_removeAdmin(msg.sender);
}
function _addAdmin(address account) internal {
admins.add(account);
emit AdminAdded(account);
}
function _removeAdmin(address account) internal {
admins.remove(account);
emit AdminRemoved(account);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.6;
/**
* @title Roles
* @dev Library for managing addresses assigned to a Role.
*/
library Roles {
struct Role {
mapping (address => bool) bearer;
}
/**
* @dev Give an account access to this role.
*/
function add(Role storage role, address account) internal {
require(!has(role, account), "Roles: account already has role");
role.bearer[account] = true;
}
/**
* @dev Remove an account's access to this role.
*/
function remove(Role storage role, address account) internal {
require(has(role, account), "Roles: account does not have role");
role.bearer[account] = false;
}
/**
* @dev Check if an account has this role.
* @return bool
*/
function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0), "Roles: account is the zero address");
return role.bearer[account];
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
import "./cardlib/AdminRole.sol";
/**
This contract acts as the oracle, it contains battling information for both the Pepemon Battle and Support cards
**/
contract PepemonCardOracle is AdminRole {
enum SupportCardType {OFFENSE, STRONG_OFFENSE, DEFENSE, STRONG_DEFENSE}
enum EffectTo {ATTACK, STRONG_ATTACK, DEFENSE, STRONG_DEFENSE, SPEED, INTELLIGENCE}
enum EffectFor {ME, ENEMY}
enum BattleCardTypes {FIRE, GRASS, WATER, LIGHTNING, WIND, POISON, GHOST, FAIRY, EARTH, UNKNOWN, NONE}
struct BattleCardStats {
uint256 battleCardId;
BattleCardTypes element;
uint16 hp; // hitpoints
uint16 spd; // speed
uint16 inte; // intelligence
uint16 def; // defense
uint16 atk; // attack
uint16 sAtk; // special attack
uint16 sDef; // special defense
}
struct SupportCardStats {
uint256 supportCardId;
SupportCardType supportCardType;
EffectOne effectOne;
EffectMany effectMany;
// If true, duplicate copies of the card in the same turn will have no extra effect.
bool unstackable;
// This property is for EffectMany now.
// If true, assume the card is already in effect
// then the same card drawn and used within a number of turns does not extend or reset duration of the effect.
bool unresettable;
}
struct EffectOne {
// If power is 0, it is equal to the total of all normal offense/defense cards in the current turn.
//basePower = power if req not met
int16 basePower;
//triggeredPower = power if req met
int16 triggeredPower;
EffectTo effectTo;
EffectFor effectFor;
uint16 reqCode; //requirement code
}
struct EffectMany {
int16 power;
uint16 numTurns;
EffectTo effectTo;
EffectFor effectFor;
uint16 reqCode; //requirement code
}
//Struct for keeping track of weakness / resistance
struct elementWR {
BattleCardTypes weakness;
BattleCardTypes resistance;
}
mapping(uint256 => BattleCardStats) public battleCardStats;
mapping(uint256 => SupportCardStats) public supportCardStats;
mapping(BattleCardTypes => string) public elementDecode;
mapping(BattleCardTypes => elementWR) public weakResist;
event BattleCardCreated(address sender, uint256 cardId);
event BattleCardUpdated(address sender, uint256 cardId);
event SupportCardCreated(address sender, uint256 cardId);
event SupportCardUpdated(address sender, uint256 cardId);
constructor() {
elementDecode[BattleCardTypes.FIRE] = "Fire";
elementDecode[BattleCardTypes.GRASS] = "Grass";
elementDecode[BattleCardTypes.WATER] = "Water";
elementDecode[BattleCardTypes.LIGHTNING] = "Lighting";
elementDecode[BattleCardTypes.WIND] = "Wind";
elementDecode[BattleCardTypes.POISON] = "Poison";
elementDecode[BattleCardTypes.GHOST] = "Ghost";
elementDecode[BattleCardTypes.FAIRY] = "Fairy";
elementDecode[BattleCardTypes.EARTH] = "Earth";
elementDecode[BattleCardTypes.UNKNOWN] = "Unknown";
elementDecode[BattleCardTypes.NONE] = "None";
weakResist[BattleCardTypes.FIRE] = elementWR(BattleCardTypes.WATER, BattleCardTypes.GRASS);
weakResist[BattleCardTypes.GRASS] = elementWR(BattleCardTypes.FIRE, BattleCardTypes.WATER);
weakResist[BattleCardTypes.WATER] = elementWR(BattleCardTypes.LIGHTNING, BattleCardTypes.FIRE);
weakResist[BattleCardTypes.LIGHTNING] = elementWR(BattleCardTypes.EARTH, BattleCardTypes.WIND);
weakResist[BattleCardTypes.WIND] = elementWR(BattleCardTypes.POISON, BattleCardTypes.EARTH);
weakResist[BattleCardTypes.POISON] = elementWR(BattleCardTypes.FAIRY, BattleCardTypes.GRASS);
weakResist[BattleCardTypes.GHOST] = elementWR(BattleCardTypes.FAIRY, BattleCardTypes.POISON);
weakResist[BattleCardTypes.FAIRY] = elementWR(BattleCardTypes.GHOST, BattleCardTypes.FAIRY);
weakResist[BattleCardTypes.EARTH] = elementWR(BattleCardTypes.GRASS, BattleCardTypes.GHOST);
weakResist[BattleCardTypes.UNKNOWN] = elementWR(BattleCardTypes.NONE, BattleCardTypes.NONE);
weakResist[BattleCardTypes.NONE] = elementWR(BattleCardTypes.NONE, BattleCardTypes.NONE);
}
function addBattleCard(BattleCardStats memory cardData) public onlyAdmin {
require(battleCardStats[cardData.battleCardId].battleCardId == 0, "PepemonCard: BattleCard already exists");
BattleCardStats storage _card = battleCardStats[cardData.battleCardId];
_card.battleCardId = cardData.battleCardId;
_card.element = cardData.element;
_card.hp = cardData.hp;
_card.spd = cardData.spd;
_card.inte = cardData.inte;
_card.def = cardData.def;
_card.atk = cardData.atk;
_card.sDef = cardData.sDef;
_card.sAtk = cardData.sAtk;
emit BattleCardCreated(msg.sender, cardData.battleCardId);
}
function updateBattleCard(BattleCardStats memory cardData) public onlyAdmin {
require(battleCardStats[cardData.battleCardId].battleCardId != 0, "PepemonCard: BattleCard not found");
BattleCardStats storage _card = battleCardStats[cardData.battleCardId];
_card.hp = cardData.hp;
_card.element = cardData.element;
_card.spd = cardData.spd;
_card.inte = cardData.inte;
_card.def = cardData.def;
_card.atk = cardData.atk;
_card.sDef = cardData.sDef;
_card.sAtk = cardData.sAtk;
emit BattleCardUpdated(msg.sender, cardData.battleCardId);
}
function getBattleCardById(uint256 _id) public view returns (BattleCardStats memory) {
return battleCardStats[_id];
}
function addSupportCard(SupportCardStats memory cardData) public onlyAdmin {
require(supportCardStats[cardData.supportCardId].supportCardId == 0, "PepemonCard: SupportCard already exists");
SupportCardStats storage _card = supportCardStats[cardData.supportCardId];
_card.supportCardId = cardData.supportCardId;
_card.supportCardType = cardData.supportCardType;
_card.effectOne = cardData.effectOne;
_card.effectMany = cardData.effectMany;
_card.unstackable = cardData.unstackable;
_card.unresettable = cardData.unresettable;
emit SupportCardCreated(msg.sender, cardData.supportCardId);
}
function updateSupportCard(SupportCardStats memory cardData) public onlyAdmin {
require(supportCardStats[cardData.supportCardId].supportCardId != 0, "PepemonCard: SupportCard not found");
SupportCardStats storage _card = supportCardStats[cardData.supportCardId];
_card.supportCardId = cardData.supportCardId;
_card.supportCardType = cardData.supportCardType;
_card.effectOne = cardData.effectOne;
_card.effectMany = cardData.effectMany;
_card.unstackable = cardData.unstackable;
_card.unresettable = cardData.unresettable;
emit SupportCardUpdated(msg.sender, cardData.supportCardId);
}
function getSupportCardById(uint256 _id) public view returns (SupportCardStats memory) {
return supportCardStats[_id];
}
function getWeakResist(BattleCardTypes element) public view returns (elementWR memory) {
return weakResist[element];
}
/**
* @dev Get supportCardType of supportCard
* @param _id uint256
*/
function getSupportCardTypeById(uint256 _id) public view returns (SupportCardType) {
return getSupportCardById(_id).supportCardType;
}
}