# Endless[文档持续更新中...请往下看]

> 一个用 Vue.js 开发的冒险类游戏;

![image](https://github.com/bastarder/Endless/blob/master/game.gif)

## 项目安装&启动

``` bash
git clone https://github.com/bastarder/Endless.git
cd Endless
npm install
npm run dev
```

## 你好
 - 如果你和我一样, 是一名学生, 喜欢前端开发, 苦于没有练手的项目, 或是您已经是独当一面的大牛, 不妨可以与我一起完成这样一个小游戏, 在这个游戏中最复杂的战斗系统已经基本完成, 剩下一些 相对容易 的功能, 能让你得到很好的锻炼。
 
 - 这是一款 简单的冒险类游戏, 我也希望在编写过程中能得到更好的锻炼;
 
 - 数据设计, UI设计 方面, 我真的不擅长, 如果你觉得你闲来无事的时候愿意帮忙, 可以联系我;
 - `QQ:85257684`,`Wechat: I85257`
 
## 游戏详细文档

## 战斗逻辑
	
游戏中的战斗系统采用`技能冷却`的模式,一次向一个目标发送一个技能,计算一次行动的效果为战斗逻辑

首先是大致逻辑:(Fight.js)

### 1. 判断技能是否可以释放 (skill-available.js)

 当`技能被释放`后会优先进入这个方法,此方法接受3个参数,`技能对象`,`攻击方`,`被攻击方`,可根据这3者定制,判断此次技能是否能够被释放;

### 2. 触发冷却时间 (cool-time-event.js)

 当技能被判定为能够成功释放以后, 技能将进入冷却时间;

### 3. 提取人物状态与敌人状态;
 
 从攻击者身上提取 `type : 1` 的状态, 从被攻击者身上提取 `type : 2`的状态;
 
 `type : 1` 为所有能够影响到此次技能的状态,并且自定义状态时应该按照这一规则创建,否则将不被认可;
 
 `type : 2` 为所有能够影响此次技能对敌人造成的改变的状态,并且自定义状态时应该按照这一规则创建,否则将不被认可;
 
### 4. 拼接技能,状态效果排序;

  将技能与状态对象中的事件提取并且合并,按照优先级进行排序;
  
### 5. 行动对象计算(关键);

  技能行动对象,由所有的状态与技能行动效果进行计算而出,根据权重排序;
  
  *权重暂定的规则*
  
  1. `1-10` Action层, 与 影响本次 `暴击`,`命中`,`闪避` 等前置条件相关的事件,权重值需要定义在这个范围;
  2. `11-89` 普通层, 普通的效果,例如技能造成的伤害,状态添加,移除,更新等,大多数都在普通层;
  3. `>90` 在`90`层中,将会计算本次技能在所有可识别加成下的最终结果（如,造成伤害,恢复血量等等）, 如果你的状态需要造成一个 `最终加成`, 例如最终伤害增加50%,那么此事件必须 定义在90层, 在计算结果确定后;
  4. `9999` 最终层, 所有权重都不应该超出9999, 在计算此层时, 行动对象将被转换为可被`unit`接口直接执行的参数,并且不再改变;
  
### 6. 判断行动对像是否有效;
行动对象生成完毕后, 判定此次攻击是否有效(如必中,miss,等 ps: 必中将优先于100%miss);

### 7. 执行变更
确定有效以后,将行动对象代理给`攻击者`与`被攻击者`处理;

### 8. 触发全局冷却
至此,技能完全释放完毕,每次释放技能为`1s`,也就是说释放一个技能以后所有技能都将获得1秒的冷却(如果技能冷却时间不满1秒,将被强制提升至1秒);

**一次技能释放结束,如果攻击方和被攻击方,有一方死亡, 则返回 false**

## 强化逻辑

 1. 消耗计算
	
	目前采用的公式是: (等级 * 基础金额) * (强化等级 + 1) * 品级参数
	
 2. 几率计算

	几率采用固定值: [1, 1, 1, 0.95, 0.9, 0.8, 0.75, 0.62, 0.54, 0.41, 0.33, 0.28, 0.2, 0.17, 0.13, 0.1, 0.04, 0.03, 0.01, 0.01]
	
 3. 属性增幅计算
	- **武器计算公式**  [等级 + 品级参数A/ 8 ] * 强化参数 * 品级参数B * 位置参数
	- **防具计算公式**  基础值 * 强化参数 * 品级参数 * 位置参数
 4. 强化失败后的处理
   - 1-3 无效果
   - 3-8 随机退级 1-2
   - 8-10 掉为0级
   - 11以上 装备被破坏

大致流程: **判断前置条件 -> 判断强化几率-> 重新计算属性**


	
## 如何自定义事件

 在地图中,我们总可以触发事件,从而获得特定的效果,目前内置的事件的有2种:
 
 1. **战斗事件** : 当英雄走入此事件格子以后,将会利用事件对象创建一个战斗事件, 并且跳转到战斗界面,当战斗完毕,在返回地图;
 	   
 2. **对话事件** : 当英雄走入此事件格子以后, 将会利用事件对象创建一个对话事件,与英雄进行一些对话交互,分支事件,物品交换等;

 **事件定义的规则:**
 
 ```
 1. 事件将在判定允许被移动后,直接执行;
 2. 在执行阶段可捕获的参数有: 当前格子对象,目标格子对象,英雄对象
 3. 事件必须为一个可执行的函数;
 4. 详细可以参考内置事件(event-class.js)
 ```

## 如何自定义技能(状态)

在这里,我们引用实例来解释,技能对象的定义规则;

*数据(skill-data.js,state-data.js),所有字符串形式将在`战斗技能释放,计算行动对象时`被转换为可执行函数;*

**范例**

```
  {
    id: 1000002, 
    name: '净化',
    dsc : '净化中毒效果~',
    label : ['测试2','伤害2'],
    defaultTime : 3000,
    restrict : [
       "[attacker]{$mp} >= {60}",
       "[attacker]{$hp} <= {250}",
       "[attacker]{$skills} nothas {1000003,1000001}",
       "[attacker]{$status} has {2000001}",
       "[skill]{coolTime} > {0}",
      function(skill, attacker, enemy){
        return true;
      }
    ],
     eventList : [
       `[1]enemy@changeHp@attacker.$atk`,
       `[2]attacker@changeHp@2`,
       `[3]
           action@{action.state.isCritical === true};
           attacker@{attacker.$hp > (attacker.$hp * 0.5)}
        #
           enemy@changeState@[{ id: 2000001, state: "ADD" }];
           enemy@changeHp@attacker.$atk
       `
       ,
       `[4]action@{action.state.isCritical = true}`,
     ],
     // 当为状态时还可以添加下面2个属性;
    stateEvent : function(hero) {
      var self = this;
      var duration = 5;
      var per = 1;
      var current = 1;
      self.stateEventTimer = setInterval(function(){
        hero.changeHp(-30);
        current +=1;
        if(current > 5){
          clearInterval(self.stateEventTimer);
          hero.removeList('$status',self);
        }
      }, per * 1000);
      this.actived = true;
    },
    powerUp : {
      $maxHp  : [0,0,0,0],
    },
  },
```

| key        | value           | dsc  |
| ------------- |:-------------:| -----|
| id      | Number | 技能的唯一标识 |
| name      | String      |   技能的名称 |
| label | [String]      |    技能的标签 |
| defaultTime | Number|技能冷却时间,单位毫秒|
| restrict | [String or function] | 技能释放的前置条件,当解析为函数时,能访问3个参数,`技能`,`攻击者`,`被攻击者`,当函数返回为true时表示此规则通过,字符串解析规则: `[对象]{属性名1} 标识符 {值}`, 标识符支持 `> < >= <= nothas has`,表达式的最终值将被判定为真与假|
| eventList |[String or function]|事件列表, 可以为一个函数,函数中接受3个参数,`行动对象`,`攻击者`,`被攻击者`,字符串形式解析规则`[权重]参数名@{前置条件语句}#参数名@事件@事件参数`,可多条应该使用`;`分开,并且末尾条目不需要添加分隔符|
| stateEvent |function| 持续状态, 一个状态被添加到对象身上时将被执行此函数,在此函数内可以访问被作用的单位,做一些处理|
| powerUp |object| 状态能带来的属性提升, Array值解析,`[值, 类型: 0:基础值 1:基础百分 2:高级值 3:高级百分]`, 属性计算公式`((默认 + 基础值) * (1 + 基础百分) + 高级值) * (1 +  高级百分)`|

*恭喜,至此你已经可以制作一个属于自己的技能了*

## 如何自定义装备(物品)

```
// 装备
  {
    id: 30000012,	
    name: '精致的铁剑',
    level: 1,
    grade: 1,
    equipType : 0,
    label: [
      '武器'
    ],
    intensify : 1,
    intPowerUp : {
    	$atk: 123
    },
    equip : {
      $def: 2,
      $atk: 15,
      $maxHp : 5,
      $maxMp : 5,
    },
    dsc : '用野草编制的手镯'
  }
 // 物品
  {
    id: 3000001,
    name: '野草',
    pile : true,
    price : 10,
    use : {
      defaultTime : 1000,
      restrict :[
        function(){
          return this.$hp > 500;
        }
      ],
      effect :[
        function(){
          this.changeHp(30);
        }
      ]
    },
    label : [
      '材料'
    ],
    dsc : '很常见的东西,或许能用来做一些东西'
  },
```
| key        | value           | dsc  |
| ------------- |:-------------:| -----|
| level      | Number | 装备的等级 |
| grade |Number| 装备的品级 `白0`,`绿1`,`蓝2`,`紫3`,`橙4`|
| equipType |Number|装备类型 `武器0`, `护肩1`, `鞋子2`, `腰带3`, `上衣4`, `绑腿5`, `戒指6`, `项链7`, `手镯8`,|
| equip |object|装备的属性 参数的值与`状态`的powerUp相同|
| intensify |Number|强化等级|
| intPowerUp |Object|强化带来的增益,武器为`$atk`,其余防具为`$dmgDown`(百分比减伤)|
| pile |Boolean| 是否可以叠加|
| price |Number|物品的价值|
|use|object|可使用物品的效果 `defaultTime :冷却时间`, `restrict 前置条件列表,接受函数为单个条件,this指向使用者`,`effect 造成的效果列表,接受函数为单个事件,this指向使用者`|
*怎么样？是不是发现自己还是不会创建一个属于自己的装备~ 没关系,是我表达的不好~*

## 文档未完待续...有空在更新
