Skip to content

Commit

Permalink
update:基本完成分类
Browse files Browse the repository at this point in the history
  • Loading branch information
LidamaoHub committed Oct 11, 2023
1 parent 99e64ba commit 218a5fb
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 147 deletions.
91 changes: 59 additions & 32 deletions packages/contracts/src/systems/BattleSystem.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,7 @@ import { GAME_CONFIG_KEY, BATTLE_CONFIG_KEY } from "../Constants.sol";

contract BattleSystem is System {

function joinBattlefield(address _user) public {
// 加入战区,用户实际上是送到原点,状态改为探索中
// User storage player = Player[_user];
PlayerState playerState = Player.getState(_user);
require(
playerState == PlayerState.Preparing || playerState == PlayerState.Idle,
"You should in preparing state"
);
//实际上是送到原点//TODO通过常数设置原点参数
Player.setX(_user, GameConfig.getOriginX(GAME_CONFIG_KEY));
Player.setY(_user, GameConfig.getOriginY(GAME_CONFIG_KEY));
BattleConfig.pushBattlefieldPlayers(BATTLE_CONFIG_KEY, _user);
Player.setState(_user, PlayerState.Exploring);
}


function checkBattlePlayer(BattleListData memory battle, BattleState _battleState) internal view {
// BattleListData memory battle = BattleList.get(_battleId);
Expand Down Expand Up @@ -283,9 +270,27 @@ contract BattleSystem is System {
}
}

function getAttackResult(
uint256 _hp,
uint256 _attackPower
) internal pure returns (uint256) {
// TODO 后期添加防御力抵消对方的攻击力
if (_attackPower > _hp) {
return 0;
}
return _hp - _attackPower;
}

function initUserHP(address _user) public pure returns (uint256) {
return 400;
}
function raiseUserHP(
uint256 _targetHP,
uint256 _percent,
address _user
) public {
Player.setHP(_user, (_targetHP * _percent) / 100);
}

function loseGame(address _looser, address _winner) internal {
// 游戏失败,将用户脱离战区,血量回满
Expand All @@ -311,24 +316,6 @@ contract BattleSystem is System {
}


function outBattlefield(address _user) internal {
// 脱离战区,则将用户血量回满,坐标不变,状态改为准备中
require(
Player.getState(_user) == PlayerState.Exploring,
"You should in exploring state"
);

Player.setHP(_user, initUserHP(_user));

for (uint256 i; i < BattleConfig.lengthBattlefieldPlayers(BATTLE_CONFIG_KEY); i++) {
if (BattleConfig.getItemBattlefieldPlayers(BATTLE_CONFIG_KEY, i) == _user) {
BattleConfig.updateBattlefieldPlayers(BATTLE_CONFIG_KEY, i, BattleConfig.getItemBattlefieldPlayers(BATTLE_CONFIG_KEY, BattleConfig.lengthBattlefieldPlayers(BATTLE_CONFIG_KEY) - 1));
BattleConfig.popBattlefieldPlayers(BATTLE_CONFIG_KEY);
break;
}
}
Player.setState(_user, PlayerState.Preparing);
}


function goHome() external {
Expand All @@ -346,5 +333,45 @@ contract BattleSystem is System {
outBattlefield(_msgSender());

}


function getAttackPower(
Buff _myBuff,
Buff _targetBuff,
uint256 _attackPower
) internal pure returns (uint256) {
// TODO 后期添加防御力抵消对方的攻击力
if (compareBuff(_myBuff, _targetBuff) == 0) {
return (_attackPower * 7) / 10;
}
if (compareBuff(_myBuff, _targetBuff) == 2) {
return (_attackPower * 13) / 10;
}

return _attackPower;
}


function compareBuff(
Buff _myBuff,
Buff _targetBuff
) internal pure returns (uint256) {
// 0表示失败,1表示相当,2表示胜利
if (
(_myBuff == Buff.Water && _targetBuff == Buff.Fire) ||
(_myBuff == Buff.Wind && _targetBuff == Buff.Water) ||
(_myBuff == Buff.Fire && _targetBuff == Buff.Wind)
) {
return 2;
}
if (
(_myBuff == Buff.Fire && _targetBuff == Buff.Water) ||
(_myBuff == Buff.Water && _targetBuff == Buff.Wind) ||
(_myBuff == Buff.Wind && _targetBuff == Buff.Fire)
) {
return 0;
}
return 1;
}

}
127 changes: 21 additions & 106 deletions packages/contracts/src/systems/GameSystem.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,127 +2,42 @@
pragma solidity >=0.8.0;

import { System } from "@latticexyz/world/src/System.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import { Game } from "../codegen/Tables.sol";
import { BattleState, Buff, PlayerState } from "../codegen/Types.sol";
import { GameConfig, BattleConfig, BattleListData, BattleList, Player, PlayerData,
PlayerLocationLock, BoxList, BoxListData} from "../codegen/Tables.sol";
import { BattleListData, BattleList, Player, PlayerData, PlayerLocationLock, BoxListData, BoxList, RandomList, RandomListData } from "../codegen/Tables.sol";
import { Move } from "./Common.sol";
import { GAME_CONFIG_KEY, BATTLE_CONFIG_KEY } from "../Constants.sol";
import { CommonUtils } from "./library/CommonUtils.sol";


contract GameSystem is System {
event MoveEvent(address indexed player, uint16 x, uint16 y);
event AttackStart(address player, address target);
bytes32 constant GAME_KEY = keccak256("Game-Key");

event NewRandom(uint256 randomId, address author);
event MoveEvent(address indexed player, uint16 x, uint16 y);
event AttackStart(address player, address target);








modifier CheckContinuity(Move[] memory moveList) {
// 验证行走轨迹合法且连续
uint8 prefer = 1;
for (uint256 i; i < moveList.length; i++) {

uint16 x2 = i > 0 ? moveList[i - 1].x : Player.getX(_msgSender());
uint16 y2 = i > 0 ? moveList[i - 1].y : Player.getY(_msgSender());
require(
CommonUtils.isNear(moveList[i].x, x2, moveList[i].y, y2),
"invalied move"
);
// 判断用户每一个移动连续性以及合法性,不能超出1格, 不能斜着走,不能原地踏步
Move memory info = moveList[i];
//prefer的意思是可以通行
bytes32 leaf = keccak256(
abi.encodePacked(info.x, ",", info.y, ",", prefer)
);
bool isValidLeaf = MerkleProof.verify(info.proof, GameConfig.getMerkleRoot(GAME_CONFIG_KEY), leaf);
require(isValidLeaf, "bad position");
}
_;
}

function move(Move[] memory moveList) external CheckContinuity(moveList) {
// 限制移动速度,每次移动需要间隔一定时间
require(PlayerLocationLock.get(_msgSender()) == 0, "You are locked");
require(
moveList.length > 0 && moveList.length <= BattleConfig.getMaxMoveDistance(BATTLE_CONFIG_KEY),
"invalid move distance"
);

Player.setX(_msgSender(), moveList[moveList.length - 1].x);
Player.setY(_msgSender(), moveList[moveList.length - 1].y);

emit MoveEvent(
_msgSender(),
moveList[moveList.length - 1].x,
moveList[moveList.length - 1].y
);
}


function battleInvitation(
address _targetAddress,
Move[] memory moveList
) external CheckContinuity(moveList) {
// 攻击,首先确定地图x,y上有具体用户,其次确定用户之间最短距离proof为10
// 需要考虑一个格子上有多个用户的情况//一个格子只能有一个人
// 判断对战双方的状态是否是Exploring

require(
moveList.length > 0 && moveList.length <= BattleConfig.getMaxAttackzDistance(BATTLE_CONFIG_KEY),
"invalid attack distance"
);

require(
Player.getState(_msgSender()) == PlayerState.Exploring &&
Player.getState(_targetAddress) == PlayerState.Exploring,
"Each player must be in exploring state"
);
require(
Player.getX(_targetAddress) == moveList[moveList.length - 1].x &&
Player.getY(_targetAddress) == moveList[moveList.length - 1].y,
"Target must be in the end of continuity"
);

Player.setState(_msgSender(), PlayerState.Attacking);
Player.setState(_targetAddress, PlayerState.Attacking);

uint256 battleId = GameConfig.getBattleId(GAME_CONFIG_KEY);
BattleList.setAttacker(battleId, _msgSender());
BattleList.setDefender(battleId, _targetAddress);
BattleList.setTimestamp(battleId, block.timestamp);
BattleList.setAttackerHP(battleId, Player.getHP(_msgSender()));
BattleList.setDefenderHP(battleId, Player.getHP(_targetAddress));

// battleId++;
GameConfig.setBattleId(GAME_CONFIG_KEY, battleId + 1);

emit AttackStart(_msgSender(), _targetAddress);
}




// function settleBattle() external {}

// function createLootBox() external {}

// function takeLoot() external {}

// function dropLoot() external {}


//------非战区空间部分
}


function settleBattle() external {}

function createLootBox() external {}

function takeLoot() external {}

function dropLoot() external {}

//------非战区空间部分








}
110 changes: 108 additions & 2 deletions packages/contracts/src/systems/MoveSystem.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
pragma solidity >=0.8.0;

import { System } from "@latticexyz/world/src/System.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";

import { BattleState, Buff, PlayerState } from "../codegen/Types.sol";
import { GameConfig, BattleConfig, RandomList, RandomListData, BoxList, BoxListData, Player, PlayerData, PlayerLocationLock} from "../codegen/Tables.sol";
import { GameConfig, BattleConfig, RandomList, RandomListData,BattleList, BoxList, BoxListData, Player, PlayerData, PlayerLocationLock} from "../codegen/Tables.sol";
import { GAME_CONFIG_KEY, BATTLE_CONFIG_KEY } from "../Constants.sol";
import { CommonUtils } from "./library/CommonUtils.sol";

import {Move} from "./Common.sol";

contract MoveSystem is System {
event MoveEvent(address indexed player, uint16 x, uint16 y);
event AttackStart(address player, address target);

function unlockUserLocation() external {
// 用户自行解锁
require(PlayerLocationLock.get(_msgSender()) != 0, "You are not locked");
Expand All @@ -28,5 +33,106 @@ contract MoveSystem is System {
Player.setY(_msgSender(), y);
}

modifier CheckContinuity(Move[] memory moveList) {
// 验证行走轨迹合法且连续
uint8 prefer = 1;
for (uint256 i; i < moveList.length; i++) {

uint16 x2 = i > 0 ? moveList[i - 1].x : Player.getX(_msgSender());
uint16 y2 = i > 0 ? moveList[i - 1].y : Player.getY(_msgSender());
require(
CommonUtils.isNear(moveList[i].x, x2, moveList[i].y, y2),
"invalied move"
);
// 判断用户每一个移动连续性以及合法性,不能超出1格, 不能斜着走,不能原地踏步
Move memory info = moveList[i];
//prefer的意思是可以通行
bytes32 leaf = keccak256(
abi.encodePacked(info.x, ",", info.y, ",", prefer)
);
bool isValidLeaf = MerkleProof.verify(info.proof, GameConfig.getMerkleRoot(GAME_CONFIG_KEY), leaf);
require(isValidLeaf, "bad position");
}
_;
}

function move(Move[] memory moveList) external CheckContinuity(moveList) {
// 限制移动速度,每次移动需要间隔一定时间
require(PlayerLocationLock.get(_msgSender()) == 0, "You are locked");
require(
moveList.length > 0 && moveList.length <= BattleConfig.getMaxMoveDistance(BATTLE_CONFIG_KEY),
"invalid move distance"
);

Player.setX(_msgSender(), moveList[moveList.length - 1].x);
Player.setY(_msgSender(), moveList[moveList.length - 1].y);

emit MoveEvent(
_msgSender(),
moveList[moveList.length - 1].x,
moveList[moveList.length - 1].y
);
}


function battleInvitation(
address _targetAddress,
Move[] memory moveList
) external CheckContinuity(moveList) {
// 攻击,首先确定地图x,y上有具体用户,其次确定用户之间最短距离proof为10
// 需要考虑一个格子上有多个用户的情况//一个格子只能有一个人
// 判断对战双方的状态是否是Exploring

require(
moveList.length > 0 && moveList.length <= BattleConfig.getMaxAttackzDistance(BATTLE_CONFIG_KEY),
"invalid attack distance"
);

require(
Player.getState(_msgSender()) == PlayerState.Exploring &&
Player.getState(_targetAddress) == PlayerState.Exploring,
"Each player must be in exploring state"
);
require(
Player.getX(_targetAddress) == moveList[moveList.length - 1].x &&
Player.getY(_targetAddress) == moveList[moveList.length - 1].y,
"Target must be in the end of continuity"
);

Player.setState(_msgSender(), PlayerState.Attacking);
Player.setState(_targetAddress, PlayerState.Attacking);

uint256 battleId = GameConfig.getBattleId(GAME_CONFIG_KEY);
BattleList.setAttacker(battleId, _msgSender());
BattleList.setDefender(battleId, _targetAddress);
BattleList.setTimestamp(battleId, block.timestamp);
BattleList.setAttackerHP(battleId, Player.getHP(_msgSender()));
BattleList.setDefenderHP(battleId, Player.getHP(_targetAddress));

// battleId++;
GameConfig.setBattleId(GAME_CONFIG_KEY, battleId + 1);

emit AttackStart(_msgSender(), _targetAddress);
}

function outBattlefield(address _user) internal {
// 脱离战区,则将用户血量回满,坐标不变,状态改为准备中
require(
Player.getState(_user) == PlayerState.Exploring,
"You should in exploring state"
);

Player.setHP(_user, initUserHP(_user));

for (uint256 i; i < BattleConfig.lengthBattlefieldPlayers(BATTLE_CONFIG_KEY); i++) {
if (BattleConfig.getItemBattlefieldPlayers(BATTLE_CONFIG_KEY, i) == _user) {
BattleConfig.updateBattlefieldPlayers(BATTLE_CONFIG_KEY, i, BattleConfig.getItemBattlefieldPlayers(BATTLE_CONFIG_KEY, BattleConfig.lengthBattlefieldPlayers(BATTLE_CONFIG_KEY) - 1));
BattleConfig.popBattlefieldPlayers(BATTLE_CONFIG_KEY);
break;
}
}
Player.setState(_user, PlayerState.Preparing);
}


}
Loading

0 comments on commit 218a5fb

Please sign in to comment.