# hearthstone
**Repository Path**: zhang-yi-han/hearthstone
## Basic Information
- **Project Name**: hearthstone
- **Description**: 炉石传说,JAVA模拟器(HearthStone Simulator for Java)
- **Primary Language**: Java
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 65
- **Created**: 2023-07-06
- **Last Updated**: 2023-07-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Java - 炉石传说
## 这是什么
这是用Java语言实现的游戏--炉石传说
- 实现了什么功能
- [x] 炉石传说
- [x] 主要组件
- [x] 随从
- [x] 英雄
- [x] 武器
- [x] 奥秘
- [x] 任务
- [x] 卡牌机制
- [x] 随从特效
- [x] 战吼
- [x] 亡语
- [ ] 其他卡牌效果
- [x] 卡牌
- [ ] 基础包
- [ ] 经典包
- [ ] 荣誉室
- [ ] 其他扩展包
- [ ] AI
- [x] QQ群对战
- [ ] 酒馆战棋
- 效果图





## 包含组件
| 模块 | 介绍 | 功能描述 |
| ------------- | ------- | --------------------- |
| hearth-core | 核心模块 | 整个游戏的架构,接口 |
| hearth-card | 卡牌模块 | 游戏的卡牌各种具体实现 |
| hearth-control | 控制器模块 | 游戏的测试启动和控制器,目前只能以文字的交互形式启动 |
| hearth-ai | AI模块 | 提供AI对战功能 |
| hearth-net | 网络模块 | 提供基于Netty的Tcp联机对战支持 |
| hearth-java-client | 对战客户端 | 独立打包运行,提供Netty联机客户端 |
| card-generator | 卡牌生成器 | 从暴雪的卡牌数据库中生成对应的java类 |
## 快速开始
- 克隆项目
- 编译
- 使用maven工具 install核心模块【hearth-core】
- 在【card-generator】模块中运行cn/eiden/hsm/util/XmlUtil.java
- 使用maven工具 install全部模块【hearth】
- 运行
- 项目的测试运行全部都在【hearth-control】模块中
- java控制台运行
- 运行cn/eiden/hsm/cockpit/console/ConsoleCockpit.java
- QQ运行
- 配置cn.eiden.hsm.cockpit.mirai.MiraiApplication中的机器人账号和密码
- 运行MiraiApplication的main方法
- 微信运行(未实装)
## 如何扩展添加新的卡牌
### 为什么要添加卡牌
- 炉石传说运营了6年,19+1个卡牌扩展包,卡牌数量太多
- 本项目从卡牌数据源能生成全部的牌面信息(费用,稀有度,职业,攻击力,生命值等静态信息)
- 作者将会从底层实现全部的游戏功能,并且至少每一种效果的卡牌会写出至少一个示例卡牌,其他的卡牌效果需要被仿写
- 希望喜欢炉石传说和Java的朋友和我一起为本项目贡献卡牌
### 有哪些卡牌需要被添加
- 大多数白板随从,武器(无描述的卡牌)无需手动添加
- 只有关键字描述的随从(比如[圣盾] [嘲讽] [冲锋]等)无需手动添加
- 关键字配合文字描述的卡牌(比如 战吼:从你的牌库中抽一张奥秘牌。)
- 全部的法术牌
- 其他牌面带有描述的卡牌
### 如何添加卡牌
> 在【hearth-card】模块中使用搜索功能找到你要实现的卡牌 (例如,我想实现卡牌【阿莱克丝塔萨】)
> 如果存在多个结果,则选择对应拓展包内的卡牌类(【阿莱克丝塔萨】在经典包,经典包的包名为【expert1】)
> 复制这个类,在cn/eiden/hsm/game/card目录中找到对应的扩展包和职业(【阿莱克丝塔萨】是经典包的中立随从对应的包名为【classic.neutral】)
> 在这个包中创建一个新类继承自上一步的类,新的类名一般在前面得类后面加Card
```java
public class AlexstraszaCard extends Alexstrasza {
}
```
> 如果这张卡牌在打出时需要选择目标(炉石传说中的卡牌只有选择一个目标和不需要选择目标两种)则需要在类头加入注解@TargetScope
>> 需要注意的是,有些卡牌可以选择全部目标(敌/我)(随从/英雄) 如[火球术][1]
>> 有些卡牌则只能选择敌方目标,如[横扫][2]
>> 示例中只能以双方英雄为目标则给注解添加以下属性
>> 灵活使用TargetScope注解
```java
@TargetScope(classScope = HeroMinion.class)
public class AlexstraszaCard extends Alexstrasza {
}
```
> 战吼随从重写selfBattleCry方法,返回一个战吼接口的实现
```java
@TargetScope(classScope = HeroMinion.class)
public class AlexstraszaCard extends Alexstrasza {
/**
* "战吼:\n"
* + "将一方英雄的剩余生命值变为15。"
*/
@Override
protected Battle selfBattleCry() {
return (e,t) -> t.setHealth(15);
}
}
```
> 完成!一张新的卡牌特效成功实现
> 一些其他卡牌示例:
```java
/**
* 幻觉药水
* @author Eiden J.P Zhou
* @date 2020/8/7 14:58
*/
public class PotionOfIllusionCard extends PotionOfIllusion {
/**
* "将你的所有随从的1/1的复制置入你的手牌,并使其法力值消耗变为(1)点。"
* @param gamer 当前卡牌所有者
* @param target 所指定目标
*/
@Override
public void magicEffect(Gamer gamer, Minion target) {
//拿到己方场上所有的随从
List minions = gamer.getMinions();
minions.stream()
//转化成他们对应的随从卡牌ID
.map(Minion::getCardId)
.mapToInt(Integer::parseInt)
.boxed()
//从卡牌工厂拿到卡牌ID对应的卡牌
.map(CardFactory::getCardById)
//我们能断定生成的卡牌一定是随从,强转为随从卡
.map(e -> (AbstractMinionCard) e)
//过滤掉空(理论上不存在空)
.filter(Objects::nonNull)
//把每一张随从卡的牌面设置1/1,费用为(1)
.peek(e -> {
e.setCost(1);
e.setAtk(1L);
e.setHealth(1L);
})
//添加进手牌
.forEach(e -> gamer.getHand().addHandsCard(e));
}
}
```
```java
/**
* 秘教侍僧
* @author Eiden J.P Zhou
* @date 2020/8/6 15:55
*/
public class CabalAcolyteCard extends CabalAcolyte {
@Override
protected SpellBurst selfSpellBurst() {
//随机获得一个攻击力小于或等于2的敌方随从的控制权。
return (s,c) -> {
//拿到所有的敌方随从列表
List minions = s.getOwner().getEnemy().getMinions();
//过滤其中攻击力小于或等于2的,并生成一个副本
List collect = minions.stream()
.filter(e -> e.getAttackValue() <= 2).collect(Collectors.toList());
//取一个随机的随从
Optional randomOne = Optional.ofNullable(RandomUtils.getRandomOne(collect));
//如果存在则
if (randomOne.isPresent()){
//敌方移除它
s.getOwner().getEnemy().removeMinion(randomOne.get());
//我方添加它
s.getOwner().addMinion(randomOne.get());
}
};
}
}
```
```java
/**
* 魔杖窃贼
* @author Eiden J.P Zhou
* @date 2020/8/7 15:35
*/
public class WandThiefCard extends WandThief {
/**
* "连击:发现一张法师法术牌。"
*/
@Override
protected Combo selfCombo() {
return (s,t)->s.getOwner()
//发现一张
.discoverChooseOne(() -> CardFactory.buildCard()
//法师的
.cardClass(CardClass.MAGE)
//法术牌
.cardType(CardType.SPELL)
.discover());
}
}
```
```java
/**
* 体能研习
* @author Eiden J.P Zhou
* @date 2020/8/8 0:39
*/
public class AthleticStudiesCard extends AthleticStudies {
/**
* "发现一张突袭随从牌。你的下一张突袭随从牌法力值消耗减少(1)点。"
*
* @param gamer 当前卡牌所有者
* @param target 所指定目标
*/
@Override
public void magicEffect(Gamer gamer, Minion target) {
//发现
gamer.discoverChooseOne(() -> CardFactory.buildCard()
//随从牌
.cardType(CardType.MINION)
//具有突袭标签
.gameTags(GameTag.RUSH)
.discover());
//添加一个规则,这个规则会使具有突袭的随从卡牌费用减少1点,满足条件(打出随从)后移除这个规则
gamer.addRule(new NextCommonCostReduceRule(1,CardType.MINION,
card -> Arrays.stream(card.getClass().getAnnotation(Tags.class).value())
.boxed()
.collect(Collectors.toSet())
.contains(GameTag.RUSH.getCode())));
}
}
```
> 其他卡牌则参考项目中已经实现的其他卡牌
#### 附录
- [ ] 卡牌关键效果及其部分demo示例(已经实现但没有示例的为自动生成,无需重写)
- [x] 随从特效
BL(gitee敏感词)狂战士
恐怖的奴隶主
- [x] 战吼
秘法学家
麦迪文的男仆
肯瑞托法师
- [x] 亡语
疯狂的科学家
麻风侏儒
- [x] 嘲讽
- [x] 冲锋
- [x] 法强
- [x] 光环
南海船长
- [x] 风怒
- [x] 圣盾
- [x] 潜行
- [x] 剧毒
- [x] 沉默
- [x] 冻结
霜冻射线
- [x] 抉择
利爪德鲁伊
愤怒
- [x] 连击
军情七处特工
刺骨
- [x] 过载
- [x] 随机卡牌
特殊坐骑商人
- [x] 发现
金甲虫
复苏
- [x] 吸血
- [x] 任务
探索地下洞穴
- [ ] 进化
- [x] 突袭
- [ ] 招募
- [ ] 回响
- [ ] 磁力
- [ ] 超杀
- [x] 免疫
- [x] 复生
- [x] 双生法术
霜冻射线
- [ ] 休眠
- [x] 流放
古尔丹之颅
眼棱
吞噬魔法
火色魔印奔行者
- [x] 法术迸发
秘教侍僧
- [x] 交换手牌和牌库
裂心者伊露希亚
- [x] 手牌洗入牌库
滑翔
- [ ] 双职业卡牌
- [ ] 卡牌包
- [ ] 基础包 CORE
- [ ] 经典包 CLASSIC
- [ ] 荣誉室 HOF
- [ ] 纳克萨玛斯 NAXX
- [ ] 地精大战侏儒 GVG
- [ ] 黑石山的火焰 BRM
- [ ] 冠军的试炼 TGT
- [ ] 探险者协会 LOE
- [ ] 上古之神的低语 OG
- [ ] 卡拉赞之夜 KAR
- [ ] 龙争虎斗加基森 CFM GANGS
- [ ] 勇闯安戈洛 UNG
- [ ] 冰封王座的骑士 ICC
- [ ] 狗头人与地下世界 LOOT
- [ ] 女巫森林 GIL
- [ ] 砰砰计划 BOT
- [ ] 拉斯塔哈的大乱斗 TRL
- [ ] 暗影崛起 DAL
- [ ] 奥丹姆奇兵 ULD
- [ ] 巨龙降临 DRG
- [ ] 迦拉克隆的觉醒 YOD
- [ ] 外域的灰烬 BT
- [x] 通灵学院 SCH
- [x] 暗月马戏团 DMF
### 交流群 :649207014
[1]: hearth-card/src/main/java/cn/eiden/hsm/game/card/base/mage/FireballCard.java
[2]: hearth-card/src/main/java/cn/eiden/hsm/game/card/base/druid/SwipeCard.java